robot_lab 0.1.0 → 0.2.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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/.architecture/AGENTS.md +32 -0
  3. data/.architecture/config.yml +8 -0
  4. data/.architecture/members.yml +60 -0
  5. data/.architecture/reviews/feature-free-will.md +490 -0
  6. data/.architecture/reviews/overall-codebase.md +427 -0
  7. data/.claude/settings.local.json +57 -0
  8. data/.codex/config.toml +2 -0
  9. data/.irbrc +2 -2
  10. data/.rubocop.yml +172 -0
  11. data/CHANGELOG.md +72 -0
  12. data/CLAUDE.md +139 -0
  13. data/README.md +91 -95
  14. data/Rakefile +109 -3
  15. data/agent2agent_review.md +192 -0
  16. data/agentf_improvements.md +253 -0
  17. data/agents.md +14 -0
  18. data/docs/examples/index.md +37 -2
  19. data/docs/getting-started/configuration.md +20 -7
  20. data/docs/guides/index.md +16 -16
  21. data/docs/guides/knowledge.md +7 -1
  22. data/docs/guides/observability.md +132 -0
  23. data/docs/index.md +30 -3
  24. data/docs/superpowers/plans/2026-05-06-agentskills.md +1303 -0
  25. data/docs/superpowers/specs/2026-05-06-agentskills-design.md +247 -0
  26. data/examples/.envrc +1 -0
  27. data/examples/01_simple_robot.rb +5 -9
  28. data/examples/02_tools.rb +5 -9
  29. data/examples/03_network.rb +8 -9
  30. data/examples/04_mcp.rb +21 -29
  31. data/examples/05_streaming.rb +12 -18
  32. data/examples/06_prompt_templates.rb +11 -19
  33. data/examples/07_network_memory.rb +16 -31
  34. data/examples/08_llm_config.rb +10 -22
  35. data/examples/09_chaining.rb +16 -27
  36. data/examples/10_memory.rb +12 -28
  37. data/examples/11_network_introspection.rb +15 -29
  38. data/examples/12_message_bus.rb +5 -12
  39. data/examples/13_spawn.rb +5 -10
  40. data/examples/14_rusty_circuit/.envrc +1 -0
  41. data/examples/14_rusty_circuit/comic.rb +2 -0
  42. data/examples/14_rusty_circuit/heckler.rb +1 -1
  43. data/examples/14_rusty_circuit/open_mic.rb +1 -3
  44. data/examples/14_rusty_circuit/scout.rb +2 -0
  45. data/examples/15_memory_network_and_bus/.envrc +1 -0
  46. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +6 -3
  47. data/examples/15_memory_network_and_bus/linux_writer.rb +1 -1
  48. data/examples/15_memory_network_and_bus/output/combined_article.md +6 -6
  49. data/examples/15_memory_network_and_bus/output/final_article.md +6 -8
  50. data/examples/15_memory_network_and_bus/output/linux_draft.md +4 -2
  51. data/examples/15_memory_network_and_bus/output/mac_draft.md +3 -3
  52. data/examples/15_memory_network_and_bus/output/memory.json +6 -6
  53. data/examples/15_memory_network_and_bus/output/revision_1.md +10 -11
  54. data/examples/15_memory_network_and_bus/output/revision_2.md +6 -8
  55. data/examples/15_memory_network_and_bus/output/windows_draft.md +3 -3
  56. data/examples/16_writers_room/.envrc +1 -0
  57. data/examples/16_writers_room/writers_room.rb +2 -4
  58. data/examples/17_skills.rb +8 -17
  59. data/examples/18_rails/Gemfile +1 -0
  60. data/examples/19_token_tracking.rb +9 -15
  61. data/examples/20_circuit_breaker.rb +10 -19
  62. data/examples/21_learning_loop.rb +11 -20
  63. data/examples/22_context_compression.rb +6 -13
  64. data/examples/23_convergence.rb +6 -17
  65. data/examples/24_structured_delegation.rb +11 -15
  66. data/examples/25_history_search.rb +5 -12
  67. data/examples/26_document_store.rb +6 -13
  68. data/examples/27_incident_response/incident_response.rb +4 -5
  69. data/examples/28_mcp_discovery.rb +8 -11
  70. data/examples/29_ractor_tools.rb +4 -9
  71. data/examples/30_ractor_network.rb +10 -19
  72. data/examples/31_launch_assessment.rb +10 -23
  73. data/examples/32_newsletter_reader.rb +188 -0
  74. data/examples/33_stock_generator.rb +80 -0
  75. data/examples/33_stock_predictor.rb +306 -0
  76. data/examples/34_agentskills.rb +72 -0
  77. data/examples/README.md +1 -1
  78. data/examples/common.rb +76 -0
  79. data/examples/ruboruby.md +423 -0
  80. data/examples/temp.md +51 -0
  81. data/lib/robot_lab/agent_skill.rb +63 -0
  82. data/lib/robot_lab/agent_skill_catalog.rb +74 -0
  83. data/lib/robot_lab/ask_user.rb +2 -2
  84. data/lib/robot_lab/bus_poller.rb +12 -5
  85. data/lib/robot_lab/config.rb +1 -12
  86. data/lib/robot_lab/delegation_future.rb +1 -1
  87. data/lib/robot_lab/doom_loop_detector.rb +98 -0
  88. data/lib/robot_lab/history_compressor.rb +4 -10
  89. data/lib/robot_lab/mcp/client.rb +1 -2
  90. data/lib/robot_lab/mcp/connection_poller.rb +3 -3
  91. data/lib/robot_lab/mcp/server.rb +1 -1
  92. data/lib/robot_lab/mcp/server_discovery.rb +0 -2
  93. data/lib/robot_lab/memory.rb +32 -27
  94. data/lib/robot_lab/memory_change.rb +2 -2
  95. data/lib/robot_lab/message.rb +4 -4
  96. data/lib/robot_lab/network.rb +11 -6
  97. data/lib/robot_lab/robot/agent_skill_matching.rb +99 -0
  98. data/lib/robot_lab/robot/bus_messaging.rb +9 -27
  99. data/lib/robot_lab/robot/history_search.rb +4 -1
  100. data/lib/robot_lab/robot/mcp_management.rb +5 -11
  101. data/lib/robot_lab/robot/template_rendering.rb +60 -40
  102. data/lib/robot_lab/robot.rb +323 -206
  103. data/lib/robot_lab/robot_result.rb +6 -5
  104. data/lib/robot_lab/run_config.rb +5 -11
  105. data/lib/robot_lab/script_tool.rb +76 -0
  106. data/lib/robot_lab/state_proxy.rb +7 -5
  107. data/lib/robot_lab/tool.rb +3 -3
  108. data/lib/robot_lab/tool_config.rb +1 -1
  109. data/lib/robot_lab/tool_manifest.rb +5 -7
  110. data/lib/robot_lab/user_message.rb +2 -2
  111. data/lib/robot_lab/version.rb +1 -1
  112. data/lib/robot_lab/waiter.rb +1 -1
  113. data/lib/robot_lab.rb +41 -52
  114. data/logfile +8 -0
  115. data/mkdocs.yml +2 -3
  116. data/robot_concurrency.md +38 -0
  117. data/simple_acp_review.md +298 -0
  118. data/site/404.html +2300 -0
  119. data/site/api/core/index.html +2706 -0
  120. data/site/api/core/memory/index.html +3793 -0
  121. data/site/api/core/network/index.html +3500 -0
  122. data/site/api/core/robot/index.html +4566 -0
  123. data/site/api/core/state/index.html +3390 -0
  124. data/site/api/core/tool/index.html +3843 -0
  125. data/site/api/index.html +2635 -0
  126. data/site/api/mcp/client/index.html +3435 -0
  127. data/site/api/mcp/index.html +2783 -0
  128. data/site/api/mcp/server/index.html +3252 -0
  129. data/site/api/mcp/transports/index.html +3352 -0
  130. data/site/api/messages/index.html +2641 -0
  131. data/site/api/messages/text-message/index.html +3087 -0
  132. data/site/api/messages/tool-call-message/index.html +3159 -0
  133. data/site/api/messages/tool-result-message/index.html +3252 -0
  134. data/site/api/messages/user-message/index.html +3212 -0
  135. data/site/api/streaming/context/index.html +3282 -0
  136. data/site/api/streaming/events/index.html +3347 -0
  137. data/site/api/streaming/index.html +2738 -0
  138. data/site/architecture/core-concepts/index.html +3757 -0
  139. data/site/architecture/index.html +2797 -0
  140. data/site/architecture/message-flow/index.html +3238 -0
  141. data/site/architecture/network-orchestration/index.html +3433 -0
  142. data/site/architecture/robot-execution/index.html +3140 -0
  143. data/site/architecture/state-management/index.html +3498 -0
  144. data/site/assets/css/custom.css +56 -0
  145. data/site/assets/images/favicon.png +0 -0
  146. data/site/assets/images/robot_lab.jpg +0 -0
  147. data/site/assets/javascripts/bundle.79ae519e.min.js +16 -0
  148. data/site/assets/javascripts/bundle.79ae519e.min.js.map +7 -0
  149. data/site/assets/javascripts/lunr/min/lunr.ar.min.js +1 -0
  150. data/site/assets/javascripts/lunr/min/lunr.da.min.js +18 -0
  151. data/site/assets/javascripts/lunr/min/lunr.de.min.js +18 -0
  152. data/site/assets/javascripts/lunr/min/lunr.du.min.js +18 -0
  153. data/site/assets/javascripts/lunr/min/lunr.el.min.js +1 -0
  154. data/site/assets/javascripts/lunr/min/lunr.es.min.js +18 -0
  155. data/site/assets/javascripts/lunr/min/lunr.fi.min.js +18 -0
  156. data/site/assets/javascripts/lunr/min/lunr.fr.min.js +18 -0
  157. data/site/assets/javascripts/lunr/min/lunr.he.min.js +1 -0
  158. data/site/assets/javascripts/lunr/min/lunr.hi.min.js +1 -0
  159. data/site/assets/javascripts/lunr/min/lunr.hu.min.js +18 -0
  160. data/site/assets/javascripts/lunr/min/lunr.hy.min.js +1 -0
  161. data/site/assets/javascripts/lunr/min/lunr.it.min.js +18 -0
  162. data/site/assets/javascripts/lunr/min/lunr.ja.min.js +1 -0
  163. data/site/assets/javascripts/lunr/min/lunr.jp.min.js +1 -0
  164. data/site/assets/javascripts/lunr/min/lunr.kn.min.js +1 -0
  165. data/site/assets/javascripts/lunr/min/lunr.ko.min.js +1 -0
  166. data/site/assets/javascripts/lunr/min/lunr.multi.min.js +1 -0
  167. data/site/assets/javascripts/lunr/min/lunr.nl.min.js +18 -0
  168. data/site/assets/javascripts/lunr/min/lunr.no.min.js +18 -0
  169. data/site/assets/javascripts/lunr/min/lunr.pt.min.js +18 -0
  170. data/site/assets/javascripts/lunr/min/lunr.ro.min.js +18 -0
  171. data/site/assets/javascripts/lunr/min/lunr.ru.min.js +18 -0
  172. data/site/assets/javascripts/lunr/min/lunr.sa.min.js +1 -0
  173. data/site/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +1 -0
  174. data/site/assets/javascripts/lunr/min/lunr.sv.min.js +18 -0
  175. data/site/assets/javascripts/lunr/min/lunr.ta.min.js +1 -0
  176. data/site/assets/javascripts/lunr/min/lunr.te.min.js +1 -0
  177. data/site/assets/javascripts/lunr/min/lunr.th.min.js +1 -0
  178. data/site/assets/javascripts/lunr/min/lunr.tr.min.js +18 -0
  179. data/site/assets/javascripts/lunr/min/lunr.vi.min.js +1 -0
  180. data/site/assets/javascripts/lunr/min/lunr.zh.min.js +1 -0
  181. data/site/assets/javascripts/lunr/tinyseg.js +206 -0
  182. data/site/assets/javascripts/lunr/wordcut.js +6708 -0
  183. data/site/assets/javascripts/workers/search.2c215733.min.js +42 -0
  184. data/site/assets/javascripts/workers/search.2c215733.min.js.map +7 -0
  185. data/site/assets/stylesheets/main.484c7ddc.min.css +1 -0
  186. data/site/assets/stylesheets/main.484c7ddc.min.css.map +1 -0
  187. data/site/assets/stylesheets/palette.ab4e12ef.min.css +1 -0
  188. data/site/assets/stylesheets/palette.ab4e12ef.min.css.map +1 -0
  189. data/site/concepts/index.html +3455 -0
  190. data/site/examples/basic-chat/index.html +2880 -0
  191. data/site/examples/index.html +2907 -0
  192. data/site/examples/mcp-server/index.html +3018 -0
  193. data/site/examples/multi-robot-network/index.html +3131 -0
  194. data/site/examples/rails-application/index.html +3329 -0
  195. data/site/examples/tool-usage/index.html +3085 -0
  196. data/site/getting-started/configuration/index.html +3745 -0
  197. data/site/getting-started/index.html +2572 -0
  198. data/site/getting-started/installation/index.html +2981 -0
  199. data/site/getting-started/quick-start/index.html +2942 -0
  200. data/site/guides/building-robots/index.html +4290 -0
  201. data/site/guides/creating-networks/index.html +3858 -0
  202. data/site/guides/index.html +2586 -0
  203. data/site/guides/mcp-integration/index.html +3581 -0
  204. data/site/guides/memory/index.html +3586 -0
  205. data/site/guides/rails-integration/index.html +4019 -0
  206. data/site/guides/streaming/index.html +3157 -0
  207. data/site/guides/using-tools/index.html +3802 -0
  208. data/site/index.html +2671 -0
  209. data/site/search/search_index.json +1 -0
  210. data/site/sitemap.xml +183 -0
  211. data/site/sitemap.xml.gz +0 -0
  212. data/site/tags.json +1 -0
  213. data/temp.md +6 -0
  214. data/tool_manifest_plan.md +155 -0
  215. metadata +154 -92
  216. data/docs/examples/rails-application.md +0 -419
  217. data/docs/guides/ractor-parallelism.md +0 -364
  218. data/docs/guides/rails-integration.md +0 -681
  219. data/docs/superpowers/plans/2026-04-14-ractor-integration.md +0 -1538
  220. data/docs/superpowers/specs/2026-04-14-ractor-integration-design.md +0 -258
  221. data/lib/generators/robot_lab/install_generator.rb +0 -90
  222. data/lib/generators/robot_lab/job_generator.rb +0 -40
  223. data/lib/generators/robot_lab/robot_generator.rb +0 -55
  224. data/lib/generators/robot_lab/templates/initializer.rb.tt +0 -42
  225. data/lib/generators/robot_lab/templates/job.rb.tt +0 -21
  226. data/lib/generators/robot_lab/templates/migration.rb.tt +0 -32
  227. data/lib/generators/robot_lab/templates/result_model.rb.tt +0 -52
  228. data/lib/generators/robot_lab/templates/robot.rb.tt +0 -31
  229. data/lib/generators/robot_lab/templates/robot_job.rb.tt +0 -18
  230. data/lib/generators/robot_lab/templates/robot_test.rb.tt +0 -34
  231. data/lib/generators/robot_lab/templates/routing_robot.rb.tt +0 -59
  232. data/lib/generators/robot_lab/templates/thread_model.rb.tt +0 -40
  233. data/lib/robot_lab/document_store.rb +0 -155
  234. data/lib/robot_lab/ractor_boundary.rb +0 -42
  235. data/lib/robot_lab/ractor_job.rb +0 -37
  236. data/lib/robot_lab/ractor_memory_proxy.rb +0 -85
  237. data/lib/robot_lab/ractor_network_scheduler.rb +0 -154
  238. data/lib/robot_lab/ractor_worker_pool.rb +0 -117
  239. data/lib/robot_lab/rails_integration/engine.rb +0 -29
  240. data/lib/robot_lab/rails_integration/job.rb +0 -158
  241. data/lib/robot_lab/rails_integration/railtie.rb +0 -51
  242. data/lib/robot_lab/rails_integration/turbo_stream_callbacks.rb +0 -72
@@ -17,10 +17,7 @@
17
17
  # ├── product_support.md
18
18
  # └── escalation.md
19
19
 
20
- # Configure template path before loading (MywayConfig reads env vars on init)
21
- ENV['ROBOT_LAB_TEMPLATE_PATH'] ||= File.join(__dir__, "prompts")
22
-
23
- require_relative "../lib/robot_lab"
20
+ require_relative "common"
24
21
 
25
22
  # =============================================================================
26
23
  # Sample Data
@@ -179,10 +176,8 @@ end
179
176
  # Main Demo
180
177
  # =============================================================================
181
178
 
182
- puts "=" * 70
183
- puts "RobotLab + Prompt Templates Demo"
179
+ banner "RobotLab + Prompt Templates Demo"
184
180
  puts "E-Commerce Support Network with Dynamic Context"
185
- puts "=" * 70
186
181
  puts
187
182
 
188
183
  # Template path is set via ROBOT_LAB_TEMPLATE_PATH env var (see top of file)
@@ -201,11 +196,12 @@ triage_robot = TriageRobot.new(
201
196
  company_name: COMPANY_NAME,
202
197
  categories: CATEGORIES
203
198
  },
204
- model: "claude-3-haiku-20240307"
199
+ model: LLM[:default].model
205
200
  )
206
201
 
207
202
  # Order Support Robot
208
203
  order_robot = RobotLab.build(
204
+ model: LLM[:default].model,
209
205
  name: "order",
210
206
  description: "Handles order-related inquiries with full order history",
211
207
  template: :order_support,
@@ -214,12 +210,12 @@ order_robot = RobotLab.build(
214
210
  company_name: COMPANY_NAME,
215
211
  policies: POLICIES,
216
212
  capabilities: ORDER_CAPABILITIES
217
- },
218
- model: "claude-3-haiku-20240307"
213
+ }
219
214
  )
220
215
 
221
216
  # Product Support Robot
222
217
  product_robot = RobotLab.build(
218
+ model: LLM[:default].model,
223
219
  name: "product",
224
220
  description: "Answers product questions with catalog knowledge",
225
221
  template: :product_support,
@@ -229,12 +225,12 @@ product_robot = RobotLab.build(
229
225
  products: PRODUCTS,
230
226
  promotions: PROMOTIONS,
231
227
  product_categories: PRODUCT_CATEGORIES
232
- },
233
- model: "claude-3-haiku-20240307"
228
+ }
234
229
  )
235
230
 
236
231
  # Escalation Robot
237
232
  escalation_robot = RobotLab.build(
233
+ model: LLM[:default].model,
238
234
  name: "escalation",
239
235
  description: "Handles complex cases requiring special authority",
240
236
  template: :escalation,
@@ -242,8 +238,7 @@ escalation_robot = RobotLab.build(
242
238
  context: {
243
239
  company_name: COMPANY_NAME,
244
240
  authorities: ESCALATION_AUTHORITIES
245
- },
246
- model: "claude-3-haiku-20240307"
241
+ }
247
242
  )
248
243
 
249
244
  # -----------------------------------------------------------------------------
@@ -277,10 +272,7 @@ demo_queries = [
277
272
  ]
278
273
 
279
274
  demo_queries.each_with_index do |query, index|
280
- puts
281
- puts "-" * 70
282
- puts "Scenario #{index + 1}: #{query[:label]}"
283
- puts "-" * 70
275
+ section "Scenario #{index + 1}: #{query[:label]}"
284
276
  puts "Customer: #{query[:message]}"
285
277
  puts
286
278
 
@@ -311,7 +303,7 @@ demo_queries.each_with_index do |query, index|
311
303
  end
312
304
 
313
305
  puts
314
- puts "=" * 70
306
+ hr
315
307
  end
316
308
 
317
309
  puts
@@ -41,16 +41,10 @@
41
41
  # Usage:
42
42
  # ANTHROPIC_API_KEY=your_key ruby examples/07_network_memory.rb
43
43
 
44
- # Configure template path before loading (MywayConfig reads env vars on init)
45
- ENV['ROBOT_LAB_TEMPLATE_PATH'] ||= File.join(__dir__, "prompts")
46
-
47
- require_relative "../lib/robot_lab"
44
+ require_relative "common"
48
45
  require "json"
49
46
 
50
- puts "=" * 60
51
- puts "Example 7: Network Memory with Concurrent Robots"
52
- puts "=" * 60
53
- puts
47
+ banner "Network Memory with Concurrent Robots"
54
48
 
55
49
  # -----------------------------------------------------------------------------
56
50
  # Custom Robot Classes that Write to Shared Memory
@@ -153,27 +147,27 @@ sentiment_robot = AnalysisRobot.new(
153
147
  name: "sentiment_analyzer",
154
148
  template: :sentiment_analyzer,
155
149
  memory_key: :sentiment,
156
- model: "claude-3-haiku-20240307"
150
+ model: LLM[:default].model
157
151
  )
158
152
 
159
153
  entity_robot = AnalysisRobot.new(
160
154
  name: "entity_extractor",
161
155
  template: :entity_extractor,
162
156
  memory_key: :entities,
163
- model: "claude-3-haiku-20240307"
157
+ model: LLM[:default].model
164
158
  )
165
159
 
166
160
  keyword_robot = AnalysisRobot.new(
167
161
  name: "keyword_extractor",
168
162
  template: :keyword_extractor,
169
163
  memory_key: :keywords,
170
- model: "claude-3-haiku-20240307"
164
+ model: LLM[:default].model
171
165
  )
172
166
 
173
167
  synthesizer = SynthesizerRobot.new(
174
168
  name: "synthesizer",
175
169
  template: :synthesizer,
176
- model: "claude-3-haiku-20240307"
170
+ model: LLM[:default].model
177
171
  )
178
172
 
179
173
  # -----------------------------------------------------------------------------
@@ -231,10 +225,10 @@ TEXT
231
225
  puts "Network structure:"
232
226
  puts network.visualize
233
227
  puts
234
- puts "-" * 60
228
+ hr
235
229
  puts "Input text:"
236
230
  puts sample_text.strip
237
- puts "-" * 60
231
+ hr
238
232
  puts
239
233
 
240
234
  # Send a broadcast before starting
@@ -248,9 +242,9 @@ result = network.run(message: sample_text)
248
242
 
249
243
  elapsed = Time.now - start_time
250
244
  puts
251
- puts "-" * 60
245
+ hr
252
246
  puts "Analysis complete in #{elapsed.round(2)} seconds"
253
- puts "-" * 60
247
+ hr
254
248
 
255
249
  # Send completion broadcast
256
250
  network.broadcast(event: "analysis_complete", details: "All robots finished")
@@ -259,21 +253,15 @@ network.broadcast(event: "analysis_complete", details: "All robots finished")
259
253
  # Display Results
260
254
  # -----------------------------------------------------------------------------
261
255
 
262
- puts
263
- puts "=" * 60
264
- puts "FINAL SYNTHESIS"
265
- puts "=" * 60
266
- puts
256
+
257
+ section "Final Synthesis"
267
258
 
268
259
  if result.value.is_a?(RobotLab::RobotResult)
269
260
  puts result.value.reply
270
261
  end
271
262
 
272
- puts
273
- puts "=" * 60
274
- puts "MEMORY STATE"
275
- puts "=" * 60
276
- puts
263
+
264
+ section "Memory State"
277
265
 
278
266
  # Show what's in shared memory
279
267
  memory = network.memory
@@ -287,11 +275,8 @@ puts "Keywords: #{memory.get(:keywords)&.to_json}"
287
275
  # Demonstrate Blocking Wait (without pipeline dependencies)
288
276
  # -----------------------------------------------------------------------------
289
277
 
290
- puts
291
- puts "=" * 60
292
- puts "DEMONSTRATING BLOCKING WAIT"
293
- puts "=" * 60
294
- puts
278
+
279
+ section "Demonstrating Blocking Wait"
295
280
 
296
281
  # Create a fresh memory for this demo
297
282
  demo_memory = RobotLab::Memory.new(network_name: "wait_demo")
@@ -29,19 +29,13 @@
29
29
  # ROBOT_LAB_ENV=test ANTHROPIC_API_KEY=your_key ruby examples/08_llm_config.rb
30
30
  # ROBOT_LAB_ENV=production ANTHROPIC_API_KEY=your_key ruby examples/08_llm_config.rb
31
31
 
32
- # Configure template path before loading (MywayConfig reads env vars on init)
33
- ENV['ROBOT_LAB_TEMPLATE_PATH'] ||= File.join(__dir__, "prompts")
34
-
35
- require_relative "../lib/robot_lab"
32
+ require_relative "common"
36
33
 
37
34
  # =============================================================================
38
35
  # Demonstration
39
36
  # =============================================================================
40
37
 
41
- puts "=" * 70
42
- puts "Example 8: LLM Configuration via MywayConfig"
43
- puts "=" * 70
44
- puts
38
+ banner "LLM Configuration via MywayConfig"
45
39
 
46
40
  # --- Gather environment from the user via AskUser ---
47
41
  ask = RobotLab::AskUser.new
@@ -73,8 +67,7 @@ api_key = config.ruby_llm.anthropic_api_key
73
67
  puts " anthropic_api_key: #{api_key ? '[SET via config]' : (ENV['ANTHROPIC_API_KEY'] ? '[SET via env]' : '(not set)')}"
74
68
  puts
75
69
 
76
- puts "-" * 70
77
- puts "Configuration hierarchy (highest priority first):"
70
+ section "Configuration Hierarchy (highest priority first)"
78
71
  puts
79
72
  puts " Per-Robot (override global settings for a specific robot):"
80
73
  puts " 11. Run-time context: kwargs to robot.run re-render template"
@@ -92,17 +85,11 @@ puts " 4. Environment variables: ROBOT_LAB_RUBY_LLM__MODEL, etc."
92
85
  puts " 3. Project config: ./config/robot_lab.yml"
93
86
  puts " 2. User config: ~/.config/robot_lab/config.yml"
94
87
  puts " 1. Bundled defaults: lib/robot_lab/config/defaults.yml + env overrides"
95
- puts "-" * 70
96
- puts
97
88
 
98
- # --- RunConfig demonstration ---
99
- puts "-" * 70
100
- puts "RunConfig: Shared Operational Defaults"
101
- puts "-" * 70
102
- puts
89
+ section "RunConfig: Shared Operational Defaults"
103
90
 
104
- shared = RobotLab::RunConfig.new(model: "claude-sonnet-4", temperature: 0.5)
105
- puts " shared = RunConfig.new(model: \"claude-sonnet-4\", temperature: 0.5)"
91
+ shared = RobotLab::RunConfig.new(model: LLM[:default].model, temperature: 0.5)
92
+ puts " shared = RunConfig.new(model: \"gpt-5.4\", temperature: 0.5)"
106
93
  puts " shared.to_h => #{shared.to_h.inspect}"
107
94
  puts
108
95
 
@@ -116,13 +103,14 @@ puts
116
103
 
117
104
  # Create a robot using the configuration
118
105
  robot = RobotLab.build(
106
+ model: LLM[:default].model,
119
107
  name: "config_demo",
120
108
  template: :llm_config_demo,
121
109
  local_tools: [RobotLab::AskUser],
122
110
  context: {
123
111
  environment: env,
124
- model: config.ruby_llm.model,
125
- provider: config.ruby_llm.provider.to_s
112
+ model: LLM[:default].model,
113
+ provider: LLM[:default].provider
126
114
  }
127
115
  )
128
116
 
@@ -153,7 +141,7 @@ puts <<~FOOTER
153
141
  Per-Robot: RunConfig, template front matter, constructor params, with_*
154
142
 
155
143
  RunConfig lets you express shared defaults that flow through the hierarchy:
156
- shared = RobotLab::RunConfig.new(model: "claude-sonnet-4", temperature: 0.5)
144
+ shared = RobotLab::RunConfig.new(model: "gpt-5.4", temperature: 0.5)
157
145
  network = RobotLab.create_network(name: "team", config: shared) { ... }
158
146
  robot = RobotLab.build(name: "bot", config: shared, temperature: 0.9)
159
147
 
@@ -17,10 +17,7 @@
17
17
  # Usage:
18
18
  # bundle exec ruby examples/09_chaining.rb
19
19
 
20
- # Configure template path before loading
21
- ENV['ROBOT_LAB_TEMPLATE_PATH'] ||= File.join(__dir__, "prompts")
22
-
23
- require_relative "../lib/robot_lab"
20
+ require_relative "common"
24
21
  require "amazing_print"
25
22
  require "hashdiff"
26
23
  require "stringio"
@@ -55,21 +52,18 @@ def show_config(robot, previous_config = nil)
55
52
  current
56
53
  end
57
54
 
58
- puts "=" * 70
59
- puts "Example 9: Robot Chaining & Reconfiguration"
60
- puts "=" * 70
61
- puts
55
+ banner "Robot Chaining & Reconfiguration"
62
56
 
63
57
  # =============================================================================
64
58
  # Section 1: Template front matter config
65
59
  # =============================================================================
66
60
 
67
- puts "--- Section 1: Template Front Matter Config ---"
68
- puts
61
+ section "Section 1: Template Front Matter Config"
69
62
 
70
63
  # The 'configurable' template sets temperature: 0.3 and max_tokens: 200
71
64
  # via YAML front matter. These are applied automatically.
72
65
  robot = RobotLab.build(
66
+ model: LLM[:default].model,
73
67
  name: "chameleon",
74
68
  template: :configurable,
75
69
  context: { task_type: "analysis" }
@@ -83,8 +77,7 @@ puts
83
77
  # Section 2: with_* method chaining
84
78
  # =============================================================================
85
79
 
86
- puts "--- Section 2: with_* Method Chaining ---"
87
- puts
80
+ section "Section 2: with_* Method Chaining"
88
81
 
89
82
  # with_* methods return self, enabling fluent chaining.
90
83
  # These override whatever the template set.
@@ -98,8 +91,7 @@ puts
98
91
  # Section 3: update() for reconfiguration
99
92
  # =============================================================================
100
93
 
101
- puts "--- Section 3: update() for Reconfiguration ---"
102
- puts
94
+ section "Section 3: update() for Reconfiguration"
103
95
 
104
96
  # update() can swap the template, model, temperature, and other settings.
105
97
  robot.update(template: :assistant, temperature: 0.5)
@@ -119,12 +111,12 @@ puts
119
111
  # Section 4: Constructor params override front matter
120
112
  # =============================================================================
121
113
 
122
- puts "--- Section 4: Constructor Params Override Front Matter ---"
123
- puts
114
+ section "Section 4: Constructor Params Override Front Matter"
124
115
 
125
116
  # The configurable template sets temperature: 0.3 in front matter.
126
117
  # Passing temperature: 0.9 to the constructor overrides it.
127
118
  robot2 = RobotLab.build(
119
+ model: LLM[:default].model,
128
120
  name: "override_demo",
129
121
  template: :configurable,
130
122
  context: { task_type: "creative" },
@@ -139,18 +131,18 @@ puts
139
131
  # Section 5: RunConfig as alternative to individual kwargs
140
132
  # =============================================================================
141
133
 
142
- puts "--- Section 5: RunConfig as Alternative to Individual kwargs ---"
143
- puts
134
+ section "Section 5: RunConfig as Alternative to Individual kwargs"
144
135
 
145
136
  # Instead of passing model:, temperature:, etc. individually,
146
137
  # use a RunConfig to express shared defaults.
147
- shared = RobotLab::RunConfig.new(model: "claude-sonnet-4", temperature: 0.5)
138
+ shared = RobotLab::RunConfig.new(model: LLM[:default].model, temperature: 0.5)
148
139
 
149
140
  puts "RunConfig: #{shared.to_h.inspect}"
150
141
  puts
151
142
 
152
143
  # Robot inherits from RunConfig; constructor kwargs still override
153
144
  robot3 = RobotLab.build(
145
+ model: LLM[:default].model,
154
146
  name: "runconfig_demo",
155
147
  template: :configurable,
156
148
  context: { task_type: "analysis" },
@@ -178,8 +170,7 @@ puts
178
170
  # Section 6: Bare robot with chaining
179
171
  # =============================================================================
180
172
 
181
- puts "--- Section 6: Bare Robot with Chaining ---"
182
- puts
173
+ section "Section 6: Bare Robot with Chaining"
183
174
 
184
175
  # A bare robot has no template. Configure entirely via chaining.
185
176
  bare = RobotLab.build(name: "bare")
@@ -200,8 +191,7 @@ puts
200
191
  # Section 7: with_template() on an existing robot
201
192
  # =============================================================================
202
193
 
203
- puts "--- Section 7: with_template() on Existing Robot ---"
204
- puts
194
+ section "Section 7: with_template() on Existing Robot"
205
195
 
206
196
  # You can apply a template to a robot after creation.
207
197
  bare.with_template(:helper)
@@ -214,8 +204,7 @@ puts
214
204
  # Section 8: AskUser tool for gathering template parameters
215
205
  # =============================================================================
216
206
 
217
- puts "--- Section 8: AskUser for Template Parameters ---"
218
- puts
207
+ section "Section 8: AskUser for Template Parameters"
219
208
  puts "The :configurable template declares `task_type: general` in its front"
220
209
  puts "matter. That default is offered to the user — they can accept it by"
221
210
  puts "pressing Enter or type something else. Parameters with null values"
@@ -225,6 +214,7 @@ puts
225
214
  # Build a robot with AskUser — the template's task_type default ("general")
226
215
  # is offered to the user, who can accept or override it.
227
216
  interactive = RobotLab.build(
217
+ model: LLM[:default].model,
228
218
  name: "interactive_demo",
229
219
  template: :configurable,
230
220
  local_tools: [RobotLab::AskUser]
@@ -257,6 +247,5 @@ puts
257
247
  puts "If the user had pressed Enter, the default \"general\" would be kept."
258
248
  puts
259
249
 
260
- puts "=" * 70
250
+ hr
261
251
  puts "All sections completed without any LLM calls."
262
- puts "=" * 70
@@ -18,25 +18,18 @@
18
18
  # Usage:
19
19
  # bundle exec ruby examples/10_memory.rb
20
20
 
21
- # Configure template path before loading
22
- ENV['ROBOT_LAB_TEMPLATE_PATH'] ||= File.join(__dir__, "prompts")
23
-
24
- require_relative "../lib/robot_lab"
21
+ require_relative "common"
25
22
  require "json"
26
23
  require "amazing_print"
27
24
  require "hashdiff"
28
25
 
29
- puts "=" * 70
30
- puts "Example 10: Advanced Memory Operations"
31
- puts "=" * 70
32
- puts
26
+ banner "Advanced Memory Operations"
33
27
 
34
28
  # =============================================================================
35
29
  # Section 1: StateProxy for method-style access
36
30
  # =============================================================================
37
31
 
38
- puts "--- Section 1: StateProxy for Method-Style Access ---"
39
- puts
32
+ section "Section 1: StateProxy for Method-Style Access"
40
33
 
41
34
  memory = RobotLab.create_memory(
42
35
  data: { category: nil, priority: "low" },
@@ -64,8 +57,7 @@ puts
64
57
  # Section 2: Subscriptions and MemoryChange
65
58
  # =============================================================================
66
59
 
67
- puts "--- Section 2: Subscriptions and MemoryChange ---"
68
- puts
60
+ section "Section 2: Subscriptions and MemoryChange"
69
61
 
70
62
  changes = []
71
63
 
@@ -107,8 +99,7 @@ puts
107
99
  # Section 3: Pattern subscriptions
108
100
  # =============================================================================
109
101
 
110
- puts "--- Section 3: Pattern Subscriptions ---"
111
- puts
102
+ section "Section 3: Pattern Subscriptions"
112
103
 
113
104
  pattern_changes = []
114
105
 
@@ -135,8 +126,7 @@ puts
135
126
  # Section 4: Unsubscribe
136
127
  # =============================================================================
137
128
 
138
- puts "--- Section 4: Unsubscribe ---"
139
- puts
129
+ section "Section 4: Unsubscribe"
140
130
 
141
131
  count_before = changes.size
142
132
  memory.unsubscribe(sub_id)
@@ -152,8 +142,7 @@ puts
152
142
  # Section 5: Key management
153
143
  # =============================================================================
154
144
 
155
- puts "--- Section 5: Key Management ---"
156
- puts
145
+ section "Section 5: Key Management"
157
146
 
158
147
  puts "memory.keys (non-reserved):"
159
148
  ap memory.keys
@@ -171,8 +160,7 @@ puts
171
160
  # Section 6: Serialization round-trip
172
161
  # =============================================================================
173
162
 
174
- puts "--- Section 6: Serialization Round-Trip ---"
175
- puts
163
+ section "Section 6: Serialization Round-Trip"
176
164
 
177
165
  hash = memory.to_h
178
166
  puts "memory.to_h:"
@@ -214,8 +202,7 @@ puts
214
202
  # Section 7: Clone for isolation
215
203
  # =============================================================================
216
204
 
217
- puts "--- Section 7: Clone for Isolation ---"
218
- puts
205
+ section "Section 7: Clone for Isolation"
219
206
 
220
207
  cloned = memory.clone
221
208
  cloned.set(:isolated_key, "only in clone")
@@ -244,8 +231,7 @@ puts
244
231
  # Section 8: Delete and reserved key protection
245
232
  # =============================================================================
246
233
 
247
- puts "--- Section 8: Delete and Reserved Key Protection ---"
248
- puts
234
+ section "Section 8: Delete and Reserved Key Protection"
249
235
 
250
236
  before_delete = memory.to_h
251
237
  memory.delete(:status)
@@ -272,8 +258,7 @@ puts
272
258
  # Section 9: Clear vs Reset
273
259
  # =============================================================================
274
260
 
275
- puts "--- Section 9: Clear vs Reset ---"
276
- puts
261
+ section "Section 9: Clear vs Reset"
277
262
 
278
263
  memory.set(:temp1, "value1")
279
264
  memory.set(:temp2, "value2")
@@ -326,6 +311,5 @@ Hashdiff.diff(before_reset, after_reset).each do |change|
326
311
  end
327
312
  puts
328
313
 
329
- puts "=" * 70
314
+ hr
330
315
  puts "All sections completed without any LLM calls."
331
- puts "=" * 70
@@ -19,10 +19,7 @@
19
19
  # Usage:
20
20
  # bundle exec ruby examples/11_network_introspection.rb
21
21
 
22
- # Configure template path before loading
23
- ENV['ROBOT_LAB_TEMPLATE_PATH'] ||= File.join(__dir__, "prompts")
24
-
25
- require_relative "../lib/robot_lab"
22
+ require_relative "common"
26
23
  require "amazing_print"
27
24
  require "tempfile"
28
25
 
@@ -50,21 +47,18 @@ def render_dot_image(dot_source)
50
47
  end
51
48
  end
52
49
 
53
- puts "=" * 70
54
- puts "Example 11: Network Visualization & Introspection"
55
- puts "=" * 70
56
- puts
50
+ banner "Network Visualization & Introspection"
57
51
 
58
52
  # Shared RunConfig for all robots in this network
59
- shared_config = RobotLab::RunConfig.new(model: "claude-sonnet-4", temperature: 0.5)
53
+ shared_config = RobotLab::RunConfig.new(model: LLM[:default].model, temperature: 0.5)
60
54
 
61
55
  # Per-task RunConfig override for the writer (higher creativity)
62
56
  creative_config = RobotLab::RunConfig.new(temperature: 0.9)
63
57
 
64
58
  # Build robots (no LLM calls, just instances)
65
- classifier = RobotLab.build(name: "classifier", system_prompt: "Classify input")
66
- analyst = RobotLab.build(name: "analyst", system_prompt: "Analyze data")
67
- writer = RobotLab.build(name: "writer", system_prompt: "Write summary")
59
+ classifier = RobotLab.build(model: LLM[:default].model, name: "classifier", system_prompt: "Classify input")
60
+ analyst = RobotLab.build(model: LLM[:default].model, name: "analyst", system_prompt: "Analyze data")
61
+ writer = RobotLab.build(model: LLM[:default].model, name: "writer", system_prompt: "Write summary")
68
62
 
69
63
  # Build network with RunConfig, dependencies, and per-task config
70
64
  network = RobotLab.create_network(name: "demo_pipeline", config: shared_config) do
@@ -77,8 +71,7 @@ end
77
71
  # Section 1: Visualization outputs
78
72
  # =============================================================================
79
73
 
80
- puts "--- Section 1: Visualization ---"
81
- puts
74
+ section "Section 1: Visualization"
82
75
 
83
76
  mermaid = network.to_mermaid
84
77
  if mermaid
@@ -123,8 +116,7 @@ end
123
116
  # Section 2: Robot access
124
117
  # =============================================================================
125
118
 
126
- puts "--- Section 2: Robot Access ---"
127
- puts
119
+ section "Section 2: Robot Access"
128
120
 
129
121
  # Access by task name with robot() method
130
122
  # Note: robots are keyed by task name (the first arg to task()), not robot.name
@@ -146,10 +138,9 @@ puts
146
138
  # Section 3: Dynamic robot addition
147
139
  # =============================================================================
148
140
 
149
- puts "--- Section 3: Dynamic Robot Addition ---"
150
- puts
141
+ section "Section 3: Dynamic Robot Addition"
151
142
 
152
- reviewer = RobotLab.build(name: "reviewer", system_prompt: "Review output")
143
+ reviewer = RobotLab.build(model: LLM[:default].model, name: "reviewer", system_prompt: "Review output")
153
144
  network.add_robot(reviewer)
154
145
 
155
146
  puts "After add_robot(reviewer):"
@@ -168,8 +159,7 @@ puts
168
159
  # Section 4: Network introspection
169
160
  # =============================================================================
170
161
 
171
- puts "--- Section 4: Network Introspection ---"
172
- puts
162
+ section "Section 4: Network Introspection"
173
163
 
174
164
  puts "network.to_h:"
175
165
  ap network.to_h
@@ -188,8 +178,7 @@ puts
188
178
  # Section 5: RunConfig Introspection
189
179
  # =============================================================================
190
180
 
191
- puts "--- Section 5: RunConfig Introspection ---"
192
- puts
181
+ section "Section 5: RunConfig Introspection"
193
182
 
194
183
  puts "Network RunConfig (shared defaults):"
195
184
  ap network.config.to_h
@@ -205,8 +194,7 @@ puts
205
194
  # Section 6: Broadcast
206
195
  # =============================================================================
207
196
 
208
- puts "--- Section 6: Broadcast ---"
209
- puts
197
+ section "Section 6: Broadcast"
210
198
 
211
199
  broadcast_messages = []
212
200
 
@@ -233,8 +221,7 @@ puts
233
221
  # Section 7: Shared memory access
234
222
  # =============================================================================
235
223
 
236
- puts "--- Section 7: Shared Network Memory ---"
237
- puts
224
+ section "Section 7: Shared Network Memory"
238
225
 
239
226
  puts "network.memory is a #{network.memory.class}"
240
227
  puts "network.memory.network_name = #{network.memory.network_name.inspect}"
@@ -248,6 +235,5 @@ puts "network.memory.to_h:"
248
235
  ap network.memory.to_h
249
236
  puts
250
237
 
251
- puts "=" * 70
238
+ hr
252
239
  puts "All sections completed without any LLM calls."
253
- puts "=" * 70