claude_swarm 1.0.1 → 1.0.2
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/.claude/commands/release.md +1 -1
- data/.claude/hooks/lint-code-files.rb +65 -0
- data/.rubocop.yml +22 -2
- data/CHANGELOG.md +14 -1
- data/CLAUDE.md +1 -1
- data/CONTRIBUTING.md +69 -0
- data/README.md +27 -2
- data/Rakefile +71 -3
- data/analyze_coverage.rb +94 -0
- data/docs/v2/CHANGELOG.swarm_cli.md +43 -0
- data/docs/v2/CHANGELOG.swarm_memory.md +379 -0
- data/docs/v2/CHANGELOG.swarm_sdk.md +362 -0
- data/docs/v2/README.md +308 -0
- data/docs/v2/guides/claude-code-agents.md +262 -0
- data/docs/v2/guides/complete-tutorial.md +3088 -0
- data/docs/v2/guides/getting-started.md +1456 -0
- data/docs/v2/guides/memory-adapters.md +998 -0
- data/docs/v2/guides/plugins.md +816 -0
- data/docs/v2/guides/quick-start-cli.md +1745 -0
- data/docs/v2/guides/rails-integration.md +1902 -0
- data/docs/v2/guides/swarm-memory.md +599 -0
- data/docs/v2/reference/cli.md +729 -0
- data/docs/v2/reference/ruby-dsl.md +2154 -0
- data/docs/v2/reference/yaml.md +1835 -0
- data/docs-team-swarm.yml +2222 -0
- data/examples/learning-assistant/assistant.md +7 -0
- data/examples/learning-assistant/example-memories/concept-example.md +90 -0
- data/examples/learning-assistant/example-memories/experience-example.md +66 -0
- data/examples/learning-assistant/example-memories/fact-example.md +76 -0
- data/examples/learning-assistant/example-memories/memory-index.md +78 -0
- data/examples/learning-assistant/example-memories/skill-example.md +168 -0
- data/examples/learning-assistant/learning_assistant.rb +34 -0
- data/examples/learning-assistant/learning_assistant.yml +20 -0
- data/examples/v2/dsl/01_basic.rb +44 -0
- data/examples/v2/dsl/02_core_parameters.rb +59 -0
- data/examples/v2/dsl/03_capabilities.rb +71 -0
- data/examples/v2/dsl/04_llm_parameters.rb +56 -0
- data/examples/v2/dsl/05_advanced_flags.rb +73 -0
- data/examples/v2/dsl/06_permissions.rb +80 -0
- data/examples/v2/dsl/07_mcp_server.rb +62 -0
- data/examples/v2/dsl/08_swarm_hooks.rb +53 -0
- data/examples/v2/dsl/09_agent_hooks.rb +67 -0
- data/examples/v2/dsl/10_all_agents_hooks.rb +67 -0
- data/examples/v2/dsl/11_delegation.rb +60 -0
- data/examples/v2/dsl/12_complete_integration.rb +137 -0
- data/examples/v2/file_tools_swarm.yml +102 -0
- data/examples/v2/hooks/01_basic_hooks.rb +133 -0
- data/examples/v2/hooks/02_usage_tracking.rb +201 -0
- data/examples/v2/hooks/03_production_monitoring.rb +429 -0
- data/examples/v2/hooks/agent_stop_exit_0.yml +21 -0
- data/examples/v2/hooks/agent_stop_exit_1.yml +21 -0
- data/examples/v2/hooks/agent_stop_exit_2.yml +26 -0
- data/examples/v2/hooks/multiple_hooks_all_pass.yml +37 -0
- data/examples/v2/hooks/multiple_hooks_first_fails.yml +37 -0
- data/examples/v2/hooks/multiple_hooks_second_fails.yml +37 -0
- data/examples/v2/hooks/multiple_hooks_warnings.yml +37 -0
- data/examples/v2/hooks/post_tool_use_exit_0.yml +24 -0
- data/examples/v2/hooks/post_tool_use_exit_1.yml +24 -0
- data/examples/v2/hooks/post_tool_use_exit_2.yml +24 -0
- data/examples/v2/hooks/post_tool_use_multi_matcher_exit_0.yml +26 -0
- data/examples/v2/hooks/post_tool_use_multi_matcher_exit_1.yml +26 -0
- data/examples/v2/hooks/post_tool_use_multi_matcher_exit_2.yml +26 -0
- data/examples/v2/hooks/pre_tool_use_exit_0.yml +24 -0
- data/examples/v2/hooks/pre_tool_use_exit_1.yml +24 -0
- data/examples/v2/hooks/pre_tool_use_exit_2.yml +24 -0
- data/examples/v2/hooks/pre_tool_use_multi_matcher_exit_0.yml +26 -0
- data/examples/v2/hooks/pre_tool_use_multi_matcher_exit_1.yml +26 -0
- data/examples/v2/hooks/pre_tool_use_multi_matcher_exit_2.yml +27 -0
- data/examples/v2/hooks/swarm_summary.sh +44 -0
- data/examples/v2/hooks/user_prompt_exit_0.yml +21 -0
- data/examples/v2/hooks/user_prompt_exit_1.yml +21 -0
- data/examples/v2/hooks/user_prompt_exit_2.yml +21 -0
- data/examples/v2/hooks/validate_bash.rb +59 -0
- data/examples/v2/multi_directory_permissions.yml +221 -0
- data/examples/v2/node_context_demo.rb +127 -0
- data/examples/v2/node_workflow.rb +173 -0
- data/examples/v2/path_resolution_demo.rb +216 -0
- data/examples/v2/simple-swarm-v2.rb +90 -0
- data/examples/v2/simple-swarm-v2.yml +62 -0
- data/examples/v2/swarm.yml +71 -0
- data/examples/v2/swarm_with_hooks.yml +61 -0
- data/examples/v2/swarm_with_hooks_simple.yml +25 -0
- data/examples/v2/think_tool_demo.rb +62 -0
- data/exe/swarm +6 -0
- data/lib/claude_swarm/claude_mcp_server.rb +0 -6
- data/lib/claude_swarm/cli.rb +10 -3
- data/lib/claude_swarm/commands/ps.rb +19 -20
- data/lib/claude_swarm/commands/show.rb +1 -1
- data/lib/claude_swarm/configuration.rb +10 -12
- data/lib/claude_swarm/mcp_generator.rb +10 -1
- data/lib/claude_swarm/orchestrator.rb +73 -49
- data/lib/claude_swarm/system_utils.rb +37 -11
- data/lib/claude_swarm/version.rb +1 -1
- data/lib/claude_swarm/worktree_manager.rb +1 -0
- data/lib/claude_swarm/yaml_loader.rb +22 -0
- data/lib/claude_swarm.rb +6 -2
- data/lib/swarm_cli/cli.rb +201 -0
- data/lib/swarm_cli/command_registry.rb +61 -0
- data/lib/swarm_cli/commands/mcp_serve.rb +130 -0
- data/lib/swarm_cli/commands/mcp_tools.rb +148 -0
- data/lib/swarm_cli/commands/migrate.rb +55 -0
- data/lib/swarm_cli/commands/run.rb +173 -0
- data/lib/swarm_cli/config_loader.rb +97 -0
- data/lib/swarm_cli/formatters/human_formatter.rb +711 -0
- data/lib/swarm_cli/formatters/json_formatter.rb +51 -0
- data/lib/swarm_cli/interactive_repl.rb +918 -0
- data/lib/swarm_cli/mcp_serve_options.rb +44 -0
- data/lib/swarm_cli/mcp_tools_options.rb +59 -0
- data/lib/swarm_cli/migrate_options.rb +54 -0
- data/lib/swarm_cli/migrator.rb +132 -0
- data/lib/swarm_cli/options.rb +151 -0
- data/lib/swarm_cli/ui/components/agent_badge.rb +33 -0
- data/lib/swarm_cli/ui/components/content_block.rb +120 -0
- data/lib/swarm_cli/ui/components/divider.rb +57 -0
- data/lib/swarm_cli/ui/components/panel.rb +62 -0
- data/lib/swarm_cli/ui/components/usage_stats.rb +70 -0
- data/lib/swarm_cli/ui/formatters/cost.rb +49 -0
- data/lib/swarm_cli/ui/formatters/number.rb +58 -0
- data/lib/swarm_cli/ui/formatters/text.rb +77 -0
- data/lib/swarm_cli/ui/formatters/time.rb +73 -0
- data/lib/swarm_cli/ui/icons.rb +59 -0
- data/lib/swarm_cli/ui/renderers/event_renderer.rb +188 -0
- data/lib/swarm_cli/ui/state/agent_color_cache.rb +45 -0
- data/lib/swarm_cli/ui/state/depth_tracker.rb +40 -0
- data/lib/swarm_cli/ui/state/spinner_manager.rb +170 -0
- data/lib/swarm_cli/ui/state/usage_tracker.rb +62 -0
- data/lib/swarm_cli/version.rb +5 -0
- data/lib/swarm_cli.rb +44 -0
- data/lib/swarm_memory/adapters/base.rb +141 -0
- data/lib/swarm_memory/adapters/filesystem_adapter.rb +845 -0
- data/lib/swarm_memory/chat_extension.rb +34 -0
- data/lib/swarm_memory/cli/commands.rb +306 -0
- data/lib/swarm_memory/core/entry.rb +37 -0
- data/lib/swarm_memory/core/frontmatter_parser.rb +108 -0
- data/lib/swarm_memory/core/metadata_extractor.rb +68 -0
- data/lib/swarm_memory/core/path_normalizer.rb +75 -0
- data/lib/swarm_memory/core/semantic_index.rb +244 -0
- data/lib/swarm_memory/core/storage.rb +288 -0
- data/lib/swarm_memory/core/storage_read_tracker.rb +63 -0
- data/lib/swarm_memory/dsl/builder_extension.rb +40 -0
- data/lib/swarm_memory/dsl/memory_config.rb +113 -0
- data/lib/swarm_memory/embeddings/embedder.rb +36 -0
- data/lib/swarm_memory/embeddings/informers_embedder.rb +152 -0
- data/lib/swarm_memory/errors.rb +21 -0
- data/lib/swarm_memory/integration/cli_registration.rb +30 -0
- data/lib/swarm_memory/integration/configuration.rb +43 -0
- data/lib/swarm_memory/integration/registration.rb +31 -0
- data/lib/swarm_memory/integration/sdk_plugin.rb +531 -0
- data/lib/swarm_memory/optimization/analyzer.rb +244 -0
- data/lib/swarm_memory/optimization/defragmenter.rb +863 -0
- data/lib/swarm_memory/prompts/memory.md.erb +109 -0
- data/lib/swarm_memory/prompts/memory_assistant.md.erb +181 -0
- data/lib/swarm_memory/prompts/memory_researcher.md.erb +281 -0
- data/lib/swarm_memory/prompts/memory_retrieval.md.erb +78 -0
- data/lib/swarm_memory/search/semantic_search.rb +112 -0
- data/lib/swarm_memory/search/text_search.rb +42 -0
- data/lib/swarm_memory/search/text_similarity.rb +80 -0
- data/lib/swarm_memory/skills/meta/deep-learning.md +101 -0
- data/lib/swarm_memory/skills/meta/deep-learning.yml +14 -0
- data/lib/swarm_memory/tools/load_skill.rb +313 -0
- data/lib/swarm_memory/tools/memory_defrag.rb +382 -0
- data/lib/swarm_memory/tools/memory_delete.rb +99 -0
- data/lib/swarm_memory/tools/memory_edit.rb +185 -0
- data/lib/swarm_memory/tools/memory_glob.rb +160 -0
- data/lib/swarm_memory/tools/memory_grep.rb +247 -0
- data/lib/swarm_memory/tools/memory_multi_edit.rb +281 -0
- data/lib/swarm_memory/tools/memory_read.rb +123 -0
- data/lib/swarm_memory/tools/memory_write.rb +231 -0
- data/lib/swarm_memory/utils.rb +50 -0
- data/lib/swarm_memory/version.rb +5 -0
- data/lib/swarm_memory.rb +166 -0
- data/lib/swarm_sdk/agent/RETRY_LOGIC.md +127 -0
- data/lib/swarm_sdk/agent/builder.rb +461 -0
- data/lib/swarm_sdk/agent/chat/context_tracker.rb +314 -0
- data/lib/swarm_sdk/agent/chat/hook_integration.rb +372 -0
- data/lib/swarm_sdk/agent/chat/logging_helpers.rb +116 -0
- data/lib/swarm_sdk/agent/chat/system_reminder_injector.rb +152 -0
- data/lib/swarm_sdk/agent/chat.rb +1159 -0
- data/lib/swarm_sdk/agent/context.rb +112 -0
- data/lib/swarm_sdk/agent/context_manager.rb +309 -0
- data/lib/swarm_sdk/agent/definition.rb +556 -0
- data/lib/swarm_sdk/claude_code_agent_adapter.rb +205 -0
- data/lib/swarm_sdk/configuration.rb +296 -0
- data/lib/swarm_sdk/context_compactor/metrics.rb +147 -0
- data/lib/swarm_sdk/context_compactor/token_counter.rb +106 -0
- data/lib/swarm_sdk/context_compactor.rb +340 -0
- data/lib/swarm_sdk/hooks/adapter.rb +359 -0
- data/lib/swarm_sdk/hooks/context.rb +197 -0
- data/lib/swarm_sdk/hooks/definition.rb +80 -0
- data/lib/swarm_sdk/hooks/error.rb +29 -0
- data/lib/swarm_sdk/hooks/executor.rb +146 -0
- data/lib/swarm_sdk/hooks/registry.rb +147 -0
- data/lib/swarm_sdk/hooks/result.rb +150 -0
- data/lib/swarm_sdk/hooks/shell_executor.rb +254 -0
- data/lib/swarm_sdk/hooks/tool_call.rb +35 -0
- data/lib/swarm_sdk/hooks/tool_result.rb +62 -0
- data/lib/swarm_sdk/log_collector.rb +51 -0
- data/lib/swarm_sdk/log_stream.rb +69 -0
- data/lib/swarm_sdk/markdown_parser.rb +75 -0
- data/lib/swarm_sdk/model_aliases.json +5 -0
- data/lib/swarm_sdk/models.json +1 -0
- data/lib/swarm_sdk/models.rb +120 -0
- data/lib/swarm_sdk/node/agent_config.rb +49 -0
- data/lib/swarm_sdk/node/builder.rb +439 -0
- data/lib/swarm_sdk/node/transformer_executor.rb +248 -0
- data/lib/swarm_sdk/node_context.rb +170 -0
- data/lib/swarm_sdk/node_orchestrator.rb +384 -0
- data/lib/swarm_sdk/permissions/config.rb +239 -0
- data/lib/swarm_sdk/permissions/error_formatter.rb +121 -0
- data/lib/swarm_sdk/permissions/path_matcher.rb +35 -0
- data/lib/swarm_sdk/permissions/validator.rb +173 -0
- data/lib/swarm_sdk/permissions_builder.rb +122 -0
- data/lib/swarm_sdk/plugin.rb +147 -0
- data/lib/swarm_sdk/plugin_registry.rb +101 -0
- data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +243 -0
- data/lib/swarm_sdk/providers/openai_with_responses.rb +582 -0
- data/lib/swarm_sdk/result.rb +97 -0
- data/lib/swarm_sdk/swarm/agent_initializer.rb +334 -0
- data/lib/swarm_sdk/swarm/all_agents_builder.rb +140 -0
- data/lib/swarm_sdk/swarm/builder.rb +586 -0
- data/lib/swarm_sdk/swarm/mcp_configurator.rb +151 -0
- data/lib/swarm_sdk/swarm/tool_configurator.rb +419 -0
- data/lib/swarm_sdk/swarm.rb +982 -0
- data/lib/swarm_sdk/tools/bash.rb +274 -0
- data/lib/swarm_sdk/tools/clock.rb +44 -0
- data/lib/swarm_sdk/tools/delegate.rb +164 -0
- data/lib/swarm_sdk/tools/document_converters/base_converter.rb +83 -0
- data/lib/swarm_sdk/tools/document_converters/docx_converter.rb +99 -0
- data/lib/swarm_sdk/tools/document_converters/html_converter.rb +101 -0
- data/lib/swarm_sdk/tools/document_converters/pdf_converter.rb +78 -0
- data/lib/swarm_sdk/tools/document_converters/xlsx_converter.rb +194 -0
- data/lib/swarm_sdk/tools/edit.rb +150 -0
- data/lib/swarm_sdk/tools/glob.rb +158 -0
- data/lib/swarm_sdk/tools/grep.rb +228 -0
- data/lib/swarm_sdk/tools/image_extractors/docx_image_extractor.rb +43 -0
- data/lib/swarm_sdk/tools/image_extractors/pdf_image_extractor.rb +163 -0
- data/lib/swarm_sdk/tools/image_formats/tiff_builder.rb +65 -0
- data/lib/swarm_sdk/tools/multi_edit.rb +232 -0
- data/lib/swarm_sdk/tools/path_resolver.rb +43 -0
- data/lib/swarm_sdk/tools/read.rb +251 -0
- data/lib/swarm_sdk/tools/registry.rb +93 -0
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +96 -0
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +76 -0
- data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +91 -0
- data/lib/swarm_sdk/tools/stores/read_tracker.rb +61 -0
- data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +224 -0
- data/lib/swarm_sdk/tools/stores/storage.rb +148 -0
- data/lib/swarm_sdk/tools/stores/todo_manager.rb +65 -0
- data/lib/swarm_sdk/tools/think.rb +95 -0
- data/lib/swarm_sdk/tools/todo_write.rb +216 -0
- data/lib/swarm_sdk/tools/web_fetch.rb +261 -0
- data/lib/swarm_sdk/tools/write.rb +117 -0
- data/lib/swarm_sdk/utils.rb +50 -0
- data/lib/swarm_sdk/version.rb +5 -0
- data/lib/swarm_sdk.rb +157 -0
- data/llm.v2.txt +13407 -0
- data/rubocop/cop/security/no_reflection_methods.rb +47 -0
- data/rubocop/cop/security/no_ruby_llm_logger.rb +32 -0
- data/swarm_cli.gemspec +57 -0
- data/swarm_memory.gemspec +28 -0
- data/swarm_sdk.gemspec +41 -0
- data/team.yml +1 -1
- data/team_full.yml +1875 -0
- data/{team_v2.yml → team_sdk.yml} +121 -52
- metadata +247 -4
- data/EXAMPLES.md +0 -164
|
@@ -0,0 +1,2154 @@
|
|
|
1
|
+
# Ruby DSL Reference
|
|
2
|
+
|
|
3
|
+
Complete Ruby DSL API reference for building swarms programmatically.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The Ruby DSL provides a fluent, type-safe API for building swarms with IDE support and Ruby's full language features. All configuration can be done programmatically with variables, conditionals, loops, and functions.
|
|
10
|
+
|
|
11
|
+
**Key benefits:**
|
|
12
|
+
- Full Ruby language features (variables, conditionals, loops, functions)
|
|
13
|
+
- Ruby blocks for hooks (inline logic, no external scripts)
|
|
14
|
+
- Type-safe, chainable API
|
|
15
|
+
- IDE autocompletion and inline documentation
|
|
16
|
+
|
|
17
|
+
**Basic structure:**
|
|
18
|
+
```ruby
|
|
19
|
+
swarm = SwarmSDK.build do
|
|
20
|
+
name "Swarm Name"
|
|
21
|
+
lead :agent_name
|
|
22
|
+
|
|
23
|
+
agent :agent_name do
|
|
24
|
+
# Agent configuration
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
result = swarm.execute("Task prompt")
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Top-Level Methods
|
|
34
|
+
|
|
35
|
+
### SwarmSDK.configure
|
|
36
|
+
|
|
37
|
+
Configure global SwarmSDK settings.
|
|
38
|
+
|
|
39
|
+
**Signature:**
|
|
40
|
+
```ruby
|
|
41
|
+
SwarmSDK.configure {|config| ... } → void
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Parameters:**
|
|
45
|
+
- `block` (required): Configuration block
|
|
46
|
+
|
|
47
|
+
**Available settings:**
|
|
48
|
+
- `webfetch_provider` (String): LLM provider for WebFetch tool (e.g., "anthropic", "openai", "ollama")
|
|
49
|
+
- `webfetch_model` (String): Model name for WebFetch tool (e.g., "claude-3-5-haiku-20241022")
|
|
50
|
+
- `webfetch_base_url` (String, optional): Custom base URL for the provider
|
|
51
|
+
- `webfetch_max_tokens` (Integer): Maximum tokens for WebFetch LLM responses (default: 4096)
|
|
52
|
+
|
|
53
|
+
**Description:**
|
|
54
|
+
Global configuration that applies to all swarms. Currently used to configure the WebFetch tool's LLM processing behavior.
|
|
55
|
+
|
|
56
|
+
When `webfetch_provider` and `webfetch_model` are set, the WebFetch tool will process fetched web content using the configured LLM. Without this configuration, WebFetch returns raw markdown.
|
|
57
|
+
|
|
58
|
+
**Example:**
|
|
59
|
+
```ruby
|
|
60
|
+
# Configure WebFetch to use Anthropic's Claude Haiku
|
|
61
|
+
SwarmSDK.configure do |config|
|
|
62
|
+
config.webfetch_provider = "anthropic"
|
|
63
|
+
config.webfetch_model = "claude-3-5-haiku-20241022"
|
|
64
|
+
config.webfetch_max_tokens = 4096
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Configure WebFetch to use local Ollama
|
|
68
|
+
SwarmSDK.configure do |config|
|
|
69
|
+
config.webfetch_provider = "ollama"
|
|
70
|
+
config.webfetch_model = "llama3.2"
|
|
71
|
+
config.webfetch_base_url = "http://localhost:11434"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Reset to defaults (disables WebFetch LLM processing)
|
|
75
|
+
SwarmSDK.reset_settings!
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### SwarmSDK.build
|
|
81
|
+
|
|
82
|
+
Build a swarm using the DSL.
|
|
83
|
+
|
|
84
|
+
**Signature:**
|
|
85
|
+
```ruby
|
|
86
|
+
SwarmSDK.build(&block) → Swarm | NodeOrchestrator
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Parameters:**
|
|
90
|
+
- `block` (required): Configuration block
|
|
91
|
+
|
|
92
|
+
**Returns:**
|
|
93
|
+
- `Swarm`: For single-swarm configurations
|
|
94
|
+
- `NodeOrchestrator`: For multi-node workflow configurations
|
|
95
|
+
|
|
96
|
+
**Example:**
|
|
97
|
+
```ruby
|
|
98
|
+
swarm = SwarmSDK.build do
|
|
99
|
+
name "Development Team"
|
|
100
|
+
lead :backend
|
|
101
|
+
|
|
102
|
+
agent :backend do
|
|
103
|
+
model "gpt-5"
|
|
104
|
+
tools :Read, :Write, :Bash
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### SwarmSDK.refresh_models_silently
|
|
112
|
+
|
|
113
|
+
Refresh the LLM model registry silently (called automatically by CLI).
|
|
114
|
+
|
|
115
|
+
**Signature:**
|
|
116
|
+
```ruby
|
|
117
|
+
SwarmSDK.refresh_models_silently → void
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Description:**
|
|
121
|
+
Updates RubyLLM's model registry to ensure latest model information is available. Called automatically by SwarmCLI before execution.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Swarm Builder DSL
|
|
126
|
+
|
|
127
|
+
Methods available in the `SwarmSDK.build` block.
|
|
128
|
+
|
|
129
|
+
### name
|
|
130
|
+
|
|
131
|
+
Set the swarm name.
|
|
132
|
+
|
|
133
|
+
**Signature:**
|
|
134
|
+
```ruby
|
|
135
|
+
name(swarm_name) → void
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Parameters:**
|
|
139
|
+
- `swarm_name` (String, required): Human-readable swarm name
|
|
140
|
+
|
|
141
|
+
**Example:**
|
|
142
|
+
```ruby
|
|
143
|
+
name "Development Team"
|
|
144
|
+
name "Code Review Swarm"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### lead
|
|
150
|
+
|
|
151
|
+
Set the lead agent (entry point for execution).
|
|
152
|
+
|
|
153
|
+
**Signature:**
|
|
154
|
+
```ruby
|
|
155
|
+
lead(agent_name) → void
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Parameters:**
|
|
159
|
+
- `agent_name` (Symbol, required): Name of lead agent
|
|
160
|
+
|
|
161
|
+
**Example:**
|
|
162
|
+
```ruby
|
|
163
|
+
lead :backend
|
|
164
|
+
lead :coordinator
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### use_scratchpad
|
|
170
|
+
|
|
171
|
+
Enable or disable shared scratchpad tools for all agents.
|
|
172
|
+
|
|
173
|
+
**Signature:**
|
|
174
|
+
```ruby
|
|
175
|
+
use_scratchpad(enabled) → void
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Parameters:**
|
|
179
|
+
- `enabled` (Boolean, required): Whether to enable scratchpad tools
|
|
180
|
+
|
|
181
|
+
**Default:** `true` (scratchpad tools enabled)
|
|
182
|
+
|
|
183
|
+
**Description:**
|
|
184
|
+
Controls whether agents have access to scratchpad tools (ScratchpadWrite, ScratchpadRead, ScratchpadList). Scratchpad is volatile (in-memory only) and shared across all agents in the swarm.
|
|
185
|
+
|
|
186
|
+
**Example:**
|
|
187
|
+
```ruby
|
|
188
|
+
# Enable scratchpad (default)
|
|
189
|
+
use_scratchpad true
|
|
190
|
+
|
|
191
|
+
# Disable scratchpad
|
|
192
|
+
use_scratchpad false
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### agent
|
|
198
|
+
|
|
199
|
+
Define an agent with its configuration.
|
|
200
|
+
|
|
201
|
+
**Signature:**
|
|
202
|
+
```ruby
|
|
203
|
+
agent(name, &block) → void
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Parameters:**
|
|
207
|
+
- `name` (Symbol, required): Agent name
|
|
208
|
+
- `block` (required): Agent configuration block
|
|
209
|
+
|
|
210
|
+
**Example:**
|
|
211
|
+
```ruby
|
|
212
|
+
agent :backend do
|
|
213
|
+
model "gpt-5"
|
|
214
|
+
description "Backend API developer"
|
|
215
|
+
tools :Read, :Write, :Bash
|
|
216
|
+
delegates_to :database
|
|
217
|
+
|
|
218
|
+
hook :pre_tool_use, matcher: "Bash" do |ctx|
|
|
219
|
+
ctx.halt("Dangerous command") if ctx.tool_call.parameters[:command].include?("rm -rf")
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
### all_agents
|
|
227
|
+
|
|
228
|
+
Configure settings that apply to all agents.
|
|
229
|
+
|
|
230
|
+
**Signature:**
|
|
231
|
+
```ruby
|
|
232
|
+
all_agents(&block) → void
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Parameters:**
|
|
236
|
+
- `block` (required): Configuration block (uses [AllAgentsBuilder DSL](#all-agents-builder-dsl))
|
|
237
|
+
|
|
238
|
+
**Description:**
|
|
239
|
+
Settings configured here apply to ALL agents but can be overridden at the agent level. Useful for shared configuration like provider, timeout, or global permissions.
|
|
240
|
+
|
|
241
|
+
**Example:**
|
|
242
|
+
```ruby
|
|
243
|
+
all_agents do
|
|
244
|
+
provider :openai
|
|
245
|
+
base_url "http://proxy.example.com/v1"
|
|
246
|
+
timeout 180
|
|
247
|
+
tools :Read, :Write
|
|
248
|
+
coding_agent false
|
|
249
|
+
|
|
250
|
+
permissions do
|
|
251
|
+
tool(:Write).deny_paths "secrets/**"
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
hook :pre_tool_use, matcher: "Write" do |ctx|
|
|
255
|
+
# Validation for all agents
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
### hook
|
|
263
|
+
|
|
264
|
+
Add a swarm-level hook (swarm_start or swarm_stop only).
|
|
265
|
+
|
|
266
|
+
**Signature:**
|
|
267
|
+
```ruby
|
|
268
|
+
hook(event, command: nil, timeout: nil, &block) → void
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Parameters:**
|
|
272
|
+
- `event` (Symbol, required): Event type (`:swarm_start` or `:swarm_stop`)
|
|
273
|
+
- `command` (String, optional): Shell command to execute
|
|
274
|
+
- `timeout` (Integer, optional): Command timeout in seconds (default: 60)
|
|
275
|
+
- `block` (optional): Ruby block for inline logic
|
|
276
|
+
|
|
277
|
+
**Valid events:** `:swarm_start`, `:swarm_stop`
|
|
278
|
+
|
|
279
|
+
**Example with block:**
|
|
280
|
+
```ruby
|
|
281
|
+
hook :swarm_start do |ctx|
|
|
282
|
+
puts "Swarm starting: #{ctx.metadata[:prompt]}"
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
hook :swarm_stop do |ctx|
|
|
286
|
+
puts "Duration: #{ctx.metadata[:duration]}s"
|
|
287
|
+
puts "Cost: $#{ctx.metadata[:total_cost]}"
|
|
288
|
+
end
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**Example with command:**
|
|
292
|
+
```ruby
|
|
293
|
+
hook :swarm_start, command: "echo 'Starting' >> log.txt"
|
|
294
|
+
hook :swarm_stop, command: "scripts/cleanup.sh", timeout: 30
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
### node
|
|
300
|
+
|
|
301
|
+
Define a node (stage in multi-step workflow).
|
|
302
|
+
|
|
303
|
+
**Signature:**
|
|
304
|
+
```ruby
|
|
305
|
+
node(name, &block) → void
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**Parameters:**
|
|
309
|
+
- `name` (Symbol, required): Node name
|
|
310
|
+
- `block` (required): Node configuration block (uses [NodeBuilder DSL](#node-builder-dsl))
|
|
311
|
+
|
|
312
|
+
**Description:**
|
|
313
|
+
Nodes enable multi-stage workflows where different agent teams collaborate in sequence. Each node is an independent swarm execution.
|
|
314
|
+
|
|
315
|
+
**Example:**
|
|
316
|
+
```ruby
|
|
317
|
+
node :planning do
|
|
318
|
+
agent(:architect)
|
|
319
|
+
|
|
320
|
+
input do |ctx|
|
|
321
|
+
"Plan this task: #{ctx.original_prompt}"
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
output do |ctx|
|
|
325
|
+
File.write("plan.txt", ctx.content)
|
|
326
|
+
"Key decisions: #{extract_decisions(ctx.content)}"
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
node :implementation do
|
|
331
|
+
agent(:backend).delegates_to(:tester)
|
|
332
|
+
agent(:tester)
|
|
333
|
+
|
|
334
|
+
depends_on :planning
|
|
335
|
+
|
|
336
|
+
input do |ctx|
|
|
337
|
+
plan = ctx.all_results[:planning].content
|
|
338
|
+
"Implement based on:\n#{plan}"
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
### start_node
|
|
346
|
+
|
|
347
|
+
Set the starting node for workflow execution.
|
|
348
|
+
|
|
349
|
+
**Signature:**
|
|
350
|
+
```ruby
|
|
351
|
+
start_node(name) → void
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**Parameters:**
|
|
355
|
+
- `name` (Symbol, required): Name of starting node
|
|
356
|
+
|
|
357
|
+
**Required when:** Nodes are defined
|
|
358
|
+
|
|
359
|
+
**Example:**
|
|
360
|
+
```ruby
|
|
361
|
+
start_node :planning
|
|
362
|
+
|
|
363
|
+
node :planning do
|
|
364
|
+
# ...
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
node :implementation do
|
|
368
|
+
depends_on :planning
|
|
369
|
+
end
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Agent Builder DSL
|
|
375
|
+
|
|
376
|
+
Methods available in the `agent` block.
|
|
377
|
+
|
|
378
|
+
### model
|
|
379
|
+
|
|
380
|
+
Set the LLM model.
|
|
381
|
+
|
|
382
|
+
**Signature:**
|
|
383
|
+
```ruby
|
|
384
|
+
model(model_name) → void
|
|
385
|
+
model() → String # getter
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**Parameters:**
|
|
389
|
+
- `model_name` (String, required): Model identifier
|
|
390
|
+
|
|
391
|
+
**Default:** `"gpt-5"`
|
|
392
|
+
|
|
393
|
+
**Common models:**
|
|
394
|
+
- OpenAI: `"gpt-5"`, `"gpt-4o"`, `"o4"`, `"o4-mini"`
|
|
395
|
+
- Anthropic: `"claude-sonnet-4"`, `"claude-opus-4"`
|
|
396
|
+
- Google: `"gemini-2.5-flash"`, `"gemini-2.0-pro"`
|
|
397
|
+
- DeepSeek: `"deepseek-chat"`, `"deepseek-reasoner"`
|
|
398
|
+
|
|
399
|
+
**Example:**
|
|
400
|
+
```ruby
|
|
401
|
+
model "gpt-5"
|
|
402
|
+
model "claude-sonnet-4"
|
|
403
|
+
model "deepseek-reasoner"
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
### provider
|
|
409
|
+
|
|
410
|
+
Set the LLM provider.
|
|
411
|
+
|
|
412
|
+
**Signature:**
|
|
413
|
+
```ruby
|
|
414
|
+
provider(provider_name) → void
|
|
415
|
+
provider() → String # getter
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**Parameters:**
|
|
419
|
+
- `provider_name` (String | Symbol, required): Provider name
|
|
420
|
+
|
|
421
|
+
**Default:** `"openai"`
|
|
422
|
+
|
|
423
|
+
**Supported providers:**
|
|
424
|
+
- `openai`: OpenAI
|
|
425
|
+
- `anthropic`: Anthropic Claude
|
|
426
|
+
- `google`: Google AI
|
|
427
|
+
- `deepseek`: DeepSeek
|
|
428
|
+
- `openrouter`: OpenRouter
|
|
429
|
+
- `mistral`: Mistral AI
|
|
430
|
+
- `perplexity`: Perplexity
|
|
431
|
+
|
|
432
|
+
**Example:**
|
|
433
|
+
```ruby
|
|
434
|
+
provider :openai
|
|
435
|
+
provider "anthropic"
|
|
436
|
+
provider :deepseek
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
### base_url
|
|
442
|
+
|
|
443
|
+
Set custom API endpoint (for proxies or compatible APIs).
|
|
444
|
+
|
|
445
|
+
**Signature:**
|
|
446
|
+
```ruby
|
|
447
|
+
base_url(url) → void
|
|
448
|
+
base_url() → String # getter
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
**Parameters:**
|
|
452
|
+
- `url` (String, required): API endpoint URL
|
|
453
|
+
|
|
454
|
+
**Default:** Provider's default endpoint
|
|
455
|
+
|
|
456
|
+
**Auto-sets:** `assume_model_exists: true` (skips model validation)
|
|
457
|
+
|
|
458
|
+
**Example:**
|
|
459
|
+
```ruby
|
|
460
|
+
base_url "http://localhost:8080/v1"
|
|
461
|
+
base_url "https://proxy.example.com/v1"
|
|
462
|
+
base_url "https://openrouter.ai/api/v1"
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
### api_version
|
|
468
|
+
|
|
469
|
+
Set API version for OpenAI-compatible providers.
|
|
470
|
+
|
|
471
|
+
**Signature:**
|
|
472
|
+
```ruby
|
|
473
|
+
api_version(version) → void
|
|
474
|
+
api_version() → String # getter
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
**Parameters:**
|
|
478
|
+
- `version` (String, required): API version path
|
|
479
|
+
|
|
480
|
+
**Valid values:**
|
|
481
|
+
- `"v1/chat/completions"`: Standard chat completions (default)
|
|
482
|
+
- `"v1/responses"`: Extended responses format
|
|
483
|
+
|
|
484
|
+
**Compatible providers:** `openai`, `deepseek`, `perplexity`, `mistral`, `openrouter`
|
|
485
|
+
|
|
486
|
+
**Example:**
|
|
487
|
+
```ruby
|
|
488
|
+
# Standard chat completions
|
|
489
|
+
api_version "v1/chat/completions"
|
|
490
|
+
|
|
491
|
+
# Extended responses
|
|
492
|
+
api_version "v1/responses"
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
### description
|
|
498
|
+
|
|
499
|
+
Set agent description (required).
|
|
500
|
+
|
|
501
|
+
**Signature:**
|
|
502
|
+
```ruby
|
|
503
|
+
description(text) → void
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
**Parameters:**
|
|
507
|
+
- `text` (String, required): Human-readable description
|
|
508
|
+
|
|
509
|
+
**Description:**
|
|
510
|
+
Describes the agent's role and responsibilities. Required for all agents.
|
|
511
|
+
|
|
512
|
+
**Example:**
|
|
513
|
+
```ruby
|
|
514
|
+
description "Backend API developer specializing in Ruby on Rails"
|
|
515
|
+
description "Frontend developer with React and TypeScript expertise"
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
### directory
|
|
521
|
+
|
|
522
|
+
Set agent's working directory.
|
|
523
|
+
|
|
524
|
+
**Signature:**
|
|
525
|
+
```ruby
|
|
526
|
+
directory(dir) → void
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
**Parameters:**
|
|
530
|
+
- `dir` (String, required): Directory path (absolute or relative)
|
|
531
|
+
|
|
532
|
+
**Default:** `"."`
|
|
533
|
+
|
|
534
|
+
**Description:**
|
|
535
|
+
All file operations (Read, Write, Edit) are relative to this directory. The directory must exist.
|
|
536
|
+
|
|
537
|
+
**Example:**
|
|
538
|
+
```ruby
|
|
539
|
+
directory "."
|
|
540
|
+
directory "backend"
|
|
541
|
+
directory "/absolute/path/to/workspace"
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
### system_prompt
|
|
547
|
+
|
|
548
|
+
Set custom system prompt text.
|
|
549
|
+
|
|
550
|
+
**Signature:**
|
|
551
|
+
```ruby
|
|
552
|
+
system_prompt(text) → void
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
**Parameters:**
|
|
556
|
+
- `text` (String, required): Custom prompt text
|
|
557
|
+
|
|
558
|
+
**Default:** `nil`
|
|
559
|
+
|
|
560
|
+
**Combination with `coding_agent`:**
|
|
561
|
+
- `coding_agent: false` (default): Uses only custom prompt + TODO/Scratchpad info
|
|
562
|
+
- `coding_agent: true`: Prepends base coding prompt, then custom prompt
|
|
563
|
+
|
|
564
|
+
**Example:**
|
|
565
|
+
```ruby
|
|
566
|
+
system_prompt "You are a backend API developer. Focus on clean, testable code."
|
|
567
|
+
system_prompt <<~PROMPT
|
|
568
|
+
You are a code reviewer. For each file:
|
|
569
|
+
1. Check for bugs and edge cases
|
|
570
|
+
2. Suggest improvements
|
|
571
|
+
3. Verify test coverage
|
|
572
|
+
PROMPT
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
### coding_agent
|
|
578
|
+
|
|
579
|
+
Enable/disable base coding prompt.
|
|
580
|
+
|
|
581
|
+
**Signature:**
|
|
582
|
+
```ruby
|
|
583
|
+
coding_agent(enabled) → void
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
**Parameters:**
|
|
587
|
+
- `enabled` (Boolean, required): Include base prompt
|
|
588
|
+
|
|
589
|
+
**Default:** `false`
|
|
590
|
+
|
|
591
|
+
**Behavior:**
|
|
592
|
+
- `false`: Uses only custom `system_prompt` + TODO/Scratchpad sections
|
|
593
|
+
- `true`: Prepends comprehensive base coding prompt, then custom prompt
|
|
594
|
+
|
|
595
|
+
**Example:**
|
|
596
|
+
```ruby
|
|
597
|
+
coding_agent true # Include base prompt for coding tasks
|
|
598
|
+
coding_agent false # Custom prompt only (default)
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
---
|
|
602
|
+
|
|
603
|
+
### tools
|
|
604
|
+
|
|
605
|
+
Add tools to the agent.
|
|
606
|
+
|
|
607
|
+
**Signature:**
|
|
608
|
+
```ruby
|
|
609
|
+
tools(*tool_names, include_default: true) → void
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
**Parameters:**
|
|
613
|
+
- `tool_names` (Symbol, variadic): Tool names to add
|
|
614
|
+
- `include_default` (Boolean, keyword): Include default tools
|
|
615
|
+
|
|
616
|
+
**Default tools (when `include_default: true`):**
|
|
617
|
+
- `Read`, `Glob`, `Grep`, `TodoWrite`, `Think`, `WebFetch`
|
|
618
|
+
|
|
619
|
+
**Scratchpad tools** (added if `scratchpad true` at swarm level, default):
|
|
620
|
+
- `ScratchpadWrite`, `ScratchpadRead`, `ScratchpadList`
|
|
621
|
+
|
|
622
|
+
**Memory tools** (added if agent has `memory` configured):
|
|
623
|
+
- `MemoryWrite`, `MemoryRead`, `MemoryEdit`, `MemoryMultiEdit`, `MemoryGlob`, `MemoryGrep`, `MemoryDelete`
|
|
624
|
+
|
|
625
|
+
**Additional tools:**
|
|
626
|
+
- `Write`, `Edit`, `MultiEdit`, `Bash`
|
|
627
|
+
|
|
628
|
+
**Behavior:**
|
|
629
|
+
- Multiple calls are cumulative (tools are merged)
|
|
630
|
+
- Duplicates are automatically removed (uses Set internally)
|
|
631
|
+
|
|
632
|
+
**Example:**
|
|
633
|
+
```ruby
|
|
634
|
+
# With defaults
|
|
635
|
+
tools :Write, :Bash
|
|
636
|
+
|
|
637
|
+
# Without defaults (explicit tools only)
|
|
638
|
+
tools :Read, :Write, :Bash, include_default: false
|
|
639
|
+
|
|
640
|
+
# Multiple calls (cumulative)
|
|
641
|
+
tools :Read, :Write
|
|
642
|
+
tools :Edit, :Bash # Now has: Read, Write, Edit, Bash + defaults
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
---
|
|
646
|
+
|
|
647
|
+
### delegates_to
|
|
648
|
+
|
|
649
|
+
Set delegation targets (agents this agent can delegate to).
|
|
650
|
+
|
|
651
|
+
**Signature:**
|
|
652
|
+
```ruby
|
|
653
|
+
delegates_to(*agent_names) → void
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
**Parameters:**
|
|
657
|
+
- `agent_names` (Symbol, variadic): Names of agents to delegate to
|
|
658
|
+
|
|
659
|
+
**Default:** `[]`
|
|
660
|
+
|
|
661
|
+
**Behavior:**
|
|
662
|
+
- Multiple calls are cumulative
|
|
663
|
+
- Creates a `DelegateTaskTo{Agent}` tool for each target (e.g., `DelegateTaskToDatabase`)
|
|
664
|
+
|
|
665
|
+
**Example:**
|
|
666
|
+
```ruby
|
|
667
|
+
delegates_to :database
|
|
668
|
+
delegates_to :tester, :reviewer
|
|
669
|
+
delegates_to :frontend # Cumulative - adds to existing list
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
---
|
|
673
|
+
|
|
674
|
+
### memory
|
|
675
|
+
|
|
676
|
+
Configure persistent memory storage for this agent.
|
|
677
|
+
|
|
678
|
+
**Signature:**
|
|
679
|
+
```ruby
|
|
680
|
+
memory(&block) → void
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
**Parameters:**
|
|
684
|
+
- `block` (required): Memory configuration block
|
|
685
|
+
|
|
686
|
+
**Block DSL:**
|
|
687
|
+
- `adapter(symbol)` - Storage adapter (default: `:filesystem`)
|
|
688
|
+
- `directory(string)` - Directory where memory.json will be stored (required)
|
|
689
|
+
|
|
690
|
+
**Description:**
|
|
691
|
+
Enables persistent memory for the agent. When configured, the agent automatically gets all 7 memory tools (MemoryWrite, MemoryRead, MemoryEdit, MemoryMultiEdit, MemoryGlob, MemoryGrep, MemoryDelete) and a memory system prompt is appended to help the agent use memory effectively.
|
|
692
|
+
|
|
693
|
+
Memory is per-agent (isolated) and persistent (survives across sessions).
|
|
694
|
+
|
|
695
|
+
**Example:**
|
|
696
|
+
```ruby
|
|
697
|
+
memory do
|
|
698
|
+
adapter :filesystem # optional, default
|
|
699
|
+
directory ".swarm/agent-memory"
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
# Minimal (adapter defaults to :filesystem)
|
|
703
|
+
memory do
|
|
704
|
+
directory ".swarm/my-agent"
|
|
705
|
+
end
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
**Future adapters:** `:sqlite`, `:faiss` (not yet implemented)
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
### mcp_server
|
|
713
|
+
|
|
714
|
+
Add an MCP server configuration.
|
|
715
|
+
|
|
716
|
+
**Signature:**
|
|
717
|
+
```ruby
|
|
718
|
+
mcp_server(name, **options) → void
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
**Parameters:**
|
|
722
|
+
- `name` (Symbol, required): MCP server name
|
|
723
|
+
- `options` (Hash, required): Server configuration
|
|
724
|
+
|
|
725
|
+
**Transport types:**
|
|
726
|
+
|
|
727
|
+
**stdio transport:**
|
|
728
|
+
```ruby
|
|
729
|
+
mcp_server :filesystem,
|
|
730
|
+
type: :stdio,
|
|
731
|
+
command: "npx",
|
|
732
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"],
|
|
733
|
+
env: { "VAR" => "value" } # optional
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
**sse transport:**
|
|
737
|
+
```ruby
|
|
738
|
+
mcp_server :web,
|
|
739
|
+
type: :sse,
|
|
740
|
+
url: "https://example.com/mcp",
|
|
741
|
+
headers: { authorization: "Bearer token" },
|
|
742
|
+
timeout: 60 # optional
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
**http transport:**
|
|
746
|
+
```ruby
|
|
747
|
+
mcp_server :api,
|
|
748
|
+
type: :http,
|
|
749
|
+
url: "https://api.example.com/mcp",
|
|
750
|
+
headers: { "api-key" => "key" },
|
|
751
|
+
timeout: 120 # optional
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
### permissions
|
|
757
|
+
|
|
758
|
+
Configure tool permissions.
|
|
759
|
+
|
|
760
|
+
**Signature:**
|
|
761
|
+
```ruby
|
|
762
|
+
permissions(&block) → void
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
**Parameters:**
|
|
766
|
+
- `block` (required): Permissions configuration block (uses [PermissionsBuilder DSL](#permissions-builder-dsl))
|
|
767
|
+
|
|
768
|
+
**Description:**
|
|
769
|
+
Defines path patterns and command patterns for tool access control. Uses glob patterns for paths and regex for commands.
|
|
770
|
+
|
|
771
|
+
**Example:**
|
|
772
|
+
```ruby
|
|
773
|
+
permissions do
|
|
774
|
+
tool(:Write).allow_paths "backend/**/*"
|
|
775
|
+
tool(:Write).deny_paths "backend/secrets/**"
|
|
776
|
+
tool(:Read).deny_paths "config/credentials.yml"
|
|
777
|
+
tool(:Bash).allow_commands "^git (status|diff|log)$"
|
|
778
|
+
tool(:Bash).deny_commands "^rm -rf"
|
|
779
|
+
end
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
---
|
|
783
|
+
|
|
784
|
+
### hook
|
|
785
|
+
|
|
786
|
+
Add a hook (Ruby block or shell command).
|
|
787
|
+
|
|
788
|
+
**Signature:**
|
|
789
|
+
```ruby
|
|
790
|
+
hook(event, matcher: nil, command: nil, timeout: nil, &block) → void
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
**Parameters:**
|
|
794
|
+
- `event` (Symbol, required): Event type
|
|
795
|
+
- `matcher` (String | Regexp, optional): Tool name pattern (for tool events)
|
|
796
|
+
- `command` (String, optional): Shell command to execute
|
|
797
|
+
- `timeout` (Integer, optional): Command timeout in seconds (default: 60)
|
|
798
|
+
- `block` (optional): Ruby block for inline logic
|
|
799
|
+
|
|
800
|
+
**Valid events:**
|
|
801
|
+
- `:pre_tool_use`: Before tool execution
|
|
802
|
+
- `:post_tool_use`: After tool execution
|
|
803
|
+
- `:user_prompt`: Before sending user message
|
|
804
|
+
- `:agent_stop`: When agent finishes
|
|
805
|
+
- `:first_message`: First user message (once per swarm)
|
|
806
|
+
- `:pre_delegation`: Before delegating to another agent
|
|
807
|
+
- `:post_delegation`: After delegation completes
|
|
808
|
+
- `:context_warning`: When context window threshold exceeded
|
|
809
|
+
|
|
810
|
+
**Example with block:**
|
|
811
|
+
```ruby
|
|
812
|
+
hook :pre_tool_use, matcher: "Bash" do |ctx|
|
|
813
|
+
if ctx.tool_call.parameters[:command].include?("rm -rf")
|
|
814
|
+
ctx.halt("Dangerous command blocked")
|
|
815
|
+
end
|
|
816
|
+
end
|
|
817
|
+
|
|
818
|
+
hook :post_tool_use, matcher: "Write|Edit" do |ctx|
|
|
819
|
+
puts "Modified: #{ctx.tool_call.parameters[:file_path]}"
|
|
820
|
+
end
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
**Example with command:**
|
|
824
|
+
```ruby
|
|
825
|
+
hook :pre_tool_use, matcher: "Write|Edit", command: "scripts/validate.sh"
|
|
826
|
+
hook :post_tool_use, matcher: "Bash", command: "logger 'Command executed'", timeout: 10
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
---
|
|
830
|
+
|
|
831
|
+
### parameters
|
|
832
|
+
|
|
833
|
+
Set LLM parameters (temperature, top_p, etc.).
|
|
834
|
+
|
|
835
|
+
**Signature:**
|
|
836
|
+
```ruby
|
|
837
|
+
parameters(params) → void
|
|
838
|
+
parameters() → Hash # getter
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
**Parameters:**
|
|
842
|
+
- `params` (Hash, required): LLM parameters
|
|
843
|
+
|
|
844
|
+
**Common parameters:**
|
|
845
|
+
- `temperature` (Float): Randomness (0.0-2.0)
|
|
846
|
+
- `top_p` (Float): Nucleus sampling (0.0-1.0)
|
|
847
|
+
- `max_tokens` (Integer): Maximum output tokens
|
|
848
|
+
- `presence_penalty` (Float): Presence penalty (-2.0-2.0)
|
|
849
|
+
- `frequency_penalty` (Float): Frequency penalty (-2.0-2.0)
|
|
850
|
+
|
|
851
|
+
**Example:**
|
|
852
|
+
```ruby
|
|
853
|
+
parameters temperature: 0.7, top_p: 0.95
|
|
854
|
+
parameters max_tokens: 2000, presence_penalty: 0.1
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
---
|
|
858
|
+
|
|
859
|
+
### headers
|
|
860
|
+
|
|
861
|
+
Set custom HTTP headers for API requests.
|
|
862
|
+
|
|
863
|
+
**Signature:**
|
|
864
|
+
```ruby
|
|
865
|
+
headers(header_hash) → void
|
|
866
|
+
headers() → Hash # getter
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
**Parameters:**
|
|
870
|
+
- `header_hash` (Hash, required): HTTP headers
|
|
871
|
+
|
|
872
|
+
**Example:**
|
|
873
|
+
```ruby
|
|
874
|
+
headers "X-API-Key" => "key123", "X-Organization" => "org123"
|
|
875
|
+
headers authorization: "Bearer token"
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
---
|
|
879
|
+
|
|
880
|
+
### timeout
|
|
881
|
+
|
|
882
|
+
Set request timeout.
|
|
883
|
+
|
|
884
|
+
**Signature:**
|
|
885
|
+
```ruby
|
|
886
|
+
timeout(seconds) → void
|
|
887
|
+
timeout() → Integer # getter
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
**Parameters:**
|
|
891
|
+
- `seconds` (Integer, required): Timeout in seconds
|
|
892
|
+
|
|
893
|
+
**Default:** `300` (5 minutes)
|
|
894
|
+
|
|
895
|
+
**Example:**
|
|
896
|
+
```ruby
|
|
897
|
+
timeout 180 # 3 minutes
|
|
898
|
+
timeout 600 # 10 minutes for reasoning models
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
---
|
|
902
|
+
|
|
903
|
+
### context_window
|
|
904
|
+
|
|
905
|
+
Set explicit context window size.
|
|
906
|
+
|
|
907
|
+
**Signature:**
|
|
908
|
+
```ruby
|
|
909
|
+
context_window(tokens) → void
|
|
910
|
+
context_window() → Integer # getter
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
**Parameters:**
|
|
914
|
+
- `tokens` (Integer, required): Context window size in tokens
|
|
915
|
+
|
|
916
|
+
**Default:** Auto-detected from model registry
|
|
917
|
+
|
|
918
|
+
**Use case:** Override when using custom models or proxies
|
|
919
|
+
|
|
920
|
+
**Example:**
|
|
921
|
+
```ruby
|
|
922
|
+
context_window 128000 # Override for custom model
|
|
923
|
+
context_window 200000 # Large context window
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
---
|
|
927
|
+
|
|
928
|
+
### bypass_permissions
|
|
929
|
+
|
|
930
|
+
Disable permission checks for this agent.
|
|
931
|
+
|
|
932
|
+
**Signature:**
|
|
933
|
+
```ruby
|
|
934
|
+
bypass_permissions(enabled) → void
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
**Parameters:**
|
|
938
|
+
- `enabled` (Boolean, required): Bypass permissions
|
|
939
|
+
|
|
940
|
+
**Default:** `false`
|
|
941
|
+
|
|
942
|
+
**Warning:** Use with caution - allows unrestricted file/command access
|
|
943
|
+
|
|
944
|
+
**Example:**
|
|
945
|
+
```ruby
|
|
946
|
+
bypass_permissions true # Disable all permission checks
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
---
|
|
950
|
+
|
|
951
|
+
### max_concurrent_tools
|
|
952
|
+
|
|
953
|
+
Set maximum concurrent tool calls.
|
|
954
|
+
|
|
955
|
+
**Signature:**
|
|
956
|
+
```ruby
|
|
957
|
+
max_concurrent_tools(count) → void
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
**Parameters:**
|
|
961
|
+
- `count` (Integer, required): Max concurrent tools
|
|
962
|
+
|
|
963
|
+
**Default:** Swarm's `default_local_concurrency` (10)
|
|
964
|
+
|
|
965
|
+
**Example:**
|
|
966
|
+
```ruby
|
|
967
|
+
max_concurrent_tools 5 # Limit concurrent tools
|
|
968
|
+
max_concurrent_tools 20 # Allow more parallelism
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
---
|
|
972
|
+
|
|
973
|
+
### disable_default_tools
|
|
974
|
+
|
|
975
|
+
Include default tools (Read, Grep, Glob, TodoWrite, Think, and scratchpad tools).
|
|
976
|
+
|
|
977
|
+
**Signature:**
|
|
978
|
+
```ruby
|
|
979
|
+
disable_default_tools(value) → void
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
**Parameters:**
|
|
983
|
+
- `enabled` (Boolean, required): Include defaults
|
|
984
|
+
|
|
985
|
+
**Default:** `true`
|
|
986
|
+
|
|
987
|
+
**Note:** Prefer `tools(..., include_default: false)` for explicit control
|
|
988
|
+
|
|
989
|
+
**Example:**
|
|
990
|
+
```ruby
|
|
991
|
+
disable_default_tools true # No default tools
|
|
992
|
+
```
|
|
993
|
+
|
|
994
|
+
---
|
|
995
|
+
|
|
996
|
+
### assume_model_exists
|
|
997
|
+
|
|
998
|
+
Skip model validation (for custom models).
|
|
999
|
+
|
|
1000
|
+
**Signature:**
|
|
1001
|
+
```ruby
|
|
1002
|
+
assume_model_exists(enabled) → void
|
|
1003
|
+
```
|
|
1004
|
+
|
|
1005
|
+
**Parameters:**
|
|
1006
|
+
- `enabled` (Boolean, required): Skip validation
|
|
1007
|
+
|
|
1008
|
+
**Default:** `false` (validate), `true` when `base_url` is set
|
|
1009
|
+
|
|
1010
|
+
**Example:**
|
|
1011
|
+
```ruby
|
|
1012
|
+
assume_model_exists true # Skip validation for custom model
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
---
|
|
1016
|
+
|
|
1017
|
+
## All-Agents Builder DSL
|
|
1018
|
+
|
|
1019
|
+
Methods available in the `all_agents` block.
|
|
1020
|
+
|
|
1021
|
+
### model
|
|
1022
|
+
|
|
1023
|
+
Set default model for all agents.
|
|
1024
|
+
|
|
1025
|
+
**Signature:**
|
|
1026
|
+
```ruby
|
|
1027
|
+
model(model_name) → void
|
|
1028
|
+
```
|
|
1029
|
+
|
|
1030
|
+
**Parameters:**
|
|
1031
|
+
- `model_name` (String, required): Model identifier
|
|
1032
|
+
|
|
1033
|
+
**Example:**
|
|
1034
|
+
```ruby
|
|
1035
|
+
all_agents do
|
|
1036
|
+
model "gpt-5"
|
|
1037
|
+
end
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
---
|
|
1041
|
+
|
|
1042
|
+
### provider
|
|
1043
|
+
|
|
1044
|
+
Set default provider for all agents.
|
|
1045
|
+
|
|
1046
|
+
**Signature:**
|
|
1047
|
+
```ruby
|
|
1048
|
+
provider(provider_name) → void
|
|
1049
|
+
```
|
|
1050
|
+
|
|
1051
|
+
**Parameters:**
|
|
1052
|
+
- `provider_name` (String | Symbol, required): Provider name
|
|
1053
|
+
|
|
1054
|
+
**Example:**
|
|
1055
|
+
```ruby
|
|
1056
|
+
all_agents do
|
|
1057
|
+
provider :anthropic
|
|
1058
|
+
end
|
|
1059
|
+
```
|
|
1060
|
+
|
|
1061
|
+
---
|
|
1062
|
+
|
|
1063
|
+
### base_url
|
|
1064
|
+
|
|
1065
|
+
Set default base URL for all agents.
|
|
1066
|
+
|
|
1067
|
+
**Signature:**
|
|
1068
|
+
```ruby
|
|
1069
|
+
base_url(url) → void
|
|
1070
|
+
```
|
|
1071
|
+
|
|
1072
|
+
**Parameters:**
|
|
1073
|
+
- `url` (String, required): API endpoint URL
|
|
1074
|
+
|
|
1075
|
+
**Example:**
|
|
1076
|
+
```ruby
|
|
1077
|
+
all_agents do
|
|
1078
|
+
base_url "https://proxy.example.com/v1"
|
|
1079
|
+
end
|
|
1080
|
+
```
|
|
1081
|
+
|
|
1082
|
+
---
|
|
1083
|
+
|
|
1084
|
+
### api_version
|
|
1085
|
+
|
|
1086
|
+
Set default API version for all agents.
|
|
1087
|
+
|
|
1088
|
+
**Signature:**
|
|
1089
|
+
```ruby
|
|
1090
|
+
api_version(version) → void
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
**Parameters:**
|
|
1094
|
+
- `version` (String, required): API version path
|
|
1095
|
+
|
|
1096
|
+
**Example:**
|
|
1097
|
+
```ruby
|
|
1098
|
+
all_agents do
|
|
1099
|
+
api_version "v1/responses"
|
|
1100
|
+
end
|
|
1101
|
+
```
|
|
1102
|
+
|
|
1103
|
+
---
|
|
1104
|
+
|
|
1105
|
+
### timeout
|
|
1106
|
+
|
|
1107
|
+
Set default timeout for all agents.
|
|
1108
|
+
|
|
1109
|
+
**Signature:**
|
|
1110
|
+
```ruby
|
|
1111
|
+
timeout(seconds) → void
|
|
1112
|
+
```
|
|
1113
|
+
|
|
1114
|
+
**Parameters:**
|
|
1115
|
+
- `seconds` (Integer, required): Timeout in seconds
|
|
1116
|
+
|
|
1117
|
+
**Example:**
|
|
1118
|
+
```ruby
|
|
1119
|
+
all_agents do
|
|
1120
|
+
timeout 180
|
|
1121
|
+
end
|
|
1122
|
+
```
|
|
1123
|
+
|
|
1124
|
+
---
|
|
1125
|
+
|
|
1126
|
+
### parameters
|
|
1127
|
+
|
|
1128
|
+
Set default LLM parameters for all agents.
|
|
1129
|
+
|
|
1130
|
+
**Signature:**
|
|
1131
|
+
```ruby
|
|
1132
|
+
parameters(params) → void
|
|
1133
|
+
```
|
|
1134
|
+
|
|
1135
|
+
**Parameters:**
|
|
1136
|
+
- `params` (Hash, required): LLM parameters
|
|
1137
|
+
|
|
1138
|
+
**Example:**
|
|
1139
|
+
```ruby
|
|
1140
|
+
all_agents do
|
|
1141
|
+
parameters temperature: 0.7, max_tokens: 2000
|
|
1142
|
+
end
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
---
|
|
1146
|
+
|
|
1147
|
+
### headers
|
|
1148
|
+
|
|
1149
|
+
Set default HTTP headers for all agents.
|
|
1150
|
+
|
|
1151
|
+
**Signature:**
|
|
1152
|
+
```ruby
|
|
1153
|
+
headers(header_hash) → void
|
|
1154
|
+
```
|
|
1155
|
+
|
|
1156
|
+
**Parameters:**
|
|
1157
|
+
- `header_hash` (Hash, required): HTTP headers
|
|
1158
|
+
|
|
1159
|
+
**Example:**
|
|
1160
|
+
```ruby
|
|
1161
|
+
all_agents do
|
|
1162
|
+
headers "X-Organization" => "org123"
|
|
1163
|
+
end
|
|
1164
|
+
```
|
|
1165
|
+
|
|
1166
|
+
---
|
|
1167
|
+
|
|
1168
|
+
### coding_agent
|
|
1169
|
+
|
|
1170
|
+
Set default coding_agent flag for all agents.
|
|
1171
|
+
|
|
1172
|
+
**Signature:**
|
|
1173
|
+
```ruby
|
|
1174
|
+
coding_agent(enabled) → void
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
**Parameters:**
|
|
1178
|
+
- `enabled` (Boolean, required): Include base prompt
|
|
1179
|
+
|
|
1180
|
+
**Example:**
|
|
1181
|
+
```ruby
|
|
1182
|
+
all_agents do
|
|
1183
|
+
coding_agent false
|
|
1184
|
+
end
|
|
1185
|
+
```
|
|
1186
|
+
|
|
1187
|
+
---
|
|
1188
|
+
|
|
1189
|
+
### tools
|
|
1190
|
+
|
|
1191
|
+
Add tools that all agents will have.
|
|
1192
|
+
|
|
1193
|
+
**Signature:**
|
|
1194
|
+
```ruby
|
|
1195
|
+
tools(*tool_names) → void
|
|
1196
|
+
```
|
|
1197
|
+
|
|
1198
|
+
**Parameters:**
|
|
1199
|
+
- `tool_names` (Symbol, variadic): Tool names
|
|
1200
|
+
|
|
1201
|
+
**Example:**
|
|
1202
|
+
```ruby
|
|
1203
|
+
all_agents do
|
|
1204
|
+
tools :Read, :Write
|
|
1205
|
+
end
|
|
1206
|
+
```
|
|
1207
|
+
|
|
1208
|
+
---
|
|
1209
|
+
|
|
1210
|
+
### permissions
|
|
1211
|
+
|
|
1212
|
+
Configure permissions for all agents.
|
|
1213
|
+
|
|
1214
|
+
**Signature:**
|
|
1215
|
+
```ruby
|
|
1216
|
+
permissions(&block) → void
|
|
1217
|
+
```
|
|
1218
|
+
|
|
1219
|
+
**Parameters:**
|
|
1220
|
+
- `block` (required): Permissions configuration block
|
|
1221
|
+
|
|
1222
|
+
**Example:**
|
|
1223
|
+
```ruby
|
|
1224
|
+
all_agents do
|
|
1225
|
+
permissions do
|
|
1226
|
+
tool(:Write).deny_paths "secrets/**"
|
|
1227
|
+
tool(:Bash).deny_commands "^rm -rf"
|
|
1228
|
+
end
|
|
1229
|
+
end
|
|
1230
|
+
```
|
|
1231
|
+
|
|
1232
|
+
---
|
|
1233
|
+
|
|
1234
|
+
### hook
|
|
1235
|
+
|
|
1236
|
+
Add hook for all agents.
|
|
1237
|
+
|
|
1238
|
+
**Signature:**
|
|
1239
|
+
```ruby
|
|
1240
|
+
hook(event, matcher: nil, command: nil, timeout: nil, &block) → void
|
|
1241
|
+
```
|
|
1242
|
+
|
|
1243
|
+
**Parameters:** Same as agent-level `hook`
|
|
1244
|
+
|
|
1245
|
+
**Valid events:** All agent-level events (not swarm-level events)
|
|
1246
|
+
|
|
1247
|
+
**Example:**
|
|
1248
|
+
```ruby
|
|
1249
|
+
all_agents do
|
|
1250
|
+
hook :pre_tool_use, matcher: "Write" do |ctx|
|
|
1251
|
+
# Validation for all agents
|
|
1252
|
+
end
|
|
1253
|
+
end
|
|
1254
|
+
```
|
|
1255
|
+
|
|
1256
|
+
---
|
|
1257
|
+
|
|
1258
|
+
## Permissions Builder DSL
|
|
1259
|
+
|
|
1260
|
+
Methods available in the `permissions` block.
|
|
1261
|
+
|
|
1262
|
+
### tool
|
|
1263
|
+
|
|
1264
|
+
Get a tool permissions proxy for configuring a specific tool.
|
|
1265
|
+
|
|
1266
|
+
**Signature:**
|
|
1267
|
+
```ruby
|
|
1268
|
+
tool(tool_name) → ToolPermissionsProxy
|
|
1269
|
+
```
|
|
1270
|
+
|
|
1271
|
+
**Parameters:**
|
|
1272
|
+
- `tool_name` (Symbol, required): Tool name
|
|
1273
|
+
|
|
1274
|
+
**Returns:** `ToolPermissionsProxy` with fluent methods
|
|
1275
|
+
|
|
1276
|
+
**Example:**
|
|
1277
|
+
```ruby
|
|
1278
|
+
permissions do
|
|
1279
|
+
tool(:Write).allow_paths("src/**/*").deny_paths("src/secrets/**")
|
|
1280
|
+
tool(:Read).deny_paths("config/credentials.yml")
|
|
1281
|
+
tool(:Bash).allow_commands("^git status$")
|
|
1282
|
+
end
|
|
1283
|
+
```
|
|
1284
|
+
|
|
1285
|
+
---
|
|
1286
|
+
|
|
1287
|
+
### allow_paths
|
|
1288
|
+
|
|
1289
|
+
Add allowed path patterns (chainable).
|
|
1290
|
+
|
|
1291
|
+
**Signature:**
|
|
1292
|
+
```ruby
|
|
1293
|
+
allow_paths(*patterns) → self
|
|
1294
|
+
```
|
|
1295
|
+
|
|
1296
|
+
**Parameters:**
|
|
1297
|
+
- `patterns` (String, variadic): Glob patterns
|
|
1298
|
+
|
|
1299
|
+
**Returns:** `self` (for chaining)
|
|
1300
|
+
|
|
1301
|
+
**Example:**
|
|
1302
|
+
```ruby
|
|
1303
|
+
tool(:Write).allow_paths("backend/**/*")
|
|
1304
|
+
tool(:Write).allow_paths("frontend/**/*", "shared/**/*")
|
|
1305
|
+
```
|
|
1306
|
+
|
|
1307
|
+
---
|
|
1308
|
+
|
|
1309
|
+
### deny_paths
|
|
1310
|
+
|
|
1311
|
+
Add denied path patterns (chainable).
|
|
1312
|
+
|
|
1313
|
+
**Signature:**
|
|
1314
|
+
```ruby
|
|
1315
|
+
deny_paths(*patterns) → self
|
|
1316
|
+
```
|
|
1317
|
+
|
|
1318
|
+
**Parameters:**
|
|
1319
|
+
- `patterns` (String, variadic): Glob patterns
|
|
1320
|
+
|
|
1321
|
+
**Returns:** `self` (for chaining)
|
|
1322
|
+
|
|
1323
|
+
**Example:**
|
|
1324
|
+
```ruby
|
|
1325
|
+
tool(:Write).deny_paths("backend/secrets/**")
|
|
1326
|
+
tool(:Read).deny_paths("config/credentials.yml", ".env")
|
|
1327
|
+
```
|
|
1328
|
+
|
|
1329
|
+
---
|
|
1330
|
+
|
|
1331
|
+
### allow_commands
|
|
1332
|
+
|
|
1333
|
+
Add allowed command patterns (Bash tool only, chainable).
|
|
1334
|
+
|
|
1335
|
+
**Signature:**
|
|
1336
|
+
```ruby
|
|
1337
|
+
allow_commands(*patterns) → self
|
|
1338
|
+
```
|
|
1339
|
+
|
|
1340
|
+
**Parameters:**
|
|
1341
|
+
- `patterns` (String, variadic): Regex patterns
|
|
1342
|
+
|
|
1343
|
+
**Returns:** `self` (for chaining)
|
|
1344
|
+
|
|
1345
|
+
**Example:**
|
|
1346
|
+
```ruby
|
|
1347
|
+
tool(:Bash).allow_commands("^git (status|diff|log)$")
|
|
1348
|
+
tool(:Bash).allow_commands("^npm test$", "^bundle exec rspec$")
|
|
1349
|
+
```
|
|
1350
|
+
|
|
1351
|
+
---
|
|
1352
|
+
|
|
1353
|
+
### deny_commands
|
|
1354
|
+
|
|
1355
|
+
Add denied command patterns (Bash tool only, chainable).
|
|
1356
|
+
|
|
1357
|
+
**Signature:**
|
|
1358
|
+
```ruby
|
|
1359
|
+
deny_commands(*patterns) → self
|
|
1360
|
+
```
|
|
1361
|
+
|
|
1362
|
+
**Parameters:**
|
|
1363
|
+
- `patterns` (String, variadic): Regex patterns
|
|
1364
|
+
|
|
1365
|
+
**Returns:** `self` (for chaining)
|
|
1366
|
+
|
|
1367
|
+
**Example:**
|
|
1368
|
+
```ruby
|
|
1369
|
+
tool(:Bash).deny_commands("^rm -rf")
|
|
1370
|
+
tool(:Bash).deny_commands("^sudo", "^dd if=")
|
|
1371
|
+
```
|
|
1372
|
+
|
|
1373
|
+
---
|
|
1374
|
+
|
|
1375
|
+
## Node Builder DSL
|
|
1376
|
+
|
|
1377
|
+
Methods available in the `node` block.
|
|
1378
|
+
|
|
1379
|
+
### agent
|
|
1380
|
+
|
|
1381
|
+
Configure an agent for this node (returns fluent config object).
|
|
1382
|
+
|
|
1383
|
+
**Signature:**
|
|
1384
|
+
```ruby
|
|
1385
|
+
agent(name) → AgentConfig
|
|
1386
|
+
```
|
|
1387
|
+
|
|
1388
|
+
**Parameters:**
|
|
1389
|
+
- `name` (Symbol, required): Agent name
|
|
1390
|
+
|
|
1391
|
+
**Returns:** `AgentConfig` with `.delegates_to(*names)` method
|
|
1392
|
+
|
|
1393
|
+
**Example:**
|
|
1394
|
+
```ruby
|
|
1395
|
+
# With delegation
|
|
1396
|
+
agent(:backend).delegates_to(:tester, :database)
|
|
1397
|
+
|
|
1398
|
+
# Without delegation
|
|
1399
|
+
agent(:planner)
|
|
1400
|
+
```
|
|
1401
|
+
|
|
1402
|
+
---
|
|
1403
|
+
|
|
1404
|
+
### depends_on
|
|
1405
|
+
|
|
1406
|
+
Declare node dependencies (prerequisite nodes).
|
|
1407
|
+
|
|
1408
|
+
**Signature:**
|
|
1409
|
+
```ruby
|
|
1410
|
+
depends_on(*node_names) → void
|
|
1411
|
+
```
|
|
1412
|
+
|
|
1413
|
+
**Parameters:**
|
|
1414
|
+
- `node_names` (Symbol, variadic): Names of prerequisite nodes
|
|
1415
|
+
|
|
1416
|
+
**Example:**
|
|
1417
|
+
```ruby
|
|
1418
|
+
depends_on :planning
|
|
1419
|
+
depends_on :frontend, :backend # Multiple dependencies
|
|
1420
|
+
```
|
|
1421
|
+
|
|
1422
|
+
---
|
|
1423
|
+
|
|
1424
|
+
### lead
|
|
1425
|
+
|
|
1426
|
+
Override the lead agent for this node.
|
|
1427
|
+
|
|
1428
|
+
**Signature:**
|
|
1429
|
+
```ruby
|
|
1430
|
+
lead(agent_name) → void
|
|
1431
|
+
```
|
|
1432
|
+
|
|
1433
|
+
**Parameters:**
|
|
1434
|
+
- `agent_name` (Symbol, required): Lead agent name
|
|
1435
|
+
|
|
1436
|
+
**Default:** First agent in node
|
|
1437
|
+
|
|
1438
|
+
**Example:**
|
|
1439
|
+
```ruby
|
|
1440
|
+
agent(:backend).delegates_to(:tester)
|
|
1441
|
+
agent(:tester)
|
|
1442
|
+
lead :tester # Make tester the lead instead of backend
|
|
1443
|
+
```
|
|
1444
|
+
|
|
1445
|
+
---
|
|
1446
|
+
|
|
1447
|
+
### input
|
|
1448
|
+
|
|
1449
|
+
Define input transformer (Ruby block).
|
|
1450
|
+
|
|
1451
|
+
**Signature:**
|
|
1452
|
+
```ruby
|
|
1453
|
+
input(&block) → void
|
|
1454
|
+
```
|
|
1455
|
+
|
|
1456
|
+
**Parameters:**
|
|
1457
|
+
- `block` (required): Transformer block, receives `NodeContext`
|
|
1458
|
+
|
|
1459
|
+
**Block return values:**
|
|
1460
|
+
- `String`: Transformed input content
|
|
1461
|
+
- `Hash`: `{ skip_execution: true, content: "..." }` to skip node
|
|
1462
|
+
|
|
1463
|
+
**Context methods:**
|
|
1464
|
+
- `ctx.content`: Previous node's content (convenience)
|
|
1465
|
+
- `ctx.original_prompt`: Original user prompt
|
|
1466
|
+
- `ctx.all_results[:node_name]`: Access any previous node
|
|
1467
|
+
- `ctx.node_name`: Current node name
|
|
1468
|
+
- `ctx.dependencies`: Node dependencies
|
|
1469
|
+
|
|
1470
|
+
**Example:**
|
|
1471
|
+
```ruby
|
|
1472
|
+
input do |ctx|
|
|
1473
|
+
previous = ctx.content
|
|
1474
|
+
"Task: #{ctx.original_prompt}\nPrevious: #{previous}"
|
|
1475
|
+
end
|
|
1476
|
+
|
|
1477
|
+
# Access specific nodes
|
|
1478
|
+
input do |ctx|
|
|
1479
|
+
plan = ctx.all_results[:planning].content
|
|
1480
|
+
design = ctx.all_results[:design].content
|
|
1481
|
+
"Implement:\nPlan: #{plan}\nDesign: #{design}"
|
|
1482
|
+
end
|
|
1483
|
+
|
|
1484
|
+
# Skip execution (caching)
|
|
1485
|
+
input do |ctx|
|
|
1486
|
+
cached = check_cache(ctx.content)
|
|
1487
|
+
if cached
|
|
1488
|
+
{ skip_execution: true, content: cached }
|
|
1489
|
+
else
|
|
1490
|
+
ctx.content
|
|
1491
|
+
end
|
|
1492
|
+
end
|
|
1493
|
+
```
|
|
1494
|
+
|
|
1495
|
+
---
|
|
1496
|
+
|
|
1497
|
+
### input_command
|
|
1498
|
+
|
|
1499
|
+
Define input transformer (Bash command).
|
|
1500
|
+
|
|
1501
|
+
**Signature:**
|
|
1502
|
+
```ruby
|
|
1503
|
+
input_command(command, timeout: 60) → void
|
|
1504
|
+
```
|
|
1505
|
+
|
|
1506
|
+
**Parameters:**
|
|
1507
|
+
- `command` (String, required): Bash command
|
|
1508
|
+
- `timeout` (Integer, keyword): Timeout in seconds
|
|
1509
|
+
|
|
1510
|
+
**Input:** NodeContext as JSON on stdin
|
|
1511
|
+
|
|
1512
|
+
**Exit codes:**
|
|
1513
|
+
- `0`: Success, use stdout as transformed content
|
|
1514
|
+
- `1`: Skip node execution, use current_input unchanged
|
|
1515
|
+
- `2`: Halt workflow with error from stderr
|
|
1516
|
+
|
|
1517
|
+
**Example:**
|
|
1518
|
+
```ruby
|
|
1519
|
+
input_command "scripts/validate.sh", timeout: 30
|
|
1520
|
+
input_command "jq '.content'"
|
|
1521
|
+
```
|
|
1522
|
+
|
|
1523
|
+
---
|
|
1524
|
+
|
|
1525
|
+
### output
|
|
1526
|
+
|
|
1527
|
+
Define output transformer (Ruby block).
|
|
1528
|
+
|
|
1529
|
+
**Signature:**
|
|
1530
|
+
```ruby
|
|
1531
|
+
output(&block) → void
|
|
1532
|
+
```
|
|
1533
|
+
|
|
1534
|
+
**Parameters:**
|
|
1535
|
+
- `block` (required): Transformer block, receives `NodeContext`
|
|
1536
|
+
|
|
1537
|
+
**Block return value:**
|
|
1538
|
+
- `String`: Transformed output content
|
|
1539
|
+
|
|
1540
|
+
**Context methods:**
|
|
1541
|
+
- `ctx.content`: Current node's result content (convenience)
|
|
1542
|
+
- `ctx.original_prompt`: Original user prompt
|
|
1543
|
+
- `ctx.all_results[:node_name]`: Access any completed node
|
|
1544
|
+
- `ctx.node_name`: Current node name
|
|
1545
|
+
|
|
1546
|
+
**Example:**
|
|
1547
|
+
```ruby
|
|
1548
|
+
output do |ctx|
|
|
1549
|
+
# Side effect: save to file
|
|
1550
|
+
File.write("results/plan.txt", ctx.content)
|
|
1551
|
+
|
|
1552
|
+
# Return transformed output
|
|
1553
|
+
"Key decisions: #{extract_decisions(ctx.content)}"
|
|
1554
|
+
end
|
|
1555
|
+
|
|
1556
|
+
# Access multiple nodes
|
|
1557
|
+
output do |ctx|
|
|
1558
|
+
plan = ctx.all_results[:planning].content
|
|
1559
|
+
impl = ctx.content
|
|
1560
|
+
"Completed:\nPlan: #{plan}\nImpl: #{impl}"
|
|
1561
|
+
end
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
---
|
|
1565
|
+
|
|
1566
|
+
### output_command
|
|
1567
|
+
|
|
1568
|
+
Define output transformer (Bash command).
|
|
1569
|
+
|
|
1570
|
+
**Signature:**
|
|
1571
|
+
```ruby
|
|
1572
|
+
output_command(command, timeout: 60) → void
|
|
1573
|
+
```
|
|
1574
|
+
|
|
1575
|
+
**Parameters:**
|
|
1576
|
+
- `command` (String, required): Bash command
|
|
1577
|
+
- `timeout` (Integer, keyword): Timeout in seconds
|
|
1578
|
+
|
|
1579
|
+
**Input:** NodeContext as JSON on stdin
|
|
1580
|
+
|
|
1581
|
+
**Exit codes:**
|
|
1582
|
+
- `0`: Success, use stdout as transformed content
|
|
1583
|
+
- `1`: Pass through unchanged, use result.content
|
|
1584
|
+
- `2`: Halt workflow with error from stderr
|
|
1585
|
+
|
|
1586
|
+
**Example:**
|
|
1587
|
+
```ruby
|
|
1588
|
+
output_command "scripts/format.sh", timeout: 30
|
|
1589
|
+
output_command "tee results.txt"
|
|
1590
|
+
```
|
|
1591
|
+
|
|
1592
|
+
---
|
|
1593
|
+
|
|
1594
|
+
## Execution Methods
|
|
1595
|
+
|
|
1596
|
+
### swarm.execute
|
|
1597
|
+
|
|
1598
|
+
Execute a task using the lead agent.
|
|
1599
|
+
|
|
1600
|
+
**Signature:**
|
|
1601
|
+
```ruby
|
|
1602
|
+
swarm.execute(prompt, &block) → Result
|
|
1603
|
+
```
|
|
1604
|
+
|
|
1605
|
+
**Parameters:**
|
|
1606
|
+
- `prompt` (String, required): Task prompt
|
|
1607
|
+
- `block` (optional): Log entry handler for streaming
|
|
1608
|
+
|
|
1609
|
+
**Returns:** `Result` object
|
|
1610
|
+
|
|
1611
|
+
**Example:**
|
|
1612
|
+
```ruby
|
|
1613
|
+
# Basic execution
|
|
1614
|
+
result = swarm.execute("Build a REST API")
|
|
1615
|
+
|
|
1616
|
+
# With logging
|
|
1617
|
+
result = swarm.execute("Build a REST API") do |log_entry|
|
|
1618
|
+
puts "#{log_entry[:type]}: #{log_entry[:agent]}" if log_entry[:type] == "tool_call"
|
|
1619
|
+
end
|
|
1620
|
+
|
|
1621
|
+
# Check result
|
|
1622
|
+
if result.success?
|
|
1623
|
+
puts result.content
|
|
1624
|
+
puts "Cost: $#{result.total_cost}"
|
|
1625
|
+
puts "Tokens: #{result.total_tokens}"
|
|
1626
|
+
puts "Duration: #{result.duration}s"
|
|
1627
|
+
else
|
|
1628
|
+
puts "Error: #{result.error.message}"
|
|
1629
|
+
end
|
|
1630
|
+
```
|
|
1631
|
+
|
|
1632
|
+
---
|
|
1633
|
+
|
|
1634
|
+
## Result Object
|
|
1635
|
+
|
|
1636
|
+
Returned by `swarm.execute`.
|
|
1637
|
+
|
|
1638
|
+
### Attributes
|
|
1639
|
+
|
|
1640
|
+
**content**
|
|
1641
|
+
```ruby
|
|
1642
|
+
result.content → String | nil
|
|
1643
|
+
```
|
|
1644
|
+
Final response content from the swarm.
|
|
1645
|
+
|
|
1646
|
+
**agent**
|
|
1647
|
+
```ruby
|
|
1648
|
+
result.agent → String
|
|
1649
|
+
```
|
|
1650
|
+
Name of the agent that produced the final response.
|
|
1651
|
+
|
|
1652
|
+
**duration**
|
|
1653
|
+
```ruby
|
|
1654
|
+
result.duration → Float
|
|
1655
|
+
```
|
|
1656
|
+
Total execution duration in seconds.
|
|
1657
|
+
|
|
1658
|
+
**logs**
|
|
1659
|
+
```ruby
|
|
1660
|
+
result.logs → Array<Hash>
|
|
1661
|
+
```
|
|
1662
|
+
Array of log entries (events during execution).
|
|
1663
|
+
|
|
1664
|
+
**error**
|
|
1665
|
+
```ruby
|
|
1666
|
+
result.error → Exception | nil
|
|
1667
|
+
```
|
|
1668
|
+
Error object if execution failed, nil otherwise.
|
|
1669
|
+
|
|
1670
|
+
---
|
|
1671
|
+
|
|
1672
|
+
### Methods
|
|
1673
|
+
|
|
1674
|
+
**success?**
|
|
1675
|
+
```ruby
|
|
1676
|
+
result.success? → Boolean
|
|
1677
|
+
```
|
|
1678
|
+
Returns true if execution succeeded (no error).
|
|
1679
|
+
|
|
1680
|
+
**failure?**
|
|
1681
|
+
```ruby
|
|
1682
|
+
result.failure? → Boolean
|
|
1683
|
+
```
|
|
1684
|
+
Returns true if execution failed (has error).
|
|
1685
|
+
|
|
1686
|
+
**total_cost**
|
|
1687
|
+
```ruby
|
|
1688
|
+
result.total_cost → Float
|
|
1689
|
+
```
|
|
1690
|
+
Total cost in dollars across all LLM calls.
|
|
1691
|
+
|
|
1692
|
+
**total_tokens**
|
|
1693
|
+
```ruby
|
|
1694
|
+
result.total_tokens → Integer
|
|
1695
|
+
```
|
|
1696
|
+
Total tokens used (input + output).
|
|
1697
|
+
|
|
1698
|
+
**agents_involved**
|
|
1699
|
+
```ruby
|
|
1700
|
+
result.agents_involved → Array<Symbol>
|
|
1701
|
+
```
|
|
1702
|
+
List of all agents that participated.
|
|
1703
|
+
|
|
1704
|
+
**llm_requests**
|
|
1705
|
+
```ruby
|
|
1706
|
+
result.llm_requests → Integer
|
|
1707
|
+
```
|
|
1708
|
+
Number of LLM API calls made.
|
|
1709
|
+
|
|
1710
|
+
**tool_calls_count**
|
|
1711
|
+
```ruby
|
|
1712
|
+
result.tool_calls_count → Integer
|
|
1713
|
+
```
|
|
1714
|
+
Number of tool calls made.
|
|
1715
|
+
|
|
1716
|
+
**to_h**
|
|
1717
|
+
```ruby
|
|
1718
|
+
result.to_h → Hash
|
|
1719
|
+
```
|
|
1720
|
+
Convert to hash representation.
|
|
1721
|
+
|
|
1722
|
+
**to_json**
|
|
1723
|
+
```ruby
|
|
1724
|
+
result.to_json → String
|
|
1725
|
+
```
|
|
1726
|
+
Convert to JSON string.
|
|
1727
|
+
|
|
1728
|
+
---
|
|
1729
|
+
|
|
1730
|
+
## Context Management
|
|
1731
|
+
|
|
1732
|
+
SwarmSDK automatically manages conversation context to prevent hitting token limits while preserving accuracy.
|
|
1733
|
+
|
|
1734
|
+
### Automatic Features
|
|
1735
|
+
|
|
1736
|
+
#### Ephemeral System Reminders
|
|
1737
|
+
|
|
1738
|
+
System reminders (guidance, tool lists, error recovery) are sent to the LLM but **NOT persisted** in conversation history. This prevents reminder accumulation and saves 80-95% of reminder tokens in long conversations.
|
|
1739
|
+
|
|
1740
|
+
**How it works:**
|
|
1741
|
+
```
|
|
1742
|
+
Turn 1: Sends reminders → LLM sees them → NOT stored in history
|
|
1743
|
+
Turn 2: Sends new reminders → LLM sees only current turn's reminders
|
|
1744
|
+
Turn 20: No accumulated reminders (saves 1,200-13,800 tokens!)
|
|
1745
|
+
```
|
|
1746
|
+
|
|
1747
|
+
**Automatic** - No configuration needed. All `<system-reminder>` blocks are extracted and sent ephemerally.
|
|
1748
|
+
|
|
1749
|
+
#### Automatic Compression (60% Threshold)
|
|
1750
|
+
|
|
1751
|
+
When context usage reaches **60%**, SwarmSDK automatically compresses old tool results to free space.
|
|
1752
|
+
|
|
1753
|
+
**What gets compressed:**
|
|
1754
|
+
- ✅ **Tool results** (`role: :tool`) older than 10 messages
|
|
1755
|
+
- ✅ **Long outputs** from Read, Bash, Grep, etc.
|
|
1756
|
+
- ❌ **User messages** - Never compressed (user intent preserved)
|
|
1757
|
+
- ❌ **Assistant messages** - Never compressed (reasoning preserved)
|
|
1758
|
+
- ❌ **Recent messages** (last 10) - Full detail maintained
|
|
1759
|
+
|
|
1760
|
+
**Progressive compression by age:**
|
|
1761
|
+
```
|
|
1762
|
+
Age 11-20 messages: → 1000 chars max (light)
|
|
1763
|
+
Age 21-40 messages: → 500 chars max (moderate)
|
|
1764
|
+
Age 41-60 messages: → 200 chars max (heavy)
|
|
1765
|
+
Age 61+ messages: → 100 chars max (minimal summary)
|
|
1766
|
+
```
|
|
1767
|
+
|
|
1768
|
+
**Triggers:**
|
|
1769
|
+
- Automatically at 60% context usage
|
|
1770
|
+
- Only once (doesn't re-compress)
|
|
1771
|
+
- Logs `context_compression` event
|
|
1772
|
+
|
|
1773
|
+
**Example log:**
|
|
1774
|
+
```json
|
|
1775
|
+
{
|
|
1776
|
+
"type": "context_compression",
|
|
1777
|
+
"agent": "assistant",
|
|
1778
|
+
"total_messages": 45,
|
|
1779
|
+
"messages_compressed": 12,
|
|
1780
|
+
"tokens_before": 95000,
|
|
1781
|
+
"current_usage": "61%",
|
|
1782
|
+
"compression_strategy": "progressive_tool_result_compression",
|
|
1783
|
+
"keep_recent": 10
|
|
1784
|
+
}
|
|
1785
|
+
```
|
|
1786
|
+
|
|
1787
|
+
**Token savings:**
|
|
1788
|
+
- Typical: 10,000-20,000 tokens freed
|
|
1789
|
+
- Heavy tool usage: 30,000-50,000 tokens freed
|
|
1790
|
+
- Extends conversation by 20-40% more turns
|
|
1791
|
+
|
|
1792
|
+
### Context Warning Thresholds
|
|
1793
|
+
|
|
1794
|
+
SwarmSDK emits warnings at these thresholds:
|
|
1795
|
+
- **60%** - Triggers automatic compression
|
|
1796
|
+
- **80%** - Informational warning (approaching limit)
|
|
1797
|
+
- **90%** - Critical warning (near limit)
|
|
1798
|
+
|
|
1799
|
+
Each threshold emits once via `context_limit_warning` event.
|
|
1800
|
+
|
|
1801
|
+
### Impact on Accuracy
|
|
1802
|
+
|
|
1803
|
+
**Minimal** - Compression is designed to preserve accuracy:
|
|
1804
|
+
1. Recent context (last 10 messages) unchanged
|
|
1805
|
+
2. Conversational flow preserved (user/assistant messages)
|
|
1806
|
+
3. Tool results compressed but essential structure kept
|
|
1807
|
+
4. Progressive (older = more compressed)
|
|
1808
|
+
5. Only triggers when needed (60% full)
|
|
1809
|
+
|
|
1810
|
+
**When it might impact accuracy:**
|
|
1811
|
+
- Agent references very old tool results (rare)
|
|
1812
|
+
- Multi-file analysis across 40+ turns (uncommon)
|
|
1813
|
+
|
|
1814
|
+
**When it doesn't impact accuracy:**
|
|
1815
|
+
- Short conversations (<30 turns)
|
|
1816
|
+
- Recent tool results (always full detail)
|
|
1817
|
+
- User/assistant conversation (never compressed)
|
|
1818
|
+
|
|
1819
|
+
### Manual Control
|
|
1820
|
+
|
|
1821
|
+
Context management is automatic, but you can monitor via events:
|
|
1822
|
+
|
|
1823
|
+
```ruby
|
|
1824
|
+
swarm = SwarmSDK.build do
|
|
1825
|
+
name "My Swarm"
|
|
1826
|
+
|
|
1827
|
+
on :context_limit_warning do |ctx|
|
|
1828
|
+
puts "Context at #{ctx.metadata[:current_usage]}"
|
|
1829
|
+
end
|
|
1830
|
+
|
|
1831
|
+
on :context_compression do |ctx|
|
|
1832
|
+
puts "Compressed #{ctx.metadata[:messages_compressed]} messages"
|
|
1833
|
+
end
|
|
1834
|
+
end
|
|
1835
|
+
```
|
|
1836
|
+
|
|
1837
|
+
---
|
|
1838
|
+
|
|
1839
|
+
## Hook Context Methods
|
|
1840
|
+
|
|
1841
|
+
Available in hook blocks via the `ctx` parameter.
|
|
1842
|
+
|
|
1843
|
+
### Context Attributes
|
|
1844
|
+
|
|
1845
|
+
**event**
|
|
1846
|
+
```ruby
|
|
1847
|
+
ctx.event → Symbol
|
|
1848
|
+
```
|
|
1849
|
+
Current event type.
|
|
1850
|
+
|
|
1851
|
+
**agent_name**
|
|
1852
|
+
```ruby
|
|
1853
|
+
ctx.agent_name → String
|
|
1854
|
+
```
|
|
1855
|
+
Current agent name.
|
|
1856
|
+
|
|
1857
|
+
**tool_call**
|
|
1858
|
+
```ruby
|
|
1859
|
+
ctx.tool_call → ToolCall
|
|
1860
|
+
```
|
|
1861
|
+
Tool call object (for tool events).
|
|
1862
|
+
|
|
1863
|
+
**tool_result**
|
|
1864
|
+
```ruby
|
|
1865
|
+
ctx.tool_result → ToolResult
|
|
1866
|
+
```
|
|
1867
|
+
Tool result object (for post_tool_use).
|
|
1868
|
+
|
|
1869
|
+
**delegation_target**
|
|
1870
|
+
```ruby
|
|
1871
|
+
ctx.delegation_target → Symbol
|
|
1872
|
+
```
|
|
1873
|
+
Target agent name (for delegation events).
|
|
1874
|
+
|
|
1875
|
+
**metadata**
|
|
1876
|
+
```ruby
|
|
1877
|
+
ctx.metadata → Hash
|
|
1878
|
+
```
|
|
1879
|
+
Additional event metadata (read-write).
|
|
1880
|
+
|
|
1881
|
+
**swarm**
|
|
1882
|
+
```ruby
|
|
1883
|
+
ctx.swarm → Swarm
|
|
1884
|
+
```
|
|
1885
|
+
Reference to the swarm instance.
|
|
1886
|
+
|
|
1887
|
+
---
|
|
1888
|
+
|
|
1889
|
+
### Context Methods
|
|
1890
|
+
|
|
1891
|
+
**tool_event?**
|
|
1892
|
+
```ruby
|
|
1893
|
+
ctx.tool_event? → Boolean
|
|
1894
|
+
```
|
|
1895
|
+
Returns true if event is pre_tool_use or post_tool_use.
|
|
1896
|
+
|
|
1897
|
+
**delegation_event?**
|
|
1898
|
+
```ruby
|
|
1899
|
+
ctx.delegation_event? → Boolean
|
|
1900
|
+
```
|
|
1901
|
+
Returns true if event is pre_delegation or post_delegation.
|
|
1902
|
+
|
|
1903
|
+
**tool_name**
|
|
1904
|
+
```ruby
|
|
1905
|
+
ctx.tool_name → String | nil
|
|
1906
|
+
```
|
|
1907
|
+
Tool name (convenience method).
|
|
1908
|
+
|
|
1909
|
+
---
|
|
1910
|
+
|
|
1911
|
+
### Action Methods
|
|
1912
|
+
|
|
1913
|
+
**halt**
|
|
1914
|
+
```ruby
|
|
1915
|
+
ctx.halt(message) → HookResult
|
|
1916
|
+
```
|
|
1917
|
+
Halt execution and return error message.
|
|
1918
|
+
|
|
1919
|
+
**replace**
|
|
1920
|
+
```ruby
|
|
1921
|
+
ctx.replace(value) → HookResult
|
|
1922
|
+
```
|
|
1923
|
+
Replace tool result or prompt with custom value.
|
|
1924
|
+
|
|
1925
|
+
**reprompt**
|
|
1926
|
+
```ruby
|
|
1927
|
+
ctx.reprompt(prompt) → HookResult
|
|
1928
|
+
```
|
|
1929
|
+
Reprompt the agent with a new prompt (swarm_stop only).
|
|
1930
|
+
|
|
1931
|
+
**finish_agent**
|
|
1932
|
+
```ruby
|
|
1933
|
+
ctx.finish_agent(message) → HookResult
|
|
1934
|
+
```
|
|
1935
|
+
Finish current agent's execution with final message.
|
|
1936
|
+
|
|
1937
|
+
**finish_swarm**
|
|
1938
|
+
```ruby
|
|
1939
|
+
ctx.finish_swarm(message) → HookResult
|
|
1940
|
+
```
|
|
1941
|
+
Finish entire swarm execution with final message.
|
|
1942
|
+
|
|
1943
|
+
**breakpoint**
|
|
1944
|
+
```ruby
|
|
1945
|
+
ctx.breakpoint → void
|
|
1946
|
+
```
|
|
1947
|
+
Enter interactive debugging (binding.irb).
|
|
1948
|
+
|
|
1949
|
+
---
|
|
1950
|
+
|
|
1951
|
+
### ToolCall Object
|
|
1952
|
+
|
|
1953
|
+
**Attributes:**
|
|
1954
|
+
```ruby
|
|
1955
|
+
tool_call.id → String # Tool call ID
|
|
1956
|
+
tool_call.name → String # Tool name
|
|
1957
|
+
tool_call.parameters → Hash # Tool parameters
|
|
1958
|
+
```
|
|
1959
|
+
|
|
1960
|
+
---
|
|
1961
|
+
|
|
1962
|
+
### ToolResult Object
|
|
1963
|
+
|
|
1964
|
+
**Attributes:**
|
|
1965
|
+
```ruby
|
|
1966
|
+
tool_result.tool_call_id → String # Tool call ID
|
|
1967
|
+
tool_result.tool_name → String # Tool name
|
|
1968
|
+
tool_result.content → String # Result content
|
|
1969
|
+
tool_result.success? → Boolean # Success status
|
|
1970
|
+
```
|
|
1971
|
+
|
|
1972
|
+
---
|
|
1973
|
+
|
|
1974
|
+
## NodeContext Methods
|
|
1975
|
+
|
|
1976
|
+
Available in node transformer blocks via the `ctx` parameter.
|
|
1977
|
+
|
|
1978
|
+
### Attributes
|
|
1979
|
+
|
|
1980
|
+
**original_prompt**
|
|
1981
|
+
```ruby
|
|
1982
|
+
ctx.original_prompt → String
|
|
1983
|
+
```
|
|
1984
|
+
Original user prompt for the workflow.
|
|
1985
|
+
|
|
1986
|
+
**all_results**
|
|
1987
|
+
```ruby
|
|
1988
|
+
ctx.all_results → Hash<Symbol, Result>
|
|
1989
|
+
```
|
|
1990
|
+
Results from all completed nodes.
|
|
1991
|
+
|
|
1992
|
+
**node_name**
|
|
1993
|
+
```ruby
|
|
1994
|
+
ctx.node_name → Symbol
|
|
1995
|
+
```
|
|
1996
|
+
Current node name.
|
|
1997
|
+
|
|
1998
|
+
**dependencies**
|
|
1999
|
+
```ruby
|
|
2000
|
+
ctx.dependencies → Array<Symbol>
|
|
2001
|
+
```
|
|
2002
|
+
Node dependencies (input transformers only).
|
|
2003
|
+
|
|
2004
|
+
---
|
|
2005
|
+
|
|
2006
|
+
### Convenience Methods
|
|
2007
|
+
|
|
2008
|
+
**content**
|
|
2009
|
+
```ruby
|
|
2010
|
+
ctx.content → String | nil
|
|
2011
|
+
```
|
|
2012
|
+
- Input transformers: Previous node's content (or transformed content)
|
|
2013
|
+
- Output transformers: Current node's content
|
|
2014
|
+
|
|
2015
|
+
**agent**
|
|
2016
|
+
```ruby
|
|
2017
|
+
ctx.agent → String | nil
|
|
2018
|
+
```
|
|
2019
|
+
Agent name from previous_result or result.
|
|
2020
|
+
|
|
2021
|
+
**logs**
|
|
2022
|
+
```ruby
|
|
2023
|
+
ctx.logs → Array | nil
|
|
2024
|
+
```
|
|
2025
|
+
Logs from previous_result or result.
|
|
2026
|
+
|
|
2027
|
+
**duration**
|
|
2028
|
+
```ruby
|
|
2029
|
+
ctx.duration → Float | nil
|
|
2030
|
+
```
|
|
2031
|
+
Duration from previous_result or result.
|
|
2032
|
+
|
|
2033
|
+
**error**
|
|
2034
|
+
```ruby
|
|
2035
|
+
ctx.error → Exception | nil
|
|
2036
|
+
```
|
|
2037
|
+
Error from previous_result or result.
|
|
2038
|
+
|
|
2039
|
+
**success?**
|
|
2040
|
+
```ruby
|
|
2041
|
+
ctx.success? → Boolean | nil
|
|
2042
|
+
```
|
|
2043
|
+
Success status from previous_result or result.
|
|
2044
|
+
|
|
2045
|
+
---
|
|
2046
|
+
|
|
2047
|
+
## Complete Example
|
|
2048
|
+
|
|
2049
|
+
```ruby
|
|
2050
|
+
#!/usr/bin/env ruby
|
|
2051
|
+
require "swarm_sdk"
|
|
2052
|
+
|
|
2053
|
+
swarm = SwarmSDK.build do
|
|
2054
|
+
name "Code Review Team"
|
|
2055
|
+
lead :reviewer
|
|
2056
|
+
|
|
2057
|
+
# Apply settings to all agents
|
|
2058
|
+
all_agents do
|
|
2059
|
+
provider :anthropic
|
|
2060
|
+
timeout 180
|
|
2061
|
+
coding_agent false
|
|
2062
|
+
|
|
2063
|
+
permissions do
|
|
2064
|
+
tool(:Write).deny_paths "secrets/**"
|
|
2065
|
+
end
|
|
2066
|
+
end
|
|
2067
|
+
|
|
2068
|
+
# Lead reviewer agent
|
|
2069
|
+
agent :reviewer do
|
|
2070
|
+
model "claude-sonnet-4"
|
|
2071
|
+
description "Lead code reviewer coordinating the review process"
|
|
2072
|
+
directory "."
|
|
2073
|
+
|
|
2074
|
+
system_prompt <<~PROMPT
|
|
2075
|
+
You are a lead code reviewer. Coordinate the review process:
|
|
2076
|
+
1. Delegate security checks to the security expert
|
|
2077
|
+
2. Delegate performance analysis to the performance expert
|
|
2078
|
+
3. Synthesize feedback into actionable recommendations
|
|
2079
|
+
PROMPT
|
|
2080
|
+
|
|
2081
|
+
tools :Read, :Write, :Edit
|
|
2082
|
+
delegates_to :security, :performance
|
|
2083
|
+
|
|
2084
|
+
hook :pre_delegation do |ctx|
|
|
2085
|
+
puts "Delegating to #{ctx.delegation_target}..."
|
|
2086
|
+
end
|
|
2087
|
+
end
|
|
2088
|
+
|
|
2089
|
+
# Security expert
|
|
2090
|
+
agent :security do
|
|
2091
|
+
model "gpt-5"
|
|
2092
|
+
description "Security expert checking for vulnerabilities"
|
|
2093
|
+
|
|
2094
|
+
system_prompt "You are a security expert. Check code for vulnerabilities, injection attacks, and security best practices."
|
|
2095
|
+
|
|
2096
|
+
tools :Read, :Grep
|
|
2097
|
+
|
|
2098
|
+
hook :pre_tool_use, matcher: "Read" do |ctx|
|
|
2099
|
+
# Log which files are being reviewed
|
|
2100
|
+
puts "Reviewing: #{ctx.tool_call.parameters[:file_path]}"
|
|
2101
|
+
end
|
|
2102
|
+
end
|
|
2103
|
+
|
|
2104
|
+
# Performance expert
|
|
2105
|
+
agent :performance do
|
|
2106
|
+
model "gpt-5"
|
|
2107
|
+
description "Performance expert analyzing efficiency"
|
|
2108
|
+
|
|
2109
|
+
system_prompt "You are a performance expert. Analyze code for performance issues, algorithmic complexity, and optimization opportunities."
|
|
2110
|
+
|
|
2111
|
+
tools :Read, :Grep, :Bash
|
|
2112
|
+
|
|
2113
|
+
permissions do
|
|
2114
|
+
tool(:Bash).allow_commands "^(node --prof|ruby-prof|py-spy)"
|
|
2115
|
+
end
|
|
2116
|
+
end
|
|
2117
|
+
|
|
2118
|
+
# Swarm-level hook
|
|
2119
|
+
hook :swarm_stop do |ctx|
|
|
2120
|
+
puts "\nReview complete!"
|
|
2121
|
+
puts "Duration: #{ctx.metadata[:duration]}s"
|
|
2122
|
+
puts "Cost: $#{ctx.metadata[:total_cost]}"
|
|
2123
|
+
end
|
|
2124
|
+
end
|
|
2125
|
+
|
|
2126
|
+
# Execute review
|
|
2127
|
+
result = swarm.execute("Review the authentication code in src/auth.rb") do |log|
|
|
2128
|
+
if log[:type] == "tool_call"
|
|
2129
|
+
puts " #{log[:tool]}: #{log[:arguments].inspect}"
|
|
2130
|
+
end
|
|
2131
|
+
end
|
|
2132
|
+
|
|
2133
|
+
# Check result
|
|
2134
|
+
if result.success?
|
|
2135
|
+
puts "\nFeedback:"
|
|
2136
|
+
puts result.content
|
|
2137
|
+
|
|
2138
|
+
puts "\nStats:"
|
|
2139
|
+
puts " Agents: #{result.agents_involved.join(", ")}"
|
|
2140
|
+
puts " Tokens: #{result.total_tokens}"
|
|
2141
|
+
puts " Cost: $#{result.total_cost}"
|
|
2142
|
+
else
|
|
2143
|
+
puts "Error: #{result.error.message}"
|
|
2144
|
+
exit 1
|
|
2145
|
+
end
|
|
2146
|
+
```
|
|
2147
|
+
|
|
2148
|
+
---
|
|
2149
|
+
|
|
2150
|
+
## See Also
|
|
2151
|
+
|
|
2152
|
+
- [YAML Reference](./yaml.md): Complete YAML configuration reference
|
|
2153
|
+
- [CLI Reference](./cli.md): Command-line interface reference
|
|
2154
|
+
- [Getting Started Guide](../guides/getting-started.md): Introduction to SwarmSDK
|