robot_lab 0.3.0 → 0.3.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 (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +1 -1
  4. data/lib/robot_lab/mcp/transports/streamable_http.rb +1 -1
  5. data/lib/robot_lab/version.rb +1 -1
  6. metadata +3 -253
  7. data/.architecture/AGENTS.md +0 -32
  8. data/.architecture/config.yml +0 -8
  9. data/.architecture/members.yml +0 -60
  10. data/.architecture/reviews/feature-free-will.md +0 -490
  11. data/.architecture/reviews/overall-codebase.md +0 -427
  12. data/.claude/settings.local.json +0 -57
  13. data/.codex/config.toml +0 -2
  14. data/.envrc +0 -6
  15. data/.github/workflows/deploy-github-pages.yml +0 -52
  16. data/.irbrc +0 -6
  17. data/.loki +0 -65
  18. data/.quality/reek_baseline.txt +0 -43
  19. data/.rubocop.yml +0 -10
  20. data/Archspec.rb +0 -44
  21. data/CLAUDE.md +0 -141
  22. data/COMMITS.md +0 -196
  23. data/Rakefile +0 -193
  24. data/_typos.toml +0 -21
  25. data/agent2agent_review.md +0 -192
  26. data/agentf_improvements.md +0 -253
  27. data/agents.md +0 -14
  28. data/docs/api/core/index.md +0 -147
  29. data/docs/api/core/memory.md +0 -578
  30. data/docs/api/core/network.md +0 -553
  31. data/docs/api/core/result.md +0 -211
  32. data/docs/api/core/robot.md +0 -1667
  33. data/docs/api/core/state.md +0 -145
  34. data/docs/api/core/tool.md +0 -520
  35. data/docs/api/errors.md +0 -323
  36. data/docs/api/hooks.md +0 -469
  37. data/docs/api/index.md +0 -137
  38. data/docs/api/mcp/client.md +0 -387
  39. data/docs/api/mcp/index.md +0 -267
  40. data/docs/api/mcp/server.md +0 -252
  41. data/docs/api/mcp/transports.md +0 -339
  42. data/docs/api/messages/index.md +0 -126
  43. data/docs/api/messages/text-message.md +0 -170
  44. data/docs/api/messages/tool-call-message.md +0 -206
  45. data/docs/api/messages/tool-result-message.md +0 -242
  46. data/docs/api/messages/user-message.md +0 -232
  47. data/docs/api/skills.md +0 -423
  48. data/docs/api/streaming/context.md +0 -280
  49. data/docs/api/streaming/events.md +0 -185
  50. data/docs/api/streaming/index.md +0 -156
  51. data/docs/api/support.md +0 -846
  52. data/docs/architecture/core-concepts.md +0 -575
  53. data/docs/architecture/index.md +0 -252
  54. data/docs/architecture/message-flow.md +0 -366
  55. data/docs/architecture/network-orchestration.md +0 -478
  56. data/docs/architecture/robot-execution.md +0 -396
  57. data/docs/architecture/state-management.md +0 -410
  58. data/docs/assets/css/custom.css +0 -56
  59. data/docs/assets/images/robot_lab.jpg +0 -0
  60. data/docs/concepts.md +0 -641
  61. data/docs/examples/basic-chat.md +0 -258
  62. data/docs/examples/index.md +0 -425
  63. data/docs/examples/mcp-server.md +0 -403
  64. data/docs/examples/multi-robot-network.md +0 -476
  65. data/docs/examples/tool-usage.md +0 -468
  66. data/docs/getting-started/configuration.md +0 -645
  67. data/docs/getting-started/index.md +0 -56
  68. data/docs/getting-started/installation.md +0 -197
  69. data/docs/getting-started/quick-start.md +0 -293
  70. data/docs/guides/building-robots.md +0 -1187
  71. data/docs/guides/creating-networks.md +0 -736
  72. data/docs/guides/hooks.md +0 -1206
  73. data/docs/guides/index.md +0 -78
  74. data/docs/guides/knowledge.md +0 -219
  75. data/docs/guides/mcp-integration.md +0 -740
  76. data/docs/guides/memory.md +0 -458
  77. data/docs/guides/observability.md +0 -733
  78. data/docs/guides/streaming.md +0 -323
  79. data/docs/guides/using-tools.md +0 -780
  80. data/docs/index.md +0 -280
  81. data/docs/superpowers/plans/2026-05-06-agentskills.md +0 -1303
  82. data/docs/superpowers/specs/2026-05-06-agentskills-design.md +0 -247
  83. data/examples/.envrc +0 -3
  84. data/examples/01_simple_robot.rb +0 -31
  85. data/examples/02_tools.rb +0 -109
  86. data/examples/03_network.rb +0 -118
  87. data/examples/04_mcp.rb +0 -217
  88. data/examples/05_streaming.rb +0 -137
  89. data/examples/06_prompt_templates.rb +0 -325
  90. data/examples/07_network_memory.rb +0 -313
  91. data/examples/08_llm_config.rb +0 -162
  92. data/examples/09_chaining.rb +0 -251
  93. data/examples/10_memory.rb +0 -315
  94. data/examples/11_network_introspection.rb +0 -239
  95. data/examples/12_message_bus.rb +0 -67
  96. data/examples/13_spawn.rb +0 -85
  97. data/examples/14_rusty_circuit/.envrc +0 -1
  98. data/examples/14_rusty_circuit/.gitignore +0 -1
  99. data/examples/14_rusty_circuit/README.md +0 -1
  100. data/examples/14_rusty_circuit/comic.rb +0 -149
  101. data/examples/14_rusty_circuit/display.rb +0 -217
  102. data/examples/14_rusty_circuit/heckler.rb +0 -65
  103. data/examples/14_rusty_circuit/open_mic.rb +0 -132
  104. data/examples/14_rusty_circuit/prompts/open_mic_comic.md +0 -20
  105. data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +0 -23
  106. data/examples/14_rusty_circuit/prompts/open_mic_scout.md +0 -20
  107. data/examples/14_rusty_circuit/scout.rb +0 -165
  108. data/examples/14_rusty_circuit/show.log +0 -234
  109. data/examples/15_memory_network_and_bus/.envrc +0 -1
  110. data/examples/15_memory_network_and_bus/README.md +0 -66
  111. data/examples/15_memory_network_and_bus/editor_in_chief.rb +0 -24
  112. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +0 -213
  113. data/examples/15_memory_network_and_bus/linux_writer.rb +0 -80
  114. data/examples/15_memory_network_and_bus/os_editor.rb +0 -48
  115. data/examples/15_memory_network_and_bus/os_writer.rb +0 -49
  116. data/examples/15_memory_network_and_bus/output/combined_article.md +0 -11
  117. data/examples/15_memory_network_and_bus/output/final_article.md +0 -8
  118. data/examples/15_memory_network_and_bus/output/linux_draft.md +0 -7
  119. data/examples/15_memory_network_and_bus/output/mac_draft.md +0 -7
  120. data/examples/15_memory_network_and_bus/output/memory.json +0 -13
  121. data/examples/15_memory_network_and_bus/output/revision_1.md +0 -29
  122. data/examples/15_memory_network_and_bus/output/revision_2.md +0 -50
  123. data/examples/15_memory_network_and_bus/output/revision_3.md +0 -8
  124. data/examples/15_memory_network_and_bus/output/windows_draft.md +0 -7
  125. data/examples/15_memory_network_and_bus/prompts/os_advocate.md +0 -13
  126. data/examples/15_memory_network_and_bus/prompts/os_chief.md +0 -13
  127. data/examples/15_memory_network_and_bus/prompts/os_editor.md +0 -13
  128. data/examples/16_writers_room/.envrc +0 -1
  129. data/examples/16_writers_room/display.rb +0 -158
  130. data/examples/16_writers_room/output/.gitignore +0 -4
  131. data/examples/16_writers_room/output/README.md +0 -69
  132. data/examples/16_writers_room/output/opus_001.md +0 -263
  133. data/examples/16_writers_room/output/opus_001_notes.log +0 -470
  134. data/examples/16_writers_room/output/opus_002.md +0 -245
  135. data/examples/16_writers_room/output/opus_002_notes.log +0 -546
  136. data/examples/16_writers_room/output/opus_002_screenplay.md +0 -7989
  137. data/examples/16_writers_room/output/opus_002_screenplay_notes.md +0 -993
  138. data/examples/16_writers_room/prompts/screenplay_writer.md +0 -66
  139. data/examples/16_writers_room/prompts/writer.md +0 -37
  140. data/examples/16_writers_room/room.rb +0 -186
  141. data/examples/16_writers_room/tools.rb +0 -173
  142. data/examples/16_writers_room/writer.rb +0 -121
  143. data/examples/16_writers_room/writers_room.rb +0 -256
  144. data/examples/17_skills.rb +0 -234
  145. data/examples/18_rails/.envrc +0 -3
  146. data/examples/18_rails/.gitignore +0 -5
  147. data/examples/18_rails/Gemfile +0 -11
  148. data/examples/18_rails/README.md +0 -67
  149. data/examples/18_rails/Rakefile +0 -4
  150. data/examples/18_rails/app/controllers/application_controller.rb +0 -4
  151. data/examples/18_rails/app/controllers/chat_controller.rb +0 -50
  152. data/examples/18_rails/app/jobs/application_job.rb +0 -4
  153. data/examples/18_rails/app/jobs/robot_run_job.rb +0 -25
  154. data/examples/18_rails/app/models/application_record.rb +0 -5
  155. data/examples/18_rails/app/models/robot_lab_result.rb +0 -36
  156. data/examples/18_rails/app/models/robot_lab_thread.rb +0 -23
  157. data/examples/18_rails/app/robots/chat_robot.rb +0 -25
  158. data/examples/18_rails/app/tools/time_tool.rb +0 -9
  159. data/examples/18_rails/app/views/chat/_user_message.html.erb +0 -1
  160. data/examples/18_rails/app/views/chat/index.html.erb +0 -67
  161. data/examples/18_rails/app/views/layouts/application.html.erb +0 -49
  162. data/examples/18_rails/bin/dev +0 -7
  163. data/examples/18_rails/bin/rails +0 -6
  164. data/examples/18_rails/bin/setup +0 -15
  165. data/examples/18_rails/config/application.rb +0 -33
  166. data/examples/18_rails/config/cable.yml +0 -2
  167. data/examples/18_rails/config/database.yml +0 -5
  168. data/examples/18_rails/config/environment.rb +0 -4
  169. data/examples/18_rails/config/initializers/robot_lab.rb +0 -11
  170. data/examples/18_rails/config/routes.rb +0 -6
  171. data/examples/18_rails/config.ru +0 -4
  172. data/examples/18_rails/db/migrate/001_create_robot_lab_tables.rb +0 -32
  173. data/examples/19_token_tracking.rb +0 -138
  174. data/examples/20_circuit_breaker.rb +0 -147
  175. data/examples/21_learning_loop.rb +0 -181
  176. data/examples/22_context_compression.rb +0 -172
  177. data/examples/23_convergence.rb +0 -133
  178. data/examples/24_structured_delegation.rb +0 -151
  179. data/examples/25_history_search/conversation.jsonl +0 -30
  180. data/examples/25_history_search.rb +0 -133
  181. data/examples/26_document_store/api_versioning_adr.md +0 -52
  182. data/examples/26_document_store/incident_postmortem.md +0 -46
  183. data/examples/26_document_store/postgres_runbook.md +0 -49
  184. data/examples/26_document_store/redis_caching_guide.md +0 -48
  185. data/examples/26_document_store/sidekiq_guide.md +0 -51
  186. data/examples/26_document_store.rb +0 -140
  187. data/examples/27_incident_response/README.md +0 -65
  188. data/examples/27_incident_response/incident_response.rb +0 -261
  189. data/examples/28_mcp_discovery.rb +0 -113
  190. data/examples/29_ractor_tools.rb +0 -240
  191. data/examples/30_ractor_network.rb +0 -252
  192. data/examples/31_launch_assessment.rb +0 -246
  193. data/examples/32_newsletter_reader.rb +0 -193
  194. data/examples/33_stock_generator.rb +0 -80
  195. data/examples/33_stock_predictor.rb +0 -327
  196. data/examples/34_agentskills.rb +0 -76
  197. data/examples/35_hooks.rb +0 -266
  198. data/examples/README.md +0 -550
  199. data/examples/common.rb +0 -180
  200. data/examples/prompts/assistant.md +0 -5
  201. data/examples/prompts/audit_trail.md +0 -8
  202. data/examples/prompts/billing.md +0 -10
  203. data/examples/prompts/classifier.md +0 -7
  204. data/examples/prompts/comedian.md +0 -6
  205. data/examples/prompts/comedy_critic.md +0 -10
  206. data/examples/prompts/configurable.md +0 -9
  207. data/examples/prompts/dispatcher.md +0 -12
  208. data/examples/prompts/entity_extractor.md +0 -14
  209. data/examples/prompts/escalation.md +0 -42
  210. data/examples/prompts/frontmatter_mcp_test.md +0 -9
  211. data/examples/prompts/frontmatter_named_test.md +0 -5
  212. data/examples/prompts/frontmatter_tools_test.md +0 -6
  213. data/examples/prompts/general.md +0 -7
  214. data/examples/prompts/github_assistant.md +0 -14
  215. data/examples/prompts/helper.md +0 -4
  216. data/examples/prompts/incident_responder.md +0 -18
  217. data/examples/prompts/keyword_extractor.md +0 -11
  218. data/examples/prompts/llm_config_demo.md +0 -20
  219. data/examples/prompts/order_support.md +0 -35
  220. data/examples/prompts/os_advocate.md +0 -13
  221. data/examples/prompts/os_chief.md +0 -13
  222. data/examples/prompts/os_editor.md +0 -13
  223. data/examples/prompts/parameterized_main_test.md +0 -6
  224. data/examples/prompts/pii_redactor.md +0 -7
  225. data/examples/prompts/product_support.md +0 -37
  226. data/examples/prompts/runbook_protocol.md +0 -12
  227. data/examples/prompts/sentiment_analyzer.md +0 -12
  228. data/examples/prompts/skill_a_test.md +0 -4
  229. data/examples/prompts/skill_b_test.md +0 -4
  230. data/examples/prompts/skill_config_test.md +0 -5
  231. data/examples/prompts/skill_cycle_a_test.md +0 -6
  232. data/examples/prompts/skill_cycle_b_test.md +0 -6
  233. data/examples/prompts/skill_description_test.md +0 -4
  234. data/examples/prompts/skill_leaf_test.md +0 -4
  235. data/examples/prompts/skill_nested_test.md +0 -6
  236. data/examples/prompts/skill_refs_main_test.md +0 -6
  237. data/examples/prompts/skill_self_ref_test.md +0 -6
  238. data/examples/prompts/skill_with_mcp_test.md +0 -9
  239. data/examples/prompts/skill_with_params_test.md +0 -6
  240. data/examples/prompts/skill_with_robot_name_test.md +0 -5
  241. data/examples/prompts/skill_with_tools_test.md +0 -6
  242. data/examples/prompts/sre_compliance.md +0 -10
  243. data/examples/prompts/structured_output.md +0 -7
  244. data/examples/prompts/synthesizer.md +0 -17
  245. data/examples/prompts/technical.md +0 -10
  246. data/examples/prompts/template_with_skills_test.md +0 -6
  247. data/examples/prompts/triage.md +0 -22
  248. data/examples/ruboruby.md +0 -423
  249. data/examples/run_all.rb +0 -60
  250. data/examples/xyzzy.rb +0 -97
  251. data/logfile +0 -8
  252. data/mkdocs.yml +0 -209
  253. data/robot_concurrency.md +0 -38
  254. data/simple_acp_review.md +0 -298
  255. data/temp.md +0 -6
  256. data/tool_manifest_plan.md +0 -155
@@ -1,197 +0,0 @@
1
- # Installation
2
-
3
- This guide covers installing RobotLab in your Ruby project.
4
-
5
- ## Requirements
6
-
7
- - **Ruby**: 3.2 or higher
8
- - **Bundler**: 2.0 or higher (recommended)
9
-
10
- ## Install via Bundler
11
-
12
- Add RobotLab to your `Gemfile`:
13
-
14
- ```ruby
15
- gem "robot_lab"
16
- ```
17
-
18
- Then install:
19
-
20
- ```bash
21
- bundle install
22
- ```
23
-
24
- ## Install via RubyGems
25
-
26
- Or install directly:
27
-
28
- ```bash
29
- gem install robot_lab
30
- ```
31
-
32
- ## Dependencies
33
-
34
- RobotLab automatically installs these core dependencies:
35
-
36
- | Gem | Purpose |
37
- |-----|---------|
38
- | `ruby_llm` (~> 2.0.0.rc3) | LLM provider integrations (Anthropic, OpenAI, Gemini, etc.) |
39
- | `prompt_manager` (~> 1.0) | Template-based prompt management with YAML front matter |
40
- | `simple_flow` (~> 0.4) | Pipeline workflow execution for networks |
41
- | `myway_config` (~> 0.1) | Layered configuration (defaults, env vars, config files) |
42
- | `zeitwerk` (~> 2.6) | Autoloading and eager loading |
43
- | `async` (~> 2.0) | Fiber-based concurrency |
44
- | `async-http` (~> 0.60) | MCP SSE and streamable-HTTP transports |
45
- | `async-websocket` (~> 0.30) | MCP WebSocket transport |
46
- | `typed_bus` (~> 0.0.1) | Typed message bus for robot-to-robot messaging |
47
- | `ractor_queue` (~> 0.2) | Queue used by the Network bus poller |
48
-
49
- > [!NOTE]
50
- > `async-http` and `async-websocket` are hard runtime dependencies, not optional
51
- > extras — they install with the gem whether or not you use MCP.
52
-
53
- ### Optional Dependencies
54
-
55
- Several features are gated behind gems the core gem does **not** install. Add
56
- whichever you need to your own `Gemfile`:
57
-
58
- | Gem | Enables | Without it |
59
- |-----|---------|------------|
60
- | `classifier` (~> 2.3) | `robot.compress_history`, `RobotLab::Convergence` | `RobotLab::DependencyError` |
61
- | `robot_lab-document_store` | `memory.store_document` / `search_documents` / `document_keys` / `delete_document`, and `AgentSkill` catalogs | `RobotLab::DependencyError` (skill catalogs raise `LoadError`) |
62
- | `redis` | Redis-backed `Memory` | `Memory#redis?` is `false` and the store silently stays in-process |
63
- | `robot_lab-ractor` | Ractor-parallel tool execution and `Network` ractor scheduling | tools run inline; a network run with `parallel_mode: :ractor` raises `RobotLab::DependencyError` |
64
-
65
- ```ruby
66
- # Gemfile
67
- gem "classifier", "~> 2.3"
68
- gem "robot_lab-document_store"
69
- gem "redis"
70
- gem "robot_lab-ractor"
71
- ```
72
-
73
- > [!NOTE]
74
- > Several capabilities advertised on the [home page](../index.md) — embedding-based
75
- > document retrieval, runtime skill matching, and CPU parallelism — depend on the
76
- > gems above. They are genuinely optional, but the feature is unavailable until the
77
- > gem is installed.
78
-
79
- ## Verify Installation
80
-
81
- Create a test file to verify everything works:
82
-
83
- ```ruby
84
- # test_robot_lab.rb
85
- require "robot_lab"
86
-
87
- puts "RobotLab version: #{RobotLab::VERSION}"
88
- puts "Installation successful!"
89
- ```
90
-
91
- Run it:
92
-
93
- ```bash
94
- ruby test_robot_lab.rb
95
- # => RobotLab version: 0.2.6
96
- # => Installation successful!
97
- ```
98
-
99
- ## Rails Installation
100
-
101
- > [!IMPORTANT]
102
- > The core `robot_lab` gem ships **no Rails Engine, no Railtie, and no generators**.
103
- > Rails integration lives in the separate
104
- > [robot_lab-rails](https://github.com/MadBomber/robot_lab-rails) gem.
105
-
106
- Core RobotLab only performs two bare `defined?(::Rails)` checks: it uses
107
- `Rails.logger` as the default logger, and it resolves the template path to
108
- `app/prompts` when `Rails.root` is present. Nothing else is Rails-aware.
109
-
110
- For generators, an `ActiveJob` base class, and Turbo Stream broadcasting, add the
111
- extension gem:
112
-
113
- ```ruby
114
- # Gemfile
115
- gem "robot_lab"
116
- gem "robot_lab-rails"
117
- ```
118
-
119
- Then follow that gem's own installation instructions for its generators and
120
- migrations.
121
-
122
- ## Environment Setup
123
-
124
- RobotLab uses a layered configuration system (see [Configuration](configuration.md) for full details). The simplest way to get started is with environment variables:
125
-
126
- === "Anthropic (Recommended)"
127
-
128
- ```bash
129
- export ROBOT_LAB_RUBY_LLM__ANTHROPIC_API_KEY="sk-ant-..."
130
- ```
131
-
132
- === "OpenAI"
133
-
134
- ```bash
135
- export ROBOT_LAB_RUBY_LLM__OPENAI_API_KEY="sk-..."
136
- ```
137
-
138
- === "Google Gemini"
139
-
140
- ```bash
141
- export ROBOT_LAB_RUBY_LLM__GEMINI_API_KEY="..."
142
- ```
143
-
144
- !!! tip "Using dotenv"
145
- For development, consider using the [dotenv](https://github.com/bkeepers/dotenv) gem to manage environment variables:
146
-
147
- ```ruby
148
- # Gemfile
149
- gem "dotenv", groups: [:development, :test]
150
- ```
151
-
152
- ```bash
153
- # .env
154
- ROBOT_LAB_RUBY_LLM__ANTHROPIC_API_KEY=sk-ant-...
155
- ```
156
-
157
- !!! info "Direct provider env vars"
158
- RubyLLM also reads provider-specific environment variables directly (e.g., `ANTHROPIC_API_KEY`). If you already have those set, they will be picked up automatically. The `ROBOT_LAB_RUBY_LLM__*` prefix gives you explicit control through RobotLab's config layer.
159
-
160
- ## Troubleshooting
161
-
162
- ### Gem Installation Fails
163
-
164
- If you encounter SSL or network errors:
165
-
166
- ```bash
167
- # Update RubyGems
168
- gem update --system
169
-
170
- # Try installing with verbose output
171
- gem install robot_lab --verbose
172
- ```
173
-
174
- ### Missing Dependencies
175
-
176
- If you see a `LoadError` (or a `RobotLab::DependencyError`) naming a gem RobotLab
177
- does not depend on, add it yourself:
178
-
179
- ```bash
180
- # e.g. compress_history / Convergence need the classifier gem
181
- bundle add classifier
182
- ```
183
-
184
- ### API Key Issues
185
-
186
- If you see authentication errors:
187
-
188
- 1. Verify your API key is set: `echo $ROBOT_LAB_RUBY_LLM__ANTHROPIC_API_KEY`
189
- 2. Check the key is valid in your provider's console
190
- 3. Ensure you're using the correct environment variable name
191
-
192
- ## Next Steps
193
-
194
- Now that RobotLab is installed:
195
-
196
- - [:octicons-arrow-right-24: Quick Start](quick-start.md) - Build your first robot
197
- - [:octicons-arrow-right-24: Configuration](configuration.md) - Configure defaults
@@ -1,293 +0,0 @@
1
- # Quick Start
2
-
3
- Build your first RobotLab application in 5 minutes.
4
-
5
- ## Step 1: Set Up API Keys
6
-
7
- RobotLab reads configuration from environment variables automatically. Set your API key before running any code:
8
-
9
- ```bash
10
- export ROBOT_LAB_RUBY_LLM__ANTHROPIC_API_KEY="sk-ant-..."
11
- ```
12
-
13
- Or create a config file at `./config/robot_lab.yml`:
14
-
15
- ```yaml
16
- ruby_llm:
17
- anthropic_api_key: <%= ENV['ANTHROPIC_API_KEY'] %>
18
- ```
19
-
20
- > [!IMPORTANT]
21
- > Config files are **flat** — put the keys at the top level. Wrapping them in a
22
- > `defaults:` key (as the gem's own bundled `defaults.yml` does) makes the whole
23
- > file silently ignored.
24
-
25
- See [Configuration](configuration.md) for all configuration options.
26
-
27
- ## Step 2: Create a Robot
28
-
29
- Build a simple assistant robot using keyword arguments:
30
-
31
- ```ruby
32
- require "robot_lab"
33
-
34
- assistant = RobotLab.build(
35
- name: "assistant",
36
- system_prompt: "You are a helpful AI assistant. You provide clear, accurate, and concise answers."
37
- )
38
- ```
39
-
40
- ## Step 3: Run It
41
-
42
- Send a message and get a response:
43
-
44
- ```ruby
45
- result = assistant.run("What is Ruby on Rails?")
46
-
47
- puts result.last_text_content
48
- ```
49
-
50
- The `run` method takes a positional string message and returns a `RobotResult`. Use `last_text_content` to extract the response text.
51
-
52
- ## Complete Example
53
-
54
- Here is everything together in one file:
55
-
56
- ```ruby title="hello_robot.rb"
57
- require "robot_lab"
58
-
59
- # Build a robot with an inline system prompt
60
- assistant = RobotLab.build(
61
- name: "assistant",
62
- system_prompt: "You are a helpful AI assistant. Be concise and friendly."
63
- )
64
-
65
- # Run the robot with a message
66
- result = assistant.run("Hello! What can you help me with?")
67
-
68
- # Print the response
69
- puts result.last_text_content
70
- ```
71
-
72
- Run it:
73
-
74
- ```bash
75
- ruby hello_robot.rb
76
- ```
77
-
78
- ## Using Templates
79
-
80
- Instead of inline prompts, you can use template files managed by `prompt_manager`. Templates are `.md` files with YAML front matter:
81
-
82
- ```markdown title="prompts/helper.md"
83
- ---
84
- description: A helpful assistant
85
- parameters:
86
- company_name: null
87
- ---
88
- You are a helpful assistant for <%= company_name %>.
89
- Be concise and friendly in your responses.
90
- ```
91
-
92
- Create the robot with a template reference and context:
93
-
94
- ```ruby
95
- robot = RobotLab.build(
96
- name: "helper",
97
- template: :helper,
98
- context: { company_name: "Acme Corp" }
99
- )
100
-
101
- result = robot.run("What services do you offer?")
102
- puts result.last_text_content
103
- ```
104
-
105
- Templates are loaded from the `prompts/` directory by default (or `app/prompts/` in Rails). You can change this in your config.
106
-
107
- ## Adding a Tool
108
-
109
- Give your robot custom capabilities by defining a `RubyLLM::Tool` subclass:
110
-
111
- ```ruby title="hello_tools.rb"
112
- require "robot_lab"
113
-
114
- class CurrentTime < RubyLLM::Tool
115
- description "Get the current date and time"
116
-
117
- param :timezone,
118
- type: "string",
119
- desc: "Timezone name (e.g., 'UTC', 'US/Eastern')",
120
- required: false
121
-
122
- def execute(timezone: "UTC")
123
- Time.now.getlocal(timezone_offset(timezone)).strftime("%Y-%m-%d %H:%M:%S %Z")
124
- rescue => e
125
- Time.now.utc.strftime("%Y-%m-%d %H:%M:%S UTC")
126
- end
127
-
128
- private
129
-
130
- def timezone_offset(tz)
131
- case tz
132
- when "UTC" then "+00:00"
133
- when "US/Eastern" then "-05:00"
134
- when "US/Pacific" then "-08:00"
135
- else "+00:00"
136
- end
137
- end
138
- end
139
-
140
- # Pass tools via the local_tools: parameter
141
- assistant = RobotLab.build(
142
- name: "time_bot",
143
- system_prompt: "You are a helpful assistant. Use the current_time tool when users ask about the time.",
144
- local_tools: [CurrentTime]
145
- )
146
-
147
- # tools: :inherit is REQUIRED -- run() sends no tools without it
148
- result = assistant.run("What time is it right now?", tools: :inherit)
149
- puts result.last_text_content
150
- ```
151
-
152
- Tools are passed to the robot via the `local_tools:` keyword argument as an array of `RubyLLM::Tool` subclasses.
153
-
154
- > [!WARNING]
155
- > **Attaching a tool is not the same as sending it.** `Robot#run` defaults to
156
- > `tools: :none`, which means "send zero tools this turn". Without
157
- > `tools: :inherit` on the run, the example above builds fine, calls the LLM
158
- > fine, and the model simply never sees `CurrentTime` — it will guess or say it
159
- > cannot check the time. The same applies to MCP: pass
160
- > `mcp: :inherit, tools: :inherit` to connect MCP servers and expose their tools.
161
- >
162
- > Do **not** try to fix this by passing `tools: :inherit` to `RobotLab.build` for
163
- > a standalone robot like this one — at build time it resolves against the global
164
- > `:none` and yields an allowlist matching nothing, suppressing the tools even
165
- > when the run asks for them. Put it on the `run` call.
166
- >
167
- > (The one place build-time `:inherit` *is* correct is a robot in a network, where
168
- > it opts into the network `config:`'s list — see
169
- > [Creating Networks](../guides/creating-networks.md).)
170
-
171
- ## Method Chaining
172
-
173
- Robots support a chaining API for runtime adjustments:
174
-
175
- ```ruby
176
- robot = RobotLab.build(name: "writer")
177
-
178
- result = robot
179
- .with_instructions("You are a creative fiction writer.")
180
- .with_temperature(0.9)
181
- .with_model("claude-sonnet-4")
182
- .run("Write a haiku about programming.")
183
-
184
- puts result.last_text_content
185
- ```
186
-
187
- The complete set of chaining methods is `with_context`, `with_headers`,
188
- `with_instructions`, `with_model`, `with_params`, `with_schema`,
189
- `with_temperature`, `with_thinking`, `with_tool`, `with_tools`, plus RobotLab's
190
- own `with_template` and `with_bus`.
191
-
192
- > [!NOTE]
193
- > There is no `with_max_tokens`, `with_top_p`, `with_top_k`, `with_stop`,
194
- > `with_presence_penalty`, or `with_frequency_penalty` — those raise
195
- > `NoMethodError`. Set them as constructor keyword arguments
196
- > (`RobotLab.build(..., max_tokens: 2000)`) or through `with_params`:
197
- >
198
- > ```ruby
199
- > robot.with_params(max_tokens: 2000, top_p: 0.3).run("...")
200
- > ```
201
-
202
- ## Multi-Robot Network
203
-
204
- Create a pipeline of robots using `RobotLab.create_network`. Networks use `SimpleFlow::Pipeline` under the hood with `task` definitions and dependency tracking:
205
-
206
- ```ruby title="hello_network.rb"
207
- require "robot_lab"
208
-
209
- # Build specialized robots
210
- analyst = RobotLab.build(
211
- name: "analyst",
212
- system_prompt: <<~PROMPT
213
- You are a text analyst. Analyze the given text and provide a brief
214
- summary of its key themes and sentiment. Be concise -- 2-3 sentences max.
215
- PROMPT
216
- )
217
-
218
- writer = RobotLab.build(
219
- name: "writer",
220
- system_prompt: <<~PROMPT
221
- You are a professional copywriter. Based on the analysis you receive,
222
- write a short, engaging summary suitable for a newsletter. Keep it
223
- to one paragraph.
224
- PROMPT
225
- )
226
-
227
- # Create a sequential pipeline
228
- network = RobotLab.create_network(name: "content_pipeline") do
229
- task :analyst, analyst, depends_on: :none
230
- task :writer, writer, depends_on: [:analyst]
231
- end
232
-
233
- # Run the network
234
- result = network.run(
235
- message: "Ruby 3.4 was released with significant performance improvements..."
236
- )
237
-
238
- # The final result is from the last robot in the pipeline
239
- if result.value.is_a?(RobotLab::RobotResult)
240
- puts result.value.last_text_content
241
- end
242
-
243
- # Access intermediate results by ROBOT name (see note below)
244
- if result.context[:analyst]
245
- puts "\nAnalysis: #{result.context[:analyst].last_text_content}"
246
- end
247
- ```
248
-
249
- > [!IMPORTANT]
250
- > `result.context` is keyed by the **robot's** `name:`, not by the task name.
251
- > Internally each robot writes `result.with_context(@name.to_sym, robot_result)`.
252
- > The lookup above works only because the robot is named `"analyst"` *and* its
253
- > task is named `:analyst`. If you register a robot under a different task name —
254
- > `task :first_pass, analyst` — the result is still at
255
- > `result.context[:analyst]`, not `result.context[:first_pass]`. Keeping the two
256
- > names identical, as in this example, is the simplest way to avoid the
257
- > surprise.
258
-
259
- ### Network Task Dependencies
260
-
261
- Tasks declare their dependencies to control execution order:
262
-
263
- | Dependency | Meaning |
264
- |-----------|---------|
265
- | `depends_on: :none` | Entry point -- runs first with no dependencies |
266
- | `depends_on: [:task_name]` | Runs after the named task(s) complete |
267
- | `depends_on: :optional` | Only runs if explicitly activated by a preceding task |
268
-
269
- Tasks with non-overlapping dependencies can execute in parallel automatically.
270
-
271
- ## What's Next?
272
-
273
- You have built your first RobotLab application. Here is where to go next:
274
-
275
- <div class="grid cards" markdown>
276
-
277
- - [:octicons-gear-24: **Configuration**](configuration.md)
278
-
279
- Learn all configuration options
280
-
281
- - [:octicons-cpu-24: **Building Robots**](../guides/building-robots.md)
282
-
283
- Deep dive into robot creation
284
-
285
- - [:octicons-tools-24: **Using Tools**](../guides/using-tools.md)
286
-
287
- Give robots custom capabilities
288
-
289
- - [:octicons-git-branch-24: **Creating Networks**](../guides/creating-networks.md)
290
-
291
- Advanced network patterns
292
-
293
- </div>