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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +1 -1
- data/lib/robot_lab/mcp/transports/streamable_http.rb +1 -1
- data/lib/robot_lab/version.rb +1 -1
- metadata +3 -253
- data/.architecture/AGENTS.md +0 -32
- data/.architecture/config.yml +0 -8
- data/.architecture/members.yml +0 -60
- data/.architecture/reviews/feature-free-will.md +0 -490
- data/.architecture/reviews/overall-codebase.md +0 -427
- data/.claude/settings.local.json +0 -57
- data/.codex/config.toml +0 -2
- data/.envrc +0 -6
- data/.github/workflows/deploy-github-pages.yml +0 -52
- data/.irbrc +0 -6
- data/.loki +0 -65
- data/.quality/reek_baseline.txt +0 -43
- data/.rubocop.yml +0 -10
- data/Archspec.rb +0 -44
- data/CLAUDE.md +0 -141
- data/COMMITS.md +0 -196
- data/Rakefile +0 -193
- data/_typos.toml +0 -21
- data/agent2agent_review.md +0 -192
- data/agentf_improvements.md +0 -253
- data/agents.md +0 -14
- data/docs/api/core/index.md +0 -147
- data/docs/api/core/memory.md +0 -578
- data/docs/api/core/network.md +0 -553
- data/docs/api/core/result.md +0 -211
- data/docs/api/core/robot.md +0 -1667
- data/docs/api/core/state.md +0 -145
- data/docs/api/core/tool.md +0 -520
- data/docs/api/errors.md +0 -323
- data/docs/api/hooks.md +0 -469
- data/docs/api/index.md +0 -137
- data/docs/api/mcp/client.md +0 -387
- data/docs/api/mcp/index.md +0 -267
- data/docs/api/mcp/server.md +0 -252
- data/docs/api/mcp/transports.md +0 -339
- data/docs/api/messages/index.md +0 -126
- data/docs/api/messages/text-message.md +0 -170
- data/docs/api/messages/tool-call-message.md +0 -206
- data/docs/api/messages/tool-result-message.md +0 -242
- data/docs/api/messages/user-message.md +0 -232
- data/docs/api/skills.md +0 -423
- data/docs/api/streaming/context.md +0 -280
- data/docs/api/streaming/events.md +0 -185
- data/docs/api/streaming/index.md +0 -156
- data/docs/api/support.md +0 -846
- data/docs/architecture/core-concepts.md +0 -575
- data/docs/architecture/index.md +0 -252
- data/docs/architecture/message-flow.md +0 -366
- data/docs/architecture/network-orchestration.md +0 -478
- data/docs/architecture/robot-execution.md +0 -396
- data/docs/architecture/state-management.md +0 -410
- data/docs/assets/css/custom.css +0 -56
- data/docs/assets/images/robot_lab.jpg +0 -0
- data/docs/concepts.md +0 -641
- data/docs/examples/basic-chat.md +0 -258
- data/docs/examples/index.md +0 -425
- data/docs/examples/mcp-server.md +0 -403
- data/docs/examples/multi-robot-network.md +0 -476
- data/docs/examples/tool-usage.md +0 -468
- data/docs/getting-started/configuration.md +0 -645
- data/docs/getting-started/index.md +0 -56
- data/docs/getting-started/installation.md +0 -197
- data/docs/getting-started/quick-start.md +0 -293
- data/docs/guides/building-robots.md +0 -1187
- data/docs/guides/creating-networks.md +0 -736
- data/docs/guides/hooks.md +0 -1206
- data/docs/guides/index.md +0 -78
- data/docs/guides/knowledge.md +0 -219
- data/docs/guides/mcp-integration.md +0 -740
- data/docs/guides/memory.md +0 -458
- data/docs/guides/observability.md +0 -733
- data/docs/guides/streaming.md +0 -323
- data/docs/guides/using-tools.md +0 -780
- data/docs/index.md +0 -280
- data/docs/superpowers/plans/2026-05-06-agentskills.md +0 -1303
- data/docs/superpowers/specs/2026-05-06-agentskills-design.md +0 -247
- data/examples/.envrc +0 -3
- data/examples/01_simple_robot.rb +0 -31
- data/examples/02_tools.rb +0 -109
- data/examples/03_network.rb +0 -118
- data/examples/04_mcp.rb +0 -217
- data/examples/05_streaming.rb +0 -137
- data/examples/06_prompt_templates.rb +0 -325
- data/examples/07_network_memory.rb +0 -313
- data/examples/08_llm_config.rb +0 -162
- data/examples/09_chaining.rb +0 -251
- data/examples/10_memory.rb +0 -315
- data/examples/11_network_introspection.rb +0 -239
- data/examples/12_message_bus.rb +0 -67
- data/examples/13_spawn.rb +0 -85
- data/examples/14_rusty_circuit/.envrc +0 -1
- data/examples/14_rusty_circuit/.gitignore +0 -1
- data/examples/14_rusty_circuit/README.md +0 -1
- data/examples/14_rusty_circuit/comic.rb +0 -149
- data/examples/14_rusty_circuit/display.rb +0 -217
- data/examples/14_rusty_circuit/heckler.rb +0 -65
- data/examples/14_rusty_circuit/open_mic.rb +0 -132
- data/examples/14_rusty_circuit/prompts/open_mic_comic.md +0 -20
- data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +0 -23
- data/examples/14_rusty_circuit/prompts/open_mic_scout.md +0 -20
- data/examples/14_rusty_circuit/scout.rb +0 -165
- data/examples/14_rusty_circuit/show.log +0 -234
- data/examples/15_memory_network_and_bus/.envrc +0 -1
- data/examples/15_memory_network_and_bus/README.md +0 -66
- data/examples/15_memory_network_and_bus/editor_in_chief.rb +0 -24
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +0 -213
- data/examples/15_memory_network_and_bus/linux_writer.rb +0 -80
- data/examples/15_memory_network_and_bus/os_editor.rb +0 -48
- data/examples/15_memory_network_and_bus/os_writer.rb +0 -49
- data/examples/15_memory_network_and_bus/output/combined_article.md +0 -11
- data/examples/15_memory_network_and_bus/output/final_article.md +0 -8
- data/examples/15_memory_network_and_bus/output/linux_draft.md +0 -7
- data/examples/15_memory_network_and_bus/output/mac_draft.md +0 -7
- data/examples/15_memory_network_and_bus/output/memory.json +0 -13
- data/examples/15_memory_network_and_bus/output/revision_1.md +0 -29
- data/examples/15_memory_network_and_bus/output/revision_2.md +0 -50
- data/examples/15_memory_network_and_bus/output/revision_3.md +0 -8
- data/examples/15_memory_network_and_bus/output/windows_draft.md +0 -7
- data/examples/15_memory_network_and_bus/prompts/os_advocate.md +0 -13
- data/examples/15_memory_network_and_bus/prompts/os_chief.md +0 -13
- data/examples/15_memory_network_and_bus/prompts/os_editor.md +0 -13
- data/examples/16_writers_room/.envrc +0 -1
- data/examples/16_writers_room/display.rb +0 -158
- data/examples/16_writers_room/output/.gitignore +0 -4
- data/examples/16_writers_room/output/README.md +0 -69
- data/examples/16_writers_room/output/opus_001.md +0 -263
- data/examples/16_writers_room/output/opus_001_notes.log +0 -470
- data/examples/16_writers_room/output/opus_002.md +0 -245
- data/examples/16_writers_room/output/opus_002_notes.log +0 -546
- data/examples/16_writers_room/output/opus_002_screenplay.md +0 -7989
- data/examples/16_writers_room/output/opus_002_screenplay_notes.md +0 -993
- data/examples/16_writers_room/prompts/screenplay_writer.md +0 -66
- data/examples/16_writers_room/prompts/writer.md +0 -37
- data/examples/16_writers_room/room.rb +0 -186
- data/examples/16_writers_room/tools.rb +0 -173
- data/examples/16_writers_room/writer.rb +0 -121
- data/examples/16_writers_room/writers_room.rb +0 -256
- data/examples/17_skills.rb +0 -234
- data/examples/18_rails/.envrc +0 -3
- data/examples/18_rails/.gitignore +0 -5
- data/examples/18_rails/Gemfile +0 -11
- data/examples/18_rails/README.md +0 -67
- data/examples/18_rails/Rakefile +0 -4
- data/examples/18_rails/app/controllers/application_controller.rb +0 -4
- data/examples/18_rails/app/controllers/chat_controller.rb +0 -50
- data/examples/18_rails/app/jobs/application_job.rb +0 -4
- data/examples/18_rails/app/jobs/robot_run_job.rb +0 -25
- data/examples/18_rails/app/models/application_record.rb +0 -5
- data/examples/18_rails/app/models/robot_lab_result.rb +0 -36
- data/examples/18_rails/app/models/robot_lab_thread.rb +0 -23
- data/examples/18_rails/app/robots/chat_robot.rb +0 -25
- data/examples/18_rails/app/tools/time_tool.rb +0 -9
- data/examples/18_rails/app/views/chat/_user_message.html.erb +0 -1
- data/examples/18_rails/app/views/chat/index.html.erb +0 -67
- data/examples/18_rails/app/views/layouts/application.html.erb +0 -49
- data/examples/18_rails/bin/dev +0 -7
- data/examples/18_rails/bin/rails +0 -6
- data/examples/18_rails/bin/setup +0 -15
- data/examples/18_rails/config/application.rb +0 -33
- data/examples/18_rails/config/cable.yml +0 -2
- data/examples/18_rails/config/database.yml +0 -5
- data/examples/18_rails/config/environment.rb +0 -4
- data/examples/18_rails/config/initializers/robot_lab.rb +0 -11
- data/examples/18_rails/config/routes.rb +0 -6
- data/examples/18_rails/config.ru +0 -4
- data/examples/18_rails/db/migrate/001_create_robot_lab_tables.rb +0 -32
- data/examples/19_token_tracking.rb +0 -138
- data/examples/20_circuit_breaker.rb +0 -147
- data/examples/21_learning_loop.rb +0 -181
- data/examples/22_context_compression.rb +0 -172
- data/examples/23_convergence.rb +0 -133
- data/examples/24_structured_delegation.rb +0 -151
- data/examples/25_history_search/conversation.jsonl +0 -30
- data/examples/25_history_search.rb +0 -133
- data/examples/26_document_store/api_versioning_adr.md +0 -52
- data/examples/26_document_store/incident_postmortem.md +0 -46
- data/examples/26_document_store/postgres_runbook.md +0 -49
- data/examples/26_document_store/redis_caching_guide.md +0 -48
- data/examples/26_document_store/sidekiq_guide.md +0 -51
- data/examples/26_document_store.rb +0 -140
- data/examples/27_incident_response/README.md +0 -65
- data/examples/27_incident_response/incident_response.rb +0 -261
- data/examples/28_mcp_discovery.rb +0 -113
- data/examples/29_ractor_tools.rb +0 -240
- data/examples/30_ractor_network.rb +0 -252
- data/examples/31_launch_assessment.rb +0 -246
- data/examples/32_newsletter_reader.rb +0 -193
- data/examples/33_stock_generator.rb +0 -80
- data/examples/33_stock_predictor.rb +0 -327
- data/examples/34_agentskills.rb +0 -76
- data/examples/35_hooks.rb +0 -266
- data/examples/README.md +0 -550
- data/examples/common.rb +0 -180
- data/examples/prompts/assistant.md +0 -5
- data/examples/prompts/audit_trail.md +0 -8
- data/examples/prompts/billing.md +0 -10
- data/examples/prompts/classifier.md +0 -7
- data/examples/prompts/comedian.md +0 -6
- data/examples/prompts/comedy_critic.md +0 -10
- data/examples/prompts/configurable.md +0 -9
- data/examples/prompts/dispatcher.md +0 -12
- data/examples/prompts/entity_extractor.md +0 -14
- data/examples/prompts/escalation.md +0 -42
- data/examples/prompts/frontmatter_mcp_test.md +0 -9
- data/examples/prompts/frontmatter_named_test.md +0 -5
- data/examples/prompts/frontmatter_tools_test.md +0 -6
- data/examples/prompts/general.md +0 -7
- data/examples/prompts/github_assistant.md +0 -14
- data/examples/prompts/helper.md +0 -4
- data/examples/prompts/incident_responder.md +0 -18
- data/examples/prompts/keyword_extractor.md +0 -11
- data/examples/prompts/llm_config_demo.md +0 -20
- data/examples/prompts/order_support.md +0 -35
- data/examples/prompts/os_advocate.md +0 -13
- data/examples/prompts/os_chief.md +0 -13
- data/examples/prompts/os_editor.md +0 -13
- data/examples/prompts/parameterized_main_test.md +0 -6
- data/examples/prompts/pii_redactor.md +0 -7
- data/examples/prompts/product_support.md +0 -37
- data/examples/prompts/runbook_protocol.md +0 -12
- data/examples/prompts/sentiment_analyzer.md +0 -12
- data/examples/prompts/skill_a_test.md +0 -4
- data/examples/prompts/skill_b_test.md +0 -4
- data/examples/prompts/skill_config_test.md +0 -5
- data/examples/prompts/skill_cycle_a_test.md +0 -6
- data/examples/prompts/skill_cycle_b_test.md +0 -6
- data/examples/prompts/skill_description_test.md +0 -4
- data/examples/prompts/skill_leaf_test.md +0 -4
- data/examples/prompts/skill_nested_test.md +0 -6
- data/examples/prompts/skill_refs_main_test.md +0 -6
- data/examples/prompts/skill_self_ref_test.md +0 -6
- data/examples/prompts/skill_with_mcp_test.md +0 -9
- data/examples/prompts/skill_with_params_test.md +0 -6
- data/examples/prompts/skill_with_robot_name_test.md +0 -5
- data/examples/prompts/skill_with_tools_test.md +0 -6
- data/examples/prompts/sre_compliance.md +0 -10
- data/examples/prompts/structured_output.md +0 -7
- data/examples/prompts/synthesizer.md +0 -17
- data/examples/prompts/technical.md +0 -10
- data/examples/prompts/template_with_skills_test.md +0 -6
- data/examples/prompts/triage.md +0 -22
- data/examples/ruboruby.md +0 -423
- data/examples/run_all.rb +0 -60
- data/examples/xyzzy.rb +0 -97
- data/logfile +0 -8
- data/mkdocs.yml +0 -209
- data/robot_concurrency.md +0 -38
- data/simple_acp_review.md +0 -298
- data/temp.md +0 -6
- data/tool_manifest_plan.md +0 -155
|
@@ -1,645 +0,0 @@
|
|
|
1
|
-
# Configuration
|
|
2
|
-
|
|
3
|
-
RobotLab uses a layered configuration system powered by [MywayConfig](https://github.com/MadBomber/myway_config). Configuration is loaded automatically from multiple sources with no block-style `configure` method required.
|
|
4
|
-
|
|
5
|
-
## How Configuration Works
|
|
6
|
-
|
|
7
|
-
Configuration values are loaded in priority order (lowest to highest):
|
|
8
|
-
|
|
9
|
-
1. **Bundled defaults** -- `lib/robot_lab/config/defaults.yml` (shipped with the gem)
|
|
10
|
-
2. **Environment-specific overrides** -- `development`, `test`, or `production` sections in defaults.yml
|
|
11
|
-
3. **User config file** -- `~/.config/robot_lab/robot_lab.yml`
|
|
12
|
-
4. **Project config file** -- `./config/robot_lab.yml`
|
|
13
|
-
5. **Environment variables** -- `ROBOT_LAB_*` prefix
|
|
14
|
-
6. **Runtime attributes** -- e.g., `RobotLab.config.logger = ...`
|
|
15
|
-
|
|
16
|
-
Higher-priority sources override lower-priority ones. You only need to set the values you want to change.
|
|
17
|
-
|
|
18
|
-
> [!IMPORTANT]
|
|
19
|
-
> The user config file is `~/.config/robot_lab/**robot_lab**.yml` — the filename
|
|
20
|
-
> repeats the application name. `~/.config/robot_lab/config.yml` is **never
|
|
21
|
-
> read**, and RobotLab gives no warning when it is present but ignored.
|
|
22
|
-
|
|
23
|
-
## Accessing Configuration
|
|
24
|
-
|
|
25
|
-
Use `RobotLab.config` to access the configuration object:
|
|
26
|
-
|
|
27
|
-
```ruby
|
|
28
|
-
# Access nested values with dot notation
|
|
29
|
-
RobotLab.config.ruby_llm.model #=> "claude-sonnet-4"
|
|
30
|
-
RobotLab.config.ruby_llm.anthropic_api_key #=> "sk-ant-..."
|
|
31
|
-
RobotLab.config.ruby_llm.request_timeout #=> 120
|
|
32
|
-
RobotLab.config.template_path #=> nil (auto-detected)
|
|
33
|
-
|
|
34
|
-
# Check the environment
|
|
35
|
-
RobotLab.config.development? #=> true/false
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
!!! tip "configure block"
|
|
39
|
-
`RobotLab.configure` yields the config object for block-style setup — useful for setting runtime-only attributes like the logger. For static settings (API keys, timeouts, model defaults) prefer config files or environment variables.
|
|
40
|
-
|
|
41
|
-
```ruby
|
|
42
|
-
RobotLab.configure do |c|
|
|
43
|
-
c.logger = Logger.new(File::NULL) # silence all RobotLab logging
|
|
44
|
-
end
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Environment Variables
|
|
48
|
-
|
|
49
|
-
Environment variables use the `ROBOT_LAB_` prefix. Use double underscores (`__`) for nested values:
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
# Top-level settings
|
|
53
|
-
export ROBOT_LAB_TEMPLATE_PATH=prompts
|
|
54
|
-
|
|
55
|
-
# Nested ruby_llm settings (note the double underscore)
|
|
56
|
-
export ROBOT_LAB_RUBY_LLM__MODEL=claude-sonnet-4
|
|
57
|
-
export ROBOT_LAB_RUBY_LLM__ANTHROPIC_API_KEY=sk-ant-...
|
|
58
|
-
export ROBOT_LAB_RUBY_LLM__OPENAI_API_KEY=sk-...
|
|
59
|
-
export ROBOT_LAB_RUBY_LLM__GEMINI_API_KEY=...
|
|
60
|
-
export ROBOT_LAB_RUBY_LLM__REQUEST_TIMEOUT=180
|
|
61
|
-
export ROBOT_LAB_RUBY_LLM__MAX_RETRIES=5
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
The double underscore convention maps to nested YAML structure:
|
|
65
|
-
|
|
66
|
-
```
|
|
67
|
-
ROBOT_LAB_RUBY_LLM__ANTHROPIC_API_KEY --> ruby_llm.anthropic_api_key
|
|
68
|
-
ROBOT_LAB_RUBY_LLM__MODEL --> ruby_llm.model
|
|
69
|
-
ROBOT_LAB_TEMPLATE_PATH --> template_path
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
> [!WARNING]
|
|
73
|
-
> **Nested values arrive as Strings.** Only top-level keys are type-coerced.
|
|
74
|
-
> With `ROBOT_LAB_RUBY_LLM__REQUEST_TIMEOUT=180` set,
|
|
75
|
-
> `RobotLab.config.ruby_llm.request_timeout` returns the String `"180"`, not the
|
|
76
|
-
> Integer `180`. If a numeric nested setting matters to your code, set it in a
|
|
77
|
-
> config file instead, or coerce it yourself with `.to_i` / `.to_f`.
|
|
78
|
-
|
|
79
|
-
## Config Files
|
|
80
|
-
|
|
81
|
-
> [!WARNING]
|
|
82
|
-
> **A `defaults:` wrapper is always ignored in your own files.** The `defaults:`
|
|
83
|
-
> key you see inside the gem's bundled `lib/robot_lab/config/defaults.yml` applies
|
|
84
|
-
> **only to that bundled file**. Wrap your own settings in it and every value
|
|
85
|
-
> silently falls back to the default — no error, no warning.
|
|
86
|
-
>
|
|
87
|
-
> ```yaml
|
|
88
|
-
> # WRONG — silently ignored in a user or project config file
|
|
89
|
-
> defaults:
|
|
90
|
-
> template_path: prompts
|
|
91
|
-
>
|
|
92
|
-
> # RIGHT
|
|
93
|
-
> template_path: prompts
|
|
94
|
-
> ```
|
|
95
|
-
>
|
|
96
|
-
> Sections named for the **current environment** (`development:`, `test:`,
|
|
97
|
-
> `production:`) are a different matter, and the two files disagree:
|
|
98
|
-
>
|
|
99
|
-
> | File | Flat keys | `development:` section |
|
|
100
|
-
> |------|-----------|------------------------|
|
|
101
|
-
> | `~/.config/robot_lab/robot_lab.yml` | honoured | honoured |
|
|
102
|
-
> | `./config/robot_lab.yml` (no Rails) | honoured | ignored |
|
|
103
|
-
> | `./config/robot_lab.yml` (under Rails) | **ignored** | **honoured** |
|
|
104
|
-
>
|
|
105
|
-
> The user file checks for a section matching the current environment and falls
|
|
106
|
-
> back to the file root, so both forms work. The project file is read by
|
|
107
|
-
> anyway_config, which only treats it as environmental once
|
|
108
|
-
> `Anyway::Settings.current_environment` is set — which is precisely what Rails
|
|
109
|
-
> does (it sets it to `Rails.env`). See [Rails Integration](#rails-integration).
|
|
110
|
-
|
|
111
|
-
### Project Config
|
|
112
|
-
|
|
113
|
-
Create `./config/robot_lab.yml` in your project root. Outside Rails, write the
|
|
114
|
-
keys at the top level (under Rails they must be nested under the environment name
|
|
115
|
-
instead — see [Rails Integration](#rails-integration)):
|
|
116
|
-
|
|
117
|
-
```yaml title="config/robot_lab.yml"
|
|
118
|
-
ruby_llm:
|
|
119
|
-
anthropic_api_key: <%= ENV['ANTHROPIC_API_KEY'] %>
|
|
120
|
-
model: claude-sonnet-4
|
|
121
|
-
request_timeout: 120
|
|
122
|
-
max_retries: 3
|
|
123
|
-
log_level: info
|
|
124
|
-
|
|
125
|
-
template_path: prompts
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
> [!NOTE]
|
|
129
|
-
> **ERB works here, and only here.** The project config file is read through ERB,
|
|
130
|
-
> so `<%= ENV['ANTHROPIC_API_KEY'] %>` is expanded before the YAML is parsed. The
|
|
131
|
-
> user config file described below is **not** — see the warning there.
|
|
132
|
-
|
|
133
|
-
> [!WARNING]
|
|
134
|
-
> **No YAML symbols in the project config file.** It is parsed with an empty
|
|
135
|
-
> permitted-classes list, so `log_level: :info` raises
|
|
136
|
-
> `Psych::DisallowedClass: Tried to load unspecified class: Symbol` and your
|
|
137
|
-
> application fails to boot. Write the plain string `log_level: info`. (Symbols
|
|
138
|
-
> *are* permitted in the bundled `defaults.yml` and in the user config file,
|
|
139
|
-
> which is why you will see `:debug` there.)
|
|
140
|
-
|
|
141
|
-
### User Config
|
|
142
|
-
|
|
143
|
-
Create `~/.config/robot_lab/robot_lab.yml` for personal defaults that apply
|
|
144
|
-
across all your projects. Keys go at the top level here too:
|
|
145
|
-
|
|
146
|
-
```yaml title="~/.config/robot_lab/robot_lab.yml"
|
|
147
|
-
ruby_llm:
|
|
148
|
-
model: claude-sonnet-4
|
|
149
|
-
request_timeout: 120
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
> [!WARNING]
|
|
153
|
-
> **Do not put ERB in the user config file.** It is parsed with
|
|
154
|
-
> `YAML.safe_load` and never passed through ERB, so
|
|
155
|
-
> `anthropic_api_key: <%= ENV['ANTHROPIC_API_KEY'] %>` is stored as the literal
|
|
156
|
-
> nine-character-plus string `"<%= ENV['ANTHROPIC_API_KEY'] %>"` and sent to the
|
|
157
|
-
> provider as your API key. Put secrets in environment variables
|
|
158
|
-
> (`ANTHROPIC_API_KEY` or `ROBOT_LAB_RUBY_LLM__ANTHROPIC_API_KEY`), or in the
|
|
159
|
-
> project config file where ERB is evaluated.
|
|
160
|
-
|
|
161
|
-
> [!NOTE]
|
|
162
|
-
> The user config file honours **both** forms: flat keys at the root, or a
|
|
163
|
-
> top-level section named for the current environment (`development:`, `test:`,
|
|
164
|
-
> `production:`). The loader looks for the environment section first and falls back
|
|
165
|
-
> to the root. Only `defaults:` is ignored here.
|
|
166
|
-
|
|
167
|
-
## Configuration Reference
|
|
168
|
-
|
|
169
|
-
### Core Settings
|
|
170
|
-
|
|
171
|
-
| Key | Default | Description |
|
|
172
|
-
|-----|---------|-------------|
|
|
173
|
-
| `template_path` | `null` (auto-detected) | Directory for prompt templates |
|
|
174
|
-
| `mcp` | `:none` | Global MCP server configuration |
|
|
175
|
-
| `tools` | `:none` | Global tool allowlist |
|
|
176
|
-
| `sandbox.*` | see below | Skill-script confinement ceiling |
|
|
177
|
-
|
|
178
|
-
> [!WARNING]
|
|
179
|
-
> **Reserved / not implemented.** `defaults.yml` also ships `max_iterations`,
|
|
180
|
-
> `max_tool_iterations`, `streaming_enabled`, and an entire `chat:` tree
|
|
181
|
-
> (`chat.with_model`, `chat.with_temperature`, `chat.with_tools`,
|
|
182
|
-
> `chat.with_params.*`). These keys resolve — `RobotLab.config.max_iterations`
|
|
183
|
-
> returns `10` — but **nothing in the library reads them**. Setting them has zero
|
|
184
|
-
> effect. They are placeholders; do not build on them.
|
|
185
|
-
>
|
|
186
|
-
> The real equivalents are:
|
|
187
|
-
>
|
|
188
|
-
> | Dead key | Use instead |
|
|
189
|
-
> |----------|-------------|
|
|
190
|
-
> | `max_tool_iterations` | `max_tool_rounds:` on a robot or `RunConfig` |
|
|
191
|
-
> | `streaming_enabled` | `on_content:` callback, or a block passed to `run` |
|
|
192
|
-
> | `chat.with_temperature` | `temperature:` on a robot or `RunConfig` |
|
|
193
|
-
> | `chat.with_params.*` | `top_p:` / `max_tokens:` / etc. on a robot or `RunConfig` |
|
|
194
|
-
> | `max_iterations` | no equivalent — networks are bounded by their task graph |
|
|
195
|
-
|
|
196
|
-
### RubyLLM Settings (`ruby_llm:` section)
|
|
197
|
-
|
|
198
|
-
All settings under the `ruby_llm:` key are applied to `RubyLLM.configure` automatically on startup.
|
|
199
|
-
|
|
200
|
-
#### Provider API Keys
|
|
201
|
-
|
|
202
|
-
| Key | Description |
|
|
203
|
-
|-----|-------------|
|
|
204
|
-
| `ruby_llm.anthropic_api_key` | Anthropic Claude API key |
|
|
205
|
-
| `ruby_llm.openai_api_key` | OpenAI API key |
|
|
206
|
-
| `ruby_llm.gemini_api_key` | Google Gemini API key |
|
|
207
|
-
| `ruby_llm.deepseek_api_key` | DeepSeek API key |
|
|
208
|
-
| `ruby_llm.mistral_api_key` | Mistral API key |
|
|
209
|
-
| `ruby_llm.openrouter_api_key` | OpenRouter API key |
|
|
210
|
-
| `ruby_llm.bedrock_api_key` | AWS Bedrock access key |
|
|
211
|
-
| `ruby_llm.bedrock_secret_key` | AWS Bedrock secret key |
|
|
212
|
-
| `ruby_llm.bedrock_region` | AWS Bedrock region |
|
|
213
|
-
| `ruby_llm.xai_api_key` | xAI (Grok) API key |
|
|
214
|
-
|
|
215
|
-
#### Model Defaults
|
|
216
|
-
|
|
217
|
-
| Key | Default | Description |
|
|
218
|
-
|-----|---------|-------------|
|
|
219
|
-
| `ruby_llm.model` | `claude-sonnet-4` | Default model for robots that do not set `model:` |
|
|
220
|
-
| `ruby_llm.default_model` | `null` | RubyLLM default model override |
|
|
221
|
-
| `ruby_llm.default_embedding_model` | `null` | Default embedding model |
|
|
222
|
-
| `ruby_llm.default_image_model` | `null` | Default image model |
|
|
223
|
-
|
|
224
|
-
> [!NOTE]
|
|
225
|
-
> `defaults.yml` also carries `ruby_llm.provider: :anthropic` and
|
|
226
|
-
> `ruby_llm.assume_model_exists: false`, but neither is read. A robot's provider
|
|
227
|
-
> comes from its own `provider:` keyword argument, and `assume_model_exists` is
|
|
228
|
-
> derived from whether that argument was given. Model ids must be full RubyLLM
|
|
229
|
-
> ids — an unknown id raises `RubyLLM::ModelNotFoundError` when the robot is
|
|
230
|
-
> constructed.
|
|
231
|
-
|
|
232
|
-
#### Connection Settings
|
|
233
|
-
|
|
234
|
-
| Key | Default | Description |
|
|
235
|
-
|-----|---------|-------------|
|
|
236
|
-
| `ruby_llm.request_timeout` | `120` | Request timeout in seconds |
|
|
237
|
-
| `ruby_llm.max_retries` | `3` | Maximum retry attempts |
|
|
238
|
-
| `ruby_llm.retry_interval` | `1` | Seconds between retries |
|
|
239
|
-
| `ruby_llm.retry_backoff_factor` | `2` | Exponential backoff factor |
|
|
240
|
-
| `ruby_llm.http_proxy` | `null` | HTTP proxy URL |
|
|
241
|
-
|
|
242
|
-
#### Provider Endpoints (self-hosted models)
|
|
243
|
-
|
|
244
|
-
| Key | Description |
|
|
245
|
-
|-----|-------------|
|
|
246
|
-
| `ruby_llm.openai_api_base` | Custom OpenAI-compatible endpoint |
|
|
247
|
-
| `ruby_llm.gemini_api_base` | Custom Gemini endpoint |
|
|
248
|
-
| `ruby_llm.ollama_api_base` | Ollama endpoint (e.g., `http://localhost:11434`) |
|
|
249
|
-
| `ruby_llm.gpustack_api_base` | GPUStack endpoint |
|
|
250
|
-
|
|
251
|
-
#### Logging
|
|
252
|
-
|
|
253
|
-
| Key | Default | Description |
|
|
254
|
-
|-----|---------|-------------|
|
|
255
|
-
| `ruby_llm.log_file` | `null` | Path to log file |
|
|
256
|
-
| `ruby_llm.log_level` | `:info` | Log level (`:debug`, `:info`, `:warn`, `:error`) |
|
|
257
|
-
| `ruby_llm.log_stream_debug` | `false` | Log streaming debug output |
|
|
258
|
-
|
|
259
|
-
### Chat Configuration (`chat:` section) — not implemented
|
|
260
|
-
|
|
261
|
-
The `chat:` tree in `defaults.yml` (`chat.with_temperature`,
|
|
262
|
-
`chat.with_params.top_p`, `chat.with_params.max_tokens`, `chat.with_tools`, …)
|
|
263
|
-
is **reserved and has no consumers**. Values set there are parsed and then
|
|
264
|
-
ignored.
|
|
265
|
-
|
|
266
|
-
To set LLM parameters globally, pass a `RunConfig` to each robot, or set them per
|
|
267
|
-
robot with constructor keyword arguments:
|
|
268
|
-
|
|
269
|
-
```ruby
|
|
270
|
-
robot = RobotLab.build(
|
|
271
|
-
name: "bot",
|
|
272
|
-
system_prompt: "You are helpful.",
|
|
273
|
-
temperature: 0.7,
|
|
274
|
-
max_tokens: 2000,
|
|
275
|
-
top_p: 0.9
|
|
276
|
-
)
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
### Skill-Script Sandboxing (`sandbox:` section)
|
|
280
|
-
|
|
281
|
-
Core declares this config schema but has no sandboxing behavior of its own — enforcement
|
|
282
|
-
lives in the optional [`robot_lab-sandbox`](https://github.com/MadBomber/robot_lab-sandbox)
|
|
283
|
-
gem. Without it, skill scripts always run unconfined regardless of these values; requiring
|
|
284
|
-
it installs a `RobotLab::ScriptTool.executor` that honors them:
|
|
285
|
-
|
|
286
|
-
| Key | Default | Description |
|
|
287
|
-
|-----|---------|-------------|
|
|
288
|
-
| `sandbox.enabled` | `false` | Turn on OS-level confinement for skill scripts |
|
|
289
|
-
| `sandbox.fs_read` | `["."]` | Ceiling: paths any skill script may read (relative to cwd) |
|
|
290
|
-
| `sandbox.fs_write` | `[]` | Ceiling: paths any skill script may write |
|
|
291
|
-
| `sandbox.network` | `false` | Ceiling: whether any skill script may use the network |
|
|
292
|
-
| `sandbox.timeout` | `60` | Ceiling: max seconds a skill script may run |
|
|
293
|
-
|
|
294
|
-
These are a **ceiling**, not a grant — the actual permissions a script runs with are the intersection of this ceiling and what the individual SKILL.md declares for itself. See [Skill Scripts and Sandboxing](../guides/using-tools.md#skill-scripts-and-sandboxing) for how the two combine and which platforms actually enforce confinement.
|
|
295
|
-
|
|
296
|
-
## Runtime-Only Attributes
|
|
297
|
-
|
|
298
|
-
Some attributes can only be set at runtime, not through config files. Use direct assignment on `RobotLab.config` or the `RobotLab.configure` block:
|
|
299
|
-
|
|
300
|
-
```ruby
|
|
301
|
-
# Direct assignment
|
|
302
|
-
RobotLab.config.logger = Logger.new(nil) # silence logging
|
|
303
|
-
RobotLab.config.logger = Logger.new("robot.log") # log to file
|
|
304
|
-
|
|
305
|
-
# Block-style configure (equivalent, useful when setting multiple values)
|
|
306
|
-
RobotLab.configure do |c|
|
|
307
|
-
c.logger = Logger.new(File::NULL)
|
|
308
|
-
end
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
`RobotLab.configure` yields the same `Config` object returned by `RobotLab.config`.
|
|
312
|
-
|
|
313
|
-
## Reloading Configuration
|
|
314
|
-
|
|
315
|
-
To reload configuration from all sources:
|
|
316
|
-
|
|
317
|
-
```ruby
|
|
318
|
-
RobotLab.reload_config!
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
This clears the cached config and reloads from all sources on next access.
|
|
322
|
-
|
|
323
|
-
## Environment-Specific Configuration
|
|
324
|
-
|
|
325
|
-
The `defaults.yml` shipped with RobotLab includes environment-specific overrides.
|
|
326
|
-
This is what the gem actually ships:
|
|
327
|
-
|
|
328
|
-
=== "Development"
|
|
329
|
-
|
|
330
|
-
```yaml
|
|
331
|
-
development:
|
|
332
|
-
ruby_llm:
|
|
333
|
-
log_level: :debug
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
=== "Test"
|
|
337
|
-
|
|
338
|
-
```yaml
|
|
339
|
-
test:
|
|
340
|
-
max_iterations: 3 # reserved, no effect
|
|
341
|
-
streaming_enabled: false # reserved, no effect
|
|
342
|
-
ruby_llm:
|
|
343
|
-
model: claude-3-haiku-20240307
|
|
344
|
-
request_timeout: 30
|
|
345
|
-
max_retries: 1
|
|
346
|
-
log_level: :warn
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
=== "Production"
|
|
350
|
-
|
|
351
|
-
```yaml
|
|
352
|
-
production:
|
|
353
|
-
streaming_enabled: false # reserved, no effect
|
|
354
|
-
max_iterations: 20 # reserved, no effect
|
|
355
|
-
ruby_llm:
|
|
356
|
-
request_timeout: 180
|
|
357
|
-
max_retries: 5
|
|
358
|
-
log_level: :warn
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
The current environment is determined automatically (via `RAILS_ENV`, `RACK_ENV`, or defaults to `development`).
|
|
362
|
-
|
|
363
|
-
> [!NOTE]
|
|
364
|
-
> Under `test`, the effective default model is `claude-3-haiku-20240307` — a full
|
|
365
|
-
> dated model id. Short aliases like `claude-haiku-3-5` are **not** valid RubyLLM
|
|
366
|
-
> model ids and raise `RubyLLM::ModelNotFoundError` at robot construction.
|
|
367
|
-
|
|
368
|
-
## Rails Integration
|
|
369
|
-
|
|
370
|
-
> [!NOTE]
|
|
371
|
-
> Core RobotLab ships **no Railtie and no Engine**. It performs two bare
|
|
372
|
-
> `defined?(::Rails)` checks: the default logger becomes `Rails.logger`, and
|
|
373
|
-
> `template_path` resolves to `Rails.root/app/prompts` when left unset. Generators,
|
|
374
|
-
> `RobotLab::Job`, and Turbo broadcasting live in the separate
|
|
375
|
-
> [robot_lab-rails](https://github.com/MadBomber/robot_lab-rails) gem.
|
|
376
|
-
|
|
377
|
-
> [!WARNING]
|
|
378
|
-
> **Under Rails, `./config/robot_lab.yml` must be environment-sectioned — a flat
|
|
379
|
-
> file is ignored.** Rails' anyway_config integration sets
|
|
380
|
-
> `Anyway::Settings.current_environment` to `Rails.env`, which switches the project
|
|
381
|
-
> config loader into environmental mode. Keys then have to live under
|
|
382
|
-
> `development:` / `test:` / `production:`; anything written at the root of the file
|
|
383
|
-
> is dropped. Outside Rails the rule is exactly inverted — flat keys are read and an
|
|
384
|
-
> environment section is ignored.
|
|
385
|
-
|
|
386
|
-
```yaml title="config/robot_lab.yml (under Rails)"
|
|
387
|
-
development:
|
|
388
|
-
ruby_llm:
|
|
389
|
-
anthropic_api_key: <%= Rails.application.credentials.anthropic_api_key %>
|
|
390
|
-
model: claude-sonnet-4
|
|
391
|
-
request_timeout: 180
|
|
392
|
-
max_retries: 5
|
|
393
|
-
template_path: null # auto-detects app/prompts in Rails
|
|
394
|
-
|
|
395
|
-
production:
|
|
396
|
-
ruby_llm:
|
|
397
|
-
anthropic_api_key: <%= Rails.application.credentials.anthropic_api_key %>
|
|
398
|
-
model: claude-sonnet-4
|
|
399
|
-
request_timeout: 180
|
|
400
|
-
max_retries: 5
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
The same file outside Rails would instead be written flat:
|
|
404
|
-
|
|
405
|
-
```yaml title="config/robot_lab.yml (no Rails)"
|
|
406
|
-
ruby_llm:
|
|
407
|
-
model: claude-sonnet-4
|
|
408
|
-
request_timeout: 180
|
|
409
|
-
|
|
410
|
-
template_path: prompts
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
You can also use Rails credentials:
|
|
414
|
-
|
|
415
|
-
```bash
|
|
416
|
-
rails credentials:edit
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
```yaml
|
|
420
|
-
# config/credentials.yml.enc
|
|
421
|
-
anthropic_api_key: sk-ant-...
|
|
422
|
-
openai_api_key: sk-...
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
`./config/robot_lab.yml` is evaluated through ERB, so credentials can be
|
|
426
|
-
referenced inline as shown above. Note that this only works in the **project**
|
|
427
|
-
config file — the `~/.config/robot_lab/robot_lab.yml` user file is not run
|
|
428
|
-
through ERB.
|
|
429
|
-
|
|
430
|
-
## RunConfig: Shared Operational Defaults
|
|
431
|
-
|
|
432
|
-
`RunConfig` is a configuration object that lets you express operational defaults for LLM settings, tools, callbacks, and infrastructure. Unlike `RobotLab.config` (which is global and static), RunConfig flows through the hierarchy and can be customized at each level:
|
|
433
|
-
|
|
434
|
-
```
|
|
435
|
-
RobotLab.config (global) -> Network RunConfig -> Robot RunConfig -> Template front matter -> Task RunConfig -> Runtime
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
### Creating a RunConfig
|
|
439
|
-
|
|
440
|
-
```ruby
|
|
441
|
-
# Keyword construction
|
|
442
|
-
config = RobotLab::RunConfig.new(model: "claude-sonnet-4", temperature: 0.7)
|
|
443
|
-
|
|
444
|
-
# Block DSL
|
|
445
|
-
config = RobotLab::RunConfig.new do |c|
|
|
446
|
-
c.model "claude-sonnet-4"
|
|
447
|
-
c.temperature 0.7
|
|
448
|
-
c.max_tokens 2000
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
# Chaining
|
|
452
|
-
config = RobotLab::RunConfig.new
|
|
453
|
-
.model("claude-sonnet-4")
|
|
454
|
-
.temperature(0.7)
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
### Applying RunConfig
|
|
458
|
-
|
|
459
|
-
Pass `config:` to robots and networks. Explicit constructor kwargs always override the RunConfig:
|
|
460
|
-
|
|
461
|
-
```ruby
|
|
462
|
-
# Shared config for a team of robots
|
|
463
|
-
shared = RobotLab::RunConfig.new(model: "claude-sonnet-4", temperature: 0.5)
|
|
464
|
-
|
|
465
|
-
# Robot uses shared config
|
|
466
|
-
robot = RobotLab.build(
|
|
467
|
-
name: "writer",
|
|
468
|
-
system_prompt: "You are a creative writer.",
|
|
469
|
-
config: shared,
|
|
470
|
-
temperature: 0.9 # overrides shared config's 0.5
|
|
471
|
-
)
|
|
472
|
-
|
|
473
|
-
# Network-level config
|
|
474
|
-
network = RobotLab.create_network(name: "pipeline", config: shared) do
|
|
475
|
-
task :analyzer, analyzer_robot, depends_on: :none
|
|
476
|
-
task :writer, writer_robot, depends_on: [:analyzer]
|
|
477
|
-
end
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
> [!WARNING]
|
|
481
|
-
> **A network-level `config:` propagates only `mcp` and `tools`** — and only when
|
|
482
|
-
> the member robot opts in by passing `mcp: :inherit` / `tools: :inherit` on its
|
|
483
|
-
> `run`. LLM fields (`model`, `temperature`, `max_tokens`, …) and callbacks
|
|
484
|
-
> (`on_content`, `on_tool_call`, `on_tool_result`) are read from each robot's
|
|
485
|
-
> **own** config at construction time and are never inherited from the network.
|
|
486
|
-
> The only field the network itself consumes is `max_concurrent_robots`.
|
|
487
|
-
>
|
|
488
|
-
> If you want a whole team on one model, pass the same `config:` to each robot:
|
|
489
|
-
>
|
|
490
|
-
> ```ruby
|
|
491
|
-
> shared = RobotLab::RunConfig.new(model: "claude-sonnet-4", temperature: 0.5)
|
|
492
|
-
> analyst = RobotLab.build(name: "analyst", system_prompt: "...", config: shared)
|
|
493
|
-
> writer = RobotLab.build(name: "writer", system_prompt: "...", config: shared)
|
|
494
|
-
> ```
|
|
495
|
-
>
|
|
496
|
-
> A per-task `config:` is merged into the network config and is subject to the
|
|
497
|
-
> same `mcp`/`tools`-only limitation.
|
|
498
|
-
|
|
499
|
-
### Merging Configs
|
|
500
|
-
|
|
501
|
-
RunConfig supports merge semantics where the more-specific config's values win:
|
|
502
|
-
|
|
503
|
-
```ruby
|
|
504
|
-
network_config = RobotLab::RunConfig.new(model: "claude-sonnet-4", temperature: 0.5)
|
|
505
|
-
robot_config = RobotLab::RunConfig.new(temperature: 0.9)
|
|
506
|
-
effective = network_config.merge(robot_config)
|
|
507
|
-
effective.model #=> "claude-sonnet-4" (inherited)
|
|
508
|
-
effective.temperature #=> 0.9 (overridden)
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
### Available Fields
|
|
512
|
-
|
|
513
|
-
| Category | Fields |
|
|
514
|
-
|----------|--------|
|
|
515
|
-
| **LLM** | `model`, `temperature`, `top_p`, `top_k`, `max_tokens`, `presence_penalty`, `frequency_penalty`, `stop` |
|
|
516
|
-
| **Tools** | `mcp`, `tools` |
|
|
517
|
-
| **Callbacks** | `on_tool_call`, `on_tool_result`, `on_content` |
|
|
518
|
-
| **Infrastructure** | `bus`, `enable_cache`, `max_tool_rounds`, `token_budget`, `cost_budget`, `max_tools`, `ractor_pool_size`, `max_concurrent_robots`, `doom_loop_threshold`, `auto_compact`, `compact_threshold` |
|
|
519
|
-
|
|
520
|
-
`cost_budget` mirrors `token_budget` for cumulative dollar spend — see [Budgets](../guides/observability.md#budgets-token-cost). `max_tools` overrides the default 128-tool ceiling enforced on every turn before tools are handed to the provider — see [Tool Capping](../guides/using-tools.md#tool-capping-and-per-turn-filtering).
|
|
521
|
-
|
|
522
|
-
### RunConfig vs RobotLab.config
|
|
523
|
-
|
|
524
|
-
| | `RobotLab.config` | `RunConfig` |
|
|
525
|
-
|---|---|---|
|
|
526
|
-
| **Scope** | Global (all robots) | Per-network, per-robot, or per-task |
|
|
527
|
-
| **Source** | YAML files, env vars | Code (constructor, block DSL) |
|
|
528
|
-
| **Mutability** | Loaded once, rarely changed | Created per use case, merged |
|
|
529
|
-
| **Purpose** | API keys, timeouts, defaults | Model, temperature, tools per workflow |
|
|
530
|
-
|
|
531
|
-
## Robot-Level Configuration
|
|
532
|
-
|
|
533
|
-
Individual robots can override the global model and other settings:
|
|
534
|
-
|
|
535
|
-
```ruby
|
|
536
|
-
# Override model for a specific robot
|
|
537
|
-
robot = RobotLab.build(
|
|
538
|
-
name: "fast_bot",
|
|
539
|
-
system_prompt: "You are a quick responder.",
|
|
540
|
-
model: "claude-3-haiku-20240307",
|
|
541
|
-
temperature: 0.3,
|
|
542
|
-
max_tokens: 500
|
|
543
|
-
)
|
|
544
|
-
|
|
545
|
-
# Or use chaining at runtime
|
|
546
|
-
robot.with_temperature(0.9).with_params(max_tokens: 2000).run("Tell me a story.")
|
|
547
|
-
```
|
|
548
|
-
|
|
549
|
-
> [!WARNING]
|
|
550
|
-
> There is **no `with_max_tokens`, `with_top_p`, `with_top_k`, `with_stop`,
|
|
551
|
-
> `with_presence_penalty`, or `with_frequency_penalty`** — calling them raises
|
|
552
|
-
> `NoMethodError`. The complete chainable set is `with_context`, `with_headers`,
|
|
553
|
-
> `with_instructions`, `with_model`, `with_params`, `with_schema`,
|
|
554
|
-
> `with_temperature`, `with_thinking`, `with_tool`, `with_tools`, plus RobotLab's
|
|
555
|
-
> own `with_template` and `with_bus`. For everything else use a constructor
|
|
556
|
-
> keyword argument or `with_params(...)`.
|
|
557
|
-
|
|
558
|
-
## Hierarchical MCP and Tools
|
|
559
|
-
|
|
560
|
-
MCP servers and tools use a hierarchical configuration: `runtime > robot > network > global`. Each level can specify:
|
|
561
|
-
|
|
562
|
-
- `:inherit` -- Use the parent level's configuration
|
|
563
|
-
- `:none` -- No MCP servers or tools at this level
|
|
564
|
-
- An explicit array -- A name **allowlist** (not a local-vs-MCP switch). Entries are
|
|
565
|
-
compared as strings against each attached tool's `name`, so they must match the
|
|
566
|
-
form the tool was attached in: a tool attached as a class matches `[RefundTool]`
|
|
567
|
-
or `%w[RefundTool]`, while one attached as an instance matches `%w[refund]`
|
|
568
|
-
|
|
569
|
-
> [!WARNING]
|
|
570
|
-
> **`tools:` and `mcp:` both default to `:none` — including on `run()` itself.**
|
|
571
|
-
> `Robot#run` is declared `run(message = nil, ..., mcp: :none, tools: :none, ...)`,
|
|
572
|
-
> and an explicit `:none` means "send zero tools this turn". So a plain
|
|
573
|
-
> `robot.run("...")` sends the LLM **no tools and connects no MCP servers**, even
|
|
574
|
-
> when you passed `local_tools:` or `mcp:` at build time.
|
|
575
|
-
>
|
|
576
|
-
> The fix goes on the **run**, not the build:
|
|
577
|
-
>
|
|
578
|
-
> ```ruby
|
|
579
|
-
> robot.run("...", tools: :inherit) # send the attached local tools
|
|
580
|
-
> robot.run("...", mcp: :inherit, tools: :inherit) # connect MCP and send its tools
|
|
581
|
-
> ```
|
|
582
|
-
>
|
|
583
|
-
> `mcp: :inherit` triggers the connection; `tools: :inherit` is additionally
|
|
584
|
-
> required for the MCP tools to actually be handed to the model.
|
|
585
|
-
|
|
586
|
-
> [!IMPORTANT]
|
|
587
|
-
> **For a standalone robot, do not pass `tools: :inherit` at build time.** Build-time
|
|
588
|
-
> `:inherit` resolves against the parent level, and for a standalone robot the parent
|
|
589
|
-
> is the global `:none` — producing an allowlist of `["none"]` that matches nothing
|
|
590
|
-
> and suppresses the tools even when the run asks for `:inherit`. Verified
|
|
591
|
-
> resolution for a standalone robot:
|
|
592
|
-
>
|
|
593
|
-
> | build `tools:` | run `tools:` | tools sent |
|
|
594
|
-
> |---|---|---|
|
|
595
|
-
> | unset | `:none` (default) | none |
|
|
596
|
-
> | unset | `:inherit` | the attached tools ✅ |
|
|
597
|
-
> | `:inherit` | `:inherit` | **none** ❌ |
|
|
598
|
-
> | `:inherit` | `:none` | none |
|
|
599
|
-
> | `:none` | `:inherit` | the attached tools ✅ |
|
|
600
|
-
>
|
|
601
|
-
> Leave `tools:` unset at build time — unless the robot is a member of a network.
|
|
602
|
-
|
|
603
|
-
> [!NOTE]
|
|
604
|
-
> **Inside a network, build-time `:inherit` is the opt-in, not a bug.** The parent
|
|
605
|
-
> is resolved at run time as the network's `config:`, so `:inherit` is how a robot
|
|
606
|
-
> asks for the network-level allowlist. With
|
|
607
|
-
> `RobotLab::RunConfig.new(tools: %w[RefundTool])` on the network and a robot
|
|
608
|
-
> holding `local_tools: [RefundTool, InvoiceTool]`:
|
|
609
|
-
>
|
|
610
|
-
> | build `tools:` | task `tools:` | tools sent |
|
|
611
|
-
> |---|---|---|
|
|
612
|
-
> | unset | omitted (`:none`) | none |
|
|
613
|
-
> | unset | `:inherit` | `refund`, `invoice` — the network allowlist is **not** applied |
|
|
614
|
-
> | `:inherit` | `:inherit` | `refund` — the network allowlist **is** applied ✅ |
|
|
615
|
-
> | `:inherit` | omitted (`:none`) | none |
|
|
616
|
-
>
|
|
617
|
-
> The same reasoning applies to `mcp:`.
|
|
618
|
-
|
|
619
|
-
```ruby
|
|
620
|
-
# Correct: attach tools at build time, request them at run time
|
|
621
|
-
robot = RobotLab.build(
|
|
622
|
-
name: "calculator",
|
|
623
|
-
system_prompt: "You solve math problems.",
|
|
624
|
-
local_tools: [Calculator]
|
|
625
|
-
)
|
|
626
|
-
|
|
627
|
-
robot.run("What is 17 * 23?", tools: :inherit)
|
|
628
|
-
|
|
629
|
-
# Robot with MCP servers attached at build time
|
|
630
|
-
robot = RobotLab.build(
|
|
631
|
-
name: "agent",
|
|
632
|
-
system_prompt: "You are helpful.",
|
|
633
|
-
mcp: [{ name: "filesystem", transport: { type: "stdio", command: "mcp-server-filesystem" } }]
|
|
634
|
-
)
|
|
635
|
-
|
|
636
|
-
robot.run("List the files in ./lib", mcp: :inherit, tools: :inherit)
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
See [Runtime Tool Filtering](../guides/using-tools.md#runtime-tool-filtering) for the full `:inherit`/`:none`/array semantics.
|
|
640
|
-
|
|
641
|
-
## Next Steps
|
|
642
|
-
|
|
643
|
-
- [Building Robots](../guides/building-robots.md) - Create custom robots
|
|
644
|
-
- [Creating Networks](../guides/creating-networks.md) - Network configuration
|
|
645
|
-
- [MCP Integration](../guides/mcp-integration.md) - Configure MCP servers
|
|
@@ -1,56 +0,0 @@
|
|
|
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.2+** 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)
|