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
|
@@ -7,8 +7,9 @@ Networks coordinate multiple robots using [SimpleFlow](https://github.com/MadBom
|
|
|
7
7
|
A network is a thin wrapper around `SimpleFlow::Pipeline`:
|
|
8
8
|
|
|
9
9
|
- **Pipeline**: DAG-based execution engine
|
|
10
|
-
- **Robots**: Named collection of
|
|
11
|
-
- **Tasks**:
|
|
10
|
+
- **Robots**: Named collection of robot instances
|
|
11
|
+
- **Tasks**: Wrap robots with per-task configuration and define dependencies
|
|
12
|
+
- **Memory**: Shared reactive memory for inter-robot communication
|
|
12
13
|
|
|
13
14
|
```ruby
|
|
14
15
|
network = RobotLab.create_network(name: "customer_service") do
|
|
@@ -18,9 +19,27 @@ network = RobotLab.create_network(name: "customer_service") do
|
|
|
18
19
|
end
|
|
19
20
|
```
|
|
20
21
|
|
|
22
|
+
## Creating Networks
|
|
23
|
+
|
|
24
|
+
Networks are created via `RobotLab.create_network` with a block DSL:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
analyst = RobotLab.build(name: "analyst", system_prompt: "Analyze the input.")
|
|
28
|
+
writer = RobotLab.build(name: "writer", system_prompt: "Write a report.")
|
|
29
|
+
reviewer = RobotLab.build(name: "reviewer", system_prompt: "Review the report.")
|
|
30
|
+
|
|
31
|
+
network = RobotLab.create_network(name: "pipeline") do
|
|
32
|
+
task :analyst, analyst, depends_on: :none
|
|
33
|
+
task :writer, writer, depends_on: [:analyst]
|
|
34
|
+
task :reviewer, reviewer, depends_on: [:writer]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
result = network.run(message: "Analyze this quarterly data")
|
|
38
|
+
```
|
|
39
|
+
|
|
21
40
|
## Task Configuration
|
|
22
41
|
|
|
23
|
-
Tasks can have per-task configuration that
|
|
42
|
+
Tasks can have per-task configuration that is deep-merged with network run params:
|
|
24
43
|
|
|
25
44
|
```ruby
|
|
26
45
|
network = RobotLab.create_network(name: "support") do
|
|
@@ -31,11 +50,23 @@ network = RobotLab.create_network(name: "support") do
|
|
|
31
50
|
depends_on: :optional
|
|
32
51
|
task :technical, technical_robot,
|
|
33
52
|
context: { department: "technical" },
|
|
34
|
-
mcp: [
|
|
53
|
+
mcp: [filesystem_server],
|
|
35
54
|
depends_on: :optional
|
|
36
55
|
end
|
|
37
56
|
```
|
|
38
57
|
|
|
58
|
+
### Task Parameters
|
|
59
|
+
|
|
60
|
+
| Parameter | Type | Description |
|
|
61
|
+
|-----------|------|-------------|
|
|
62
|
+
| `name` | Symbol | Task/step name |
|
|
63
|
+
| `robot` | Robot | The robot instance |
|
|
64
|
+
| `context` | Hash | Task-specific context (deep-merged with run params) |
|
|
65
|
+
| `mcp` | Symbol, Array | MCP server config (`:none`, `:inherit`, or array) |
|
|
66
|
+
| `tools` | Symbol, Array | Tools config (`:none`, `:inherit`, or array) |
|
|
67
|
+
| `memory` | Memory, Hash, nil | Task-specific memory |
|
|
68
|
+
| `depends_on` | Symbol, Array | Dependencies (`:none`, `:optional`, or task names) |
|
|
69
|
+
|
|
39
70
|
## Execution Model
|
|
40
71
|
|
|
41
72
|
```mermaid
|
|
@@ -55,53 +86,86 @@ stateDiagram-v2
|
|
|
55
86
|
| Type | Description |
|
|
56
87
|
|------|-------------|
|
|
57
88
|
| `:none` | No dependencies, runs first |
|
|
58
|
-
| `[:task1, :task2]` | Waits for listed tasks |
|
|
59
|
-
| `:optional` | Only runs when activated |
|
|
89
|
+
| `[:task1, :task2]` | Waits for listed tasks to complete |
|
|
90
|
+
| `:optional` | Only runs when explicitly activated |
|
|
60
91
|
|
|
61
92
|
## Robot#call Interface
|
|
62
93
|
|
|
63
|
-
Each robot implements the SimpleFlow step interface
|
|
94
|
+
Each robot implements the SimpleFlow step interface via `call(result)`:
|
|
64
95
|
|
|
65
96
|
```ruby
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
97
|
+
# Inside Robot (simplified)
|
|
98
|
+
def call(result)
|
|
99
|
+
run_context = extract_run_context(result)
|
|
100
|
+
message = run_context.delete(:message)
|
|
70
101
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
102
|
+
robot_result = run(message, **run_context)
|
|
103
|
+
|
|
104
|
+
result
|
|
105
|
+
.with_context(@name.to_sym, robot_result)
|
|
106
|
+
.continue(robot_result)
|
|
76
107
|
end
|
|
77
108
|
```
|
|
78
109
|
|
|
79
|
-
###
|
|
110
|
+
### extract_run_context
|
|
80
111
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
112
|
+
The `extract_run_context` method pulls parameters from the SimpleFlow result:
|
|
113
|
+
|
|
114
|
+
- Extracts `:mcp`, `:tools`, `:memory`, and `:network_memory` from `run_params`
|
|
115
|
+
- Merges the current result value into the context
|
|
116
|
+
- If the previous result value is a `RobotResult`, extracts its `last_text_content` as the message
|
|
117
|
+
- If it is a String, uses it directly as the message
|
|
118
|
+
- If it is a Hash, merges it with the run params
|
|
119
|
+
|
|
120
|
+
## Task#call Interface
|
|
121
|
+
|
|
122
|
+
Each `Task` wraps a robot and enhances the SimpleFlow result before delegation:
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
125
|
+
# Inside Task (simplified)
|
|
126
|
+
def call(result)
|
|
127
|
+
# Deep merge task context with run_params
|
|
128
|
+
run_params = deep_merge(
|
|
129
|
+
result.context[:run_params] || {},
|
|
130
|
+
@context
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# Add task-specific config
|
|
134
|
+
run_params[:mcp] = @mcp unless @mcp == :none
|
|
135
|
+
run_params[:tools] = @tools unless @tools == :none
|
|
136
|
+
run_params[:memory] = @memory if @memory
|
|
137
|
+
|
|
138
|
+
enhanced_result = result.with_context(:run_params, run_params)
|
|
139
|
+
@robot.call(enhanced_result)
|
|
140
|
+
end
|
|
141
|
+
```
|
|
87
142
|
|
|
88
143
|
## SimpleFlow::Result
|
|
89
144
|
|
|
90
145
|
The result object flows through the pipeline:
|
|
91
146
|
|
|
92
147
|
```ruby
|
|
93
|
-
result.value # Current task's output
|
|
148
|
+
result.value # Current task's output (RobotResult)
|
|
94
149
|
result.context # Accumulated context from all tasks
|
|
95
150
|
result.halted? # Whether execution stopped early
|
|
96
151
|
result.continued? # Whether execution continues
|
|
97
152
|
```
|
|
98
153
|
|
|
154
|
+
### Result Methods
|
|
155
|
+
|
|
156
|
+
| Method | Description |
|
|
157
|
+
|--------|-------------|
|
|
158
|
+
| `continue(value)` | Continue to next tasks |
|
|
159
|
+
| `halt(value)` | Stop pipeline execution |
|
|
160
|
+
| `with_context(key, val)` | Add data to context |
|
|
161
|
+
| `activate(task_name)` | Enable an optional task |
|
|
162
|
+
|
|
99
163
|
### Context Structure
|
|
100
164
|
|
|
101
165
|
```ruby
|
|
102
166
|
{
|
|
103
|
-
run_params: { message: "...", customer_id: 123 },
|
|
104
|
-
classifier: RobotResult,
|
|
167
|
+
run_params: { message: "...", customer_id: 123, network_memory: memory },
|
|
168
|
+
classifier: RobotResult, # Stored by Robot#call
|
|
105
169
|
billing: RobotResult,
|
|
106
170
|
# ... other task results
|
|
107
171
|
}
|
|
@@ -109,18 +173,45 @@ result.continued? # Whether execution continues
|
|
|
109
173
|
|
|
110
174
|
## Optional Task Activation
|
|
111
175
|
|
|
112
|
-
Optional tasks
|
|
176
|
+
Optional tasks (those with `depends_on: :optional`) do not run automatically. They must be activated by a preceding task using `result.activate(:task_name)`.
|
|
177
|
+
|
|
178
|
+
This pattern is commonly used with a classifier robot that analyzes the input and routes to the appropriate handler:
|
|
179
|
+
|
|
180
|
+
```ruby
|
|
181
|
+
classifier = RobotLab.build(
|
|
182
|
+
name: "classifier",
|
|
183
|
+
system_prompt: "Classify the request. Respond with: BILLING, TECHNICAL, or GENERAL."
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
billing = RobotLab.build(name: "billing", system_prompt: "Handle billing requests.")
|
|
187
|
+
technical = RobotLab.build(name: "technical", system_prompt: "Handle technical requests.")
|
|
188
|
+
general = RobotLab.build(name: "general", system_prompt: "Handle general requests.")
|
|
189
|
+
|
|
190
|
+
network = RobotLab.create_network(name: "support") do
|
|
191
|
+
task :classifier, classifier, depends_on: :none
|
|
192
|
+
task :billing, billing, depends_on: :optional
|
|
193
|
+
task :technical, technical, depends_on: :optional
|
|
194
|
+
task :general, general, depends_on: :optional
|
|
195
|
+
end
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Classifier Robot Pattern
|
|
199
|
+
|
|
200
|
+
To activate optional tasks, a robot subclass overrides `call` to inspect its own output and activate the appropriate downstream task:
|
|
113
201
|
|
|
114
202
|
```ruby
|
|
115
203
|
class ClassifierRobot < RobotLab::Robot
|
|
116
204
|
def call(result)
|
|
117
|
-
|
|
205
|
+
run_context = extract_run_context(result)
|
|
206
|
+
message = run_context.delete(:message)
|
|
207
|
+
|
|
208
|
+
robot_result = run(message, **run_context)
|
|
118
209
|
|
|
119
210
|
new_result = result
|
|
120
211
|
.with_context(@name.to_sym, robot_result)
|
|
121
212
|
.continue(robot_result)
|
|
122
213
|
|
|
123
|
-
# Analyze output and activate appropriate task
|
|
214
|
+
# Analyze output and activate the appropriate optional task
|
|
124
215
|
category = robot_result.last_text_content.to_s.downcase
|
|
125
216
|
|
|
126
217
|
case category
|
|
@@ -135,6 +226,56 @@ class ClassifierRobot < RobotLab::Robot
|
|
|
135
226
|
end
|
|
136
227
|
```
|
|
137
228
|
|
|
229
|
+
## Shared Memory
|
|
230
|
+
|
|
231
|
+
All robots in a network share the network's memory during execution. The network injects its memory into the run context:
|
|
232
|
+
|
|
233
|
+
```ruby
|
|
234
|
+
# Inside Network#run
|
|
235
|
+
def run(**run_context)
|
|
236
|
+
run_context[:network_memory] = @memory
|
|
237
|
+
initial_result = SimpleFlow::Result.new(
|
|
238
|
+
run_context,
|
|
239
|
+
context: { run_params: run_context }
|
|
240
|
+
)
|
|
241
|
+
@pipeline.call_parallel(initial_result)
|
|
242
|
+
end
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Robots use the shared memory for inter-robot communication:
|
|
246
|
+
|
|
247
|
+
```ruby
|
|
248
|
+
# Robot A writes to shared memory
|
|
249
|
+
memory.set(:classification, "billing")
|
|
250
|
+
|
|
251
|
+
# Robot B reads from shared memory
|
|
252
|
+
category = memory.get(:classification, wait: true)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
See [Memory Management](state-management.md) for details on reactive features like subscriptions and blocking reads.
|
|
256
|
+
|
|
257
|
+
## Broadcasting
|
|
258
|
+
|
|
259
|
+
Networks support a broadcast channel for network-wide announcements:
|
|
260
|
+
|
|
261
|
+
```ruby
|
|
262
|
+
# Register handlers
|
|
263
|
+
network.on_broadcast do |message|
|
|
264
|
+
case message[:payload][:event]
|
|
265
|
+
when :pause
|
|
266
|
+
pause_current_work
|
|
267
|
+
when :resume
|
|
268
|
+
resume_work
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Send broadcasts
|
|
273
|
+
network.broadcast(event: :pause, reason: "rate limit hit")
|
|
274
|
+
network.broadcast(event: :phase_complete, phase: "analysis")
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Broadcasts are dispatched asynchronously and also written to memory at the `_network_broadcast` key, so robots can subscribe via `memory.subscribe(:_network_broadcast)`.
|
|
278
|
+
|
|
138
279
|
## Parallel Execution
|
|
139
280
|
|
|
140
281
|
Tasks with the same dependencies can run in parallel:
|
|
@@ -143,7 +284,7 @@ Tasks with the same dependencies can run in parallel:
|
|
|
143
284
|
network = RobotLab.create_network(name: "analysis", concurrency: :threads) do
|
|
144
285
|
task :fetch, fetcher, depends_on: :none
|
|
145
286
|
|
|
146
|
-
# These three run in parallel
|
|
287
|
+
# These three run in parallel after :fetch completes
|
|
147
288
|
task :sentiment, sentiment_bot, depends_on: [:fetch]
|
|
148
289
|
task :entities, entity_bot, depends_on: [:fetch]
|
|
149
290
|
task :keywords, keyword_bot, depends_on: [:fetch]
|
|
@@ -163,28 +304,26 @@ end
|
|
|
163
304
|
|
|
164
305
|
## Data Flow
|
|
165
306
|
|
|
166
|
-
1. **Initial Value**: `network.run(**params)` creates initial
|
|
307
|
+
1. **Initial Value**: `network.run(**params)` creates an initial `SimpleFlow::Result` with the run context
|
|
167
308
|
2. **Run Params**: Stored in `result.context[:run_params]`
|
|
168
|
-
3. **Task Results**: Each task adds to context
|
|
309
|
+
3. **Task Results**: Each task adds its `RobotResult` to context under its task name
|
|
169
310
|
4. **Final Value**: Last task's output becomes `result.value`
|
|
170
311
|
|
|
171
312
|
```ruby
|
|
172
|
-
# Run with context
|
|
173
313
|
result = network.run(
|
|
174
314
|
message: "Help with billing",
|
|
175
315
|
customer_id: 123
|
|
176
316
|
)
|
|
177
317
|
|
|
178
|
-
|
|
179
|
-
result.context[:
|
|
180
|
-
result.context[:
|
|
181
|
-
result.
|
|
182
|
-
result.value # Final RobotResult
|
|
318
|
+
result.context[:run_params] #=> { message: "...", customer_id: 123, network_memory: ... }
|
|
319
|
+
result.context[:classifier] #=> RobotResult from classifier
|
|
320
|
+
result.context[:billing] #=> RobotResult from billing robot
|
|
321
|
+
result.value #=> Final RobotResult
|
|
183
322
|
```
|
|
184
323
|
|
|
185
324
|
## Visualization
|
|
186
325
|
|
|
187
|
-
Networks provide visualization methods:
|
|
326
|
+
Networks provide visualization methods via the underlying SimpleFlow pipeline:
|
|
188
327
|
|
|
189
328
|
```ruby
|
|
190
329
|
# ASCII representation
|
|
@@ -193,24 +332,32 @@ puts network.visualize
|
|
|
193
332
|
# Mermaid diagram
|
|
194
333
|
puts network.to_mermaid
|
|
195
334
|
|
|
335
|
+
# DOT format (Graphviz)
|
|
336
|
+
puts network.to_dot
|
|
337
|
+
|
|
196
338
|
# Execution plan description
|
|
197
339
|
puts network.execution_plan
|
|
198
340
|
```
|
|
199
341
|
|
|
200
|
-
## Network
|
|
342
|
+
## Network Inspection
|
|
201
343
|
|
|
202
344
|
```ruby
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
345
|
+
# Get a robot by name
|
|
346
|
+
network.robot(:classifier) #=> Robot
|
|
347
|
+
network[:classifier] #=> Robot (alias)
|
|
348
|
+
|
|
349
|
+
# List all robots
|
|
350
|
+
network.available_robots #=> [Robot, Robot, ...]
|
|
351
|
+
|
|
352
|
+
# Add a robot without a task
|
|
353
|
+
network.add_robot(extra_robot)
|
|
354
|
+
|
|
355
|
+
# Convert to hash
|
|
356
|
+
network.to_h
|
|
357
|
+
#=> { name: "support", robots: ["classifier", "billing"], tasks: [...], optional_tasks: [...] }
|
|
210
358
|
```
|
|
211
359
|
|
|
212
360
|
## Next Steps
|
|
213
361
|
|
|
214
|
-
- [
|
|
215
|
-
- [
|
|
216
|
-
- [API Reference: Network](../api/core/network.md) - Complete API
|
|
362
|
+
- [Memory Management](state-management.md) - Shared memory and reactive features
|
|
363
|
+
- [Message Flow](message-flow.md) - How messages are processed within robots
|