robot_lab 0.0.1 → 0.0.4
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 +4 -4
- data/.github/workflows/deploy-github-pages.yml +9 -9
- data/.irbrc +6 -0
- data/CHANGELOG.md +90 -0
- data/README.md +203 -46
- data/Rakefile +70 -1
- data/docs/api/core/index.md +12 -0
- data/docs/api/core/robot.md +478 -130
- data/docs/api/core/tool.md +205 -209
- data/docs/api/history/active-record-adapter.md +174 -94
- data/docs/api/history/config.md +186 -93
- data/docs/api/history/index.md +57 -61
- data/docs/api/history/thread-manager.md +123 -73
- data/docs/api/mcp/client.md +119 -48
- data/docs/api/mcp/index.md +75 -60
- data/docs/api/mcp/server.md +120 -136
- data/docs/api/mcp/transports.md +172 -184
- data/docs/api/streaming/context.md +157 -74
- data/docs/api/streaming/events.md +114 -166
- data/docs/api/streaming/index.md +74 -72
- data/docs/architecture/core-concepts.md +361 -112
- data/docs/architecture/index.md +97 -59
- data/docs/architecture/message-flow.md +138 -129
- data/docs/architecture/network-orchestration.md +197 -50
- data/docs/architecture/robot-execution.md +199 -146
- data/docs/architecture/state-management.md +255 -187
- data/docs/concepts.md +312 -48
- data/docs/examples/basic-chat.md +89 -77
- data/docs/examples/index.md +222 -47
- data/docs/examples/mcp-server.md +207 -203
- data/docs/examples/multi-robot-network.md +129 -35
- data/docs/examples/rails-application.md +159 -160
- data/docs/examples/tool-usage.md +295 -204
- data/docs/getting-started/configuration.md +275 -162
- data/docs/getting-started/index.md +1 -1
- data/docs/getting-started/installation.md +22 -13
- data/docs/getting-started/quick-start.md +166 -121
- data/docs/guides/building-robots.md +417 -212
- data/docs/guides/creating-networks.md +94 -24
- data/docs/guides/mcp-integration.md +152 -113
- data/docs/guides/memory.md +220 -164
- data/docs/guides/streaming.md +80 -110
- data/docs/guides/using-tools.md +259 -212
- data/docs/index.md +50 -37
- data/examples/01_simple_robot.rb +6 -9
- data/examples/02_tools.rb +6 -9
- data/examples/03_network.rb +13 -14
- data/examples/04_mcp.rb +5 -8
- data/examples/05_streaming.rb +5 -8
- data/examples/06_prompt_templates.rb +42 -37
- data/examples/07_network_memory.rb +13 -14
- data/examples/08_llm_config.rb +140 -0
- data/examples/09_chaining.rb +223 -0
- data/examples/10_memory.rb +331 -0
- data/examples/11_network_introspection.rb +230 -0
- data/examples/12_message_bus.rb +74 -0
- data/examples/13_spawn.rb +90 -0
- data/examples/14_rusty_circuit/comic.rb +143 -0
- data/examples/14_rusty_circuit/display.rb +203 -0
- data/examples/14_rusty_circuit/heckler.rb +57 -0
- data/examples/14_rusty_circuit/open_mic.rb +121 -0
- data/examples/14_rusty_circuit/prompts/open_mic_comic.md +20 -0
- data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +23 -0
- data/examples/14_rusty_circuit/prompts/open_mic_scout.md +20 -0
- data/examples/14_rusty_circuit/scout.rb +173 -0
- data/examples/14_rusty_circuit/scout_notes.md +89 -0
- data/examples/14_rusty_circuit/show.log +234 -0
- data/examples/15_memory_network_and_bus/editor_in_chief.rb +24 -0
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +206 -0
- data/examples/15_memory_network_and_bus/linux_writer.rb +80 -0
- data/examples/15_memory_network_and_bus/os_editor.rb +46 -0
- data/examples/15_memory_network_and_bus/os_writer.rb +46 -0
- data/examples/15_memory_network_and_bus/output/combined_article.md +13 -0
- data/examples/15_memory_network_and_bus/output/final_article.md +15 -0
- data/examples/15_memory_network_and_bus/output/linux_draft.md +5 -0
- data/examples/15_memory_network_and_bus/output/mac_draft.md +7 -0
- data/examples/15_memory_network_and_bus/output/memory.json +13 -0
- data/examples/15_memory_network_and_bus/output/revision_1.md +19 -0
- data/examples/15_memory_network_and_bus/output/revision_2.md +15 -0
- data/examples/15_memory_network_and_bus/output/windows_draft.md +7 -0
- data/examples/15_memory_network_and_bus/prompts/os_advocate.md +13 -0
- data/examples/15_memory_network_and_bus/prompts/os_chief.md +13 -0
- data/examples/15_memory_network_and_bus/prompts/os_editor.md +13 -0
- data/examples/README.md +197 -0
- data/examples/prompts/{assistant/system.txt.erb → assistant.md} +3 -0
- data/examples/prompts/{billing/system.txt.erb → billing.md} +3 -0
- data/examples/prompts/{classifier/system.txt.erb → classifier.md} +3 -0
- data/examples/prompts/comedian.md +6 -0
- data/examples/prompts/comedy_critic.md +10 -0
- data/examples/prompts/configurable.md +9 -0
- data/examples/prompts/dispatcher.md +12 -0
- data/examples/prompts/{entity_extractor/system.txt.erb → entity_extractor.md} +3 -0
- data/examples/prompts/{escalation/system.txt.erb → escalation.md} +7 -0
- data/examples/prompts/frontmatter_mcp_test.md +9 -0
- data/examples/prompts/frontmatter_named_test.md +5 -0
- data/examples/prompts/frontmatter_tools_test.md +6 -0
- data/examples/prompts/{general/system.txt.erb → general.md} +3 -0
- data/examples/prompts/{github_assistant/system.txt.erb → github_assistant.md} +8 -0
- data/examples/prompts/{helper/system.txt.erb → helper.md} +3 -0
- data/examples/prompts/{keyword_extractor/system.txt.erb → keyword_extractor.md} +3 -0
- data/examples/prompts/llm_config_demo.md +20 -0
- data/examples/prompts/{order_support/system.txt.erb → order_support.md} +8 -0
- data/examples/prompts/os_advocate.md +13 -0
- data/examples/prompts/os_chief.md +13 -0
- data/examples/prompts/os_editor.md +13 -0
- data/examples/prompts/{product_support/system.txt.erb → product_support.md} +7 -0
- data/examples/prompts/{sentiment_analyzer/system.txt.erb → sentiment_analyzer.md} +3 -0
- data/examples/prompts/{synthesizer/system.txt.erb → synthesizer.md} +3 -0
- data/examples/prompts/{technical/system.txt.erb → technical.md} +3 -0
- data/examples/prompts/{triage/system.txt.erb → triage.md} +6 -0
- data/lib/generators/robot_lab/templates/initializer.rb.tt +1 -1
- data/lib/robot_lab/adapters/openai.rb +2 -1
- data/lib/robot_lab/ask_user.rb +75 -0
- data/lib/robot_lab/config/defaults.yml +121 -0
- data/lib/robot_lab/config.rb +183 -0
- data/lib/robot_lab/error.rb +6 -0
- data/lib/robot_lab/mcp/client.rb +1 -1
- data/lib/robot_lab/memory.rb +2 -2
- data/lib/robot_lab/robot.rb +523 -249
- data/lib/robot_lab/robot_message.rb +44 -0
- data/lib/robot_lab/robot_result.rb +1 -0
- data/lib/robot_lab/robotic_model.rb +1 -1
- data/lib/robot_lab/streaming/context.rb +1 -1
- data/lib/robot_lab/tool.rb +108 -172
- data/lib/robot_lab/tool_config.rb +1 -1
- data/lib/robot_lab/tool_manifest.rb +2 -18
- data/lib/robot_lab/version.rb +1 -1
- data/lib/robot_lab.rb +66 -55
- metadata +107 -116
- data/examples/prompts/assistant/user.txt.erb +0 -1
- data/examples/prompts/billing/user.txt.erb +0 -1
- data/examples/prompts/classifier/user.txt.erb +0 -1
- data/examples/prompts/entity_extractor/user.txt.erb +0 -3
- data/examples/prompts/escalation/user.txt.erb +0 -34
- data/examples/prompts/general/user.txt.erb +0 -1
- data/examples/prompts/github_assistant/user.txt.erb +0 -1
- data/examples/prompts/helper/user.txt.erb +0 -1
- data/examples/prompts/keyword_extractor/user.txt.erb +0 -3
- data/examples/prompts/order_support/user.txt.erb +0 -22
- data/examples/prompts/product_support/user.txt.erb +0 -32
- data/examples/prompts/sentiment_analyzer/user.txt.erb +0 -3
- data/examples/prompts/synthesizer/user.txt.erb +0 -15
- data/examples/prompts/technical/user.txt.erb +0 -1
- data/examples/prompts/triage/user.txt.erb +0 -17
- data/lib/robot_lab/configuration.rb +0 -143
|
@@ -4,7 +4,7 @@ Customer service system with intelligent routing using SimpleFlow pipelines.
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
This example demonstrates a multi-robot network where a classifier routes customer inquiries to specialized support robots using optional task activation.
|
|
7
|
+
This example demonstrates a multi-robot network where a classifier routes customer inquiries to specialized support robots using SimpleFlow's optional task activation.
|
|
8
8
|
|
|
9
9
|
## Complete Example
|
|
10
10
|
|
|
@@ -15,14 +15,12 @@ This example demonstrates a multi-robot network where a classifier routes custom
|
|
|
15
15
|
require "bundler/setup"
|
|
16
16
|
require "robot_lab"
|
|
17
17
|
|
|
18
|
-
RobotLab.configure do |config|
|
|
19
|
-
config.default_model = "claude-sonnet-4"
|
|
20
|
-
end
|
|
21
|
-
|
|
22
18
|
# Custom classifier that routes to specialists
|
|
23
19
|
class ClassifierRobot < RobotLab::Robot
|
|
24
20
|
def call(result)
|
|
25
|
-
|
|
21
|
+
context = extract_run_context(result)
|
|
22
|
+
message = context.delete(:message)
|
|
23
|
+
robot_result = run(message, **context)
|
|
26
24
|
|
|
27
25
|
new_result = result
|
|
28
26
|
.with_context(@name.to_sym, robot_result)
|
|
@@ -44,7 +42,7 @@ end
|
|
|
44
42
|
classifier = ClassifierRobot.new(
|
|
45
43
|
name: "classifier",
|
|
46
44
|
description: "Classifies customer inquiries",
|
|
47
|
-
system_prompt: <<~PROMPT
|
|
45
|
+
system_prompt: <<~PROMPT,
|
|
48
46
|
You are a customer inquiry classifier. Analyze the customer's message
|
|
49
47
|
and respond with exactly ONE of these categories:
|
|
50
48
|
|
|
@@ -55,13 +53,14 @@ classifier = ClassifierRobot.new(
|
|
|
55
53
|
|
|
56
54
|
Respond with ONLY the category name, nothing else.
|
|
57
55
|
PROMPT
|
|
56
|
+
model: "claude-sonnet-4"
|
|
58
57
|
)
|
|
59
58
|
|
|
60
59
|
# Billing specialist
|
|
61
60
|
billing_agent = RobotLab.build(
|
|
62
61
|
name: "billing_agent",
|
|
63
62
|
description: "Handles billing inquiries",
|
|
64
|
-
system_prompt: <<~PROMPT
|
|
63
|
+
system_prompt: <<~PROMPT,
|
|
65
64
|
You are a billing support specialist. You help customers with:
|
|
66
65
|
- Payment issues and refunds
|
|
67
66
|
- Invoice questions
|
|
@@ -70,13 +69,14 @@ billing_agent = RobotLab.build(
|
|
|
70
69
|
|
|
71
70
|
Be helpful, empathetic, and provide clear next steps.
|
|
72
71
|
PROMPT
|
|
72
|
+
model: "claude-sonnet-4"
|
|
73
73
|
)
|
|
74
74
|
|
|
75
75
|
# Technical support
|
|
76
76
|
tech_agent = RobotLab.build(
|
|
77
77
|
name: "tech_agent",
|
|
78
78
|
description: "Handles technical issues",
|
|
79
|
-
system_prompt: <<~PROMPT
|
|
79
|
+
system_prompt: <<~PROMPT,
|
|
80
80
|
You are a technical support specialist. You help customers with:
|
|
81
81
|
- Bug reports and troubleshooting
|
|
82
82
|
- Feature explanations
|
|
@@ -85,13 +85,14 @@ tech_agent = RobotLab.build(
|
|
|
85
85
|
|
|
86
86
|
Ask clarifying questions when needed. Provide step-by-step solutions.
|
|
87
87
|
PROMPT
|
|
88
|
+
model: "claude-sonnet-4"
|
|
88
89
|
)
|
|
89
90
|
|
|
90
91
|
# Account specialist
|
|
91
92
|
account_agent = RobotLab.build(
|
|
92
93
|
name: "account_agent",
|
|
93
94
|
description: "Handles account issues",
|
|
94
|
-
system_prompt: <<~PROMPT
|
|
95
|
+
system_prompt: <<~PROMPT,
|
|
95
96
|
You are an account support specialist. You help customers with:
|
|
96
97
|
- Login and authentication issues
|
|
97
98
|
- Profile and settings changes
|
|
@@ -100,13 +101,14 @@ account_agent = RobotLab.build(
|
|
|
100
101
|
|
|
101
102
|
Prioritize security while being helpful.
|
|
102
103
|
PROMPT
|
|
104
|
+
model: "claude-sonnet-4"
|
|
103
105
|
)
|
|
104
106
|
|
|
105
107
|
# General support
|
|
106
108
|
general_agent = RobotLab.build(
|
|
107
109
|
name: "general_agent",
|
|
108
110
|
description: "Handles general inquiries",
|
|
109
|
-
system_prompt: <<~PROMPT
|
|
111
|
+
system_prompt: <<~PROMPT,
|
|
110
112
|
You are a general support agent. You help customers with:
|
|
111
113
|
- Product information
|
|
112
114
|
- General questions
|
|
@@ -115,6 +117,7 @@ general_agent = RobotLab.build(
|
|
|
115
117
|
|
|
116
118
|
Be friendly and informative.
|
|
117
119
|
PROMPT
|
|
120
|
+
model: "claude-sonnet-4"
|
|
118
121
|
)
|
|
119
122
|
|
|
120
123
|
# Create the network with optional task routing
|
|
@@ -161,16 +164,53 @@ test_inquiries.each do |inquiry|
|
|
|
161
164
|
end
|
|
162
165
|
```
|
|
163
166
|
|
|
164
|
-
##
|
|
167
|
+
## ClassifierRobot Pattern
|
|
168
|
+
|
|
169
|
+
The key to conditional routing is overriding the `call` method. The base `Robot#call` extracts the message from the `SimpleFlow::Result` and calls `run`. A classifier overrides this to inspect the output and activate the appropriate optional task:
|
|
165
170
|
|
|
166
171
|
```ruby
|
|
167
|
-
|
|
172
|
+
class ClassifierRobot < RobotLab::Robot
|
|
173
|
+
def call(result)
|
|
174
|
+
# 1. Extract run context from the SimpleFlow result
|
|
175
|
+
context = extract_run_context(result)
|
|
176
|
+
|
|
177
|
+
# 2. Pull out the message (it's a key in the context hash)
|
|
178
|
+
message = context.delete(:message)
|
|
179
|
+
|
|
180
|
+
# 3. Run the robot to get a classification
|
|
181
|
+
robot_result = run(message, **context)
|
|
182
|
+
|
|
183
|
+
# 4. Store our result and continue the pipeline
|
|
184
|
+
new_result = result
|
|
185
|
+
.with_context(@name.to_sym, robot_result)
|
|
186
|
+
.continue(robot_result)
|
|
187
|
+
|
|
188
|
+
# 5. Activate the appropriate optional task based on output
|
|
189
|
+
category = robot_result.last_text_content.to_s.strip.downcase
|
|
190
|
+
case category
|
|
191
|
+
when /billing/ then new_result.activate(:billing)
|
|
192
|
+
when /technical/ then new_result.activate(:technical)
|
|
193
|
+
else new_result.activate(:general)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
!!! note "extract_run_context"
|
|
200
|
+
The `extract_run_context(result)` method is a protected helper on `Robot`. It extracts `run_params` from the SimpleFlow result context, handles value propagation from previous steps, and separates robot-specific params (`mcp:`, `tools:`, `memory:`, `network_memory:`) from the message and other context.
|
|
168
201
|
|
|
202
|
+
## With Context Passing
|
|
203
|
+
|
|
204
|
+
Enhanced version where the classifier passes additional context to specialists:
|
|
205
|
+
|
|
206
|
+
```ruby
|
|
169
207
|
class ContextAwareClassifier < RobotLab::Robot
|
|
170
208
|
def call(result)
|
|
171
|
-
|
|
209
|
+
context = extract_run_context(result)
|
|
210
|
+
message = context.delete(:message)
|
|
211
|
+
robot_result = run(message, **context)
|
|
172
212
|
|
|
173
|
-
# Store classification in context for specialist
|
|
213
|
+
# Store classification and original message in context for specialist
|
|
174
214
|
new_result = result
|
|
175
215
|
.with_context(@name.to_sym, robot_result)
|
|
176
216
|
.with_context(:classification, robot_result.last_text_content.strip)
|
|
@@ -193,11 +233,10 @@ class BillingAgent < RobotLab::Robot
|
|
|
193
233
|
classification = result.context[:classification]
|
|
194
234
|
original_message = result.context[:original_message]
|
|
195
235
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
)
|
|
236
|
+
context = extract_run_context(result)
|
|
237
|
+
message = context.delete(:message)
|
|
238
|
+
|
|
239
|
+
robot_result = run(message, **context)
|
|
201
240
|
|
|
202
241
|
result.with_context(@name.to_sym, robot_result).continue(robot_result)
|
|
203
242
|
end
|
|
@@ -206,8 +245,9 @@ end
|
|
|
206
245
|
|
|
207
246
|
## Per-Task Configuration
|
|
208
247
|
|
|
248
|
+
Tasks can have individual context, tools, and MCP servers:
|
|
249
|
+
|
|
209
250
|
```ruby
|
|
210
|
-
# Tasks with individual context and tools
|
|
211
251
|
network = RobotLab.create_network(name: "support") do
|
|
212
252
|
task :classifier, classifier, depends_on: :none
|
|
213
253
|
task :billing_agent, billing_agent,
|
|
@@ -216,15 +256,33 @@ network = RobotLab.create_network(name: "support") do
|
|
|
216
256
|
depends_on: :optional
|
|
217
257
|
task :tech_agent, tech_agent,
|
|
218
258
|
context: { department: "technical" },
|
|
219
|
-
mcp: [
|
|
259
|
+
mcp: [filesystem_server],
|
|
220
260
|
depends_on: :optional
|
|
221
261
|
end
|
|
222
262
|
```
|
|
223
263
|
|
|
264
|
+
The `Task` wrapper deep-merges per-task context with the network's run params before delegating to the robot's `call` method.
|
|
265
|
+
|
|
224
266
|
## Pipeline Pattern
|
|
225
267
|
|
|
268
|
+
Sequential processing pipeline where each robot depends on the previous:
|
|
269
|
+
|
|
226
270
|
```ruby
|
|
227
|
-
|
|
271
|
+
extractor = RobotLab.build(
|
|
272
|
+
name: "extractor",
|
|
273
|
+
system_prompt: "Extract key information from documents."
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
analyzer = RobotLab.build(
|
|
277
|
+
name: "analyzer",
|
|
278
|
+
system_prompt: "Analyze extracted data and provide insights."
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
formatter = RobotLab.build(
|
|
282
|
+
name: "formatter",
|
|
283
|
+
system_prompt: "Format analysis results into a clear report."
|
|
284
|
+
)
|
|
285
|
+
|
|
228
286
|
network = RobotLab.create_network(name: "document_processor") do
|
|
229
287
|
task :extract, extractor, depends_on: :none
|
|
230
288
|
task :analyze, analyzer, depends_on: [:extract]
|
|
@@ -237,35 +295,69 @@ puts result.value.last_text_content
|
|
|
237
295
|
|
|
238
296
|
## Parallel Analysis Pattern
|
|
239
297
|
|
|
298
|
+
Fan-out / fan-in pattern where multiple robots analyze in parallel and a synthesizer merges results:
|
|
299
|
+
|
|
240
300
|
```ruby
|
|
241
|
-
|
|
242
|
-
network = RobotLab.create_network(name: "multi_analysis", concurrency: :threads) do
|
|
301
|
+
network = RobotLab.create_network(name: "multi_analysis") do
|
|
243
302
|
task :prepare, preparer, depends_on: :none
|
|
244
303
|
|
|
245
|
-
# These run in parallel
|
|
304
|
+
# These run in parallel (all depend on :prepare)
|
|
246
305
|
task :sentiment, sentiment_analyzer, depends_on: [:prepare]
|
|
247
306
|
task :entities, entity_extractor, depends_on: [:prepare]
|
|
248
307
|
task :keywords, keyword_extractor, depends_on: [:prepare]
|
|
249
308
|
|
|
250
|
-
# Waits for all three
|
|
309
|
+
# Waits for all three to complete
|
|
251
310
|
task :summarize, summarizer, depends_on: [:sentiment, :entities, :keywords]
|
|
252
311
|
end
|
|
253
312
|
|
|
254
313
|
result = network.run(message: "Analyze this text")
|
|
255
314
|
|
|
256
|
-
# Access parallel results
|
|
315
|
+
# Access parallel results from context
|
|
257
316
|
puts "Sentiment: #{result.context[:sentiment].last_text_content}"
|
|
258
317
|
puts "Entities: #{result.context[:entities].last_text_content}"
|
|
259
318
|
puts "Keywords: #{result.context[:keywords].last_text_content}"
|
|
260
319
|
puts "Summary: #{result.value.last_text_content}"
|
|
261
320
|
```
|
|
262
321
|
|
|
322
|
+
## Shared Memory in Networks
|
|
323
|
+
|
|
324
|
+
Networks provide a shared `Memory` instance that all robots can read and write. This is especially useful for parallel robots that need to coordinate:
|
|
325
|
+
|
|
326
|
+
```ruby
|
|
327
|
+
class AnalysisRobot < RobotLab::Robot
|
|
328
|
+
def initialize(memory_key:, **opts)
|
|
329
|
+
super(**opts)
|
|
330
|
+
@memory_key = memory_key
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def call(result)
|
|
334
|
+
context = extract_run_context(result)
|
|
335
|
+
network_memory = context.delete(:network_memory)
|
|
336
|
+
message = context.delete(:message)
|
|
337
|
+
|
|
338
|
+
robot_result = run(message, network_memory: network_memory, **context)
|
|
339
|
+
|
|
340
|
+
# Write parsed results to shared memory
|
|
341
|
+
if network_memory
|
|
342
|
+
network_memory.current_writer = @name
|
|
343
|
+
network_memory.set(@memory_key, robot_result.last_text_content)
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
result.with_context(@name.to_sym, robot_result).continue(robot_result)
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
```
|
|
350
|
+
|
|
263
351
|
## Conditional Halting
|
|
264
352
|
|
|
353
|
+
Use `result.halt` to stop the pipeline early:
|
|
354
|
+
|
|
265
355
|
```ruby
|
|
266
356
|
class ValidatorRobot < RobotLab::Robot
|
|
267
357
|
def call(result)
|
|
268
|
-
|
|
358
|
+
context = extract_run_context(result)
|
|
359
|
+
message = context.delete(:message)
|
|
360
|
+
robot_result = run(message, **context)
|
|
269
361
|
|
|
270
362
|
if robot_result.last_text_content.include?("INVALID")
|
|
271
363
|
# Halt the pipeline early
|
|
@@ -298,12 +390,14 @@ ruby examples/customer_service.rb
|
|
|
298
390
|
|
|
299
391
|
## Key Concepts
|
|
300
392
|
|
|
301
|
-
1. **SimpleFlow Pipeline**: DAG-based execution with dependency management
|
|
302
|
-
2. **Optional Tasks**:
|
|
303
|
-
3. **Robot#call**: Custom routing logic in classifier robots
|
|
304
|
-
4. **
|
|
305
|
-
5. **
|
|
306
|
-
6. **
|
|
393
|
+
1. **SimpleFlow Pipeline**: DAG-based execution with dependency management via `depends_on:`
|
|
394
|
+
2. **Optional Tasks**: Use `depends_on: :optional` for tasks activated dynamically by classifiers
|
|
395
|
+
3. **Robot#call Override**: Custom routing logic in classifier robots that override the `call` method
|
|
396
|
+
4. **extract_run_context**: Helper method to extract message and params from `SimpleFlow::Result`
|
|
397
|
+
5. **Context Flow**: Data passed through `result.context` and accessed by downstream robots
|
|
398
|
+
6. **Parallel Execution**: Tasks with the same dependencies run concurrently
|
|
399
|
+
7. **Shared Memory**: Network memory (`network_memory:`) enables inter-robot communication
|
|
400
|
+
8. **Per-Task Configuration**: Each task can have its own context, tools, and MCP servers via `Task`
|
|
307
401
|
|
|
308
402
|
## See Also
|
|
309
403
|
|