claude_swarm 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGELOG.md → CHANGELOG.claude-swarm.md} +10 -0
  3. data/CLAUDE.md +346 -191
  4. data/decisions/2025-11-22-001-global-agent-registry.md +172 -0
  5. data/docs/v2/CHANGELOG.swarm_cli.md +20 -0
  6. data/docs/v2/CHANGELOG.swarm_memory.md +146 -1
  7. data/docs/v2/CHANGELOG.swarm_sdk.md +433 -10
  8. data/docs/v2/README.md +20 -5
  9. data/docs/v2/guides/complete-tutorial.md +95 -9
  10. data/docs/v2/guides/getting-started.md +10 -8
  11. data/docs/v2/guides/memory-adapters.md +41 -0
  12. data/docs/v2/guides/migrating-to-2.x.md +746 -0
  13. data/docs/v2/guides/plugins.md +52 -5
  14. data/docs/v2/guides/rails-integration.md +6 -0
  15. data/docs/v2/guides/snapshots.md +14 -14
  16. data/docs/v2/guides/swarm-memory.md +2 -13
  17. data/docs/v2/reference/architecture-flow.md +3 -3
  18. data/docs/v2/reference/cli.md +0 -1
  19. data/docs/v2/reference/configuration_reference.md +300 -0
  20. data/docs/v2/reference/event_payload_structures.md +27 -5
  21. data/docs/v2/reference/ruby-dsl.md +614 -18
  22. data/docs/v2/reference/swarm_memory_technical_details.md +7 -29
  23. data/docs/v2/reference/yaml.md +172 -54
  24. data/examples/snapshot_demo.rb +2 -2
  25. data/lib/claude_swarm/mcp_generator.rb +8 -21
  26. data/lib/claude_swarm/orchestrator.rb +8 -1
  27. data/lib/claude_swarm/version.rb +1 -1
  28. data/lib/swarm_cli/commands/run.rb +2 -2
  29. data/lib/swarm_cli/config_loader.rb +11 -11
  30. data/lib/swarm_cli/formatters/human_formatter.rb +0 -33
  31. data/lib/swarm_cli/interactive_repl.rb +2 -2
  32. data/lib/swarm_cli/ui/icons.rb +0 -23
  33. data/lib/swarm_cli/version.rb +1 -1
  34. data/lib/swarm_memory/adapters/filesystem_adapter.rb +11 -34
  35. data/lib/swarm_memory/core/semantic_index.rb +10 -2
  36. data/lib/swarm_memory/core/storage.rb +7 -2
  37. data/lib/swarm_memory/dsl/memory_config.rb +37 -0
  38. data/lib/swarm_memory/integration/sdk_plugin.rb +201 -28
  39. data/lib/swarm_memory/optimization/defragmenter.rb +1 -1
  40. data/lib/swarm_memory/prompts/memory_researcher.md.erb +0 -1
  41. data/lib/swarm_memory/tools/load_skill.rb +0 -1
  42. data/lib/swarm_memory/tools/memory_edit.rb +2 -1
  43. data/lib/swarm_memory/tools/memory_read.rb +1 -1
  44. data/lib/swarm_memory/version.rb +1 -1
  45. data/lib/swarm_memory.rb +8 -6
  46. data/lib/swarm_sdk/agent/builder.rb +58 -0
  47. data/lib/swarm_sdk/agent/chat.rb +527 -1061
  48. data/lib/swarm_sdk/agent/{chat → chat_helpers}/context_tracker.rb +13 -88
  49. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +204 -0
  50. data/lib/swarm_sdk/agent/{chat → chat_helpers}/hook_integration.rb +108 -46
  51. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +78 -0
  52. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +267 -0
  53. data/lib/swarm_sdk/agent/{chat → chat_helpers}/logging_helpers.rb +3 -3
  54. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +83 -0
  55. data/lib/swarm_sdk/agent/{chat → chat_helpers}/system_reminder_injector.rb +11 -13
  56. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +79 -0
  57. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +146 -0
  58. data/lib/swarm_sdk/agent/context.rb +1 -2
  59. data/lib/swarm_sdk/agent/definition.rb +66 -154
  60. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +4 -2
  61. data/lib/swarm_sdk/agent/system_prompt_builder.rb +161 -0
  62. data/lib/swarm_sdk/agent_registry.rb +146 -0
  63. data/lib/swarm_sdk/builders/base_builder.rb +488 -0
  64. data/lib/swarm_sdk/concerns/cleanupable.rb +39 -0
  65. data/lib/swarm_sdk/concerns/snapshotable.rb +67 -0
  66. data/lib/swarm_sdk/concerns/validatable.rb +55 -0
  67. data/lib/swarm_sdk/config.rb +302 -0
  68. data/lib/swarm_sdk/configuration/parser.rb +373 -0
  69. data/lib/swarm_sdk/configuration/translator.rb +255 -0
  70. data/lib/swarm_sdk/configuration.rb +77 -546
  71. data/lib/swarm_sdk/context_compactor/token_counter.rb +2 -6
  72. data/lib/swarm_sdk/context_compactor.rb +6 -11
  73. data/lib/swarm_sdk/context_management/builder.rb +128 -0
  74. data/lib/swarm_sdk/context_management/context.rb +328 -0
  75. data/lib/swarm_sdk/custom_tool_registry.rb +226 -0
  76. data/lib/swarm_sdk/defaults.rb +196 -0
  77. data/lib/swarm_sdk/events_to_messages.rb +18 -0
  78. data/lib/swarm_sdk/hooks/adapter.rb +3 -3
  79. data/lib/swarm_sdk/hooks/shell_executor.rb +4 -2
  80. data/lib/swarm_sdk/log_collector.rb +179 -29
  81. data/lib/swarm_sdk/log_stream.rb +29 -0
  82. data/lib/swarm_sdk/models.json +4333 -1
  83. data/lib/swarm_sdk/models.rb +43 -2
  84. data/lib/swarm_sdk/node_context.rb +1 -1
  85. data/lib/swarm_sdk/observer/builder.rb +81 -0
  86. data/lib/swarm_sdk/observer/config.rb +45 -0
  87. data/lib/swarm_sdk/observer/manager.rb +236 -0
  88. data/lib/swarm_sdk/patterns/agent_observer.rb +160 -0
  89. data/lib/swarm_sdk/plugin.rb +95 -5
  90. data/lib/swarm_sdk/result.rb +52 -0
  91. data/lib/swarm_sdk/snapshot.rb +6 -6
  92. data/lib/swarm_sdk/snapshot_from_events.rb +13 -2
  93. data/lib/swarm_sdk/state_restorer.rb +136 -151
  94. data/lib/swarm_sdk/state_snapshot.rb +65 -100
  95. data/lib/swarm_sdk/swarm/agent_initializer.rb +181 -137
  96. data/lib/swarm_sdk/swarm/builder.rb +44 -578
  97. data/lib/swarm_sdk/swarm/executor.rb +213 -0
  98. data/lib/swarm_sdk/swarm/hook_triggers.rb +151 -0
  99. data/lib/swarm_sdk/swarm/logging_callbacks.rb +341 -0
  100. data/lib/swarm_sdk/swarm/mcp_configurator.rb +7 -4
  101. data/lib/swarm_sdk/swarm/tool_configurator.rb +58 -140
  102. data/lib/swarm_sdk/swarm.rb +203 -683
  103. data/lib/swarm_sdk/tools/bash.rb +14 -8
  104. data/lib/swarm_sdk/tools/delegate.rb +61 -43
  105. data/lib/swarm_sdk/tools/edit.rb +8 -13
  106. data/lib/swarm_sdk/tools/glob.rb +12 -4
  107. data/lib/swarm_sdk/tools/grep.rb +7 -0
  108. data/lib/swarm_sdk/tools/multi_edit.rb +15 -11
  109. data/lib/swarm_sdk/tools/path_resolver.rb +51 -2
  110. data/lib/swarm_sdk/tools/read.rb +16 -18
  111. data/lib/swarm_sdk/tools/registry.rb +122 -10
  112. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +9 -5
  113. data/lib/swarm_sdk/tools/stores/storage.rb +0 -6
  114. data/lib/swarm_sdk/tools/todo_write.rb +7 -0
  115. data/lib/swarm_sdk/tools/web_fetch.rb +20 -17
  116. data/lib/swarm_sdk/tools/write.rb +8 -13
  117. data/lib/swarm_sdk/version.rb +1 -1
  118. data/lib/swarm_sdk/{node → workflow}/agent_config.rb +1 -1
  119. data/lib/swarm_sdk/workflow/builder.rb +192 -0
  120. data/lib/swarm_sdk/workflow/executor.rb +497 -0
  121. data/lib/swarm_sdk/{node/builder.rb → workflow/node_builder.rb} +7 -5
  122. data/lib/swarm_sdk/{node → workflow}/transformer_executor.rb +5 -3
  123. data/lib/swarm_sdk/{node_orchestrator.rb → workflow.rb} +152 -456
  124. data/lib/swarm_sdk.rb +294 -108
  125. data/rubocop/cop/security/no_reflection_methods.rb +1 -1
  126. data/swarm_cli.gemspec +1 -1
  127. data/swarm_memory.gemspec +8 -3
  128. data/swarm_sdk.gemspec +6 -4
  129. data/team_full.yml +124 -320
  130. metadata +42 -14
  131. data/lib/swarm_memory/chat_extension.rb +0 -34
  132. data/lib/swarm_memory/tools/memory_multi_edit.rb +0 -281
  133. data/lib/swarm_sdk/providers/openai_with_responses.rb +0 -589
  134. /data/lib/swarm_memory/{errors.rb → error.rb} +0 -0
@@ -21,6 +21,53 @@ The **plugin system** allows gems to extend SwarmSDK without creating tight coup
21
21
  - 🛠️ **Tool Provider** - Plugins create and manage their own tools
22
22
  - 📦 **Storage Provider** - Plugins handle their own data persistence
23
23
 
24
+ ### Plugins vs Custom Tools
25
+
26
+ SwarmSDK offers two ways to add custom functionality:
27
+
28
+ | Feature | Custom Tools (`SwarmSDK.register_tool`) | Plugins |
29
+ |---------|----------------------------------------|---------|
30
+ | **Use Case** | Simple, stateless tools | Complex features with storage & hooks |
31
+ | **Setup** | One line: `register_tool(ToolClass)` | Full plugin class with lifecycle |
32
+ | **Storage** | ❌ No persistent storage | ✅ Per-agent storage |
33
+ | **Lifecycle Hooks** | ❌ No hooks | ✅ on_agent_initialized, on_user_message, etc. |
34
+ | **System Prompts** | ❌ No prompt injection | ✅ Can contribute to system prompts |
35
+ | **Examples** | Weather API, Calculator | SwarmMemory (persistent knowledge) |
36
+
37
+ **Choose Custom Tools when:**
38
+ - Tool is simple and stateless
39
+ - No need for persistent storage
40
+ - No lifecycle hooks required
41
+ - Want quickest setup
42
+
43
+ **Choose Plugins when:**
44
+ - Need per-agent storage
45
+ - Need lifecycle hooks
46
+ - Want to contribute to system prompts
47
+ - Building a suite of related tools
48
+
49
+ **Custom Tool Example:**
50
+ ```ruby
51
+ class WeatherTool < RubyLLM::Tool
52
+ description "Get weather for a city"
53
+ param :city, type: "string", required: true
54
+
55
+ def execute(city:)
56
+ "Weather in #{city}: Sunny"
57
+ end
58
+ end
59
+
60
+ SwarmSDK.register_tool(WeatherTool)
61
+
62
+ SwarmSDK.build do
63
+ agent :helper do
64
+ tools :Weather # Use the registered tool
65
+ end
66
+ end
67
+ ```
68
+
69
+ See the Ruby DSL reference for complete custom tool documentation.
70
+
24
71
  ---
25
72
 
26
73
  ## Architecture
@@ -85,8 +132,8 @@ module MyPlugin
85
132
  end
86
133
  end
87
134
 
88
- # Check if storage should be created for an agent
89
- def storage_enabled?(agent_definition)
135
+ # Check if memory should be configured for an agent
136
+ def memory_configured?(agent_definition)
90
137
  agent_definition.respond_to?(:my_plugin) && agent_definition.my_plugin
91
138
  end
92
139
 
@@ -216,8 +263,8 @@ def create_storage(agent_name:, config:)
216
263
  MyStorage.new(...)
217
264
  end
218
265
 
219
- # Check if storage should be created
220
- def storage_enabled?(agent_definition)
266
+ # Check if memory should be configured
267
+ def memory_configured?(agent_definition)
221
268
  agent_definition.respond_to?(:my_plugin)
222
269
  end
223
270
 
@@ -750,7 +797,7 @@ class StoragePlugin < SwarmSDK::Plugin
750
797
  :database
751
798
  end
752
799
 
753
- def storage_enabled?(agent_definition)
800
+ def memory_configured?(agent_definition)
754
801
  agent_definition.respond_to?(:database)
755
802
  end
756
803
 
@@ -45,6 +45,12 @@ Install dependencies:
45
45
  bundle install
46
46
  ```
47
47
 
48
+ ### Set the active support isolation level to :Fiber
49
+ Edit `config/application.rb` and add:
50
+ ```
51
+ config.active_support.isolation_level = :fiber
52
+ ```
53
+
48
54
  ### Create Initializer
49
55
 
50
56
  Create `config/initializers/swarm_sdk.rb`:
@@ -112,8 +112,8 @@ snapshot.write_to_file("session.json")
112
112
  snapshot.write_to_file("session.json", pretty: false)
113
113
 
114
114
  # Access metadata
115
- snapshot.version # => "1.0.0"
116
- snapshot.type # => "swarm" or "node_orchestrator"
115
+ snapshot.version: 2.0.0"
116
+ snapshot.type # => "swarm" or "workflow"
117
117
  snapshot.snapshot_at # => "2025-01-03T14:30:00Z"
118
118
  snapshot.swarm_sdk_version # => "2.1.3"
119
119
  snapshot.agent_names # => ["backend", "database"]
@@ -121,7 +121,7 @@ snapshot.delegation_instance_names # => ["database@backend"]
121
121
 
122
122
  # Type checks
123
123
  snapshot.swarm? # => true
124
- snapshot.node_orchestrator? # => false
124
+ snapshot.workflow? # => false
125
125
  ```
126
126
 
127
127
  ### Loading Snapshots
@@ -137,7 +137,7 @@ json_string = redis.get("session:#{user_id}")
137
137
  snapshot = SwarmSDK::Snapshot.from_json(json_string)
138
138
 
139
139
  # From hash
140
- hash = { version: "1.0.0", type: "swarm", ... }
140
+ hash = { version: 2.0.0", type: "swarm", ... }
141
141
  snapshot = SwarmSDK::Snapshot.from_hash(hash)
142
142
  ```
143
143
 
@@ -616,7 +616,7 @@ result = swarm.restore(hash)
616
616
  result = swarm.restore(json_string)
617
617
  ```
618
618
 
619
- ### NodeOrchestrator Methods
619
+ ### Workflow Methods
620
620
 
621
621
  Same API as Swarm:
622
622
 
@@ -639,8 +639,8 @@ Snapshot.from_json(json_string) # => Snapshot
639
639
  Snapshot.from_hash(hash) # => Snapshot
640
640
 
641
641
  # Metadata accessors
642
- snapshot.version # => "1.0.0"
643
- snapshot.type # => "swarm" | "node_orchestrator"
642
+ snapshot.version: 2.0.0"
643
+ snapshot.type # => "swarm" | "workflow"
644
644
  snapshot.snapshot_at # => "2025-01-03T14:30:00Z"
645
645
  snapshot.swarm_sdk_version # => "2.1.3"
646
646
  snapshot.agent_names # => ["agent1", "agent2"]
@@ -648,7 +648,7 @@ snapshot.delegation_instance_names # => ["agent2@agent1"]
648
648
 
649
649
  # Type checks
650
650
  snapshot.swarm? # => true | false
651
- snapshot.node_orchestrator? # => true | false
651
+ snapshot.workflow? # => true | false
652
652
  ```
653
653
 
654
654
  ### SnapshotFromEvents Class
@@ -799,10 +799,10 @@ swarm.restore(snapshot)
799
799
  result = swarm.execute("Implement API endpoints using different pattern")
800
800
  ```
801
801
 
802
- ### NodeOrchestrator Workflows
802
+ ### Workflow Workflows
803
803
 
804
804
  ```ruby
805
- orchestrator = SwarmSDK::NodeOrchestrator.new(
805
+ orchestrator = SwarmSDK::Workflow.new(
806
806
  swarm_name: "Dev Workflow",
807
807
  agent_definitions: { planner: planner_def, coder: coder_def },
808
808
  nodes: { planning: planning_node, coding: coding_node },
@@ -819,7 +819,7 @@ snapshot.write_to_file("workflow_session.json")
819
819
  # === Later, new process ===
820
820
 
821
821
  # Restore and continue
822
- orchestrator = SwarmSDK::NodeOrchestrator.new(...) # Same config
822
+ orchestrator = SwarmSDK::Workflow.new(...) # Same config
823
823
  snapshot = SwarmSDK::Snapshot.from_file("workflow_session.json")
824
824
  orchestrator.restore(snapshot)
825
825
 
@@ -1283,7 +1283,7 @@ swarm2.execute("Read scratchpad://tasks/auth.md")
1283
1283
  # => Agent sees content from previous session
1284
1284
  ```
1285
1285
 
1286
- **Note**: NodeOrchestrator doesn't snapshot scratchpad because each node creates its own fresh scratchpad.
1286
+ **Note**: Workflow doesn't snapshot scratchpad because each node creates its own fresh scratchpad.
1287
1287
 
1288
1288
  ## Troubleshooting
1289
1289
 
@@ -1340,9 +1340,9 @@ result = swarm.restore(snapshot)
1340
1340
 
1341
1341
  ### Type Mismatch
1342
1342
 
1343
- **Problem**: `Snapshot type 'swarm' doesn't match orchestration type 'node_orchestrator'`
1343
+ **Problem**: `Snapshot type 'swarm' doesn't match orchestration type 'workflow'`
1344
1344
 
1345
- **Cause**: Trying to restore swarm snapshot into NodeOrchestrator (or vice versa)
1345
+ **Cause**: Trying to restore swarm snapshot into Workflow (or vice versa)
1346
1346
 
1347
1347
  **Solution**: Use correct orchestration type that matches snapshot
1348
1348
 
@@ -113,7 +113,7 @@ Auto-registration: SwarmMemory::Integration::SDKPlugin
113
113
  SwarmSDK::PluginRegistry.register(plugin)
114
114
 
115
115
  Plugin provides:
116
- - 8 memory tools (MemoryWrite, MemoryRead, etc.)
116
+ - 7 memory tools (MemoryWrite, MemoryRead, MemoryEdit, MemoryDelete, MemoryGlob, MemoryGrep, MemoryDefrag)
117
117
  - Memory storage (FilesystemAdapter + Embeddings)
118
118
  - System prompt contributions
119
119
  - Automatic skill discovery on user messages
@@ -190,17 +190,6 @@ MemoryEdit(
190
190
  )
191
191
  ```
192
192
 
193
- **MemoryMultiEdit** - Multiple edits in one operation
194
- ```ruby
195
- MemoryMultiEdit(
196
- file_path: "concept/ruby/classes.md",
197
- edits_json: '[
198
- {"old_string": "foo", "new_string": "bar"},
199
- {"old_string": "baz", "new_string": "qux"}
200
- ]'
201
- )
202
- ```
203
-
204
193
  **MemoryDelete** - Remove entries
205
194
  ```ruby
206
195
  MemoryDelete(file_path: "concept/old-api/deprecated.md")
@@ -382,7 +371,7 @@ end
382
371
  When memory is configured:
383
372
 
384
373
  1. **Storage Created**: `FilesystemAdapter` + `InformersEmbedder`
385
- 2. **Tools Registered**: 8 memory tools + LoadSkill
374
+ 2. **Tools Registered**: 7 memory tools + LoadSkill (8 total)
386
375
  3. **Prompt Injected**: Memory system guidance
387
376
  4. **Discovery Enabled**: Semantic search on user messages
388
377
  5. **Embeddings Generated**: For all stored content
@@ -93,7 +93,7 @@ flowchart TB
93
93
  end
94
94
 
95
95
  subgraph "Node Workflows"
96
- NODE_ORCH["NodeOrchestrator<br/>(multi-stage execution)"]
96
+ NODE_ORCH["Workflow<br/>(multi-stage execution)"]
97
97
  NODE_CTX["NodeContext<br/>(goto_node, halt_workflow, skip_execution)"]
98
98
  TRANSFORMERS["Bash/Ruby Transformers<br/>(input/output transformation)"]
99
99
  MINI_SWARMS["Mini-Swarms<br/>(one per node)"]
@@ -318,7 +318,7 @@ Event occurs →
318
318
 
319
319
  ### 9. Node Workflow Flow
320
320
  ```
321
- NodeOrchestrator.execute →
321
+ Workflow.execute →
322
322
  Build execution order (topological sort) →
323
323
  For each node:
324
324
  Input transformer (Bash/Ruby) →
@@ -339,7 +339,7 @@ NodeOrchestrator.execute →
339
339
  - **AgentInitializer**: Complex 5-pass initialization (tools, MCP, delegation, hooks)
340
340
  - **ToolConfigurator**: Tool registration, creation, permissions wrapping
341
341
  - **McpConfigurator**: MCP client management, external tool integration
342
- - **NodeOrchestrator**: Multi-stage workflows with transformers
342
+ - **Workflow**: Multi-stage workflows with transformers
343
343
  - **Plugin System**: Extensibility framework (SwarmMemory uses this)
344
344
 
345
345
  ### SwarmCLI
@@ -401,7 +401,6 @@ Starts an MCP server that exposes SwarmSDK tools (Read, Write, Edit, Bash, Grep,
401
401
  - `MemoryWrite`: Write to per-agent memory (persistent)
402
402
  - `MemoryRead`: Read from memory (with line numbers)
403
403
  - `MemoryEdit`: Edit memory entries
404
- - `MemoryMultiEdit`: Apply multiple edits to memory
405
404
  - `MemoryGlob`: Search memory by glob pattern
406
405
  - `MemoryGrep`: Search memory content by regex
407
406
  - `MemoryDelete`: Delete memory entries
@@ -0,0 +1,300 @@
1
+ # Configuration Reference
2
+
3
+ This document provides a comprehensive reference for all SwarmSDK configuration options. Configuration can be set via environment variables or programmatically through `SwarmSDK.configure`.
4
+
5
+ ## Configuration Priority
6
+
7
+ Values are resolved in this order:
8
+ 1. **Explicit value** (set via `SwarmSDK.configure`)
9
+ 2. **Environment variable**
10
+ 3. **Default value**
11
+
12
+ ## Usage
13
+
14
+ ```ruby
15
+ SwarmSDK.configure do |config|
16
+ # API Keys
17
+ config.openai_api_key = "sk-..."
18
+
19
+ # Defaults
20
+ config.default_model = "claude-sonnet-4"
21
+ config.agent_request_timeout = 600
22
+
23
+ # WebFetch
24
+ config.webfetch_provider = "anthropic"
25
+ config.webfetch_model = "claude-3-5-haiku-20241022"
26
+ end
27
+ ```
28
+
29
+ ---
30
+
31
+ ## API Keys
32
+
33
+ API keys are automatically proxied to `RubyLLM.config` when set.
34
+
35
+ | Environment Variable | Config Key | Description | Default |
36
+ |---------------------|------------|-------------|---------|
37
+ | `OPENAI_API_KEY` | `openai_api_key` | OpenAI API authentication key | `nil` |
38
+ | `OPENAI_API_BASE` | `openai_api_base` | Custom OpenAI-compatible API endpoint URL | `nil` |
39
+ | `OPENAI_ORG_ID` | `openai_organization_id` | OpenAI organization identifier | `nil` |
40
+ | `OPENAI_PROJECT_ID` | `openai_project_id` | OpenAI project identifier | `nil` |
41
+ | `ANTHROPIC_API_KEY` | `anthropic_api_key` | Anthropic (Claude) API authentication key | `nil` |
42
+ | `GEMINI_API_KEY` | `gemini_api_key` | Google Gemini API authentication key | `nil` |
43
+ | `GEMINI_API_BASE` | `gemini_api_base` | Custom Gemini API endpoint URL | `nil` |
44
+ | `GOOGLE_CLOUD_PROJECT` | `vertexai_project_id` | Google Cloud project ID for Vertex AI | `nil` |
45
+ | `GOOGLE_CLOUD_LOCATION` | `vertexai_location` | Google Cloud region for Vertex AI | `nil` |
46
+ | `DEEPSEEK_API_KEY` | `deepseek_api_key` | DeepSeek API authentication key | `nil` |
47
+ | `MISTRAL_API_KEY` | `mistral_api_key` | Mistral AI API authentication key | `nil` |
48
+ | `PERPLEXITY_API_KEY` | `perplexity_api_key` | Perplexity API authentication key | `nil` |
49
+ | `OPENROUTER_API_KEY` | `openrouter_api_key` | OpenRouter API authentication key | `nil` |
50
+ | `AWS_ACCESS_KEY_ID` | `bedrock_api_key` | AWS access key for Bedrock | `nil` |
51
+ | `AWS_SECRET_ACCESS_KEY` | `bedrock_secret_key` | AWS secret key for Bedrock | `nil` |
52
+ | `AWS_REGION` | `bedrock_region` | AWS region for Bedrock | `nil` |
53
+ | `AWS_SESSION_TOKEN` | `bedrock_session_token` | AWS session token for temporary credentials | `nil` |
54
+ | `OLLAMA_API_BASE` | `ollama_api_base` | Local Ollama server URL | `nil` |
55
+ | `GPUSTACK_API_BASE` | `gpustack_api_base` | GPUStack server URL | `nil` |
56
+ | `GPUSTACK_API_KEY` | `gpustack_api_key` | GPUStack API authentication key | `nil` |
57
+
58
+ ---
59
+
60
+ ## Agent & Swarm Defaults
61
+
62
+ Default values for agent and swarm configuration.
63
+
64
+ | Environment Variable | Config Key | Description | Default |
65
+ |---------------------|------------|-------------|---------|
66
+ | `SWARM_SDK_DEFAULT_MODEL` | `default_model` | Default LLM model when not specified per-agent | `"gpt-5"` |
67
+ | `SWARM_SDK_DEFAULT_PROVIDER` | `default_provider` | Default LLM provider when not specified per-agent | `"openai"` |
68
+ | `SWARM_SDK_GLOBAL_CONCURRENCY_LIMIT` | `global_concurrency_limit` | Maximum concurrent API calls across entire swarm | `50` |
69
+ | `SWARM_SDK_LOCAL_CONCURRENCY_LIMIT` | `local_concurrency_limit` | Maximum parallel tool executions per agent | `10` |
70
+
71
+ ---
72
+
73
+ ## Timeouts
74
+
75
+ Timeout values for various operations.
76
+
77
+ | Environment Variable | Config Key | Description | Default |
78
+ |---------------------|------------|-------------|---------|
79
+ | `SWARM_SDK_AGENT_REQUEST_TIMEOUT` | `agent_request_timeout` | LLM API request timeout in seconds | `300` (5 min) |
80
+ | `SWARM_SDK_BASH_COMMAND_TIMEOUT` | `bash_command_timeout` | Bash command execution timeout in milliseconds | `120000` (2 min) |
81
+ | `SWARM_SDK_BASH_COMMAND_MAX_TIMEOUT` | `bash_command_max_timeout` | Maximum allowed bash command timeout in milliseconds | `600000` (10 min) |
82
+ | `SWARM_SDK_WEB_FETCH_TIMEOUT` | `web_fetch_timeout` | HTTP request timeout for WebFetch tool in seconds | `30` |
83
+ | `SWARM_SDK_HOOK_SHELL_TIMEOUT` | `hook_shell_timeout` | Shell hook executor timeout in seconds | `60` |
84
+ | `SWARM_SDK_TRANSFORMER_COMMAND_TIMEOUT` | `transformer_command_timeout` | Workflow transformer command timeout in seconds | `60` |
85
+
86
+ ---
87
+
88
+ ## Output & Content Limits
89
+
90
+ Limits for output sizes and content lengths.
91
+
92
+ | Environment Variable | Config Key | Description | Default |
93
+ |---------------------|------------|-------------|---------|
94
+ | `SWARM_SDK_OUTPUT_CHARACTER_LIMIT` | `output_character_limit` | Maximum characters in Bash command output | `30000` |
95
+ | `SWARM_SDK_READ_LINE_LIMIT` | `read_line_limit` | Default number of lines to read from files | `2000` |
96
+ | `SWARM_SDK_LINE_CHARACTER_LIMIT` | `line_character_limit` | Maximum characters per line in Read output | `2000` |
97
+ | `SWARM_SDK_WEB_FETCH_CHARACTER_LIMIT` | `web_fetch_character_limit` | Maximum characters from web page content | `100000` |
98
+ | `SWARM_SDK_GLOB_RESULT_LIMIT` | `glob_result_limit` | Maximum file paths returned by Glob tool | `1000` |
99
+
100
+ ---
101
+
102
+ ## Storage Limits
103
+
104
+ Limits for persistent storage.
105
+
106
+ | Environment Variable | Config Key | Description | Default |
107
+ |---------------------|------------|-------------|---------|
108
+ | `SWARM_SDK_SCRATCHPAD_ENTRY_SIZE_LIMIT` | `scratchpad_entry_size_limit` | Maximum size for single scratchpad entry in bytes | `3000000` (3 MB) |
109
+ | `SWARM_SDK_SCRATCHPAD_TOTAL_SIZE_LIMIT` | `scratchpad_total_size_limit` | Maximum total scratchpad storage in bytes | `100000000000` (100 GB) |
110
+
111
+ ---
112
+
113
+ ## Context Management
114
+
115
+ Settings for context management and optimization.
116
+
117
+ | Environment Variable | Config Key | Description | Default |
118
+ |---------------------|------------|-------------|---------|
119
+ | `SWARM_SDK_CONTEXT_COMPRESSION_THRESHOLD` | `context_compression_threshold` | Context usage percentage triggering compression warning | `60` |
120
+ | `SWARM_SDK_TODOWRITE_REMINDER_INTERVAL` | `todowrite_reminder_interval` | Message count between TodoWrite reminders | `8` |
121
+ | `SWARM_SDK_CHARS_PER_TOKEN_PROSE` | `chars_per_token_prose` | Characters per token for prose text estimation | `4.0` |
122
+ | `SWARM_SDK_CHARS_PER_TOKEN_CODE` | `chars_per_token_code` | Characters per token for code estimation | `3.5` |
123
+
124
+ ---
125
+
126
+ ## Logging
127
+
128
+ Logging configuration settings.
129
+
130
+ | Environment Variable | Config Key | Description | Default |
131
+ |---------------------|------------|-------------|---------|
132
+ | `SWARM_SDK_MCP_LOG_LEVEL` | `mcp_log_level` | Log level for MCP client (0=DEBUG, 1=INFO, 2=WARN, 3=ERROR) | `2` (WARN) |
133
+
134
+ ---
135
+
136
+ ## WebFetch LLM Processing
137
+
138
+ Settings for WebFetch tool's optional LLM content processing.
139
+
140
+ | Environment Variable | Config Key | Description | Default |
141
+ |---------------------|------------|-------------|---------|
142
+ | `SWARM_SDK_WEBFETCH_PROVIDER` | `webfetch_provider` | LLM provider for WebFetch content processing | `nil` |
143
+ | `SWARM_SDK_WEBFETCH_MODEL` | `webfetch_model` | LLM model for WebFetch content processing | `nil` |
144
+ | `SWARM_SDK_WEBFETCH_BASE_URL` | `webfetch_base_url` | Custom API endpoint for WebFetch LLM | `nil` |
145
+ | `SWARM_SDK_WEBFETCH_MAX_TOKENS` | `webfetch_max_tokens` | Maximum tokens for WebFetch LLM responses | `4096` |
146
+
147
+ **Note:** WebFetch LLM processing is enabled when both `webfetch_provider` and `webfetch_model` are configured. When enabled, the `prompt` parameter is required when calling WebFetch.
148
+
149
+ ---
150
+
151
+ ## Security Settings
152
+
153
+ Security-related configuration options.
154
+
155
+ | Environment Variable | Config Key | Description | Default |
156
+ |---------------------|------------|-------------|---------|
157
+ | `SWARM_SDK_ALLOW_FILESYSTEM_TOOLS` | `allow_filesystem_tools` | Global toggle to enable/disable filesystem tools (Read, Write, Edit, Glob, Grep) | `true` |
158
+ | `SWARM_SDK_ENV_INTERPOLATION` | `env_interpolation` | Global toggle to enable/disable environment variable interpolation in YAML configs | `true` |
159
+
160
+ **Boolean Environment Variable Values:**
161
+ - True: `true`, `yes`, `1`, `on`, `enabled`
162
+ - False: `false`, `no`, `0`, `off`, `disabled`
163
+
164
+ ---
165
+
166
+ ## YAML Environment Variable Interpolation
167
+
168
+ YAML configurations support environment variable interpolation using the `${VAR}` and `${VAR:=default}` syntax. This feature can be controlled globally or per-load.
169
+
170
+ ### Interpolation Syntax
171
+
172
+ ```yaml
173
+ # Required variable (raises error if not set)
174
+ model: ${OPENAI_MODEL}
175
+
176
+ # Variable with default value
177
+ model: ${OPENAI_MODEL:=gpt-4}
178
+
179
+ # Empty default
180
+ api_key: ${OPTIONAL_KEY:=}
181
+ ```
182
+
183
+ ### Disabling Interpolation
184
+
185
+ **Per-load** (highest priority):
186
+ ```ruby
187
+ # Disable for a specific load
188
+ swarm = SwarmSDK.load(yaml_content, env_interpolation: false)
189
+ swarm = SwarmSDK.load_file("config.yml", env_interpolation: false)
190
+ ```
191
+
192
+ **Globally** (via configuration):
193
+ ```ruby
194
+ SwarmSDK.configure do |config|
195
+ config.env_interpolation = false
196
+ end
197
+ ```
198
+
199
+ **Globally** (via environment variable):
200
+ ```bash
201
+ export SWARM_SDK_ENV_INTERPOLATION=false
202
+ ```
203
+
204
+ ### Priority Order
205
+
206
+ 1. Per-load parameter (`env_interpolation:`) - highest priority
207
+ 2. Global config (`SwarmSDK.config.env_interpolation`)
208
+ 3. Environment variable (`SWARM_SDK_ENV_INTERPOLATION`)
209
+ 4. Default (`true`) - lowest priority
210
+
211
+ ---
212
+
213
+ ## Examples
214
+
215
+ ### Minimal Configuration (ENV only)
216
+
217
+ ```bash
218
+ # .env
219
+ OPENAI_API_KEY=sk-...
220
+ ```
221
+
222
+ ```ruby
223
+ require "swarm_sdk"
224
+
225
+ # No explicit configuration needed - lazy loads from ENV
226
+ swarm = SwarmSDK.build do
227
+ name "My Swarm"
228
+ lead :assistant
229
+ agent :assistant do
230
+ description "General assistant"
231
+ prompt "You are helpful"
232
+ end
233
+ end
234
+ ```
235
+
236
+ ### Full Configuration
237
+
238
+ ```ruby
239
+ SwarmSDK.configure do |config|
240
+ # API Keys
241
+ config.openai_api_key = ENV["OPENAI_API_KEY"]
242
+ config.anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
243
+
244
+ # Agent Defaults
245
+ config.default_model = "claude-sonnet-4"
246
+ config.default_provider = "anthropic"
247
+ config.agent_request_timeout = 600
248
+
249
+ # Concurrency
250
+ config.global_concurrency_limit = 100
251
+ config.local_concurrency_limit = 20
252
+
253
+ # Timeouts
254
+ config.bash_command_timeout = 180_000
255
+ config.web_fetch_timeout = 60
256
+
257
+ # Limits
258
+ config.output_character_limit = 50_000
259
+ config.read_line_limit = 5000
260
+
261
+ # WebFetch LLM
262
+ config.webfetch_provider = "openai"
263
+ config.webfetch_model = "gpt-4o-mini"
264
+ config.webfetch_max_tokens = 8192
265
+
266
+ # Security
267
+ config.allow_filesystem_tools = true
268
+ end
269
+ ```
270
+
271
+ ### Testing Configuration
272
+
273
+ ```ruby
274
+ # test/test_helper.rb
275
+ def setup
276
+ SwarmSDK.reset_config!
277
+ end
278
+
279
+ def teardown
280
+ SwarmSDK.reset_config!
281
+ end
282
+
283
+ # test/my_test.rb
284
+ def test_with_custom_config
285
+ SwarmSDK.configure do |config|
286
+ config.openai_api_key = "test-key"
287
+ config.agent_request_timeout = 60
288
+ end
289
+
290
+ # Test code here
291
+ end
292
+ ```
293
+
294
+ ---
295
+
296
+ ## See Also
297
+
298
+ - [Ruby DSL Reference](ruby-dsl.md) - Programmatic swarm building
299
+ - [YAML Configuration](yaml-configuration.md) - YAML-based swarm definitions
300
+ - [Changelog](../CHANGELOG.swarm_sdk.md) - Version history and breaking changes
@@ -72,13 +72,35 @@ Emitted when swarm execution completes (success or error).
72
72
  duration: 277.5, # Seconds (Float)
73
73
  total_cost: 0.00234, # USD (Float)
74
74
  total_tokens: 12450, # Integer
75
- agents_involved: [:lead, :backend, :frontend] # Array of agent names
75
+ agents_involved: [:lead, :backend, :frontend], # Array of agent names
76
+ per_agent_usage: { # Per-agent usage breakdown (Hash)
77
+ lead: {
78
+ input_tokens: 5200,
79
+ output_tokens: 1800,
80
+ total_tokens: 7000,
81
+ input_cost: 0.00156,
82
+ output_cost: 0.00054,
83
+ total_cost: 0.0021,
84
+ context_limit: 200000,
85
+ context_usage_percentage: 3.5
86
+ },
87
+ backend: {
88
+ input_tokens: 3250,
89
+ output_tokens: 1200,
90
+ total_tokens: 4450,
91
+ input_cost: 0.00015,
92
+ output_cost: 0.00009,
93
+ total_cost: 0.00024,
94
+ context_limit: 128000,
95
+ context_usage_percentage: 3.48
96
+ }
97
+ }
76
98
  }
77
99
  ```
78
100
 
79
101
  **Field Locations**:
80
- - Root level: All fields including `swarm_id` and `parent_swarm_id`
81
- - No nested metadata for this event
102
+ - Root level: All fields including `swarm_id`, `parent_swarm_id`, and `per_agent_usage`
103
+ - Nested in `per_agent_usage`: Per-agent hash with token counts, costs, context metrics
82
104
 
83
105
  ---
84
106
 
@@ -100,7 +122,7 @@ Emitted once per agent when agents are initialized (lazy initialization).
100
122
  provider: "openai", # Provider name
101
123
  directory: "./backend", # Working directory
102
124
  system_prompt: "You are a backend dev...", # Full system prompt
103
- tools: [:Read, :Edit, :Bash, :DelegateTaskToFrontend], # Array of tool names
125
+ tools: [:Read, :Edit, :Bash, :WorkWithFrontend], # Array of tool names
104
126
  delegates_to: [:frontend], # Array of delegate agent names
105
127
  plugin_storages: { # Plugin storage info (optional)
106
128
  memory: {
@@ -677,7 +699,7 @@ Emitted after receiving HTTP response from LLM API provider (only when logging i
677
699
  | Event | Root Fields | Nested Fields |
678
700
  |-------|-------------|---------------|
679
701
  | `swarm_start` | swarm_name, lead_agent, prompt | None |
680
- | `swarm_stop` | swarm_name, lead_agent, last_agent, content, success, duration, total_cost, total_tokens, agents_involved | None |
702
+ | `swarm_stop` | swarm_name, lead_agent, last_agent, content, success, duration, total_cost, total_tokens, agents_involved, per_agent_usage | per_agent_usage.{agent}.* |
681
703
  | `agent_start` | swarm_name, model, provider, directory, system_prompt, tools, delegates_to | plugin_storages.* |
682
704
  | `agent_stop` | model, content, tool_calls, finish_reason, tool_executions | usage.*, metadata.* |
683
705
  | `agent_step` | model, content, tool_calls, finish_reason, tool_executions | usage.*, tool_calls[].*, metadata.* |