Class: SwarmSDK::Swarm

Inherits:
Object
  • Object
show all
Includes:
Concerns::Cleanupable, Concerns::Snapshotable, Concerns::Validatable, HookTriggers, LoggingCallbacks
Defined in:
lib/swarm_sdk/swarm.rb,
lib/swarm_sdk/swarm/builder.rb,
lib/swarm_sdk/swarm/executor.rb,
lib/swarm_sdk/swarm/hook_triggers.rb,
lib/swarm_sdk/swarm/mcp_configurator.rb,
lib/swarm_sdk/swarm/agent_initializer.rb,
lib/swarm_sdk/swarm/logging_callbacks.rb,
lib/swarm_sdk/swarm/tool_configurator.rb,
lib/swarm_sdk/swarm/all_agents_builder.rb,
lib/swarm_sdk/swarm/swarm_registry_builder.rb

Overview

Swarm orchestrates multiple AI agents with shared rate limiting and coordination.

This is the main user-facing API for SwarmSDK. Users create swarms using:

  • Ruby DSL: SwarmSDK.build { ... } (Recommended)
  • YAML String: SwarmSDK.load(yaml, base_dir:)
  • YAML File: SwarmSDK.load_file(path)
  • Direct API: Swarm.new + add_agent (Advanced)
swarm = SwarmSDK.build do
name "Development Team"
lead :backend

agent :backend do
  model "gpt-5"
  description "Backend developer"
  prompt "You build APIs"
  tools :Read, :Edit, :Bash
end
end
result = swarm.execute("Build authentication")

YAML String API

yaml = File.read("swarm.yml")
swarm = SwarmSDK.load(yaml, base_dir: "/path/to/project")
result = swarm.execute("Build authentication")

YAML File API (Convenience)

swarm = SwarmSDK.load_file("swarm.yml")
result = swarm.execute("Build authentication")

Direct API (Advanced)

swarm = Swarm.new(name: "Development Team")

backend_agent = Agent::Definition.new(:backend, {
description: "Backend developer",
model: "gpt-5",
system_prompt: "You build APIs and databases...",
tools: [:Read, :Edit, :Bash],
delegates_to: [:database]
})
swarm.add_agent(backend_agent)

swarm.lead = :backend
result = swarm.execute("Build authentication")

Architecture

All APIs converge on Agent::Definition for validation. Swarm delegates to specialized concerns:

  • Agent::Definition: Validates configuration, builds system prompts
  • AgentInitializer: Complex 5-pass agent setup
  • ToolConfigurator: Tool creation and permissions (via AgentInitializer)
  • McpConfigurator: MCP client management (via AgentInitializer)

Defined Under Namespace

Modules: HookTriggers, LoggingCallbacks Classes: AgentInitializer, AllAgentsBuilder, Builder, Executor, McpConfigurator, SwarmRegistryBuilder, ToolConfigurator

Constant Summary collapse

DEFAULT_TOOLS =

Default tools available to all agents

ToolConfigurator::DEFAULT_TOOLS

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HookTriggers

#add_default_callback, #trigger_swarm_stop, #trigger_swarm_stop_final

Methods included from LoggingCallbacks

#emit_agent_start_events, #emit_agent_start_for, #emit_retroactive_agent_start_events, #register_default_logging_callbacks, #setup_logging, #setup_logging_for_all_agents

Methods included from Concerns::Cleanupable

#cleanup

Methods included from Concerns::Validatable

#emit_validation_warnings, #validate

Constructor Details

#initialize(name:, swarm_id: nil, parent_swarm_id: nil, global_concurrency: nil, default_local_concurrency: nil, scratchpad: nil, scratchpad_mode: :enabled, allow_filesystem_tools: nil) ⇒ Swarm

Initialize a new Swarm

Parameters:

  • name (String)

    Human-readable swarm name

  • swarm_id (String, nil) (defaults to: nil)

    Optional swarm ID (auto-generated if not provided)

  • parent_swarm_id (String, nil) (defaults to: nil)

    Optional parent swarm ID (nil for root swarms)

  • global_concurrency (Integer, nil) (defaults to: nil)

    Max concurrent LLM calls across entire swarm (nil uses config default)

  • default_local_concurrency (Integer, nil) (defaults to: nil)

    Default max concurrent tool calls per agent (nil uses config default)

  • scratchpad (Tools::Stores::Scratchpad, nil) (defaults to: nil)

    Optional scratchpad instance (for testing/internal use)

  • scratchpad_mode (Symbol, String) (defaults to: :enabled)

    Scratchpad mode (:enabled or :disabled). :per_node not allowed for non-node swarms.

  • allow_filesystem_tools (Boolean, nil) (defaults to: nil)

    Whether to allow filesystem tools (nil uses global setting)



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/swarm_sdk/swarm.rb', line 142

def initialize(name:, swarm_id: nil, parent_swarm_id: nil, global_concurrency: nil, default_local_concurrency: nil, scratchpad: nil, scratchpad_mode: :enabled, allow_filesystem_tools: nil)
  @name = name
  @swarm_id = swarm_id || generate_swarm_id(name)
  @parent_swarm_id = parent_swarm_id
  @global_concurrency = global_concurrency || SwarmSDK.config.global_concurrency_limit
  @default_local_concurrency = default_local_concurrency || SwarmSDK.config.local_concurrency_limit

  # Handle scratchpad_mode parameter
  # For Swarm: :enabled or :disabled (not :per_node - that's for nodes)
  @scratchpad_mode = validate_swarm_scratchpad_mode(scratchpad_mode)

  # Resolve allow_filesystem_tools with priority:
  # 1. Explicit parameter (if not nil)
  # 2. Global config
  @allow_filesystem_tools = if allow_filesystem_tools.nil?
    SwarmSDK.config.allow_filesystem_tools
  else
    allow_filesystem_tools
  end

  # Swarm registry for managing sub-swarms (initialized later if needed)
  @swarm_registry = nil

  # Delegation call stack for circular dependency detection
  @delegation_call_stack = []

  # Shared semaphore for all agents
  @global_semaphore = Async::Semaphore.new(@global_concurrency)

  # Shared scratchpad storage for all agents (volatile)
  # Use provided scratchpad storage (for testing) or create volatile one based on mode
  @scratchpad_storage = if scratchpad
    scratchpad # Testing/internal use - explicit instance provided
  elsif @scratchpad_mode == :enabled
    Tools::Stores::ScratchpadStorage.new
  end

  # Per-agent plugin storages (persistent)
  # Format: { plugin_name => { agent_name => storage } }
  # Will be populated when agents are initialized
  @plugin_storages = {}

  # Hook registry for named hooks and swarm defaults
  @hook_registry = Hooks::Registry.new

  # Register default logging hooks
  register_default_logging_callbacks

  # Agent definitions and instances
  @agent_definitions = {}
  @agents = {}
  @delegation_instances = {} # { "delegate@delegator" => Agent::Chat }
  @agents_initialized = false
  @agent_contexts = {}

  # MCP clients per agent (for cleanup)
  @mcp_clients = Hash.new { |h, k| h[k] = [] }

  @lead_agent = nil

  # Track if first message has been sent
  @first_message_sent = false

  # Track if agent_start events have been emitted
  # This prevents duplicate emissions and ensures events are emitted when logging is ready
  @agent_start_events_emitted = false

  # Observer agent configurations
  @observer_configs = []
  @observer_manager = nil
end

Class Attribute Details

.mcp_log_levelObject

Returns the value of attribute mcp_log_level.



104
105
106
# File 'lib/swarm_sdk/swarm.rb', line 104

def mcp_log_level
  @mcp_log_level
end

Instance Attribute Details

#agent_definitionsObject (readonly)

Returns the value of attribute agent_definitions.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def agent_definitions
  @agent_definitions
end

#agentsObject (readonly)

Returns the value of attribute agents.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def agents
  @agents
end

#allow_filesystem_toolsObject (readonly)

Returns the value of attribute allow_filesystem_tools.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def allow_filesystem_tools
  @allow_filesystem_tools
end

#config_for_hooksObject

Returns the value of attribute config_for_hooks.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def config_for_hooks
  @config_for_hooks
end

#delegation_call_stackObject

Returns the value of attribute delegation_call_stack.



76
77
78
# File 'lib/swarm_sdk/swarm.rb', line 76

def delegation_call_stack
  @delegation_call_stack
end

#delegation_instancesObject (readonly)

Returns the value of attribute delegation_instances.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def delegation_instances
  @delegation_instances
end

#first_message_sent=(value) ⇒ void (writeonly)

This method returns an undefined value.

Set first message sent flag (used by snapshot/restore)

Parameters:

  • value (Boolean)

    New value



97
98
99
# File 'lib/swarm_sdk/swarm.rb', line 97

def first_message_sent=(value)
  @first_message_sent = value
end

#global_semaphoreObject (readonly)

Returns the value of attribute global_semaphore.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def global_semaphore
  @global_semaphore
end

#hook_registryObject (readonly)

Returns the value of attribute hook_registry.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def hook_registry
  @hook_registry
end

#lead_agentObject (readonly)

Returns the value of attribute lead_agent.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def lead_agent
  @lead_agent
end

#mcp_clientsObject (readonly)

Returns the value of attribute mcp_clients.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def mcp_clients
  @mcp_clients
end

#nameObject (readonly)

Returns the value of attribute name.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def name
  @name
end

#observer_configsObject (readonly)

Returns the value of attribute observer_configs.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def observer_configs
  @observer_configs
end

#parent_swarm_idObject (readonly)

Returns the value of attribute parent_swarm_id.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def parent_swarm_id
  @parent_swarm_id
end

#plugin_storagesObject (readonly)

Returns the value of attribute plugin_storages.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def plugin_storages
  @plugin_storages
end

#scratchpad_storageObject (readonly)

Returns the value of attribute scratchpad_storage.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def scratchpad_storage
  @scratchpad_storage
end

#swarm_idObject (readonly)

Returns the value of attribute swarm_id.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def swarm_id
  @swarm_id
end

#swarm_registryObject

Returns the value of attribute swarm_registry.



75
76
77
# File 'lib/swarm_sdk/swarm.rb', line 75

def swarm_registry
  @swarm_registry
end

Class Method Details

.apply_mcp_logging_configurationvoid

This method returns an undefined value.

Apply MCP logging configuration to RubyLLM::MCP



121
122
123
124
125
126
127
128
129
# File 'lib/swarm_sdk/swarm.rb', line 121

def apply_mcp_logging_configuration
  return if @mcp_logging_configured

  RubyLLM::MCP.configure do |config|
    config.log_level = @mcp_log_level || SwarmSDK.config.mcp_log_level
  end

  @mcp_logging_configured = true
end

.configure_mcp_logging(level = nil) ⇒ void

This method returns an undefined value.

Configure MCP client logging globally

This should be called before creating any swarms that use MCP servers. The configuration is global and affects all MCP clients.

Parameters:

  • level (Integer) (defaults to: nil)

    Log level (Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR, Logger::FATAL)



113
114
115
116
# File 'lib/swarm_sdk/swarm.rb', line 113

def configure_mcp_logging(level = nil)
  @mcp_log_level = level || SwarmSDK.config.mcp_log_level
  apply_mcp_logging_configuration
end

Instance Method Details

#add_agent(definition) ⇒ self

Add an agent to the swarm

Accepts only Agent::Definition objects. This ensures all validation happens in a single place (Agent::Definition) and keeps the API clean.

If the definition doesn't specify max_concurrent_tools, the swarm's default_local_concurrency is applied.

Examples:

definition = Agent::Definition.new(:backend, {
  description: "Backend developer",
  model: "gpt-5",
  system_prompt: "You build APIs"
})
swarm.add_agent(definition)

Parameters:

Returns:

  • (self)

Raises:



232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/swarm_sdk/swarm.rb', line 232

def add_agent(definition)
  unless definition.is_a?(Agent::Definition)
    raise ArgumentError, "Expected Agent::Definition, got #{definition.class}"
  end

  name = definition.name
  raise ConfigurationError, "Agent '#{name}' already exists" if @agent_definitions.key?(name)

  # Apply swarm's default_local_concurrency if max_concurrent_tools not set
  definition.max_concurrent_tools = @default_local_concurrency if definition.max_concurrent_tools.nil?

  @agent_definitions[name] = definition
  self
end

#add_observer_config(config) ⇒ void

This method returns an undefined value.

Add observer configuration

Called by Swarm::Builder to register observer agent configurations. Validates that the referenced agent exists.

Parameters:



459
460
461
462
# File 'lib/swarm_sdk/swarm.rb', line 459

def add_observer_config(config)
  validate_observer_agent(config.agent_name)
  @observer_configs << config
end

#agent(name) ⇒ AgentChat

Get an agent chat instance by name

Parameters:

  • name (Symbol, String)

    Agent name

Returns:

  • (AgentChat)

    Agent chat instance



342
343
344
345
346
347
# File 'lib/swarm_sdk/swarm.rb', line 342

def agent(name)
  name = name.to_sym
  initialize_agents unless @agents_initialized

  @agents[name] || raise(AgentNotFoundError, "Agent '#{name}' not found")
end

#agent_definition(name) ⇒ AgentDefinition

Get an agent definition by name

Use this to access and modify agent configuration:

swarm.agent_definition(:backend).bypass_permissions = true

Parameters:

  • name (Symbol, String)

    Agent name

Returns:

  • (AgentDefinition)

    Agent definition object



356
357
358
359
360
# File 'lib/swarm_sdk/swarm.rb', line 356

def agent_definition(name)
  name = name.to_sym

  @agent_definitions[name] || raise(AgentNotFoundError, "Agent '#{name}' not found")
end

#agent_namesArray<Symbol>

Get all agent names

Returns:

  • (Array<Symbol>)

    Agent names



365
366
367
# File 'lib/swarm_sdk/swarm.rb', line 365

def agent_names
  @agent_definitions.keys
end

#cleanup_observersvoid

This method returns an undefined value.

Cleanup observer subscriptions

Called by Executor.cleanup_after_execution to unsubscribe observers. Matches the MCP cleanup pattern.



480
481
482
483
# File 'lib/swarm_sdk/swarm.rb', line 480

def cleanup_observers
  @observer_manager&.cleanup
  @observer_manager = nil
end

#context_breakdownHash{Symbol => Hash}

Get context usage breakdown for all agents

Returns per-agent context statistics including tokens used, context limit, usage percentage, and cost. Useful for monitoring context window consumption across the swarm.

Examples:

breakdown = swarm.context_breakdown
breakdown[:backend]
# => {
#   input_tokens: 15000,
#   output_tokens: 5000,
#   total_tokens: 20000,
#   cached_tokens: 2000,
#   context_limit: 200000,
#   usage_percentage: 10.0,
#   tokens_remaining: 180000,
#   input_cost: 0.045,
#   output_cost: 0.075,
#   total_cost: 0.12
# }

Returns:

  • (Hash{Symbol => Hash})

    Per-agent context breakdown



392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/swarm_sdk/swarm.rb', line 392

def context_breakdown
  initialize_agents unless @agents_initialized

  breakdown = {}

  # Include primary agents
  @agents.each do |name, chat|
    breakdown[name] = build_agent_context_info(chat)
  end

  # Include delegation instances
  @delegation_instances.each do |instance_name, chat|
    breakdown[instance_name.to_sym] = build_agent_context_info(chat)
  end

  breakdown
end

#delegation_instances_hashObject



415
416
417
# File 'lib/swarm_sdk/swarm.rb', line 415

def delegation_instances_hash
  @delegation_instances
end

#execute(prompt, wait: true) {|Hash| ... } ⇒ Result, Async::Task

Execute a task using the lead agent

The lead agent can delegate to other agents via tool calls, and the entire swarm coordinates with shared rate limiting. Supports reprompting via swarm_stop hooks.

By default, this method blocks until execution completes. Set wait: false to return an Async::Task immediately, enabling cancellation via task.stop.

Examples:

Blocking execution (default)

result = swarm.execute("Build auth")
puts result.content

Non-blocking execution with cancellation

task = swarm.execute("Build auth", wait: false) { |event| puts event }
# ... do other work ...
task.stop  # Cancel anytime
result = task.wait  # Returns nil for cancelled tasks

Parameters:

  • prompt (String)

    Task to execute

  • wait (Boolean) (defaults to: true)

    If true (default), blocks until execution completes. If false, returns Async::Task immediately for non-blocking execution.

Yields:

  • (Hash)

    Log entry if block given (for streaming)

Returns:

  • (Result, Async::Task)

    Result if wait: true, Async::Task if wait: false

Raises:



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/swarm_sdk/swarm.rb', line 285

def execute(prompt, wait: true, &block)
  raise ConfigurationError, "No lead agent set. Set lead= first." unless @lead_agent

  logs = []
  current_prompt = prompt
  has_logging = block_given?

  # Save original Fiber storage for restoration (preserves parent context for nested swarms)
  original_fiber_storage = {
    execution_id: Fiber[:execution_id],
    swarm_id: Fiber[:swarm_id],
    parent_swarm_id: Fiber[:parent_swarm_id],
  }

  # Set fiber-local execution context
  # Use ||= to inherit parent's execution_id if one exists (for mini-swarms)
  Fiber[:execution_id] ||= generate_execution_id
  Fiber[:swarm_id] = @swarm_id
  Fiber[:parent_swarm_id] = @parent_swarm_id

  # Setup logging FIRST if block given (so swarm_start event can be emitted)
  setup_logging(logs, &block) if has_logging

  # Setup observer execution if any observers configured
  # MUST happen AFTER setup_logging (which clears Fiber[:log_subscriptions])
  setup_observer_execution if @observer_configs.any?

  # Trigger swarm_start hooks (before any execution)
  current_prompt = apply_swarm_start_hooks(current_prompt)

  # Trigger first_message hooks on first execution
  unless @first_message_sent
    trigger_first_message(current_prompt)
    @first_message_sent = true
  end

  # Lazy initialization of agents (with optional logging)
  initialize_agents unless @agents_initialized

  # Emit agent_start events if agents were initialized before logging was set up
  emit_retroactive_agent_start_events if has_logging

  # Delegate to Executor for actual execution
  executor = Executor.new(self)
  @current_task = executor.run(
    current_prompt,
    wait: wait,
    logs: logs,
    has_logging: has_logging,
    original_fiber_storage: original_fiber_storage,
  )
end

#first_message_sent?Boolean

Check if first message has been sent (for system reminder injection)

Returns:

  • (Boolean)


89
90
91
# File 'lib/swarm_sdk/swarm.rb', line 89

def first_message_sent?
  @first_message_sent
end

#lead=(name) ⇒ self

Set the lead agent (entry point for swarm execution)

Parameters:

  • name (Symbol, String)

    Name of agent to make lead

Returns:

  • (self)


251
252
253
254
255
256
257
258
259
# File 'lib/swarm_sdk/swarm.rb', line 251

def lead=(name)
  name = name.to_sym

  unless @agent_definitions.key?(name)
    raise ConfigurationError, "Cannot set lead: agent '#{name}' not found"
  end

  @lead_agent = name
end

#override_swarm_ids(swarm_id:, parent_swarm_id:) ⇒ void

This method returns an undefined value.

Override swarm IDs for composable swarms

Used by SwarmLoader to set hierarchical IDs when loading sub-swarms. This is called after the swarm is built to ensure proper parent/child relationships.

Parameters:

  • swarm_id (String)

    New swarm ID

  • parent_swarm_id (String)

    New parent swarm ID



558
559
560
561
# File 'lib/swarm_sdk/swarm.rb', line 558

def override_swarm_ids(swarm_id:, parent_swarm_id:)
  @swarm_id = swarm_id
  @parent_swarm_id = parent_swarm_id
end

#primary_agentsObject

Implement Snapshotable interface



411
412
413
# File 'lib/swarm_sdk/swarm.rb', line 411

def primary_agents
  @agents
end

#register_hook(name, &block) ⇒ self

Register a named hook that can be referenced in agent configurations

Named hooks are stored in the registry and can be referenced by symbol in agent YAML configurations or programmatically.

Examples:

Register a validation hook

swarm.register_hook(:validate_code) do |context|
  raise SwarmSDK::Hooks::Error, "Invalid" unless valid?(context.tool_call)
end

Parameters:

  • name (Symbol)

    Unique hook name

  • block (Proc)

    Hook implementation

Returns:

  • (self)


435
436
437
438
# File 'lib/swarm_sdk/swarm.rb', line 435

def register_hook(name, &block)
  @hook_registry.register(name, &block)
  self
end

#reset_context!void

This method returns an undefined value.

Reset context for all agents

Clears conversation history for all agents. This is used by composable swarms to reset sub-swarm context when keep_context: false is specified.



446
447
448
449
450
# File 'lib/swarm_sdk/swarm.rb', line 446

def reset_context!
  @agents.each_value do |agent_chat|
    agent_chat.clear_conversation if agent_chat.respond_to?(:clear_conversation)
  end
end

#restore(snapshot, preserve_system_prompts: false) ⇒ RestoreResult

Restore conversation state from snapshot

Accepts a Snapshot object, hash, or JSON string. Validates compatibility between snapshot and current swarm configuration, restores agent conversations, context state, scratchpad, and read tracking. Returns RestoreResult with warnings about any agents that couldn't be restored due to configuration mismatches.

The swarm must be created with the SAME configuration (agent definitions, tools, prompts) as when the snapshot was created. Only conversation state is restored from the snapshot.

Restore swarm state from snapshot

By default, uses current system prompts from agent definitions (YAML + SDK defaults + plugin injections). Set preserve_system_prompts: true to use historical prompts from snapshot.

Examples:

Restore from Snapshot object

swarm = SwarmSDK.build { ... }  # Same config as snapshot
snapshot = Snapshot.from_file("session.json")
result = swarm.restore(snapshot)
if result.success?
  puts "All agents restored"
else
  puts result.summary
  result.warnings.each { |w| puts "  - #{w[:message]}" }
end

Parameters:

  • snapshot (Snapshot, Hash, String)

    Snapshot object, hash, or JSON string

  • snapshot (Snapshot, Hash, String)

    Snapshot object, hash, or JSON string

  • preserve_system_prompts (Boolean) (defaults to: false)

    Use historical system prompts instead of current config (default: false)

Returns:



546
547
548
# File 'lib/swarm_sdk/swarm.rb', line 546

def restore(snapshot, preserve_system_prompts: false)
  StateRestorer.new(self, snapshot, preserve_system_prompts: preserve_system_prompts).restore
end

#scratchpad_enabled?Boolean

Check if scratchpad tools are enabled

Returns:

  • (Boolean)


81
82
83
# File 'lib/swarm_sdk/swarm.rb', line 81

def scratchpad_enabled?
  @scratchpad_mode == :enabled
end

#snapshotSnapshot

Create snapshot of current conversation state

Returns a Snapshot object containing:

  • All agent conversations (@messages arrays)
  • Agent context state (warnings, compression, TodoWrite tracking, skills)
  • Delegation instance conversations
  • Scratchpad contents (volatile shared storage)
  • Read tracking state (which files each agent has read with digests)
  • Memory read tracking state (which memory entries each agent has read with digests)

Configuration (agent definitions, tools, prompts) stays in your YAML/DSL and is NOT included in snapshots.

Examples:

Save snapshot to JSON file

snapshot = swarm.snapshot
snapshot.write_to_file("session.json")

Convert to hash or JSON string

snapshot = swarm.snapshot
hash = snapshot.to_hash
json_string = snapshot.to_json

Returns:

  • (Snapshot)

    Snapshot object with convenient serialization methods



508
509
510
# File 'lib/swarm_sdk/swarm.rb', line 508

def snapshot
  StateSnapshot.new(self).snapshot
end

#wait_for_observersvoid

This method returns an undefined value.

Wait for all observer tasks to complete

Called by Executor to wait for observer agents before cleanup. Safe to call even if no observers are configured.



470
471
472
# File 'lib/swarm_sdk/swarm.rb', line 470

def wait_for_observers
  @observer_manager&.wait_for_completion
end