strands-swarms 0.1.1__tar.gz → 0.1.2__tar.gz
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-0.1.2/.claude/settings.local.json +12 -0
- {strands_swarms-0.1.1 → strands_swarms-0.1.2}/.gitignore +1 -0
- strands_swarms-0.1.2/PKG-INFO +171 -0
- strands_swarms-0.1.2/README.md +143 -0
- strands_swarms-0.1.2/examples/simple.py +51 -0
- {strands_swarms-0.1.1 → strands_swarms-0.1.2}/pyproject.toml +1 -1
- {strands_swarms-0.1.1 → strands_swarms-0.1.2}/src/strands_swarms/__init__.py +29 -42
- strands_swarms-0.1.2/src/strands_swarms/definition.py +169 -0
- strands_swarms-0.1.2/src/strands_swarms/dynamic_swarm.py +439 -0
- strands_swarms-0.1.2/src/strands_swarms/orchestrator.py +116 -0
- strands_swarms-0.1.1/PKG-INFO +0 -391
- strands_swarms-0.1.1/README.md +0 -363
- strands_swarms-0.1.1/examples/dynamic_swarm.py +0 -207
- strands_swarms-0.1.1/src/strands_swarms/events.py +0 -563
- strands_swarms-0.1.1/src/strands_swarms/orchestrator.py +0 -265
- strands_swarms-0.1.1/src/strands_swarms/py.typed +0 -0
- strands_swarms-0.1.1/src/strands_swarms/swarm.py +0 -739
- {strands_swarms-0.1.1 → strands_swarms-0.1.2}/.github/workflows/ci.yml +0 -0
- {strands_swarms-0.1.1 → strands_swarms-0.1.2}/LICENSE +0 -0
- {strands_swarms-0.1.1 → strands_swarms-0.1.2}/assets/architecture.png +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: strands-swarms
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Task-based workflow orchestration for Strands Agents
|
|
5
|
+
Project-URL: Homepage, https://github.com/JackXu0/strands-swarms
|
|
6
|
+
Project-URL: Issues, https://github.com/JackXu0/strands-swarms/issues
|
|
7
|
+
Author-email: Zhuocheng Xu <zhuocheng.xu@icloud.com>
|
|
8
|
+
License: Apache-2.0
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: strands-agents>=0.1.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: mypy>=1.15.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-asyncio>=1.0.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff>=0.13.0; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# strands-swarms
|
|
30
|
+
|
|
31
|
+
[](https://github.com/JackXu0/strands-swarms/actions/workflows/ci.yml)
|
|
32
|
+
[](https://pypi.org/project/strands-swarms/)
|
|
33
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
34
|
+
|
|
35
|
+
**Turn natural language into multi-agent workflows — automatically.**
|
|
36
|
+
|
|
37
|
+
Give `DynamicSwarm` a query, and it automatically plans the workflow, spawns specialized agents, and executes tasks with dependencies. No manual graph configuration or agent wiring required.
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
swarm = DynamicSwarm(available_tools={...}, available_models={...})
|
|
41
|
+
result = swarm.execute("Research AI trends and write a summary report")
|
|
42
|
+
# → Spawns researcher + writer agents, handles dependencies, returns final report
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Inspiration
|
|
46
|
+
|
|
47
|
+
This project is inspired by [Kimi K2.5's Agent Swarm](https://www.kimi.com/blog/kimi-k2-5.html) — where a trainable orchestrator dynamically creates and coordinates sub-agents without predefined roles or workflows. The goal is to build an open-source foundation for training orchestrators that can spin up agent swarms on the fly.
|
|
48
|
+
|
|
49
|
+
## How It Works
|
|
50
|
+
|
|
51
|
+

|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install strands-swarms
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from strands import tool
|
|
63
|
+
from strands.models import BedrockModel
|
|
64
|
+
from strands_swarms import DynamicSwarm
|
|
65
|
+
|
|
66
|
+
# Define your tools
|
|
67
|
+
@tool
|
|
68
|
+
def search_web(query: str) -> str:
|
|
69
|
+
"""Search the web for information."""
|
|
70
|
+
return f"[Search Results for '{query}']\n- Result 1: Latest developments..."
|
|
71
|
+
|
|
72
|
+
@tool
|
|
73
|
+
def analyze_data(data: str) -> str:
|
|
74
|
+
"""Analyze data and extract insights."""
|
|
75
|
+
return f"[Analysis]\nKey insights: ..."
|
|
76
|
+
|
|
77
|
+
@tool
|
|
78
|
+
def write_file(path: str, content: str) -> str:
|
|
79
|
+
"""Write content to a file."""
|
|
80
|
+
return f"Successfully wrote {len(content)} characters to {path}"
|
|
81
|
+
|
|
82
|
+
# Configure models
|
|
83
|
+
powerful_model = BedrockModel(model_id="us.anthropic.claude-3-opus-20240229-v1:0")
|
|
84
|
+
fast_model = BedrockModel(model_id="us.anthropic.claude-3-5-haiku-20241022-v1:0")
|
|
85
|
+
|
|
86
|
+
# Create the swarm
|
|
87
|
+
swarm = DynamicSwarm(
|
|
88
|
+
available_tools={
|
|
89
|
+
"search_web": search_web,
|
|
90
|
+
"analyze_data": analyze_data,
|
|
91
|
+
"write_file": write_file,
|
|
92
|
+
},
|
|
93
|
+
available_models={
|
|
94
|
+
"powerful": powerful_model,
|
|
95
|
+
"fast": fast_model,
|
|
96
|
+
},
|
|
97
|
+
orchestrator_model=powerful_model,
|
|
98
|
+
default_agent_model="fast",
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Execute with natural language
|
|
102
|
+
result = swarm.execute("Research the latest AI trends and write a summary report")
|
|
103
|
+
|
|
104
|
+
print(f"Status: {result.status}")
|
|
105
|
+
print(f"Agents spawned: {result.agents_spawned_count}")
|
|
106
|
+
for agent in result.agents_spawned:
|
|
107
|
+
print(f" - {agent.name}: {agent.role}")
|
|
108
|
+
print(f"Tasks created: {result.tasks_created_count}")
|
|
109
|
+
for task in result.tasks_created:
|
|
110
|
+
depends = f" (depends: [{', '.join(task.depends_on)}])" if task.depends_on else ""
|
|
111
|
+
print(f" - {task.name} -> {task.agent}{depends}")
|
|
112
|
+
print(f"Final response: {result.final_response}")
|
|
113
|
+
```
|
|
114
|
+
<details>
|
|
115
|
+
<summary>Example output (see examples/simple.py)</summary>
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
Status: Status.COMPLETED
|
|
119
|
+
Agents spawned: 2
|
|
120
|
+
- researcher: AI trends researcher
|
|
121
|
+
- writer: AI trends summary writer
|
|
122
|
+
Tasks created: 3
|
|
123
|
+
- web_research -> researcher
|
|
124
|
+
- analyze_trends -> researcher (depends: [web_research])
|
|
125
|
+
- write_summary -> writer (depends: [analyze_trends])
|
|
126
|
+
Final response: <thinking>
|
|
127
|
+
The job is complete. The researchers gathered comprehensive information on the latest AI trends through web searches, analyzed that information to identify the most important developments and themes, and the writer put it together into a clear summary report touching on:
|
|
128
|
+
|
|
129
|
+
- Major AI breakthroughs in the last year across language, vision, multimodal and generative models
|
|
130
|
+
- Potential applications of these advancing AI capabilities
|
|
131
|
+
- Rapid growth in enterprise adoption and startup investment
|
|
132
|
+
- Key technical challenges like robustness, interpretability and scalability
|
|
133
|
+
- Important societal and ethical considerations around safety, bias and responsible use
|
|
134
|
+
- Longer-term possibilities around artificial general intelligence
|
|
135
|
+
|
|
136
|
+
The report provides a succinct yet informative overview of the state of the art in AI and the key trends shaping the field. It directly addresses the original request, so no further analysis or synthesis is needed. The final report can be delivered as-is to the human who made the request.
|
|
137
|
+
</thinking>
|
|
138
|
+
|
|
139
|
+
Here is a summary report on the latest trends in artificial intelligence:
|
|
140
|
+
|
|
141
|
+
Artificial intelligence continues to progress rapidly, with significant developments over the past year in areas like natural language processing, computer vision, multimodal learning, and generative AI. Powerful language models can now engage in human-like dialogue and assist with writing. AI systems can perceive and reason jointly about text, images, audio and video. New generative models can create highly realistic images from textual descriptions. And AI has achieved human-level performance on complex strategy games.
|
|
142
|
+
|
|
143
|
+
These advances open up transformative potential applications — enhancing creative workflows, accelerating scientific discovery, enabling more natural human-computer interaction. Enterprises across sectors are increasingly adopting AI technologies, and venture capital investment into AI startups reached record levels in 2022.
|
|
144
|
+
|
|
145
|
+
However, key technical challenges remain in making AI systems more robust, interpretable and scalable. Important societal considerations are also in play around AI ethics, safety, bias and responsible use. Longer-term, some believe AI could progress toward human-level artificial general intelligence, though this remains a future possibility.
|
|
146
|
+
|
|
147
|
+
In summary, AI capabilities are advancing quickly, with potentially profound impacts across domains in the coming years. Ongoing research aims to further enhance performance while addressing crucial challenges. Organizations will need to balance leveraging AI's competitive advantages with deploying it in a trustworthy manner. The field's rapid progress looks set to continue — and to reshape the world in the process.
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
</details>
|
|
151
|
+
|
|
152
|
+
## Status & Roadmap
|
|
153
|
+
|
|
154
|
+
> **Current version: Rollout-only**
|
|
155
|
+
>
|
|
156
|
+
> This release supports **rollout execution** (string-in, string-out) — ideal for inference and deployment.
|
|
157
|
+
>
|
|
158
|
+
> **Coming soon:** RL support via [strands-sglang](https://github.com/strands-agents/strands-sglang) integration.
|
|
159
|
+
|
|
160
|
+
- [x] Rollout execution — string-in, string-out multi-agent workflows
|
|
161
|
+
- [x] Dynamic orchestration — automatic agent creation and task assignment
|
|
162
|
+
- [ ] Streaming trajectory output — consume `stream_async()`
|
|
163
|
+
- [ ] RL support — training and fine-tuning via strands-sglang
|
|
164
|
+
|
|
165
|
+
## Contributing
|
|
166
|
+
|
|
167
|
+
Contributions welcome! Please feel free to submit issues and pull requests.
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
Apache-2.0
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# strands-swarms
|
|
2
|
+
|
|
3
|
+
[](https://github.com/JackXu0/strands-swarms/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/strands-swarms/)
|
|
5
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
6
|
+
|
|
7
|
+
**Turn natural language into multi-agent workflows — automatically.**
|
|
8
|
+
|
|
9
|
+
Give `DynamicSwarm` a query, and it automatically plans the workflow, spawns specialized agents, and executes tasks with dependencies. No manual graph configuration or agent wiring required.
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
swarm = DynamicSwarm(available_tools={...}, available_models={...})
|
|
13
|
+
result = swarm.execute("Research AI trends and write a summary report")
|
|
14
|
+
# → Spawns researcher + writer agents, handles dependencies, returns final report
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Inspiration
|
|
18
|
+
|
|
19
|
+
This project is inspired by [Kimi K2.5's Agent Swarm](https://www.kimi.com/blog/kimi-k2-5.html) — where a trainable orchestrator dynamically creates and coordinates sub-agents without predefined roles or workflows. The goal is to build an open-source foundation for training orchestrators that can spin up agent swarms on the fly.
|
|
20
|
+
|
|
21
|
+
## How It Works
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install strands-swarms
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from strands import tool
|
|
35
|
+
from strands.models import BedrockModel
|
|
36
|
+
from strands_swarms import DynamicSwarm
|
|
37
|
+
|
|
38
|
+
# Define your tools
|
|
39
|
+
@tool
|
|
40
|
+
def search_web(query: str) -> str:
|
|
41
|
+
"""Search the web for information."""
|
|
42
|
+
return f"[Search Results for '{query}']\n- Result 1: Latest developments..."
|
|
43
|
+
|
|
44
|
+
@tool
|
|
45
|
+
def analyze_data(data: str) -> str:
|
|
46
|
+
"""Analyze data and extract insights."""
|
|
47
|
+
return f"[Analysis]\nKey insights: ..."
|
|
48
|
+
|
|
49
|
+
@tool
|
|
50
|
+
def write_file(path: str, content: str) -> str:
|
|
51
|
+
"""Write content to a file."""
|
|
52
|
+
return f"Successfully wrote {len(content)} characters to {path}"
|
|
53
|
+
|
|
54
|
+
# Configure models
|
|
55
|
+
powerful_model = BedrockModel(model_id="us.anthropic.claude-3-opus-20240229-v1:0")
|
|
56
|
+
fast_model = BedrockModel(model_id="us.anthropic.claude-3-5-haiku-20241022-v1:0")
|
|
57
|
+
|
|
58
|
+
# Create the swarm
|
|
59
|
+
swarm = DynamicSwarm(
|
|
60
|
+
available_tools={
|
|
61
|
+
"search_web": search_web,
|
|
62
|
+
"analyze_data": analyze_data,
|
|
63
|
+
"write_file": write_file,
|
|
64
|
+
},
|
|
65
|
+
available_models={
|
|
66
|
+
"powerful": powerful_model,
|
|
67
|
+
"fast": fast_model,
|
|
68
|
+
},
|
|
69
|
+
orchestrator_model=powerful_model,
|
|
70
|
+
default_agent_model="fast",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Execute with natural language
|
|
74
|
+
result = swarm.execute("Research the latest AI trends and write a summary report")
|
|
75
|
+
|
|
76
|
+
print(f"Status: {result.status}")
|
|
77
|
+
print(f"Agents spawned: {result.agents_spawned_count}")
|
|
78
|
+
for agent in result.agents_spawned:
|
|
79
|
+
print(f" - {agent.name}: {agent.role}")
|
|
80
|
+
print(f"Tasks created: {result.tasks_created_count}")
|
|
81
|
+
for task in result.tasks_created:
|
|
82
|
+
depends = f" (depends: [{', '.join(task.depends_on)}])" if task.depends_on else ""
|
|
83
|
+
print(f" - {task.name} -> {task.agent}{depends}")
|
|
84
|
+
print(f"Final response: {result.final_response}")
|
|
85
|
+
```
|
|
86
|
+
<details>
|
|
87
|
+
<summary>Example output (see examples/simple.py)</summary>
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
Status: Status.COMPLETED
|
|
91
|
+
Agents spawned: 2
|
|
92
|
+
- researcher: AI trends researcher
|
|
93
|
+
- writer: AI trends summary writer
|
|
94
|
+
Tasks created: 3
|
|
95
|
+
- web_research -> researcher
|
|
96
|
+
- analyze_trends -> researcher (depends: [web_research])
|
|
97
|
+
- write_summary -> writer (depends: [analyze_trends])
|
|
98
|
+
Final response: <thinking>
|
|
99
|
+
The job is complete. The researchers gathered comprehensive information on the latest AI trends through web searches, analyzed that information to identify the most important developments and themes, and the writer put it together into a clear summary report touching on:
|
|
100
|
+
|
|
101
|
+
- Major AI breakthroughs in the last year across language, vision, multimodal and generative models
|
|
102
|
+
- Potential applications of these advancing AI capabilities
|
|
103
|
+
- Rapid growth in enterprise adoption and startup investment
|
|
104
|
+
- Key technical challenges like robustness, interpretability and scalability
|
|
105
|
+
- Important societal and ethical considerations around safety, bias and responsible use
|
|
106
|
+
- Longer-term possibilities around artificial general intelligence
|
|
107
|
+
|
|
108
|
+
The report provides a succinct yet informative overview of the state of the art in AI and the key trends shaping the field. It directly addresses the original request, so no further analysis or synthesis is needed. The final report can be delivered as-is to the human who made the request.
|
|
109
|
+
</thinking>
|
|
110
|
+
|
|
111
|
+
Here is a summary report on the latest trends in artificial intelligence:
|
|
112
|
+
|
|
113
|
+
Artificial intelligence continues to progress rapidly, with significant developments over the past year in areas like natural language processing, computer vision, multimodal learning, and generative AI. Powerful language models can now engage in human-like dialogue and assist with writing. AI systems can perceive and reason jointly about text, images, audio and video. New generative models can create highly realistic images from textual descriptions. And AI has achieved human-level performance on complex strategy games.
|
|
114
|
+
|
|
115
|
+
These advances open up transformative potential applications — enhancing creative workflows, accelerating scientific discovery, enabling more natural human-computer interaction. Enterprises across sectors are increasingly adopting AI technologies, and venture capital investment into AI startups reached record levels in 2022.
|
|
116
|
+
|
|
117
|
+
However, key technical challenges remain in making AI systems more robust, interpretable and scalable. Important societal considerations are also in play around AI ethics, safety, bias and responsible use. Longer-term, some believe AI could progress toward human-level artificial general intelligence, though this remains a future possibility.
|
|
118
|
+
|
|
119
|
+
In summary, AI capabilities are advancing quickly, with potentially profound impacts across domains in the coming years. Ongoing research aims to further enhance performance while addressing crucial challenges. Organizations will need to balance leveraging AI's competitive advantages with deploying it in a trustworthy manner. The field's rapid progress looks set to continue — and to reshape the world in the process.
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
</details>
|
|
123
|
+
|
|
124
|
+
## Status & Roadmap
|
|
125
|
+
|
|
126
|
+
> **Current version: Rollout-only**
|
|
127
|
+
>
|
|
128
|
+
> This release supports **rollout execution** (string-in, string-out) — ideal for inference and deployment.
|
|
129
|
+
>
|
|
130
|
+
> **Coming soon:** RL support via [strands-sglang](https://github.com/strands-agents/strands-sglang) integration.
|
|
131
|
+
|
|
132
|
+
- [x] Rollout execution — string-in, string-out multi-agent workflows
|
|
133
|
+
- [x] Dynamic orchestration — automatic agent creation and task assignment
|
|
134
|
+
- [ ] Streaming trajectory output — consume `stream_async()`
|
|
135
|
+
- [ ] RL support — training and fine-tuning via strands-sglang
|
|
136
|
+
|
|
137
|
+
## Contributing
|
|
138
|
+
|
|
139
|
+
Contributions welcome! Please feel free to submit issues and pull requests.
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
Apache-2.0
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from strands import tool
|
|
2
|
+
from strands.models import BedrockModel
|
|
3
|
+
from strands_swarms import DynamicSwarm
|
|
4
|
+
|
|
5
|
+
# Define your tools
|
|
6
|
+
@tool
|
|
7
|
+
def search_web(query: str) -> str:
|
|
8
|
+
"""Search the web for information."""
|
|
9
|
+
return f"[Search Results for '{query}']\n- Result 1: Latest developments..."
|
|
10
|
+
|
|
11
|
+
@tool
|
|
12
|
+
def analyze_data(data: str) -> str:
|
|
13
|
+
"""Analyze data and extract insights."""
|
|
14
|
+
return f"[Analysis]\nKey insights: ..."
|
|
15
|
+
|
|
16
|
+
@tool
|
|
17
|
+
def write_file(path: str, content: str) -> str:
|
|
18
|
+
"""Write content to a file."""
|
|
19
|
+
return f"Successfully wrote {len(content)} characters to {path}"
|
|
20
|
+
|
|
21
|
+
# Configure models
|
|
22
|
+
powerful_model = BedrockModel(model_id="us.anthropic.claude-3-opus-20240229-v1:0")
|
|
23
|
+
fast_model = BedrockModel(model_id="us.anthropic.claude-3-5-haiku-20241022-v1:0")
|
|
24
|
+
|
|
25
|
+
# Create the swarm
|
|
26
|
+
swarm = DynamicSwarm(
|
|
27
|
+
available_tools={
|
|
28
|
+
"search_web": search_web,
|
|
29
|
+
"analyze_data": analyze_data,
|
|
30
|
+
"write_file": write_file,
|
|
31
|
+
},
|
|
32
|
+
available_models={
|
|
33
|
+
"powerful": powerful_model,
|
|
34
|
+
"fast": fast_model,
|
|
35
|
+
},
|
|
36
|
+
orchestrator_model=powerful_model,
|
|
37
|
+
default_agent_model="fast",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Execute with natural language
|
|
41
|
+
result = swarm.execute("Research the latest AI trends and write a summary report")
|
|
42
|
+
|
|
43
|
+
print(f"Status: {result.status}")
|
|
44
|
+
print(f"Agents spawned: {result.agents_spawned_count}")
|
|
45
|
+
for agent in result.agents_spawned:
|
|
46
|
+
print(f" - {agent.name}: {agent.role}")
|
|
47
|
+
print(f"Tasks created: {result.tasks_created_count}")
|
|
48
|
+
for task in result.tasks_created:
|
|
49
|
+
depends = f" (depends: [{', '.join(task.depends_on)}])" if task.depends_on else ""
|
|
50
|
+
print(f" - {task.name} -> {task.agent}{depends}")
|
|
51
|
+
print(f"Final response: {result.final_response}")
|
|
@@ -26,37 +26,35 @@ Example:
|
|
|
26
26
|
'''Search the web.'''
|
|
27
27
|
return f"Results for: {query}"
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
verbose=True,
|
|
32
|
-
)
|
|
29
|
+
# Basic usage
|
|
30
|
+
swarm = DynamicSwarm(available_tools={"search_web": search_web})
|
|
33
31
|
result = swarm.execute("Research AI trends and summarize")
|
|
32
|
+
|
|
33
|
+
# Streaming trajectory
|
|
34
|
+
import asyncio
|
|
35
|
+
|
|
36
|
+
async def run():
|
|
37
|
+
async for event in swarm.stream_async(
|
|
38
|
+
"Research AI trends and summarize",
|
|
39
|
+
include_subagent_events=False,
|
|
40
|
+
):
|
|
41
|
+
print(event)
|
|
42
|
+
|
|
43
|
+
asyncio.run(run())
|
|
34
44
|
"""
|
|
35
45
|
|
|
36
46
|
# Re-export strands types for convenience
|
|
37
|
-
from strands.hooks import HookProvider, HookRegistry
|
|
38
47
|
from strands.multiagent.base import Status
|
|
39
48
|
|
|
40
|
-
from .
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
PlanningStartedEvent,
|
|
47
|
-
# Hook provider
|
|
48
|
-
PrintingHookProvider,
|
|
49
|
-
SwarmCompletedEvent,
|
|
50
|
-
SwarmFailedEvent,
|
|
51
|
-
# Planning/Orchestration events
|
|
52
|
-
SwarmStartedEvent,
|
|
53
|
-
TaskCompletedEvent,
|
|
54
|
-
TaskCreatedEvent,
|
|
55
|
-
TaskFailedEvent,
|
|
56
|
-
TaskStartedEvent,
|
|
49
|
+
from .definition import (
|
|
50
|
+
AgentDefinition,
|
|
51
|
+
DynamicSwarmCapabilities,
|
|
52
|
+
SessionConfig,
|
|
53
|
+
SwarmDefinition,
|
|
54
|
+
TaskDefinition,
|
|
57
55
|
)
|
|
56
|
+
from .dynamic_swarm import DynamicSwarm, DynamicSwarmResult, build_swarm
|
|
58
57
|
from .orchestrator import create_orchestrator_agent
|
|
59
|
-
from .swarm import DynamicSwarm, DynamicSwarmResult
|
|
60
58
|
|
|
61
59
|
__version__ = "0.1.1"
|
|
62
60
|
|
|
@@ -64,25 +62,14 @@ __all__ = [
|
|
|
64
62
|
# Main API
|
|
65
63
|
"DynamicSwarm",
|
|
66
64
|
"DynamicSwarmResult",
|
|
67
|
-
|
|
65
|
+
"build_swarm",
|
|
66
|
+
# Definition types
|
|
67
|
+
"DynamicSwarmCapabilities",
|
|
68
|
+
"SwarmDefinition",
|
|
69
|
+
"AgentDefinition",
|
|
70
|
+
"TaskDefinition",
|
|
71
|
+
"SessionConfig",
|
|
72
|
+
# Orchestrator
|
|
68
73
|
"create_orchestrator_agent",
|
|
69
|
-
# Status enum
|
|
70
74
|
"Status",
|
|
71
|
-
# Events (for custom hooks)
|
|
72
|
-
"SwarmStartedEvent",
|
|
73
|
-
"PlanningStartedEvent",
|
|
74
|
-
"AgentSpawnedEvent",
|
|
75
|
-
"TaskCreatedEvent",
|
|
76
|
-
"PlanningCompletedEvent",
|
|
77
|
-
"ExecutionStartedEvent",
|
|
78
|
-
"TaskStartedEvent",
|
|
79
|
-
"TaskCompletedEvent",
|
|
80
|
-
"TaskFailedEvent",
|
|
81
|
-
"ExecutionCompletedEvent",
|
|
82
|
-
"SwarmCompletedEvent",
|
|
83
|
-
"SwarmFailedEvent",
|
|
84
|
-
# Hook system
|
|
85
|
-
"PrintingHookProvider",
|
|
86
|
-
"HookProvider",
|
|
87
|
-
"HookRegistry",
|
|
88
75
|
]
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""Swarm definition types - data structures for defining multi-agent workflows."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Callable
|
|
7
|
+
|
|
8
|
+
from strands.session.file_session_manager import FileSessionManager
|
|
9
|
+
|
|
10
|
+
# ANSI Color Constants (for consistent agent output coloring)
|
|
11
|
+
AGENT_COLORS: list[str] = [
|
|
12
|
+
"\033[94m", # Blue
|
|
13
|
+
"\033[92m", # Green
|
|
14
|
+
"\033[93m", # Yellow
|
|
15
|
+
"\033[95m", # Magenta
|
|
16
|
+
"\033[96m", # Cyan
|
|
17
|
+
"\033[91m", # Red
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from strands.models import Model
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class DynamicSwarmCapabilities:
|
|
26
|
+
"""Immutable configuration for available tools and models."""
|
|
27
|
+
|
|
28
|
+
available_tools: dict[str, Callable[..., Any]]
|
|
29
|
+
available_models: dict[str, "Model"]
|
|
30
|
+
default_model: str | None = None
|
|
31
|
+
|
|
32
|
+
def validate_tools(self, tool_names: list[str]) -> None:
|
|
33
|
+
"""Validate that all tool names exist in available tools."""
|
|
34
|
+
for tool_name in tool_names:
|
|
35
|
+
if tool_name not in self.available_tools:
|
|
36
|
+
available = list(self.available_tools.keys())
|
|
37
|
+
raise ValueError(
|
|
38
|
+
f"Tool '{tool_name}' not in available tools: {available}"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def validate_model(self, model_name: str | None) -> None:
|
|
42
|
+
"""Validate that the model name exists in available models."""
|
|
43
|
+
if model_name and model_name not in self.available_models:
|
|
44
|
+
available = list(self.available_models.keys())
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"Model '{model_name}' not in available models: {available}"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def available_tool_names(self) -> list[str]:
|
|
51
|
+
return list(self.available_tools.keys())
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def available_model_names(self) -> list[str]:
|
|
55
|
+
return list(self.available_models.keys())
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class AgentDefinition:
|
|
60
|
+
"""Definition of a sub-agent to be spawned."""
|
|
61
|
+
|
|
62
|
+
name: str
|
|
63
|
+
role: str
|
|
64
|
+
instructions: str | None = None
|
|
65
|
+
tools: list[str] = field(default_factory=list)
|
|
66
|
+
model: str | None = None
|
|
67
|
+
color: str | None = None
|
|
68
|
+
|
|
69
|
+
def build_system_prompt(self) -> str:
|
|
70
|
+
parts = [f"You are a {self.role}."]
|
|
71
|
+
if self.instructions:
|
|
72
|
+
parts.append(f"\n\nInstructions:\n{self.instructions}")
|
|
73
|
+
return "\n".join(parts)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass
|
|
77
|
+
class TaskDefinition:
|
|
78
|
+
"""Definition of a task to be executed by a sub-agent."""
|
|
79
|
+
|
|
80
|
+
name: str
|
|
81
|
+
agent: str
|
|
82
|
+
description: str | None = None
|
|
83
|
+
depends_on: list[str] = field(default_factory=list)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@dataclass
|
|
87
|
+
class SessionConfig:
|
|
88
|
+
"""Configuration for session persistence."""
|
|
89
|
+
|
|
90
|
+
session_id: str
|
|
91
|
+
storage_dir: str = "./.swarm_sessions"
|
|
92
|
+
|
|
93
|
+
def for_agent(self, agent_name: str) -> FileSessionManager:
|
|
94
|
+
return FileSessionManager(
|
|
95
|
+
session_id=f"{self.session_id}-{agent_name}",
|
|
96
|
+
storage_dir=self.storage_dir,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
def for_graph(self) -> FileSessionManager:
|
|
100
|
+
return FileSessionManager(
|
|
101
|
+
session_id=f"{self.session_id}-graph",
|
|
102
|
+
storage_dir=self.storage_dir,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class SwarmDefinition:
|
|
107
|
+
"""Per-query definition of sub-agents and tasks created during planning."""
|
|
108
|
+
|
|
109
|
+
def __init__(
|
|
110
|
+
self,
|
|
111
|
+
capabilities: DynamicSwarmCapabilities,
|
|
112
|
+
) -> None:
|
|
113
|
+
self._capabilities = capabilities
|
|
114
|
+
self.sub_agents: dict[str, AgentDefinition] = {}
|
|
115
|
+
self.tasks: dict[str, TaskDefinition] = {}
|
|
116
|
+
self._color_index = 0
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def capabilities(self) -> DynamicSwarmCapabilities:
|
|
120
|
+
return self._capabilities
|
|
121
|
+
|
|
122
|
+
def register_agent(self, definition: AgentDefinition) -> None:
|
|
123
|
+
"""Register a sub-agent definition."""
|
|
124
|
+
if definition.name in self.sub_agents:
|
|
125
|
+
raise ValueError(f"Agent '{definition.name}' already exists")
|
|
126
|
+
|
|
127
|
+
self._capabilities.validate_tools(definition.tools)
|
|
128
|
+
self._capabilities.validate_model(definition.model)
|
|
129
|
+
|
|
130
|
+
definition.color = AGENT_COLORS[self._color_index % len(AGENT_COLORS)]
|
|
131
|
+
self._color_index += 1
|
|
132
|
+
|
|
133
|
+
self.sub_agents[definition.name] = definition
|
|
134
|
+
|
|
135
|
+
def register_task(self, definition: TaskDefinition) -> None:
|
|
136
|
+
"""Register a task definition.
|
|
137
|
+
|
|
138
|
+
Note: dependencies must already be registered (create dependency tasks first).
|
|
139
|
+
"""
|
|
140
|
+
if definition.name in self.tasks:
|
|
141
|
+
raise ValueError(f"Task '{definition.name}' already exists")
|
|
142
|
+
|
|
143
|
+
if definition.agent not in self.sub_agents:
|
|
144
|
+
available = list(self.sub_agents.keys())
|
|
145
|
+
raise ValueError(
|
|
146
|
+
f"Agent '{definition.agent}' not found. Available: {available}"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
for dep in definition.depends_on:
|
|
150
|
+
if dep not in self.tasks:
|
|
151
|
+
available = list(self.tasks.keys())
|
|
152
|
+
raise ValueError(
|
|
153
|
+
f"Dependency '{dep}' not found. Available: {available}"
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
self.tasks[definition.name] = definition
|
|
157
|
+
|
|
158
|
+
def get_summary(self) -> str:
|
|
159
|
+
"""Get a summary of registered sub-agents and tasks."""
|
|
160
|
+
lines = [
|
|
161
|
+
f"Agents ({len(self.sub_agents)}):",
|
|
162
|
+
*[f" - {name}: {d.role}" for name, d in self.sub_agents.items()],
|
|
163
|
+
f"\nTasks ({len(self.tasks)}):",
|
|
164
|
+
*[
|
|
165
|
+
f" - {name} -> {d.agent}" + (f" (depends: {d.depends_on})" if d.depends_on else "")
|
|
166
|
+
for name, d in self.tasks.items()
|
|
167
|
+
],
|
|
168
|
+
]
|
|
169
|
+
return "\n".join(lines)
|