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,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