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
data/docs/api/errors.md
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
# Error Reference
|
|
2
|
-
|
|
3
|
-
All RobotLab exceptions inherit from `RobotLab::Error`, which inherits from `StandardError`. Rescue `RobotLab::Error` to catch any framework exception in one clause, or rescue specific subclasses for targeted handling.
|
|
4
|
-
|
|
5
|
-
## Hierarchy
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
StandardError
|
|
9
|
-
└── RobotLab::Error
|
|
10
|
-
├── RobotLab::ConfigurationError
|
|
11
|
-
│ └── RobotLab::DependencyError
|
|
12
|
-
├── RobotLab::InferenceError
|
|
13
|
-
│ └── RobotLab::ToolLoopError
|
|
14
|
-
├── RobotLab::ToolNotFoundError
|
|
15
|
-
├── RobotLab::MCPError
|
|
16
|
-
├── RobotLab::BusError
|
|
17
|
-
├── RobotLab::RactorBoundaryError
|
|
18
|
-
├── RobotLab::ToolError
|
|
19
|
-
├── RobotLab::BudgetExceeded
|
|
20
|
-
└── RobotLab::AwaitTimeout
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
`AwaitTimeout` is defined in `lib/robot_lab/memory.rb` and raised by
|
|
24
|
-
[`Memory#get`](core/memory.md#get) when a blocking read expires.
|
|
25
|
-
|
|
26
|
-
Additionally, `DelegationFuture` defines its own scoped error:
|
|
27
|
-
|
|
28
|
-
```
|
|
29
|
-
StandardError
|
|
30
|
-
└── RobotLab::Error
|
|
31
|
-
└── RobotLab::DelegationFuture::DelegationTimeout
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## RobotLab::Error
|
|
37
|
-
|
|
38
|
-
Base class for all RobotLab errors. Rescue this to catch any framework exception.
|
|
39
|
-
|
|
40
|
-
```ruby
|
|
41
|
-
begin
|
|
42
|
-
robot.run("hello")
|
|
43
|
-
rescue RobotLab::Error => e
|
|
44
|
-
puts "RobotLab error: #{e.message}"
|
|
45
|
-
end
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
## RobotLab::ConfigurationError
|
|
51
|
-
|
|
52
|
-
Raised when configuration is invalid or missing required values.
|
|
53
|
-
|
|
54
|
-
```ruby
|
|
55
|
-
# Example: missing API key, invalid template path
|
|
56
|
-
begin
|
|
57
|
-
robot.run("hello")
|
|
58
|
-
rescue RobotLab::ConfigurationError => e
|
|
59
|
-
puts "Bad config: #{e.message}"
|
|
60
|
-
end
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## RobotLab::DependencyError < ConfigurationError
|
|
66
|
-
|
|
67
|
-
Raised when a required optional gem dependency is not installed. There are three
|
|
68
|
-
distinct raise sites in core, each with its own message:
|
|
69
|
-
|
|
70
|
-
| Raised by | Missing dependency | Message |
|
|
71
|
-
|-----------|--------------------|---------|
|
|
72
|
-
| `TextAnalysis.require_classifier!` — reached from `Convergence`, `HistoryCompressor`, `Robot#compress_history`, `Robot#search_history` | `classifier` gem | `The 'classifier' gem is required for text analysis features. Add it to your Gemfile: gem 'classifier', '~> 2.3'` |
|
|
73
|
-
| `Memory`'s document-store methods (`store_document`, `search_documents`, `document_keys`, `delete_document`) | `robot_lab-document_store` gem | `document storage requires the robot_lab-document_store gem. Add \`gem 'robot_lab-document_store'\` to your Gemfile.` |
|
|
74
|
-
| `Network#run` under `parallel_mode: :ractor` | `robot_lab-ractor` gem | `parallel_mode: :ractor requires the robot_lab-ractor gem. Add \`gem 'robot_lab-ractor'\` to your Gemfile.` |
|
|
75
|
-
|
|
76
|
-
```ruby
|
|
77
|
-
begin
|
|
78
|
-
robot.compress_history
|
|
79
|
-
rescue RobotLab::DependencyError => e
|
|
80
|
-
warn e.message
|
|
81
|
-
end
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Two places swallow it rather than propagate: `auto_compact: :context_window`
|
|
85
|
-
logs the message at `:warn` and skips compaction, and
|
|
86
|
-
`MCP::ServerDiscovery` rescues it and falls back.
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## RobotLab::InferenceError
|
|
91
|
-
|
|
92
|
-
Raised when LLM inference fails (API errors, timeouts, rate limits).
|
|
93
|
-
|
|
94
|
-
```ruby
|
|
95
|
-
begin
|
|
96
|
-
robot.run("hello")
|
|
97
|
-
rescue RobotLab::InferenceError => e
|
|
98
|
-
puts "LLM call failed: #{e.message}"
|
|
99
|
-
end
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## RobotLab::ToolLoopError < InferenceError
|
|
105
|
-
|
|
106
|
-
Raised when a robot's tool call count exceeds `max_tool_rounds:`. The chat history will contain a dangling `tool_use` block with no matching `tool_result`; call `robot.clear_messages` before reusing the robot.
|
|
107
|
-
|
|
108
|
-
```ruby
|
|
109
|
-
robot = RobotLab.build(
|
|
110
|
-
name: "runner",
|
|
111
|
-
system_prompt: "Execute every step.",
|
|
112
|
-
local_tools: [StepTool],
|
|
113
|
-
max_tool_rounds: 10
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
begin
|
|
117
|
-
robot.run("Run all steps.", tools: :inherit)
|
|
118
|
-
rescue RobotLab::ToolLoopError => e
|
|
119
|
-
puts e.message
|
|
120
|
-
# "Circuit breaker triggered: 11 tool calls exceeded max_tool_rounds (10)"
|
|
121
|
-
robot.clear_messages # required before reuse
|
|
122
|
-
end
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
The message format is:
|
|
126
|
-
|
|
127
|
-
```
|
|
128
|
-
Circuit breaker triggered: <N> tool calls exceeded max_tool_rounds (<M>)
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
`N` is the call count that tripped the breaker (always `M + 1`); `M` is the configured limit.
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
## RobotLab::ToolNotFoundError
|
|
136
|
-
|
|
137
|
-
Raised when a tool name is referenced but cannot be found in the `ToolManifest`.
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## RobotLab::MCPError
|
|
142
|
-
|
|
143
|
-
Raised when MCP server communication fails (connection refused, timeout, protocol error).
|
|
144
|
-
|
|
145
|
-
```ruby
|
|
146
|
-
begin
|
|
147
|
-
robot.run("hello", mcp: :inherit, tools: :inherit)
|
|
148
|
-
rescue RobotLab::MCPError => e
|
|
149
|
-
puts "MCP failed: #{e.message}"
|
|
150
|
-
end
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
`MCPError.new(message, retryable: true)` marks a specific instance as safe to retry (see [Retryable Errors](#retryable-errors) below). The connection-lost and timeout errors raised internally by `MCP::ConnectionPoller` are always constructed with `retryable: true`.
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
## RobotLab::BusError
|
|
158
|
-
|
|
159
|
-
Raised when message bus communication fails (no bus configured, channel not found).
|
|
160
|
-
|
|
161
|
-
```ruby
|
|
162
|
-
begin
|
|
163
|
-
robot.send_message(to: :bob, content: "hi")
|
|
164
|
-
rescue RobotLab::BusError => e
|
|
165
|
-
puts "Bus error: #{e.message}"
|
|
166
|
-
end
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
---
|
|
170
|
-
|
|
171
|
-
## RobotLab::RactorBoundaryError
|
|
172
|
-
|
|
173
|
-
Raised when a value cannot be made Ractor-shareable before crossing a Ractor boundary (e.g., a live `IO` object, a `Proc`, or an object with mutable state).
|
|
174
|
-
|
|
175
|
-
!!! note "The error class is core; the machinery that raises it is not"
|
|
176
|
-
`RobotLab::RactorBoundaryError` is defined in core
|
|
177
|
-
(`lib/robot_lab/error.rb`) so hosts can rescue it without loading anything
|
|
178
|
-
extra. But `RactorBoundary`, `RactorWorkerPool`, and `RactorMemoryProxy` are
|
|
179
|
-
**not defined in core** — they ship in the separate **`robot_lab-ractor`**
|
|
180
|
-
gem. Core only *references* `RactorBoundary.freeze_deep` from
|
|
181
|
-
`Network#build_robot_spec`, which is reachable only under
|
|
182
|
-
`parallel_mode: :ractor`, which itself raises `DependencyError` unless that
|
|
183
|
-
gem is loaded.
|
|
184
|
-
|
|
185
|
-
```ruby
|
|
186
|
-
require "robot_lab"
|
|
187
|
-
require "robot_lab/ractor" # provides RactorBoundary and the worker pool
|
|
188
|
-
|
|
189
|
-
begin
|
|
190
|
-
RobotLab::RactorBoundary.freeze_deep({ io: StringIO.new })
|
|
191
|
-
rescue RobotLab::RactorBoundaryError => e
|
|
192
|
-
puts e.message
|
|
193
|
-
end
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## RobotLab::ToolError
|
|
199
|
-
|
|
200
|
-
An opt-in error type for tool failures. Core raises it nowhere itself — you raise
|
|
201
|
-
it from your own `execute`, and the `robot_lab-ractor` worker pool raises it when
|
|
202
|
-
unwrapping a failure that happened inside a Ractor.
|
|
203
|
-
|
|
204
|
-
`ToolError.new(message, retryable: true)` marks a specific instance as retryable.
|
|
205
|
-
|
|
206
|
-
When a tool raises inside `Tool#call`, the error is caught and returned to the
|
|
207
|
-
LLM as text rather than propagating (unless the class sets
|
|
208
|
-
`self.raise_on_error = true`). RobotLab appends `" (retryable)"` whenever
|
|
209
|
-
`RobotLab::Errors.retryable?(error)` is true, so the model itself can see that
|
|
210
|
-
another attempt is worth trying:
|
|
211
|
-
|
|
212
|
-
```ruby
|
|
213
|
-
class Fetch < RobotLab::Tool
|
|
214
|
-
description "Fetch a record"
|
|
215
|
-
param :id, type: "string", desc: "record id"
|
|
216
|
-
|
|
217
|
-
def execute(id:)
|
|
218
|
-
raise RobotLab::ToolError.new("upstream unavailable", retryable: true)
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
Fetch.new.call({ "id" => "1" })
|
|
223
|
-
# => "Error (fetch): upstream unavailable (retryable)"
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
Unlike the generic `StandardError` path, the `ToolError` path writes **nothing**
|
|
227
|
-
to the logger. See [Tool#call](core/tool.md#call).
|
|
228
|
-
|
|
229
|
-
---
|
|
230
|
-
|
|
231
|
-
## RobotLab::BudgetExceeded
|
|
232
|
-
|
|
233
|
-
Raised when a Robot's configured `token_budget` or `cost_budget` is already exhausted **before** an LLM call is attempted (see [Budgets](../guides/observability.md#budgets-token-cost) and `RobotLab::Budget::Ledger`). This is distinct from the pre-existing `InferenceError` "Token budget exceeded" message, which covers a call that *completed* but pushed cumulative usage over budget — `BudgetExceeded` means the call was refused outright, before any tokens were spent.
|
|
234
|
-
|
|
235
|
-
```ruby
|
|
236
|
-
robot = RobotLab.build(name: "capped", system_prompt: "...", cost_budget: 0.50)
|
|
237
|
-
|
|
238
|
-
begin
|
|
239
|
-
robot.run("Do the expensive thing")
|
|
240
|
-
rescue RobotLab::BudgetExceeded => e
|
|
241
|
-
puts e.message # "budget exceeded for cost: 0.62 > 0.5"
|
|
242
|
-
end
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
Raised by `Budget::Ledger#reserve!`; the message format is
|
|
246
|
-
`"budget exceeded for <dimension>: <committed + amount> > <limit>"` where
|
|
247
|
-
`<dimension>` is `tokens` or `cost`.
|
|
248
|
-
|
|
249
|
-
The post-call `InferenceError` messages are formatted differently:
|
|
250
|
-
|
|
251
|
-
| Dimension | Message |
|
|
252
|
-
|-----------|---------|
|
|
253
|
-
| `token_budget` | `Token budget exceeded: <N> tokens used, budget is <M>` |
|
|
254
|
-
| `cost_budget` | `Cost budget exceeded: $0.523100 used, budget is $0.500000` (both values via `%.6f`) |
|
|
255
|
-
|
|
256
|
-
---
|
|
257
|
-
|
|
258
|
-
## RobotLab::AwaitTimeout
|
|
259
|
-
|
|
260
|
-
Raised by [`Memory#get`](core/memory.md#get) when a blocking read
|
|
261
|
-
(`wait: true` or `wait: <seconds>`) expires before the key is written.
|
|
262
|
-
|
|
263
|
-
```ruby
|
|
264
|
-
begin
|
|
265
|
-
memory.get(:sentiment, wait: 30)
|
|
266
|
-
rescue RobotLab::AwaitTimeout => e
|
|
267
|
-
puts e.message # "Timeout waiting for :sentiment after 30 seconds"
|
|
268
|
-
end
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
With multiple keys the timeout is applied **per missing key**, so
|
|
272
|
-
`get(:a, :b, wait: 30)` can block for up to 60 seconds before raising.
|
|
273
|
-
|
|
274
|
-
Not retryable per `RobotLab::Errors.retryable?` — it falls into the
|
|
275
|
-
"everything else" bucket.
|
|
276
|
-
|
|
277
|
-
---
|
|
278
|
-
|
|
279
|
-
## Retryable Errors
|
|
280
|
-
|
|
281
|
-
`RobotLab::Errors.retryable?(error)` classifies whether a host (an ActiveJob `retry_on` list, `robot_lab-to`'s takeover loop, a custom retry wrapper) should retry the operation that raised `error`:
|
|
282
|
-
|
|
283
|
-
| Error | Retryable? |
|
|
284
|
-
|-------|------------|
|
|
285
|
-
| `InferenceError` (and subclasses, except `ToolLoopError`) | Always |
|
|
286
|
-
| `ToolLoopError` | Never — it's a circuit breaker; retrying immediately re-triggers the same loop |
|
|
287
|
-
| `MCPError` / `ToolError` | Only when raised with `retryable: true` at the raise site |
|
|
288
|
-
| Everything else (`ConfigurationError`, `ToolNotFoundError`, `DependencyError`, `RactorBoundaryError`, `BusError`, `BudgetExceeded`, `AwaitTimeout`, `DelegationTimeout`, non-RobotLab errors) | Never |
|
|
289
|
-
|
|
290
|
-
```ruby
|
|
291
|
-
begin
|
|
292
|
-
robot.run(task)
|
|
293
|
-
rescue RobotLab::Error => e
|
|
294
|
-
retry if RobotLab::Errors.retryable?(e)
|
|
295
|
-
raise
|
|
296
|
-
end
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
`RobotLab::Errors.retryable_classes` returns `[RobotLab::InferenceError]` — an always-retryable allow-list for explicit ActiveJob-style `retry_on` declarations. It excludes `MCPError`/`ToolError` because their retryability is per-raise (via `retryable:`), not per-class.
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
|
-
## RobotLab::DelegationFuture::DelegationTimeout
|
|
304
|
-
|
|
305
|
-
Raised by `DelegationFuture#value(timeout: N)` when the delegated task does not complete within `N` seconds.
|
|
306
|
-
|
|
307
|
-
```ruby
|
|
308
|
-
future = manager.delegate(to: analyst, task: "...", async: true)
|
|
309
|
-
|
|
310
|
-
begin
|
|
311
|
-
result = future.value(timeout: 10)
|
|
312
|
-
rescue RobotLab::DelegationFuture::DelegationTimeout => e
|
|
313
|
-
puts e.message # "Delegation to 'analyst' timed out after 10s"
|
|
314
|
-
end
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
---
|
|
318
|
-
|
|
319
|
-
## Related
|
|
320
|
-
|
|
321
|
-
- [Building Robots](../guides/building-robots.md) — Tool loop circuit breaker, delegation
|
|
322
|
-
- [Observability & Safety](../guides/observability.md) — circuit breaker and tool loop errors
|
|
323
|
-
- [MCP Integration](../guides/mcp-integration.md) — MCP connection errors
|