rcrewai 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0024080cd05b151b653bcedb4b29afea563e149f9d68dce1662d636a919020a9'
4
- data.tar.gz: 53bb6b1376f88d1379cb0f877eeaa35aed0822f08df5f76d482e28d55101efe6
3
+ metadata.gz: e0a4a20865a08157cf9148d63439eeb653570c39f4f6e850bf6cc9f8e963a437
4
+ data.tar.gz: 4abf734ac77a3bdb1c43887b077cd99e1aea4ff9e2f8ba08b5fcac72a27ac7b5
5
5
  SHA512:
6
- metadata.gz: b7923adbf161caa5361568268306513c92e5ffbddc3736cd91cd0fbccedd8cdd4230854f8310cf358964c7ccea09b1e43040e944f4c5472b0f5e58983bf37aaf
7
- data.tar.gz: e4c9426c4e948fca50c3708a8a0e57588b4b18c51a5ac8df0bd2dd902aa2440a20d8d1f6a464333bb9c3244d5ff6901070645bb932fd5fb6e77f3d3f82ff9f83
6
+ metadata.gz: 01bd0f68ca18dcee76ccca334821bd1412695922b1a84fba092b7bf4686179401c581844b36094b9cf765415e8ce2652cfb7300b496d4c57c9b78dbcd6b7ac22
7
+ data.tar.gz: afdc22e50a5a61bc0e153c0e8a702e9e0aa465cbf268d06d71a82f372c626236a163ceab777f4eee5e8f6134740a8b54903fdb50cdebd38b6ae7b987d1394581
data/CHANGELOG.md CHANGED
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.7.1] - 2026-08-13
11
+
12
+ ### Fixed
13
+ - `Crew#execute` built its event sink but never delivered it to agents, so no agent-level events (`IterationStart`/`IterationEnd`, tool calls, token usage) reached a sink passed to `crew.execute(stream:)`. `Task` now carries a `stream_sink` that `Crew` populates at execute time and passes to `Agent#execute_task`; the two `Process` call sites that bypass `Task#execute` read `crew.stream_sink` directly. Subscribers now receive the full event stream on the sync, async, hierarchical, and consensual paths.
14
+ - Tasks retained a reference to the caller's sink after `execute` returned, keeping request-scoped subscribers reachable for the lifetime of the task object. The sink is now cleared in an `ensure`.
15
+
16
+ ### Note
17
+ - `Events.fan_out` invokes sinks inline on the emitting thread with no serialization, so under `async: true` a sink may be called concurrently from multiple worker threads. Subscribers must do their own locking.
18
+
10
19
  ## [0.7.0] - 2026-07-07
11
20
 
12
21
  Turns the `:consensual` crew process from a stub into a real multi-agent
@@ -217,7 +226,8 @@ output, guardrails, planning, and training/testing. See `ROADMAP.md`.
217
226
  - CLI usage documentation
218
227
  - Real-world use cases and examples
219
228
 
220
- [Unreleased]: https://github.com/gkosmo/rcrewAI/compare/v0.7.0...HEAD
229
+ [Unreleased]: https://github.com/gkosmo/rcrewAI/compare/v0.7.1...HEAD
230
+ [0.7.1]: https://github.com/gkosmo/rcrewAI/compare/v0.7.0...v0.7.1
221
231
  [0.7.0]: https://github.com/gkosmo/rcrewAI/compare/v0.6.1...v0.7.0
222
232
  [0.6.1]: https://github.com/gkosmo/rcrewAI/compare/v0.6.0...v0.6.1
223
233
  [0.6.0]: https://github.com/gkosmo/rcrewAI/compare/v0.5.0...v0.6.0
data/docs/api/agent.md CHANGED
@@ -28,6 +28,14 @@ Creates a new agent instance.
28
28
  - `human_input` (Boolean, optional) - Enable human-in-the-loop interactions (default: false)
29
29
  - `require_approval_for_tools` (Boolean, optional) - Require human approval for tool usage
30
30
  - `require_approval_for_final_answer` (Boolean, optional) - Require human approval for final results
31
+ - `llm` (Symbol \| Hash \| client, optional) - Per-agent LLM override: a provider symbol (`:anthropic`), an options hash (`{ provider:, model:, api_key:, temperature: }`), or a pre-built client. Defaults to the global configuration. See [Advanced Agent Options]({{ site.baseurl }}/tutorials/agent-options)
32
+ - `reasoning` (Boolean, optional) - Run a reasoning/planning pass before answering (default: false); surfaced on the result as `:reasoning`
33
+ - `max_reasoning_attempts` (Integer, optional) - Reasoning retries on empty output (default: 3)
34
+ - `respect_context_window` (Boolean, optional) - Trim history to fit the model's context window (default: false)
35
+ - `max_rpm` (Integer, optional) - Throttle the agent's LLM calls to this many requests per minute (default: unlimited)
36
+ - `knowledge` (Knowledge::Base, optional) - A knowledge base to ground the agent (see [Knowledge (RAG)]({{ site.baseurl }}/tutorials/knowledge))
37
+ - `knowledge_sources` (Array, optional) - Knowledge sources the agent wraps in a base
38
+ - `memory` (Memory \| Hash, optional) - A pre-built `Memory`, or options (`{ embedder:, store:, scope:, short_term_limit:, entity_extractor: }`); defaults to zero-config in-memory (see [Cognitive Memory]({{ site.baseurl }}/tutorials/memory))
31
39
 
32
40
  **Returns:** `RCrewAI::Agent` instance
33
41
 
data/docs/api/crew.md CHANGED
@@ -10,18 +10,26 @@ The Crew class is the main orchestrator in RCrewAI. It manages a collection of a
10
10
 
11
11
  ## Class Methods
12
12
 
13
- ### `.new(name)`
13
+ ### `.new(name, **options)`
14
14
 
15
15
  Creates a new crew instance.
16
16
 
17
17
  **Parameters:**
18
18
  - `name` (String) - The name of the crew
19
+ - `process` (Symbol, optional) - `:sequential` (default), `:hierarchical`, or `:consensual`
20
+ - `consensus_agents` (Integer, optional) - For `:consensual`, how many agents propose and vote per task (default: 3). See [Consensual Process]({{ site.baseurl }}/tutorials/consensual-process)
21
+ - `planning` (Boolean, optional) - Run a planner pass that drafts a per-task plan before execution (default: false)
22
+ - `planning_llm` (Symbol \| Hash \| client, optional) - The planner's LLM (defaults to the global provider)
23
+ - `knowledge` (Knowledge::Base, optional) - A knowledge base shared with all agents
24
+ - `knowledge_sources` (Array, optional) - Sources the crew wraps in a shared base (see [Knowledge (RAG)]({{ site.baseurl }}/tutorials/knowledge))
25
+ - `verbose` (Boolean, optional) - Detailed logging (default: false)
26
+ - `max_iterations` (Integer, optional) - Max iterations per agent (default: 10)
19
27
 
20
28
  **Returns:** `RCrewAI::Crew` instance
21
29
 
22
30
  **Example:**
23
31
  ```ruby
24
- crew = RCrewAI::Crew.new("research_team")
32
+ crew = RCrewAI::Crew.new("research_team", process: :consensual, consensus_agents: 3)
25
33
  ```
26
34
 
27
35
  ### `.create(name)`
@@ -342,4 +350,46 @@ crew.add_agent(manager)
342
350
  # Add other agents...
343
351
 
344
352
  crew.execute
345
- ```
353
+ ```
354
+
355
+ ### Consensual Process
356
+
357
+ Agents propose competing answers and vote to pick the best (see the
358
+ [Consensual Process]({{ site.baseurl }}/tutorials/consensual-process) tutorial).
359
+
360
+ ```ruby
361
+ crew = RCrewAI::Crew.new("panel", process: :consensual, consensus_agents: 3)
362
+ crew.add_agent(junior)
363
+ crew.add_agent(senior)
364
+ crew.add_task(task)
365
+
366
+ crew.execute # each task: propose → vote → pick
367
+ ```
368
+
369
+ ## Lifecycle, Batch, Training
370
+
371
+ ### `#before_kickoff { |inputs| ... }` / `#after_kickoff { |result| ... }`
372
+
373
+ Register callbacks that run before/after execution. A `before_kickoff` hook
374
+ receives the inputs hash (from `execute(inputs:)`) and may transform it; an
375
+ `after_kickoff` hook receives and may transform the result. The resolved inputs
376
+ are exposed on `#last_inputs`.
377
+
378
+ ### `#kickoff_for_each(inputs:)`
379
+
380
+ Runs the crew once per input set, returning one result per input in order. Runs
381
+ are isolated to their own inputs.
382
+
383
+ ```ruby
384
+ results = crew.kickoff_for_each(inputs: [{ topic: "ruby" }, { topic: "python" }])
385
+ ```
386
+
387
+ ### `#train(n_iterations:, filename:, feedback: nil)`
388
+
389
+ Runs the crew repeatedly, collects feedback after each run (via a `feedback:`
390
+ callable, defaulting to a human prompt), and persists it to JSON.
391
+
392
+ ### `#test(n_iterations:, scorer: nil)`
393
+
394
+ Runs the crew repeatedly and reports per-run and average scores (via a `scorer:`
395
+ callable, defaulting to the run's success rate).
data/docs/api/index.md CHANGED
@@ -19,23 +19,24 @@ Individual AI agents with specific roles and capabilities.
19
19
  ### [RCrewAI::Task]({{ site.baseurl }}/api/task)
20
20
  Tasks that agents execute to achieve goals.
21
21
 
22
- ## Tools
22
+ ## Capabilities (0.4 – 0.7)
23
+
24
+ These subsystems are covered in depth by the tutorials (with runnable examples):
23
25
 
24
- ### [RCrewAI::Tools::WebSearch]({{ site.baseurl }}/api/tools/web-search)
25
- Enable agents to search the web for information.
26
+ - **`RCrewAI::Flow`** — event-driven workflows. See [Flows]({{ site.baseurl }}/tutorials/flows)
27
+ - **`RCrewAI::Knowledge::Base`** and sources/embedders RAG. See [Knowledge]({{ site.baseurl }}/tutorials/knowledge)
28
+ - **`RCrewAI::Memory`** (+ `SqliteStore`, memory types) — cognitive memory. See [Memory]({{ site.baseurl }}/tutorials/memory)
29
+ - **Consensual process** — multi-agent voting. See [Consensual Process]({{ site.baseurl }}/tutorials/consensual-process)
30
+ - **Advanced agent/task options** — per-agent LLM, reasoning, rate limiting, context window, multimodal, structured output, guardrails, hooks. See [Advanced Options]({{ site.baseurl }}/tutorials/agent-options)
26
31
 
27
- ### [RCrewAI::Tools::FileSystem]({{ site.baseurl }}/api/tools/file-system)
28
- Allow agents to read and write files.
32
+ ## Tools
29
33
 
30
- ### [RCrewAI::Tools::Database]({{ site.baseurl }}/api/tools/database)
31
- Connect agents to databases for data operations.
34
+ See the [Tools System]({{ site.baseurl }}/api/tools) reference for the full API.
35
+ Built-in tools include `WebSearch`, `FileReader`, `FileWriter`, `SqlDatabase`,
36
+ `EmailSender`, `PdfProcessor`, and `CodeExecutor` — plus native function calling
37
+ and MCP servers.
32
38
 
33
39
  ## Configuration
34
40
 
35
41
  ### [RCrewAI::Configuration]({{ site.baseurl }}/api/configuration)
36
- Configure LLM providers and other settings.
37
-
38
- ## CLI
39
-
40
- ### [RCrewAI::CLI]({{ site.baseurl }}/api/cli)
41
- Command-line interface for managing crews.
42
+ Configure LLM providers, models, and other settings.
data/docs/api/task.md CHANGED
@@ -32,6 +32,13 @@ Creates a new task instance.
32
32
  - `allow_guidance` (Boolean) - Allow human guidance during execution
33
33
  - `human_review_points` (Array) - Points where human review is requested ([:completion, :error])
34
34
  - `async` (Boolean) - Whether task can be executed asynchronously (default: false)
35
+ - `output_schema` (Hash) - A JSON-schema subset the output is validated/coerced against; parsed result on `#structured_output` (raw string on `#raw_result`). Non-conforming output re-runs the agent with the error fed back
36
+ - `guardrail` (callable) - `->(output) { [ok, value_or_error] }` to validate/transform output before it flows downstream
37
+ - `guardrail_max_retries` (Integer) - Guardrail retries with the reason fed back (default: 3)
38
+ - `output_file` (String) - Path to write the result to after completion
39
+ - `create_directory` (Boolean) - Create the output file's parent dirs (default: true)
40
+ - `markdown` (Boolean) - Prepend a heading when the output isn't already markdown (default: false)
41
+ - `attachments` (Array) - Multimodal image inputs, e.g. `[{ type: :image, path: 'x.png' }]` or `{ type: :image, url: '...' }` (OpenAI/Azure). See [Advanced Agent Options]({{ site.baseurl }}/tutorials/agent-options)
35
42
 
36
43
  **Returns:** `RCrewAI::Task` instance
37
44
 
@@ -30,9 +30,10 @@ require 'benchmark'
30
30
  RCrewAI.configure do |config|
31
31
  config.llm_provider = :openai
32
32
  config.temperature = 0.4
33
- config.max_concurrent_tasks = 8 # Allow up to 8 concurrent tasks
34
- config.task_timeout = 300 # 5-minute timeout per task
33
+ config.timeout = 300 # request timeout (seconds)
35
34
  end
35
+ # Concurrency is a per-run option, not global config:
36
+ # crew.execute(async: true, max_concurrency: 8)
36
37
 
37
38
  # ===== CONCURRENT PROCESSING TOOLS =====
38
39
 
@@ -885,9 +886,11 @@ context: [] # Dependency management continues with available results
885
886
  Designed for horizontal and vertical scaling:
886
887
 
887
888
  ```ruby
888
- config.max_concurrent_tasks = 8 # Configurable concurrency
889
- config.task_timeout = 300 # Timeout management
890
- config.resource_pool_size = 16 # Shared resource scaling
889
+ # Concurrency is controlled per run via the async executor:
890
+ crew.execute(async: true, max_concurrency: 8) # up to 8 concurrent tasks
891
+
892
+ # Request timeout is global config:
893
+ RCrewAI.configure { |c| c.timeout = 300 }
891
894
  ```
892
895
 
893
896
  This concurrent processing system provides a complete framework for optimizing performance through intelligent parallel execution while maintaining reliability and quality standards across all processing streams.
@@ -25,12 +25,12 @@ require 'time'
25
25
 
26
26
  # Configure RCrewAI
27
27
  RCrewAI.configure do |config|
28
- config.llm_client = :openai
28
+ config.llm_provider = :openai
29
29
  config.openai_api_key = ENV['OPENAI_API_KEY']
30
30
  config.log_level = :info
31
- config.max_concurrent_tasks = 6
32
- config.task_timeout = 300
31
+ config.timeout = 300 # request timeout (seconds)
33
32
  end
33
+ # Concurrency is set per run: crew.execute(async: true, max_concurrency: 6)
34
34
 
35
35
  # Base tool for common functionality
36
36
  class CompositeToolBase < RCrewAI::Tools::Base
data/docs/index.md CHANGED
@@ -19,16 +19,31 @@ Build powerful AI agent crews in Ruby that work together to accomplish complex t
19
19
  ## Features
20
20
 
21
21
  - **🤖 Intelligent Agents**: AI agents with reasoning loops, memory, and tool usage capabilities
22
- - **🔗 Multi-LLM Support**: OpenAI, Anthropic (Claude), Google (Gemini), Azure OpenAI, and Ollama
23
- - **🛠️ Rich Tool Ecosystem**: Web search, file operations, SQL, email, code execution, PDF processing, and custom tools
24
- - **🧠 Agent Memory**: Short-term and long-term memory for learning from past executions
22
+ - **🔗 Multi-LLM Support**: OpenAI, Anthropic (Claude), Google (Gemini), Azure OpenAI, and Ollama — configurable per agent
23
+ - **🛠️ Rich Tool Ecosystem**: Native function calling, MCP servers, web search, file operations, SQL, email, code execution, PDF processing, and custom tools
24
+ - **🌊 Flows**: Event-driven workflows (`start`/`listen`/`router`) with branching and persistent state
25
+ - **📚 Knowledge (RAG)**: Ground agents in your own documents (string/file/PDF/CSV/URL) with built-in retrieval
26
+ - **🧠 Cognitive Memory**: Semantic recall (embeddings + cosine) with optional SQLite persistence and short-term/long-term/entity/tool memory types
27
+ - **📤 Structured Output & Guardrails**: Schema-validated task output and validate/transform guardrails
28
+ - **🗳️ Flexible Orchestration**: Sequential, hierarchical, and consensual (propose → vote → pick) processes, plus async execution
25
29
  - **🤝 Human-in-the-Loop**: Interactive approval workflows, human guidance, and collaborative decision making
26
- - **⚡ Advanced Task System**: Dependencies, retries, async/concurrent execution, and context sharing
27
- - **🏗️ Hierarchical Teams**: Manager agents that coordinate and delegate tasks to specialist agents
28
- - **🔒 Production Ready**: Security controls, error handling, logging, monitoring, and sandboxing
29
- - **🎯 Flexible Orchestration**: Sequential, hierarchical, and concurrent execution modes
30
+ - **⚡ Advanced Task System**: Dependencies, retries, async/concurrent execution, planning, and context sharing
31
+ - **🎛️ Production Controls**: Rate limiting (`max_rpm`), context-window management, reasoning passes, multimodal input, and streaming events with cost tracking
30
32
  - **💎 Ruby-First Design**: Built specifically for Ruby developers with idiomatic patterns
31
33
 
34
+ ## What's new (0.4 – 0.7)
35
+
36
+ RCrewAI has expanded well beyond the classic crew model. Recent releases added:
37
+
38
+ - **[Flows]({{ site.baseurl }}/tutorials/flows)** — a second orchestration pillar for event-driven, stateful workflows
39
+ - **[Knowledge / RAG]({{ site.baseurl }}/tutorials/knowledge)** — retrieval-augmented grounding from your own documents
40
+ - **[Cognitive Memory]({{ site.baseurl }}/tutorials/memory)** — semantic, persistent, multi-type agent memory
41
+ - **[Consensual process]({{ site.baseurl }}/tutorials/consensual-process)** — multi-agent voting to pick the best answer
42
+ - **[Advanced agent options]({{ site.baseurl }}/tutorials/agent-options)** — per-agent LLM, reasoning, rate limiting, context-window management, multimodal, structured output, guardrails, and lifecycle hooks
43
+
44
+ See the [CHANGELOG](https://github.com/gkosmo/rcrewAI/blob/main/CHANGELOG.md) and the
45
+ per-release upgrade guides (e.g. [upgrading to 0.7](https://github.com/gkosmo/rcrewAI/blob/main/docs/upgrading-to-0.7.md)) for details.
46
+
32
47
  ## Quick Start
33
48
 
34
49
  ### Basic Agent Collaboration
@@ -0,0 +1,128 @@
1
+ ---
2
+ layout: tutorial
3
+ title: Advanced Agent & Task Options
4
+ description: Per-agent LLM, reasoning, rate limiting, context window, multimodal, structured output, guardrails, and lifecycle hooks
5
+ ---
6
+
7
+ # Advanced Agent & Task Options
8
+
9
+ A tour of the production controls added across 0.4–0.7. All are opt-in; agents
10
+ and tasks behave as before when you don't set them.
11
+
12
+ ## Per-agent LLM
13
+
14
+ Give each agent its own provider/model instead of only the global default:
15
+
16
+ ```ruby
17
+ worker = RCrewAI::Agent.new(name: 'worker', role: '...', goal: '...',
18
+ llm: { provider: :openai, model: 'gpt-4o-mini' })
19
+ manager = RCrewAI::Agent.new(name: 'manager', role: '...', goal: '...',
20
+ llm: { provider: :anthropic, model: 'claude-3-opus-20240229' })
21
+ ```
22
+
23
+ Accepts a provider symbol, an options hash, or a pre-built client. Overrides
24
+ never mutate the global configuration.
25
+
26
+ ## Reasoning
27
+
28
+ Have an agent draft a plan before answering. The trace is exposed on the result
29
+ and doesn't pollute `task.result`:
30
+
31
+ ```ruby
32
+ agent = RCrewAI::Agent.new(name: '...', role: '...', goal: '...',
33
+ reasoning: true, max_reasoning_attempts: 3)
34
+ result = agent.execute_task(task)
35
+ result[:reasoning] # the plan
36
+ result[:content] # the answer
37
+ ```
38
+
39
+ ## Rate limiting
40
+
41
+ Cap an agent's LLM calls to stay under provider limits (thread-safe, holds under
42
+ async execution):
43
+
44
+ ```ruby
45
+ agent = RCrewAI::Agent.new(name: '...', role: '...', goal: '...', max_rpm: 20)
46
+ ```
47
+
48
+ ## Context-window management
49
+
50
+ Trim history to fit the model's context window (oldest non-system messages drop
51
+ first; system + latest always kept):
52
+
53
+ ```ruby
54
+ agent = RCrewAI::Agent.new(name: '...', role: '...', goal: '...',
55
+ respect_context_window: true)
56
+ ```
57
+
58
+ ## Multimodal input
59
+
60
+ Pass images to a vision-capable model via task attachments (local files are
61
+ base64-encoded; URLs pass through). Supported on OpenAI/Azure.
62
+
63
+ ```ruby
64
+ task = RCrewAI::Task.new(
65
+ name: 'describe', description: 'What is in this chart?', agent: agent,
66
+ attachments: [
67
+ { type: :image, path: 'chart.png' },
68
+ { type: :image, url: 'https://example.com/photo.jpg' }
69
+ ]
70
+ )
71
+ ```
72
+
73
+ ## Structured output & guardrails
74
+
75
+ Validate, transform, and persist a task's result:
76
+
77
+ ```ruby
78
+ task = RCrewAI::Task.new(
79
+ name: 'extract', description: '...', agent: agent,
80
+
81
+ output_schema: { type: 'object', properties: { title: { type: 'string' } },
82
+ required: ['title'] }, # -> task.structured_output
83
+
84
+ guardrail: ->(out) { [out.length < 5000, 'too long'] }, # [ok, value_or_error]
85
+
86
+ output_file: 'out/report.md', markdown: true
87
+ )
88
+ task.execute
89
+ task.structured_output # validated object
90
+ task.raw_result # unprocessed string
91
+ ```
92
+
93
+ Schema/guardrail failures re-run the agent with the error fed back.
94
+
95
+ ## Planning
96
+
97
+ Run a planner pass that drafts a per-task plan before execution:
98
+
99
+ ```ruby
100
+ crew = RCrewAI::Crew.new('research', planning: true) # optional planning_llm:
101
+ ```
102
+
103
+ ## Lifecycle hooks & batch runs
104
+
105
+ ```ruby
106
+ crew.before_kickoff { |inputs| inputs.merge(started_at: Time.now) }
107
+ crew.after_kickoff { |result| notify(result); result }
108
+
109
+ crew.execute(inputs: { topic: 'ruby' })
110
+ crew.last_inputs # the resolved inputs
111
+
112
+ # Run the crew once per input set:
113
+ results = crew.kickoff_for_each(inputs: [{ topic: 'ruby' }, { topic: 'python' }])
114
+ ```
115
+
116
+ ## Training & testing
117
+
118
+ ```ruby
119
+ crew.train(n_iterations: 3, filename: 'training.json') # collect feedback
120
+ crew.test(n_iterations: 5) # score repeated runs
121
+ ```
122
+
123
+ ## See also
124
+
125
+ - [Flows]({{ site.baseurl }}/tutorials/flows)
126
+ - [Knowledge (RAG)]({{ site.baseurl }}/tutorials/knowledge)
127
+ - [Cognitive Memory]({{ site.baseurl }}/tutorials/memory)
128
+ - [Consensual Process]({{ site.baseurl }}/tutorials/consensual-process)
@@ -0,0 +1,58 @@
1
+ ---
2
+ layout: tutorial
3
+ title: Consensual Process
4
+ description: Multi-agent consensus — agents propose competing answers and vote to pick one
5
+ ---
6
+
7
+ # Consensual Process
8
+
9
+ For decisions where multiple perspectives matter, the `:consensual` process has
10
+ several agents propose competing answers and vote to pick the best one.
11
+
12
+ > **Since 0.7.0.** Earlier versions treated `:consensual` as a stub that ran
13
+ > tasks sequentially. It now performs real consensus — if you relied on the old
14
+ > behavior, use `process: :sequential`.
15
+
16
+ ## How it works
17
+
18
+ For each task:
19
+
20
+ 1. **Propose** — up to `consensus_agents` agents (default 3, capped from the
21
+ crew) each produce a candidate answer.
22
+ 2. **Vote** — every participant scores each candidate 0–10 against the task's
23
+ description and expected output.
24
+ 3. **Pick** — the highest total score wins. Ties break toward the task's
25
+ assigned agent.
26
+
27
+ ```ruby
28
+ crew = RCrewAI::Crew.new('panel', process: :consensual, consensus_agents: 3)
29
+ crew.add_agent(junior)
30
+ crew.add_agent(senior)
31
+ crew.add_task(task)
32
+
33
+ result = crew.execute # each task goes through propose → vote → pick
34
+ ```
35
+
36
+ ## Cost
37
+
38
+ Consensus multiplies LLM calls: roughly `N` proposals + `N × N` scoring calls per
39
+ task, where `N` is `consensus_agents` (default 3). The cap keeps cost bounded even
40
+ on large crews — raise or lower it to trade thoroughness for cost.
41
+
42
+ ## Edge cases
43
+
44
+ - **One agent** → a single proposal (no meaningful vote), still a valid result.
45
+ - **A proposer errors** → that candidate is dropped; consensus continues with the
46
+ rest.
47
+ - **All proposals fail** → the task is marked failed.
48
+
49
+ ## When to use it
50
+
51
+ Reach for `:consensual` when answer quality benefits from diversity and
52
+ cross-checking — design decisions, judgment calls, ambiguous tasks. For
53
+ straightforward pipelines, `:sequential` or `:hierarchical` is cheaper.
54
+
55
+ ## Runnable example
56
+
57
+ See [`examples/consensual_process_example.rb`](https://github.com/gkosmo/rcrewAI/blob/main/examples/consensual_process_example.rb)
58
+ — runs without an API key.
@@ -0,0 +1,135 @@
1
+ ---
2
+ layout: tutorial
3
+ title: Flows — Event-Driven Workflows
4
+ description: Build structured, stateful workflows with start/listen/router, combinators, and persistence
5
+ ---
6
+
7
+ # Flows
8
+
9
+ Crews are great for "have these agents produce these outputs." **Flows** are the
10
+ second orchestration pillar — for workflows that need explicit branching, joins,
11
+ persistent state, or coordination across multiple crews and plain Ruby steps.
12
+
13
+ Subclass `RCrewAI::Flow` and wire methods together with a class-level DSL.
14
+
15
+ ## A first flow
16
+
17
+ ```ruby
18
+ require 'rcrewai'
19
+
20
+ class ArticleFlow < RCrewAI::Flow
21
+ start :outline
22
+ def outline
23
+ state.sections = %w[intro body conclusion]
24
+ state.sections.length # return value is passed to listeners of :outline
25
+ end
26
+
27
+ listen :outline
28
+ def draft(section_count)
29
+ state.words = section_count * 100
30
+ state.words
31
+ end
32
+
33
+ router :draft
34
+ def review(words)
35
+ words >= 250 ? :publish : :expand # a router returns a label
36
+ end
37
+
38
+ listen :publish
39
+ def publish = state.status = 'published'
40
+
41
+ listen :expand
42
+ def expand = state.status = 'needs more work'
43
+ end
44
+
45
+ flow = ArticleFlow.new
46
+ flow.kickoff(inputs: { author: 'Ada' })
47
+ flow.state.status # => "published"
48
+ flow.state.id # => automatic UUID
49
+ ```
50
+
51
+ ## The DSL
52
+
53
+ - **`start :method`** — an entry point. A flow can have several; all run first.
54
+ - **`listen :trigger`** — runs the following method after `:trigger` completes,
55
+ receiving its return value.
56
+ - **`router :trigger`** — like `listen`, but the method's return value becomes a
57
+ **label** that other `listen` methods can trigger on. This is how you branch.
58
+
59
+ ### Combining triggers
60
+
61
+ ```ruby
62
+ listen and_(:fetch_a, :fetch_b) # fires once, after BOTH complete
63
+ def merge(...); end
64
+
65
+ listen or_(:cache_hit, :cache_miss) # fires when EITHER completes
66
+ def proceed(...); end
67
+ ```
68
+
69
+ ## State
70
+
71
+ `state` is a schemaless object with an automatic UUID. Read and write attributes
72
+ directly (`state.foo = 1`), and seed initial values via `kickoff(inputs:)`:
73
+
74
+ ```ruby
75
+ flow.kickoff(inputs: { topic: 'ruby', max_words: 800 })
76
+ flow.state.topic # => "ruby"
77
+ ```
78
+
79
+ ## Persistence — pause and resume
80
+
81
+ Pass a `state_store:` and a flow's state is saved after each run, so you can
82
+ restore it later by id:
83
+
84
+ ```ruby
85
+ store = RCrewAI::Flow::FileStateStore.new('tmp/flows') # or your own #save/#load
86
+ flow = ArticleFlow.new(state_store: store)
87
+ flow.kickoff
88
+ id = flow.state.id
89
+
90
+ # ...later, even in a fresh process...
91
+ resumed = ArticleFlow.new(state_store: store)
92
+ resumed.restore(id)
93
+ resumed.state.status # => recovered
94
+ ```
95
+
96
+ Built-in stores: `RCrewAI::Flow::MemoryStateStore` (volatile) and
97
+ `RCrewAI::Flow::FileStateStore` (JSON on disk). Any object responding to
98
+ `#save(id, hash)` / `#load(id)` works.
99
+
100
+ ## Running a crew inside a flow
101
+
102
+ A flow step is just a method, so it can kick off a whole crew:
103
+
104
+ ```ruby
105
+ class ResearchFlow < RCrewAI::Flow
106
+ def initialize(crew:, **opts)
107
+ super(**opts)
108
+ @crew = crew
109
+ end
110
+
111
+ start :run
112
+ def run
113
+ state.crew_result = @crew.execute(inputs: { topic: state.topic })
114
+ end
115
+ end
116
+ ```
117
+
118
+ ## Human feedback
119
+
120
+ Pause a flow for input with `human_feedback`:
121
+
122
+ ```ruby
123
+ listen :draft
124
+ def approve(_draft)
125
+ state.approved = human_feedback('Approve this draft?')
126
+ end
127
+ ```
128
+
129
+ Provide a handler for non-interactive runs:
130
+ `ArticleFlow.new(feedback_handler: ->(prompt) { auto_approve(prompt) })`.
131
+
132
+ ## Runnable example
133
+
134
+ See [`examples/flow_example.rb`](https://github.com/gkosmo/rcrewAI/blob/main/examples/flow_example.rb)
135
+ — it runs without an API key.
@@ -62,6 +62,51 @@ Welcome to the RCrewAI tutorials! These step-by-step guides will take you from b
62
62
 
63
63
  ---
64
64
 
65
+ ## ✨ Capabilities (0.4 – 0.7)
66
+
67
+ The features that grew RCrewAI beyond the classic crew model.
68
+
69
+ ### [Flows — Event-Driven Workflows]({{ site.baseurl }}/tutorials/flows)
70
+ **Orchestrate with branching and state.** `start`/`listen`/`router`, `and_`/`or_`
71
+ combinators, schemaless state with a UUID, persistence and resume, running crews
72
+ as steps, and `human_feedback` pause points.
73
+
74
+ **Prerequisites:** Getting Started tutorial
75
+ **Difficulty:** Intermediate ⭐⭐
76
+
77
+ ### [Knowledge (RAG)]({{ site.baseurl }}/tutorials/knowledge)
78
+ **Ground agents in your documents.** String/file/PDF/CSV/URL sources, chunking,
79
+ multi-provider embeddings, and agent- or crew-level attachment with automatic
80
+ retrieval into the prompt.
81
+
82
+ **Prerequisites:** Getting Started tutorial
83
+ **Difficulty:** Intermediate ⭐⭐
84
+
85
+ ### [Cognitive Memory]({{ site.baseurl }}/tutorials/memory)
86
+ **Agents that remember.** Semantic recall (embeddings + cosine), optional SQLite
87
+ persistence, and short-term/long-term/entity/tool memory types — with a
88
+ zero-config default.
89
+
90
+ **Prerequisites:** Getting Started tutorial
91
+ **Difficulty:** Intermediate ⭐⭐
92
+
93
+ ### [Consensual Process]({{ site.baseurl }}/tutorials/consensual-process)
94
+ **Multi-agent voting.** Agents propose competing answers and score each other to
95
+ pick the best; tune cost with `consensus_agents`.
96
+
97
+ **Prerequisites:** Getting Started tutorial
98
+ **Difficulty:** Beginner ⭐
99
+
100
+ ### [Advanced Agent & Task Options]({{ site.baseurl }}/tutorials/agent-options)
101
+ **Production controls.** Per-agent LLM, reasoning passes, rate limiting,
102
+ context-window management, multimodal input, structured output, guardrails,
103
+ planning, lifecycle hooks, and batch runs.
104
+
105
+ **Prerequisites:** Getting Started tutorial
106
+ **Difficulty:** Intermediate ⭐⭐
107
+
108
+ ---
109
+
65
110
  ## 🏗️ Architecture & Scaling
66
111
 
67
112
  ### [Working with Multiple Crews]({{ site.baseurl }}/tutorials/multiple-crews)
@@ -0,0 +1,80 @@
1
+ ---
2
+ layout: tutorial
3
+ title: Knowledge (RAG)
4
+ description: Ground agents in your own documents with retrieval-augmented generation
5
+ ---
6
+
7
+ # Knowledge (RAG)
8
+
9
+ Give agents access to your own documents. Sources are chunked, embedded, and
10
+ stored in a vector store; at execution time the most relevant chunks are
11
+ injected into the agent's task prompt automatically.
12
+
13
+ ## Building a knowledge base
14
+
15
+ ```ruby
16
+ require 'rcrewai'
17
+
18
+ kb = RCrewAI::Knowledge::Base.new(sources: [
19
+ RCrewAI::Knowledge::StringSource.new('Refunds are available within 30 days.'),
20
+ RCrewAI::Knowledge::FileSource.new('docs/policy.txt'),
21
+ RCrewAI::Knowledge::PdfSource.new('handbook.pdf'),
22
+ RCrewAI::Knowledge::CsvSource.new('faq.csv'),
23
+ RCrewAI::Knowledge::UrlSource.new('https://example.com/faq')
24
+ ])
25
+ ```
26
+
27
+ ## Attaching knowledge
28
+
29
+ **Agent-level** (role-specific):
30
+
31
+ ```ruby
32
+ support = RCrewAI::Agent.new(
33
+ name: 'support', role: 'Support specialist', goal: 'Answer using company policy',
34
+ knowledge: kb
35
+ )
36
+
37
+ # Or pass raw sources and let the agent build the base:
38
+ support = RCrewAI::Agent.new(name: 'support', role: '...', goal: '...',
39
+ knowledge_sources: [RCrewAI::Knowledge::StringSource.new('...')])
40
+ ```
41
+
42
+ **Crew-level** (shared with every agent):
43
+
44
+ ```ruby
45
+ crew = RCrewAI::Crew.new('support_crew', knowledge: kb)
46
+ ```
47
+
48
+ When a task runs, chunks relevant to the task description are retrieved and added
49
+ to the prompt under a "Relevant Knowledge" heading.
50
+
51
+ ## Embeddings — pick a provider
52
+
53
+ Embeddings default to OpenAI's `text-embedding-3-small`. Since 0.6.1 the embedder
54
+ is multi-provider:
55
+
56
+ ```ruby
57
+ # Local, no API key:
58
+ embedder = RCrewAI::Knowledge::Embedder.new(provider: :ollama, model: 'nomic-embed-text')
59
+
60
+ # Or :azure / :google. (:anthropic has no embeddings API and raises.)
61
+ kb = RCrewAI::Knowledge::Base.new(sources: [...], embedder: embedder)
62
+ ```
63
+
64
+ Any object responding to `embed(texts) -> [[float, ...], ...]` can be substituted.
65
+
66
+ ## Chunking and the vector store
67
+
68
+ `Knowledge::Base.new` accepts `chunk_size:` and `overlap:` to tune how documents
69
+ are split. The default vector store is in-memory with cosine similarity; the
70
+ store is pluggable if you need a different backend.
71
+
72
+ ```ruby
73
+ kb = RCrewAI::Knowledge::Base.new(sources: [...], chunk_size: 800, overlap: 100)
74
+ kb.search('what is the refund window?', k: 3) # => top-k relevant chunks
75
+ ```
76
+
77
+ ## Runnable example
78
+
79
+ See [`examples/knowledge_rag_example.rb`](https://github.com/gkosmo/rcrewAI/blob/main/examples/knowledge_rag_example.rb)
80
+ — it runs without an API key using a fake embedder.
@@ -0,0 +1,90 @@
1
+ ---
2
+ layout: tutorial
3
+ title: Cognitive Memory
4
+ description: Semantic, persistent, multi-type agent memory
5
+ ---
6
+
7
+ # Cognitive Memory
8
+
9
+ Agents remember what they've done and recall it on future tasks. Memory is
10
+ **zero-config by default** (in-memory, word-overlap recall) and becomes far more
11
+ capable when you add an embedder (semantic recall) and a store (persistence).
12
+
13
+ ## Zero-config
14
+
15
+ Every agent gets a `Memory` scoped to itself. Nothing to set up:
16
+
17
+ ```ruby
18
+ agent = RCrewAI::Agent.new(name: 'engineer', role: '...', goal: '...')
19
+ # agent.memory records executions and recalls relevant ones automatically
20
+ ```
21
+
22
+ ## Semantic recall
23
+
24
+ Pass an embedder and recall becomes semantic — the agent finds conceptually
25
+ related past work even when the wording differs:
26
+
27
+ ```ruby
28
+ embedder = RCrewAI::Knowledge::Embedder.new # or provider: :ollama
29
+ agent = RCrewAI::Agent.new(name: 'engineer', role: '...', goal: '...',
30
+ memory: { embedder: embedder })
31
+ ```
32
+
33
+ Recall falls back to word-overlap similarity without an embedder, and embedding
34
+ failures fall back gracefully — **memory never breaks agent execution.**
35
+
36
+ ## Persistence
37
+
38
+ Give memory a SQLite store and it survives restarts:
39
+
40
+ ```ruby
41
+ store = RCrewAI::Memory::SqliteStore.new(path: '~/.rcrewai/memory.db')
42
+ agent = RCrewAI::Agent.new(name: 'engineer', role: '...', goal: '...',
43
+ memory: { embedder: embedder, store: store })
44
+ ```
45
+
46
+ The default store is `InMemoryStore` (volatile). `SqliteStore` accepts
47
+ `max_candidates:` (default 1000) to bound how many recent rows a search scans,
48
+ keeping recall fast as memory grows.
49
+
50
+ ## Memory types
51
+
52
+ The `Memory` facade exposes four underlying types:
53
+
54
+ ```ruby
55
+ agent.memory.short_term # recent executions (capped, semantic recall)
56
+ agent.memory.long_term # durable, deduped insights from successful runs
57
+ agent.memory.entity # facts about entities (people, systems) seen in work
58
+ agent.memory.tool # tool-call history + outcomes
59
+
60
+ agent.memory.entity.entities # => ["Alice", "AWS", ...]
61
+ agent.memory.long_term.recall('...', limit: 3)
62
+ ```
63
+
64
+ ### Better entity extraction
65
+
66
+ By default entities are extracted heuristically (capitalized tokens). For
67
+ multi-word names, plug in an LLM extractor:
68
+
69
+ ```ruby
70
+ extractor = RCrewAI::Memory::LlmEntityExtractor.new(agent.llm_client)
71
+ agent = RCrewAI::Agent.new(name: '...', role: '...', goal: '...',
72
+ memory: { entity_extractor: extractor })
73
+ ```
74
+
75
+ ## Scoping
76
+
77
+ Memory is scoped per agent, so agents sharing a persistent store don't read each
78
+ other's memories. Override with `memory: { scope: 'shared' }` for deliberate
79
+ sharing.
80
+
81
+ ## The classic API still works
82
+
83
+ `add_execution`, `add_tool_usage`, `relevant_executions`, `tool_usage_for`,
84
+ `clear_short_term!`, `clear_all!`, and `stats` behave as before — the cognitive
85
+ system is a drop-in upgrade.
86
+
87
+ ## Runnable example
88
+
89
+ See [`examples/cognitive_memory_example.rb`](https://github.com/gkosmo/rcrewAI/blob/main/examples/cognitive_memory_example.rb)
90
+ — semantic recall + SQLite persistence, no API key required.
data/lib/rcrewai/crew.rb CHANGED
@@ -64,6 +64,7 @@ module RCrewAI
64
64
  sinks << block if block_given?
65
65
  Array(stream).each { |s| sinks << s } if stream
66
66
  @stream_sink = sinks.empty? ? nil : RCrewAI::Events.fan_out(sinks)
67
+ @tasks.each { |t| t.stream_sink = @stream_sink }
67
68
 
68
69
  run_before_hooks(inputs)
69
70
 
@@ -72,6 +73,11 @@ module RCrewAI
72
73
 
73
74
  result = async ? execute_async(**async_options) : execute_sync
74
75
  run_after_hooks(result)
76
+ ensure
77
+ # Drop per-task references to the caller's sink so request-scoped
78
+ # collectors do not stay reachable after the run. The crew's own
79
+ # +stream_sink+ reader is left intact: Process reads it.
80
+ @tasks.each { |t| t.stream_sink = nil }
75
81
  end
76
82
 
77
83
  # Runs the crew once per input set, returning one result per input in order.
@@ -351,7 +351,7 @@ module RCrewAI
351
351
  end
352
352
 
353
353
  # Execute the task
354
- agent.execute_task(enhanced_task)
354
+ agent.execute_task(enhanced_task, stream: crew.stream_sink)
355
355
  end
356
356
 
357
357
  def should_abort_execution?(failed_tasks, phase_number, _plan)
@@ -421,7 +421,7 @@ module RCrewAI
421
421
 
422
422
  def gather_proposals(task, participants)
423
423
  participants.filter_map do |agent|
424
- content = extract_content(agent.execute_task(task))
424
+ content = extract_content(agent.execute_task(task, stream: crew.stream_sink))
425
425
  { agent: agent, content: content }
426
426
  rescue StandardError => e
427
427
  @logger.warn "Agent #{agent.name} failed to propose: #{e.message}"
data/lib/rcrewai/task.rb CHANGED
@@ -10,7 +10,7 @@ module RCrewAI
10
10
  include HumanInteractionExtensions
11
11
  attr_reader :name, :description, :agent, :context, :expected_output, :tools, :async,
12
12
  :raw_result, :structured_output, :attachments
13
- attr_accessor :result, :status, :start_time, :end_time, :execution_time
13
+ attr_accessor :result, :status, :start_time, :end_time, :execution_time, :stream_sink
14
14
 
15
15
  def initialize(name:, description:, agent: nil, **options)
16
16
  @name = name
@@ -44,6 +44,7 @@ module RCrewAI
44
44
  @start_time = nil
45
45
  @end_time = nil
46
46
  @execution_time = nil
47
+ @stream_sink = nil
47
48
  @retry_count = 0
48
49
  @max_retries = options.fetch(:max_retries, 2)
49
50
  end
@@ -218,7 +219,7 @@ module RCrewAI
218
219
 
219
220
  loop do
220
221
  attempts += 1
221
- raw = extract_content(agent.execute_task(self))
222
+ raw = extract_content(agent.execute_task(self, stream: @stream_sink))
222
223
  @raw_result = raw
223
224
 
224
225
  begin
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RCrewAI
4
- VERSION = '0.7.0'
4
+ VERSION = '0.7.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rcrewai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - gkosmo
@@ -359,10 +359,15 @@ files:
359
359
  - docs/superpowers/specs/2026-07-06-cognitive-memory-design.md
360
360
  - docs/superpowers/specs/2026-07-07-consensual-process-design.md
361
361
  - docs/tutorials/advanced-agents.md
362
+ - docs/tutorials/agent-options.md
363
+ - docs/tutorials/consensual-process.md
362
364
  - docs/tutorials/custom-tools.md
363
365
  - docs/tutorials/deployment.md
366
+ - docs/tutorials/flows.md
364
367
  - docs/tutorials/getting-started.md
365
368
  - docs/tutorials/index.md
369
+ - docs/tutorials/knowledge.md
370
+ - docs/tutorials/memory.md
366
371
  - docs/tutorials/multiple-crews.md
367
372
  - docs/upgrading-to-0.3.md
368
373
  - docs/upgrading-to-0.4.md