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.
Files changed (153) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +1 -0
  3. data/.github/workflows/deploy-github-pages.yml +52 -0
  4. data/.github/workflows/deploy-yard-docs.yml +52 -0
  5. data/CHANGELOG.md +55 -0
  6. data/COMMITS.md +196 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +332 -0
  9. data/Rakefile +67 -0
  10. data/docs/api/adapters/anthropic.md +121 -0
  11. data/docs/api/adapters/gemini.md +133 -0
  12. data/docs/api/adapters/index.md +104 -0
  13. data/docs/api/adapters/openai.md +134 -0
  14. data/docs/api/core/index.md +113 -0
  15. data/docs/api/core/memory.md +314 -0
  16. data/docs/api/core/network.md +291 -0
  17. data/docs/api/core/robot.md +273 -0
  18. data/docs/api/core/state.md +273 -0
  19. data/docs/api/core/tool.md +353 -0
  20. data/docs/api/history/active-record-adapter.md +195 -0
  21. data/docs/api/history/config.md +191 -0
  22. data/docs/api/history/index.md +132 -0
  23. data/docs/api/history/thread-manager.md +144 -0
  24. data/docs/api/index.md +82 -0
  25. data/docs/api/mcp/client.md +221 -0
  26. data/docs/api/mcp/index.md +111 -0
  27. data/docs/api/mcp/server.md +225 -0
  28. data/docs/api/mcp/transports.md +264 -0
  29. data/docs/api/messages/index.md +67 -0
  30. data/docs/api/messages/text-message.md +102 -0
  31. data/docs/api/messages/tool-call-message.md +144 -0
  32. data/docs/api/messages/tool-result-message.md +154 -0
  33. data/docs/api/messages/user-message.md +171 -0
  34. data/docs/api/streaming/context.md +174 -0
  35. data/docs/api/streaming/events.md +237 -0
  36. data/docs/api/streaming/index.md +108 -0
  37. data/docs/architecture/core-concepts.md +243 -0
  38. data/docs/architecture/index.md +138 -0
  39. data/docs/architecture/message-flow.md +320 -0
  40. data/docs/architecture/network-orchestration.md +216 -0
  41. data/docs/architecture/robot-execution.md +243 -0
  42. data/docs/architecture/state-management.md +323 -0
  43. data/docs/assets/css/custom.css +56 -0
  44. data/docs/assets/images/robot_lab.jpg +0 -0
  45. data/docs/concepts.md +216 -0
  46. data/docs/examples/basic-chat.md +193 -0
  47. data/docs/examples/index.md +129 -0
  48. data/docs/examples/mcp-server.md +290 -0
  49. data/docs/examples/multi-robot-network.md +312 -0
  50. data/docs/examples/rails-application.md +420 -0
  51. data/docs/examples/tool-usage.md +310 -0
  52. data/docs/getting-started/configuration.md +230 -0
  53. data/docs/getting-started/index.md +56 -0
  54. data/docs/getting-started/installation.md +179 -0
  55. data/docs/getting-started/quick-start.md +203 -0
  56. data/docs/guides/building-robots.md +376 -0
  57. data/docs/guides/creating-networks.md +366 -0
  58. data/docs/guides/history.md +359 -0
  59. data/docs/guides/index.md +68 -0
  60. data/docs/guides/mcp-integration.md +356 -0
  61. data/docs/guides/memory.md +309 -0
  62. data/docs/guides/rails-integration.md +432 -0
  63. data/docs/guides/streaming.md +314 -0
  64. data/docs/guides/using-tools.md +394 -0
  65. data/docs/index.md +160 -0
  66. data/examples/01_simple_robot.rb +38 -0
  67. data/examples/02_tools.rb +106 -0
  68. data/examples/03_network.rb +103 -0
  69. data/examples/04_mcp.rb +219 -0
  70. data/examples/05_streaming.rb +124 -0
  71. data/examples/06_prompt_templates.rb +324 -0
  72. data/examples/07_network_memory.rb +329 -0
  73. data/examples/prompts/assistant/system.txt.erb +2 -0
  74. data/examples/prompts/assistant/user.txt.erb +1 -0
  75. data/examples/prompts/billing/system.txt.erb +7 -0
  76. data/examples/prompts/billing/user.txt.erb +1 -0
  77. data/examples/prompts/classifier/system.txt.erb +4 -0
  78. data/examples/prompts/classifier/user.txt.erb +1 -0
  79. data/examples/prompts/entity_extractor/system.txt.erb +11 -0
  80. data/examples/prompts/entity_extractor/user.txt.erb +3 -0
  81. data/examples/prompts/escalation/system.txt.erb +35 -0
  82. data/examples/prompts/escalation/user.txt.erb +34 -0
  83. data/examples/prompts/general/system.txt.erb +4 -0
  84. data/examples/prompts/general/user.txt.erb +1 -0
  85. data/examples/prompts/github_assistant/system.txt.erb +6 -0
  86. data/examples/prompts/github_assistant/user.txt.erb +1 -0
  87. data/examples/prompts/helper/system.txt.erb +1 -0
  88. data/examples/prompts/helper/user.txt.erb +1 -0
  89. data/examples/prompts/keyword_extractor/system.txt.erb +8 -0
  90. data/examples/prompts/keyword_extractor/user.txt.erb +3 -0
  91. data/examples/prompts/order_support/system.txt.erb +27 -0
  92. data/examples/prompts/order_support/user.txt.erb +22 -0
  93. data/examples/prompts/product_support/system.txt.erb +30 -0
  94. data/examples/prompts/product_support/user.txt.erb +32 -0
  95. data/examples/prompts/sentiment_analyzer/system.txt.erb +9 -0
  96. data/examples/prompts/sentiment_analyzer/user.txt.erb +3 -0
  97. data/examples/prompts/synthesizer/system.txt.erb +14 -0
  98. data/examples/prompts/synthesizer/user.txt.erb +15 -0
  99. data/examples/prompts/technical/system.txt.erb +7 -0
  100. data/examples/prompts/technical/user.txt.erb +1 -0
  101. data/examples/prompts/triage/system.txt.erb +16 -0
  102. data/examples/prompts/triage/user.txt.erb +17 -0
  103. data/lib/generators/robot_lab/install_generator.rb +78 -0
  104. data/lib/generators/robot_lab/robot_generator.rb +55 -0
  105. data/lib/generators/robot_lab/templates/initializer.rb.tt +41 -0
  106. data/lib/generators/robot_lab/templates/migration.rb.tt +32 -0
  107. data/lib/generators/robot_lab/templates/result_model.rb.tt +52 -0
  108. data/lib/generators/robot_lab/templates/robot.rb.tt +46 -0
  109. data/lib/generators/robot_lab/templates/robot_test.rb.tt +32 -0
  110. data/lib/generators/robot_lab/templates/routing_robot.rb.tt +53 -0
  111. data/lib/generators/robot_lab/templates/thread_model.rb.tt +40 -0
  112. data/lib/robot_lab/adapters/anthropic.rb +163 -0
  113. data/lib/robot_lab/adapters/base.rb +85 -0
  114. data/lib/robot_lab/adapters/gemini.rb +193 -0
  115. data/lib/robot_lab/adapters/openai.rb +159 -0
  116. data/lib/robot_lab/adapters/registry.rb +81 -0
  117. data/lib/robot_lab/configuration.rb +143 -0
  118. data/lib/robot_lab/error.rb +32 -0
  119. data/lib/robot_lab/errors.rb +70 -0
  120. data/lib/robot_lab/history/active_record_adapter.rb +146 -0
  121. data/lib/robot_lab/history/config.rb +115 -0
  122. data/lib/robot_lab/history/thread_manager.rb +93 -0
  123. data/lib/robot_lab/mcp/client.rb +210 -0
  124. data/lib/robot_lab/mcp/server.rb +84 -0
  125. data/lib/robot_lab/mcp/transports/base.rb +56 -0
  126. data/lib/robot_lab/mcp/transports/sse.rb +117 -0
  127. data/lib/robot_lab/mcp/transports/stdio.rb +133 -0
  128. data/lib/robot_lab/mcp/transports/streamable_http.rb +139 -0
  129. data/lib/robot_lab/mcp/transports/websocket.rb +108 -0
  130. data/lib/robot_lab/memory.rb +882 -0
  131. data/lib/robot_lab/memory_change.rb +123 -0
  132. data/lib/robot_lab/message.rb +357 -0
  133. data/lib/robot_lab/network.rb +350 -0
  134. data/lib/robot_lab/rails/engine.rb +29 -0
  135. data/lib/robot_lab/rails/railtie.rb +42 -0
  136. data/lib/robot_lab/robot.rb +560 -0
  137. data/lib/robot_lab/robot_result.rb +205 -0
  138. data/lib/robot_lab/robotic_model.rb +324 -0
  139. data/lib/robot_lab/state_proxy.rb +188 -0
  140. data/lib/robot_lab/streaming/context.rb +144 -0
  141. data/lib/robot_lab/streaming/events.rb +95 -0
  142. data/lib/robot_lab/streaming/sequence_counter.rb +48 -0
  143. data/lib/robot_lab/task.rb +117 -0
  144. data/lib/robot_lab/tool.rb +223 -0
  145. data/lib/robot_lab/tool_config.rb +112 -0
  146. data/lib/robot_lab/tool_manifest.rb +234 -0
  147. data/lib/robot_lab/user_message.rb +118 -0
  148. data/lib/robot_lab/version.rb +5 -0
  149. data/lib/robot_lab/waiter.rb +73 -0
  150. data/lib/robot_lab.rb +195 -0
  151. data/mkdocs.yml +214 -0
  152. data/sig/robot_lab.rbs +4 -0
  153. 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)