strands-swarms 0.1.0__py3-none-any.whl
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.
- strands_swarms/__init__.py +88 -0
- strands_swarms/events.py +564 -0
- strands_swarms/orchestrator.py +265 -0
- strands_swarms/py.typed +0 -0
- strands_swarms/swarm.py +738 -0
- strands_swarms-0.1.0.dist-info/METADATA +386 -0
- strands_swarms-0.1.0.dist-info/RECORD +9 -0
- strands_swarms-0.1.0.dist-info/WHEEL +4 -0
- strands_swarms-0.1.0.dist-info/licenses/LICENSE +176 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"""Orchestrator agent that plans, creates sub-agents, assigns tasks, and synthesizes completion."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
6
|
+
|
|
7
|
+
from strands import Agent, tool
|
|
8
|
+
from strands.hooks import HookRegistry
|
|
9
|
+
|
|
10
|
+
from .events import AgentInfo, AgentSpawnedEvent, PlanningCompletedEvent, TaskCreatedEvent, TaskInfo
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from strands.models import Model
|
|
14
|
+
|
|
15
|
+
from .swarm import SwarmConfig
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# --- System Prompt ---
|
|
19
|
+
|
|
20
|
+
ORCHESTRATOR_SYSTEM_PROMPT = """\
|
|
21
|
+
You are a workflow orchestrator that plans, creates sub-agents, assigns tasks, and synthesizes completion.
|
|
22
|
+
|
|
23
|
+
## Your Four Responsibilities
|
|
24
|
+
|
|
25
|
+
### 1. Planning
|
|
26
|
+
Analyze the request and break it into logical steps. Determine what specialized agents are needed.
|
|
27
|
+
|
|
28
|
+
### 2. Creating Sub-agents
|
|
29
|
+
Spawn specialized agents with appropriate tools and models. Each agent should have a focused role.
|
|
30
|
+
|
|
31
|
+
### 3. Assigning Tasks
|
|
32
|
+
Create tasks and assign them to agents. Define dependencies when one task needs results from another.
|
|
33
|
+
|
|
34
|
+
### 4. Synthesizing Completion
|
|
35
|
+
After all tasks complete, synthesize outputs into a cohesive final response. Be direct - deliver
|
|
36
|
+
the result as if you completed the task yourself without mentioning sub-agents or the process.
|
|
37
|
+
|
|
38
|
+
## Your Process
|
|
39
|
+
|
|
40
|
+
Think through the problem step-by-step:
|
|
41
|
+
|
|
42
|
+
1. **Analyze the request** - What needs to be done? Break it into logical steps.
|
|
43
|
+
2. **Design agents** - What specialized agents are needed? What tools does each need?
|
|
44
|
+
3. **Plan dependencies** - Which tasks must wait for others? Draw the dependency graph.
|
|
45
|
+
4. **Finalize** - Call finalize_plan when done creating agents and tasks.
|
|
46
|
+
|
|
47
|
+
## Output Format
|
|
48
|
+
|
|
49
|
+
Structure your response clearly:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
### Analysis
|
|
53
|
+
[Brief analysis of what's needed]
|
|
54
|
+
|
|
55
|
+
### Agents Needed
|
|
56
|
+
[List agents you'll create and why]
|
|
57
|
+
|
|
58
|
+
### Workflow Dependencies
|
|
59
|
+
[Show which tasks depend on which, e.g., "write_report waits for research to complete"]
|
|
60
|
+
|
|
61
|
+
### Building Workflow
|
|
62
|
+
[Then call the tools]
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Tools
|
|
66
|
+
|
|
67
|
+
**spawn_agent(name, role, tools, model)**
|
|
68
|
+
- Creates an agent with specific capabilities
|
|
69
|
+
|
|
70
|
+
**create_task(name, agent_name, description, depends_on)**
|
|
71
|
+
- Creates a task assigned to an agent
|
|
72
|
+
- depends_on: list of task names that must finish BEFORE this task starts
|
|
73
|
+
|
|
74
|
+
**finalize_plan()**
|
|
75
|
+
- Signals that planning is complete
|
|
76
|
+
- Call this after you've created all agents and tasks
|
|
77
|
+
|
|
78
|
+
## Example
|
|
79
|
+
|
|
80
|
+
For "Research AI and write a report":
|
|
81
|
+
|
|
82
|
+
### Analysis
|
|
83
|
+
Need to: 1) Research AI trends, 2) Write a report based on research.
|
|
84
|
+
The report cannot be written until research is done.
|
|
85
|
+
|
|
86
|
+
### Agents Needed
|
|
87
|
+
- researcher: Gathers information (needs search_web)
|
|
88
|
+
- writer: Creates reports (needs write_file)
|
|
89
|
+
|
|
90
|
+
### Workflow Dependencies
|
|
91
|
+
research_task → write_task (writer waits for researcher)
|
|
92
|
+
|
|
93
|
+
### Building Workflow
|
|
94
|
+
[spawn agents, create tasks with depends_on, finalize_plan]
|
|
95
|
+
|
|
96
|
+
Now analyze the request and build the workflow.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# --- Swarm Config Management ---
|
|
101
|
+
|
|
102
|
+
_swarm_config: SwarmConfig | None = None
|
|
103
|
+
_hook_registry: HookRegistry | None = None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def set_swarm_config(config: SwarmConfig | None, hook_registry: HookRegistry | None = None) -> None:
|
|
107
|
+
"""Set swarm config and hook registry. Called by DynamicSwarm before orchestration."""
|
|
108
|
+
global _swarm_config, _hook_registry
|
|
109
|
+
_swarm_config = config
|
|
110
|
+
_hook_registry = hook_registry
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def get_swarm_config() -> SwarmConfig:
|
|
114
|
+
"""Get swarm config, raising RuntimeError if not set."""
|
|
115
|
+
if _swarm_config is None:
|
|
116
|
+
raise RuntimeError("No swarm config set. Orchestrator tools must be used within DynamicSwarm.")
|
|
117
|
+
return _swarm_config
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _emit(event: Any) -> None:
|
|
121
|
+
if _hook_registry and _hook_registry.has_callbacks():
|
|
122
|
+
_hook_registry.invoke_callbacks(event)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _build_agents_info(config: SwarmConfig) -> list[AgentInfo]:
|
|
126
|
+
return [
|
|
127
|
+
AgentInfo(
|
|
128
|
+
name=a.name, role=a.role, tools=a.tools, model=a.model, color=a.color
|
|
129
|
+
)
|
|
130
|
+
for a in config.agents.values()
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _build_tasks_info(config: SwarmConfig) -> list[TaskInfo]:
|
|
135
|
+
return [
|
|
136
|
+
TaskInfo(
|
|
137
|
+
name=t.name, agent=t.agent, description=t.description, depends_on=t.depends_on
|
|
138
|
+
)
|
|
139
|
+
for t in config.tasks.values()
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
# --- Orchestrator Tools ---
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@tool
|
|
147
|
+
def list_available_tools() -> str:
|
|
148
|
+
"""List all tools available for spawned agents."""
|
|
149
|
+
tools = get_swarm_config().available_tool_names
|
|
150
|
+
return "Available tools:\n" + "\n".join(f" - {t}" for t in tools) if tools else "No tools available."
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@tool
|
|
154
|
+
def list_available_models() -> str:
|
|
155
|
+
"""List all models available for spawned agents."""
|
|
156
|
+
models = get_swarm_config().available_model_names
|
|
157
|
+
return "Available models:\n" + "\n".join(f" - {m}" for m in models) if models else "No models configured."
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@tool
|
|
161
|
+
def spawn_agent(
|
|
162
|
+
name: str,
|
|
163
|
+
role: str,
|
|
164
|
+
instructions: str = "",
|
|
165
|
+
tools: list[str] | None = None,
|
|
166
|
+
model: str | None = None,
|
|
167
|
+
) -> str:
|
|
168
|
+
"""Spawn a new sub-agent with specific capabilities."""
|
|
169
|
+
from .swarm import AgentDefinition
|
|
170
|
+
|
|
171
|
+
config = get_swarm_config()
|
|
172
|
+
definition = AgentDefinition(
|
|
173
|
+
name=name,
|
|
174
|
+
role=role,
|
|
175
|
+
instructions=instructions or None,
|
|
176
|
+
tools=tools or [],
|
|
177
|
+
model=model,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
config.register_agent(definition)
|
|
182
|
+
agent_def = config.agents.get(name)
|
|
183
|
+
_emit(AgentSpawnedEvent(
|
|
184
|
+
name=name,
|
|
185
|
+
role=role,
|
|
186
|
+
instructions=instructions or None,
|
|
187
|
+
tools=tools or [],
|
|
188
|
+
model=model,
|
|
189
|
+
color=agent_def.color if agent_def else None,
|
|
190
|
+
))
|
|
191
|
+
return f"✓ Spawned '{name}' ({role})"
|
|
192
|
+
except ValueError as e:
|
|
193
|
+
return f"✗ Failed: {e}"
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@tool
|
|
197
|
+
def create_task(
|
|
198
|
+
name: str,
|
|
199
|
+
agent_name: str,
|
|
200
|
+
description: str = "",
|
|
201
|
+
depends_on: list[str] | None = None,
|
|
202
|
+
) -> str:
|
|
203
|
+
"""Create a task and assign it to a spawned agent."""
|
|
204
|
+
from .swarm import TaskDefinition
|
|
205
|
+
|
|
206
|
+
config = get_swarm_config()
|
|
207
|
+
definition = TaskDefinition(
|
|
208
|
+
name=name,
|
|
209
|
+
agent=agent_name,
|
|
210
|
+
description=description or None,
|
|
211
|
+
depends_on=depends_on or [],
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
try:
|
|
215
|
+
config.register_task(definition)
|
|
216
|
+
_emit(TaskCreatedEvent(
|
|
217
|
+
name=name,
|
|
218
|
+
agent=agent_name,
|
|
219
|
+
description=description or None,
|
|
220
|
+
depends_on=depends_on or [],
|
|
221
|
+
))
|
|
222
|
+
return f"✓ Created '{name}' -> '{agent_name}'"
|
|
223
|
+
except ValueError as e:
|
|
224
|
+
return f"✗ Failed: {e}"
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
@tool
|
|
228
|
+
def get_planning_status() -> str:
|
|
229
|
+
"""Get current planning status - agents and tasks defined so far."""
|
|
230
|
+
return get_swarm_config().get_summary()
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
@tool
|
|
234
|
+
def finalize_plan() -> str:
|
|
235
|
+
"""Signal that planning is complete. Call after creating all agents and tasks."""
|
|
236
|
+
config = get_swarm_config()
|
|
237
|
+
|
|
238
|
+
_emit(PlanningCompletedEvent(
|
|
239
|
+
entry_task=None,
|
|
240
|
+
agents=_build_agents_info(config),
|
|
241
|
+
tasks=_build_tasks_info(config),
|
|
242
|
+
))
|
|
243
|
+
return f"✓ Planning complete.\n\n{config.get_summary()}"
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
# --- Agent Factory ---
|
|
247
|
+
|
|
248
|
+
ORCHESTRATOR_TOOLS = [
|
|
249
|
+
list_available_tools,
|
|
250
|
+
list_available_models,
|
|
251
|
+
spawn_agent,
|
|
252
|
+
create_task,
|
|
253
|
+
get_planning_status,
|
|
254
|
+
finalize_plan,
|
|
255
|
+
]
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def create_orchestrator_agent(model: Model | None = None) -> Agent:
|
|
259
|
+
"""Create orchestrator agent that plans, creates sub-agents, assigns tasks, and synthesizes completion."""
|
|
260
|
+
return Agent(
|
|
261
|
+
name="orchestrator",
|
|
262
|
+
system_prompt=ORCHESTRATOR_SYSTEM_PROMPT,
|
|
263
|
+
model=model,
|
|
264
|
+
tools=ORCHESTRATOR_TOOLS,
|
|
265
|
+
)
|
strands_swarms/py.typed
ADDED
|
File without changes
|