Skip to content

Commit b637e7e

Browse files
author
Murat Kaan Meral
committed
feat(swarm): Make entry point configurable
1 parent fe7a700 commit b637e7e

2 files changed

Lines changed: 78 additions & 1 deletion

File tree

src/strands/multiagent/swarm.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ def __init__(
196196
self,
197197
nodes: list[Agent],
198198
*,
199+
entry_point: str | None = None,
199200
max_handoffs: int = 20,
200201
max_iterations: int = 20,
201202
execution_timeout: float = 900.0,
@@ -207,6 +208,7 @@ def __init__(
207208
208209
Args:
209210
nodes: List of nodes (e.g. Agent) to include in the swarm
211+
entry_point: Name of the agent to start with. If None, uses the first agent (default: None)
210212
max_handoffs: Maximum handoffs to agents and users (default: 20)
211213
max_iterations: Maximum node executions within the swarm (default: 20)
212214
execution_timeout: Total execution timeout in seconds (default: 900.0)
@@ -218,6 +220,7 @@ def __init__(
218220
"""
219221
super().__init__()
220222

223+
self.entry_point = entry_point
221224
self.max_handoffs = max_handoffs
222225
self.max_iterations = max_iterations
223226
self.execution_timeout = execution_timeout
@@ -276,7 +279,11 @@ async def invoke_async(
276279
logger.debug("starting swarm execution")
277280

278281
# Initialize swarm state with configuration
279-
initial_node = next(iter(self.nodes.values())) # First SwarmNode
282+
if self.entry_point:
283+
initial_node = self.nodes[self.entry_point]
284+
else:
285+
initial_node = next(iter(self.nodes.values())) # First SwarmNode
286+
280287
self.state = SwarmState(
281288
current_node=initial_node,
282289
task=task,
@@ -326,9 +333,23 @@ def _setup_swarm(self, nodes: list[Agent]) -> None:
326333

327334
self.nodes[node_id] = SwarmNode(node_id=node_id, executor=node)
328335

336+
# Validate entry point if specified
337+
if self.entry_point is not None:
338+
if self.entry_point not in self.nodes:
339+
available_nodes = list(self.nodes.keys())
340+
raise ValueError(
341+
f"Entry point '{self.entry_point}' not found in swarm nodes. Available nodes: {available_nodes}"
342+
)
343+
329344
swarm_nodes = list(self.nodes.values())
330345
logger.debug("nodes=<%s> | initialized swarm with nodes", [node.node_id for node in swarm_nodes])
331346

347+
if self.entry_point:
348+
logger.debug("entry_point=<%s> | configured entry point", self.entry_point)
349+
else:
350+
first_node = next(iter(self.nodes.keys()))
351+
logger.debug("entry_point=<%s> | using first node as entry point", first_node)
352+
332353
def _validate_swarm(self, nodes: list[Agent]) -> None:
333354
"""Validate swarm structure and nodes."""
334355
# Check for duplicate object instances

tests/strands/multiagent/test_swarm.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,62 @@ def test_swarm_auto_completion_without_handoff():
451451
no_handoff_agent.invoke_async.assert_called()
452452

453453

454+
def test_swarm_configurable_entry_point():
455+
"""Test swarm with configurable entry point."""
456+
# Create multiple agents
457+
agent1 = create_mock_agent("agent1", "Agent 1 response")
458+
agent2 = create_mock_agent("agent2", "Agent 2 response")
459+
agent3 = create_mock_agent("agent3", "Agent 3 response")
460+
461+
# Create swarm with agent2 as entry point
462+
swarm = Swarm([agent1, agent2, agent3], entry_point="agent2")
463+
464+
# Verify entry point is set correctly
465+
assert swarm.entry_point == "agent2"
466+
467+
# Execute swarm
468+
result = swarm("Test task")
469+
470+
# Verify agent2 was the first to execute
471+
assert result.status == Status.COMPLETED
472+
assert len(result.node_history) == 1
473+
assert result.node_history[0].node_id == "agent2"
474+
475+
476+
def test_swarm_invalid_entry_point():
477+
"""Test swarm with invalid entry point raises error."""
478+
agent1 = create_mock_agent("agent1", "Agent 1 response")
479+
agent2 = create_mock_agent("agent2", "Agent 2 response")
480+
481+
# Try to create swarm with non-existent entry point
482+
with pytest.raises(ValueError, match="Entry point 'nonexistent' not found in swarm nodes"):
483+
Swarm([agent1, agent2], entry_point="nonexistent")
484+
485+
# Try with random string entry point
486+
with pytest.raises(ValueError, match="Entry point 'xyz123random' not found in swarm nodes"):
487+
Swarm([agent1, agent2], entry_point="xyz123random")
488+
489+
490+
def test_swarm_default_entry_point():
491+
"""Test swarm uses first agent as default entry point."""
492+
agent1 = create_mock_agent("agent1", "Agent 1 response")
493+
agent2 = create_mock_agent("agent2", "Agent 2 response")
494+
495+
# Create swarm without specifying entry point
496+
swarm = Swarm([agent1, agent2])
497+
498+
# Verify no explicit entry point is set
499+
assert swarm.entry_point is None
500+
501+
# Execute swarm
502+
result = swarm("Test task")
503+
504+
# Verify first agent was used as entry point
505+
assert result.status == Status.COMPLETED
506+
assert len(result.node_history) == 1
507+
assert result.node_history[0].node_id == "agent1"
508+
509+
454510
def test_swarm_validate_unsupported_features():
455511
"""Test Swarm validation for session persistence and callbacks."""
456512
# Test with normal agent (should work)

0 commit comments

Comments
 (0)