robot_lab 0.0.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 +7 -0
- data/.envrc +1 -0
- data/.github/workflows/deploy-github-pages.yml +52 -0
- data/.github/workflows/deploy-yard-docs.yml +52 -0
- data/CHANGELOG.md +55 -0
- data/COMMITS.md +196 -0
- data/LICENSE.txt +21 -0
- data/README.md +332 -0
- data/Rakefile +67 -0
- data/docs/api/adapters/anthropic.md +121 -0
- data/docs/api/adapters/gemini.md +133 -0
- data/docs/api/adapters/index.md +104 -0
- data/docs/api/adapters/openai.md +134 -0
- data/docs/api/core/index.md +113 -0
- data/docs/api/core/memory.md +314 -0
- data/docs/api/core/network.md +291 -0
- data/docs/api/core/robot.md +273 -0
- data/docs/api/core/state.md +273 -0
- data/docs/api/core/tool.md +353 -0
- data/docs/api/history/active-record-adapter.md +195 -0
- data/docs/api/history/config.md +191 -0
- data/docs/api/history/index.md +132 -0
- data/docs/api/history/thread-manager.md +144 -0
- data/docs/api/index.md +82 -0
- data/docs/api/mcp/client.md +221 -0
- data/docs/api/mcp/index.md +111 -0
- data/docs/api/mcp/server.md +225 -0
- data/docs/api/mcp/transports.md +264 -0
- data/docs/api/messages/index.md +67 -0
- data/docs/api/messages/text-message.md +102 -0
- data/docs/api/messages/tool-call-message.md +144 -0
- data/docs/api/messages/tool-result-message.md +154 -0
- data/docs/api/messages/user-message.md +171 -0
- data/docs/api/streaming/context.md +174 -0
- data/docs/api/streaming/events.md +237 -0
- data/docs/api/streaming/index.md +108 -0
- data/docs/architecture/core-concepts.md +243 -0
- data/docs/architecture/index.md +138 -0
- data/docs/architecture/message-flow.md +320 -0
- data/docs/architecture/network-orchestration.md +216 -0
- data/docs/architecture/robot-execution.md +243 -0
- data/docs/architecture/state-management.md +323 -0
- data/docs/assets/css/custom.css +56 -0
- data/docs/assets/images/robot_lab.jpg +0 -0
- data/docs/concepts.md +216 -0
- data/docs/examples/basic-chat.md +193 -0
- data/docs/examples/index.md +129 -0
- data/docs/examples/mcp-server.md +290 -0
- data/docs/examples/multi-robot-network.md +312 -0
- data/docs/examples/rails-application.md +420 -0
- data/docs/examples/tool-usage.md +310 -0
- data/docs/getting-started/configuration.md +230 -0
- data/docs/getting-started/index.md +56 -0
- data/docs/getting-started/installation.md +179 -0
- data/docs/getting-started/quick-start.md +203 -0
- data/docs/guides/building-robots.md +376 -0
- data/docs/guides/creating-networks.md +366 -0
- data/docs/guides/history.md +359 -0
- data/docs/guides/index.md +68 -0
- data/docs/guides/mcp-integration.md +356 -0
- data/docs/guides/memory.md +309 -0
- data/docs/guides/rails-integration.md +432 -0
- data/docs/guides/streaming.md +314 -0
- data/docs/guides/using-tools.md +394 -0
- data/docs/index.md +160 -0
- data/examples/01_simple_robot.rb +38 -0
- data/examples/02_tools.rb +106 -0
- data/examples/03_network.rb +103 -0
- data/examples/04_mcp.rb +219 -0
- data/examples/05_streaming.rb +124 -0
- data/examples/06_prompt_templates.rb +324 -0
- data/examples/07_network_memory.rb +329 -0
- data/examples/prompts/assistant/system.txt.erb +2 -0
- data/examples/prompts/assistant/user.txt.erb +1 -0
- data/examples/prompts/billing/system.txt.erb +7 -0
- data/examples/prompts/billing/user.txt.erb +1 -0
- data/examples/prompts/classifier/system.txt.erb +4 -0
- data/examples/prompts/classifier/user.txt.erb +1 -0
- data/examples/prompts/entity_extractor/system.txt.erb +11 -0
- data/examples/prompts/entity_extractor/user.txt.erb +3 -0
- data/examples/prompts/escalation/system.txt.erb +35 -0
- data/examples/prompts/escalation/user.txt.erb +34 -0
- data/examples/prompts/general/system.txt.erb +4 -0
- data/examples/prompts/general/user.txt.erb +1 -0
- data/examples/prompts/github_assistant/system.txt.erb +6 -0
- data/examples/prompts/github_assistant/user.txt.erb +1 -0
- data/examples/prompts/helper/system.txt.erb +1 -0
- data/examples/prompts/helper/user.txt.erb +1 -0
- data/examples/prompts/keyword_extractor/system.txt.erb +8 -0
- data/examples/prompts/keyword_extractor/user.txt.erb +3 -0
- data/examples/prompts/order_support/system.txt.erb +27 -0
- data/examples/prompts/order_support/user.txt.erb +22 -0
- data/examples/prompts/product_support/system.txt.erb +30 -0
- data/examples/prompts/product_support/user.txt.erb +32 -0
- data/examples/prompts/sentiment_analyzer/system.txt.erb +9 -0
- data/examples/prompts/sentiment_analyzer/user.txt.erb +3 -0
- data/examples/prompts/synthesizer/system.txt.erb +14 -0
- data/examples/prompts/synthesizer/user.txt.erb +15 -0
- data/examples/prompts/technical/system.txt.erb +7 -0
- data/examples/prompts/technical/user.txt.erb +1 -0
- data/examples/prompts/triage/system.txt.erb +16 -0
- data/examples/prompts/triage/user.txt.erb +17 -0
- data/lib/generators/robot_lab/install_generator.rb +78 -0
- data/lib/generators/robot_lab/robot_generator.rb +55 -0
- data/lib/generators/robot_lab/templates/initializer.rb.tt +41 -0
- data/lib/generators/robot_lab/templates/migration.rb.tt +32 -0
- data/lib/generators/robot_lab/templates/result_model.rb.tt +52 -0
- data/lib/generators/robot_lab/templates/robot.rb.tt +46 -0
- data/lib/generators/robot_lab/templates/robot_test.rb.tt +32 -0
- data/lib/generators/robot_lab/templates/routing_robot.rb.tt +53 -0
- data/lib/generators/robot_lab/templates/thread_model.rb.tt +40 -0
- data/lib/robot_lab/adapters/anthropic.rb +163 -0
- data/lib/robot_lab/adapters/base.rb +85 -0
- data/lib/robot_lab/adapters/gemini.rb +193 -0
- data/lib/robot_lab/adapters/openai.rb +159 -0
- data/lib/robot_lab/adapters/registry.rb +81 -0
- data/lib/robot_lab/configuration.rb +143 -0
- data/lib/robot_lab/error.rb +32 -0
- data/lib/robot_lab/errors.rb +70 -0
- data/lib/robot_lab/history/active_record_adapter.rb +146 -0
- data/lib/robot_lab/history/config.rb +115 -0
- data/lib/robot_lab/history/thread_manager.rb +93 -0
- data/lib/robot_lab/mcp/client.rb +210 -0
- data/lib/robot_lab/mcp/server.rb +84 -0
- data/lib/robot_lab/mcp/transports/base.rb +56 -0
- data/lib/robot_lab/mcp/transports/sse.rb +117 -0
- data/lib/robot_lab/mcp/transports/stdio.rb +133 -0
- data/lib/robot_lab/mcp/transports/streamable_http.rb +139 -0
- data/lib/robot_lab/mcp/transports/websocket.rb +108 -0
- data/lib/robot_lab/memory.rb +882 -0
- data/lib/robot_lab/memory_change.rb +123 -0
- data/lib/robot_lab/message.rb +357 -0
- data/lib/robot_lab/network.rb +350 -0
- data/lib/robot_lab/rails/engine.rb +29 -0
- data/lib/robot_lab/rails/railtie.rb +42 -0
- data/lib/robot_lab/robot.rb +560 -0
- data/lib/robot_lab/robot_result.rb +205 -0
- data/lib/robot_lab/robotic_model.rb +324 -0
- data/lib/robot_lab/state_proxy.rb +188 -0
- data/lib/robot_lab/streaming/context.rb +144 -0
- data/lib/robot_lab/streaming/events.rb +95 -0
- data/lib/robot_lab/streaming/sequence_counter.rb +48 -0
- data/lib/robot_lab/task.rb +117 -0
- data/lib/robot_lab/tool.rb +223 -0
- data/lib/robot_lab/tool_config.rb +112 -0
- data/lib/robot_lab/tool_manifest.rb +234 -0
- data/lib/robot_lab/user_message.rb +118 -0
- data/lib/robot_lab/version.rb +5 -0
- data/lib/robot_lab/waiter.rb +73 -0
- data/lib/robot_lab.rb +195 -0
- data/mkdocs.yml +214 -0
- data/sig/robot_lab.rbs +4 -0
- metadata +442 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# Building Robots
|
|
2
|
+
|
|
3
|
+
This guide covers everything you need to know about creating robots in RobotLab.
|
|
4
|
+
|
|
5
|
+
## Basic Robot
|
|
6
|
+
|
|
7
|
+
Create a simple robot with the builder DSL:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
robot = RobotLab.build do
|
|
11
|
+
name "assistant"
|
|
12
|
+
description "A helpful AI assistant"
|
|
13
|
+
template "You are a helpful assistant."
|
|
14
|
+
end
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Robot Properties
|
|
18
|
+
|
|
19
|
+
### Name
|
|
20
|
+
|
|
21
|
+
A unique identifier used for routing and logging:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
name "support_agent"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Description
|
|
28
|
+
|
|
29
|
+
Describes what the robot does (useful for routing decisions):
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
description "Handles customer support inquiries about orders and refunds"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Model
|
|
36
|
+
|
|
37
|
+
The LLM model to use:
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
model "claude-sonnet-4" # Anthropic
|
|
41
|
+
model "gpt-4o" # OpenAI
|
|
42
|
+
model "gemini-1.5-pro" # Google
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Template (System Prompt)
|
|
46
|
+
|
|
47
|
+
Instructions that define the robot's personality and behavior:
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
template <<~PROMPT
|
|
51
|
+
You are a customer support specialist for TechCo.
|
|
52
|
+
|
|
53
|
+
Your responsibilities:
|
|
54
|
+
- Answer questions about products and services
|
|
55
|
+
- Help resolve order issues
|
|
56
|
+
- Provide friendly, professional assistance
|
|
57
|
+
|
|
58
|
+
Always be polite and acknowledge the customer's concerns.
|
|
59
|
+
PROMPT
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Adding Tools
|
|
63
|
+
|
|
64
|
+
Give robots capabilities with tools:
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
robot = RobotLab.build do
|
|
68
|
+
name "order_assistant"
|
|
69
|
+
|
|
70
|
+
tool :lookup_order do
|
|
71
|
+
description "Look up order details by order ID"
|
|
72
|
+
parameter :order_id, type: :string, required: true, description: "The order ID"
|
|
73
|
+
handler do |order_id:, **_context|
|
|
74
|
+
Order.find_by(id: order_id)&.to_h || { error: "Order not found" }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
tool :check_inventory do
|
|
79
|
+
description "Check product inventory"
|
|
80
|
+
parameter :product_id, type: :string, required: true
|
|
81
|
+
parameter :warehouse, type: :string, default: "main"
|
|
82
|
+
handler do |product_id:, warehouse:, **_context|
|
|
83
|
+
Inventory.check(product_id, warehouse: warehouse)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Tool Parameters
|
|
90
|
+
|
|
91
|
+
Define parameters with types and descriptions:
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
tool :search do
|
|
95
|
+
parameter :query, type: :string, required: true, description: "Search query"
|
|
96
|
+
parameter :limit, type: :integer, default: 10, description: "Max results"
|
|
97
|
+
parameter :category, type: :string, enum: %w[books movies music]
|
|
98
|
+
end
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
| Option | Description |
|
|
102
|
+
|--------|-------------|
|
|
103
|
+
| `type` | Parameter type (`:string`, `:integer`, `:boolean`, `:number`, `:array`, `:object`) |
|
|
104
|
+
| `required` | Whether the parameter is required |
|
|
105
|
+
| `default` | Default value if not provided |
|
|
106
|
+
| `description` | Description for the LLM |
|
|
107
|
+
| `enum` | List of allowed values |
|
|
108
|
+
|
|
109
|
+
### Tool Handler Context
|
|
110
|
+
|
|
111
|
+
Handlers receive execution context:
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
handler do |param1:, param2:, robot:, network:, state:|
|
|
115
|
+
# robot - The Robot instance
|
|
116
|
+
# network - The NetworkRun
|
|
117
|
+
# state - Current State
|
|
118
|
+
|
|
119
|
+
# Access state data
|
|
120
|
+
user_id = state.data[:user_id]
|
|
121
|
+
|
|
122
|
+
# Use memory
|
|
123
|
+
state.memory.remember("last_search", param1)
|
|
124
|
+
|
|
125
|
+
# Return result (will be sent to LLM)
|
|
126
|
+
{ success: true, data: result }
|
|
127
|
+
end
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
!!! tip "Ignoring Context"
|
|
131
|
+
Use `**_context` to accept but ignore context:
|
|
132
|
+
```ruby
|
|
133
|
+
handler { |query:, **_context| search(query) }
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Template Files
|
|
137
|
+
|
|
138
|
+
Load templates from files:
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
# Configure template path
|
|
142
|
+
RobotLab.configure do |config|
|
|
143
|
+
config.template_path = "prompts" # or "app/prompts" in Rails
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Reference template by name
|
|
147
|
+
robot = RobotLab.build do
|
|
148
|
+
name "support"
|
|
149
|
+
template "support_agent" # Loads prompts/support_agent.erb
|
|
150
|
+
end
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Template Variables
|
|
154
|
+
|
|
155
|
+
Pass variables to templates:
|
|
156
|
+
|
|
157
|
+
```ruby
|
|
158
|
+
robot = RobotLab.build do
|
|
159
|
+
name "support"
|
|
160
|
+
template "support_agent", company: "TechCo", tone: "friendly"
|
|
161
|
+
end
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```erb title="prompts/support_agent.erb"
|
|
165
|
+
You are a support agent for <%= company %>.
|
|
166
|
+
Your tone should be <%= tone %>.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## MCP Configuration
|
|
170
|
+
|
|
171
|
+
Connect to MCP servers:
|
|
172
|
+
|
|
173
|
+
```ruby
|
|
174
|
+
robot = RobotLab.build do
|
|
175
|
+
name "coder"
|
|
176
|
+
|
|
177
|
+
# Use specific MCP servers
|
|
178
|
+
mcp [
|
|
179
|
+
{
|
|
180
|
+
name: "filesystem",
|
|
181
|
+
transport: { type: "stdio", command: "mcp-server-fs", args: ["--root", "/data"] }
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
# Or inherit from network
|
|
186
|
+
mcp :inherit
|
|
187
|
+
|
|
188
|
+
# Or disable MCP
|
|
189
|
+
mcp :none
|
|
190
|
+
end
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Tool Whitelist
|
|
194
|
+
|
|
195
|
+
Restrict available tools:
|
|
196
|
+
|
|
197
|
+
```ruby
|
|
198
|
+
robot = RobotLab.build do
|
|
199
|
+
name "reader"
|
|
200
|
+
|
|
201
|
+
# Only allow specific tools
|
|
202
|
+
tools %w[read_file list_directory]
|
|
203
|
+
|
|
204
|
+
# Or inherit from network
|
|
205
|
+
tools :inherit
|
|
206
|
+
|
|
207
|
+
# Or disable all inherited tools
|
|
208
|
+
tools :none
|
|
209
|
+
end
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Running Robots
|
|
213
|
+
|
|
214
|
+
### Standalone
|
|
215
|
+
|
|
216
|
+
Run a robot directly:
|
|
217
|
+
|
|
218
|
+
```ruby
|
|
219
|
+
state = RobotLab.create_state(message: "Hello!")
|
|
220
|
+
result = robot.run(state: state, network: nil)
|
|
221
|
+
|
|
222
|
+
puts result.output.first.content
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### In a Network
|
|
226
|
+
|
|
227
|
+
Run through a network for full orchestration:
|
|
228
|
+
|
|
229
|
+
```ruby
|
|
230
|
+
network = RobotLab.create_network do
|
|
231
|
+
add_robot robot
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
state = RobotLab.create_state(message: "Hello!")
|
|
235
|
+
result = network.run(state: state)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### With Streaming
|
|
239
|
+
|
|
240
|
+
Stream responses in real-time:
|
|
241
|
+
|
|
242
|
+
```ruby
|
|
243
|
+
robot.run(
|
|
244
|
+
state: state,
|
|
245
|
+
network: network,
|
|
246
|
+
streaming: ->(event) {
|
|
247
|
+
case event[:event]
|
|
248
|
+
when "delta"
|
|
249
|
+
print event[:data][:content]
|
|
250
|
+
when "tool_call"
|
|
251
|
+
puts "\nCalling tool: #{event[:data][:name]}"
|
|
252
|
+
end
|
|
253
|
+
}
|
|
254
|
+
)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Robot Patterns
|
|
258
|
+
|
|
259
|
+
### Classifier Robot
|
|
260
|
+
|
|
261
|
+
Route requests to specialized handlers:
|
|
262
|
+
|
|
263
|
+
```ruby
|
|
264
|
+
classifier = RobotLab.build do
|
|
265
|
+
name "classifier"
|
|
266
|
+
description "Classifies incoming requests"
|
|
267
|
+
|
|
268
|
+
template <<~PROMPT
|
|
269
|
+
Analyze the user's message and classify it into exactly one category:
|
|
270
|
+
- BILLING: Questions about invoices, payments, subscriptions
|
|
271
|
+
- TECHNICAL: Technical issues, bugs, how-to questions
|
|
272
|
+
- GENERAL: General inquiries, feedback, other
|
|
273
|
+
|
|
274
|
+
Respond with only the category name, nothing else.
|
|
275
|
+
PROMPT
|
|
276
|
+
end
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Specialist Robot
|
|
280
|
+
|
|
281
|
+
Handle specific domains:
|
|
282
|
+
|
|
283
|
+
```ruby
|
|
284
|
+
billing_specialist = RobotLab.build do
|
|
285
|
+
name "billing_specialist"
|
|
286
|
+
description "Handles billing and payment inquiries"
|
|
287
|
+
|
|
288
|
+
template <<~PROMPT
|
|
289
|
+
You are a billing specialist. You help customers with:
|
|
290
|
+
- Invoice questions
|
|
291
|
+
- Payment issues
|
|
292
|
+
- Subscription management
|
|
293
|
+
|
|
294
|
+
Always verify the customer's account before making changes.
|
|
295
|
+
PROMPT
|
|
296
|
+
|
|
297
|
+
tool :get_invoices do
|
|
298
|
+
description "Get customer's recent invoices"
|
|
299
|
+
parameter :customer_id, type: :string, required: true
|
|
300
|
+
handler { |customer_id:, **_| Invoice.where(customer_id: customer_id).limit(10) }
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Summarizer Robot
|
|
306
|
+
|
|
307
|
+
Condense information:
|
|
308
|
+
|
|
309
|
+
```ruby
|
|
310
|
+
summarizer = RobotLab.build do
|
|
311
|
+
name "summarizer"
|
|
312
|
+
description "Summarizes conversations and documents"
|
|
313
|
+
|
|
314
|
+
template <<~PROMPT
|
|
315
|
+
Create concise summaries of the provided content.
|
|
316
|
+
Focus on key points and actionable items.
|
|
317
|
+
Use bullet points for clarity.
|
|
318
|
+
PROMPT
|
|
319
|
+
end
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Best Practices
|
|
323
|
+
|
|
324
|
+
### 1. Clear, Focused Templates
|
|
325
|
+
|
|
326
|
+
```ruby
|
|
327
|
+
# Good: Specific and focused
|
|
328
|
+
template <<~PROMPT
|
|
329
|
+
You are a code reviewer. Review code for:
|
|
330
|
+
- Security vulnerabilities
|
|
331
|
+
- Performance issues
|
|
332
|
+
- Best practice violations
|
|
333
|
+
|
|
334
|
+
Provide specific line numbers and suggestions.
|
|
335
|
+
PROMPT
|
|
336
|
+
|
|
337
|
+
# Bad: Vague and unfocused
|
|
338
|
+
template "You help with code stuff."
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### 2. Descriptive Tool Definitions
|
|
342
|
+
|
|
343
|
+
```ruby
|
|
344
|
+
# Good: Clear description and parameter docs
|
|
345
|
+
tool :search_users do
|
|
346
|
+
description "Search for users by email, name, or ID. Returns up to 10 matches."
|
|
347
|
+
parameter :query, type: :string, required: true,
|
|
348
|
+
description: "Email address, partial name, or user ID"
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
# Bad: Missing context
|
|
352
|
+
tool :search do
|
|
353
|
+
parameter :q, type: :string
|
|
354
|
+
end
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### 3. Handle Tool Errors Gracefully
|
|
358
|
+
|
|
359
|
+
```ruby
|
|
360
|
+
handler do |user_id:, **_|
|
|
361
|
+
user = User.find_by(id: user_id)
|
|
362
|
+
if user
|
|
363
|
+
{ success: true, user: user.to_h }
|
|
364
|
+
else
|
|
365
|
+
{ success: false, error: "User not found", user_id: user_id }
|
|
366
|
+
end
|
|
367
|
+
rescue ActiveRecord::ConnectionError => e
|
|
368
|
+
{ success: false, error: "Database unavailable", retry: true }
|
|
369
|
+
end
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## Next Steps
|
|
373
|
+
|
|
374
|
+
- [Creating Networks](creating-networks.md) - Orchestrate multiple robots
|
|
375
|
+
- [Using Tools](using-tools.md) - Advanced tool patterns
|
|
376
|
+
- [API Reference: Robot](../api/core/robot.md) - Complete API documentation
|