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