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,310 @@
|
|
|
1
|
+
# Tool Usage
|
|
2
|
+
|
|
3
|
+
Robots with external API integration.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This example demonstrates how to give robots access to external systems through tools, including API calls, database queries, and calculations.
|
|
8
|
+
|
|
9
|
+
## Complete Example
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
#!/usr/bin/env ruby
|
|
13
|
+
# examples/weather_assistant.rb
|
|
14
|
+
|
|
15
|
+
require "bundler/setup"
|
|
16
|
+
require "robot_lab"
|
|
17
|
+
require "http"
|
|
18
|
+
require "json"
|
|
19
|
+
|
|
20
|
+
RobotLab.configure do |config|
|
|
21
|
+
config.default_model = "claude-sonnet-4"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Weather assistant with API integration
|
|
25
|
+
weather_bot = RobotLab.build do
|
|
26
|
+
name "weather_assistant"
|
|
27
|
+
description "Provides weather information"
|
|
28
|
+
|
|
29
|
+
template <<~PROMPT
|
|
30
|
+
You are a helpful weather assistant. You can look up current weather
|
|
31
|
+
conditions for any city. When users ask about weather, use the
|
|
32
|
+
get_weather tool to fetch real data.
|
|
33
|
+
|
|
34
|
+
Always provide temperatures in both Fahrenheit and Celsius.
|
|
35
|
+
Include relevant advice based on conditions (umbrella, sunscreen, etc).
|
|
36
|
+
PROMPT
|
|
37
|
+
|
|
38
|
+
tool :get_weather do
|
|
39
|
+
description "Get current weather for a city"
|
|
40
|
+
|
|
41
|
+
parameter :city, type: :string, required: true,
|
|
42
|
+
description: "City name (e.g., 'New York', 'London')"
|
|
43
|
+
|
|
44
|
+
handler do |city:, **_|
|
|
45
|
+
# Using wttr.in API (free, no key required)
|
|
46
|
+
response = HTTP.get("https://wttr.in/#{URI.encode_www_form_component(city)}?format=j1")
|
|
47
|
+
|
|
48
|
+
if response.status.success?
|
|
49
|
+
data = JSON.parse(response.body)
|
|
50
|
+
current = data["current_condition"].first
|
|
51
|
+
|
|
52
|
+
{
|
|
53
|
+
city: city,
|
|
54
|
+
temperature_f: current["temp_F"],
|
|
55
|
+
temperature_c: current["temp_C"],
|
|
56
|
+
condition: current["weatherDesc"].first["value"],
|
|
57
|
+
humidity: current["humidity"],
|
|
58
|
+
wind_mph: current["windspeedMiles"],
|
|
59
|
+
feels_like_f: current["FeelsLikeF"],
|
|
60
|
+
uv_index: current["uvIndex"]
|
|
61
|
+
}
|
|
62
|
+
else
|
|
63
|
+
{ error: "Could not fetch weather for #{city}" }
|
|
64
|
+
end
|
|
65
|
+
rescue HTTP::Error => e
|
|
66
|
+
{ error: "Network error: #{e.message}" }
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
tool :get_forecast do
|
|
71
|
+
description "Get weather forecast for upcoming days"
|
|
72
|
+
|
|
73
|
+
parameter :city, type: :string, required: true
|
|
74
|
+
parameter :days, type: :integer, default: 3
|
|
75
|
+
|
|
76
|
+
handler do |city:, days: 3, **_|
|
|
77
|
+
response = HTTP.get("https://wttr.in/#{URI.encode_www_form_component(city)}?format=j1")
|
|
78
|
+
|
|
79
|
+
if response.status.success?
|
|
80
|
+
data = JSON.parse(response.body)
|
|
81
|
+
|
|
82
|
+
data["weather"].take(days).map do |day|
|
|
83
|
+
{
|
|
84
|
+
date: day["date"],
|
|
85
|
+
high_f: day["maxtempF"],
|
|
86
|
+
low_f: day["mintempF"],
|
|
87
|
+
condition: day["hourly"].first["weatherDesc"].first["value"]
|
|
88
|
+
}
|
|
89
|
+
end
|
|
90
|
+
else
|
|
91
|
+
{ error: "Could not fetch forecast" }
|
|
92
|
+
end
|
|
93
|
+
rescue HTTP::Error => e
|
|
94
|
+
{ error: "Network error: #{e.message}" }
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Run interactive session
|
|
100
|
+
puts "Weather Assistant (type 'quit' to exit)"
|
|
101
|
+
puts "-" * 50
|
|
102
|
+
|
|
103
|
+
loop do
|
|
104
|
+
print "\nYou: "
|
|
105
|
+
input = gets&.chomp
|
|
106
|
+
|
|
107
|
+
break if input.nil? || input.downcase == "quit"
|
|
108
|
+
next if input.empty?
|
|
109
|
+
|
|
110
|
+
state = RobotLab.create_state(message: input)
|
|
111
|
+
|
|
112
|
+
print "\nAssistant: "
|
|
113
|
+
weather_bot.run(state: state) do |event|
|
|
114
|
+
case event.type
|
|
115
|
+
when :text_delta
|
|
116
|
+
print event.text
|
|
117
|
+
when :tool_call
|
|
118
|
+
puts "\n[Checking weather for #{event.input[:city]}...]"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
puts
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
puts "\nGoodbye!"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Database Integration
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
# examples/order_assistant.rb
|
|
131
|
+
|
|
132
|
+
require "robot_lab"
|
|
133
|
+
|
|
134
|
+
# Mock database
|
|
135
|
+
ORDERS = {
|
|
136
|
+
"ORD001" => { id: "ORD001", status: "shipped", items: ["Widget"], total: 29.99 },
|
|
137
|
+
"ORD002" => { id: "ORD002", status: "processing", items: ["Gadget", "Gizmo"], total: 89.99 }
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
order_bot = RobotLab.build do
|
|
141
|
+
name "order_assistant"
|
|
142
|
+
template "You help customers check their orders."
|
|
143
|
+
|
|
144
|
+
tool :get_order do
|
|
145
|
+
description "Look up an order by ID"
|
|
146
|
+
parameter :order_id, type: :string, required: true
|
|
147
|
+
|
|
148
|
+
handler do |order_id:, state:, **_|
|
|
149
|
+
# Verify user owns this order
|
|
150
|
+
user_id = state.data[:user_id]
|
|
151
|
+
order = ORDERS[order_id.upcase]
|
|
152
|
+
|
|
153
|
+
if order
|
|
154
|
+
order
|
|
155
|
+
else
|
|
156
|
+
{ error: "Order not found" }
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
tool :list_orders do
|
|
162
|
+
description "List user's recent orders"
|
|
163
|
+
parameter :limit, type: :integer, default: 5
|
|
164
|
+
|
|
165
|
+
handler do |limit:, state:, **_|
|
|
166
|
+
user_id = state.data[:user_id]
|
|
167
|
+
# Filter by user in real implementation
|
|
168
|
+
ORDERS.values.take(limit)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
tool :cancel_order do
|
|
173
|
+
description "Cancel an order"
|
|
174
|
+
parameter :order_id, type: :string, required: true
|
|
175
|
+
parameter :reason, type: :string
|
|
176
|
+
|
|
177
|
+
handler do |order_id:, reason: nil, state:, **_|
|
|
178
|
+
order = ORDERS[order_id.upcase]
|
|
179
|
+
|
|
180
|
+
if order.nil?
|
|
181
|
+
{ success: false, error: "Order not found" }
|
|
182
|
+
elsif order[:status] == "shipped"
|
|
183
|
+
{ success: false, error: "Cannot cancel shipped orders" }
|
|
184
|
+
else
|
|
185
|
+
order[:status] = "cancelled"
|
|
186
|
+
order[:cancel_reason] = reason
|
|
187
|
+
{ success: true, message: "Order #{order_id} cancelled" }
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Run with user context
|
|
194
|
+
state = RobotLab.create_state(
|
|
195
|
+
message: "What's the status of order ORD001?",
|
|
196
|
+
data: { user_id: "user_123" }
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
result = order_bot.run(state: state)
|
|
200
|
+
puts result.output.first.content
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Calculator Tool
|
|
204
|
+
|
|
205
|
+
```ruby
|
|
206
|
+
# examples/math_assistant.rb
|
|
207
|
+
|
|
208
|
+
require "robot_lab"
|
|
209
|
+
require "dentaku"
|
|
210
|
+
|
|
211
|
+
calculator = Dentaku::Calculator.new
|
|
212
|
+
|
|
213
|
+
math_bot = RobotLab.build do
|
|
214
|
+
name "math_assistant"
|
|
215
|
+
template "You help with mathematical calculations."
|
|
216
|
+
|
|
217
|
+
tool :calculate do
|
|
218
|
+
description "Evaluate a mathematical expression"
|
|
219
|
+
parameter :expression, type: :string, required: true,
|
|
220
|
+
description: "Math expression like '2 + 2' or 'sqrt(16)'"
|
|
221
|
+
|
|
222
|
+
handler do |expression:, **_|
|
|
223
|
+
result = calculator.evaluate(expression)
|
|
224
|
+
{ expression: expression, result: result }
|
|
225
|
+
rescue => e
|
|
226
|
+
{ error: "Invalid expression: #{e.message}" }
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
tool :solve_equation do
|
|
231
|
+
description "Solve for a variable"
|
|
232
|
+
parameter :equation, type: :string, required: true
|
|
233
|
+
parameter :variable, type: :string, required: true
|
|
234
|
+
|
|
235
|
+
handler do |equation:, variable:, **_|
|
|
236
|
+
result = calculator.solve(equation, variable.to_sym)
|
|
237
|
+
{ equation: equation, variable: variable, solutions: result }
|
|
238
|
+
rescue => e
|
|
239
|
+
{ error: "Could not solve: #{e.message}" }
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Multi-Tool Example
|
|
246
|
+
|
|
247
|
+
```ruby
|
|
248
|
+
# examples/research_assistant.rb
|
|
249
|
+
|
|
250
|
+
research_bot = RobotLab.build do
|
|
251
|
+
name "research_assistant"
|
|
252
|
+
template "You help with research tasks."
|
|
253
|
+
|
|
254
|
+
tool :web_search do
|
|
255
|
+
description "Search the web"
|
|
256
|
+
parameter :query, type: :string, required: true
|
|
257
|
+
handler { |query:, **_| SearchAPI.search(query) }
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
tool :read_url do
|
|
261
|
+
description "Read content from a URL"
|
|
262
|
+
parameter :url, type: :string, required: true
|
|
263
|
+
handler { |url:, **_| HTTP.get(url).body.to_s }
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
tool :summarize do
|
|
267
|
+
description "Summarize text"
|
|
268
|
+
parameter :text, type: :string, required: true
|
|
269
|
+
parameter :length, type: :string, enum: %w[short medium long], default: "medium"
|
|
270
|
+
handler { |text:, length:, **_| Summarizer.summarize(text, length) }
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
tool :save_note do
|
|
274
|
+
description "Save a research note"
|
|
275
|
+
parameter :title, type: :string, required: true
|
|
276
|
+
parameter :content, type: :string, required: true
|
|
277
|
+
handler do |title:, content:, state:, **_|
|
|
278
|
+
notes = state.memory.recall("notes") || []
|
|
279
|
+
notes << { title: title, content: content, created: Time.now }
|
|
280
|
+
state.memory.remember("notes", notes)
|
|
281
|
+
{ saved: true, total_notes: notes.size }
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Running
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
export ANTHROPIC_API_KEY="your-key"
|
|
291
|
+
|
|
292
|
+
# Weather assistant
|
|
293
|
+
ruby examples/weather_assistant.rb
|
|
294
|
+
|
|
295
|
+
# Order lookup
|
|
296
|
+
ruby examples/order_assistant.rb
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Key Concepts
|
|
300
|
+
|
|
301
|
+
1. **Tool Definition**: Use the `tool` DSL with description and parameters
|
|
302
|
+
2. **Handler**: Receives parameters plus state, robot, network context
|
|
303
|
+
3. **Error Handling**: Return error hashes for graceful failures
|
|
304
|
+
4. **State Access**: Tools can read/write state and memory
|
|
305
|
+
|
|
306
|
+
## See Also
|
|
307
|
+
|
|
308
|
+
- [Using Tools Guide](../guides/using-tools.md)
|
|
309
|
+
- [Tool API](../api/core/tool.md)
|
|
310
|
+
- [Memory Guide](../guides/memory.md)
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
RobotLab provides flexible configuration options at global, network, and robot levels.
|
|
4
|
+
|
|
5
|
+
## Global Configuration
|
|
6
|
+
|
|
7
|
+
Configure RobotLab globally using the `configure` block:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
RobotLab.configure do |config|
|
|
11
|
+
# LLM Provider API Keys
|
|
12
|
+
config.anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
|
|
13
|
+
config.openai_api_key = ENV["OPENAI_API_KEY"]
|
|
14
|
+
config.gemini_api_key = ENV["GEMINI_API_KEY"]
|
|
15
|
+
|
|
16
|
+
# Default settings
|
|
17
|
+
config.default_provider = :anthropic
|
|
18
|
+
config.default_model = "claude-sonnet-4"
|
|
19
|
+
|
|
20
|
+
# Execution limits
|
|
21
|
+
config.max_iterations = 10 # Max robots per network run
|
|
22
|
+
config.max_tool_iterations = 10 # Max tool calls per robot run
|
|
23
|
+
|
|
24
|
+
# Streaming
|
|
25
|
+
config.streaming_enabled = true
|
|
26
|
+
|
|
27
|
+
# Logging
|
|
28
|
+
config.logger = Logger.new($stdout)
|
|
29
|
+
|
|
30
|
+
# Template path for prompt files
|
|
31
|
+
config.template_path = "prompts"
|
|
32
|
+
end
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Configuration Options
|
|
36
|
+
|
|
37
|
+
### API Keys
|
|
38
|
+
|
|
39
|
+
| Option | Description |
|
|
40
|
+
|--------|-------------|
|
|
41
|
+
| `anthropic_api_key` | Anthropic Claude API key |
|
|
42
|
+
| `openai_api_key` | OpenAI API key |
|
|
43
|
+
| `gemini_api_key` | Google Gemini API key |
|
|
44
|
+
| `bedrock_api_key` | AWS Bedrock API key |
|
|
45
|
+
| `openrouter_api_key` | OpenRouter API key |
|
|
46
|
+
|
|
47
|
+
### Defaults
|
|
48
|
+
|
|
49
|
+
| Option | Default | Description |
|
|
50
|
+
|--------|---------|-------------|
|
|
51
|
+
| `default_provider` | `:anthropic` | Default LLM provider |
|
|
52
|
+
| `default_model` | `"claude-sonnet-4"` | Default model |
|
|
53
|
+
| `max_iterations` | `10` | Max robots per network run |
|
|
54
|
+
| `max_tool_iterations` | `10` | Max tool calls per robot |
|
|
55
|
+
| `streaming_enabled` | `true` | Enable streaming by default |
|
|
56
|
+
|
|
57
|
+
### Templates
|
|
58
|
+
|
|
59
|
+
| Option | Default | Description |
|
|
60
|
+
|--------|---------|-------------|
|
|
61
|
+
| `template_path` | `"prompts"` (or `"app/prompts"` in Rails) | Directory for prompt templates |
|
|
62
|
+
|
|
63
|
+
### Global MCP & Tools
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
RobotLab.configure do |config|
|
|
67
|
+
# Global MCP servers available to all networks
|
|
68
|
+
config.mcp = [
|
|
69
|
+
{ name: "github", transport: { type: "stdio", command: "github-mcp" } }
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
# Global tool whitelist
|
|
73
|
+
config.tools = %w[search_code create_issue]
|
|
74
|
+
end
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Network-Level Configuration
|
|
78
|
+
|
|
79
|
+
Override global settings at the network level:
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
network = RobotLab.create_network do
|
|
83
|
+
name "my_network"
|
|
84
|
+
|
|
85
|
+
# Override default model for this network
|
|
86
|
+
default_model "claude-sonnet-4"
|
|
87
|
+
|
|
88
|
+
# Network-specific MCP servers
|
|
89
|
+
mcp [
|
|
90
|
+
{ name: "filesystem", transport: { type: "stdio", command: "mcp-fs" } }
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
# Network-specific tool whitelist
|
|
94
|
+
tools %w[read_file write_file]
|
|
95
|
+
|
|
96
|
+
# Or inherit from global
|
|
97
|
+
mcp :inherit
|
|
98
|
+
tools :inherit
|
|
99
|
+
end
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Robot-Level Configuration
|
|
103
|
+
|
|
104
|
+
Configure individual robots:
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
robot = RobotLab.build do
|
|
108
|
+
name "specialist"
|
|
109
|
+
|
|
110
|
+
# Robot-specific model
|
|
111
|
+
model "claude-sonnet-4"
|
|
112
|
+
|
|
113
|
+
# Robot-specific MCP (overrides network)
|
|
114
|
+
mcp :inherit # Use network's MCP servers
|
|
115
|
+
# or
|
|
116
|
+
mcp :none # No MCP servers for this robot
|
|
117
|
+
# or
|
|
118
|
+
mcp [...] # Specific servers
|
|
119
|
+
|
|
120
|
+
# Robot-specific tools
|
|
121
|
+
tools :inherit # Use network's tools
|
|
122
|
+
end
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Configuration Hierarchy
|
|
126
|
+
|
|
127
|
+
Configuration cascades from global to network to robot:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
Global (RobotLab.configure)
|
|
131
|
+
└── Network (create_network)
|
|
132
|
+
└── Robot (build)
|
|
133
|
+
└── Runtime (robot.run)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Each level can:
|
|
137
|
+
|
|
138
|
+
- `:inherit` - Use parent level's configuration
|
|
139
|
+
- `:none` or `nil` or `[]` - No items allowed
|
|
140
|
+
- `[items]` - Specific items only
|
|
141
|
+
|
|
142
|
+
## Rails Configuration
|
|
143
|
+
|
|
144
|
+
In Rails, configure in an initializer:
|
|
145
|
+
|
|
146
|
+
```ruby title="config/initializers/robot_lab.rb"
|
|
147
|
+
RobotLab.configure do |config|
|
|
148
|
+
# Use Rails credentials
|
|
149
|
+
config.anthropic_api_key = Rails.application.credentials.anthropic_api_key
|
|
150
|
+
|
|
151
|
+
# Use Rails logger
|
|
152
|
+
config.logger = Rails.logger
|
|
153
|
+
|
|
154
|
+
# Template path is automatically set to app/prompts
|
|
155
|
+
end
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Or use `config/application.rb`:
|
|
159
|
+
|
|
160
|
+
```ruby title="config/application.rb"
|
|
161
|
+
module MyApp
|
|
162
|
+
class Application < Rails::Application
|
|
163
|
+
config.robot_lab.default_model = "claude-sonnet-4"
|
|
164
|
+
config.robot_lab.default_provider = :anthropic
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Environment-Specific Configuration
|
|
170
|
+
|
|
171
|
+
```ruby title="config/initializers/robot_lab.rb"
|
|
172
|
+
RobotLab.configure do |config|
|
|
173
|
+
config.anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
|
|
174
|
+
|
|
175
|
+
case Rails.env
|
|
176
|
+
when "development"
|
|
177
|
+
config.logger = Logger.new($stdout, level: :debug)
|
|
178
|
+
config.default_model = "claude-haiku-3" # Faster/cheaper for dev
|
|
179
|
+
when "test"
|
|
180
|
+
config.streaming_enabled = false
|
|
181
|
+
when "production"
|
|
182
|
+
config.logger = Rails.logger
|
|
183
|
+
config.default_model = "claude-sonnet-4"
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Using Environment Variables
|
|
189
|
+
|
|
190
|
+
Recommended environment variables:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# Required - at least one provider
|
|
194
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
195
|
+
OPENAI_API_KEY=sk-...
|
|
196
|
+
GEMINI_API_KEY=...
|
|
197
|
+
|
|
198
|
+
# Optional - override defaults
|
|
199
|
+
ROBOT_LAB_DEFAULT_MODEL=claude-sonnet-4
|
|
200
|
+
ROBOT_LAB_DEFAULT_PROVIDER=anthropic
|
|
201
|
+
ROBOT_LAB_MAX_ITERATIONS=20
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Load them in configuration:
|
|
205
|
+
|
|
206
|
+
```ruby
|
|
207
|
+
RobotLab.configure do |config|
|
|
208
|
+
config.anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
|
|
209
|
+
config.default_model = ENV.fetch("ROBOT_LAB_DEFAULT_MODEL", "claude-sonnet-4")
|
|
210
|
+
config.max_iterations = ENV.fetch("ROBOT_LAB_MAX_ITERATIONS", 10).to_i
|
|
211
|
+
end
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Accessing Configuration
|
|
215
|
+
|
|
216
|
+
```ruby
|
|
217
|
+
# Get current configuration
|
|
218
|
+
config = RobotLab.configuration
|
|
219
|
+
|
|
220
|
+
# Check settings
|
|
221
|
+
config.default_model # => "claude-sonnet-4"
|
|
222
|
+
config.default_provider # => :anthropic
|
|
223
|
+
config.streaming_enabled # => true
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Next Steps
|
|
227
|
+
|
|
228
|
+
- [Building Robots](../guides/building-robots.md) - Create custom robots
|
|
229
|
+
- [Creating Networks](../guides/creating-networks.md) - Network configuration
|
|
230
|
+
- [MCP Integration](../guides/mcp-integration.md) - Configure MCP servers
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
Welcome to RobotLab! This section will help you get up and running quickly.
|
|
4
|
+
|
|
5
|
+
## What You'll Learn
|
|
6
|
+
|
|
7
|
+
In this section, you'll learn how to:
|
|
8
|
+
|
|
9
|
+
1. **Install RobotLab** - Add the gem to your project
|
|
10
|
+
2. **Configure Your Environment** - Set up API keys and defaults
|
|
11
|
+
3. **Create Your First Robot** - Build a simple AI assistant
|
|
12
|
+
4. **Run a Network** - Execute a multi-robot workflow
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
Before you begin, make sure you have:
|
|
17
|
+
|
|
18
|
+
- **Ruby 3.1+** installed
|
|
19
|
+
- An **API key** from at least one LLM provider:
|
|
20
|
+
- [Anthropic](https://console.anthropic.com/) (recommended)
|
|
21
|
+
- [OpenAI](https://platform.openai.com/)
|
|
22
|
+
- [Google AI](https://ai.google.dev/)
|
|
23
|
+
|
|
24
|
+
## Quick Links
|
|
25
|
+
|
|
26
|
+
<div class="grid cards" markdown>
|
|
27
|
+
|
|
28
|
+
- [:octicons-download-24: **Installation**](installation.md)
|
|
29
|
+
|
|
30
|
+
Install RobotLab and dependencies
|
|
31
|
+
|
|
32
|
+
- [:octicons-rocket-24: **Quick Start**](quick-start.md)
|
|
33
|
+
|
|
34
|
+
Build your first robot in 5 minutes
|
|
35
|
+
|
|
36
|
+
- [:octicons-gear-24: **Configuration**](configuration.md)
|
|
37
|
+
|
|
38
|
+
Configure API keys and defaults
|
|
39
|
+
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
## Estimated Time
|
|
43
|
+
|
|
44
|
+
| Guide | Time |
|
|
45
|
+
|-------|------|
|
|
46
|
+
| Installation | 2 minutes |
|
|
47
|
+
| Quick Start | 5 minutes |
|
|
48
|
+
| Configuration | 5 minutes |
|
|
49
|
+
|
|
50
|
+
## Need Help?
|
|
51
|
+
|
|
52
|
+
If you run into issues:
|
|
53
|
+
|
|
54
|
+
- Check the [API Reference](../api/index.md) for detailed documentation
|
|
55
|
+
- Browse [Examples](../examples/index.md) for working code
|
|
56
|
+
- Open an issue on [GitHub](https://github.com/madbomber/robot_lab/issues)
|