swarm_memory 2.1.3 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/lib/claude_swarm/claude_mcp_server.rb +1 -0
  3. data/lib/claude_swarm/cli.rb +5 -18
  4. data/lib/claude_swarm/configuration.rb +2 -15
  5. data/lib/claude_swarm/mcp_generator.rb +1 -0
  6. data/lib/claude_swarm/openai/chat_completion.rb +4 -12
  7. data/lib/claude_swarm/openai/executor.rb +3 -1
  8. data/lib/claude_swarm/openai/responses.rb +13 -32
  9. data/lib/claude_swarm/version.rb +1 -1
  10. data/lib/swarm_cli/commands/run.rb +2 -2
  11. data/lib/swarm_cli/config_loader.rb +11 -11
  12. data/lib/swarm_cli/formatters/human_formatter.rb +70 -0
  13. data/lib/swarm_cli/interactive_repl.rb +11 -5
  14. data/lib/swarm_cli/ui/icons.rb +0 -23
  15. data/lib/swarm_cli/version.rb +1 -1
  16. data/lib/swarm_memory/adapters/filesystem_adapter.rb +11 -34
  17. data/lib/swarm_memory/integration/sdk_plugin.rb +87 -7
  18. data/lib/swarm_memory/version.rb +1 -1
  19. data/lib/swarm_memory.rb +1 -1
  20. data/lib/swarm_sdk/agent/builder.rb +58 -0
  21. data/lib/swarm_sdk/agent/chat.rb +527 -1059
  22. data/lib/swarm_sdk/agent/{chat → chat_helpers}/context_tracker.rb +9 -88
  23. data/lib/swarm_sdk/agent/chat_helpers/event_emitter.rb +204 -0
  24. data/lib/swarm_sdk/agent/{chat → chat_helpers}/hook_integration.rb +111 -44
  25. data/lib/swarm_sdk/agent/chat_helpers/instrumentation.rb +78 -0
  26. data/lib/swarm_sdk/agent/chat_helpers/llm_configuration.rb +233 -0
  27. data/lib/swarm_sdk/agent/{chat → chat_helpers}/logging_helpers.rb +1 -1
  28. data/lib/swarm_sdk/agent/chat_helpers/serialization.rb +83 -0
  29. data/lib/swarm_sdk/agent/{chat → chat_helpers}/system_reminder_injector.rb +12 -12
  30. data/lib/swarm_sdk/agent/chat_helpers/system_reminders.rb +79 -0
  31. data/lib/swarm_sdk/agent/chat_helpers/token_tracking.rb +98 -0
  32. data/lib/swarm_sdk/agent/context.rb +2 -2
  33. data/lib/swarm_sdk/agent/definition.rb +66 -154
  34. data/lib/swarm_sdk/agent/llm_instrumentation_middleware.rb +4 -2
  35. data/lib/swarm_sdk/agent/system_prompt_builder.rb +161 -0
  36. data/lib/swarm_sdk/builders/base_builder.rb +409 -0
  37. data/lib/swarm_sdk/concerns/cleanupable.rb +39 -0
  38. data/lib/swarm_sdk/concerns/snapshotable.rb +67 -0
  39. data/lib/swarm_sdk/concerns/validatable.rb +55 -0
  40. data/lib/swarm_sdk/configuration/parser.rb +353 -0
  41. data/lib/swarm_sdk/configuration/translator.rb +255 -0
  42. data/lib/swarm_sdk/configuration.rb +65 -543
  43. data/lib/swarm_sdk/context_compactor/token_counter.rb +3 -3
  44. data/lib/swarm_sdk/context_compactor.rb +6 -11
  45. data/lib/swarm_sdk/context_management/builder.rb +128 -0
  46. data/lib/swarm_sdk/context_management/context.rb +328 -0
  47. data/lib/swarm_sdk/defaults.rb +196 -0
  48. data/lib/swarm_sdk/events_to_messages.rb +18 -0
  49. data/lib/swarm_sdk/hooks/shell_executor.rb +2 -1
  50. data/lib/swarm_sdk/log_collector.rb +179 -29
  51. data/lib/swarm_sdk/log_stream.rb +29 -0
  52. data/lib/swarm_sdk/node_context.rb +1 -1
  53. data/lib/swarm_sdk/observer/builder.rb +81 -0
  54. data/lib/swarm_sdk/observer/config.rb +45 -0
  55. data/lib/swarm_sdk/observer/manager.rb +236 -0
  56. data/lib/swarm_sdk/patterns/agent_observer.rb +160 -0
  57. data/lib/swarm_sdk/plugin.rb +93 -3
  58. data/lib/swarm_sdk/snapshot.rb +6 -6
  59. data/lib/swarm_sdk/snapshot_from_events.rb +13 -2
  60. data/lib/swarm_sdk/state_restorer.rb +136 -151
  61. data/lib/swarm_sdk/state_snapshot.rb +65 -100
  62. data/lib/swarm_sdk/swarm/agent_initializer.rb +180 -136
  63. data/lib/swarm_sdk/swarm/builder.rb +44 -578
  64. data/lib/swarm_sdk/swarm/executor.rb +213 -0
  65. data/lib/swarm_sdk/swarm/hook_triggers.rb +150 -0
  66. data/lib/swarm_sdk/swarm/logging_callbacks.rb +340 -0
  67. data/lib/swarm_sdk/swarm/mcp_configurator.rb +7 -4
  68. data/lib/swarm_sdk/swarm/tool_configurator.rb +42 -138
  69. data/lib/swarm_sdk/swarm.rb +137 -679
  70. data/lib/swarm_sdk/tools/bash.rb +11 -3
  71. data/lib/swarm_sdk/tools/delegate.rb +61 -43
  72. data/lib/swarm_sdk/tools/edit.rb +8 -13
  73. data/lib/swarm_sdk/tools/glob.rb +9 -1
  74. data/lib/swarm_sdk/tools/grep.rb +7 -0
  75. data/lib/swarm_sdk/tools/multi_edit.rb +15 -11
  76. data/lib/swarm_sdk/tools/path_resolver.rb +51 -2
  77. data/lib/swarm_sdk/tools/read.rb +11 -13
  78. data/lib/swarm_sdk/tools/registry.rb +122 -10
  79. data/lib/swarm_sdk/tools/stores/scratchpad_storage.rb +8 -5
  80. data/lib/swarm_sdk/tools/stores/storage.rb +0 -6
  81. data/lib/swarm_sdk/tools/todo_write.rb +7 -0
  82. data/lib/swarm_sdk/tools/web_fetch.rb +3 -2
  83. data/lib/swarm_sdk/tools/write.rb +8 -13
  84. data/lib/swarm_sdk/version.rb +1 -1
  85. data/lib/swarm_sdk/{node → workflow}/agent_config.rb +1 -1
  86. data/lib/swarm_sdk/workflow/builder.rb +143 -0
  87. data/lib/swarm_sdk/workflow/executor.rb +497 -0
  88. data/lib/swarm_sdk/{node/builder.rb → workflow/node_builder.rb} +3 -3
  89. data/lib/swarm_sdk/{node → workflow}/transformer_executor.rb +3 -2
  90. data/lib/swarm_sdk/{node_orchestrator.rb → workflow.rb} +152 -456
  91. data/lib/swarm_sdk.rb +33 -3
  92. metadata +37 -14
  93. data/lib/swarm_memory/chat_extension.rb +0 -34
  94. data/lib/swarm_sdk/providers/openai_with_responses.rb +0 -589
@@ -14,16 +14,11 @@ module SwarmSDK
14
14
  # This encapsulates the complex initialization logic that was previously
15
15
  # embedded in Swarm#initialize_agents.
16
16
  class AgentInitializer
17
- # rubocop:disable Metrics/ParameterLists
18
- def initialize(swarm, agent_definitions, global_semaphore, hook_registry, scratchpad_storage, plugin_storages, config_for_hooks: nil)
19
- # rubocop:enable Metrics/ParameterLists
17
+ # Initialize with swarm reference (all data accessible via swarm)
18
+ #
19
+ # @param swarm [Swarm] The parent swarm instance
20
+ def initialize(swarm)
20
21
  @swarm = swarm
21
- @agent_definitions = agent_definitions
22
- @global_semaphore = global_semaphore
23
- @hook_registry = hook_registry
24
- @scratchpad_storage = scratchpad_storage
25
- @plugin_storages = plugin_storages
26
- @config_for_hooks = config_for_hooks
27
22
  @agents = {}
28
23
  @agent_contexts = {}
29
24
  end
@@ -51,6 +46,39 @@ module SwarmSDK
51
46
  # Provide access to agent contexts for Swarm
52
47
  attr_reader :agent_contexts
53
48
 
49
+ # Initialize a single agent in isolation (for observer agents)
50
+ #
51
+ # Creates an isolated agent chat without delegation tools,
52
+ # suitable for observer agents that don't need to delegate.
53
+ # Reuses existing create_agent_chat infrastructure.
54
+ #
55
+ # @param agent_name [Symbol] Name of agent to initialize
56
+ # @return [Agent::Chat] Isolated agent chat instance
57
+ # @raise [ConfigurationError] If agent not found
58
+ #
59
+ # @example
60
+ # initializer = AgentInitializer.new(swarm)
61
+ # chat = initializer.initialize_isolated_agent(:profiler)
62
+ # chat.ask("Analyze this prompt")
63
+ def initialize_isolated_agent(agent_name)
64
+ agent_def = @swarm.agent_definitions[agent_name]
65
+ raise ConfigurationError, "Agent '#{agent_name}' not found" unless agent_def
66
+
67
+ # Ensure plugin storages are created (needed by ToolConfigurator)
68
+ create_plugin_storages if @swarm.plugin_storages.empty?
69
+
70
+ # Reuse existing create_agent_chat infrastructure
71
+ tool_configurator = ToolConfigurator.new(
72
+ @swarm,
73
+ @swarm.scratchpad_storage,
74
+ @swarm.plugin_storages,
75
+ )
76
+
77
+ # Create chat using same method as pass_1_create_agents
78
+ # This gives us full tool setup, MCP servers, etc.
79
+ create_agent_chat(agent_name, agent_def, tool_configurator)
80
+ end
81
+
54
82
  # Create a tool that delegates work to another agent
55
83
  #
56
84
  # This method is public for testing delegation from Swarm.
@@ -68,9 +96,6 @@ module SwarmSDK
68
96
  delegate_chat: delegate_chat,
69
97
  agent_name: agent_name,
70
98
  swarm: @swarm,
71
- hook_registry: @hook_registry,
72
- call_stack: @swarm.delegation_call_stack,
73
- swarm_registry: @swarm.swarm_registry,
74
99
  delegating_chat: delegating_chat,
75
100
  )
76
101
  end
@@ -90,9 +115,9 @@ module SwarmSDK
90
115
  # Create plugin storages for agents
91
116
  create_plugin_storages
92
117
 
93
- tool_configurator = ToolConfigurator.new(@swarm, @scratchpad_storage, @plugin_storages)
118
+ tool_configurator = ToolConfigurator.new(@swarm, @swarm.scratchpad_storage, @swarm.plugin_storages)
94
119
 
95
- @agent_definitions.each do |name, agent_definition|
120
+ @swarm.agent_definitions.each do |name, agent_definition|
96
121
  # Skip if this agent will only exist as delegation instances
97
122
  next if should_skip_primary_creation?(name, agent_definition)
98
123
 
@@ -111,19 +136,19 @@ module SwarmSDK
111
136
  # 2b. Wire primary agents to delegation instances OR shared primaries
112
137
  # 2c. Wire delegation instances to their delegates (nested delegation support)
113
138
  def pass_2_register_delegation_tools
114
- tool_configurator = ToolConfigurator.new(@swarm, @scratchpad_storage, @plugin_storages)
139
+ tool_configurator = ToolConfigurator.new(@swarm, @swarm.scratchpad_storage, @swarm.plugin_storages)
115
140
 
116
141
  # Sub-pass 2a: Create delegation instances for isolated agents
117
- @agent_definitions.each do |delegator_name, delegator_def|
142
+ @swarm.agent_definitions.each do |delegator_name, delegator_def|
118
143
  delegator_def.delegates_to.each do |delegate_base_name|
119
144
  delegate_base_name = delegate_base_name.to_sym
120
145
 
121
- unless @agent_definitions.key?(delegate_base_name)
146
+ unless @swarm.agent_definitions.key?(delegate_base_name)
122
147
  raise ConfigurationError,
123
148
  "Agent '#{delegator_name}' delegates to unknown agent '#{delegate_base_name}'"
124
149
  end
125
150
 
126
- delegate_definition = @agent_definitions[delegate_base_name]
151
+ delegate_definition = @swarm.agent_definitions[delegate_base_name]
127
152
 
128
153
  # Check isolation mode of the DELEGATE agent
129
154
  # If delegate wants to be shared, skip instance creation (use primary)
@@ -146,54 +171,20 @@ module SwarmSDK
146
171
  end
147
172
 
148
173
  # Sub-pass 2b: Wire primary agents to delegation instances OR shared primaries OR registered swarms
149
- @agent_definitions.each do |delegator_name, delegator_def|
174
+ @swarm.agent_definitions.each do |delegator_name, delegator_def|
150
175
  delegator_chat = @agents[delegator_name]
151
176
 
152
177
  # Skip if delegator doesn't exist as primary (wasn't created in pass_1)
153
178
  next unless delegator_chat
154
179
 
155
- delegator_def.delegates_to.each do |delegate_base_name|
156
- delegate_base_name_str = delegate_base_name.to_s
157
-
158
- # Check if target is a registered swarm
159
- if @swarm.swarm_registry&.registered?(delegate_base_name_str)
160
- # Create delegation tool for swarm
161
- tool = create_delegation_tool(
162
- name: delegate_base_name_str,
163
- description: "External swarm: #{delegate_base_name_str}",
164
- delegate_chat: nil, # Swarm delegation - no direct chat
165
- agent_name: delegator_name,
166
- delegating_chat: delegator_chat,
167
- )
168
-
169
- delegator_chat.with_tool(tool)
170
- elsif @agent_definitions.key?(delegate_base_name)
171
- # Delegate to local agent
172
- delegate_definition = @agent_definitions[delegate_base_name]
173
-
174
- # Determine which chat instance to use
175
- target_chat = if delegate_definition.shared_across_delegations
176
- # Shared mode: use primary agent (old behavior)
177
- @agents[delegate_base_name]
178
- else
179
- # Isolated mode: use delegation instance
180
- instance_name = "#{delegate_base_name}@#{delegator_name}"
181
- @swarm.delegation_instances[instance_name]
182
- end
183
-
184
- # Create delegation tool pointing to chosen instance
185
- tool = create_delegation_tool(
186
- name: delegate_base_name.to_s,
187
- description: delegate_definition.description,
188
- delegate_chat: target_chat, # ← Isolated instance OR shared primary
189
- agent_name: delegator_name,
190
- delegating_chat: delegator_chat,
191
- )
192
-
193
- delegator_chat.with_tool(tool)
194
- else
195
- raise ConfigurationError, "Agent '#{delegator_name}' delegates to unknown target '#{delegate_base_name_str}' (not a local agent or registered swarm)"
196
- end
180
+ delegator_def.delegates_to.each do |delegate_name|
181
+ wire_delegation(
182
+ delegator_name: delegator_name,
183
+ delegator_chat: delegator_chat,
184
+ delegate_name: delegate_name,
185
+ tool_configurator: tool_configurator,
186
+ create_nested_instances: false,
187
+ )
197
188
  end
198
189
  end
199
190
 
@@ -201,63 +192,118 @@ module SwarmSDK
201
192
  # Convert to array first to avoid "can't add key during iteration" error
202
193
  @swarm.delegation_instances.to_a.each do |instance_name, delegation_chat|
203
194
  base_name = extract_base_name(instance_name)
204
- delegate_definition = @agent_definitions[base_name]
195
+ delegate_definition = @swarm.agent_definitions[base_name]
205
196
 
206
197
  # Register delegation tools for THIS instance's delegates_to
207
198
  delegate_definition.delegates_to.each do |nested_delegate_name|
208
- nested_delegate_name_sym = nested_delegate_name.to_sym
209
- nested_delegate_name_str = nested_delegate_name.to_s
210
-
211
- # Check if target is a registered swarm
212
- if @swarm.swarm_registry&.registered?(nested_delegate_name_str)
213
- # Create delegation tool for swarm
214
- nested_tool = create_delegation_tool(
215
- name: nested_delegate_name_str,
216
- description: "External swarm: #{nested_delegate_name_str}",
217
- delegate_chat: nil, # Swarm delegation - no direct chat
218
- agent_name: instance_name.to_sym,
219
- delegating_chat: delegation_chat,
220
- )
221
-
222
- delegation_chat.with_tool(nested_tool)
223
- elsif @agent_definitions.key?(nested_delegate_name_sym)
224
- # Delegate to local agent
225
- nested_definition = @agent_definitions[nested_delegate_name_sym]
226
-
227
- # Determine target: shared primary OR isolated instance
228
- target_chat = if nested_definition.shared_across_delegations
229
- # Shared mode: point to primary (semaphore-protected)
230
- @agents[nested_delegate_name_sym]
231
- else
232
- # Isolated mode: delegation instances also get isolated nested delegates
233
- # Create unique instance for this delegation chain
234
- nested_instance_name = "#{nested_delegate_name}@#{instance_name}"
235
-
236
- # Check if already created in 2a (if delegator also delegates to this agent)
237
- @swarm.delegation_instances[nested_instance_name] ||= create_agent_chat_for_delegation(
238
- instance_name: nested_instance_name,
239
- base_name: nested_delegate_name_sym,
240
- agent_definition: nested_definition,
241
- tool_configurator: tool_configurator,
242
- )
243
- end
244
-
245
- # Create delegation tool
246
- nested_tool = create_delegation_tool(
247
- name: nested_delegate_name.to_s,
248
- description: nested_definition.description,
249
- delegate_chat: target_chat, # ← Isolated OR shared
250
- agent_name: instance_name.to_sym,
251
- delegating_chat: delegation_chat,
252
- )
253
-
254
- delegation_chat.with_tool(nested_tool)
255
- else
256
- raise ConfigurationError,
257
- "Delegation instance '#{instance_name}' delegates to unknown target '#{nested_delegate_name_str}' (not a local agent or registered swarm)"
258
- end
199
+ wire_delegation(
200
+ delegator_name: instance_name.to_sym,
201
+ delegator_chat: delegation_chat,
202
+ delegate_name: nested_delegate_name,
203
+ tool_configurator: tool_configurator,
204
+ create_nested_instances: true,
205
+ )
206
+ end
207
+ end
208
+ end
209
+
210
+ # Wire a single delegation from one agent/instance to a delegate
211
+ #
212
+ # This is the unified logic for delegation wiring used by both:
213
+ # - Sub-pass 2b: Primary agents → delegates
214
+ # - Sub-pass 2c: Delegation instances → nested delegates
215
+ #
216
+ # @param delegator_name [Symbol, String] Name of the agent doing the delegating
217
+ # @param delegator_chat [Agent::Chat] Chat instance of the delegator
218
+ # @param delegate_name [Symbol, String] Name of the delegate target
219
+ # @param tool_configurator [ToolConfigurator] Tool configuration helper
220
+ # @param create_nested_instances [Boolean] Whether to create new instances for nested delegation
221
+ # @return [void]
222
+ def wire_delegation(delegator_name:, delegator_chat:, delegate_name:, tool_configurator:, create_nested_instances:)
223
+ delegate_name_str = delegate_name.to_s
224
+ delegate_name_sym = delegate_name.to_sym
225
+
226
+ # Check if target is a registered swarm
227
+ if @swarm.swarm_registry&.registered?(delegate_name_str)
228
+ wire_swarm_delegation(delegator_name, delegator_chat, delegate_name_str)
229
+ elsif @swarm.agent_definitions.key?(delegate_name_sym)
230
+ wire_agent_delegation(
231
+ delegator_name: delegator_name,
232
+ delegator_chat: delegator_chat,
233
+ delegate_name_sym: delegate_name_sym,
234
+ tool_configurator: tool_configurator,
235
+ create_nested_instances: create_nested_instances,
236
+ )
237
+ else
238
+ raise ConfigurationError,
239
+ "Agent '#{delegator_name}' delegates to unknown target '#{delegate_name_str}' (not a local agent or registered swarm)"
240
+ end
241
+ end
242
+
243
+ # Wire delegation to an external swarm
244
+ #
245
+ # @param delegator_name [Symbol, String] Name of the delegating agent
246
+ # @param delegator_chat [Agent::Chat] Chat instance of the delegator
247
+ # @param swarm_name [String] Name of the registered swarm
248
+ # @return [void]
249
+ def wire_swarm_delegation(delegator_name, delegator_chat, swarm_name)
250
+ tool = create_delegation_tool(
251
+ name: swarm_name,
252
+ description: "External swarm: #{swarm_name}",
253
+ delegate_chat: nil, # Swarm delegation - no direct chat
254
+ agent_name: delegator_name,
255
+ delegating_chat: delegator_chat,
256
+ )
257
+
258
+ delegator_chat.add_tool(tool)
259
+ end
260
+
261
+ # Wire delegation to a local agent
262
+ #
263
+ # Determines whether to use shared primary or isolated instance based on
264
+ # the delegate's shared_across_delegations setting.
265
+ #
266
+ # @param delegator_name [Symbol, String] Name of the delegating agent
267
+ # @param delegator_chat [Agent::Chat] Chat instance of the delegator
268
+ # @param delegate_name_sym [Symbol] Name of the delegate agent
269
+ # @param tool_configurator [ToolConfigurator] Tool configuration helper
270
+ # @param create_nested_instances [Boolean] Whether to create new instances if not found
271
+ # @return [void]
272
+ def wire_agent_delegation(delegator_name:, delegator_chat:, delegate_name_sym:, tool_configurator:, create_nested_instances:)
273
+ delegate_definition = @swarm.agent_definitions[delegate_name_sym]
274
+
275
+ # Determine which chat instance to use
276
+ target_chat = if delegate_definition.shared_across_delegations
277
+ # Shared mode: use primary agent (semaphore-protected)
278
+ @agents[delegate_name_sym]
279
+ else
280
+ # Isolated mode: use delegation instance
281
+ instance_name = "#{delegate_name_sym}@#{delegator_name}"
282
+
283
+ if create_nested_instances
284
+ # For nested delegation: create if not exists
285
+ @swarm.delegation_instances[instance_name] ||= create_agent_chat_for_delegation(
286
+ instance_name: instance_name,
287
+ base_name: delegate_name_sym,
288
+ agent_definition: delegate_definition,
289
+ tool_configurator: tool_configurator,
290
+ )
291
+ else
292
+ # For primary delegation: instance was pre-created in 2a
293
+ @swarm.delegation_instances[instance_name]
259
294
  end
260
295
  end
296
+
297
+ # Create delegation tool pointing to chosen instance
298
+ tool = create_delegation_tool(
299
+ name: delegate_name_sym.to_s,
300
+ description: delegate_definition.description,
301
+ delegate_chat: target_chat,
302
+ agent_name: delegator_name,
303
+ delegating_chat: delegator_chat,
304
+ )
305
+
306
+ delegator_chat.add_tool(tool)
261
307
  end
262
308
 
263
309
  # Pass 3: Setup agent contexts
@@ -267,13 +313,13 @@ module SwarmSDK
267
313
  def pass_3_setup_contexts
268
314
  # Setup contexts for PRIMARY agents
269
315
  @agents.each do |agent_name, chat|
270
- setup_agent_context(agent_name, @agent_definitions[agent_name], chat, is_delegation: false)
316
+ setup_agent_context(agent_name, @swarm.agent_definitions[agent_name], chat, is_delegation: false)
271
317
  end
272
318
 
273
319
  # Setup contexts for DELEGATION instances
274
320
  @swarm.delegation_instances.each do |instance_name, chat|
275
321
  base_name = extract_base_name(instance_name)
276
- agent_definition = @agent_definitions[base_name]
322
+ agent_definition = @swarm.agent_definitions[base_name]
277
323
  setup_agent_context(instance_name.to_sym, agent_definition, chat, is_delegation: true)
278
324
  end
279
325
  end
@@ -281,7 +327,7 @@ module SwarmSDK
281
327
  # Setup context for an agent (primary or delegation instance)
282
328
  def setup_agent_context(agent_name, agent_definition, chat, is_delegation: false)
283
329
  delegate_tool_names = agent_definition.delegates_to.map do |delegate_name|
284
- "DelegateTaskTo#{delegate_name.to_s.capitalize}"
330
+ Tools::Delegate.tool_name_for(delegate_name)
285
331
  end
286
332
 
287
333
  context = Agent::Context.new(
@@ -351,10 +397,10 @@ module SwarmSDK
351
397
  # Configure hooks for an agent (primary or delegation instance)
352
398
  def configure_hooks_for_agent(agent_name, chat)
353
399
  base_name = extract_base_name(agent_name)
354
- agent_definition = @agent_definitions[base_name]
400
+ agent_definition = @swarm.agent_definitions[base_name]
355
401
 
356
402
  chat.setup_hooks(
357
- registry: @hook_registry,
403
+ registry: @swarm.hook_registry,
358
404
  agent_definition: agent_definition,
359
405
  swarm: @swarm,
360
406
  ) if chat.respond_to?(:setup_hooks)
@@ -365,7 +411,7 @@ module SwarmSDK
365
411
  # If the swarm was loaded from YAML with agent-specific hooks,
366
412
  # apply them now via HooksAdapter.
367
413
  def pass_5_apply_yaml_hooks
368
- return unless @config_for_hooks
414
+ return unless @swarm.config_for_hooks
369
415
 
370
416
  # Apply YAML hooks to PRIMARY agents
371
417
  @agents.each do |agent_name, chat|
@@ -381,7 +427,7 @@ module SwarmSDK
381
427
  # Apply YAML hooks for an agent (primary or delegation instance)
382
428
  def apply_yaml_hooks_for_agent(agent_name, chat)
383
429
  base_name = extract_base_name(agent_name)
384
- agent_config = @config_for_hooks.agents[base_name]
430
+ agent_config = @swarm.config_for_hooks.agents[base_name]
385
431
  return unless agent_config
386
432
 
387
433
  # Configuration.agents now returns hashes, not Definitions
@@ -401,7 +447,7 @@ module SwarmSDK
401
447
  chat = Agent::Chat.new(
402
448
  definition: agent_definition.to_h,
403
449
  agent_name: agent_name,
404
- global_semaphore: @global_semaphore,
450
+ global_semaphore: @swarm.global_semaphore,
405
451
  )
406
452
 
407
453
  # Set agent name on provider for logging (if provider supports it)
@@ -437,7 +483,7 @@ module SwarmSDK
437
483
  chat = Agent::Chat.new(
438
484
  definition: agent_definition.to_h,
439
485
  agent_name: instance_name.to_sym, # Full instance name for isolation
440
- global_semaphore: @global_semaphore,
486
+ global_semaphore: @swarm.global_semaphore,
441
487
  )
442
488
 
443
489
  # Set provider agent name for logging
@@ -485,7 +531,7 @@ module SwarmSDK
485
531
  if @agents.key?(delegate_name_sym)
486
532
  # Delegate to local agent
487
533
  delegate_agent = @agents[delegate_name_sym]
488
- delegate_definition = @agent_definitions[delegate_name_sym]
534
+ delegate_definition = @swarm.agent_definitions[delegate_name_sym]
489
535
 
490
536
  tool = create_delegation_tool(
491
537
  name: delegate_name_str,
@@ -495,7 +541,7 @@ module SwarmSDK
495
541
  delegating_chat: chat,
496
542
  )
497
543
 
498
- chat.with_tool(tool)
544
+ chat.add_tool(tool)
499
545
  elsif @swarm.swarm_registry&.registered?(delegate_name_str)
500
546
  # Delegate to registered swarm
501
547
  tool = create_delegation_tool(
@@ -506,7 +552,7 @@ module SwarmSDK
506
552
  delegating_chat: chat,
507
553
  )
508
554
 
509
- chat.with_tool(tool)
555
+ chat.add_tool(tool)
510
556
  else
511
557
  raise ConfigurationError, "Agent '#{agent_name}' delegates to unknown target '#{delegate_name_str}' (not a local agent or registered swarm)"
512
558
  end
@@ -521,7 +567,7 @@ module SwarmSDK
521
567
  # @return [void]
522
568
  def create_plugin_storages
523
569
  PluginRegistry.all.each do |plugin|
524
- @agent_definitions.each do |agent_name, agent_definition|
570
+ @swarm.agent_definitions.each do |agent_name, agent_definition|
525
571
  # Check if this plugin needs storage for this agent
526
572
  next unless plugin.storage_enabled?(agent_definition)
527
573
 
@@ -536,25 +582,23 @@ module SwarmSDK
536
582
  storage = plugin.create_storage(agent_name: agent_name, config: parsed_config)
537
583
 
538
584
  # Store in plugin_storages: { plugin_name => { agent_name => storage } }
539
- @plugin_storages[plugin.name] ||= {}
540
- @plugin_storages[plugin.name][agent_name] = storage
585
+ @swarm.plugin_storages[plugin.name] ||= {}
586
+ @swarm.plugin_storages[plugin.name][agent_name] = storage
541
587
  end
542
588
  end
543
589
  end
544
590
 
545
591
  # Get plugin-specific config from agent definition
546
592
  #
547
- # Plugins can store their config in agent definition under their plugin name.
548
- # E.g., memory plugin looks for `agent_definition.memory`
593
+ # Uses the generic plugin_configs accessor to retrieve plugin-specific config.
594
+ # E.g., memory plugin config is accessed via `agent_definition.plugin_config(:memory)`
549
595
  #
550
596
  # @param agent_definition [Agent::Definition] Agent definition
551
597
  # @param plugin_name [Symbol] Plugin name
552
598
  # @return [Object, nil] Plugin config or nil
553
599
  def get_plugin_config(agent_definition, plugin_name)
554
- # Try to call method named after plugin (e.g., .memory for :memory plugin)
555
- if agent_definition.respond_to?(plugin_name)
556
- agent_definition.public_send(plugin_name)
557
- end
600
+ # Use generic plugin config accessor
601
+ agent_definition.plugin_config(plugin_name)
558
602
  end
559
603
 
560
604
  # Notify all plugins that an agent was initialized
@@ -569,7 +613,7 @@ module SwarmSDK
569
613
  def notify_plugins_agent_initialized(agent_name, chat, agent_definition, tool_configurator)
570
614
  PluginRegistry.all.each do |plugin|
571
615
  # Get plugin storage for this agent (if any)
572
- plugin_storages = @plugin_storages[plugin.name] || {}
616
+ plugin_storages = @swarm.plugin_storages[plugin.name] || {}
573
617
  storage = plugin_storages[agent_name]
574
618
 
575
619
  # Build context for plugin
@@ -611,7 +655,7 @@ module SwarmSDK
611
655
  # @return [Boolean] True if only referenced as delegate
612
656
  def only_referenced_as_delegate?(name)
613
657
  # Check if any agent delegates to this one
614
- referenced_as_delegate = @agent_definitions.any? do |_agent_name, definition|
658
+ referenced_as_delegate = @swarm.agent_definitions.any? do |_agent_name, definition|
615
659
  definition.delegates_to.include?(name)
616
660
  end
617
661