# Agent Configuration
Source: https://docs.swarms.world/agents/agent-configuration
Complete guide to configuring agents with all available parameters
The `Agent` class provides extensive configuration options to customize behavior, performance, and capabilities.
## Core Parameters
### Model Configuration
The name of the language model to use. Supports any model from OpenAI, Anthropic, Groq, Cohere, and more via LiteLLM.
```python theme={null}
agent = Agent(model_name="claude-sonnet-4-6")
agent = Agent(model_name="claude-sonnet-4-5")
agent = Agent(model_name="groq/llama-3.1-70b")
```
Pre-configured LLM instance. If not provided, will be created automatically based on `model_name`.
```python theme={null}
from swarms.utils.litellm_wrapper import LiteLLM
llm = LiteLLM(model_name="claude-sonnet-4-6", temperature=0.5)
agent = Agent(llm=llm)
```
Controls randomness in model outputs (0.0 = deterministic, 1.0 = creative).
```python theme={null}
# Deterministic for code generation
agent = Agent(model_name="claude-sonnet-4-6", temperature=0.1)
# Creative for writing
agent = Agent(model_name="claude-sonnet-4-6", temperature=0.9)
```
Maximum number of tokens to generate in a single response.
The constructor default is actually `None`. When left unset, `self.max_tokens` resolves during `__init__` to the model's real max-output-tokens (via `_default_max_tokens()`), falling back to `16000` only if that lookup fails. Pass `max_tokens` explicitly to override the resolved value.
```python theme={null}
agent = Agent(model_name="claude-sonnet-4-6", max_tokens=8192)
```
Maximum context window size, used as the denominator for the `ContextCompressor` threshold check (see [Agent Memory](/agents/agent-memory)).
The value you pass is respected: `self.context_length` is only replaced by a model-derived default when you leave it as `None`. (An earlier release did overwrite it unconditionally; that is fixed.)
```python theme={null}
agent = Agent(model_name="claude-sonnet-4-6", context_length=128000)
```
Enable provider-side prompt caching. When `True`, the stable prefix of each request (system prompt, tools, and last message) is cached and re-billed at a large discount. Applies to the Anthropic model family (Claude on Anthropic / Bedrock / Vertex); OpenAI and other auto-caching providers are left untouched. See the full [Prompt Caching guide](/agents/prompt-caching).
```python theme={null}
agent = Agent(model_name="claude-opus-4-8", prompt_caching=True, temperature=None)
```
Fine-grained prompt-caching options; only consulted when `prompt_caching=True`. Keys (all optional): `ttl` (`"5m"` | `"1h"`), `cache_system_prompt` (bool), `cache_messages` (bool), `cache_tools` (bool), `override` (bool | None — force injection on/off), and OpenAI-only `prompt_cache_key` / `prompt_cache_retention` (`"in_memory"` | `"24h"`).
```python theme={null}
agent = Agent(
model_name="claude-opus-4-8",
prompt_caching=True,
cache_config={"ttl": "1h", "cache_tools": True},
temperature=None,
)
```
### Agent Identity
Unique name for the agent. Used in multi-agent systems and logging. Omitted,
it defaults to the literal string `"swarm-worker-01"` — the same value for
every agent that doesn't set one.
Because `MEMORY.md` is keyed on `agent_name`, every agent left at the
default name reads and writes the *same* memory folder. Always give
long-running or persistent-memory agents a unique `agent_name`.
```python theme={null}
agent = Agent(
agent_name="Financial-Analyst",
model_name="claude-sonnet-4-6"
)
```
Description of the agent's purpose and capabilities.
```python theme={null}
agent = Agent(
agent_name="Data-Analyst",
agent_description="Expert in data analysis, visualization, and statistical modeling",
model_name="claude-sonnet-4-6"
)
```
The system prompt that defines agent behavior and expertise.
```python theme={null}
SYSTEM_PROMPT = """
You are a senior software engineer specializing in:
- Clean code architecture
- Test-driven development
- Code review best practices
Provide detailed, well-documented code solutions.
"""
agent = Agent(
system_prompt=SYSTEM_PROMPT,
model_name="claude-sonnet-4-6"
)
```
### Execution Control
Number of execution loops. Set to "auto" for autonomous mode.
```python theme={null}
# Single execution
agent = Agent(max_loops=1)
# Multi-step reasoning
agent = Agent(max_loops=5)
# Autonomous mode
agent = Agent(max_loops="auto")
```
Delay in seconds between loops.
```python theme={null}
agent = Agent(max_loops=5, loop_interval=1) # 1 second delay
```
Number of retry attempts for failed LLM calls.
```python theme={null}
agent = Agent(retry_attempts=5)
```
### Output Configuration
Format for agent output. Options: "str", "list", "json", "dict", "yaml", "xml".
```python theme={null}
# String output
agent = Agent(output_type="str")
# JSON output
agent = Agent(output_type="json")
# Dictionary output
agent = Agent(output_type="dict")
```
Enable basic streaming with formatted panels.
```python theme={null}
agent = Agent(streaming_on=True)
```
Enable detailed token-by-token streaming with metadata.
```python theme={null}
agent = Agent(stream=True)
response = agent.run("Tell me a story") # Streams each token
```
Callback function to receive streaming tokens in real-time.
```python theme={null}
def on_token(token: str):
print(f"Token: {token}", end="", flush=True)
agent = Agent(streaming_callback=on_token)
```
### Streaming Methods
In addition to the streaming flags above, the `Agent` exposes two streaming methods that yield tokens as a generator. They are real LLM streaming — tokens are forwarded the moment LiteLLM emits them, across **every loop** of the agent (tool-call turns, synthesis turns, autonomous plan/execute/summary phases).
#### `agent.run_stream(task) -> Iterator[str]`
Sync generator that yields tokens. The agent runs in a background thread; tokens are pushed onto a queue and yielded to the caller in order.
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="Writer",
model_name="gpt-5.4-mini",
max_loops=3,
)
for token in agent.run_stream("Write a short poem about distributed systems."):
print(token, end="", flush=True)
```
#### `agent.arun_stream(task) -> AsyncIterator[str]`
Async generator. Same semantics as `run_stream`, but the agent loop runs in a thread executor while tokens are forwarded through an `asyncio.Queue`, so the caller's event loop is never blocked.
```python theme={null}
import asyncio
from swarms import Agent
agent = Agent(
agent_name="Writer",
model_name="gpt-5.4-mini",
max_loops=1,
)
async def main():
async for token in agent.arun_stream("Explain async/await in two sentences."):
print(token, end="", flush=True)
asyncio.run(main())
```
Both methods stream tokens through every internal loop, including tool calls, synthesis turns after a tool returns, and the autonomous plan/execute/summary cycle when `max_loops="auto"`.
Enable detailed logging output.
```python theme={null}
agent = Agent(verbose=True)
```
Enable printing of agent responses.
```python theme={null}
agent = Agent(print_on=True)
```
### Memory and History
To get the full conversation history instead of just the final response, use the `output_type` parameter (e.g. `output_type="list"` or `output_type="dict"`) rather than a dedicated history flag — see [Structured Outputs](/agents/structured-outputs).
```python theme={null}
agent = Agent(output_type="list")
response = agent.run("Hello") # Returns full conversation as a list of messages
```
Name to use for user messages in conversation history.
```python theme={null}
agent = Agent(user_name="John")
```
Automatically manage context window to prevent overflow.
```python theme={null}
agent = Agent(dynamic_context_window=True)
```
### Advanced Features
Randomly adjust temperature between loops for varied outputs.
```python theme={null}
agent = Agent(dynamic_temperature_enabled=True)
```
Add reasoning prompts to guide multi-step thinking.
```python theme={null}
agent = Agent(max_loops=5, reasoning_prompt_on=True)
```
Enable interactive mode for conversational agents.
```python theme={null}
agent = Agent(interactive=True)
```
Display agent dashboard on initialization.
```python theme={null}
agent = Agent(dashboard=True)
```
### State Management
Automatically save agent state after each execution.
```python theme={null}
agent = Agent(autosave=True)
```
Path to save agent state. `save()` writes here when called with no argument.
Earlier releases accepted this argument and then overwrote `self.saved_state_path` during initialization with an auto-generated `{api_key}_state.json` filename, so a custom path had no effect. It is now honoured; omit it to keep the auto-generated name.
Pass a file path, not a directory. The value is used as a filename, so a trailing slash such as `"./agent_states/"` resolves to `./agent_states/.json` — a hidden file. While the argument was ignored this was harmless; now that it is honoured it is not.
```python theme={null}
agent = Agent(
autosave=True,
saved_state_path="./states/my_agent.json"
)
```
Path to load previous agent state from.
```python theme={null}
agent = Agent(load_state_path="./states/my_agent.json")
```
### Reliability
List of fallback models to try if primary model fails.
```python theme={null}
agent = Agent(
fallback_models=[
"claude-sonnet-4-6",
"gpt-5.4",
"gpt-5.4-mini"
]
)
```
### Performance
Agent execution mode. Options: "interactive", "fast", "standard".
```python theme={null}
# Fast mode (no printing, minimal overhead)
agent = Agent(mode="fast")
# Interactive mode
agent = Agent(mode="interactive")
```
Nucleus sampling parameter for model generation. When left as `None`, no `top_p` value is sent in the request and the provider's own default applies.
```python theme={null}
agent = Agent(top_p=0.95)
```
## Example Configurations
### Production Agent
```python theme={null}
production_agent = Agent(
agent_name="Production-Agent",
agent_description="Production-ready agent with reliability features",
model_name="claude-sonnet-4-6",
fallback_models=["claude-sonnet-4-6", "gpt-5.4"],
max_loops=1,
temperature=0.3,
max_tokens=4096,
retry_attempts=5,
autosave=True,
verbose=True,
dynamic_context_window=True,
)
```
### Research Agent
```python theme={null}
research_agent = Agent(
agent_name="Research-Agent",
system_prompt="Expert researcher providing detailed analysis",
model_name="claude-sonnet-4-6",
max_loops=3,
temperature=0.5,
reasoning_prompt_on=True,
verbose=True,
)
```
### Fast Batch Processing Agent
```python theme={null}
batch_agent = Agent(
agent_name="Batch-Processor",
model_name="gpt-5.4",
max_loops=1,
mode="fast", # Disable printing for performance
temperature=0.2,
print_on=False,
verbose=False,
)
```
## Next Steps
Configure conversation history and memory
Add tools to extend capabilities
## Reference
Location in source: `swarms/structs/agent.py:309-411` (the `Agent.__init__` signature)
# Agent Judge
Source: https://docs.swarms.world/agents/agent-judge
Specialized agent for evaluating and judging outputs from other agents, providing structured feedback and quality metrics
The `AgentJudge` evaluates and critiques outputs from other AI agents, providing structured feedback on quality, accuracy, and areas for improvement. It supports single-shot evaluations and iterative refinement through multiple evaluation loops with context building.
Based on the research paper: [Agent-as-a-Judge: Evaluate Agents with Agents](https://arxiv.org/abs/2410.10934)
| Capability | Description |
| ------------------------------ | ----------------------------------------------------------------------- |
| **Quality Assessment** | Evaluates correctness, clarity, and completeness of agent outputs |
| **Structured Feedback** | Provides detailed critiques with strengths, weaknesses, and suggestions |
| **Multimodal Support** | Can evaluate text outputs alongside images |
| **Context Building** | Maintains evaluation context across multiple iterations |
| **Custom Evaluation Criteria** | Supports weighted evaluation criteria for domain-specific assessments |
| **Batch Processing** | Efficiently processes multiple evaluations |
## Architecture
```mermaid theme={null}
graph TD
A[Input Task] --> B[AgentJudge]
B --> C{Evaluation Mode}
C -->|step| D[Single Eval]
C -->|run| E[Iterative Eval]
C -->|run_batched| F[Batch Eval]
D --> G[Agent Core]
E --> G
F --> G
G --> H[LLM Model]
H --> I[Quality Analysis]
I --> J[Feedback & Output]
```
## Parameters
| Parameter | Type | Default | Description |
| --------------------- | ---------------------------- | -------------------------------------- | -------------------------------------------------------------------- |
| `id` | `str` | `generate_id("agent-judge")` | Unique identifier for the judge instance (`-<32 hex chars>`) |
| `agent_name` | `str` | `"Agent Judge"` | Name of the agent judge |
| `description` | `str` | `"You're an expert AI agent judge..."` | Description of the agent's role |
| `system_prompt` | `str` | `None` | Custom system instructions (uses default if None) |
| `model_name` | `str` | `"openai/o1"` | LLM model for evaluation |
| `max_loops` | `int` | `1` | Maximum evaluation iterations |
| `verbose` | `bool` | `False` | Enable verbose logging |
| `evaluation_criteria` | `Optional[Dict[str, float]]` | `None` | Dictionary of evaluation criteria and weights |
| `return_score` | `bool` | `False` | Whether to return a numerical score instead of full conversation |
## Methods
### step()
Processes a single task and returns the agent's evaluation.
```python theme={null}
result = judge.step(task: str = None, img: Optional[str] = None, messages: Optional[List[Dict[str, str]]] = None) -> str
```
### run()
Executes evaluation in multiple iterations with context building.
```python theme={null}
result = judge.run(task: str, img: Optional[str] = None) -> Union[str, int]
```
Returns `str` (full conversation) if `return_score=False`, or `int` (numerical score) if `return_score=True`.
### run\_batched()
Executes batch evaluation of multiple tasks.
```python theme={null}
results = judge.run_batched(tasks: List[str]) -> List[Union[str, int]]
```
## Examples
### Basic Evaluation
```python theme={null}
from swarms import AgentJudge
judge = AgentJudge(
agent_name="quality-judge",
model_name="claude-sonnet-4-6",
max_loops=2
)
agent_output = "The capital of France is Paris. The city is known for its famous Eiffel Tower."
evaluations = judge.run(task=agent_output)
```
### Custom Evaluation Criteria
```python theme={null}
from swarms import AgentJudge
judge = AgentJudge(
agent_name="technical-judge",
model_name="claude-sonnet-4-6",
max_loops=1,
evaluation_criteria={
"accuracy": 0.4,
"completeness": 0.3,
"clarity": 0.2,
"logic": 0.1,
},
)
technical_output = "To solve x^2 + 5x + 6 = 0, we use the quadratic formula..."
evaluations = judge.run(task=technical_output)
```
### Scoring Mode
```python theme={null}
from swarms import AgentJudge
judge = AgentJudge(
agent_name="scoring-judge",
model_name="claude-sonnet-4-6",
max_loops=2,
return_score=True
)
score = judge.run(task="This is a correct and well-explained answer.")
```
### Batch Processing
```python theme={null}
from swarms import AgentJudge
judge = AgentJudge()
tasks = [
"The capital of France is Paris.",
"2 + 2 = 4",
"The Earth is flat."
]
evaluations = judge.run_batched(tasks=tasks)
```
## Reference
```bibtex theme={null}
@misc{zhuge2024agentasajudgeevaluateagentsagents,
title={Agent-as-a-Judge: Evaluate Agents with Agents},
author={Mingchen Zhuge and Changsheng Zhao and Dylan Ashley and Wenyi Wang and Dmitrii Khizbullin and Yunyang Xiong and Zechun Liu and Ernie Chang and Raghuraman Krishnamoorthi and Yuandong Tian and Yangyang Shi and Vikas Chandra and Jürgen Schmidhuber},
year={2024},
eprint={2410.10934},
archivePrefix={arXiv},
primaryClass={cs.AI},
}
```
# Agent Memory
Source: https://docs.swarms.world/agents/agent-memory
Configure persistent agent memory, context compression, archives, and conversation history
Swarms agents can keep disk-backed persistent memory through the `Conversation` class. When `persistent_memory=True`, each agent writes its active interaction log to a `MEMORY.md` file and reloads that file when another process starts an agent with the same `agent_name`. The flag is `False` by default, so agents are ephemeral and keep no on-disk state unless you opt in.
Use this page to understand:
* How `MEMORY.md` is created, loaded, and updated
* How context compression keeps memory within the model context window
* How archived transcripts preserve raw chat history
* How to inspect, compact, export, or disable memory in code
* How to give an agent external knowledge with a retrieval tool
Persistent memory is keyed by `agent_name`. Reusing the same `agent_name` (with `persistent_memory=True`) resumes the same memory across process restarts. Changing the name starts a separate memory folder. Leaving `persistent_memory` at its default of `False` keeps the agent fully ephemeral.
## The `persistent_memory` flag
`persistent_memory` is the top-level switch that controls whether the agent reads from and writes to `MEMORY.md`.
Enables disk-backed persistent memory. When `True`, the agent creates `MEMORY.md` on first run, preloads it on subsequent runs, and writes new turns through to disk. When `False` (the default), the agent runs fully in-process — no `MEMORY.md`, no `archive/`, fresh state every run.
```python theme={null}
from swarms import Agent
# Persistent agent — opt in explicitly.
# On first run it creates MEMORY.md. On subsequent runs it picks up
# where it left off — the model sees the prior conversation as a
# system preamble.
persistent_agent = Agent(
agent_name="ResearchAssistant",
agent_description="Remembers context across sessions",
model_name="gpt-5.4",
max_loops=1,
persistent_memory=True, # state survives restarts
)
# Ephemeral agent (default) — no disk writes, no preload, fresh every run.
ephemeral_agent = Agent(
agent_name="OneShotAgent",
model_name="gpt-5.4",
max_loops=1,
persistent_memory=False,
)
```
## Memory stack
An agent can use several memory layers at the same time:
| Layer | Purpose | Persistence |
| -------------------------------- | ----------------------------------------------------- | ------------------- |
| `conversation_history` | In-memory messages for the current run | Current process |
| `MEMORY.md` | Active user, agent, and tool interaction log | Disk-backed |
| `archive/history_.md` | Raw transcripts saved before compaction | Disk-backed |
| `Conversation.compact()` | Replaces raw active history with a summary | Disk-backed summary |
| `ContextCompressor` | Automatically calls compaction near the context limit | Runtime behavior |
`MEMORY.md` records the agent's own interaction history. To let an agent look things up in external documents or a database, give it a [retrieval tool](#external-knowledge) instead.
## Disk layout
Agent memory lives under the workspace directory:
```text theme={null}
$WORKSPACE_DIR/agents/{agent_name}/
|-- MEMORY.md
`-- archive/
|-- history_2026-04-20_14-30-45.md
|-- history_2026-04-20_16-12-08.md
`-- ...
```
Stable name used to identify the agent's memory folder.
Set this explicitly when using `persistent_memory`. An omitted name
defaults to the same literal string, `"swarm-worker-01"`, for every
agent — so multiple default-named agents don't just lose history on
restart, they all read and write the *same* `MEMORY.md` folder at the
same time, corrupting each other's memory.
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="ResearchAgent",
model_name="claude-sonnet-4-6",
persistent_memory=True,
)
# Memory path (when persistent_memory=True):
# $WORKSPACE_DIR/agents/ResearchAgent/MEMORY.md
```
### Key design points
* The folder is keyed by `agent_name`, not by `id`.
* `MEMORY.md` is append-updated during normal operation.
* Every `conversation.add(role, content)` writes to in-memory history and to disk.
* Compression archives the current `MEMORY.md` before replacing it with a compact summary.
* The agent's static `system_prompt`, `rules`, and constructor configuration are not repeatedly appended to `MEMORY.md`.
## Lifecycle
### 1. File creation
On first construction of an agent with a new `agent_name`, Swarms creates:
```text theme={null}
$WORKSPACE_DIR/agents/{agent_name}/MEMORY.md
```
The file starts with a small header and an interaction log section:
```markdown theme={null}
# Agent Memory
**Conversation:** ResearchAgent_id__conversation
**Created:** 2026-04-20T18:33:12
---
## Interaction Log
```
If the file already exists, Swarms leaves it in place.
### 2. Preload on construction
During `Conversation.__init__`, Swarms reads the existing `MEMORY.md` and injects it into `conversation_history` as a single `System` message.
The resulting prompt order is:
```text theme={null}
[0] System:
[1] User: # if provided
[2] User: # if provided
[3] System: [Persistent Memory — MEMORY.md]
... full MEMORY.md contents ...
```
The preload is added directly to memory, so it is not written back to disk again. When `return_history_as_string()` builds the prompt, the model sees the system prompt, rules, persistent memory, and current task in order.
### 3. Write-through on new messages
Every `conversation.add(role, content)` call:
1. Appends the message to `conversation_history`
2. Appends a timestamped block to `MEMORY.md`
The on-disk format looks like this:
```markdown theme={null}
### User — 2026-04-20T18:35:04
Research cloud database options for low-latency analytics.
---
### ResearchAgent — 2026-04-20T18:35:21
I recommend evaluating BigQuery, ClickHouse Cloud, and AlloyDB...
---
```
Disk writes are serialized with a per-conversation lock. Construction-time messages such as system prompts and rules are suppressed from disk so static identity does not get duplicated on every restart.
## Context compression
Without compression, a long-running agent could eventually exceed the model's context window. Swarms can attach a `ContextCompressor` that summarizes the current transcript and compacts the active memory.
Enables automatic compression when memory approaches the configured context limit.
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="ResearchAgent",
model_name="claude-sonnet-4-6",
max_loops=5,
context_compression=True,
context_length=32000, # optional — overrides the resolved default
)
```
### When compression runs
Compression can run when all of these are true:
* `context_compression=True`
* `context_length` is set to a non-zero value
* The token usage of `short_memory.return_history_as_string()` is greater than or equal to `threshold * context_length`
* The agent is at the top of a loop iteration
The default threshold is `0.9`, so compression starts when the active prompt reaches about 90% of the context window.
`context_length` accepts `None` as its constructor default, but the agent never runs with an actual `None` value: during `__init__`, an unset `context_length` is resolved to a model-derived value (or `16000` as a fallback), so compression always has a real denominator to measure against. Pass `context_length` explicitly only to override that resolved default — for example, to match a larger context window.
Compression works for both `max_loops="auto"` and integer `max_loops` runs. The `context_compression` flag is the gate.
### What compression does
When compression fires:
1. The current transcript is summarized with an LLM call.
2. `Conversation.compact(summary=...)` is called.
3. The current `MEMORY.md` is copied to `archive/history_.md`.
4. The active `MEMORY.md` is deleted and recreated with a fresh header.
5. `conversation_history` is rebuilt with the system prompt, rules, and custom rules.
6. The summary is appended as one `System` message to both memory and `MEMORY.md`.
After compaction, active memory is small again:
```text theme={null}
conversation_history:
[0] System:
[1] User: # if provided
[2] User: # if provided
[3] System: [Compressed Memory Summary] ...
MEMORY.md:
# Agent Memory
...
## Interaction Log
### System —
[Compressed Memory Summary] ...
archive/history_.md:
Full pre-compaction transcript
```
On the next process restart, Swarms loads the compact summary from `MEMORY.md` instead of the raw pre-compaction transcript. The archive keeps the full transcript available without filling the active context window.
## Configure compression
Compression is enabled by default:
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="ResearchAgent",
model_name="claude-sonnet-4-6",
max_loops=5,
context_compression=True,
context_length=32000,
)
```
Disable compression when you want the active `MEMORY.md` to remain un-compacted:
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="StaticAgent",
model_name="claude-sonnet-4-6",
max_loops="auto",
context_compression=False,
)
```
When compression is enabled, the agent attaches a `ContextCompressor(threshold=0.9)`. You can replace it after construction to tune the threshold, summarizer model, temperature, or summary length:
```python theme={null}
from swarms import Agent
from swarms.agents.context_compressor import ContextCompressor
agent = Agent(
agent_name="ResearchAgent",
model_name="claude-sonnet-4-6",
max_loops=5,
context_compression=True,
context_length=32000,
)
agent._context_compressor = ContextCompressor(
threshold=0.75,
summarizer_model="claude-haiku-4-5",
summarizer_temperature=0.1,
summarizer_max_tokens=3000,
)
```
## Access memory in code
The `Conversation` object is available as `agent.short_memory`.
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="ResearchAgent",
model_name="claude-sonnet-4-6",
persistent_memory=True,
)
agent.run("Research low-latency data warehouse options.")
agent.run("Narrow the recommendation to GCP.")
# Path to the active on-disk memory file (None when persistent_memory=False)
print(agent.short_memory.memory_md_path)
# Full prompt-ready history
print(agent.short_memory.return_history_as_string())
# Structured message list
messages = agent.short_memory.to_dict()
print(messages)
# Last response content
print(agent.short_memory.get_final_message_content())
```
### Manual compaction
You can compact memory yourself at any time:
```python theme={null}
agent.short_memory.compact(
summary=(
"Researched cloud data warehouses. "
"The user prefers GCP for latency and operations reasons. "
"Shortlist: BigQuery, AlloyDB, and ClickHouse Cloud."
)
)
```
Manual compaction follows the same archive, wipe, and re-seed flow as automatic compression.
### Export and load conversations
`MEMORY.md` is the active persistent memory file. You can also export or load conversation history in other formats:
```python theme={null}
# Save conversation snapshots
agent.short_memory.export(force=True)
agent.short_memory.save_as_json(force=True)
agent.short_memory.save_as_yaml(force=True)
# Load a prior exported conversation
agent.short_memory.load("conversation_agent-123.json")
```
### Search memory
Use built-in search helpers for quick inspection:
```python theme={null}
results = agent.short_memory.search("GCP")
matches = agent.short_memory.search_keyword_in_conversation("latency")
```
## Disable disk-backed memory
`persistent_memory=False` is the default, and it keeps an agent fully in-process. Nothing is preloaded, nothing is written to `MEMORY.md`, and no `archive/` directory is created:
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="EphemeralAgent",
model_name="gpt-5.4",
persistent_memory=False, # default
)
agent.run("This updates conversation_history but does not write to MEMORY.md.")
```
If you have already constructed a persistent agent and want to stop further disk writes for the rest of the run, you can also clear `memory_md_path`:
```python theme={null}
agent.short_memory.memory_md_path = None
```
This stops future writes but does not retroactively delete `MEMORY.md`. Neither approach disables `conversation_history` — that always tracks the current run in memory.
## External knowledge
`MEMORY.md` holds the agent's own interaction history. When the agent needs to look things up in documents, a database, or any other external store, give it a retrieval **tool**. The agent calls the tool during its loop and the results enter the conversation like any other tool output.
```python theme={null}
from swarms import Agent
KNOWLEDGE = {
"storage": "Grid-scale batteries now cover 4-hour peaks at $95/kWh.",
"solar": "Utility solar LCOE fell to $29/MWh in 2025.",
}
def search_knowledge_base(query: str) -> str:
"""Search the internal knowledge base and return matching passages.
Args:
query: Words to look for in the knowledge base.
Returns:
Matching passages, or a message saying nothing matched.
"""
hits = [
text for key, text in KNOWLEDGE.items() if key in query.lower()
]
return "\n".join(hits) if hits else "No matching documents."
agent = Agent(
agent_name="KnowledgeAgent",
model_name="claude-sonnet-4-6",
tools=[search_knowledge_base],
max_loops=2,
)
response = agent.run(
"Summarize what our renewable energy documents say about storage."
)
```
Swap the dictionary lookup for a real vector store, SQL query, or HTTP call and the shape of the code stays the same. See [Agent Tools](/agents/agent-tools) for the full tool interface.
An arbitrary object attached to the agent and stored on `agent.long_term_memory`.
`agent.run()` never queries this object. The only method Swarms calls on it is `.save(path)`, and only when `autosave` writes agent state to disk. There is no automatic retrieval in the run loop and no built-in vector database ships with Swarms. Use a retrieval tool, as shown above, for anything the agent must actually read during a run.
## Best practices
* Use stable, descriptive `agent_name` values for agents that should remember previous work.
* Keep `context_compression=True` and set `context_length` for autonomous or long-running agents.
* Tune `ContextCompressor.threshold` lower for agents with large tool outputs or long responses.
* Compact manually after major milestones to preserve the important state and reduce prompt size.
* Use a retrieval tool for external knowledge. Do not rely on `MEMORY.md` as a document database.
* Leave `persistent_memory` at its default `False` for privacy-sensitive or one-off agents that should not write a transcript.
## Why it works this way
### Why key memory by `agent_name`?
`id` values can change between process starts. `agent_name` is user-controlled and stable, so it gives the agent a durable identity.
### Why preload memory as one `System` message?
The model needs to understand that the content is prior memory, not a current user request. A single system-level memory preamble is compact and less ambiguous than replaying old turns as active messages.
### Why wipe `MEMORY.md` during compaction?
If compaction only appended a summary, the next run would load both the summary and the raw transcript it summarizes. Wiping the active file keeps the working context small, while `archive/` preserves the raw log.
## Next steps
Configure core agent parameters such as `agent_name`, `max_loops`, and context limits.
Explore the underlying `Conversation` class and its export, load, and search helpers.
# Agent Skills
Source: https://docs.swarms.world/agents/agent-skills
Learn about the markdown-based Agent Skills system for modular agent capabilities
Agent Skills is a lightweight, markdown-based framework introduced by Anthropic for defining modular, reusable agent capabilities. Skills enable you to specialize agents without modifying code by loading skill definitions from simple `SKILL.md` files.
## What are Agent Skills?
Agent Skills are:
* **Markdown-based**: Written in simple Markdown format with YAML frontmatter
* **Modular**: Each skill is a self-contained capability
* **Reusable**: Skills can be shared across agents and projects
* **Context-aware**: Automatically loaded based on task similarity
* **Code-free**: No code changes needed to add new capabilities
## Skills Directory Structure
```
skills/
├── financial-analysis/
│ └── SKILL.md
├── code-review/
│ └── SKILL.md
├── data-visualization/
│ └── SKILL.md
└── technical-writing/
└── SKILL.md
```
## SKILL.md Format
### Basic Structure
Each `SKILL.md` file has two parts:
1. **YAML Frontmatter**: Metadata about the skill
2. **Markdown Content**: Instructions and methodology
```markdown theme={null}
---
name: skill-name
description: Brief description of the skill's purpose and capabilities
---
# Skill Title
Detailed instructions for the skill...
## Methodology
Step-by-step instructions...
## Guidelines
Best practices and rules...
## Examples
Usage examples...
```
### Example: Financial Analysis Skill
```markdown theme={null}
---
name: financial-analysis
description: Perform comprehensive financial analysis including DCF modeling, ratio analysis, and financial statement evaluation for companies and investment opportunities
---
# Financial Analysis Skill
When performing financial analysis, follow these systematic steps to ensure thorough and accurate evaluation:
## Core Methodology
### 1. Data Collection and Verification
- Gather historical financial statements (income statement, balance sheet, cash flow)
- Verify data sources for accuracy and completeness
- Identify any anomalies or missing data points
### 2. Financial Ratio Analysis
Calculate and analyze key financial ratios:
- **Profitability**: EBITDA margin, net profit margin, ROE, ROA
- **Liquidity**: Current ratio, quick ratio, cash ratio
- **Leverage**: Debt-to-equity, interest coverage ratio
- **Efficiency**: Asset turnover, inventory turnover
### 3. Valuation Models
Build appropriate valuation models:
- **DCF Analysis**: Project free cash flows, determine WACC, calculate terminal value
- **Comparable Company Analysis**: Identify peers, analyze multiples (P/E, EV/EBITDA)
- **Precedent Transactions**: Review similar deals for valuation benchmarks
## Guidelines
- Always use conservative assumptions when uncertain
- Cross-validate findings with multiple valuation methods
- Clearly document all assumptions and their rationale
- Present results with appropriate caveats and risk factors
## Key Outputs
Your analysis should produce:
1. Executive summary of findings
2. Detailed financial model with assumptions
3. Valuation range with sensitivity analysis
4. Investment recommendation with risk assessment
```
## Using Agent Skills
### Dynamic Loading (Task-Based, Automatic)
Setting `skills_dir` on an agent enables **dynamic, task-based** skill loading automatically. Every call to `agent.run(task)` loads only the skills whose `description` is similar enough to the current task (cosine similarity over term-frequency vectors, threshold `0.3` by default) and appends them to the system prompt for that run. There is no separate "load everything" mode triggered by `run()` — this dynamic path is what fires whenever `skills_dir` is set.
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="Versatile-Agent",
model_name="claude-sonnet-4-6",
skills_dir="./skills",
max_loops=1,
)
# Only relevant skills are loaded based on the task
response = agent.run(
"Analyze the financial statements and create a visualization of the revenue trends"
)
# Loads: financial-analysis and data-visualization skills
```
### Static Loading (Load All Skills)
To force-load every skill in `skills_dir` regardless of task similarity, call `handle_skills()` directly with no `task` argument (e.g. right after construction, before `run()`):
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="Financial-Analyst",
model_name="claude-sonnet-4-6",
skills_dir="./skills",
max_loops=1,
)
agent.handle_skills() # No task -> loads and appends every skill in skills_dir
response = agent.run("Perform a DCF valuation of Tesla")
```
## Creating Custom Skills
### Step 1: Create Directory
```bash theme={null}
mkdir -p skills/my-skill
```
### Step 2: Write SKILL.md
```markdown theme={null}
---
name: code-review
description: Perform thorough code reviews focusing on security, performance, maintainability, and best practices
---
# Code Review Skill
When reviewing code, follow this systematic approach:
## Review Checklist
### 1. Security
- [ ] No hardcoded credentials or API keys
- [ ] Input validation for all user inputs
- [ ] Proper authentication and authorization
- [ ] SQL injection prevention
- [ ] XSS protection
### 2. Performance
- [ ] Efficient algorithms and data structures
- [ ] No unnecessary database queries
- [ ] Proper caching where appropriate
- [ ] Optimized loops and iterations
### 3. Code Quality
- [ ] Follows language conventions and style guide
- [ ] Clear and descriptive variable names
- [ ] Functions are single-purpose and small
- [ ] Proper error handling
- [ ] Adequate comments for complex logic
### 4. Testing
- [ ] Unit tests for all functions
- [ ] Edge cases covered
- [ ] Integration tests where needed
- [ ] Test coverage > 80%
## Review Format
Provide feedback in this structure:
1. Summary of findings (high-level overview)
2. Critical issues (must fix)
3. Important suggestions (should fix)
4. Minor improvements (nice to have)
5. Positive observations (what's done well)
## Communication Guidelines
- Be constructive and specific
- Provide examples and alternatives
- Explain the "why" behind suggestions
- Acknowledge good code when you see it
```
### Step 3: Use the Skill
```python theme={null}
agent = Agent(
agent_name="Code-Reviewer",
model_name="claude-sonnet-4-6",
skills_dir="./skills",
)
code = """
def login(username, password):
query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
return db.execute(query)
"""
review = agent.run(f"Review this code:\n{code}")
print(review)
```
## Skill Examples
### Data Visualization Skill
````markdown theme={null}
---
name: data-visualization
description: Create effective data visualizations and charts using best practices for data communication
---
# Data Visualization Skill
## Visualization Selection
### Choose the right chart type:
- **Comparison**: Bar charts, grouped bar charts
- **Trend over time**: Line charts, area charts
- **Distribution**: Histograms, box plots
- **Relationship**: Scatter plots, bubble charts
- **Composition**: Pie charts (use sparingly), stacked bar charts
- **Geographic**: Maps, choropleth maps
## Design Principles
1. **Clarity**: Make the message immediately clear
2. **Simplicity**: Remove chart junk and unnecessary elements
3. **Accuracy**: Don't mislead with scale or perspective
4. **Accessibility**: Use colorblind-friendly palettes
## Best Practices
- Start y-axis at zero for bar charts
- Use clear, descriptive labels
- Include data sources
- Provide context with annotations
- Choose appropriate color schemes
- Ensure text is readable
## Code Template
```python
import matplotlib.pyplot as plt
import seaborn as sns
# Set style
sns.set_style("whitegrid")
plt.figure(figsize=(12, 6))
# Create visualization
# ... your code ...
# Add labels and title
plt.xlabel("X Label", fontsize=12)
plt.ylabel("Y Label", fontsize=12)
plt.title("Descriptive Title", fontsize=14)
# Show plot
plt.tight_layout()
plt.show()
````
````
### Technical Writing Skill
```markdown
---
name: technical-writing
description: Write clear, accurate technical documentation including API docs, tutorials, and guides
---
# Technical Writing Skill
## Documentation Structure
### 1. Introduction
- What is it?
- Why should I use it?
- Quick example
### 2. Getting Started
- Prerequisites
- Installation
- Basic setup
- "Hello World" example
### 3. Core Concepts
- Key terminology
- Architecture overview
- Main features
### 4. How-To Guides
- Task-oriented instructions
- Step-by-step procedures
- Real-world examples
### 5. API Reference
- Complete API documentation
- Parameters and return values
- Code examples
## Writing Guidelines
- Use active voice
- Be concise and direct
- Use consistent terminology
- Include code examples
- Explain the "why" not just the "how"
- Test all code samples
- Use headings and structure
- Include diagrams where helpful
## Code Documentation Format
```python
def function_name(param1: type1, param2: type2) -> return_type:
"""
Brief description of what the function does.
More detailed explanation if needed, including:
- When to use this function
- Important considerations
- Edge cases
Args:
param1: Description of param1
param2: Description of param2
Returns:
Description of return value
Raises:
ErrorType: When and why this error occurs
Examples:
>>> function_name("value1", "value2")
"expected output"
"""
pass
````
````
## Skill Loading Internals
### How Skills are Loaded
```python
# skills_dir is only stored during __init__; skills are actually loaded
# and injected into the system prompt inside agent.run(task), once per call
agent = Agent(
skills_dir="./skills", # Path to skills directory
model_name="claude-sonnet-4-6",
)
response = agent.run("Perform a DCF valuation of Tesla")
# On this call: skills metadata is loaded from SKILL.md frontmatter,
# scored against the task by similarity, and relevant skill content
# is appended to the system prompt
````
### Dynamic Skills Loader
```python theme={null}
from swarms.structs.dynamic_skills_loader import DynamicSkillsLoader
# Manual skill loading
loader = DynamicSkillsLoader(skills_dir="./skills")
# Load skills relevant to a task
relevant_skills = loader.load_relevant_skills(
"Perform financial analysis and create visualizations"
)
print(f"Loaded {len(relevant_skills)} relevant skills")
```
## Best Practices
### 1. Keep Skills Focused
```markdown theme={null}
# Good - Single, focused skill
---
name: api-design
description: Design RESTful APIs following best practices
---
# Bad - Too broad
---
name: software-engineering
description: All software engineering best practices
---
```
### 2. Include Examples
Always provide concrete examples in your skills:
```markdown theme={null}
## Example Use Cases
- **Public Company Valuation**: "Analyze Tesla's financials and provide a DCF valuation"
- **Private Investment**: "Evaluate this startup's unit economics and runway"
- **M&A Analysis**: "Assess the financial implications of this acquisition"
```
### 3. Use Clear Instructions
```markdown theme={null}
## Core Methodology
### 1. Data Collection
- Gather historical financial statements
- Verify data sources
- Identify anomalies
### 2. Analysis
- Calculate key ratios
- Build valuation models
- Perform sensitivity analysis
```
### 4. Provide Guidelines
```markdown theme={null}
## Guidelines
- Always use conservative assumptions when uncertain
- Cross-validate findings with multiple methods
- Clearly document all assumptions
- Present results with appropriate caveats
```
## Sharing Skills
Skills can be easily shared across projects and teams:
```bash theme={null}
# Copy skills to another project
cp -r skills/financial-analysis ../other-project/skills/
# Or create a skills library repository
git clone https://github.com/myorg/agent-skills-library.git skills
```
## Next Steps
Get structured responses from agents
Learn how to create agents
## Reference
* Skills handling: `swarms/structs/agent.py` (`handle_skills`, a short delegate) plus `swarms/agents/skills_manager.py` (`SkillsManager._static_prompt`, `SkillsManager._dynamic_prompt`) for the tiered static/dynamic loading logic
* Dynamic skills loader: `swarms/structs/dynamic_skills_loader.py`
* Example skills: `examples/single_agent/agent_skill_examples/`
* Anthropic Agent Skills: [Agent Skills announcement](https://www.anthropic.com/news/agent-skills)
# Agent Tools
Source: https://docs.swarms.world/agents/agent-tools
Add tools and function calling capabilities to agents
Tools extend agent capabilities by allowing them to call external functions, APIs, and services. Swarms supports OpenAI-style function calling with automatic schema generation.
## Basic Tool Usage
### Define a Simple Tool
Tools are Python functions with type hints and docstrings:
```python theme={null}
from swarms import Agent
def get_weather(location: str, units: str = "celsius") -> str:
"""
Get the current weather for a location.
Args:
location: The city and country, e.g., 'San Francisco, CA'
units: Temperature units ('celsius' or 'fahrenheit')
Returns:
Weather information as a string
"""
# Your weather API logic here
return f"Weather in {location}: 72°{units[0].upper()}, sunny"
# Create agent with tool
agent = Agent(
agent_name="Weather-Assistant",
model_name="claude-sonnet-4-6",
max_loops=1,
tools=[get_weather], # Add tools as a list
)
# Agent can now call the tool
response = agent.run("What's the weather in New York?")
print(response)
```
## Tool Requirements
### Type Hints and Docstrings
For reliable tool execution, functions must have:
1. **Type hints** for all parameters and return value
2. **Docstring** describing the function's purpose
3. **Parameter descriptions** in the docstring
```python theme={null}
# Good - Complete type hints and docstring
def search_web(query: str, max_results: int = 10) -> str:
"""
Search the web and return results.
Args:
query: The search query string
max_results: Maximum number of results to return
Returns:
Search results as formatted text
"""
# Implementation
return f"Results for: {query}"
# Bad - Missing type hints
def search_web(query, max_results=10): # ❌ No type hints
return f"Results for: {query}"
# Bad - Missing docstring
def search_web(query: str) -> str: # ❌ No docstring
return f"Results for: {query}"
```
## Multiple Tools
### Add Multiple Tools to an Agent
```python theme={null}
def calculate(expression: str) -> float:
"""
Calculate a mathematical expression.
Args:
expression: A mathematical expression like '2 + 2'
Returns:
The result of the calculation
"""
return eval(expression) # Use a safe evaluator in production
def get_time(timezone: str = "UTC") -> str:
"""
Get the current time in a timezone.
Args:
timezone: The timezone name (e.g., 'UTC', 'America/New_York')
Returns:
Current time as a string
"""
from datetime import datetime
import pytz
tz = pytz.timezone(timezone)
return datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S %Z")
def search_database(query: str) -> str:
"""
Search the internal database.
Args:
query: SQL query to execute
Returns:
Query results
"""
# Database logic here
return "Query results..."
# Agent with multiple tools
agent = Agent(
agent_name="Multi-Tool-Agent",
model_name="claude-sonnet-4-6",
max_loops=2,
tools=[calculate, get_time, search_database],
verbose=True,
)
response = agent.run(
"What time is it in Tokyo and what's 123 * 456?"
)
```
## Real-World Tool Examples
### Web Search Tool
```python theme={null}
import requests
def web_search(query: str, num_results: int = 5) -> str:
"""
Search the web using a search API.
Args:
query: The search query
num_results: Number of results to return (1-10)
Returns:
Formatted search results
"""
# Example using a hypothetical search API
response = requests.get(
"https://api.searchengine.com/search",
params={"q": query, "limit": num_results}
)
results = response.json().get("results", [])
formatted = []
for i, result in enumerate(results, 1):
formatted.append(
f"{i}. {result['title']}\n {result['snippet']}\n {result['url']}"
)
return "\n\n".join(formatted)
agent = Agent(
agent_name="Research-Agent",
model_name="claude-sonnet-4-6",
tools=[web_search],
)
```
### Database Query Tool
```python theme={null}
import sqlite3
from typing import List, Dict, Any
def query_database(sql: str) -> List[Dict[str, Any]]:
"""
Execute a SQL query on the database.
Args:
sql: SQL query to execute (SELECT statements only)
Returns:
Query results as a list of dictionaries
"""
# Validate it's a SELECT query
if not sql.strip().upper().startswith("SELECT"):
return [{"error": "Only SELECT queries are allowed"}]
conn = sqlite3.connect("data.db")
cursor = conn.cursor()
try:
cursor.execute(sql)
columns = [desc[0] for desc in cursor.description]
results = [
dict(zip(columns, row))
for row in cursor.fetchall()
]
return results
except Exception as e:
return [{"error": str(e)}]
finally:
conn.close()
agent = Agent(
agent_name="Data-Analyst",
model_name="claude-sonnet-4-6",
tools=[query_database],
)
```
### File Operations Tool
```python theme={null}
import os
from pathlib import Path
def read_file(filepath: str) -> str:
"""
Read the contents of a file.
Args:
filepath: Path to the file to read
Returns:
File contents as a string
"""
try:
with open(filepath, "r") as f:
return f.read()
except Exception as e:
return f"Error reading file: {e}"
def write_file(filepath: str, content: str) -> str:
"""
Write content to a file.
Args:
filepath: Path to the file to write
content: Content to write to the file
Returns:
Success or error message
"""
try:
Path(filepath).parent.mkdir(parents=True, exist_ok=True)
with open(filepath, "w") as f:
f.write(content)
return f"Successfully wrote to {filepath}"
except Exception as e:
return f"Error writing file: {e}"
def list_directory(path: str = ".") -> str:
"""
List files and directories in a path.
Args:
path: Directory path to list (default: current directory)
Returns:
List of files and directories
"""
try:
items = os.listdir(path)
return "\n".join(items)
except Exception as e:
return f"Error listing directory: {e}"
agent = Agent(
agent_name="File-Manager",
model_name="claude-sonnet-4-6",
tools=[read_file, write_file, list_directory],
max_loops=3,
)
```
## Tool Configuration
### Tool Schema Control
List of tool functions to make available to the agent.
```python theme={null}
agent = Agent(
tools=[tool1, tool2, tool3],
model_name="claude-sonnet-4-6"
)
```
`tool_choice` is **not** an `Agent` constructor parameter. Whenever `tools` (or MCP tools) are configured, the agent always sends `tool_choice="auto"` to the underlying LLM call — passing `tool_choice=...` to `Agent(...)` is silently absorbed into `**kwargs` and has no effect.
Defer tool schemas behind a searchable `tool_search` tool instead of sending every schema on every request. On by default whenever the agent has `tools`, an MCP connection, or `max_loops="auto"`.
```python theme={null}
agent = Agent(
tools=[tool1, tool2, tool3],
dynamic_tools=False, # send every schema on every request
)
```
See [Dynamic Tool Loading](/agents/dynamic-tools) for how deferral, search ranking, and turn budgeting work.
With deferral active, a tool costs one extra round trip: the model must call `tool_search` before it can call the tool. With `max_loops=1` it can search but never call what it found — raise `max_loops` or set `dynamic_tools=False`.
Display tool execution results.
```python theme={null}
agent = Agent(
tools=[my_tool],
show_tool_execution_output=True
)
```
Number of retry attempts for failed tool executions.
```python theme={null}
agent = Agent(
tools=[my_tool],
tool_retry_attempts=5
)
```
## Advanced Tool Patterns
### Tool with State
```python theme={null}
class DatabaseTool:
def __init__(self, db_path: str):
self.db_path = db_path
self.connection = None
def connect(self) -> str:
"""
Connect to the database.
Returns:
Connection status message
"""
import sqlite3
self.connection = sqlite3.connect(self.db_path)
return "Connected to database"
def query(self, sql: str) -> str:
"""
Execute a SQL query.
Args:
sql: SQL query to execute
Returns:
Query results
"""
if not self.connection:
return "Not connected to database"
cursor = self.connection.cursor()
cursor.execute(sql)
results = cursor.fetchall()
return str(results)
# Create instance and use methods as tools
db_tool = DatabaseTool("data.db")
agent = Agent(
agent_name="DB-Agent",
model_name="claude-sonnet-4-6",
tools=[db_tool.connect, db_tool.query],
)
```
### Async Tools
```python theme={null}
import asyncio
import aiohttp
async def fetch_url_async(url: str) -> str:
"""
Fetch content from a URL asynchronously.
Args:
url: The URL to fetch
Returns:
Response content
"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
# Wrap async function for synchronous agent
def fetch_url(url: str) -> str:
"""
Fetch content from a URL.
Args:
url: The URL to fetch
Returns:
Response content
"""
return asyncio.run(fetch_url_async(url))
agent = Agent(
model_name="claude-sonnet-4-6",
tools=[fetch_url],
)
```
## BaseTool API
Swarms uses the `BaseTool` class internally to manage tools:
```python theme={null}
from swarms.tools.base_tool import BaseTool
# Tools are automatically converted to OpenAI function schemas
tool_manager = BaseTool(
tools=[my_function],
verbose=True,
)
# Get function schema
schema = tool_manager.convert_tool_into_openai_schema()
print(schema)
# Execute a tool
result = tool_manager.execute_tool(
response='{"name": "my_function", "parameters": {...}}'
)
```
## MCP Tools
Model Context Protocol (MCP) enables connecting to external tool servers:
```python theme={null}
from swarms.schemas.mcp_schemas import MCPConnection
from swarms import Agent
# Connect to MCP server over HTTP (MCPConnection is URL/transport based,
# not a local command+args launcher)
mcp_config = MCPConnection(
url="http://localhost:8000/mcp",
transport="streamable_http",
)
agent = Agent(
agent_name="MCP-Agent",
model_name="claude-sonnet-4-6",
mcp_config=mcp_config, # Tools auto-loaded from MCP server
)
# Agent can now use all tools from the MCP server
response = agent.run("What's the weather in Paris?")
```
Simpler alternative for a single server — pass the URL directly with `mcp_url`:
```python theme={null}
agent = Agent(
agent_name="MCP-Agent",
model_name="claude-sonnet-4-6",
mcp_url="http://localhost:8000/mcp",
)
```
## Best Practices
### 1. Always Include Type Hints
```python theme={null}
# Good
def search(query: str, limit: int = 10) -> list[dict]:
"""Search with proper types"""
pass
# Bad
def search(query, limit=10): # ❌ No type hints
pass
```
### 2. Write Descriptive Docstrings
```python theme={null}
# Good
def analyze_data(data: str, method: str = "statistical") -> dict:
"""
Analyze data using specified method.
Args:
data: JSON string containing data to analyze
method: Analysis method ('statistical', 'ml', 'deep_learning')
Returns:
Dictionary with analysis results including metrics and insights
"""
pass
# Bad
def analyze_data(data: str) -> dict:
"""Analyze data""" # ❌ Not descriptive enough
pass
```
### 3. Handle Errors Gracefully
```python theme={null}
def api_call(endpoint: str) -> str:
"""
Make an API call.
Args:
endpoint: API endpoint to call
Returns:
API response or error message
"""
try:
response = requests.get(f"https://api.example.com/{endpoint}")
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
return f"API call failed: {str(e)}"
```
### 4. Use Specific Parameter Names
```python theme={null}
# Good - Clear parameter names
def send_email(to_address: str, subject: str, body: str) -> str:
"""Send an email"""
pass
# Bad - Vague parameter names
def send_email(to: str, s: str, b: str) -> str: # ❌ Unclear
pass
```
### 5. Return Structured Data When Possible
```python theme={null}
from typing import Dict, Any
import json
def get_user_info(user_id: str) -> str:
"""
Get user information.
Args:
user_id: The user's ID
Returns:
JSON string with user information
"""
user_data = {
"id": user_id,
"name": "John Doe",
"email": "john@example.com"
}
return json.dumps(user_data, indent=2)
```
## Next Steps
Defer tool schemas behind a searchable catalog
Learn about the Agent Skills system
Get structured responses from agents
## Reference
* Tool handling: `swarms/structs/agent.py:887-974` (`tool_handling`)
* BaseTool class: `swarms/tools/base_tool.py:69`
* Function schema generation: `swarms/tools/py_func_to_openai_func_str.py`
# Creating Agents
Source: https://docs.swarms.world/agents/creating-agents
Learn how to create and initialize agents in the Swarms framework
Agents are the fundamental building blocks of the Swarms framework. An agent is an autonomous entity powered by an LLM with tools, memory, and the ability to execute complex tasks.
## Basic Agent Creation
The simplest way to create an agent is to instantiate the `Agent` class with minimal configuration:
```python theme={null}
from swarms import Agent
# Create a basic agent
agent = Agent(
agent_name="my-agent",
model_name="gpt-5.4",
max_loops=1,
)
# Run the agent
response = agent.run("What are the key benefits of using a multi-agent system?")
print(response)
```
## Agent Initialization Patterns
### Pattern 1: Simple Agent
For quick prototyping and simple tasks:
```python theme={null}
from swarms import Agent
agent = Agent(
model_name="gpt-5.4",
max_loops=1,
)
response = agent.run("Generate a report on the financials.")
print(response)
```
### Pattern 2: Named Agent with Description
For better organization and clarity:
```python theme={null}
agent = Agent(
agent_name="Financial-Analyst",
agent_description="An expert financial analyst specializing in market analysis and reporting",
model_name="claude-sonnet-4-6",
max_loops=1,
verbose=True,
)
```
### Pattern 3: Agent with System Prompt
For specialized behavior and domain expertise:
```python theme={null}
SYSTEM_PROMPT = """
You are a senior financial analyst with expertise in:
- Financial statement analysis
- Market research and competitor analysis
- Investment recommendations
- Risk assessment
Provide detailed, data-driven insights with proper citations.
"""
agent = Agent(
agent_name="Financial-Expert",
system_prompt=SYSTEM_PROMPT,
model_name="claude-sonnet-4-6",
max_loops=1,
)
```
### Pattern 4: Interactive Agent
For conversational interfaces:
```python theme={null}
agent = Agent(
agent_name="Assistant",
model_name="gpt-5.4",
max_loops=5,
interactive=True, # Enable interactive mode
user_name="User",
custom_exit_command="exit",
)
# Agent will prompt for user input in a loop
agent.run("Hello! How can I help you today?")
```
### Pattern 5: Autonomous Agent
For complex, multi-step reasoning:
```python theme={null}
agent = Agent(
agent_name="Research-Agent",
model_name="claude-sonnet-4-6",
max_loops="auto", # Autonomous loop mode
reasoning_prompt_on=True,
dynamic_temperature_enabled=True,
verbose=True,
)
response = agent.run(
"Research the latest trends in AI and create a comprehensive report"
)
```
### Pattern 6: Agent with Fallback Models
For reliability and cost optimization:
```python theme={null}
agent = Agent(
agent_name="Reliable-Agent",
fallback_models=[
"claude-sonnet-4-6", # Primary model
"gpt-5.4", # First fallback
"gpt-5.4-mini" # Final fallback
],
max_loops=1,
)
# Agent will automatically try fallback models if primary fails
response = agent.run("Generate a report")
```
### Pattern 7: Agent from Marketplace Prompt
Load prompts from the Swarms Marketplace:
```python theme={null}
import os
# Set your Swarms API key
os.environ["SWARMS_API_KEY"] = "your-api-key"
agent = Agent(
model_name="claude-sonnet-4-6",
marketplace_prompt_id="550e8400-e29b-41d4-a716-446655440000", # UUID from marketplace
max_loops=1,
)
# System prompt is automatically loaded from the marketplace
response = agent.run("Execute the marketplace prompt task")
```
## Best Practices
### 1. Always Name Your Agents
```python theme={null}
# Good
agent = Agent(
agent_name="Financial-Analyst",
agent_description="Expert in financial analysis",
model_name="claude-sonnet-4-6",
)
# Avoid
agent = Agent(model_name="claude-sonnet-4-6") # Uses default name
```
### 2. Use Descriptive System Prompts
```python theme={null}
# Good - Specific and detailed
system_prompt = """
You are a healthcare data analyst specializing in:
1. Patient data analysis
2. Medical coding (ICD-10, CPT)
3. HIPAA compliance
4. Clinical research metrics
Always maintain patient privacy and follow HIPAA guidelines.
"""
# Avoid - Too vague
system_prompt = "You are a helpful assistant."
```
### 3. Set Appropriate Max Loops
```python theme={null}
# For simple tasks
agent = Agent(max_loops=1) # Single response
# For multi-step reasoning
agent = Agent(max_loops=5) # Fixed iterations
# For autonomous tasks
agent = Agent(max_loops="auto") # Dynamic execution
```
### 4. Enable Verbose Mode During Development
```python theme={null}
agent = Agent(
model_name="gpt-5.4",
verbose=True, # See detailed logs
print_on=True, # Print agent responses
)
```
### 5. Use Autosave for Important Work
```python theme={null}
agent = Agent(
agent_name="Research-Agent",
model_name="claude-sonnet-4-6",
autosave=True, # Automatically save state
saved_state_path="./agent_states/research_agent.json",
)
```
### 6. Set Environment Variables
```python theme={null}
import os
# Set API keys
os.environ["OPENAI_API_KEY"] = "your-api-key"
os.environ["WORKSPACE_DIR"] = "agent_workspace"
# Create agent
agent = Agent(
model_name="claude-sonnet-4-6",
max_loops=1,
)
```
## Common Patterns
### Research Agent
```python theme={null}
research_agent = Agent(
agent_name="Researcher",
system_prompt="You are an expert researcher. Provide detailed, cited information.",
model_name="claude-sonnet-4-6",
max_loops=3,
temperature=0.5,
verbose=True,
)
```
### Writing Agent
```python theme={null}
writer_agent = Agent(
agent_name="Writer",
system_prompt="You are a professional writer. Create engaging, well-structured content.",
model_name="claude-sonnet-4-6",
max_loops=1,
temperature=0.7,
)
```
### Code Generation Agent
```python theme={null}
code_agent = Agent(
agent_name="Code-Generator",
system_prompt="You are an expert software engineer. Write clean, documented code.",
model_name="claude-sonnet-4-6",
max_loops=2,
temperature=0.3, # Lower temperature for more deterministic output
)
```
## Next Steps
Learn about all configuration parameters
Configure memory and conversation history
Add tools to extend agent capabilities
Get structured responses from agents
## Reference
For the complete API reference, see the [Agent class documentation](/api/agent).
Location in source: `swarms/structs/agent.py:140` (`class Agent`); the constructor (`__init__`) starts at line 309.
# Dynamic Tool Loading
Source: https://docs.swarms.world/agents/dynamic-tools
Defer tool schemas behind a searchable catalog so the model only pays for the tools it actually needs
Tool definitions are part of the prompt. They are re-sent on every request and they sit inside the cached prefix, so a large tool set is paid for continuously. Dynamic tool loading keeps your tools registered and executable but **absent from the schema list sent to the model**, exposing a single `tool_search` tool that loads them on demand.
The 16 built-in autonomous-loop tools alone are roughly 2,600 tokens per request, and a single MCP server can add 40 more tools on top. Selection accuracy also falls as the list grows — a model choosing among 80 tools chooses worse than one choosing among 8.
## How It Works
Tools are *deferred*: registered, searchable, and executable, but not advertised. Only `tool_search` is always present alongside your control tools. The model searches the catalog by keyword, the matching schemas are loaded, and they become callable on the **next** turn.
```mermaid theme={null}
sequenceDiagram
participant M as Model
participant A as Agent
participant L as DynamicToolLoader
Note over A,L: Catalog holds every tool; only tool_search is exposed
M->>A: Turn 1 - tool_search("weather currency")
A->>L: run_search(query)
L-->>A: matches loaded, summaries returned
A->>A: tools_list_dictionary = loader.schemas()
A->>A: llm = llm_handling() (rebuild so new schemas ship)
M->>A: Turn 2 - get_weather("Paris")
A-->>M: tool result
M->>A: Turn 3 - final answer
```
A deferred tool costs one extra round trip. With `max_loops=1` the model can search but never call what it found. Use `max_loops=2` or higher for a single tool call, or `max_loops="auto"`.
## Enabling It
`dynamic_tools` is a constructor parameter on `Agent` and is **`True` by default**.
```python theme={null}
from swarms import Agent
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
...
def convert_currency(amount: float, source: str, target: str) -> str:
"""Convert an amount between two currencies."""
...
agent = Agent(
agent_name="TravelAgent",
model_name="gpt-5.4",
max_loops="auto",
tools=[get_weather, convert_currency],
dynamic_tools=True,
)
result = agent.run("What should I pack for Paris next week, and what is 500 USD in euros?")
```
Defer tool schemas behind `tool_search` instead of sending them all on every request. Set to `False` to restore classic eager registration, where every tool schema ships with every call.
### When Deferral Actually Activates
Setting `dynamic_tools=True` on its own does nothing. Deferral needs something to defer, so it activates only when at least one of these is true:
| Condition | Meaning |
| --------------------- | ------------------------------------------------- |
| `tools` is set | You passed local Python callables |
| `mcp_enabled` | You passed `mcp_url`, `mcp_urls`, or `mcp_config` |
| `max_loops == "auto"` | The autonomous loop's built-in tools are deferred |
If none apply, `agent.tool_loader` stays `None` and no catalog is built.
```python theme={null}
# Deferral is inactive here - nothing to defer.
agent = Agent(agent_name="Chat", model_name="gpt-5.4", dynamic_tools=True)
assert agent.tool_loader is None
```
When deferral activates, a system-prompt notice headed `## MOST TOOLS ARE NOT LOADED` is appended once at construction. It tells the model that its visible tool list describes what exists, not what it can call right now, and that it must search before concluding a task is impossible.
## Inspecting the Catalog
`agent.tool_loader` is a `DynamicToolLoader`. It reports what is deferred and what has been loaded so far.
```python theme={null}
loader = agent.tool_loader
len(loader) # number of catalog entries (tool_search not counted)
loader.deferred_names # ['convert_currency', 'get_weather']
loader.loaded_names # [] until a search loads something
loader.catalog_listing() # 'convert_currency: Convert an amount ...\nget_weather: ...'
"get_weather" in loader # True
```
After a search, the loaded tools move across:
```python theme={null}
print(loader.run_search("weather"))
# get_weather: Get the current weather for a city.
#
# Loaded 1: get_weather. They are callable from your next turn.
loader.loaded_names # ['get_weather']
loader.deferred_names # ['convert_currency']
```
## Searching the Catalog
The model calls `tool_search` with a query. Matching is deliberately simple, dependency-free, and deterministic, so it can be tested.
The query is lowercased and split into tokens, with underscores treated as spaces so `get_weather` matches both `get` and `weather`. Each catalog entry scores **3 points for a name match** and **1 point for a description or parameter-name match**, summed over the query's terms. Entries scoring zero are dropped, and results are sorted by score then name.
```python theme={null}
loader.search("weather") # name match, ranks first
loader.search("recipient subject") # matches send_email by parameter names
```
Prefix the query with `select:` to load tools by exact name, bypassing ranking, `limit`, and `min_score_ratio` entirely.
```python theme={null}
loader.run_search("select:get_weather,convert_currency")
```
Unknown names are silently ignored. If *none* of the names match, the loader falls back to a keyword search over the guessed names rather than returning nothing.
Common words (`a`, `the`, `and`, `of`, `to`, `can`, `please`, …) and single characters are dropped before matching. Without this, a query like `"weather in a city"` would match every tool whose description contains `"a"` and load the entire catalog, defeating the point.
```python theme={null}
loader.search("weather in a city") # -> [get_weather]
loader.search("please can you help with") # -> []
```
A search that matches nothing returns the available tool names rather than an empty string, so the model can retry with `select:`. The listing is capped at 30 names with a `(+N more)` suffix so a large catalog cannot flood the conversation.
```
No tools matched 'xyz'. Available tools: convert_currency, get_weather.
Retry with different keywords, or load by exact name with 'select:name1,name2'.
```
## Dynamic Tools in the Autonomous Loop
With `max_loops="auto"`, the loop's own tools are deferred too — but the control tools that let the agent make progress are never deferred, since an agent that has to search for its own `complete_task` cannot finish.
**Always loaded:** `create_plan`, `think`, `subtask_done`, `complete_task`, `respond_to_user`.
**Deferred into the catalog:** `create_file`, `update_file`, `read_file`, `list_directory`, `delete_file`, `run_bash`, `grep`, `create_sub_agent`, `assign_task`, `check_sub_agent_status`, `cancel_sub_agent_tasks`, plus every tool you passed in `tools`.
### Plan-Based Pre-Warming
Searching one subtask at a time wastes turns. When the agent calls `create_plan`, the loop takes the task description plus every step description as a single query and pre-loads the tools that plan implies — at no extra turn cost, since it runs inside the `create_plan` handler that just succeeded.
| Constant | Value | Purpose |
| ------------------------- | ----- | ----------------------------------------------------------- |
| `PREWARM_TOOL_LIMIT` | `8` | Maximum tools one plan may pre-load |
| `PREWARM_MIN_SCORE_RATIO` | `0.6` | Matches must score at least this fraction of the best match |
The `create_plan` result then tells the model what it already has:
```
Pre-loaded the tools this plan implies: read_file, grep.
They are callable from your next turn - do not search for them again.
```
The score ratio matters here: a long plan description contains enough common words to give weak matches a nonzero score, so speculative pre-warming filters harder than an explicit search does.
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="Researcher",
model_name="gpt-5.4",
max_loops="auto",
dynamic_tools=True,
)
agent.run("Summarize every Python file in this directory into notes.md")
```
`selected_tools` filters the loop's tool list **before** deferral, so a tool you exclude is not merely hidden — it never enters the catalog and cannot be found by `tool_search` at all.
## MCP Servers
MCP tools are the strongest case for deferral: a single server can contribute dozens of schemas that would otherwise ship on every request. With `dynamic_tools=True` they join the catalog instead.
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="RepoResearcher",
model_name="gpt-5.4",
max_loops="auto",
mcp_url="https://mcp.deepwiki.com/mcp",
mcp_timeout=120,
dynamic_tools=True,
)
result = agent.run("What is the architecture of the kyegomez/swarms repository?")
```
MCP deferral is **lazy** — the server is contacted while the LLM is being built, not at construction. To inspect the catalog before running, build the LLM yourself:
```python theme={null}
agent.llm = agent.llm_handling()
print(agent.tool_loader.deferred_names)
```
The fetch happens once per agent and is cached, so rebuilding the LLM does not re-contact the server. If the server is unreachable, the agent still builds: the failure is logged, zero tools are deferred, and `tool_search` simply has nothing to find.
MCP entries are registered as schemas with no local callable, so they never appear in `loader.handlers()`. They are dispatched through the MCP manager instead. This is by design — do not treat an empty `handlers()` as a sign that MCP tools failed to load.
## Prompt Caching
Every load changes the tool array, which invalidates the provider's cached prompt prefix. Two mitigations are built in:
1. `schemas()` returns tools in a stable order — `always_loaded` first, then `tool_search`, then loaded tools sorted by name — so two runs that load the same tools produce an identical prefix.
2. The `tool_search` description explicitly instructs the model to load everything it expects to need in a **single** call rather than one tool at a time.
If you use `prompt_caching=True`, prefer `select:` with a full list of names, or lean on plan-based pre-warming, so the tool array settles early and stays put for the rest of the run.
## Turning It Off
Set `dynamic_tools=False` for classic eager registration — every schema ships with every request, and `agent.tool_loader` is `None`.
```python theme={null}
agent = Agent(
agent_name="StockAnalyst",
model_name="gpt-5.4",
tools=[get_stock_price],
dynamic_tools=False,
max_loops=1,
)
```
Prefer eager registration when:
| Situation | Why |
| ------------------------------------- | ------------------------------------------------------- |
| Two or three tools total | The catalog saves less than the extra turn costs |
| `max_loops=1` | There is no second turn in which to call what was found |
| Latency matters more than tokens | Deferral trades a round trip for prompt size |
| The tool must be callable on turn one | Nothing deferred is available before a search |
## Gotchas
`tool_struct` is built from `self.tools` before deferral, so a model that guesses a correct tool name can still execute it. Only the *schema* is withheld. Dynamic tool loading is a token-and-accuracy optimization, not an access control mechanism.
A tool of your own named `tool_search` is dropped from the catalog with a warning, and becomes permanently uncallable — both it and the search tool would appear in the list and the model could not tell them apart. Rename yours.
```
Ignoring a tool named 'tool_search': that name is reserved for the dynamic
tool search tool. Rename it to make it reachable.
```
Once deferral is active, `tools_list_dictionary` becomes an *output* of the loader — it is overwritten every time a search loads something. Schemas you append to it after construction are clobbered. Register them with `agent.defer_tool_schemas([...])` instead.
Calling `setup_dynamic_tools()` discards the existing loader, including which tools were already marked loaded. Autonomous agents call it twice by design. MCP schemas survive via an internal cache; anything you registered manually must be re-added with `defer_tool_schemas()`.
The `handoff_task` tool registered by the `handoffs` parameter is preserved across setup and stays always-loaded, so delegation works on turn one without a search.
## Next Steps
Runnable end-to-end examples for local tools, MCP, and the autonomous loop
Full class reference for the loader, its search algorithm, and its methods
How tools are defined, converted to schemas, and executed
Connect MCP servers and defer their tool catalogs
## Reference
* Loader: `swarms/tools/dynamic_tool_loader.py`
* Agent parameter and activation: `swarms/structs/agent.py` (`dynamic_tools`, `setup_dynamic_tools`, `defer_tool_schemas`, `defer_mcp_tools`)
* Autonomous-loop control tools and pre-warming: `swarms/agents/autonomous_loop.py`
# GKP Agent (Generated Knowledge Prompting)
Source: https://docs.swarms.world/agents/gkp-agent
Knowledge-driven reasoning system that generates relevant information before answering queries through multi-perspective analysis
The GKP Agent enhances its reasoning by generating relevant knowledge before answering queries. This approach, inspired by [Liu et al. 2022](https://arxiv.org/abs/2110.08387), is particularly effective for tasks requiring commonsense reasoning and factual information.
The agent consists of three main components:
1. **Knowledge Generator** — Creates relevant factual information
2. **Reasoner** — Uses generated knowledge to form answers
3. **Coordinator** — Synthesizes multiple reasoning paths into a final answer
## Architecture
```mermaid theme={null}
graph TD
A[Input Query] --> B[Knowledge Generator]
B --> C[Generate Knowledge Items]
C --> D[Reasoner]
D --> E[Multiple Reasoning Paths]
E --> F[Coordinator]
F --> G[Final Answer]
subgraph "Knowledge Generation"
B
C
end
subgraph "Reasoning"
D
E
end
subgraph "Coordination"
F
G
end
```
## API Reference
### GKPAgent
| Parameter | Type | Default | Description |
| --------------------- | ----- | ------------- | -------------------------------------------------- |
| `agent_name` | `str` | `"gkp-agent"` | Name identifier for the agent |
| `model_name` | `str` | `"openai/o1"` | LLM model to use for all components |
| `num_knowledge_items` | `int` | `6` | Number of knowledge snippets to generate per query |
| Method | Parameters | Returns |
| ---------------- | ------------ | ------------------------------------------ |
| `process(query)` | `query: str` | `Dict[str, Any]` — full processing results |
| `run(task)` | `task: str` | `str` — the final answer to a single task |
| `__call__(task)` | `task: str` | `str` — alias for `run(task)` |
`run()` only accepts a single task string (it internally calls the private `_run([task])[0]`). There is no public batch-processing method that accepts a list of tasks; process each task with a separate `run()` call if you need to handle multiple queries.
### KnowledgeGenerator
| Parameter | Type | Default | Description |
| --------------------- | ----- | -------------------------------------------------------------------------- | ----------------------------------------------- |
| `agent_name` | `str` | `"knowledge-generator"` | Name identifier |
| `description` | `str` | `"Generates factual, relevant knowledge to assist with answering queries"` | Description of the agent's role |
| `model_name` | `str` | `"openai/o1"` | Model for knowledge generation |
| `num_knowledge_items` | `int` | `2` | Number of knowledge items to generate per query |
| Method | Parameters | Returns |
| --------------------------- | ------------ | -------------------------------------------- |
| `generate_knowledge(query)` | `query: str` | `List[str]` — generated knowledge statements |
### Reasoner
| Parameter | Type | Default | Description |
| ------------ | ----- | ---------------------- | ------------------- |
| `agent_name` | `str` | `"knowledge-reasoner"` | Name identifier |
| `model_name` | `str` | `"openai/o1"` | Model for reasoning |
| Method | Parameters | Returns |
| ------------------------------------- | ------------------------------ | -------------------------------------------------- |
| `reason_and_answer(query, knowledge)` | `query: str`, `knowledge: str` | `Dict[str, str]` — explanation, confidence, answer |
## Example
```python theme={null}
from swarms import GKPAgent
agent = GKPAgent(
agent_name="gkp-agent",
model_name="claude-sonnet-4-6",
num_knowledge_items=6,
)
query = "What are the implications of quantum entanglement on information theory?"
result = agent.run(query)
print(f"Query: {query}")
print(f"Answer: {result}")
```
## Best Practices
1. **Knowledge Generation**: Set appropriate number of knowledge items based on query complexity
2. **Reasoning Process**: Ensure diverse reasoning paths for complex queries. Validate confidence levels.
3. **Coordination**: Review coordination logic for complex scenarios. Validate final answers against source knowledge.
## Performance Considerations
* Processing time increases with number of knowledge items
* Complex queries may require more knowledge items
* Consider caching frequently used knowledge
* Monitor token usage for cost optimization
# IRE Agent (Iterative Reflective Expansion)
Source: https://docs.swarms.world/agents/iterative-agent
Iterative hypothesis generation, simulation, and refinement through continuous cycles of testing and meta-cognitive reflection
The Iterative Reflective Expansion (IRE) Algorithm is a sophisticated reasoning framework that employs iterative hypothesis generation, simulation, and refinement to solve complex problems. It leverages a multi-step approach where an AI agent generates initial solution paths, evaluates their effectiveness through simulation, reflects on errors, and dynamically revises reasoning strategies.
## Architecture
```mermaid theme={null}
graph TD
Problem_Input["Problem Input"] --> Generate_Hypotheses
Generate_Hypotheses["Generate Initial Hypotheses"] --> Simulate
subgraph Iterative Reflective Expansion Loop
Simulate["Simulate Reasoning Paths"] --> Evaluate
Evaluate["Evaluate Outcomes"] --> Reflect{Is solution satisfactory?}
Reflect -->|No, issues found| Meta_Reflect
Reflect -->|Yes| Promising
Meta_Reflect["Meta-Cognitive Reflection"] --> Revise_Paths
Revise_Paths["Revise Paths Based on Feedback"] --> Expand_Paths
Expand_Paths["Iterative Expansion & Pruning"] --> Simulate
end
Promising["Promising Paths Selected"] --> Memory
Memory["Memory Integration"] --> Synthesize
Synthesize["Synthesize Final Solution"] --> Final["Final Solution"]
```
## Workflow
1. Generate initial hypotheses
2. Simulate paths
3. Reflect on errors
4. Revise paths
5. Select promising paths
6. Synthesize solution
## Class: `IterativeReflectiveExpansion`
### Parameters
| Parameter | Type | Default | Description |
| --------------- | ------------ | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `agent_name` | `str` | `"General-Reasoning-Agent"` | Name of the internal reasoning agent |
| `description` | `str` | `"A reasoning agent that can answer questions and help with tasks."` | Description of the agent's purpose |
| `agent` | `Agent` | `None` | Reserved for a Swarms agent instance; the constructor always builds and assigns its own internal `Agent` regardless of this value |
| `max_loops` | `int` | `5` | Maximum number of loops for the reasoning process |
| `system_prompt` | `str` | `GENERAL_REASONING_AGENT_SYS_PROMPT` | The system prompt for the internal agent |
| `model_name` | `str` | `"gpt-5.4"` | The underlying language model used by the internal agent |
| `output_type` | `OutputType` | `"dict"` | Format of the value returned by `run()` |
### Methods
| Method | Description |
| ----------------------------- | --------------------------------------------------------------------------- |
| `generate_initial_hypotheses` | Generates an initial set of reasoning hypotheses based on the problem input |
| `simulate_path` | Simulates a given reasoning path and evaluates its effectiveness |
| `meta_reflect` | Performs meta-cognitive reflection on the provided error information |
| `revise_path` | Revises the reasoning path based on the provided feedback |
| `select_promising_paths` | Selects the most promising reasoning paths from a list of candidates |
| `synthesize_solution` | Synthesizes a final solution from the promising paths and historical memory |
| `run` | Executes the Iterative Reflective Expansion process on the provided problem |
## Example
```python theme={null}
from swarms import IterativeReflectiveExpansion
agent = IterativeReflectiveExpansion(
max_loops=3,
)
agent.run("What is the 40th prime number?")
```
# Prompt Caching
Source: https://docs.swarms.world/agents/prompt-caching
Cache the stable prefix of every request — system prompt, tools, and history — to cut cost and latency across providers.
Prompt caching lets a provider store the **stable prefix** of your request — the tool definitions, system prompt, and earlier conversation turns — and re-bill it at a large discount (typically \~90% cheaper on reads) instead of re-processing it on every call. Because the prefix is served from cache, you also get lower time-to-first-token. In Swarms you turn it on with a single flag, `prompt_caching=True`, and tune it with an optional `cache_config` dictionary.
Caching is a **prefix match**. Everything up to a cache breakpoint must be byte-for-byte identical between requests for a cache hit. Keep volatile content (timestamps, per-request IDs, changing tool sets) out of the cached prefix.
## Quick start
The minimal setup: flip `prompt_caching=True` on an Anthropic model. Swarms automatically inserts ephemeral `cache_control` breakpoints on the tool block, the system prompt, and the last message.
```python theme={null}
from swarms import Agent
# A large, stable system prompt so the prefix clears the provider token minimum.
SYSTEM_PROMPT = (
"You are a senior financial analyst. You produce rigorous, well-sourced "
"analysis of public companies, macroeconomic trends, and capital markets. "
"Always show your reasoning, cite the metrics you rely on, quantify risk, "
"and separate fact from forecast. Cover valuation, growth, margins, balance "
"sheet strength, competitive moat, and downside scenarios. "
) * 40 # repeated to exceed the model's minimum cacheable prefix
agent = Agent(
agent_name="FinancialAnalyst",
system_prompt=SYSTEM_PROMPT,
model_name="claude-opus-4-8",
temperature=None, # Opus 4.7+/Sonnet 5 reject a temperature value
max_loops=1,
prompt_caching=True, # the on-switch
)
# First call writes the prefix to cache; later calls with the same prefix read it.
agent.run("Analyze NVIDIA's competitive moat in AI accelerators.")
agent.run("Now do the same for AMD.") # reuses the cached system prefix
```
## How it works
Prompt caching works on the **stable prefix** of a request. A cache *breakpoint* marks the end of a cacheable span; on the next request the provider compares your prefix against what it stored and, if it matches exactly up to a breakpoint, serves everything before that point from cache.
The request is assembled in this order, which is also the order things get cached:
1. **Tool definitions** (rendered before the system prompt)
2. **System prompt**
3. **Conversation messages** (through the last message)
Because it is a strict prefix match, a single changed byte anywhere before a breakpoint invalidates the cache for everything after it.
### Which providers use `cache_control`
Swarms only injects `cache_control` breakpoints for the **Anthropic model family** — any model whose name contains `claude` or `anthropic`. This covers Claude on the Anthropic API, on AWS Bedrock, and on Google Vertex AI.
Requires explicit `cache_control` markers. Swarms injects them automatically. Up to **4 breakpoints** per request — the defaults use tools + system + last message = 3.
Cache **automatically** — no markers needed. Swarms leaves their messages untouched. OpenAI-only routing/retention hints are passed through.
Uses a separate context-cache API, not `cache_control`. Injecting markers breaks the request, so Swarms leaves it untouched unless you force `override`.
Left untouched by default. Use `cache_config={"override": True}` to force marker injection at your own risk.
Anthropic allows a maximum of **4 cache breakpoints** per request. The Swarms defaults place breakpoints on the tools block, the system prompt, and the last message (3 total), leaving one spare.
## Parameters
Prompt caching is controlled by two `Agent` constructor parameters.
Master on-switch. When `True`, Swarms adds ephemeral `cache_control` breakpoints to the stable prefix of each request (for Anthropic models) so the prefix is cached and re-billed at a discount. When `False`, no caching behavior is added and `cache_config` is ignored.
`cache_config` is a dictionary of fine-grained options. It is **only consulted when `prompt_caching=True`**. Every key is optional and falls back to the defaults below.
Cache lifetime. `"5m"` (default) or `"1h"` for Anthropic's extended one-hour cache. The 1-hour cache costs **2x on writes** but survives longer gaps between requests. The required beta header (`extended-cache-ttl-2025-04-11`) is attached automatically when you select `"1h"`.
Cache the system-prompt prefix. Turn off if your system prompt is small or changes every request.
Cache through the last message, enabling incremental multi-turn caching where each new turn extends the cached prefix.
Cache the tool-definitions block. Tools render before the system prompt, so this is a big win for tool-heavy agents with large schemas.
Force `cache_control` injection on (`True`) or off (`False`) regardless of the detected provider. `None` (default) auto-detects based on the model name. Set to `True` to try injection on providers Swarms would normally skip (e.g. Gemini).
**OpenAI-only** routing hint. Grouping requests under a stable key raises cache hit rates. Passed through to the provider; ignored for Anthropic.
**OpenAI-only** cache TTL: `"in_memory"` (default) or `"24h"`. Passed through to the provider; ignored for Anthropic.
### Default caching
With `prompt_caching=True` and no `cache_config`, you get the sensible defaults: a 5-minute TTL caching tools, system prompt, and the last message.
```python theme={null}
from swarms import Agent
SYSTEM_PROMPT = (
"You are a senior financial analyst covering equities, fixed income, and "
"macro. Deliver structured, quantitative, source-aware analysis with clear "
"assumptions, risk quantification, and explicit forecasts versus facts. "
) * 40 # large enough to clear the token minimum
agent = Agent(
agent_name="FinancialAnalyst",
system_prompt=SYSTEM_PROMPT,
model_name="claude-opus-4-8",
temperature=None,
max_loops=1,
prompt_caching=True, # defaults: ttl=5m, cache tools + system + messages
)
agent.run("Summarize the bull and bear case for Apple.")
```
### `ttl="1h"` — extended one-hour cache
Use the one-hour cache when there are longer gaps between related requests. Writes cost 2x, but the prefix survives well past the default 5-minute window. The beta header is attached for you.
```python theme={null}
from swarms import Agent
SYSTEM_PROMPT = (
"You are a senior financial analyst. Provide deep, well-cited analysis of "
"companies and markets, quantifying risk and separating fact from forecast. "
) * 40
agent = Agent(
agent_name="FinancialAnalyst",
system_prompt=SYSTEM_PROMPT,
model_name="claude-opus-4-8",
temperature=None,
max_loops=1,
prompt_caching=True,
cache_config={"ttl": "1h"}, # extended cache; beta header added automatically
)
agent.run("Give me a full valuation walkthrough for Microsoft.")
```
### Toggling `cache_system_prompt` and `cache_messages`
You can cache the system prompt but not the running conversation (or vice versa). This is useful when the system prompt is large and stable but each turn's content varies enough that message caching would rarely hit.
```python theme={null}
from swarms import Agent
SYSTEM_PROMPT = (
"You are a senior financial analyst. Produce rigorous, quantitative, "
"well-sourced analysis with explicit assumptions and risk scenarios. "
) * 40
agent = Agent(
agent_name="FinancialAnalyst",
system_prompt=SYSTEM_PROMPT,
model_name="claude-opus-4-8",
temperature=None,
max_loops=1,
prompt_caching=True,
cache_config={
"cache_system_prompt": True, # cache the big stable system prefix
"cache_messages": False, # don't cache per-turn messages
},
)
agent.run("What macro risks matter most for semiconductors this quarter?")
```
### `cache_tools` — caching the tool block
Tool definitions render before the system prompt, so caching them is a big win for tool-heavy agents with large JSON schemas. This example attaches a schema via `tools_list_dictionary` (a plain schema, no callable) so the tool block itself is large and stable.
```python theme={null}
from swarms import Agent
SYSTEM_PROMPT = (
"You are a senior financial analyst with access to market-data tools. "
"Use them to ground every claim in current figures before reasoning. "
) * 40
TOOLS = [
{
"type": "function",
"function": {
"name": "get_financials",
"description": (
"Fetch a comprehensive financial statement bundle for a public "
"company: income statement, balance sheet, cash flow, and key "
"ratios across multiple reporting periods."
),
"parameters": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "Stock ticker symbol, e.g. 'AAPL'.",
},
"period": {
"type": "string",
"enum": ["annual", "quarterly"],
"description": "Reporting cadence to return.",
},
"years": {
"type": "integer",
"description": "Number of historical periods to include.",
},
},
"required": ["ticker"],
},
},
}
]
agent = Agent(
agent_name="FinancialAnalyst",
system_prompt=SYSTEM_PROMPT,
model_name="claude-opus-4-8",
temperature=None,
max_loops=1,
prompt_caching=True,
tools_list_dictionary=TOOLS,
cache_config={"cache_tools": True}, # cache the tool-definitions block
)
agent.run("Pull Tesla's last 5 years of financials and assess margin trends.")
```
### `override` — forcing injection on Gemini
By default Swarms skips `cache_control` for Gemini because it uses a different caching API. Set `override=True` to force marker injection anyway if you want to experiment.
```python theme={null}
from swarms import Agent
SYSTEM_PROMPT = (
"You are a senior financial analyst. Deliver structured, quantitative "
"analysis with clear assumptions, risk quantification, and forecasts. "
) * 40
agent = Agent(
agent_name="FinancialAnalyst",
system_prompt=SYSTEM_PROMPT,
model_name="gemini/gemini-2.5-pro",
max_loops=1,
prompt_caching=True,
cache_config={"override": True}, # force cache_control on a non-Anthropic provider
)
agent.run("Assess the growth outlook for the cloud infrastructure market.")
```
Forcing `override=True` on a provider that doesn't accept `cache_control` markers can break requests. Gemini normally uses its own context-cache API — only force injection when you are intentionally testing it.
### OpenAI passthrough — `prompt_cache_key` and `prompt_cache_retention`
OpenAI caches automatically, so Swarms doesn't inject markers. But it does pass through OpenAI's routing and retention hints. Use a stable `prompt_cache_key` to raise hit rates and `prompt_cache_retention` to extend the TTL to 24 hours.
```python theme={null}
from swarms import Agent
SYSTEM_PROMPT = (
"You are a senior financial analyst. Produce rigorous, well-sourced, "
"quantitative analysis separating fact from forecast at every step. "
) * 40
agent = Agent(
agent_name="FinancialAnalyst",
system_prompt=SYSTEM_PROMPT,
model_name="gpt-5.4",
max_loops=1,
prompt_caching=True,
cache_config={
"prompt_cache_key": "financial-analyst-v1", # routing hint for higher hit rates
"prompt_cache_retention": "24h", # extend cache TTL
},
)
agent.run("Compare the capital allocation strategies of Meta and Alphabet.")
```
### All options — reference config
A single config showing every supported key together.
```python theme={null}
from swarms import Agent
SYSTEM_PROMPT = (
"You are a senior financial analyst. Deliver deep, quantitative, "
"well-cited analysis with explicit assumptions and downside scenarios. "
) * 40
agent = Agent(
agent_name="FinancialAnalyst",
system_prompt=SYSTEM_PROMPT,
model_name="claude-opus-4-8",
temperature=None,
max_loops=1,
prompt_caching=True,
cache_config={
"ttl": "1h", # 5m (default) or 1h
"cache_system_prompt": True, # cache the system prefix
"cache_messages": True, # incremental multi-turn caching
"cache_tools": True, # cache the tool-definitions block
"override": None, # None=auto-detect, True/False to force
"prompt_cache_key": "analyst-v1", # OpenAI-only routing hint
"prompt_cache_retention": "24h", # OpenAI-only: in_memory or 24h
},
)
agent.run("Build a full investment thesis for Amazon.")
```
## Provider support
Caching is **silently skipped** below the provider's minimum cacheable prefix — there is no error, the request simply isn't cached. Make sure your stable prefix (tools + system prompt + history) exceeds the minimum, and verify with the usage fields described below.
| Provider / model | Minimum input tokens |
| ------------------------------- | -------------------- |
| OpenAI | 1,024 |
| Anthropic Claude 3.x | 1,024 |
| Anthropic Sonnet / Opus 4.x | 2,048 |
| Anthropic Haiku 4.5+, Opus 4.5+ | 4,096 |
| Google Gemini | 1,024 |
**`cache_control` vs. automatic caching:**
* **Anthropic (Claude / Bedrock / Vertex)** — requires explicit `cache_control` breakpoints. Swarms injects them automatically when the model name contains `claude` or `anthropic`. Up to 4 breakpoints per request.
* **OpenAI and xAI** — cache automatically with no markers. Swarms leaves messages untouched and passes through OpenAI's `prompt_cache_key` / `prompt_cache_retention`.
* **Gemini / Google AI Studio** — uses a separate context-cache API. Markers would break the request, so Swarms leaves it untouched unless you set `cache_config={"override": True}`.
## Verifying cache hits
`Agent.run()` returns a formatted string, so it won't show token usage. To inspect cache behavior, read from the agent's underlying LLM wrapper directly with `return_all = True`, which returns the raw provider response including the usage block.
```python theme={null}
# After building `agent` with prompt_caching=True
agent.llm.return_all = True
resp = agent.llm.run("Analyze the semiconductor supply chain in 2026.")
usage = resp["usage"] if isinstance(resp, dict) else resp.usage
print(usage)
```
**What the usage fields mean:**
(Anthropic) Tokens **written** to the cache on this request. Non-zero on the first call that populates a new prefix.
(Anthropic) Tokens **read** from the cache on this request — this is where the savings show up. Should be non-zero on repeat requests with an identical prefix.
(OpenAI-style) Number of prompt tokens served from cache on this request.
If `cache_read_input_tokens` stays `0` across requests that should share a prefix, a **silent invalidator** is breaking the prefix match — usually a timestamp or UUID in the system prompt, or a changing tool set. Check that everything before the breakpoint is byte-for-byte identical.
## Gotchas and best practices
* **Prefix match is exact.** Any byte change before a breakpoint invalidates everything after it. Keep timestamps, per-request IDs, random seeds, and other volatile content out of the system prompt and tool definitions.
* **Watch for silent invalidators.** Time-enabled conversation history, dynamically reordered tools, or a per-request nonce in the persona will quietly break caching. If `cache_read_input_tokens` is always 0, hunt for one of these.
* **Clear the token minimum.** Caching is skipped below the provider minimum with no error. If the prefix is too small, make the system prompt larger or accept that small prompts won't cache. The examples repeat the persona to exceed the minimum.
* **`temperature=None` on newer Anthropic models.** Opus 4.7 / 4.8 and Sonnet 5 reject a `temperature` value — pass `temperature=None` on the Agent for those models (as every Anthropic example above does).
* **The 1-hour cache costs 2x on writes.** Use `ttl="1h"` only when gaps between related requests exceed the 5-minute default window; otherwise the extra write cost isn't worth it.
* **Order matters for tool-heavy agents.** Tools render before the system prompt, so a large, stable tool block cached via `cache_tools=True` is often the single biggest saving.
* **Stay within 4 breakpoints (Anthropic).** The defaults use 3 (tools + system + last message). If you add manual breakpoints elsewhere, keep the total at or below 4.
# Reasoning Agent Router
Source: https://docs.swarms.world/agents/reasoning-agent-router
Dynamic routing system for selecting and executing different reasoning strategies based on task requirements
The `ReasoningAgentRouter` enables dynamic selection and execution of different reasoning strategies based on task requirements. It provides a flexible interface to work with multiple reasoning approaches.
## Architecture
```mermaid theme={null}
graph TD
Task[Task Input] --> Router[ReasoningAgentRouter]
Router --> SelectSwarm{Select Swarm Type}
SelectSwarm -->|Reasoning Duo| RD[ReasoningDuo]
SelectSwarm -->|Self Consistency| SC[SelfConsistencyAgent]
SelectSwarm -->|IRE| IRE[IterativeReflectiveExpansion]
SelectSwarm -->|Reflexion| RF[ReflexionAgent]
SelectSwarm -->|GKP| GKP[GKPAgent]
SelectSwarm -->|Agent Judge| AJ[AgentJudge]
RD --> Output[Task Output]
SC --> Output
IRE --> Output
RF --> Output
GKP --> Output
AJ --> Output
```
## Parameters
| Parameter | Type | Default | Description |
| ------------------------ | --------------- | ------------------------- | ------------------------------------------- |
| `agent_name` | `str` | `"reasoning_agent"` | Name identifier for the agent |
| `description` | `str` | `"A reasoning agent..."` | Description of the agent's capabilities |
| `model_name` | `str` | `"gpt-5.4"` | The underlying language model to use |
| `system_prompt` | `str` | `"You are a helpful..."` | System prompt for the agent |
| `max_loops` | `int` | `1` | Maximum number of reasoning loops |
| `swarm_type` | `agent_types` | `"reasoning-duo"` | Type of reasoning swarm to use |
| `num_samples` | `int` | `1` | Number of samples for self-consistency |
| `output_type` | `OutputType` | `"dict-all-except-first"` | Format of the output |
| `num_knowledge_items` | `int` | `6` | Number of knowledge items for GKP agent |
| `memory_capacity` | `int` | `6` | Memory capacity for agents that support it |
| `eval` | `bool` | `False` | Enable evaluation mode for self-consistency |
| `random_models_on` | `bool` | `False` | Enable random model selection for diversity |
| `majority_voting_prompt` | `Optional[str]` | `None` | Custom prompt for majority voting |
| `reasoning_model_name` | `Optional[str]` | `"gpt-4o"` | Model for reasoning in ReasoningDuo |
## Available Agent Types
The following values are supported for the `swarm_type` parameter:
* `"reasoning-duo"` or `"reasoning-agent"`
* `"self-consistency"` or `"consistency-agent"`
* `"ire"` or `"ire-agent"` — `_create_ire_agent` passes `max_loops=self.num_samples` when building the underlying agent, so the router's own `max_loops` is ignored for this type; `num_samples` controls the number of IRE iterations instead.
* `"ReflexionAgent"` — `run()` returns the raw `list` produced by `ReflexionAgent.run()` directly; it bypasses `history_output_formatter`, so `output_type` has no effect for this swarm type (every other type is formatted according to `output_type`).
* `"GKPAgent"`
* `"AgentJudge"`
## Methods
| Method | Description |
| ------------------------------------- | ---------------------------------------------------------------------------------- |
| `select_swarm()` | Selects and initializes the appropriate reasoning swarm |
| `run(task, *args, **kwargs)` | Executes the selected swarm's reasoning process |
| `batched_run(tasks, *args, **kwargs)` | Executes the reasoning process on a batch of tasks (each task processed via `run`) |
## Examples
### Basic Usage
```python theme={null}
from swarms import ReasoningAgentRouter
router = ReasoningAgentRouter(
agent_name="reasoning-agent",
model_name="claude-sonnet-4-6",
swarm_type="self-consistency",
num_samples=3,
)
result = router.run("What is the best approach to solve this problem?")
```
### Self-Consistency with Evaluation
```python theme={null}
router = ReasoningAgentRouter(
swarm_type="self-consistency",
num_samples=5,
model_name="claude-sonnet-4-6",
eval=True,
random_models_on=True
)
result = router.run("What is 2 + 2?")
```
### ReasoningDuo with Image Support
```python theme={null}
router = ReasoningAgentRouter(
swarm_type="reasoning-duo",
model_name="claude-sonnet-4-6",
reasoning_model_name="claude-sonnet-4-6",
max_loops=2
)
result = router.run(
"Analyze this image and explain the patterns you see",
img="data_visualization.png"
)
```
### GKP Agent
```python theme={null}
router = ReasoningAgentRouter(
swarm_type="GKPAgent",
model_name="claude-sonnet-4-6",
num_knowledge_items=6
)
result = router.run("What are the implications of quantum entanglement?")
```
### Reflexion Agent
```python theme={null}
router = ReasoningAgentRouter(
swarm_type="ReflexionAgent",
max_loops=3,
model_name="claude-sonnet-4-6"
)
result = router.run("Explain quantum computing to a beginner.")
```
## Choosing the Right Type
| Scenario | Recommended Type | Why |
| --------------------------------------- | ------------------ | --------------------------------------------- |
| Tasks requiring high reliability | `self-consistency` | Multiple validation paths, consensus building |
| Complex tasks needing analysis + action | `reasoning-duo` | Separates reasoning from execution |
| Problems requiring iterative refinement | `ire` | Designed for progressive improvement |
| Tasks requiring introspection | `ReflexionAgent` | Self-reflection and learning from experience |
| Knowledge-intensive tasks | `GKPAgent` | Generates knowledge before reasoning |
| Quality control | `AgentJudge` | Specialized evaluation capabilities |
## Best Practices
1. **Swarm Type Selection**: Match the reasoning strategy to your task requirements
2. **Performance**: Adjust `max_loops` and `num_samples` based on task complexity
3. **Self-Consistency**: Use 3-5 samples for most tasks, 7+ for critical decisions
4. **Multi-modal**: Use vision-capable models when processing images
5. **ReasoningDuo**: Set different models for reasoning vs execution via `reasoning_model_name`
# Reasoning Agents Overview
Source: https://docs.swarms.world/agents/reasoning-agents-overview
Advanced agents that employ structured cognitive strategies for improved problem-solving beyond standard language model capabilities
Reasoning agents are sophisticated agents that employ advanced cognitive strategies to improve problem-solving performance beyond standard language model capabilities. Unlike traditional prompt-based approaches, reasoning agents implement structured methodologies that enable them to think more systematically, self-reflect, collaborate, and iteratively refine their responses.
These agents are inspired by cognitive science and human reasoning processes, incorporating techniques such as:
* **Multi-step reasoning**: Breaking down complex problems into manageable components
* **Self-reflection**: Evaluating and critiquing their own outputs
* **Iterative refinement**: Progressively improving solutions through multiple iterations
* **Collaborative thinking**: Using multiple reasoning pathways or agent perspectives
* **Memory integration**: Learning from past experiences and building knowledge over time
* **Meta-cognitive awareness**: Understanding their own thinking processes and limitations
## Available Reasoning Agents
| Agent Name | Type | Research Paper | Key Features | Best Use Cases |
| -------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- |
| **Self-Consistency Agent** | Consensus-based | [Self-Consistency Improves Chain of Thought Reasoning](https://arxiv.org/abs/2203.07870) (Wang et al., 2022) | Multiple independent reasoning paths, majority voting aggregation, concurrent execution, validation mode | Mathematical problem solving, high-accuracy requirements, decision making |
| **Reasoning Duo** | Collaborative | Novel dual-agent architecture | Separate reasoning and execution agents, collaborative problem solving, task decomposition, cross-validation | Complex analysis tasks, multi-step problem solving, research and planning |
| **IRE Agent** | Iterative | Iterative Reflective Expansion framework | Hypothesis generation, path simulation, error reflection, dynamic revision | Complex reasoning tasks, research problems, strategy development |
| **Reflexion Agent** | Self-reflective | [Reflexion: Language Agents with Verbal Reinforcement Learning](https://arxiv.org/abs/2303.11366) (Shinn et al., 2023) | Self-evaluation, experience memory, adaptive improvement, learning from failures | Continuous improvement tasks, long-term projects, quality refinement |
| **GKP Agent** | Knowledge-based | [Generated Knowledge Prompting](https://arxiv.org/abs/2110.08387) (Liu et al., 2022) | Knowledge generation, multi-perspective reasoning, information synthesis | Knowledge-intensive tasks, research questions, fact-based reasoning |
| **Agent Judge** | Evaluation | [Agent-as-a-Judge](https://arxiv.org/abs/2410.10934) | Quality assessment, structured evaluation, performance metrics, feedback generation | Quality control, output evaluation, performance assessment |
## Agent Architectures
### Self-Consistency Agent
Implements multiple independent reasoning paths with consensus-building to improve response reliability and accuracy through majority voting mechanisms.
```mermaid theme={null}
graph TD
A[Task Input] --> B[Agent Pool]
B --> C[Response 1]
B --> D[Response 2]
B --> E[Response 3]
B --> F[Response N]
C --> G[Aggregation Agent]
D --> G
E --> G
F --> G
G --> H[Majority Voting Analysis]
H --> I[Consensus Evaluation]
I --> J[Final Answer]
style A fill:#e1f5fe
style J fill:#c8e6c9
style G fill:#fff3e0
```
**Use Cases**: Mathematical problem solving, high-stakes decision making, answer validation, quality assurance
[Self-Consistency Agent Guide](/agents/self-consistency-agent)
***
### Reasoning Duo
Dual-agent collaborative system that separates reasoning and execution phases, enabling specialized analysis and task completion through coordinated agent interaction.
```mermaid theme={null}
graph TD
A[Task Input] --> B[Reasoning Agent]
B --> C[Deep Analysis]
C --> D[Strategy Planning]
D --> E[Reasoning Output]
E --> F[Main Agent]
F --> G[Task Execution]
G --> H[Response Generation]
H --> I[Final Output]
style A fill:#e1f5fe
style B fill:#f3e5f5
style F fill:#e8f5e8
style I fill:#c8e6c9
```
**Use Cases**: Complex analysis tasks, multi-step problem solving, research and planning, verification workflows
[Reasoning Duo Guide](/agents/reasoning-duo)
***
### IRE Agent (Iterative Reflective Expansion)
Sophisticated reasoning framework employing iterative hypothesis generation, simulation, and refinement through continuous cycles of testing and meta-cognitive reflection.
```mermaid theme={null}
graph TD
A[Problem Input] --> B[Hypothesis Generation]
B --> C[Path Simulation]
C --> D[Outcome Evaluation]
D --> E{Satisfactory?}
E -->|No| F[Meta-Cognitive Reflection]
F --> G[Path Revision]
G --> H[Knowledge Integration]
H --> C
E -->|Yes| I[Solution Synthesis]
I --> J[Final Answer]
style A fill:#e1f5fe
style F fill:#fff3e0
style J fill:#c8e6c9
```
**Use Cases**: Complex reasoning tasks, research problems, strategy development, iterative learning
[IRE Agent Guide](/agents/iterative-agent)
***
### Reflexion Agent
Advanced self-reflective system implementing actor-evaluator-reflector architecture for continuous improvement through experience-based learning and memory integration.
```mermaid theme={null}
graph TD
A[Task Input] --> B[Actor Agent]
B --> C[Initial Response]
C --> D[Evaluator Agent]
D --> E[Quality Assessment]
E --> F[Performance Score]
F --> G[Reflector Agent]
G --> H[Self-Reflection]
H --> I[Experience Memory]
I --> J{Max Iterations?}
J -->|No| K[Refined Response]
K --> D
J -->|Yes| L[Final Response]
style A fill:#e1f5fe
style B fill:#e8f5e8
style D fill:#fff3e0
style G fill:#f3e5f5
style L fill:#c8e6c9
```
**Use Cases**: Continuous improvement tasks, long-term projects, adaptive learning, quality refinement
[Reflexion Agent Guide](/agents/reflexion-agent)
***
### GKP Agent (Generated Knowledge Prompting)
Knowledge-driven reasoning system that generates relevant information before answering queries, implementing multi-perspective analysis through coordinated knowledge synthesis.
```mermaid theme={null}
graph TD
A[Query Input] --> B[Knowledge Generator]
B --> C[Generate Knowledge Item 1]
B --> D[Generate Knowledge Item 2]
B --> E[Generate Knowledge Item N]
C --> F[Reasoner Agent]
D --> F
E --> F
F --> G[Knowledge Integration]
G --> H[Reasoning Process]
H --> I[Response Generation]
I --> J[Coordinator]
J --> K[Final Answer]
style A fill:#e1f5fe
style B fill:#fff3e0
style F fill:#e8f5e8
style J fill:#f3e5f5
style K fill:#c8e6c9
```
**Use Cases**: Knowledge-intensive tasks, research questions, fact-based reasoning, information synthesis
[GKP Agent Guide](/agents/gkp-agent)
***
### Agent Judge
Specialized evaluation system for assessing agent outputs and system performance, providing structured feedback and quality metrics through comprehensive assessment frameworks.
```mermaid theme={null}
graph TD
A[Output to Evaluate] --> B[Evaluation Criteria]
A --> C[Judge Agent]
B --> C
C --> D[Quality Analysis]
D --> E[Criteria Assessment]
E --> F[Scoring Framework]
F --> G[Feedback Generation]
G --> H[Evaluation Report]
style A fill:#e1f5fe
style C fill:#fff3e0
style H fill:#c8e6c9
```
**Use Cases**: Quality control, output evaluation, performance assessment, model comparison
[Agent Judge Guide](/agents/agent-judge)
## Implementation Guide
### Unified Interface via Reasoning Agent Router
The `ReasoningAgentRouter` provides a centralized interface for accessing all reasoning agent implementations:
```python theme={null}
from swarms import ReasoningAgentRouter
# Initialize router with specific reasoning strategy
router = ReasoningAgentRouter(
swarm_type="self-consistency",
model_name="claude-sonnet-4-6",
num_samples=5,
max_loops=3
)
# Execute reasoning process
result = router.run("Analyze the optimal solution for this complex business problem")
print(result)
```
[Reasoning Agent Router Reference](/agents/reasoning-agent-router)
### Direct Agent Implementation
```python theme={null}
from swarms import SelfConsistencyAgent, ReasoningDuo, ReflexionAgent
# Self-Consistency Agent for high-accuracy requirements
consistency_agent = SelfConsistencyAgent(
model_name="claude-sonnet-4-6",
num_samples=5
)
# Reasoning Duo for collaborative analysis workflows
duo_agent = ReasoningDuo(
model_names=["claude-sonnet-4-6", "gpt-5.4"]
)
# Reflexion Agent for adaptive learning scenarios
reflexion_agent = ReflexionAgent(
model_name="claude-sonnet-4-6",
max_loops=3,
memory_capacity=100
)
```
## Choosing the Right Reasoning Agent
| Scenario | Recommended Agent | Why? |
| -------------------------- | ------------------- | -------------------------------------------- |
| **High-stakes decisions** | Self-Consistency | Multiple validation paths ensure reliability |
| **Complex research tasks** | Reasoning Duo + GKP | Collaboration + knowledge synthesis |
| **Learning & improvement** | Reflexion | Built-in self-improvement mechanisms |
| **Mathematical problems** | Self-Consistency | Proven effectiveness on logical reasoning |
| **Quality assessment** | Agent Judge | Specialized evaluation capabilities |
| **Iterative refinement** | IRE | Designed for progressive improvement |
# Reasoning Duo
Source: https://docs.swarms.world/agents/reasoning-duo
Dual-agent collaborative system that separates reasoning and execution phases for more robust and reliable outputs
The `ReasoningDuo` class implements a dual-agent reasoning system that combines a reasoning agent and a main agent to provide well-thought-out responses to complex tasks. This architecture separates the reasoning process from the final response generation.
## Architecture
```
Task Input → Reasoning Agent → Structured Analysis → Main Agent → Final Output
```
## Parameters
| Parameter | Type | Default | Description |
| ---------------------- | --------------- | ------------------------------ | ----------------------------------------------------------------------------------- |
| `id` | `str` | `generate_id("reasoning-duo")` | Unique identifier for the duo (`-<32 hex chars>`) |
| `agent_name` | `str` | `"reasoning-agent-01"` | Base name for the two internal agents, which are suffixed `-reasoning` and `-main` |
| `agent_description` | `str` | `"A highly intelligent..."` | Description passed to both internal agents |
| `model_name` | `str` | `"gpt-5.4"` | Stored on the instance; not currently used to configure either internal agent |
| `description` | `str` | `"A highly intelligent..."` | Description of the reasoning duo's capabilities |
| `model_names` | `list[str]` | `["gpt-5.4", "gpt-5.4"]` | Model names for `[reasoning_agent, main_agent]` (index 1 configures the main agent) |
| `system_prompt` | `str` | `"You are a helpful..."` | System prompt for the main agent |
| `output_type` | `OutputType` | `"dict-all-except-first"` | Format of the value returned by `run()` |
| `reasoning_model_name` | `Optional[str]` | `"gpt-4o"` | Model used by the reasoning agent; if `None`, falls back to `model_names[0]` |
| `max_loops` | `int` | `1` | Number of reasoning/main-agent loop iterations in `run()` |
### Methods
| Method | Parameters | Returns | Description |
| ------------- | ---------------------------------------------------- | --------------------------- | --------------------------------------------------------------------------- |
| `step` | `task: str, img: Optional[str] = None` | `None` | Runs one reasoning-agent → main-agent cycle and appends to the conversation |
| `run` | `task: str, img: Optional[str] = None` | Formatted per `output_type` | Processes a task through both agents for `max_loops` iterations |
| `batched_run` | `tasks: List[str], imgs: Optional[List[str]] = None` | `list` | Processes multiple tasks sequentially |
## Quick Start
```python theme={null}
from swarms import ReasoningDuo
duo = ReasoningDuo(
agent_name="reasoning-agent-01",
model_names=["claude-sonnet-4-6", "gpt-5.4"]
)
result = duo.run("Explain the concept of gravitational waves")
```
## Examples
### Mathematical Analysis
```python theme={null}
duo = ReasoningDuo()
math_task = """
Solve the following differential equation:
dy/dx + 2y = x^2, y(0) = 1
"""
solution = duo.run(math_task)
```
### Financial Analysis
```python theme={null}
finance_task = """
Calculate the Net Present Value (NPV) of a project with:
- Initial investment: $100,000
- Annual cash flows: $25,000 for 5 years
- Discount rate: 8%
"""
analysis = duo.run(finance_task)
```
### Customizing Agent Behavior
```python theme={null}
duo = ReasoningDuo(
agent_name="custom-reasoning-agent",
description="Specialized financial analysis agent",
model_names=["claude-sonnet-4-6", "gpt-5.4"],
system_prompt="You are a financial expert AI assistant..."
)
```
### Batch Processing
```python theme={null}
tasks = [
"Analyze market trends for tech stocks",
"Calculate risk metrics for a portfolio",
"Forecast revenue growth"
]
results = duo.batched_run(tasks)
```
## Best Practices
1. **Task Formulation**: Be specific and clear in task descriptions. Include relevant context and constraints.
2. **Performance Optimization**: Use `batched_run` for multiple related tasks. Monitor agent outputs for consistency.
3. **Model Selection**: Adjust model parameters based on task complexity.
# Reflexion Agent
Source: https://docs.swarms.world/agents/reflexion-agent
Self-reflective agent that improves through iterative acting, evaluating, and reflecting with experience memory
The `ReflexionAgent` implements the Reflexion framework to improve through self-reflection. It follows a process of acting on tasks, evaluating its performance, generating self-reflections, and using these reflections to improve future responses.
Based on the research paper: [Reflexion: Language Agents with Verbal Reinforcement Learning](https://arxiv.org/abs/2303.11366) (Shinn et al., 2023).
The agent consists of three specialized sub-agents:
* **Actor**: Generates initial responses to tasks
* **Evaluator**: Critically assesses responses against quality criteria
* **Reflector**: Generates self-reflections to improve future responses
## Parameters
| Parameter | Type | Default | Description |
| ----------------- | ----- | ------------------- | ------------------------------------------------ |
| `agent_name` | `str` | `"reflexion-agent"` | Name of the agent |
| `system_prompt` | `str` | `REFLEXION_PROMPT` | System prompt for the agent |
| `model_name` | `str` | `"openai/o1"` | Model name for generating responses |
| `max_loops` | `int` | `3` | Maximum number of reflection iterations per task |
| `memory_capacity` | `int` | `100` | Maximum capacity of long-term memory |
## Methods
### act
Generates a response to the given task using the actor agent.
```python theme={null}
response = agent.act(task: str, relevant_memories: List[Dict[str, Any]] = None) -> str
```
### evaluate
Evaluates the quality of a response to a task. Returns an evaluation string and a score between 0 and 1.
```python theme={null}
evaluation, score = agent.evaluate(task: str, response: str) -> Tuple[str, float]
```
### reflect
Generates a self-reflection based on the task, response, and evaluation.
```python theme={null}
reflection = agent.reflect(task: str, response: str, evaluation: str) -> str
```
### refine
Refines the original response based on evaluation and reflection.
```python theme={null}
refined_response = agent.refine(task: str, original_response: str, evaluation: str, reflection: str) -> str
```
### step
Processes a single task through one iteration of the Reflexion process. Returns a dictionary containing task, response, evaluation, reflection, score, and iteration number.
```python theme={null}
result = agent.step(task: str, iteration: int = 0, previous_response: str = None) -> Dict[str, Any]
```
### run
Executes the full Reflexion process for a list of tasks.
```python theme={null}
results = agent.run(tasks: List[str], include_intermediates: bool = False) -> List[Any]
```
## Example
```python theme={null}
from swarms import ReflexionAgent
agent = ReflexionAgent(
agent_name="reflexion-agent",
model_name="openai/o1",
max_loops=3
)
tasks = [
"Explain quantum computing to a beginner.",
"Write a Python function to sort a list of dictionaries by a specific key."
]
results = agent.run(tasks)
for i, result in enumerate(results):
print(f"\nTask {i+1}: {tasks[i]}")
print(f"Response: {result}")
```
## Memory System
The agent includes a `ReflexionMemory` system that maintains both short-term and long-term memories of past experiences, reflections, and feedback.
* Short-term memory for recent interactions
* Long-term memory for important reflections and patterns
* Automatic memory management with capacity limits
* Relevance-based memory retrieval
* Similarity-based deduplication
## Best Practices
1. **Task Clarity**: Provide clear, specific tasks to get the best results
2. **Iteration Count**: Adjust `max_loops` based on task complexity (more complex tasks benefit from more iterations)
3. **Memory Management**: Monitor memory usage and adjust `memory_capacity` as needed
4. **Model Selection**: Choose an appropriate model based on your specific use case
# Self-Consistency Agent
Source: https://docs.swarms.world/agents/self-consistency-agent
Generate multiple independent reasoning paths and aggregate them via majority voting for reliable, high-accuracy answers
The `SelfConsistencyAgent` generates multiple independent responses to a given task and aggregates them into a single, consistent final answer. It leverages concurrent processing and employs a majority voting mechanism to ensure reliability.
Based on the research paper: [Self-Consistency Improves Chain of Thought Reasoning in Language Models](https://arxiv.org/abs/2203.07870) (Wang et al., 2022).
## Class: `SelfConsistencyAgent`
### Parameters
| Parameter | Type | Default | Description |
| ------------------------ | --------------- | ------------------------------------------ | --------------------------------------------- |
| `name` | `str` | `"Self-Consistency-Agent"` | Name of the agent |
| `description` | `str` | `"An agent that uses self consistency..."` | Description of the agent's purpose |
| `system_prompt` | `str` | `CONSISTENCY_SYSTEM_PROMPT` | System prompt for the reasoning agent |
| `model_name` | `str` | `"gpt-5.4"` | The underlying language model to use |
| `num_samples` | `int` | `5` | Number of independent responses to generate |
| `max_loops` | `int` | `1` | Maximum number of reasoning loops per sample |
| `majority_voting_prompt` | `Optional[str]` | `majority_voting_prompt` | Custom prompt for majority voting aggregation |
| `eval` | `bool` | `False` | Enable evaluation mode for answer validation |
| `output_type` | `OutputType` | `"dict"` | Format of the output |
| `random_models_on` | `bool` | `False` | Enable random model selection for diversity |
### Methods
| Method | Description | Returns |
| ----------------------------------------------- | ------------------------------------------------ | ---------------------------------- |
| `run(task, img?, answer?)` | Generates multiple responses and aggregates them | `Union[str, Dict[str, Any]]` |
| `check_responses_for_answer(responses, answer)` | Checks if an answer appears in any response | `bool` |
| `batched_run(tasks)` | Run the agent on multiple tasks in batch | `List[Union[str, Dict[str, Any]]]` |
`aggregation_agent(responses, prompt?, model_name?)` is a module-level helper function (not a method on `SelfConsistencyAgent`) used internally to synthesize the final answer via majority voting. Import it separately as `from swarms.agents.consistency_agent import aggregation_agent` if you need it directly.
## Examples
### Basic Usage
```python theme={null}
from swarms import SelfConsistencyAgent
agent = SelfConsistencyAgent(
name="Math-Reasoning-Agent",
model_name="claude-sonnet-4-6",
max_loops=1,
num_samples=5
)
task = "What is the 40th prime number?"
final_answer = agent.run(task)
print("Final aggregated answer:", final_answer)
```
### Evaluation Mode
```python theme={null}
from swarms import SelfConsistencyAgent
agent = SelfConsistencyAgent(
name="Validation-Agent",
model_name="claude-sonnet-4-6",
num_samples=3,
eval=True
)
result = agent.run("What is 2 + 2?", answer="4", eval=True)
if result is not None:
print("Validation passed:", result)
else:
print("Validation failed - expected answer not found")
```
### Random Models for Diversity
```python theme={null}
from swarms import SelfConsistencyAgent
agent = SelfConsistencyAgent(
name="Diverse-Reasoning-Agent",
model_name="claude-sonnet-4-6",
num_samples=5,
random_models_on=True
)
result = agent.run("What are the benefits of renewable energy?")
print("Diverse reasoning result:", result)
```
### Batch Processing
```python theme={null}
from swarms import SelfConsistencyAgent
agent = SelfConsistencyAgent(
name="Batch-Processing-Agent",
model_name="claude-sonnet-4-6",
num_samples=3
)
tasks = [
"What is the capital of France?",
"What is 15 * 23?",
"Explain photosynthesis in simple terms."
]
results = agent.batched_run(tasks)
for i, result in enumerate(results):
print(f"Task {i+1} result: {result}")
```
## How It Works
1. **Generates Multiple Independent Responses**: Creates several reasoning paths for the same problem
2. **Analyzes Consistency**: Examines agreement among different reasoning approaches
3. **Aggregates Results**: Uses majority voting or consensus building
4. **Produces Reliable Output**: Delivers a final answer reflecting the most reliable consensus
The agent uses `ThreadPoolExecutor` to generate multiple responses concurrently, improving performance while maintaining independence between reasoning paths.
## Output Formats
* `"dict"`: Dictionary format with conversation history
* `"str"`: Simple string output
* `"list"`: List format
* `"json"`: JSON formatted output
## Best Practices
1. **Sample Size**: Use 3-7 samples for most tasks; increase for critical decisions
2. **Model Selection**: Choose models with strong reasoning capabilities
3. **Evaluation Mode**: Enable for tasks with known correct answers
4. **Custom Prompts**: Tailor majority voting prompts for specific domains
5. **Batch Processing**: Use `batched_run` for multiple related tasks
# Structured Outputs
Source: https://docs.swarms.world/agents/structured-outputs
Get structured, typed responses from agents using JSON schemas and Pydantic models
Structured outputs enable agents to return responses in a specific format, such as JSON objects, lists, or Pydantic models. This is essential for integrating agents into applications and workflows.
## Output Types
Swarms supports multiple output formats through the `output_type` parameter. `output_type` controls how the **conversation transcript** (`agent.short_memory`) is formatted when `agent.run()` returns — it is not a schema parser. In particular:
* `"str"` / `"string"` — the full conversation as one string
* `"str-all-except-first"` (default) — the conversation, excluding the first (system prompt) message, joined into one string
* `"final"` / `"last"` — just the content of the last message (a plain string) — this is usually what you want when you also configure a `list_base_models`/`tool_schema`, since the model's final response text is where schema-shaped JSON ends up
* `"json"` — the full conversation history serialized as a JSON string (an array of `{"role", "content", ...}` message dicts, **not** a single schema-shaped object)
* `"dict"` / `"dictionary"` — the full conversation history as a Python `list` of message dicts (despite the name, this is a list, not a single dict)
* `"list"` — the conversation as a list of message dicts
* `"yaml"` — the conversation history as a YAML string
* `"xml"` — the conversation history as an XML string
* `"all"` — the conversation as a string (same as `"string"`)
* `"dict-all-except-first"` — all messages except the first, as a list of message dicts. This is the default `output_type` used internally by several multi-agent harnesses (`HeavySwarm`, `HierarchicalSwarm`, `SwarmRouter`, `LLMCouncil`, `PlannerWorkerSwarm`, and others)
* `"list-final"` — the content of the last message, wrapped in a single-item list
* `"dict-final"` — the content of the last message, as a `(content, content)` tuple
```python theme={null}
from swarms import Agent
# String output (default is "str-all-except-first")
agent = Agent(output_type="str")
# Full conversation history as JSON
agent = Agent(output_type="json")
# Full conversation history as a list of message dicts
agent = Agent(output_type="dict")
# List output
agent = Agent(output_type="list")
# YAML output
agent = Agent(output_type="yaml")
# XML output
agent = Agent(output_type="xml")
# Just the agent's final response as a plain string — pair this with
# list_base_models / tool_schema to get back schema-shaped JSON text
agent = Agent(output_type="final")
```
## JSON Schema Output
### Basic JSON Schema
Use Pydantic models to define structured output schemas:
```python theme={null}
from swarms import Agent
from pydantic import BaseModel, Field
from typing import List
class CompanyAnalysis(BaseModel):
company_name: str = Field(description="Name of the company")
industry: str = Field(description="Primary industry")
revenue: float = Field(description="Annual revenue in millions")
growth_rate: float = Field(description="Year-over-year growth rate")
strengths: List[str] = Field(description="Key strengths")
risks: List[str] = Field(description="Main risk factors")
recommendation: str = Field(description="Investment recommendation")
agent = Agent(
agent_name="Financial-Analyst",
model_name="claude-sonnet-4-6",
max_loops=1,
list_base_models=[CompanyAnalysis], # Adds the schema to the agent's memory as guidance
output_type="final", # Return just the model's final text response
)
result = agent.run(
"Analyze Tesla as an investment opportunity"
)
# `list_base_models` only tells the LLM what shape to respond in — it does not
# parse or validate the response for you. `result` is a plain string; if the
# model complied with the schema, it will be JSON text you can parse yourself.
import json
data = json.loads(result)
analysis = CompanyAnalysis(**data)
print(analysis.company_name)
```
### Multiple Output Schemas
Define multiple possible output formats:
```python theme={null}
from pydantic import BaseModel, Field
from typing import List
class ProductReview(BaseModel):
product_name: str
rating: float = Field(ge=0, le=5)
pros: List[str]
cons: List[str]
verdict: str
class ComparisonReport(BaseModel):
products: List[str]
winner: str
reasoning: str
price_comparison: dict
agent = Agent(
agent_name="Product-Reviewer",
model_name="claude-sonnet-4-6",
list_base_models=[ProductReview, ComparisonReport],
output_type="final",
)
# Both schemas are described in the agent's memory; the model picks
# whichever shape fits the task when it writes its final text response.
# Parse the result yourself against whichever schema you expect.
review = agent.run("Review the iPhone 15 Pro")
comparison = agent.run("Compare iPhone 15 Pro vs Samsung S24 Ultra")
```
## Tool Schema
### Using tool\_schema Parameter
Define output structure using `tool_schema`:
```python theme={null}
from pydantic import BaseModel, Field
class EmailDraft(BaseModel):
subject: str = Field(description="Email subject line")
body: str = Field(description="Email body content")
recipients: list[str] = Field(description="List of recipient email addresses")
cc: list[str] = Field(default=[], description="CC recipients")
priority: str = Field(default="normal", description="Email priority: low, normal, high")
agent = Agent(
agent_name="Email-Assistant",
model_name="claude-sonnet-4-6",
tool_schema=EmailDraft, # Adds the schema to the agent's memory as guidance
output_type="final", # Return the model's raw final text (expected to be JSON)
)
result = agent.run(
"Draft an email to the engineering team about the new feature release"
)
# `tool_schema` guides the model to respond in this shape; it does not parse
# the response for you. Parse the JSON text yourself:
import json
email = json.loads(result)
print(f"Subject: {email['subject']}")
print(f"To: {', '.join(email['recipients'])}")
print(f"Body: {email['body']}")
```
## Complex Output Structures
### Nested Models
```python theme={null}
from pydantic import BaseModel, Field
from typing import List, Optional
from datetime import datetime
class Task(BaseModel):
title: str
description: str
priority: str = Field(pattern="^(low|medium|high|critical)$")
estimated_hours: float
assigned_to: Optional[str] = None
class Milestone(BaseModel):
name: str
deadline: str
tasks: List[Task]
status: str = Field(pattern="^(planning|in_progress|completed)$")
class ProjectPlan(BaseModel):
project_name: str
description: str
start_date: str
end_date: str
milestones: List[Milestone]
budget: float
team_size: int
agent = Agent(
agent_name="Project-Manager",
model_name="claude-sonnet-4-6",
list_base_models=[ProjectPlan],
max_loops=1,
output_type="final",
)
result = agent.run(
"""
Create a 3-month project plan for building a mobile app with the following requirements:
- User authentication
- Real-time chat
- Push notifications
- Payment integration
"""
)
# Parse the model's JSON text response yourself
import json
project = json.loads(result)
# Access nested structure
for milestone in project['milestones']:
print(f"\nMilestone: {milestone['name']}")
for task in milestone['tasks']:
print(f" - {task['title']} ({task['priority']} priority)")
```
### Lists and Arrays
```python theme={null}
from pydantic import BaseModel, Field
from typing import List
class StockRecommendation(BaseModel):
ticker: str = Field(description="Stock ticker symbol")
company_name: str
current_price: float
target_price: float
action: str = Field(pattern="^(buy|sell|hold)$")
confidence: float = Field(ge=0, le=100)
reasoning: str
class PortfolioRecommendations(BaseModel):
recommendations: List[StockRecommendation]
overall_strategy: str
risk_level: str = Field(pattern="^(conservative|moderate|aggressive)$")
agent = Agent(
agent_name="Portfolio-Advisor",
model_name="claude-sonnet-4-6",
list_base_models=[PortfolioRecommendations],
output_type="final",
)
result = agent.run(
"Provide 5 stock recommendations for a moderate-risk portfolio"
)
import json
portfolio = json.loads(result)
for rec in portfolio['recommendations']:
print(f"{rec['ticker']}: {rec['action']} - {rec['reasoning']}")
```
## Validation and Constraints
### Field Validation
```python theme={null}
from pydantic import BaseModel, Field, validator
from typing import List
class FinancialReport(BaseModel):
quarter: str = Field(pattern="^Q[1-4] 20[0-9]{2}$")
revenue: float = Field(gt=0, description="Revenue in millions")
expenses: float = Field(gt=0, description="Total expenses in millions")
profit_margin: float = Field(ge=0, le=100, description="Profit margin percentage")
key_metrics: dict
recommendations: List[str] = Field(min_items=1, max_items=10)
@validator('expenses')
def expenses_less_than_revenue(cls, v, values):
if 'revenue' in values and v >= values['revenue']:
raise ValueError('Expenses should be less than revenue for profitable quarter')
return v
agent = Agent(
agent_name="Financial-Reporter",
model_name="claude-sonnet-4-6",
list_base_models=[FinancialReport],
)
report = agent.run(
"Create a financial report for Q4 2024 based on revenue of $100M"
)
```
### Enums and Choices
```python theme={null}
from pydantic import BaseModel, Field
from enum import Enum
from typing import List
class Priority(str, Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
CRITICAL = "critical"
class Status(str, Enum):
TODO = "todo"
IN_PROGRESS = "in_progress"
REVIEW = "review"
DONE = "done"
class Bug(BaseModel):
title: str
description: str
priority: Priority
status: Status
affected_components: List[str]
steps_to_reproduce: List[str]
expected_behavior: str
actual_behavior: str
agent = Agent(
agent_name="Bug-Tracker",
model_name="claude-sonnet-4-6",
list_base_models=[Bug],
output_type="final",
)
result = agent.run(
"""
Create a bug report: Users can't login after the latest update.
Login button is unresponsive on mobile devices.
"""
)
import json
bug = json.loads(result)
print(f"Priority: {bug['priority']}")
print(f"Status: {bug['status']}")
```
## Output Processing
### JSON Output
`output_type="json"` serializes the **entire conversation history** (a list of `{"role", "content", ...}` message dicts) to a JSON string — it does not extract a single task-specific object with your own keys. For a task-specific structured payload, combine `list_base_models`/`tool_schema` with `output_type="final"` and parse the model's final text yourself, as shown below.
```python theme={null}
import json
from pydantic import BaseModel
from typing import List
class LanguageList(BaseModel):
languages: List[str]
agent = Agent(
agent_name="Data-Agent",
model_name="claude-sonnet-4-6",
list_base_models=[LanguageList],
output_type="final", # Return just the model's final text response
)
result = agent.run("List the top 5 programming languages in 2024")
data = json.loads(result)
for lang in data['languages']:
print(f"- {lang}")
```
### Dictionary Output
`output_type="dict"` (or `"dictionary"`) returns the full conversation history as a Python **list** of message dicts, not a single dict keyed by your schema's fields. Index it as `result[-1]["content"]` to get the last message, then parse that content yourself.
```python theme={null}
agent = Agent(
agent_name="Analyzer",
model_name="claude-sonnet-4-6",
output_type="dict",
)
result = agent.run("Analyze sentiment: 'This product is amazing!'")
# result is a list of message dicts; the model's answer is the last one
last_message = result[-1]["content"]
print(last_message)
```
## Working with Responses
### Pydantic Model Response
```python theme={null}
from pydantic import BaseModel
from typing import List
class Article(BaseModel):
title: str
summary: str
key_points: List[str]
word_count: int
agent = Agent(
agent_name="Content-Creator",
model_name="claude-sonnet-4-6",
list_base_models=[Article],
output_type="final",
)
response = agent.run("Write an article about renewable energy")
# `response` is a plain string (the model's final text). If the model
# complied with the Article schema, parse it and validate with Pydantic:
import json
data = json.loads(response)
article = Article(**data)
print(f"Title: {article.title}")
print(f"Summary: {article.summary}")
print(f"Key points: {', '.join(article.key_points)}")
```
### Function Calling Response
When tools are used, responses include function calls:
```python theme={null}
from swarms import Agent
def calculate(expression: str) -> float:
"""Calculate a mathematical expression"""
return eval(expression)
agent = Agent(
agent_name="Calculator",
model_name="claude-sonnet-4-6",
tools=[calculate],
max_loops=2,
)
response = agent.run("What is 25 * 4 + 10?")
# Agent calls the tool and returns the result
print(response)
```
## Best Practices
### 1. Use Descriptive Field Names
```python theme={null}
# Good
class UserProfile(BaseModel):
full_name: str = Field(description="User's full name")
email_address: str = Field(description="Contact email")
# Bad
class UserProfile(BaseModel):
n: str # ❌ Not clear
e: str # ❌ Not clear
```
### 2. Add Field Descriptions
```python theme={null}
class Product(BaseModel):
name: str = Field(description="Product name")
price: float = Field(description="Price in USD", gt=0)
category: str = Field(description="Product category (electronics, clothing, etc.)")
in_stock: bool = Field(description="Whether the product is currently available")
```
### 3. Use Appropriate Constraints
```python theme={null}
class Review(BaseModel):
rating: int = Field(ge=1, le=5, description="Star rating 1-5")
comment: str = Field(min_length=10, max_length=500)
verified_purchase: bool
```
### 4. Provide Examples in Descriptions
```python theme={null}
class Address(BaseModel):
street: str = Field(description="Street address, e.g., '123 Main St'")
city: str = Field(description="City name, e.g., 'San Francisco'")
state: str = Field(description="Two-letter state code, e.g., 'CA'")
zip_code: str = Field(pattern=r"^\d{5}(-\d{4})?$", description="ZIP code, e.g., '94102' or '94102-1234'")
```
## Next Steps
Add tools to extend agent capabilities
Learn how to create agents
## Reference
* Output type formatting: `swarms/utils/history_output_formatter.py`
* Pydantic integration: `swarms/tools/pydantic_to_json.py`
* Tool/list-base-model schema handling: `swarms/structs/agent.py:3059-3087` (`handle_tool_schema_ops`)
# AdvisorSwarm
Source: https://docs.swarms.world/api/advisor-swarm
An executor-advisor swarm that pairs a cheaper executor model with a powerful advisor model consulted on-demand between turns
## Overview
The `AdvisorSwarm` implements the [advisor strategy](https://claude.com/blog/the-advisor-strategy) described in Anthropic's research (April 2026). It pairs a cheaper **executor** model that drives the task end-to-end with a powerful **advisor** model consulted on-demand between executor turns.
The executor runs every turn. The advisor is on-demand -- consulted between executor turns when budget allows. Both agents read from and write to the same shared conversation context. The advisor never calls tools or produces user-facing output.
This is provider-agnostic: any model supported by LiteLLM works for either role.
```mermaid theme={null}
graph TD
A[User Task] --> B[Shared Context]
B --> C{Advisor Budget?}
C -->|Yes| D[Advisor reads context, provides guidance]
D --> B
C -->|No| E[Executor reads context, produces output]
B --> E
E --> B
E --> F{More turns?}
F -->|Yes| C
F -->|No| G[Return Result]
```
The swarm follows this workflow:
1. User task goes into the shared conversation
2. Before each executor turn, the advisor reads the full shared context and provides guidance (if budget allows)
3. The executor reads the full shared context (including any advisor guidance) and produces output
4. Both advisor guidance and executor output are added to the shared conversation
5. Repeat for `max_loops` executor turns
## Installation
```bash theme={null}
pip install -U swarms
```
## Key Features
| Feature | Description |
| ------------------------ | ----------------------------------------------------------------- |
| **Executor-Driven Loop** | The executor runs every turn -- it's the main driver |
| **On-Demand Advisor** | Advisor is consulted between turns, not in a fixed sequence |
| **Shared Context** | Both agents read from and write to the same conversation |
| **Budget Control** | `max_advisor_uses` caps advisor consultations per run |
| **Provider-Agnostic** | Any LiteLLM-supported model works for either role |
| **Custom Agents** | Pass pre-configured agents with tools, MCP, or any Agent settings |
## Attributes
Unique identifier for this swarm instance. Auto-generated via `generate_id("advisor-swarm")` if not provided, producing `advisor-swarm-<32 hex chars>`.
Human-readable name
Description of the swarm's purpose
Model for the executor agent
Model for the advisor agent
System prompt for the executor
System prompt for the advisor
Max advisor consultations per `run()`. 0 = executor runs alone.
Number of executor turns
Format for output (dict, str, list, final, json, yaml)
Enable detailed logging
Pre-configured Agent for execution (e.g., with tools or MCP)
Pre-configured Agent for advising
Tools available to the executor agent only
**Raises:**
| Exception | Condition |
| ------------ | -------------------------------------------------------------------- |
| `ValueError` | If `max_advisor_uses < 0`, `max_loops < 1`, or model names are empty |
## Methods
### run()
Execute the advisor-executor orchestration flow.
```python theme={null}
def run(self, task: str, img: str = None, imgs: List[str] = None) -> Any
```
**Parameters:**
* `task` (str): The task to accomplish
* `img` (str, optional): Optional single image input
* `imgs` (List\[str], optional): Optional list of image inputs
**Returns:** Formatted conversation history according to `output_type`
### batched\_run()
Run the swarm on multiple tasks sequentially.
```python theme={null}
def batched_run(self, tasks: List[str]) -> List[Any]
```
**Parameters:**
* `tasks` (List\[str]): List of task strings
**Returns:** List of results, one per task
## Usage Examples
### Basic Usage
```python theme={null}
from swarms import AdvisorSwarm
swarm = AdvisorSwarm(
executor_model_name="claude-sonnet-4-6",
advisor_model_name="claude-opus-4-6",
max_advisor_uses=3,
max_loops=1,
verbose=True,
)
result = swarm.run(
"Write a Python function that implements binary search on a sorted list. "
"Include proper error handling, type hints, and edge cases."
)
print(result)
```
### Multi-Turn with Advisor Guidance
Run the executor for multiple turns, with the advisor providing guidance before each:
```python theme={null}
from swarms import AdvisorSwarm
swarm = AdvisorSwarm(
executor_model_name="claude-sonnet-4-6",
advisor_model_name="claude-opus-4-6",
max_advisor_uses=3,
max_loops=3,
)
result = swarm.run("Design and implement a REST API rate limiter in Python")
```
### Custom Executor with Tools
Pass a pre-configured executor agent with tools while keeping the advisor tool-free:
```python theme={null}
from swarms import Agent, AdvisorSwarm
def write_file(filename: str, content: str) -> str:
"""Write content to a file."""
with open(filename, "w") as f:
f.write(content)
return f"Written: {filename}"
executor = Agent(
agent_name="Executor",
model_name="claude-sonnet-4-6",
max_loops=1,
tools=[write_file],
)
swarm = AdvisorSwarm(
executor_agent=executor,
advisor_model_name="claude-opus-4-6",
)
result = swarm.run("Create a Python module for string manipulation utilities")
```
### Executor Only (No Advisor)
Set `max_advisor_uses=0` to run the executor alone:
```python theme={null}
from swarms import AdvisorSwarm
swarm = AdvisorSwarm(
executor_model_name="claude-sonnet-4-6",
advisor_model_name="claude-opus-4-6",
max_advisor_uses=0,
max_loops=1,
)
result = swarm.run("Simple task that doesn't need advisor guidance")
```
### Different Providers
The swarm is provider-agnostic. Use any models LiteLLM supports:
```python theme={null}
from swarms import AdvisorSwarm
# OpenAI models
swarm = AdvisorSwarm(
executor_model_name="gpt-5.4-mini",
advisor_model_name="gpt-5.4",
)
# Mix providers
swarm = AdvisorSwarm(
executor_model_name="gpt-5.4-mini",
advisor_model_name="claude-opus-4-6",
)
```
## Architecture Details
### Shared Context
Both agents read from and write to the same `Conversation` object. This mirrors the Anthropic diagram where the advisor reads the same context as the executor. On each turn:
1. The advisor reads `conversation.get_str()` -- sees everything so far
2. The advisor's guidance is added to the conversation
3. The executor reads `conversation.get_str()` -- sees the task, any prior output, and the advisor's guidance
4. The executor's output is added to the conversation
### Advisor Budget
The `max_advisor_uses` parameter controls how many times the advisor is consulted:
| `max_advisor_uses` | `max_loops` | Behavior |
| ------------------ | ----------- | ----------------------------------------------------- |
| `0` | `1` | Executor runs alone -- no advisor |
| `1` | `1` | Advisor guides once, executor runs once |
| `3` | `3` | Advisor guides before each of 3 executor turns |
| `1` | `3` | Advisor guides first turn only, executor runs 3 turns |
### Multi-Turn Execution
When `max_loops > 1`, the executor runs multiple turns. Each turn, it reads the full conversation -- including its own previous output and any advisor guidance -- so it can build on prior work. The advisor's budget is distributed across turns: it is consulted before each executor turn until the budget is exhausted.
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/advisor_swarm.py)
# Agent
Source: https://docs.swarms.world/api/agent
The core Agent class for building autonomous AI agents with tools, memory, and multi-modal capabilities
## Overview
The `Agent` class is the core component of the Swarms framework, connecting LLMs with tools, long-term memory, and advanced autonomous capabilities. It provides a production-ready interface for building intelligent agents that can reason, use tools, handle multimodal inputs, and execute complex tasks. The class is designed to handle a variety of document types—including PDFs, text files, Markdown, and JSON—enabling robust document ingestion and processing.
```mermaid theme={null}
graph TD
A[Task Initiation] -->|Receives Task| B[Initial LLM Processing]
B -->|Interprets Task| C[Tool Usage]
C -->|Calls Tools| D[Function 1]
C -->|Calls Tools| E[Function 2]
D -->|Returns Data| C
E -->|Returns Data| C
C -->|Provides Data| F[Memory Interaction]
F -->|Stores and Retrieves Data| G[RAG System]
G -->|Vector Store / Retriever| H[Enhanced Data]
F -->|Provides Enhanced Data| I[Final LLM Processing]
I -->|Generates Final Response| J[Output]
C -->|No Tools Available| K[Skip Tool Usage]
K -->|Proceeds to Memory Interaction| F
F -->|No Memory Available| L[Skip Memory Interaction]
L -->|Proceeds to Final LLM Processing| I
```
| Feature | Description |
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Conversational Loop** | Enables back-and-forth interaction with the model. |
| **Feedback Collection** | Allows users to provide feedback on generated responses. |
| **Stoppable Conversation** | Supports custom stopping conditions for the conversation. |
| **Retry Mechanism** | Implements a retry system for handling issues in response generation. |
| **Tool Integration** | Supports the integration of various tools for enhanced capabilities. |
| **Long-term Memory Management** | Incorporates vector databases for efficient information retrieval. |
| **Document Ingestion** | Processes various document types for information extraction. |
| **Interactive Mode** | Allows real-time communication with the agent. |
| **Sentiment Analysis** | Evaluates the sentiment of generated responses. |
| **Output Filtering and Cleaning** | Ensures generated responses meet specific criteria. |
| **Asynchronous and Concurrent Execution** | Supports efficient parallelization of tasks. |
| **Planning and Reasoning** | Implements planning functionality for enhanced decision-making. |
| **Autonomous Planning and Execution** | When `max_loops="auto"`, automatically creates plans, executes subtasks, and generates summaries. Includes built-in tools for file operations, user communication, and workspace management. |
| **Agent Handoffs and Task Delegation** | Intelligently routes tasks to specialized agents based on capabilities and task requirements. |
## Import
```python theme={null}
from swarms import Agent
```
## Key Features
* **Tool Integration**: Native support for function calling and tool execution
* **Long-term Memory**: RAG-based memory system for context retention
* **Autonomous Loops**: Dynamic execution with configurable stopping conditions
* **Multi-modal Support**: Process text, images, and other media
* **MCP Support**: Integration with Model Context Protocol servers
* **Agent Handoffs**: Delegate tasks to specialized agents
* **Streaming**: Real-time token streaming with callbacks
* **Fallback Models**: Automatic failover to backup models
* **State Management**: Autosave and state persistence
* **Telemetry**: Optional OpenTelemetry tracing of every run
## Architecture
`Agent` delegates its larger subsystems to dedicated collaborator objects, each built during `__init__` and reachable as an attribute. The agent's own methods are thin wrappers over them, so both call styles work and neither is deprecated.
| Attribute | Class | Owns |
| ------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `agent.llm_manager` | [`LLMManager`](/api/llm-manager) | Model selection, LiteLLM construction, invocation, streaming, fallback rotation |
| `agent.mcp_manager` | [`MCPManager`](/api/mcp-manager) | MCP server connections, tool discovery, tool-call routing |
| `agent.skills` | [`SkillsManager`](/api/skills-manager) | Agent Skills discovery and prompt rendering |
| `agent.marketplace` | [`AgentMarketplaceHandler`](/api/agent-marketplace-handler) | Fetching and publishing marketplace prompts |
```python theme={null}
agent = Agent(agent_name="Analyst", model_name="gpt-5.4-mini")
# These are equivalent
agent.get_current_model()
agent.llm_manager.get_current_model()
```
Each collaborator is independently usable and independently documented — reach for them directly when you want the behavior without an agent around it.
## Initialization
Unique identifier for the agent instance. When omitted the agent generates one via `generate_id("agent")`, of the form `agent-` followed by 32 hex characters (`secrets.token_hex(16)`) — not a UUID.
The name of the agent, used for identification and logging. Omit it and the
agent defaults to the literal `"swarm-worker-01"` — every agent that does
not set a name shares this same value.
Because the default is a shared literal rather than a generated value,
anything keyed on `agent_name` collides across unnamed agents: concurrent
result dictionaries keep one entry for the whole group, and `MEMORY.md`
folders are shared. Pass an explicit name whenever agents run
concurrently or need memory to be stable across restarts.
A description of the agent's purpose and capabilities. Shown to orchestrators when routing tasks.
The system prompt that defines the agent's behavior and personality. Defaults to the framework's general-purpose `AGENT_SYSTEM_PROMPT_3` rather than an empty prompt.
The language model instance to use. If None, a LiteLLM instance will be created
The LiteLLM-compatible model identifier (e.g. `"gpt-5.4"`, `"claude-sonnet-4-6"`, `"groq/llama-3.3-70b-versatile"`).
Extra keyword arguments forwarded to the underlying LiteLLM client.
Enable provider-side prompt caching. When `True`, ephemeral `cache_control` breakpoints are added to the stable prefix of each request (system prompt, tools, and the last message) so it is cached and re-billed at a large discount. Applies to the Anthropic model family (Claude on Anthropic / Bedrock / Vertex); providers that cache automatically (e.g. OpenAI) are left untouched. See the [Prompt Caching guide](/agents/prompt-caching).
Fine-grained prompt-caching options; only consulted when `prompt_caching=True`. All keys optional:
* `ttl` (`str`): `"5m"` (default) or `"1h"` for Anthropic's extended cache (2x write cost, survives longer gaps; the required beta header is attached automatically).
* `cache_system_prompt` (`bool`, default `True`): cache the system prefix.
* `cache_messages` (`bool`, default `True`): cache through the last message (incremental multi-turn caching).
* `cache_tools` (`bool`, default `True`): cache the tool-definitions block.
* `override` (`bool`, default `None`): force `cache_control` injection on/off regardless of the detected provider (e.g. opt Gemini/Vertex in, or a custom alias out). `None` auto-detects (Anthropic only).
* `prompt_cache_key` (`str`): OpenAI-only routing hint for higher cache hit rates.
* `prompt_cache_retention` (`str`): OpenAI-only cache TTL — `"in_memory"` or `"24h"`.
Base URL for OpenAI-compatible providers (Ollama, LM Studio, vLLM, etc.).
Override API key for the LLM provider. Falls back to environment variables when unset.
Single fallback model used when the primary model fails.
Maximum number of reasoning loops. Use "auto" for autonomous mode with dynamic planning
List of callable functions that the agent can use as tools
Temperature for LLM sampling (0.0 to 1.0)
Maximum number of tokens in the LLM response. A positive value you pass is kept and forwarded to the LLM. Leave it as `None` (or pass `0`/a negative number) and the agent resolves the model's own maximum output-token limit, falling back to `16000` when that lookup fails.
Effective context window in tokens. When `context_compression=True`, the agent compresses memory once usage crosses 90% of this limit. Leave as `None` to derive the window from the model.
Nucleus-sampling parameter. Stripped automatically for Anthropic models when extended thinking is enabled.
Allow the framework to grow/shrink the per-call context budget based on token usage signals.
When `True`, the agent runs a `ContextCompressor` that summarises long histories at 90% of `context_length` so long sessions never hit the context wall.
When `True`, read/write `MEMORY.md` under the workspace so agent state survives process restarts. Off by default: opt in explicitly for agents that should remember across runs.
Optional pre/post-processing transforms applied to the conversation history.
Enable basic streaming with formatted panels
Enable detailed token-by-token streaming with metadata (citations, tokens used, etc.)
Callback function to receive streaming tokens in real-time. Use with `agent.run_stream` / `agent.arun_stream` for generator-style consumption.
Enable interactive mode (REPL-style) — prompt the user for input between loops.
Enable verbose logging for debugging.
When `False`, suppress the agent's printed output (Rich panels, thinking panel, etc.). Token streams via `arun_stream` / `streaming_callback` are unaffected.
How the run's result is formatted. See [Output Types](#output-types) for all 17 accepted values.
Automatically save agent state during execution
Display agent dashboard on initialization
A store that is written out with agent state. The agent never queries it — only `.save(path)` is ever called on it, so this does not provide RAG. For retrieval, expose the lookup as a tool instead.
List of fallback models to try in order if the primary model fails.
Number of retry attempts for LLM calls
Token that signals the agent to stop execution
Function that returns True when the agent should stop
Alternative stopping function
Enable dynamic temperature adjustment during execution
Enable dynamic loop count adjustment (sets max\_loops="auto")
Seconds to wait between consecutive loop iterations.
Token the user can type in interactive mode to exit the loop.
When `True`, append the framework's preset stopping marker to the system prompt.
Auto-generate a system prompt from the task description when one is not provided.
Name of the user in conversation history
Path that `save()` writes to when called with no argument. When unset, falls back to an auto-generated `{api_key}_state.json` filename inside the agent workspace.
Standard operating procedure for the agent
List of standard operating procedures
Rules that govern agent behavior
Prompt for planning phase
Enable planning phase before execution
Enable multi-modal processing (images, etc.).
After every tool call, run a brief LLM summary of the tool result and add it to the conversation.
Number of times to retry a failing tool call before giving up.
Display tool inputs/outputs in the agent's printed output.
Pre-built OpenAI function-calling tool schemas. Use when you want to bypass the auto-generated schema.
Override tool schema used at runtime.
Optional post-processor applied to the agent's output before returning.
Pydantic models registered for structured-output prompting.
A single MCP server. Pass a URL string for an unauthenticated server, or an `MCPConnection`/dict to configure auth, transport, headers and timeouts.
Several MCP servers. Each entry may be a URL string, an `MCPConnection`, or a dict. Tools from every server are merged and each tool call is routed back to the server that owns it.
A single MCP server given as a connection object (or the equivalent dict).
Several MCP servers given as connection objects (or dicts).
API key applied to every MCP server that does not define its own. Sent as `Authorization: Bearer ` by default; override the header or prefix per-server with `MCPConnection(api_key_header=..., api_key_prefix=...)`. Supports `"env:MY_VAR"` / `"${MY_VAR}"` indirection so secrets stay out of code.
Bearer token applied to every MCP server that does not define its own. Equivalent to `mcp_api_key` with the default header and prefix.
OAuth 2.1 settings applied to every MCP server without its own. Supports the interactive authorization-code flow (PKCE plus dynamic client registration, tokens cached on disk), the headless `client_credentials` grant, and pre-issued access tokens.
Extra headers merged into every MCP request.
Force a transport for every MCP server. `None` auto-detects from the URL.
Request timeout in seconds for every MCP server. Falls back to the per-connection default of 30.
List of agents to enable task handoffs/delegation
Free-form list of agent capabilities used for routing and documentation.
The agent's role within a swarm (e.g. `"worker"`, `"director"`).
Tags used to filter or categorise the agent.
Structured list of intended use cases for documentation/marketplace listings.
Execution mode: `interactive` (REPL), `fast` (minimal logging/decoration), or `standard`.
UUID of a prompt from the Swarms marketplace to use as the system prompt.
When `True`, publish this agent to the Swarms marketplace on initialization.
Path to a directory of Agent Skills (Anthropic `SKILL.md` format).
Tools to enable for the autonomous looper when `max_loops="auto"`. Use `"all"`, or a list of tool names — the list filters the **entire** loop tool set, control-flow tools included, so include `create_plan` and `complete_task` unless you intend to remove them. `agent.get_all_selected_tools()` returns every valid name.
Give the autonomous looper (`max_loops="auto"`) a `think` tool for an explicit reasoning turn. Off by default: it costs a full round-trip to produce reasoning most models can emit inline alongside their actions. When `False` the system prompt is adjusted to match, so the model is never told to call a tool it does not have.
Defer tool schemas behind a `tool_search` tool instead of sending them all on every request. See [Dynamic Tool Loading](#dynamic-tool-loading) below.
Enable ReAct-style reasoning prompting.
Whether to prepend the framework's reasoning preamble to the system prompt.
Enable reasoning mode for supported models (e.g. o1, o3, Claude with extended thinking).
Effort level for reasoning models: `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`, `"ultra"`, `"max"`, or `"none"`.
Left unset, the parameter is not sent to the provider at all.
Do not combine `reasoning_effort` with `tools` on OpenAI reasoning models such as `gpt-5.4-mini`. `/v1/chat/completions` rejects the pair with `BadRequestError: Function tools with reasoning_effort are not supported`. This is why the default is `None`: it previously defaulted to `"medium"`, which shipped on every request and made `Agent(model_name="gpt-5.4-mini", tools=[...])` fail out of the box.
Maximum extended-thinking budget for Claude reasoning models.
Prepend the framework's safety preamble to the system prompt.
Randomly select from a pool of models on each call (load-balancing/experimentation).
Not a constructor argument — any value passed here is ignored. The workspace root is read from the `WORKSPACE_DIR` environment variable; set it explicitly (e.g. via a `.env` file — `.env.example` uses `agent_workspace`). When it is unset, `agent.workspace_dir` resolves to `None` and an error is logged; the workspace manager behind `agent.workspace` then falls back to `{cwd}/agent_workspace` the first time it needs a directory. Each agent gets its own subdirectory at `{workspace}/agents/{agent-name}-{id12}/`, where `id12` is the last 12 characters of `agent.id`. Read the resolved path from `agent.workspace.dir`.
Path from which to load saved agent state on init.
## Methods
### run
Execute the agent's main loop for a given task.
```python theme={null}
def run(
task: Optional[Union[str, Any]] = None,
img: Optional[str] = None,
imgs: Optional[List[str]] = None,
correct_answer: Optional[str] = None,
streaming_callback: Optional[Callable[[str], None]] = None,
n: int = 1,
*args,
**kwargs
) -> Any
```
The task or prompt for the agent to process
Optional image path or data for vision-enabled models
Optional list of image paths for batch processing
Expected correct answer for validation with automatic retries
Callback function to receive streaming tokens in real-time
Number of times to run the task. When `n > 1`, `run` recursively calls itself `n` times and returns a list of results.
Prior conversation as typed chat turns. When given, these replace the transcript
the agent would otherwise derive from its own memory, and `task` is appended as
the new user turn. Multi-agent structures use this to hand an agent the shared
room with roles intact — the agent's own turns as `assistant`, everyone else's
as labelled `user` turns — instead of one flattened string.
```python theme={null}
agent.run(
task="What did the analyst conclude?",
messages=[
{"role": "user", "content": "Summarise the Q3 numbers."},
{"role": "assistant", "content": "Revenue rose 12%."},
{"role": "user", "content": "Analyst: margins are the risk."},
],
)
```
Agent output formatted according to output\_type configuration
**Return types based on input:**
| Scenario | Return Type | Description |
| ----------------- | ----------- | ------------------------------------------------------- |
| Single task | `str` | Returns the agent's response |
| Multiple images | `List[Any]` | Returns a list of results, one for each image |
| Answer validation | `str` | Returns the correct answer as a string |
| Streaming | `str` | Returns the complete response after streaming completes |
**Examples:**
```python theme={null}
# Basic usage
response = agent.run("Generate a report on financial performance.")
# Single image processing
response = agent.run(
task="Analyze this image and describe what you see",
img="path/to/image.jpg"
)
# Multiple image processing
response = agent.run(
task="Analyze these images and identify common patterns",
imgs=["image1.jpg", "image2.png", "image3.jpeg"]
)
# Answer validation with retries
response = agent.run(
task="What is the capital of France?",
correct_answer="Paris"
)
# Real-time streaming
def streaming_callback(token: str):
print(token, end="", flush=True)
response = agent.run(
task="Tell me a long story about space exploration",
streaming_callback=streaming_callback
)
```
### **call**
Alternative syntax for running the agent (calls `run` internally).
```python theme={null}
def __call__(
task: Optional[str] = None,
img: Optional[str] = None,
*args,
**kwargs
) -> Any
```
### arun
Async version of `run`.
```python theme={null}
async def arun(
task: Optional[str] = None,
img: Optional[str] = None,
*args,
**kwargs,
) -> Any
```
### run\_batched
Run multiple tasks **sequentially**, one after another, and collect the results. For concurrent execution use `run_concurrent_tasks` instead.
```python theme={null}
def run_batched(
tasks: List[str],
imgs: List[str] = None,
*args,
**kwargs,
) -> List[Any]
```
List of tasks to run, in order
One image per task, paired by position. Omit to run the tasks without images. A length mismatch raises `ValueError` rather than silently dropping the extras.
List of results from each task execution, in the same order as the input tasks
```python theme={null}
tasks = [
"Analyze the financial data for Q1",
"Generate a summary report for stakeholders",
"Create recommendations for Q2 planning"
]
batch_results = agent.run_batched(tasks)
for i, (task, result) in enumerate(zip(tasks, batch_results)):
print(f"Task {i+1}: {task}")
print(f"Result: {result}\n")
```
### run\_stream
Run the agent and yield response tokens one-by-one as a sync generator. The full agent loop (multi-step reasoning, tool calls, MCP, autonomous plan/execute/summary) runs in a background daemon thread; tokens are forwarded to the caller the moment the LLM emits them.
```python theme={null}
def run_stream(
task: str,
img: Optional[str] = None,
**kwargs,
) -> Iterator[str]
```
Tool-call results are fed back into the loop automatically — tokens from each subsequent LLM turn (synthesis turn, autonomous summary phase, etc.) are streamed through as well.
```python theme={null}
for token in agent.run_stream("Analyse NVDA"):
print(token, end="", flush=True)
```
### arun\_stream
Async generator version of `run_stream`. The agent loop runs in a thread executor while tokens are forwarded through an `asyncio.Queue`, so the caller's event loop is never blocked.
```python theme={null}
async def arun_stream(
task: str,
img: Optional[str] = None,
**kwargs,
) -> AsyncIterator[str]
```
```python theme={null}
import asyncio
async def main():
async for token in agent.arun_stream("Analyse NVDA"):
print(token, end="", flush=True)
asyncio.run(main())
```
Both `run_stream` and `arun_stream` work for any `max_loops` value (1, integer > 1 with tools, or `"auto"`). They stream tokens through every internal loop, including tool-call turns, synthesis turns after a tool returns, and the autonomous plan/execute/summary cycle.
### run\_concurrent\_tasks
Run a batch of tasks concurrently via a thread pool.
```python theme={null}
def run_concurrent_tasks(
tasks: List[str],
*args,
**kwargs,
) -> List[Any]
```
### bulk\_run
Generate responses for multiple input sets. Each input is a dict of kwargs forwarded to `run`.
```python theme={null}
def bulk_run(
inputs: List[Dict[str, Any]],
) -> List[str]
```
### save
Save the agent's current state to disk.
```python theme={null}
def save(
file_path: str = None
) -> None
```
### load
Load agent state from a saved file (JSON, via `SafeStateManager`). If `file_path` is omitted, falls back to `load_state_path`, then `saved_state_path`, then a path derived from `agent_name`.
```python theme={null}
def load(
file_path: str = None
) -> None
```
### save\_to\_yaml
Save the agent to a YAML file.
```python theme={null}
def save_to_yaml(
file_path: str
) -> None
```
### to\_dict
Convert agent configuration to dictionary.
```python theme={null}
def to_dict() -> Dict[str, Any]
```
### to\_json
Convert agent configuration to JSON string.
```python theme={null}
def to_json(
indent: int = 4
) -> str
```
### to\_yaml
Convert agent configuration to YAML string.
```python theme={null}
def to_yaml(
indent: int = 4
) -> str
```
### to\_toml
Convert agent configuration to TOML string.
```python theme={null}
def to_toml() -> str
```
### model\_dump\_json / model\_dump\_yaml
Save the agent model to a JSON or YAML file in the workspace directory.
```python theme={null}
def model_dump_json() -> None
def model_dump_yaml() -> None
```
### add\_tool / add\_tools
Dynamically add a tool (or list of tools) to the agent at runtime.
```python theme={null}
def add_tool(tool: Callable) -> None
def add_tools(tools: List[Callable]) -> None
```
### remove\_tool / remove\_tools
Remove a previously-registered tool (or list of tools).
```python theme={null}
def remove_tool(tool: Callable) -> None
def remove_tools(tools: List[Callable]) -> None
```
### add\_memory
Append a message to the agent's short-term memory.
```python theme={null}
def add_memory(message: str) -> None
```
### talk\_to
Initiate a conversation with another agent.
```python theme={null}
def talk_to(
agent: Any,
task: str,
img: Optional[str] = None,
*args,
**kwargs
) -> Any
```
### talk\_to\_multiple\_agents
Talk to multiple agents concurrently.
```python theme={null}
def talk_to_multiple_agents(
agents: List[Union[Any, Callable]],
task: str,
*args,
**kwargs
) -> Any
```
Returns one entry per agent, in the order the agents were given. An agent whose conversation raised contributes `None`.
### receive\_message / send\_agent\_message
`receive_message` wraps an incoming message from another agent in a short preamble and runs it through the agent's normal `run()` loop, returning the agent's response. `send_agent_message` prefixes a message with `To: {agent_name}:` and runs that through `run()`, returning the result.
```python theme={null}
def receive_message(agent_name: str, task: str, *args, **kwargs) -> Any
def send_agent_message(agent_name: str, message: str, *args, **kwargs) -> str
```
Task delegation via `handoffs` happens automatically inside `run()` — the LLM calls an internal handoff tool when it decides to delegate. There is no separate public `handle_handoffs()` method to call directly.
### reset
Drop the agent's short-term memory by setting `agent.short_memory = None`. Nothing is re-initialized in its place.
```python theme={null}
def reset() -> None
```
After `reset()` the agent cannot run again until `short_memory` is replaced with a fresh `Conversation`. Construct a new agent instead unless you intend to rebuild it yourself.
### plan
Run only the planning phase for a task without executing.
```python theme={null}
def plan(task: str, *args, **kwargs) -> None
```
### print\_dashboard
Display the agent's configuration dashboard.
```python theme={null}
def print_dashboard() -> None
```
### showcase\_config
Display the agent's configuration in a formatted table.
```python theme={null}
def showcase_config() -> None
```
### update\_system\_prompt / update\_max\_loops / update\_loop\_interval
In-place setters for runtime reconfiguration.
```python theme={null}
def update_system_prompt(system_prompt: str) -> None
def update_max_loops(max_loops: Union[int, str]) -> None
def update_loop_interval(loop_interval: int) -> None
```
### Tool Management
Methods backing dynamic tool loading and MCP tool discovery. See [Dynamic Tool Loading](#dynamic-tool-loading).
```python theme={null}
def setup_dynamic_tools(always_loaded: Optional[List[dict]] = None) -> DynamicToolLoader
def defer_tool_schemas(schemas: List[dict]) -> None
def defer_mcp_tools() -> int
def add_mcp_tools_to_memory() -> List[Dict[str, Any]]
def get_all_selected_tools() -> List[str]
```
| Method | Behaviour |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setup_dynamic_tools(always_loaded)` | Rebuild the agent's [`DynamicToolLoader`](/api/dynamic-tool-loader), deferring its tool schemas behind `tool_search`. Schemas in `always_loaded` are never deferred — control-flow tools belong there, since an agent that has to search for its own `complete_task` cannot finish. Schemas already registered (handoff tools, MCP tools) are preserved. Runs automatically during `__init__` when `dynamic_tools` applies. Returns the loader, also stored on `agent.tool_loader`. |
| `defer_tool_schemas(schemas)` | Add pre-built OpenAI function-calling schemas to the deferred catalog. No-op when no loader is active. |
| `defer_mcp_tools()` | Move this agent's MCP tool schemas into the deferred catalog and return how many were added. The fetch is a network call and runs once per agent. |
| `add_mcp_tools_to_memory()` | Fetch the tool schemas exposed by the configured MCP servers, as OpenAI function-calling definitions. Connections, authentication, and transport selection are delegated to [`MCPManager`](/api/mcp-manager). |
| `get_all_selected_tools()` | Every autonomous-loop tool name, e.g. `["create_plan", "think", "subtask_done", ...]`. Build a `selected_tools` list from this instead of hardcoding names. |
Two related properties:
| Property | Type | Value |
| ------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `agent.workspace` | `WorkspaceManager` | The agent's workspace manager, created on first access and rooted at `{workspace}/agents/{name}-{id12}`. Read the resolved path from `agent.workspace.dir`. |
| `agent.mcp_enabled` | `bool` | Whether at least one MCP server is configured. Backed by [`MCPManager`](/api/mcp-manager), which normalizes `mcp_url`, `mcp_urls`, `mcp_config`, and `mcp_configs` into one list of connections. |
### get\_llm\_parameters
Returns the parameters of the language model as a string (`str(vars(self.llm))`).
```python theme={null}
def get_llm_parameters() -> str
```
### Fallback Model Helpers
Methods backing the `fallback_models` / `fallback_model_name` feature. All delegate to [`LLMManager`](/api/llm-manager).
```python theme={null}
def get_available_models() -> List[str]
def get_current_model() -> str
def switch_to_next_model() -> bool
def reset_model_index() -> None
def is_fallback_available() -> bool
```
### Skills Helpers
Agent Skills loading, delegating to [`SkillsManager`](/api/skills-manager).
```python theme={null}
def handle_skills(task: Optional[str] = None) -> None # append skills to the system prompt
def load_skills_metadata(skills_dir: str = None) -> List[Dict[str, str]]
def load_full_skill(skill_name: str) -> Optional[str]
```
`agent.skills_dir` and `agent.skills_metadata` are properties that read and write through to the manager.
### Marketplace Helpers
Marketplace integration, delegating to [`AgentMarketplaceHandler`](/api/agent-marketplace-handler).
```python theme={null}
def handle_publish_to_marketplace() -> Dict[str, Any] # requires use_cases
```
Setting `marketplace_prompt_id` loads a prompt during construction; setting `publish_to_marketplace=True` publishes during construction.
### Complete Methods Reference
| Method | Description | Usage Example |
| ----------------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------- |
| `run(task, img, imgs, correct_answer, streaming_callback, n, messages)` | Run the autonomous agent loop | `agent.run("Generate a report")` |
| `run_batched(tasks, imgs)` | Run multiple tasks sequentially | `agent.run_batched(["Task 1", "Task 2"])` |
| `__call__(task, img)` | Alternative way to call `run` | `agent("Generate a report")` |
| `arun(task, img)` | Async version of `run` | `await agent.arun("Task")` |
| `run_stream(task, img)` | Sync streaming generator | `for t in agent.run_stream("Task"): ...` |
| `arun_stream(task, img)` | Async streaming generator | `async for t in agent.arun_stream("Task"): ...` |
| `run_concurrent_tasks(tasks)` | Run multiple tasks concurrently | `agent.run_concurrent_tasks(["T1", "T2"])` |
| `bulk_run(inputs)` | Generate responses for multiple inputs | `agent.bulk_run([{"task": "T1"}])` |
| `tool_execution_retry(response, loop_count)` | Execute tools with retry logic | `agent.tool_execution_retry(response, 1)` |
| `add_memory(message)` | Add message to memory | `agent.add_memory("Important info")` |
| `plan(task)` | Plan task execution | `agent.plan("Analyze trends")` |
| `save(file_path)` | Save agent state to JSON | `agent.save("state.json")` |
| `load(file_path)` | Load agent state from JSON | `agent.load("state.json")` |
| `save_to_yaml(file_path)` | Save to YAML | `agent.save_to_yaml("config.yaml")` |
| `to_dict()` | Convert to dictionary | `agent.to_dict()` |
| `to_json(indent)` | Convert to JSON string | `agent.to_json()` |
| `to_yaml(indent)` | Convert to YAML string | `agent.to_yaml()` |
| `to_toml()` | Convert to TOML string | `agent.to_toml()` |
| `model_dump_json()` | Save model to JSON file | `agent.model_dump_json()` |
| `model_dump_yaml()` | Save model to YAML file | `agent.model_dump_yaml()` |
| `add_tool(tool)` | Add a tool | `agent.add_tool(my_tool)` |
| `add_tools(tools)` | Add multiple tools | `agent.add_tools([t1, t2])` |
| `remove_tool(tool)` | Remove a tool | `agent.remove_tool(my_tool)` |
| `remove_tools(tools)` | Remove multiple tools | `agent.remove_tools([t1, t2])` |
| `talk_to(agent, task)` | Talk to another agent | `agent.talk_to(other, "Collaborate")` |
| `talk_to_multiple_agents(agents, task)` | Talk to multiple agents | `agent.talk_to_multiple_agents([a1], "Task")` |
| `receive_message(agent_name, task)` | Run a message received from another agent through `run()` | `agent.receive_message("User", "Hello")` |
| `send_agent_message(agent_name, message)` | Send a message | `agent.send_agent_message("AgentX", "Done")` |
| `update_system_prompt(prompt)` | Update system prompt | `agent.update_system_prompt("New prompt")` |
| `update_max_loops(max_loops)` | Update max loops | `agent.update_max_loops(5)` |
| `reset()` | Drop short-term memory (leaves the agent unusable until rebuilt) | `agent.reset()` |
| `print_dashboard()` | Display dashboard | `agent.print_dashboard()` |
| `showcase_config()` | Display config table | `agent.showcase_config()` |
| `get_llm_parameters()` | Get LLM parameters (as a string) | `agent.get_llm_parameters()` |
| `get_available_models()` | List primary + fallback model names | `agent.get_available_models()` |
| `get_current_model()` | Get the model currently in use | `agent.get_current_model()` |
| `switch_to_next_model()` | Switch to the next fallback model | `agent.switch_to_next_model()` |
| `reset_model_index()` | Reset back to the primary model | `agent.reset_model_index()` |
| `is_fallback_available()` | Whether more than one model is configured | `agent.is_fallback_available()` |
| `check_available_tokens()` | Check available tokens | `agent.check_available_tokens()` |
| `pretty_print(response, loop_count)` | Print formatted response | `agent.pretty_print("Done", 1)` |
| `call_llm(task)` | Call the language model | `agent.call_llm("Generate text")` |
| `execute_tools(response, loop_count)` | Execute tools from response | `agent.execute_tools(response, 1)` |
| `list_output_types()` | List available output types | `agent.list_output_types()` |
| `update_loop_interval(interval)` | Update loop interval | `agent.update_loop_interval(2)` |
| `handle_tool_schema_ops()` | Handle tool schema operations | `agent.handle_tool_schema_ops()` |
| `handle_sop_ops()` | Handle SOP operations | `agent.handle_sop_ops()` |
| `mcp_tool_handling(response, current_loop)` | Handle MCP tool execution | `agent.mcp_tool_handling(response, 1)` |
| `parse_llm_output(response)` | Parse and standardize LLM output | `agent.parse_llm_output(llm_output)` |
| `check_if_no_prompt_then_autogenerate(task)` | Auto-generate prompt if none set | `agent.check_if_no_prompt_then_autogenerate("Task")` |
| `output_cleaner_op(response)` | Apply output cleaning operations | `agent.output_cleaner_op(response)` |
| `stream_response(response, delay)` | Stream response token by token | `agent.stream_response("Response", 0.001)` |
| `temp_llm_instance_for_tool_summary()` | Create temp LLM for tool summaries | `agent.temp_llm_instance_for_tool_summary()` |
| `load_skills_metadata(skills_dir)` | Load Agent Skills metadata | `agent.load_skills_metadata("./skills")` |
| `load_full_skill(skill_name)` | Load complete skill content | `agent.load_full_skill("my-skill")` |
| `setup_dynamic_tools(always_loaded)` | Defer tool schemas behind `tool_search` | `agent.setup_dynamic_tools()` |
| `defer_tool_schemas(schemas)` | Add pre-built schemas to the deferred catalog | `agent.defer_tool_schemas(schemas)` |
| `defer_mcp_tools()` | Move MCP tool schemas into the deferred catalog | `agent.defer_mcp_tools()` |
| `add_mcp_tools_to_memory()` | Fetch tool schemas from the configured MCP servers | `agent.add_mcp_tools_to_memory()` |
| `get_all_selected_tools()` | List every autonomous-loop tool name | `agent.get_all_selected_tools()` |
## Advanced Capabilities
### Tool Integration
The `Agent` class allows seamless integration of external tools by accepting a list of Python functions via the `tools` parameter. Each tool function must include type annotations and a docstring. The agent automatically converts these functions into an OpenAI-compatible function calling schema.
| Requirement | Description |
| -------------------- | -------------------------------------------------------------- |
| Function | The tool must be a Python function. |
| With types | The function must have type annotations for its parameters. |
| With doc strings | The function must include a docstring describing its behavior. |
| Must return a string | The function must return a string value. |
```python theme={null}
from swarms import Agent
import subprocess
def terminal(code: str):
"""
Run code in the terminal.
Args:
code (str): The code to run in the terminal.
Returns:
str: The output of the code.
"""
out = subprocess.run(code, shell=True, capture_output=True, text=True).stdout
return str(out)
agent = Agent(
agent_name="Terminal-Agent",
model_name="claude-sonnet-4-6",
tools=[terminal],
system_prompt="You are an agent that can execute terminal commands.",
)
response = agent.run("List the contents of the current directory")
print(response)
```
You can also provide tool schemas in OpenAI function-calling dictionary format via `tools_list_dictionary`:
```python theme={null}
from swarms import Agent
from swarms.prompts.finance_agent_sys_prompt import FINANCIAL_AGENT_SYS_PROMPT
from swarms.utils.str_to_dict import str_to_dict
tools = [
{
"type": "function",
"function": {
"name": "get_stock_price",
"description": "Retrieve the current stock price for a specified company.",
"parameters": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "The stock ticker symbol, e.g. AAPL for Apple Inc.",
},
"include_history": {
"type": "boolean",
"description": "Whether to include historical price data.",
},
"time": {
"type": "string",
"format": "date-time",
"description": "Time for which stock data is requested, in ISO 8601 format.",
},
},
"required": ["ticker", "include_history", "time"],
},
},
}
]
agent = Agent(
agent_name="Financial-Analysis-Agent",
agent_description="Personal finance advisor agent",
system_prompt=FINANCIAL_AGENT_SYS_PROMPT,
max_loops=1,
tools_list_dictionary=tools,
)
out = agent.run("What is the current stock price for Apple Inc. (AAPL)?")
print(out)
print(str_to_dict(out))
```
### Dynamic Tool Loading
`dynamic_tools=True` is the default, and it changes how tools reach the model.
Tool definitions are re-sent on every request, so a large tool set is paid for on every turn. When `dynamic_tools` is on **and** the agent has something to defer — that is, when `tools` are given, an MCP server is configured, or `max_loops="auto"` — the agent:
1. Appends a notice to the system prompt telling the model that most of its tools are **not** currently loaded.
2. Sends only a `tool_search` tool (plus anything marked always-loaded, such as the autonomous loop's control-flow tools) instead of the full schema list.
3. Loads the schemas the model asks for through `tool_search`. **They become callable on the next turn, not the one that searched.**
An agent with no tools, no MCP server, and a fixed `max_loops` has nothing to defer, so nothing changes.
```python theme={null}
from swarms import Agent
# Default: schemas are deferred behind tool_search
agent = Agent(
agent_name="Toolsmith",
model_name="gpt-5.4",
tools=[search_web, read_file, write_file],
)
# Opt out: send every schema on every request
eager_agent = Agent(
agent_name="Eager-Toolsmith",
model_name="gpt-5.4",
tools=[search_web, read_file, write_file],
dynamic_tools=False,
)
```
Deferral is a separate mechanism from `selected_tools`. `selected_tools` decides which autonomous-loop tools exist at all; `dynamic_tools` decides which of the existing schemas are sent up front.
See the [Dynamic Tools guide](/agents/dynamic-tools) and the [DynamicToolLoader reference](/api/dynamic-tool-loader) for the search behaviour, pre-warming, and the always-loaded set.
### External Knowledge and Retrieval
Swarms bundles no vector database, and `Agent` performs no retrieval of its own. To give an agent access to an external knowledge base, expose the lookup as a **tool** — the agent then decides when to query it and the result enters the conversation like any other tool output.
```python theme={null}
from swarms import Agent
def search_knowledge_base(query: str) -> str:
"""Search the company knowledge base for passages matching a query.
Args:
query: What to search for.
Returns:
The matching passages, as text.
"""
# Call whatever store you already run - Chroma, Qdrant, Pinecone, Postgres.
hits = my_vector_store.query(query, top_k=3)
return "\n\n".join(h.text for h in hits)
agent = Agent(
agent_name="Financial-Analysis-Agent",
model_name="claude-sonnet-4-6",
system_prompt="You answer using the company knowledge base.",
tools=[search_knowledge_base],
max_loops=3,
)
response = agent.run("What are the components of a startup's stock incentive equity plan?")
print(response)
```
`long_term_memory` is a constructor parameter, but the agent never queries it. The only method invoked on it is `.save(path)`, and only when agent state is written to disk. Passing a vector store here does **not** give the agent retrieval — use a tool, as above.
### Memory Persistence and Context Compression
The agent ships with two complementary memory controls that work together to manage what is remembered between runs and how the context window is managed during long sessions.
#### Persistent Memory
With `persistent_memory=True` the agent reads and writes a `MEMORY.md` file under `$WORKSPACE_DIR/agents/{agent_name}/MEMORY.md`. Every message is appended to this file, and on the next run the file is loaded back so the agent remembers prior interactions.
The default is `persistent_memory=False` — no on-disk state at all, so the agent starts from a blank slate every run. Opt in explicitly for agents that should remember across runs, and use the same `agent_name` each time, since the memory file is keyed on it.
```python theme={null}
from swarms import Agent
# Opt in: memory survives process restarts
agent = Agent(
agent_name="Persistent-Agent",
model_name="gpt-5.4",
system_prompt="You are a helpful assistant.",
persistent_memory=True,
)
agent.run("My name is Alice and I work in finance.")
# On the next run — same agent_name, persistent_memory=True again —
# the agent will still know the user's name and role.
# Default: stateless, no cross-session memory
stateless_agent = Agent(
agent_name="Stateless-Agent",
model_name="gpt-5.4",
system_prompt="You are a helpful assistant.",
# persistent_memory=False is the default
)
stateless_agent.run("Summarise the latest news.")
```
#### Context Compression
For long-running agents the conversation history can grow until it fills the context window. `context_compression=True` (the default) attaches a `ContextCompressor` that automatically summarises and collapses `MEMORY.md` whenever token usage crosses 90% of `context_length`.
```python theme={null}
from swarms import Agent
# Default: automatic summarisation when the window gets full
agent = Agent(
agent_name="Long-Session-Agent",
model_name="gpt-5.4",
system_prompt="You are a research assistant.",
max_loops=10,
context_length=8192,
# context_compression=True is the default
)
agent.run("Deep-dive analysis of transformer architecture papers.")
# If token usage passes ~7,372 tokens (90% of 8192) the compressor
# summarises MEMORY.md in place and continues without interruption.
# Disabled: keep every raw message intact
audit_agent = Agent(
agent_name="Audit-Agent",
model_name="gpt-5.4",
system_prompt="You are a compliance auditor.",
context_compression=False,
)
```
#### Combining Both Controls
```python theme={null}
from swarms import Agent
# Persistent across runs + automatic context management (production default)
production_agent = Agent(
agent_name="Production-Agent",
model_name="gpt-5.4",
system_prompt="You are a customer support assistant.",
persistent_memory=True,
context_compression=True,
context_length=16000,
)
# Stateless + no compression (CI / unit-test friendly)
test_agent = Agent(
agent_name="Test-Agent",
model_name="gpt-5.4",
system_prompt="You are a helpful assistant.",
persistent_memory=False,
context_compression=False,
print_on=False,
)
```
### Agent Handoffs and Task Delegation
The `Agent` class supports intelligent task delegation through the `handoffs` parameter. When provided with a list of specialized agents, the main agent acts as a router that analyzes incoming tasks and delegates them to the most appropriate specialized agent.
**How Handoffs Work:**
1. **Task Analysis**: When a task is received, the main agent uses a built-in "boss agent" to analyze the task requirements
2. **Agent Selection**: The boss agent evaluates all available specialized agents and selects the most suitable one(s)
3. **Task Delegation**: The selected agent(s) receive the task and process it
4. **Response Aggregation**: Results from specialized agents are collected and returned
| Feature | Description |
| -------------------------- | ------------------------------------------------------------------------------- |
| **Intelligent Routing** | Uses AI to determine the best agent for each task |
| **Multiple Agent Support** | Can delegate to multiple agents for complex tasks requiring different expertise |
| **Task Modification** | Can modify tasks to better suit the selected agent's capabilities |
| **Transparent Reasoning** | Provides clear explanations for agent selection decisions |
| **Seamless Integration** | Works transparently with the existing `run()` method |
```python theme={null}
from swarms.structs.agent import Agent
research_agent = Agent(
agent_name="ResearchAgent",
agent_description="Specializes in researching topics and providing detailed, factual information",
model_name="gpt-5.4",
max_loops=1,
system_prompt="You are a research specialist.",
)
code_agent = Agent(
agent_name="CodeExpertAgent",
agent_description="Expert in writing, reviewing, and explaining code",
model_name="gpt-5.4",
max_loops=1,
system_prompt="You are a coding expert.",
)
writing_agent = Agent(
agent_name="WritingAgent",
agent_description="Skilled in creative and technical writing",
model_name="gpt-5.4",
max_loops=1,
system_prompt="You are a writing specialist.",
)
coordinator = Agent(
agent_name="CoordinatorAgent",
agent_description="Coordinates tasks and delegates to specialized agents",
model_name="gpt-5.4",
max_loops=1,
handoffs=[research_agent, code_agent, writing_agent],
system_prompt="You are a coordinator agent. Analyze tasks and delegate them to the most appropriate specialized agent.",
output_type="all",
)
result = coordinator.run(task="Call all the agents and ask them how they are doing")
print(result)
```
### Autonomous Mode
When `max_loops="auto"` is set, the agent enables automatic planning and execution. The agent creates a structured plan with subtasks, executes them sequentially with dependency management, and generates a comprehensive summary.
#### Available Tools in Autonomous Mode
When `max_loops="auto"` and `interactive=False`, the agent has access to specialized tools:
| Tool | Description | Parameters |
| --------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `create_plan` | Break the task into subtasks with dependencies | `task_description` (str), `steps` (list of dicts) |
| `think` *(only when `think_tool=True`)* | Pause and reason about the current state before acting | `current_state` (str), `analysis` (str), `next_actions` (list), `confidence` (float) |
| `subtask_done` | Mark the current subtask complete and advance to the next | `task_id` (str), `summary` (str), `success` (bool) |
| `complete_task` | Mark the whole task complete and produce a final summary | `task_id` (str), `summary` (str), `success` (bool), `results` (str, optional), `lessons_learned` (str, optional) |
| `respond_to_user` | Send messages to the user | `message` (str), `message_type` (str) |
| `create_file` | Create a new file | `file_path` (str), `content` (str) |
| `update_file` | Update an existing file | `file_path` (str), `content` (str), `mode` (str) |
| `read_file` | Read file contents | `file_path` (str) |
| `list_directory` | List files and directories | `directory_path` (str) |
| `delete_file` | Delete a file (with safety checks) | `file_path` (str) |
| `run_bash` | Execute a bash command | `command` (str), `timeout_seconds` (int) |
| `grep` | Search files for a pattern, returning matching lines. Preferred over `run_bash` for searches | `pattern` (str), `path` (str), `recursive` (bool), `case_insensitive` (bool), `include_line_numbers` (bool), `file_pattern` (str), `context_lines` (int) |
| `create_sub_agent` | Create specialized sub-agents | `agents` (array of agent specs) |
| `assign_task` | Assign tasks to sub-agents | `assignments` (array), `wait_for_completion` (bool) |
| `check_sub_agent_status` | Inspect the async task status of a sub-agent via the sub-agent registry | `agent_name` (str) |
| `cancel_sub_agent_tasks` | Cancel a sub-agent's pending or running async tasks | `agent_name` (str) |
`selected_tools` filters this entire list, including the control-flow tools. Passing a list that omits `create_plan` or `complete_task` leaves the agent unable to plan or to declare itself finished — include them explicitly, or leave `selected_tools="all"`.
`think` is opt-in. It is stripped from the tool list unless the agent is constructed with `think_tool=True`, and the system prompt is adjusted to match so the model is never told to call a tool it lacks.
All file operations use the agent's workspace directory (`$WORKSPACE_DIR/agents/{agent-name}-{id12}/`, reachable as `agent.workspace.dir`).
```python theme={null}
from swarms.structs.agent import Agent
agent = Agent(
agent_name="Quantitative-Trading-Agent",
agent_description="Advanced quantitative trading and algorithmic analysis agent",
model_name="gpt-5.4",
dynamic_temperature_enabled=True,
max_loops="auto",
dynamic_context_window=True,
output_type="all",
)
out = agent.run(
"Generate a comprehensive report on the top 5 publicly traded energy stocks. "
"For each stock include company name, ticker, key financial metrics, and analysis. "
"Only create 3 subtasks in your plan."
)
print(out)
```
#### Sub-Agent Delegation
The autonomous agent can create and manage sub-agents for parallel task execution:
```python theme={null}
from swarms.structs.agent import Agent
coordinator = Agent(
agent_name="Research-Coordinator",
agent_description="Coordinates complex research by delegating to specialized sub-agents",
model_name="gpt-5.4",
max_loops="auto",
selected_tools="all",
)
task = """
Conduct comprehensive research on three emerging technology trends:
1. Artificial Intelligence in Healthcare
2. Quantum Computing Advances
3. Renewable Energy Innovations
For each topic, create a specialized sub-agent and assign research tasks.
"""
result = coordinator.run(task)
print(result)
```
| Benefit | Description |
| ----------------------- | ----------------------------------------------------------- |
| **Parallel Processing** | Multiple tasks execute simultaneously for faster completion |
| **Specialization** | Each sub-agent can focus on a specific domain or capability |
| **Scalability** | Complex tasks can be broken into manageable pieces |
| **Reusability** | Sub-agents are cached and can handle multiple assignments |
| **Fault Tolerance** | One sub-agent failure doesn't stop others from completing |
### Batch Processing
Run a list of tasks one after another with `run_batched`. It is sequential, not concurrent — reach for `run_concurrent_tasks` when the tasks are independent and you want them in parallel:
```python theme={null}
tasks = [
"Analyze the financial data for Q1",
"Generate a summary report for stakeholders",
"Create recommendations for Q2 planning"
]
batch_results = agent.run_batched(tasks)
# Batch processing with images
tasks = ["Analyze this chart", "Identify patterns", "Summarize insights"]
images = ["chart1.png", "chart2.png", "chart3.png"]
batch_results = agent.run_batched(tasks, imgs=images)
```
## Examples
### Basic Usage
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="Financial-Analyst",
model_name="claude-sonnet-4-6",
max_loops=1,
system_prompt="You are a financial analyst. Provide detailed, data-driven insights."
)
response = agent.run("Analyze the Q4 2024 revenue trends")
print(response)
```
### Minimal Configuration
```python theme={null}
from swarms import Agent
agent = Agent(
model_name="gpt-5.4",
max_loops=1,
)
response = agent.run("What is the capital of France?")
print(response)
```
### Agent with Tools
```python theme={null}
from swarms import Agent
def search_web(query: str) -> str:
"""Search the web for information."""
return f"Search results for: {query}"
def calculate(expression: str) -> float:
"""Evaluate a mathematical expression."""
return eval(expression)
agent = Agent(
agent_name="Research-Agent",
model_name="claude-sonnet-4-6",
max_loops=5,
tools=[search_web, calculate],
system_prompt="You are a research assistant with web search and calculation abilities."
)
result = agent.run("Search for the population of Tokyo and calculate its growth rate")
```
### Multi-modal Agent
```python theme={null}
agent = Agent(
agent_name="Vision-Agent",
model_name="claude-sonnet-4-6",
multi_modal=True,
max_loops=1
)
response = agent.run(
task="Describe what you see in this image and identify any objects",
img="path/to/image.jpg"
)
```
### Multi-Image Processing
```python theme={null}
image_agent = Agent(
agent_name="Image-Analysis-Agent",
system_prompt="You are an expert at analyzing images.",
multi_modal=True,
)
images = ["product1.jpg", "product2.jpg", "product3.jpg"]
analysis = image_agent.run(
task="Analyze these product images and identify design patterns",
imgs=images
)
```
### Autonomous Agent with Auto Loops
```python theme={null}
agent = Agent(
agent_name="Autonomous-Developer",
model_name="claude-sonnet-4-6",
max_loops="auto",
system_prompt="You are an autonomous software developer."
)
result = agent.run("Build a REST API for a todo application with authentication")
# Agent will:
# 1. Create a plan with subtasks
# 2. Execute each subtask using available tools
# 3. Generate a comprehensive summary
```
### Multiple Loops
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="Iterative-Reasoning-Agent",
model_name="gpt-5.4",
max_loops=3,
reasoning_prompt_on=True,
system_prompt="You are an agent that reasons through problems step by step.",
)
response = agent.run("Solve this complex problem step by step: [problem description]")
```
### Dynamic Loops
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="Dynamic-Agent",
model_name="gpt-5.4",
dynamic_loops=True,
system_prompt="You are an adaptive agent that adjusts reasoning depth based on task complexity.",
)
response = agent.run("Analyze this complex scenario and provide insights")
```
### Agent with Streaming
```python theme={null}
def on_token(token: str):
print(token, end="", flush=True)
agent = Agent(
agent_name="Streaming-Agent",
model_name="claude-sonnet-4-6",
stream=True,
streaming_callback=on_token,
max_loops=1
)
response = agent.run("Write a creative story about space exploration")
```
### Token-by-Token Streaming
```python theme={null}
from swarms import Agent
agent = Agent(
model_name="gpt-5.4",
max_loops=1,
stream=True,
)
# Each token shows metadata including token count, model info, citations, and usage
agent.run("Tell me a short story about a robot learning to paint.")
```
### Agent with Fallback Models
```python theme={null}
agent = Agent(
agent_name="Reliable-Agent",
fallback_models=["claude-sonnet-4-6", "gpt-5.4", "gpt-5.4-mini"],
max_loops=1
)
response = agent.run("Generate a market analysis report")
```
### Agent with MCP Integration
```python theme={null}
agent = Agent(
agent_name="MCP-Agent",
model_name="claude-sonnet-4-6",
mcp_url="npx -y @modelcontextprotocol/server-filesystem /path/to/directory",
max_loops=3
)
result = agent.run("Read the contents of config.json and summarize the settings")
```
### Multiple MCP Connections
```python theme={null}
from swarms import Agent
agent = Agent(
model_name="gpt-5.4",
mcp_urls=[
"http://localhost:8000",
"http://localhost:8001",
],
max_loops=1,
)
response = agent.run("Use tools from both MCP servers")
```
### MCP with Connection Config
```python theme={null}
from swarms import Agent
from swarms.schemas.mcp_schemas import MCPConnection
mcp_config = MCPConnection(
url="http://localhost:8000",
name="my_mcp_server",
)
mcp_agent = Agent(
agent_name="MCP-Enabled-Agent",
system_prompt="You are an agent with access to external tools via MCP.",
mcp_config=mcp_config,
mcp_urls=["http://localhost:8000", "http://localhost:8001"],
tool_call_summary=True
)
response = mcp_agent.run("Use the available tools to analyze system status")
```
### Agent Handoffs
```python theme={null}
researcher = Agent(
agent_name="Researcher",
model_name="claude-sonnet-4-6",
system_prompt="You are a research specialist."
)
writer = Agent(
agent_name="Writer",
model_name="claude-sonnet-4-6",
system_prompt="You are a technical writer."
)
coordinator = Agent(
agent_name="Coordinator",
model_name="claude-sonnet-4-6",
max_loops=5,
handoffs=[researcher, writer],
system_prompt="You coordinate tasks between research and writing teams."
)
result = coordinator.run("Create a comprehensive report on quantum computing")
```
### Interactive Mode
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="Interactive-Agent",
model_name="claude-sonnet-4-6",
interactive=True,
system_prompt="You are an interactive agent. Engage in a conversation with the user.",
)
agent.run("Let's start a conversation")
```
### Auto Generate Prompt
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="Financial-Analysis-Agent",
system_prompt=None,
model_name="gpt-5.4",
max_loops=1,
auto_generate_prompt=True,
)
agent.run("How can I establish a ROTH IRA to buy stocks and get a tax break?")
print(agent.system_prompt)
```
### Reasoning-Enabled Models
```python theme={null}
from swarms import Agent
agent = Agent(
model_name="o1-preview",
reasoning_enabled=True,
reasoning_effort="high",
thinking_tokens=10000,
max_loops=1
)
response = agent.run("Solve this complex mathematical problem step by step")
```
### Execution Modes
```python theme={null}
from swarms import Agent
# Fast mode - optimized for performance
fast_agent = Agent(
model_name="gpt-5.4",
mode="fast",
max_loops=1
)
# Interactive mode - for real-time conversations
interactive_agent = Agent(
model_name="gpt-5.4",
mode="interactive",
max_loops=5
)
# Standard mode - default behavior
standard_agent = Agent(
model_name="gpt-5.4",
mode="standard",
max_loops=1
)
```
### Marketplace Prompt Loading
```python theme={null}
from swarms import Agent
agent = Agent(
model_name="claude-sonnet-4-6",
marketplace_prompt_id="550e8400-e29b-41d4-a716-446655440000",
max_loops=1
)
response = agent.run("Execute the marketplace prompt task")
```
### Publishing to Marketplace
```python theme={null}
from swarms import Agent
agent = Agent(
model_name="gpt-5.4",
agent_name="Financial-Advisor",
agent_description="Expert financial advisor agent",
system_prompt="You are an expert financial advisor...",
tags=["finance", "advisor"],
capabilities=["financial_planning", "investment_advice"],
use_cases=[
{"title": "Retirement Planning", "description": "Help users plan for retirement"},
{"title": "Investment Analysis", "description": "Analyze investment opportunities"}
],
publish_to_marketplace=True,
max_loops=1
)
```
### Message Transforms for Context Management
```python theme={null}
from swarms import Agent
from swarms.structs.transforms import TransformConfig
transforms = TransformConfig(
max_tokens=8000,
strategy="truncate_oldest"
)
agent = Agent(
model_name="gpt-5.4",
transforms=transforms,
context_length=100000,
max_loops=1
)
response = agent.run("Process this very long conversation history")
```
### Agent with Capabilities
```python theme={null}
from swarms import Agent
agent = Agent(
model_name="gpt-5.4",
agent_name="Data-Analysis-Agent",
capabilities=["data_analysis", "statistics", "visualization"],
max_loops=1
)
response = agent.run("Analyze this dataset")
```
### Saving and Loading State
```python theme={null}
# Save the agent state
agent.save('saved_flow.json')
# Load the agent state
agent = Agent(model_name="gpt-5.4", max_loops=5)
agent.load('saved_flow.json')
agent.run("Continue with the task")
```
### Autosave
When `autosave=True`, the agent saves its configuration at each loop step to `{workspace}/agents/{agent-name}-{id12}/config.json` via its `WorkspaceManager`. Files are written atomically to prevent corruption.
```python theme={null}
from swarms import Agent
agent = Agent(
model_name="gpt-5.4",
agent_name="autosave-demo",
max_loops=5,
autosave=True,
verbose=True,
)
response = agent.run("Complete a complex multi-step task")
workspace = agent.workspace.dir
print(f"Files saved to: {workspace}")
```
The workspace root comes from the `WORKSPACE_DIR` environment variable. Autosave goes through `WorkspaceManager`, which falls back to `{cwd}/agent_workspace` (and sets `WORKSPACE_DIR` to it) when the variable is unset. Other readers are stricter: `agent.workspace_dir`, resolved during construction, is `None` when the variable was unset at that moment. Set `WORKSPACE_DIR` explicitly rather than relying on the fallback.
### Async and Concurrent Execution
```python theme={null}
# Run several tasks concurrently on a call-scoped thread pool
results = agent.run_concurrent_tasks(["Task A", "Task B"])
# Run multiple tasks concurrently
tasks = [
{"task": "Task 1"},
{"task": "Task 2", "img": "path/to/image.jpg"},
{"task": "Task 3"}
]
responses = agent.bulk_run(tasks)
# Run multiple tasks in batch mode
task_list = ["Analyze data", "Generate report", "Create summary"]
batch_responses = agent.run_batched(task_list)
```
### Comprehensive Agent Configuration
```python theme={null}
from swarms import Agent
agent = Agent(
agent_name="Advanced-Analysis-Agent",
agent_description="Multi-modal analysis agent with advanced capabilities",
system_prompt="You are an advanced analysis agent.",
max_loops=3,
dynamic_loops=True,
interactive=False,
dashboard=True,
context_length=100000,
dynamic_context_window=True,
auto_generate_prompt=True,
plan_enabled=True,
react_on=True,
safety_prompt_on=True,
reasoning_prompt_on=True,
tool_retry_attempts=5,
tool_call_summary=True,
show_tool_execution_output=True,
output_type="json",
model_name="gpt-5.4",
temperature=0.3,
max_tokens=8000,
top_p=0.95,
retry_attempts=3,
tags=["analysis", "multi-modal", "advanced"],
use_cases=[{"name": "Data Analysis", "description": "Process and analyze complex datasets"}],
verbose=True,
print_on=True
)
def streaming_callback(token: str):
print(token, end="", flush=True)
response = agent.run(
task="Analyze these financial charts",
imgs=["chart1.png", "chart2.png", "chart3.png"],
streaming_callback=streaming_callback
)
```
### Various Settings
```python theme={null}
print(agent.to_dict())
print(agent.to_toml())
print(agent.model_dump_json())
print(agent.model_dump_yaml())
agent.receive_message(agent_name="OtherAgent", task="message")
agent.send_agent_message(agent_name="agent_name", message="message")
agent.add_memory("Add a memory to the agent")
agent.check_available_tokens()
agent.print_dashboard()
```
## Output Types
The agent supports multiple output formats via the `output_type` parameter:
| Value | Returns |
| ---------------------------- | ----------------------------------------------------------------------------------------------- |
| `"str"`, `"string"`, `"all"` | The whole conversation as a string |
| `"str-all-except-first"` | The conversation as a string, minus the first message (default) |
| `"list"` | The conversation as a list of message dicts |
| `"list-final"` | The final message, wrapped in a list |
| `"dict"`, `"dictionary"` | The conversation as a dictionary |
| `"dict-all-except-first"` | The conversation as a dictionary, minus the first message |
| `"dict-final"` | The final message as a dictionary |
| `"final"`, `"last"` | The content of the final message |
| `"json"` | The conversation as a JSON string |
| `"yaml"` | The conversation as a YAML string |
| `"xml"` | The conversation as an XML string |
| `"basemodel"` | Accepted by the type but **not** implemented by the formatter — raises `ValueError` at runtime. |
The accepted values are the `HistoryOutputType` literal in `swarms.utils.output_types`; anything outside it raises `ValueError`.
## Error Handling
The Agent class includes comprehensive error handling:
* **AgentError**: Base class for every exception below
* **AgentInitializationError**: Raised when agent fails to initialize
* **AgentRunError**: Raised when execution fails
* **AgentLLMError**: Raised when LLM encounters issues
* **AgentLLMInitializationError**: Raised when the LLM fails to initialize
* **AgentToolExecutionError**: Raised when the agent fails to execute a tool
These live in `swarms.schemas.agent_errors` so collaborator classes can raise and catch them without importing `Agent`:
```python theme={null}
from swarms.schemas import AgentError, AgentRunError # canonical home
try:
agent.run(task)
except AgentError as e: # catches every agent exception
...
```
Only the subclasses are re-exported from `swarms.structs.agent`
(`AgentInitializationError`, `AgentLLMError`, `AgentRunError`,
`AgentToolExecutionError`). The base `AgentError` is not, so
`from swarms.structs.agent import AgentError` raises `ImportError`. Import the
base class from `swarms.schemas`.
MCP-specific failures use a separate hierarchy in `swarms.schemas.agent_mcp_errors`: `AgentMCPError`, `AgentMCPConnectionError`, `AgentMCPToolError`.
## Telemetry
`Agent.run` is instrumented with OpenTelemetry, **on by default**. Each run emits an `Agent.run` span carrying the task, the output, status, and the agent's identity — nested under the swarm run that invoked it, if any. Construction emits an `Agent.init` span carrying the full constructor configuration.
Opt out with `SWARMS_TELEMETRY_ON=false`, which reduces the cost to \~0.14 µs per call. See the [Telemetry guide](/deployment/telemetry) for what is captured and how to turn it off.
## New Features and Parameters
### Enhanced Run Method Parameters
* **`imgs`**: Process multiple images simultaneously instead of just one
* **`correct_answer`**: Validate responses against expected answers with automatic retries
* **`streaming_callback`**: Real-time token streaming for interactive applications
### MCP (Model Context Protocol) Integration
| Parameter | Description |
| ------------------------- | ------------------------------------------------------------------------------------- |
| `mcp_url` | A single MCP server: URL string, `MCPConnection`, or dict |
| `mcp_urls` | Several MCP servers, each a URL string, `MCPConnection`, or dict |
| `mcp_config` | A single MCP server as a connection object (or dict) |
| `mcp_configs` | Several MCP servers as connection objects (or dicts) |
| `mcp_api_key` | API key applied to every server without its own; supports `env:`/`${...}` indirection |
| `mcp_authorization_token` | Bearer token applied to every server without its own |
| `mcp_oauth` | OAuth 2.1 settings (`MCPOAuthConfig` or dict) applied to every server without its own |
| `mcp_headers` | Extra headers merged into every MCP request |
| `mcp_transport` | Force `streamable_http`, `sse`, `stdio`, or `auto` for every server |
| `mcp_timeout` | Request timeout in seconds for every server |
### Advanced Reasoning and Safety
| Parameter | Description |
| --------------------- | ----------------------------------------------------------------- |
| `react_on` | Enable ReAct reasoning for complex problem-solving |
| `safety_prompt_on` | Add safety constraints to agent responses |
| `reasoning_prompt_on` | Enable multi-loop reasoning for complex tasks |
| `reasoning_enabled` | Enable reasoning capabilities for supported models (e.g., o1) |
| `reasoning_effort` | Reasoning effort level; unset by default, omit when using `tools` |
| `thinking_tokens` | Maximum number of thinking tokens for reasoning models |
### Performance and Resource Management
| Parameter | Description |
| ------------------------ | ------------------------------------------------------------- |
| `dynamic_context_window` | Automatically adjust context window based on available tokens |
| `tool_retry_attempts` | Configure retry behavior for tool execution |
### Advanced Memory and Context
| Parameter | Description |
| ---------------------- | ------------------------------------------------------------------------ |
| `auto_generate_prompt` | Automatically generate system prompts based on tasks |
| `plan_enabled` | Enable planning functionality for complex tasks |
| `context_compression` | Auto-summarize MEMORY.md once token usage crosses 90% of context\_length |
| `persistent_memory` | Off by default; set `True` to read/write MEMORY.md across sessions |
### Enhanced Tool Management
| Parameter | Description |
| ---------------------------- | -------------------------------------------- |
| `tools_list_dictionary` | Provide tool schemas in dictionary format |
| `tool_call_summary` | Enable automatic summarization of tool calls |
| `show_tool_execution_output` | Control visibility of tool execution details |
### Advanced LLM Configuration
| Parameter | Description |
| -------------- | ------------------------------------ |
| `llm_args` | Pass additional arguments to the LLM |
| `llm_base_url` | Specify custom LLM API endpoint |
| `llm_api_key` | Provide LLM API key directly |
| `top_p` | Control top-p sampling parameter |
### Execution Modes and Marketplace
| Parameter | Description |
| ------------------------ | -------------------------------------------------------- |
| `mode` | Execution mode: "interactive", "fast", or "standard" |
| `capabilities` | List of agent capabilities for documentation and routing |
| `publish_to_marketplace` | Publish agent prompt to Swarms marketplace |
| `marketplace_prompt_id` | Load prompt from Swarms marketplace by UUID |
## Best Practices
| Best Practice | Description |
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `system_prompt` | Always provide a clear and concise system prompt to guide the agent's behavior. |
| `tools` | Use tools to extend the agent's capabilities for specific tasks. |
| `retry_attempts` & error handling | Implement error handling and utilize the retry\_attempts feature for robust execution. |
| `interactive` & `dashboard` | Use interactive mode for real-time conversations and dashboard for monitoring. |
| `autosave`, `save`/`load` | Utilize autosave and save/load methods for continuity across sessions. |
| `dynamic_context_window` & `check_available_tokens()` | Optimize token usage with the dynamic\_context\_window parameter and the check\_available\_tokens() method. |
| `concurrent` & `async` methods | Use concurrent and async methods for performance-critical applications. |
| `run_batched` | Leverage run\_batched to process a list of related tasks in order; use run\_concurrent\_tasks for parallelism. |
| `mcp_url` or `mcp_urls` | Use mcp\_url or mcp\_urls to extend agent capabilities with external tools. |
| `react_on` | Enable react\_on for complex reasoning tasks requiring step-by-step analysis. |
| `tool_retry_attempts` | Configure tool\_retry\_attempts for robust tool execution in production environments. |
| `handoffs` | Use handoffs to create specialized agent teams that can intelligently route tasks. |
| Set appropriate `max_loops` | Use 1 for simple tasks, higher numbers for complex reasoning, or "auto" for autonomous planning. |
| Enable `verbose` during development | Helps debug issues during development and testing. |
| Set `context_length` appropriately | Prevents token limit errors in production. |
## Related
**Agent subsystems**
* [LLMManager](/api/llm-manager) - Model selection, invocation, and fallback rotation
* [MCPManager](/api/mcp-manager) - MCP servers, tool discovery, and tool-call routing
* [SkillsManager](/api/skills-manager) - Agent Skills loading and prompt rendering
* [AgentMarketplaceHandler](/api/agent-marketplace-handler) - Marketplace fetch and publish
**Everything else**
* [Tools](/concepts/tools) - Creating and using agent tools
* [Memory](/agents/agent-memory) - Long-term memory systems
* [Telemetry](/deployment/telemetry) - Tracing agent and swarm runs
# AgentLoader
Source: https://docs.swarms.world/api/agent-loader
Loader class for creating Agent objects from Markdown, YAML, and CSV files
## Overview
The `AgentLoader` class provides a unified interface for instantiating `Agent` objects from on-disk definitions. It supports three file formats and dispatches automatically based on the file extension.
| Format | Extension | Backing loader |
| -------- | --------- | --------------------------- |
| Markdown | `.md` | `load_agents_from_markdown` |
| YAML | `.yaml` | `create_agents_from_yaml` |
| CSV | `.csv` | `CSVAgentLoader` |
Use this when you want agent definitions to live as data — checked into git, edited by humans, generated by tools — rather than hard-coded in Python.
## Installation
```bash theme={null}
pip install -U swarms
```
## Constructor
```python theme={null}
from swarms import AgentLoader
loader = AgentLoader(concurrent=True)
```
Default for concurrent loading when multiple files are passed. Individual `load_*` methods accept their own `concurrent` override.
## Methods
### auto()
Dispatch to the right loader based on file extension. The simplest entry point.
```python theme={null}
def auto(self, file_path: str, *args, **kwargs) -> List[Agent]
```
**Parameters:**
* `file_path` (str): Path to `.md`, `.yaml`, or `.csv` file.
* `*args`, `**kwargs`: Forwarded to the underlying loader.
**Returns:** `List[Agent]`
**Raises:** `ValueError` if the file extension is not `.md`, `.yaml`, or `.csv`.
### load\_single\_agent()
Alias for `auto()` — loads a single file by dispatching on extension.
```python theme={null}
def load_single_agent(self, *args, **kwargs) -> List[Agent]
```
### load\_multiple\_agents()
Apply `auto()` to a list of files. Each file may be a different format.
```python theme={null}
def load_multiple_agents(
self,
file_paths: List[str],
*args,
**kwargs,
) -> List[List[Agent]]
```
**Parameters:**
* `file_paths` (List\[str]): Paths to agent definition files.
**Returns:** List of agent lists, one per input file.
### load\_agent\_from\_markdown()
Load a single agent from a Markdown file.
```python theme={null}
def load_agent_from_markdown(
self,
file_path: str,
**kwargs,
) -> Agent
```
### load\_agents\_from\_markdown()
Load multiple agents from one or more Markdown files.
```python theme={null}
def load_agents_from_markdown(
self,
file_paths: Union[str, List[str]],
concurrent: bool = True,
max_file_size_mb: float = 10.0,
**kwargs,
) -> List[Agent]
```
Single path or list of paths to Markdown agent files.
Load files in parallel.
Files above this size are skipped.
### load\_agents\_from\_yaml()
Load agents from a single YAML file.
```python theme={null}
def load_agents_from_yaml(
self,
yaml_file: str,
return_type: ReturnTypes = "auto",
**kwargs,
) -> List[Agent]
```
Path to the YAML definitions file.
Controls the return shape from the underlying YAML loader.
### load\_many\_agents\_from\_yaml()
Load agents from a list of YAML files with per-file return type control.
```python theme={null}
def load_many_agents_from_yaml(
self,
yaml_files: List[str],
return_types: List[ReturnTypes] = ["auto"],
**kwargs,
) -> List[Agent]
```
### load\_agents\_from\_csv()
Load agents from a CSV file via `CSVAgentLoader`.
```python theme={null}
def load_agents_from_csv(
self,
csv_file: str,
**kwargs,
) -> List[Agent]
```
### parse\_markdown\_file()
Lower-level: parse a Markdown file via `MarkdownAgentLoader` directly, using the host's CPU count as worker count.
```python theme={null}
def parse_markdown_file(self, file_path: str) -> List[Agent]
```
## Usage Examples
### Auto-Dispatch on Extension
The shortest path — let `auto()` figure out the format.
```python theme={null}
from swarms import AgentLoader
loader = AgentLoader()
# Each file uses its own format; auto() picks the right loader
research_agents = loader.auto("agents/research_team.yaml")
support_agents = loader.auto("agents/support_squad.md")
sales_agents = loader.auto("agents/sales_reps.csv")
```
### Load Many Files in One Call
```python theme={null}
from swarms import AgentLoader
loader = AgentLoader()
all_agents = loader.load_multiple_agents([
"agents/research_team.yaml",
"agents/support_squad.md",
"agents/sales_reps.csv",
])
# all_agents is a list-of-lists; one entry per file
for file_agents in all_agents:
for agent in file_agents:
print(agent.agent_name)
```
### Markdown with Concurrency Control
```python theme={null}
from swarms import AgentLoader
loader = AgentLoader()
agents = loader.load_agents_from_markdown(
file_paths=[
"agents/researcher.md",
"agents/writer.md",
"agents/editor.md",
],
concurrent=True,
max_file_size_mb=5.0,
)
```
### Compose with a Swarm
```python theme={null}
from swarms import AgentLoader, SequentialWorkflow
loader = AgentLoader()
agents = loader.auto("agents/research_pipeline.yaml")
workflow = SequentialWorkflow(agents=agents, max_loops=1)
result = workflow.run("Summarize the current state of multi-agent research")
```
## Source Code
View the [source on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/agent_loader.py).
# AgentMarketplaceHandler
Source: https://docs.swarms.world/api/agent-marketplace-handler
Fetch prompts from, and publish prompts to, the Swarms Marketplace
## Overview
`AgentMarketplaceHandler` owns both directions of Swarms Marketplace integration: resolving a prompt UUID into an agent's system prompt, and publishing an agent's prompt with its metadata.
Every `Agent` builds one as `agent.marketplace`. The class also works with **no agent at all** — fetching and publishing are classmethods, so you can use it as a standalone marketplace client.
```python theme={null}
from swarms import Agent
# Load a prompt at construction
agent = Agent(marketplace_prompt_id="550e8400-e29b-41d4-a716-446655440000")
# Publish this agent's prompt
agent.handle_publish_to_marketplace()
```
## Import
```python theme={null}
from swarms.agents.agent_marketplace_handler import AgentMarketplaceHandler
```
## Authentication
Both directions require `SWARMS_API_KEY`. Get one at [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys).
```bash theme={null}
export SWARMS_API_KEY="your-key"
```
### check\_api\_key
```python theme={null}
@staticmethod
def check_api_key() -> str
```
Return the key from the environment, raising `ValueError` when it is unset, empty, or whitespace-only.
The key is read **fresh on every call** — not cached. A key exported after import, or rotated mid-process, is picked up immediately.
## Fetching
### fetch
```python theme={null}
@classmethod
def fetch(
prompt_id: Optional[str] = None,
name: Optional[str] = None,
timeout: float = 30.0,
return_params_on: bool = True,
) -> Optional[Union[Dict[str, Any], Tuple[str, str, str]]]
```
`GET https://swarms.world/api/get-prompts/`
The prompt's UUID. Takes precedence over `name` when both are given.
The prompt's name, URL-encoded automatically.
Request timeout in seconds.
`True` returns a `(name, description, prompt)` tuple; `False` returns the full JSON response.
Returns `None` when the prompt does not exist (404). Raises `ValueError` when neither argument is given, and `httpx.HTTPStatusError` for any other error status.
```python theme={null}
name, description, prompt = AgentMarketplaceHandler.fetch(
name="code-review-assistant"
)
```
### fetch\_prompt
```python theme={null}
@classmethod
def fetch_prompt(prompt_id: str) -> Tuple[str, str, str]
```
Like `fetch`, but requires the prompt to exist — raises `ValueError` with a helpful message on 404.
### load\_prompt
```python theme={null}
def load_prompt(prompt_id: Optional[str] = None) -> None
```
Fetch a prompt and fold it into the owning agent:
* appends the prompt body to `agent.system_prompt`
* sets `agent_name` / `name` **only if** `agent.agent_name` still equals the default sentinel `"swarm-worker-01"` (a value comparison, not a flag — an agent deliberately named `"swarm-worker-01"` is treated as unnamed and gets overwritten)
* sets `agent_description` / `description` **only if** it is `None`
Defaults to the agent's configured `marketplace_prompt_id`.
`Agent.__init__` gives `agent_description` a generic default string rather than `None`, so the description back-fill only fires when you explicitly pass `agent_description=None`.
## Publishing
### publish
```python theme={null}
def publish(category: str = "research") -> Dict[str, Any]
```
Publish the owning agent's prompt and metadata. Raises `AgentInitializationError` when `use_cases` was not provided.
```python theme={null}
agent = Agent(
agent_name="Medical-Analyst",
agent_description="Analyzes lab results",
tags=["medical", "diagnostics"],
capabilities=["lab-analysis"],
use_cases=[{"title": "Blood panel review", "description": "..."}],
publish_to_marketplace=True, # publishes on construction
)
```
### build\_tags
```python theme={null}
def build_tags() -> str
```
Merge the agent's `tags` and `capabilities` into one comma-separated string. Either list may be empty or unset; only what exists is included, and neither returns `""`.
### add\_prompt
```python theme={null}
@classmethod
def add_prompt(
name=None, prompt=None, description=None, use_cases=None,
tags=None, is_free=True, price_usd=0.0,
category="research", timeout=30.0,
) -> Dict[str, Any]
```
`POST https://swarms.world/api/add-prompt` — the low-level publish, usable without an agent.
Prompt name.
The prompt text.
What the prompt does.
Dicts with `title` and `description` keys. Sent to the API as `useCases`.
Comma-separated tags. `None` becomes `""`.
Whether the prompt is free.
Price, ignored when `is_free`.
Category of the prompt (e.g. `"content"`, `"coding"`). Despite the default, it is validated like the other required fields — passing `category=None` explicitly raises `ValueError`.
Request timeout in seconds for the underlying HTTP call.
Each missing required field (including `category`, if explicitly passed as `None`) raises `ValueError` naming that field.
## Agent integration
| `Agent` member | Behavior |
| ----------------------------------------- | -------------------------------------- |
| `agent.marketplace` | The `AgentMarketplaceHandler` instance |
| `Agent(marketplace_prompt_id=...)` | Loads the prompt during construction |
| `Agent(publish_to_marketplace=True, ...)` | Publishes during construction |
| `agent.handle_publish_to_marketplace()` | Delegates to `publish()` |
| `agent._load_prompt_from_marketplace()` | Delegates to `load_prompt()` |
## Standalone use
```python theme={null}
from swarms.agents.agent_marketplace_handler import AgentMarketplaceHandler
# No agent required
handler = AgentMarketplaceHandler()
AgentMarketplaceHandler.check_api_key()
AgentMarketplaceHandler.fetch(name="code-review-assistant")
AgentMarketplaceHandler.add_prompt(
name="My Prompt",
prompt="You are...",
description="Does a thing",
use_cases=[{"title": "Example", "description": "..."}],
)
```
## Migration
This class absorbed two modules that have been removed:
| Removed | Replacement |
| ----------------------------------------------------------------------- | --------------------------------------- |
| `swarms.utils.fetch_prompts_marketplace.fetch_prompts_from_marketplace` | `AgentMarketplaceHandler.fetch` |
| `swarms.utils.fetch_prompts_marketplace.return_params` | inlined into `fetch` |
| `swarms.utils.swarms_marketplace_utils.add_prompt_to_marketplace` | `AgentMarketplaceHandler.add_prompt` |
| `swarms.utils.swarms_marketplace_utils.check_swarms_api_key` | `AgentMarketplaceHandler.check_api_key` |
## Related
Marketplace integration guide
The class that owns the handler
# AgentRearrange
Source: https://docs.swarms.world/api/agent-rearrange
A sophisticated multi-agent system for dynamic task orchestration with custom flow patterns
## Overview
The `AgentRearrange` class enables complex workflows where multiple agents can work sequentially or concurrently based on a defined flow pattern. It supports both sequential execution (using `->`) and concurrent execution (using `,`) within the same workflow, providing maximum flexibility for agent orchestration.
## Key Features
* **Flexible Flow Syntax**: Define sequential (`->`) and concurrent (`,`) agent execution in one flow
* **Custom Flow Patterns**: Mix sequential and concurrent execution patterns
* **Team Awareness**: Agents can be aware of their position in the workflow
* **Batch Processing**: Process multiple tasks with the same flow
* **Concurrent Execution**: Run multiple tasks in parallel
* **Async Support**: Asynchronous execution for non-blocking operations
## Installation
```bash theme={null}
pip install -U swarms
```
## Class Definition
```python theme={null}
class AgentRearrange:
def __init__(
self,
id: str = None,
name: str = "AgentRearrange",
description: str = "A swarm of agents for rearranging tasks.",
agents: List[Union[Agent, Callable]] = None,
flow: str = None,
max_loops: int = 1,
verbose: bool = False,
memory_system: Any = None,
output_type: OutputType = "all",
autosave: bool = True,
team_awareness: bool = False,
time_enabled: bool = False,
message_id_on: bool = False,
collab_prompt: Optional[str] = None,
)
```
Earlier versions accepted `human_in_the_loop`, `custom_human_in_the_loop`, and `rules` parameters (and an `H` token in the flow string for human review steps). These have been **removed** — `AgentRearrange` no longer supports inline human-in-the-loop steps or a `rules` argument.
## Parameters
Unique identifier for the agent rearrange system. Auto-generated via `generate_id("agent-rearrange")` if not provided, producing `agent-rearrange-<32 hex chars>`.
Human-readable name for the system
Description of the system's purpose
List of agents to include in the system. Can be Agent objects or callable functions.
Flow pattern defining agent execution order. Uses `->` for sequential and `,` for concurrent execution.
Example: `"agent1 -> agent2, agent3 -> agent4"`
Maximum number of execution loops. Must be greater than 0.
Whether to enable verbose logging
Accepted for backwards compatibility. The value is stored on the instance and is not read by the workflow. Configure memory on the individual agents with `persistent_memory` instead.
Format for output results. Options: "all", "final", "list", "dict"
Whether to automatically save execution data
Whether agents should be aware of team structure and sequential flow
Guidance prepended to every agent's messages as a system turn for the duration
of the run. It is not written to the shared conversation, so other agents never
see it, and the caller's `Agent` objects are not modified. `SequentialWorkflow`
passes its collaboration preamble through this parameter.
Whether to track timestamps in conversations
Whether to include message IDs in conversations
## Flow Syntax
The flow pattern defines how agents execute:
* **Sequential**: `agent1 -> agent2 -> agent3` (agents run one after another)
* **Concurrent**: `agent1, agent2, agent3` (agents run simultaneously)
* **Mixed**: `agent1 -> agent2, agent3 -> agent4` (agent1 first, then agent2 and agent3 concurrently, then agent4)
## Methods
### `run(task, img=None, *args, **kwargs)`
Execute the agent rearrangement task.
The task to execute through the agent workflow
Path to input image if required by any agents
The processed output in the format specified by output\_type
### `batch_run(tasks, img=None, batch_size=10, *args, **kwargs)`
Process multiple tasks in batches.
List of tasks to process through the agent workflow
Optional list of images corresponding to tasks
Number of tasks to process simultaneously in each batch
List of results corresponding to input tasks
### `concurrent_run(tasks, img=None, max_workers=None, *args, **kwargs)`
Process multiple tasks concurrently using ThreadPoolExecutor.
List of tasks to process through the agent workflow
Optional list of images corresponding to tasks
Maximum number of worker threads. Uses default ThreadPoolExecutor behavior if None.
List of results corresponding to input tasks
### `run_async(task, img=None, *args, **kwargs)`
Asynchronously execute a task.
The task to be executed through the agent workflow
Optional image input for the task
The result of the task execution
### `set_custom_flow(flow)`
Set a custom flow pattern for agent execution.
The new flow pattern to use for agent execution
### `add_agent(agent)`
Add an agent to the swarm.
The agent to be added
### `add_agents(agents)`
Add multiple agents to the swarm at once.
A list of Agent objects to be added
### `remove_agent(agent_name)`
Remove an agent from the swarm.
The name of the agent to be removed
### `explain(return_str=False)`
Print (or return) the resolved execution plan for the current flow, listing every step in order and marking each as sequential or parallel. Does not invoke any agents or LLMs. Validates the flow first and raises if it is invalid.
When `True`, returns the plan as a string instead of printing it
The plan string if `return_str=True`; otherwise `None`
### `get_agent_sequential_awareness(agent_name)`
Get the sequential awareness information (agents immediately ahead/behind) for a specific agent in the current flow.
The name of the agent to get awareness for
A string describing the agents ahead and behind in the sequence
### `get_sequential_flow_structure()`
Get a string describing the complete sequential flow structure (step-by-step breakdown of the flow).
A string describing the overall sequential flow structure
### `run_stream(task=None, img=None, with_events=False, **kwargs)`
Sync generator that streams tokens from each agent in flow order as they are generated. Sequential segments stream one agent at a time; parallel (comma) segments interleave tokens fairly across concurrent agents.
Initial task fed into the first agent in the flow
Optional image input forwarded to every agent
When `False`, yields `(agent_name, token)` tuples. When `True`, yields structured event dicts (`agent_start`, `token`, `agent_end`)
Not yet supported in streaming mode: `max_loops > 1`, `custom_tasks`. Use `run()` for those.
### `arun_stream(task=None, img=None, with_events=False, **kwargs)`
Async generator version of `run_stream`, with the same parameters and yield semantics.
### `validate_flow()`
Validate the flow pattern.
True if the flow pattern is valid
**Raises:**
* `ValueError`: If the flow pattern is incorrectly formatted or contains unregistered agents
### `to_dict()`
Convert all attributes to a dictionary for serialization.
Dictionary representation of all class attributes
## Attributes
| Attribute | Type | Description |
| -------------- | ------------------------------ | ------------------------------------------- |
| `id` | str | Unique identifier for the system |
| `name` | str | Human-readable name |
| `description` | str | Description of the system's purpose |
| `agents` | List\[Union\[Agent, Callable]] | List of agents or callables in the system |
| `flow` | str | Flow pattern defining agent execution order |
| `conversation` | Conversation | Conversation history management |
## Usage Examples
### Sequential Flow
```python theme={null}
from swarms import Agent, AgentRearrange
# Create agents
researcher = Agent(
agent_name="researcher",
model_name="claude-sonnet-4-6",
system_prompt="You are a research specialist."
)
writer = Agent(
agent_name="writer",
model_name="claude-sonnet-4-6",
system_prompt="You are a content writer."
)
editor = Agent(
agent_name="editor",
model_name="claude-sonnet-4-6",
system_prompt="You are an editor."
)
# Define sequential flow
flow = "researcher -> writer -> editor"
# Create rearrange system
system = AgentRearrange(
agents=[researcher, writer, editor],
flow=flow,
max_loops=1
)
# Execute task
result = system.run("Write a blog post about AI")
print(result)
```
### Concurrent Flow
```python theme={null}
# Define concurrent flow - all agents run simultaneously
flow = "researcher, writer, editor"
system = AgentRearrange(
agents=[researcher, writer, editor],
flow=flow
)
result = system.run("Analyze this topic from different angles")
```
### Mixed Sequential and Concurrent Flow
```python theme={null}
# Create more agents
data_collector = Agent(
agent_name="data_collector",
llm=llm,
system_prompt="You collect and organize data."
)
technical_analyst = Agent(
agent_name="technical_analyst",
llm=llm,
system_prompt="You analyze technical aspects."
)
business_analyst = Agent(
agent_name="business_analyst",
llm=llm,
system_prompt="You analyze business aspects."
)
synthesizer = Agent(
agent_name="synthesizer",
llm=llm,
system_prompt="You synthesize multiple perspectives."
)
# Mixed flow: collect data, then analyze concurrently, then synthesize
flow = "data_collector -> technical_analyst, business_analyst -> synthesizer"
system = AgentRearrange(
agents=[data_collector, technical_analyst, business_analyst, synthesizer],
flow=flow,
team_awareness=True # Agents know about each other
)
result = system.run("Analyze the market opportunity for AI assistants")
```
### Batch Processing
```python theme={null}
# Process multiple tasks through the same flow
tasks = [
"Analyze healthcare AI trends",
"Analyze education AI trends",
"Analyze finance AI trends"
]
system = AgentRearrange(
agents=[researcher, writer, editor],
flow="researcher -> writer -> editor"
)
results = system.batch_run(tasks, batch_size=2)
for task, result in zip(tasks, results):
print(f"Task: {task}")
print(f"Result: {result}")
print("-" * 80)
```
### Concurrent Task Execution
```python theme={null}
tasks = [
"Research AI in healthcare",
"Research AI in education",
"Research AI in finance"
]
# Run all tasks in parallel
results = system.concurrent_run(tasks, max_workers=3)
print(f"Processed {len(results)} tasks concurrently")
```
### Async Execution
```python theme={null}
import asyncio
async def process_async():
result = await system.run_async("Analyze quantum computing trends")
return result
result = asyncio.run(process_async())
```
### Dynamic Flow Modification
```python theme={null}
# Create system with initial flow
system = AgentRearrange(
agents=[researcher, writer, editor],
flow="researcher -> writer -> editor"
)
# Run with initial flow
result1 = system.run("Task 1")
# Change flow dynamically
system.set_custom_flow("researcher -> editor -> writer")
# Run with new flow
result2 = system.run("Task 2")
```
### With Team Awareness
```python theme={null}
# Agents will know about their position in the workflow
system = AgentRearrange(
agents=[researcher, writer, editor],
flow="researcher -> writer -> editor",
team_awareness=True, # Enable team awareness
verbose=True
)
result = system.run("Create comprehensive analysis")
# Each agent will receive information about agents ahead and behind
```
### Different Output Types
```python theme={null}
# Return all outputs
system_all = AgentRearrange(
agents=[researcher, writer],
flow="researcher -> writer",
output_type="all" # Return all agent outputs
)
# Return only final output
system_final = AgentRearrange(
agents=[researcher, writer],
flow="researcher -> writer",
output_type="final" # Return only last agent's output
)
# Return as list
system_list = AgentRearrange(
agents=[researcher, writer],
flow="researcher -> writer",
output_type="list" # Return list of outputs
)
# Return as dict
system_dict = AgentRearrange(
agents=[researcher, writer],
flow="researcher -> writer",
output_type="dict" # Return dict mapping agent names to outputs
)
```
## Convenience Function
The `rearrange()` function provides a quick way to create and execute:
```python theme={null}
from swarms import rearrange
result = rearrange(
name="Quick Analysis",
agents=[researcher, writer, editor],
flow="researcher -> writer -> editor",
task="Analyze AI trends in 2024"
)
```
## Error Handling
```python theme={null}
try:
system = AgentRearrange(
agents=[researcher, writer],
flow="researcher -> writer"
)
result = system.run("Process this task")
except ValueError as e:
print(f"Configuration error: {e}")
except Exception as e:
print(f"Execution error: {e}")
```
## Best Practices
1. **Flow Design**: Carefully design your flow to match your task requirements
2. **Team Awareness**: Enable for complex flows where context matters
3. **Error Handling**: Always wrap execution in try-except blocks
4. **Logging**: Enable verbose mode during development
5. **Memory Systems**: Use for tasks requiring persistent context
6. **Flow Validation**: Always validate flows before production use
7. **Agent Naming**: Use clear, descriptive agent names in flows
## Common Flow Patterns
### Fan-Out Pattern
```python theme={null}
# One agent feeds multiple agents
flow = "collector -> analyst1, analyst2, analyst3 -> synthesizer"
```
### Pipeline Pattern
```python theme={null}
# Linear processing chain
flow = "stage1 -> stage2 -> stage3 -> stage4"
```
### Review Pattern
```python theme={null}
# Create, review, revise
flow = "creator -> reviewer -> reviser"
```
### Ensemble Pattern
```python theme={null}
# Multiple independent analyses
flow = "agent1, agent2, agent3, agent4 -> aggregator"
```
## Related Classes
* [SequentialWorkflow](/api/sequential-workflow): For simple sequential execution
* [ConcurrentWorkflow](/api/concurrent-workflow): For parallel agent execution
* [GraphWorkflow](/api/graph-workflow): For complex DAG-based workflows
* [Agent](/api/agent): The base agent class used in workflows
# AgentRouter
Source: https://docs.swarms.world/api/agent-router
An embedding-based routing system that intelligently matches tasks to the most appropriate specialized agent using cosine similarity
## Overview
The `AgentRouter` is an embedding-based routing system that intelligently matches tasks to the most appropriate specialized agent using cosine similarity on embeddings. It uses LiteLLM's embedding models to generate vector representations of both agents and tasks, enabling semantic matching for optimal agent selection.
When a task is submitted, the router:
1. Generates an embedding vector for the task
2. Calculates cosine similarity between the task embedding and all agent embeddings
3. Returns the agent with the highest similarity score
4. Optionally updates agent embeddings with interaction history for improved matching over time
## Installation
```bash theme={null}
pip install -U swarms
```
## Class Definition
```python theme={null}
from swarms.structs.agent_router import AgentRouter
```
## Attributes
The embedding model to use for generating embeddings. Supports various models like `text-embedding-3-small`, `text-embedding-3-large`, `cohere/embed-english-v3.0`, `huggingface/microsoft/codebert-base`, etc.
Number of agents to return in queries (currently supports returning the best match)
API key for the embedding service. If not provided, will use environment variables.
Custom API base URL for the embedding service.
List of agents to initialize the router with. Each agent should have `name`, `description`, and `system_prompt` attributes.
## Methods
### add\_agent()
Add a single agent to the router. The agent will be embedded using its name, description, and system prompt.
```python theme={null}
def add_agent(self, agent: AgentType) -> None
```
**Parameters:**
* `agent` (AgentType): The agent to add. Must have `name`, `description`, and `system_prompt` attributes.
**Raises:**
* `Exception`: If there's an error generating the embedding or adding the agent.
***
### add\_agents()
Add multiple agents to the router at once.
```python theme={null}
def add_agents(self, agents: List[Union[AgentType, Callable, Any]]) -> None
```
**Parameters:**
* `agents` (List\[Union\[AgentType, Callable, Any]]): List of agents to add.
***
### find\_best\_agent()
Find the best matching agent for a given task using cosine similarity on embeddings.
```python theme={null}
def find_best_agent(self, task: str, *args, **kwargs) -> Optional[AgentType]
```
**Parameters:**
* `task` (str): The task description to match against agents.
**Returns:** The best matching agent if found, `None` otherwise.
***
### run()
Convenience method that calls `find_best_agent`. Run the agent router on a given task.
```python theme={null}
def run(self, task: str) -> Optional[AgentType]
```
**Parameters:**
* `task` (str): The task description to match against agents.
**Returns:** The best matching agent if found, `None` otherwise.
***
### update\_agent\_history()
Update the agent's embedding in the router with its interaction history. This allows the router to learn from past interactions and improve matching over time.
```python theme={null}
def update_agent_history(self, agent_name: str) -> None
```
**Parameters:**
* `agent_name` (str): The name of the agent to update.
This method updates the agent's embedding to include its conversation history, which can improve future routing decisions based on what the agent has learned or discussed.
## Usage Examples
### Basic Medical Use Case
```python theme={null}
from swarms import Agent
from swarms.structs.agent_router import AgentRouter
# Initialize the router
agent_router = AgentRouter(
embedding_model="text-embedding-ada-002",
n_agents=1,
agents=[
Agent(
agent_name="Symptom Checker",
agent_description="Expert agent for initial triage and identifying possible causes based on symptom input.",
system_prompt=(
"You are a medical symptom checker agent. Ask clarifying questions "
"about the patient's symptoms, duration, severity, and related risk factors. "
"Provide a list of possible conditions and next diagnostic steps, but do not make a final diagnosis."
),
),
Agent(
agent_name="Diagnosis Synthesizer",
agent_description="Agent specializing in synthesizing diagnostic possibilities from patient information and medical history.",
system_prompt=(
"You are a medical diagnosis assistant. Analyze the patient's reported symptoms, medical history, and any test results. "
"Provide a differential diagnosis, and highlight the most likely conditions a physician should consider."
),
),
Agent(
agent_name="Lab Interpretation Expert",
agent_description="Specializes in interpreting laboratory and imaging results for diagnostic support.",
system_prompt=(
"You are a medical lab and imaging interpretation agent. Take the patient's test results, imaging findings, and vitals, "
"and interpret them in context of their symptoms. Suggest relevant follow-up diagnostics or considerations for the physician."
),
),
],
)
# Route a task to the best agent
result = agent_router.run(
"I have a headache, fever, and cough. What could be wrong?"
)
# Use the selected agent
if result:
print(f"Selected agent: {result.agent_name}")
response = result.run("I have a headache, fever, and cough. What could be wrong?")
print(response)
# Update agent history after interaction
agent_router.update_agent_history(result.name)
```
### Finance Analysis Use Case
```python theme={null}
from swarms import Agent
from swarms.structs.agent_router import AgentRouter
# Define specialized finance agents
finance_agents = [
Agent(
agent_name="Market Analyst",
agent_description="Analyzes market trends and provides trading insights",
system_prompt="You are a financial market analyst specializing in market data analysis and trading insights."
),
Agent(
agent_name="Risk Assessor",
agent_description="Evaluates financial risks and compliance requirements",
system_prompt="You are a risk assessment specialist focusing on financial risk analysis and compliance."
),
Agent(
agent_name="Investment Strategist",
agent_description="Provides investment strategies and portfolio management",
system_prompt="You are an investment strategy specialist developing long-term financial planning strategies."
)
]
# Initialize router
finance_router = AgentRouter(
embedding_model="text-embedding-ada-002",
agents=finance_agents
)
# Route tasks
market_task = finance_router.run("Analyze current market conditions for technology sector")
if market_task:
market_analysis = market_task.run("Analyze current market conditions for technology sector")
risk_task = finance_router.run("Assess the risk profile for a cryptocurrency investment")
if risk_task:
risk_assessment = risk_task.run("Assess the risk profile for a cryptocurrency investment")
```
### Custom Embedding Model
```python theme={null}
from swarms.structs.agent_router import AgentRouter
# Use a different embedding model
router = AgentRouter(
embedding_model="text-embedding-3-large", # OpenAI's newer model
n_agents=1,
api_key="your-api-key", # Optional: specify API key
)
# Or use Cohere embeddings
cohere_router = AgentRouter(
embedding_model="cohere/embed-english-v3.0",
api_key="your-cohere-api-key"
)
```
### Dynamic Agent Addition
```python theme={null}
from swarms import Agent
from swarms.structs.agent_router import AgentRouter
# Initialize empty router
router = AgentRouter(embedding_model="text-embedding-ada-002")
# Add agents dynamically
agent1 = Agent(
agent_name="Data Extractor",
agent_description="Extracts structured data from documents",
system_prompt="You are a data extraction specialist..."
)
router.add_agent(agent1)
agent2 = Agent(
agent_name="Document Summarizer",
agent_description="Creates concise summaries of documents",
system_prompt="You are a document summarization expert..."
)
router.add_agent(agent2)
# Now use the router
best_agent = router.run("Extract key information from this contract")
```
## Best Practices
### Agent Descriptions
Provide clear, specific descriptions for agents to improve matching accuracy:
```python theme={null}
# Good: Specific description
Agent(
agent_name="Medical Diagnostician",
agent_description="Specializes in analyzing patient symptoms, medical history, and test results to provide differential diagnoses for common medical conditions.",
system_prompt="..."
)
# Poor: Vague description
Agent(
agent_name="Doctor",
agent_description="Helps with medical stuff",
system_prompt="..."
)
```
### Embedding Model Selection
| Provider | Model Names | Recommended Use |
| --------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| **OpenAI** | `text-embedding-ada-002`, `text-embedding-3-small`, `text-embedding-3-large` | Ada-002 is default, cost-effective; 3-small/large offer higher accuracy |
| **Cohere** | `cohere/embed-english-v3.0` | Excellent for English text |
| **HuggingFace** | `huggingface/microsoft/codebert-base` | Best for code-related tasks |
### Error Handling
Always handle cases where no agent is found:
```python theme={null}
best_agent = router.run(task)
if best_agent:
result = best_agent.run(task)
print(f"Task completed by {best_agent.name}: {result}")
else:
print("No suitable agent found for this task")
```
## Performance Considerations
1. **Embedding Generation**: The first time agents are added, embeddings are generated which can take a few seconds per agent
2. **API Rate Limits**: Be aware of rate limits when using embedding APIs, especially when adding many agents
3. **Caching**: The router doesn't cache task embeddings — consider caching results for repeated tasks
4. **Batch Processing**: For processing multiple tasks, consider batching or using concurrent execution
## Troubleshooting
### No Agent Found
If `find_best_agent` returns `None`:
1. Check that agents have been added: `len(router.agents) > 0`
2. Verify agent descriptions are clear and specific
3. Ensure the task description is detailed enough to match an agent
4. Check logs for embedding generation errors
### Low Similarity Scores
If agents are being matched but with low similarity:
1. Improve agent descriptions to be more specific
2. Enhance system prompts with more relevant keywords
3. Consider using a different embedding model
4. Update agent history after interactions to improve matching
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/agent_router.py)
# SubagentRegistry
Source: https://docs.swarms.world/api/async-subagent
Background async subagent execution with task tracking, retry policies, depth-limited recursion, and result aggregation
## Overview
`SubagentRegistry` runs agent tasks in the background on a `ThreadPoolExecutor`, tracking each as a `SubagentTask` with status, retries, depth, and parent linkage. Use it when one agent needs to fan out work to other agents — recursively if needed — and gather results later.
The module exports three symbols:
| Export | Kind | Purpose |
| ------------------ | ---------- | -------------------------------------------------------- |
| `SubagentRegistry` | class | Spawns and tracks tasks, gathers results |
| `SubagentTask` | dataclass | Per-task record with status, result, retry info |
| `TaskStatus` | `str` enum | `PENDING`, `RUNNING`, `COMPLETED`, `FAILED`, `CANCELLED` |
## Installation
```bash theme={null}
pip install -U swarms
```
## TaskStatus
```python theme={null}
from swarms import TaskStatus
TaskStatus.PENDING # spawned but not yet started
TaskStatus.RUNNING # currently executing
TaskStatus.COMPLETED # finished successfully
TaskStatus.FAILED # exhausted retries
TaskStatus.CANCELLED # cancelled before completion
```
Backed by `(str, Enum)`, so the values compare equal to plain strings (`TaskStatus.PENDING == "pending"`).
## SubagentTask
Dataclass describing a single in-flight or completed task. Populated by `SubagentRegistry.spawn()`.
Unique task ID, e.g. `task-a1b2c3d4`.
The agent instance assigned to this task.
The prompt/task handed to `agent.run(...)`.
Current execution status.
Return value from the agent — set when `status == COMPLETED`.
Last exception raised — set when `status == FAILED`.
Underlying `Future` returned by the thread pool.
ID of the parent task that spawned this one, if any.
Recursion depth — incremented when an agent spawns another subagent.
Number of retries used so far.
Retry budget for this task.
Whitelist of exception classes that trigger retries. `None` retries on any exception.
Unix timestamp when the task was spawned.
Unix timestamp when the task entered a terminal state.
## SubagentRegistry
### Constructor
```python theme={null}
from swarms import SubagentRegistry
registry = SubagentRegistry(max_depth=3, max_workers=None)
```
Maximum recursion depth. `spawn()` raises `ValueError` if `depth > max_depth`.
Thread-pool size. `None` defers to `ThreadPoolExecutor`'s default.
### Methods
#### spawn()
Submit an agent task to the pool. Returns the new task ID synchronously; the agent runs in the background.
```python theme={null}
def spawn(
self,
agent: Any,
task: str,
parent_id: Optional[str] = None,
depth: int = 0,
max_retries: int = 0,
retry_on: Optional[List[Type[Exception]]] = None,
fail_fast: bool = True,
) -> str
```
Agent instance with a `.run(task)` method.
The prompt to run.
Set when this task was spawned by another task. Used for tracking trees.
Recursion depth. Spawning from inside another task increments this.
Retry budget on failure.
Only retry on these exception types. `None` retries on any exception.
When `True`, the underlying thread re-raises on final failure (the exception surfaces when you call `future.result()`). When `False`, the failure is captured on the `SubagentTask` and the thread returns `None`.
**Raises:** `ValueError` if `depth > max_depth`.
#### get\_task()
Look up a `SubagentTask` by ID.
```python theme={null}
def get_task(self, task_id: str) -> SubagentTask
```
**Raises:** `KeyError` if the ID is not in the registry.
#### get\_results()
Return a `Dict[task_id, Any]` for every completed or failed task. Failed tasks map to their exception object.
```python theme={null}
def get_results(self) -> Dict[str, Any]
```
#### cancel()
Attempt to cancel a not-yet-started task. Returns `True` if the underlying `Future` accepted the cancellation.
```python theme={null}
def cancel(self, task_id: str) -> bool
```
#### gather()
Block until tasks complete and return a list of results.
```python theme={null}
def gather(
self,
strategy: str = "wait_all",
timeout: Optional[float] = None,
) -> List[Any]
```
Wait policy. `"wait_all"` returns once every pending task settles; `"wait_first"` returns as soon as one does.
Max seconds to wait. `None` blocks indefinitely.
**Returns:** Mixed list — successful tasks contribute their result, failed tasks contribute their exception object.
#### shutdown()
Tear down the thread pool without waiting for outstanding tasks.
```python theme={null}
def shutdown(self) -> None
```
#### tasks
Read-only property — snapshot of all known tasks as `Dict[task_id, SubagentTask]`.
```python theme={null}
@property
def tasks(self) -> Dict[str, SubagentTask]
```
## Usage Examples
### Fan Out, Gather, Map by Agent
```python theme={null}
from swarms import Agent, SubagentRegistry
researchers = [
Agent(agent_name=f"Researcher-{i}", model_name="claude-sonnet-4-6", max_loops=1)
for i in range(3)
]
registry = SubagentRegistry(max_workers=4)
topics = [
"Recent advances in RAG retrieval",
"Long-context LLM scaling laws",
"Agent tool-use benchmarks",
]
task_ids = [
registry.spawn(agent, topic)
for agent, topic in zip(researchers, topics)
]
results = registry.gather(strategy="wait_all")
for tid in task_ids:
print(registry.get_task(tid).status, registry.get_task(tid).result[:80])
registry.shutdown()
```
### Retries on Specific Exceptions
Retry only on transient network errors; surface anything else immediately.
```python theme={null}
import httpx
from swarms import Agent, SubagentRegistry
registry = SubagentRegistry()
agent = Agent(agent_name="Crawler", model_name="claude-sonnet-4-6", max_loops=1)
task_id = registry.spawn(
agent=agent,
task="Fetch and summarize https://example.com/whitepaper",
max_retries=3,
retry_on=[httpx.TimeoutException, httpx.NetworkError],
fail_fast=False,
)
registry.gather(timeout=60)
task = registry.get_task(task_id)
print(task.status, task.retries, task.result or task.error)
```
### Take the First Successful Result
```python theme={null}
from swarms import Agent, SubagentRegistry
registry = SubagentRegistry()
candidates = [
Agent(agent_name="GPT", model_name="gpt-5.4", max_loops=1),
Agent(agent_name="Claude", model_name="claude-sonnet-4-6", max_loops=1),
Agent(agent_name="Mistral", model_name="mistral-large", max_loops=1),
]
for agent in candidates:
registry.spawn(agent, "Draft a one-sentence product tagline for a developer-tools startup")
first_results = registry.gather(strategy="wait_first", timeout=30)
print(first_results[0])
```
### Depth-Limited Recursion
```python theme={null}
from swarms import Agent, SubagentRegistry
registry = SubagentRegistry(max_depth=2)
root = Agent(agent_name="Root", model_name="claude-sonnet-4-6", max_loops=1)
root_id = registry.spawn(root, "Plan a research project", depth=0)
# From inside a tool/handler the root agent can do:
# child_id = registry.spawn(child_agent, "Investigate sub-topic", parent_id=root_id, depth=1)
# Spawning at depth=3 would raise ValueError because max_depth=2.
```
## Source Code
View the [source on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/async_subagent.py).
# AutoAgentBuilder
Source: https://docs.swarms.world/api/auto-agent-builder
Generates a roster of agent configurations from a task using a single forced function call
## Overview
The `AutoAgentBuilder` class turns a plain-English task into a roster of agents. A single builder agent is forced to call one function, `build_agents`, and must answer with a list of agent configurations rather than prose.
Each generated agent carries exactly four fields — the minimum needed to construct an [`Agent`](/api/agent):
```
name, description, system_prompt, model_name
```
The builder designs the team and stops there. It does **not** choose a multi-agent architecture and it does **not** execute anything, so you decide what runs the roster.
Because the provider enforces the tool schema, there is no markdown fence to strip and no JSON to extract from a paragraph. This is the main behavioral difference from [`AutoSwarmBuilder`](/api/auto-swarm-builder), which uses structured output and also selects a `swarm_type` for you.
## Class Definition
```python theme={null}
from swarms import AutoAgentBuilder
```
## Parameters
Name of this builder instance
What this builder is for
Model backing the builder agent itself. This is not the model given to the generated agents — the builder chooses those per agent. Must support function calling
Upper bound on roster size. This is a **ceiling, not a target** — the builder is instructed to prefer the smallest roster that covers the task, so it will routinely return fewer. Must be >= 1
Exact number of agents to generate. When set, overrides `max_agents` and the builder's prefer-fewer guidance, and the count is verified on the result. Must be >= 1
Instructions for the builder agent. Override to constrain the roster — force a model tier, require a specific role, or restrict the decomposition strategy
Extra keyword arguments forwarded to every generated `Agent`, e.g. `max_loops` or `streaming_on`. Keys that collide with the four generated fields are ignored. Unused when `return_dict` is True, since no agent is constructed
When True, `run()` returns the raw configuration dicts instead of constructed `Agent` objects. Use this to inspect, serialize, or edit the roster before building anything from it
Whether to log the generated roster
**Raises:**
* `ValueError`: If `max_agents` or `num_agents` is less than 1
## Roster size: ceiling vs exact count
This is the setting most likely to surprise you.
| Parameter | Meaning | Result for a 3-role task |
| -------------- | --------------------------------------------------------------------- | ------------------------ |
| `max_agents=5` | A ceiling. The builder picks the smallest roster that covers the task | 3 agents |
| `num_agents=5` | A hard requirement. Overrides the prefer-fewer guidance | 5 agents |
The default system prompt actively pushes the count down — it states that "fewer is almost always better" and that "2–3 agents is the common, correct case for most tasks." So `max_agents=5` returning three agents is the builder working correctly, not a failure.
```python theme={null}
# Ceiling — the builder decides how many it needs
AutoAgentBuilder(max_agents=5).run(task)
# Exact — the builder must split the work to reach five
AutoAgentBuilder(num_agents=5).run(task)
```
If the model returns fewer than `num_agents`, a warning is logged and the shorter roster is returned. Agents cannot be fabricated for a task that does not support them.
## Methods
### `run()`
```python theme={null}
def run(self, task: str) -> Union[List[Agent], List[Dict[str, str]]]
```
Generates the roster in the shape this builder was configured for.
**Parameters:**
The task the generated team should be able to handle
**Returns:**
Configuration dicts when `return_dict=True`, otherwise constructed `Agent` objects
**Raises:**
* `ValueError`: If `task` is empty, or the builder returns no usable agent configurations
***
### `batch_run()`
```python theme={null}
def batch_run(self, tasks: List[str]) -> Any
```
Generates a roster for each task in sequence by calling `run()` once per task.
**Parameters:**
The tasks the generated team should be able to handle
**Returns:**
The roster generated for each task, in the same shape `run()` would return per task
***
### `build_agents()`
```python theme={null}
def build_agents(self, task: str) -> List[Agent]
```
Generates configurations and constructs the `Agent` objects. Ignores `return_dict` — this is the shape-specific entry point for callers that want agents regardless of how the builder was configured.
**Returns:**
Constructed agents, ready to run or hand to a multi-agent structure. `agent_kwargs` is applied to each
***
### `build_configs()`
```python theme={null}
def build_configs(self, task: str) -> List[Dict[str, str]]
```
Generates agent configurations for a task, always as dicts. Ignores `return_dict`.
**Returns:**
One dict per agent with `name`, `description`, `system_prompt` and `model_name`. Truncated to `num_agents` or `max_agents`
***
### `__call__()`
```python theme={null}
def __call__(self, task: str) -> Union[List[Agent], List[Dict[str, str]]]
```
Alias for `run()`. Follows `return_dict`.
## Output shapes
```python theme={null}
AutoAgentBuilder().run(task) # -> [Agent, Agent, ...]
AutoAgentBuilder(return_dict=True).run(task) # -> [{...}, {...}, ...]
builder.build_agents(task) # always Agent objects
builder.build_configs(task) # always configuration dicts
```
## One LLM call per method
Every public method triggers a fresh call, and the builder is not deterministic. Calling `build_configs()` and then `build_agents()` designs **two different rosters** — so what you printed may not be what you ran.
Generate once and reuse the result:
```python theme={null}
configs = builder.build_configs(task)
agents = [
Agent(
agent_name=c["name"],
agent_description=c["description"],
system_prompt=c["system_prompt"],
model_name=c["model_name"],
max_loops=1,
)
for c in configs
]
```
## Validation behavior
The builder filters the model's output before returning it:
| Condition | Behavior |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| Entry missing any of the four fields | Dropped, warning logged |
| Duplicate `name` | Dropped, warning logged. `Agent` memory is keyed on `agent_name`, so duplicates would corrupt each other's state |
| More agents than the limit | Truncated to `num_agents` or `max_agents`, warning logged |
| Fewer than `num_agents` | Returned as-is, warning logged |
| No usable entries at all | Raises `ValueError` |
| Malformed or non-JSON tool output | Raises `ValueError` |
Tool calls are parsed from all shapes providers return: a plain dict, a list-wrapped dict, or an attribute-style object such as litellm's `ChatCompletionMessageToolCall`.
## Usage Examples
### Inspect the roster before building
```python theme={null}
from swarms import AutoAgentBuilder
builder = AutoAgentBuilder(model_name="gpt-5.4", max_agents=3, return_dict=True)
for config in builder.run("Analyze why SaaS churn increased last quarter."):
print(f"{config['name']} [{config['model_name']}]")
print(f" {config['description']}")
```
### Build and run in sequence
```python theme={null}
from swarms import AutoAgentBuilder, SequentialWorkflow
agents = AutoAgentBuilder(num_agents=3, agent_kwargs={"max_loops": 1}).run(task)
result = SequentialWorkflow(agents=agents, max_loops=1).run(task)
```
### Compose with SwarmRouter
The builder answers *who is on the team*; [`SwarmRouter`](/api/swarm-router) answers *how they run*.
```python theme={null}
from swarms import AutoAgentBuilder, SwarmRouter
agents = AutoAgentBuilder(max_agents=4).run(task)
router = SwarmRouter(agents=agents, swarm_type="ConcurrentWorkflow", max_loops=1)
result = router.run(task)
```
Since the roster is just a list of agents, it also drops into `MixtureOfAgents`, `HierarchicalSwarm`, `GroupChat`, or anything else that accepts one.
### Constrain the roster with a custom prompt
```python theme={null}
from swarms.prompts.auto_agent_builder_prompt import (
AUTO_AGENT_BUILDER_SYSTEM_PROMPT,
)
CONSTRAINED = AUTO_AGENT_BUILDER_SYSTEM_PROMPT + """
ADDITIONAL CONSTRAINTS:
- Every agent must use model_name "gpt-5.4-mini".
- Include exactly one agent whose sole job is to verify the others' output.
"""
builder = AutoAgentBuilder(system_prompt=CONSTRAINED, num_agents=4)
```
## The builder system prompt
The default prompt is exported and can be imported, extended, or replaced:
```python theme={null}
from swarms import AUTO_AGENT_BUILDER_SYSTEM_PROMPT
```
It instructs the builder to:
| Area | Guidance |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Decomposition** | Split by stage, domain, source, or perspective — and pick one seam rather than mixing them |
| **Sizing** | Prefer the smallest roster; a single agent is a valid answer. An explicit exact count overrides this |
| **Merge test** | Merge any two agents where one competent specialist could do both jobs |
| **Coverage test** | Confirm every part of the task has an owner; gaps are worse than redundancy |
| **`system_prompt` field** | Several paragraphs covering identity, responsibility, method, output, and standards — the generated agent never sees the builder prompt or its teammates' prompts, so each must stand alone |
| **`model_name` field** | Match the model to cognitive load, not to the agent's importance. Mixing tiers is a sign of good design |
## Comparison with AutoSwarmBuilder
| | `AutoAgentBuilder` | [`AutoSwarmBuilder`](/api/auto-swarm-builder) |
| ------------------------ | -------------------- | ---------------------------------------------------- |
| Output | Agent roster only | Roster plus `swarm_type` and optional execution |
| Structured output method | Forced function call | `response_format` |
| Fields per agent | 4 | 10+ (`max_tokens`, `temperature`, `role`, `goal`, …) |
| Picks architecture | No | Yes |
| Executes the task | No | Optionally |
Use `AutoAgentBuilder` when you want the roster and full control over what runs it. Use `AutoSwarmBuilder` when you want the whole pipeline decided for you.
## Requirements
The builder needs a model that supports function calling, plus a provider key:
```bash theme={null}
export OPENAI_API_KEY=sk-...
```
Generated agents may name a different provider than the builder — it chooses a model per agent and deliberately mixes tiers. If a roster references a provider you have no key for, set that key or edit `model_name` on the configs before constructing.
## Source Code
* [`swarms/structs/auto_agent_builder.py`](https://github.com/kyegomez/swarms/blob/master/swarms/structs/auto_agent_builder.py)
* [`swarms/prompts/auto_agent_builder_prompt.py`](https://github.com/kyegomez/swarms/blob/master/swarms/prompts/auto_agent_builder_prompt.py)
* [Examples](https://github.com/kyegomez/swarms/tree/master/examples/multi_agent/auto_agent_builder_examples)
# AutoSwarmBuilder
Source: https://docs.swarms.world/api/auto-swarm-builder
Automatically builds and manages swarms of AI agents with intelligent task decomposition
## Overview
The `AutoSwarmBuilder` class automatically builds and manages swarms of AI agents by intelligently decomposing tasks and creating specialized agents as needed. It uses a sophisticated boss agent system to delegate work, design agent architectures, and orchestrate multi-agent collaboration.
## Class Definition
```python theme={null}
from swarms import AutoSwarmBuilder
```
## Parameters
The name of the swarm builder instance
A description of the swarm builder's purpose
Whether to output detailed logs during execution
Maximum number of execution loops. Must be greater than 0
The LLM model to use for the boss agent that designs the swarm architecture
Maximum tokens for the LLM responses from the boss agent
Type of execution to perform. Options: "return-agents", "return-swarm-router-config", "return-agents-objects"
System prompt for the boss agent that designs swarm architectures. Defaults to comprehensive agent design prompt
Additional arguments to pass to the LiteLLM wrapper
Default value for `run()`'s `execute` parameter. When `True`, `run()` builds real `Agent` objects from a freshly generated spec and executes them through a `SwarmRouter` (via `build_and_run_swarm()`) instead of returning a spec-only result
## Execution Types
### return-agents
Returns agent specifications as a dictionary:
```python theme={null}
{
"agents": [
{
"agent_name": "Research-Agent",
"description": "Expert in research",
"system_prompt": "...",
"model_name": "gpt-5.4",
...
},
...
]
}
```
### return-swarm-router-config
Returns complete SwarmRouter configuration:
```python theme={null}
{
"name": "Research-Team",
"description": "...",
"agents": [...],
"swarm_type": "SequentialWorkflow",
"rearrange_flow": "...",
"rules": "...",
"task": "..."
}
```
### return-agents-objects
Returns instantiated Agent objects ready for use:
```python theme={null}
[Agent(...), Agent(...), Agent(...)]
```
## Methods
### `run()`
```python theme={null}
def run(self, task: str, execute: Optional[bool] = None, *args, **kwargs) -> Any
```
Runs the swarm builder on a given task, creating agents based on execution type.
**Parameters:**
The task to execute. The boss agent will analyze this task and design an appropriate swarm architecture
When `True`, builds real agents and a `SwarmRouter` from a freshly generated spec and runs it (see `build_and_run_swarm()`), returning a dict that includes the execution output. When `False`, only a spec-only result is returned, per `swarm_type`. Defaults to `self.auto_execute` when left as `None`
**Returns:**
When executing (`execute` resolves to `True`): a dict from `build_and_run_swarm()`. Otherwise, the result depends on swarm\_type:
* "return-agents": Dictionary with agent specifications
* "return-swarm-router-config": SwarmRouter configuration dictionary
* "return-agents-objects": List of instantiated Agent objects
**Raises:**
* `ValueError`: If swarm\_type is invalid
* `Exception`: If there's an error during swarm execution
***
### `build_and_run_swarm()`
```python theme={null}
def build_and_run_swarm(self, task: str) -> dict
```
Designs a multi-agent team for `task` and executes it. Generates one validated `SwarmRouterConfig`, builds the real `Agent` objects from that same spec's agents, and runs a `SwarmRouter` with them — so the agents that execute are exactly the ones described in the returned metadata, unlike chaining `create_agents()` and `initialize_swarm_router()` (which make two independent, potentially-disagreeing LLM calls). This is what `run()` calls when `execute` resolves to `True`.
**Parameters:**
The task to design and run a swarm for
**Returns:**
`{"name", "description", "agents" (names actually built), "swarm_type", "task", "output"}` where `output` is the `SwarmRouter`'s execution result
***
### `create_agents()`
```python theme={null}
def create_agents(self, task: str) -> dict
```
Creates agent specifications for a given task using the boss agent.
**Parameters:**
The task to create agents for
**Returns:**
Dictionary containing agent specifications with comprehensive system prompts and configurations
**Raises:**
* `Exception`: If there's an error during agent creation
***
### `create_agents_from_specs()`
```python theme={null}
def create_agents_from_specs(
self,
agents_dictionary: Any
) -> List[Agent]
```
Creates Agent objects from agent specifications.
**Parameters:**
Dictionary or Pydantic model containing agent specifications
**Returns:**
List of instantiated Agent objects ready for use
**Note:** Automatically handles parameter name mapping (e.g., 'description' → 'agent\_description')
***
### `create_router_config()`
```python theme={null}
def create_router_config(self, task: str) -> dict
```
Creates a SwarmRouter configuration for a given task.
**Parameters:**
The task to create router configuration for
**Returns:**
Complete SwarmRouter configuration including agents, swarm type, and execution parameters
**Raises:**
* `Exception`: If there's an error during router config creation
***
### `batch_run()`
```python theme={null}
def batch_run(self, tasks: List[str]) -> List[Any]
```
Runs the swarm builder on a list of tasks sequentially.
**Parameters:**
List of tasks to execute
**Returns:**
List of results from each task execution
***
### `reliability_check()`
```python theme={null}
def reliability_check(self) -> None
```
Performs reliability checks on the AutoSwarmBuilder configuration.
**Raises:**
* `ValueError`: If max\_loops is set to 0
***
### `list_types()`
```python theme={null}
def list_types(self) -> List[str]
```
Lists all available execution types.
**Returns:**
List of available execution types
***
### `initialize_swarm_router()`
```python theme={null}
def initialize_swarm_router(self, agents: List[Agent], task: str) -> Any
```
Builds a `SwarmRouterConfig` for the task via the boss agent, then constructs and runs a `SwarmRouter` with the given agents. Not called automatically by `run()` for any `swarm_type` — call it directly if you want `AutoSwarmBuilder` to both design agents (via `create_agents`) and immediately execute them through a `SwarmRouter`.
**Parameters:**
Agents to pass to the constructed `SwarmRouter`
The task used to derive the `SwarmRouter` configuration and to execute
**Returns:** Result of `swarm_router.run(task)`
**Raises:** `Exception` if router config generation or execution fails
***
### `dict_to_agent()`
```python theme={null}
def dict_to_agent(self, output: dict) -> List[Agent]
```
Alternate helper that builds `Agent` objects directly from a raw `{"agents": [...]}` dictionary via `Agent(**agent_config)`, without the field-name mapping (`description` → `agent_description`) that `create_agents_from_specs()` performs.
**Parameters:**
Dictionary containing an `"agents"` list of agent configuration dicts
**Returns:** `List[Agent]`
## Data Models
### AgentSpec
```python theme={null}
class AgentSpec(BaseModel):
agent_name: Optional[str] # Agent's unique name
description: Optional[str] # Detailed agent description
system_prompt: Optional[str] # Complete system prompt
model_name: Optional[str] = "gpt-5.4" # LLM model name
auto_generate_prompt: Optional[bool] = False
max_tokens: Optional[int] = 8192
temperature: Optional[float] = 0.5
role: Optional[str] = "worker"
max_loops: Optional[int] = 1
goal: Optional[str] # Agent's primary objective
```
### SwarmRouterConfig
```python theme={null}
class SwarmRouterConfig(BaseModel):
name: str # Team name
description: str # Team description
agents: List[AgentSpec] # Agent configurations
swarm_type: SwarmType # Multi-agent structure type
rearrange_flow: Optional[str] # Flow configuration
rules: Optional[str] # Rules for all agents
multi_agent_collab_prompt: Optional[str]
task: str # Task to execute
```
## Boss Agent Design Principles
The AutoSwarmBuilder uses a sophisticated boss agent with expertise in:
1. **Comprehensive Task Analysis**: Deconstructing tasks into components and sub-tasks
2. **Agent Design Excellence**: Creating agents with clear purposes and complementary personalities
3. **System Prompt Engineering**: Crafting detailed prompts with role, capabilities, and protocols
4. **Multi-Agent Coordination**: Designing communication channels and task handoff procedures
5. **Quality Assurance**: Establishing success criteria and validation procedures
## Usage Examples
### Basic Agent Creation
```python theme={null}
from swarms import AutoSwarmBuilder
# Create swarm builder
builder = AutoSwarmBuilder(
name="intelligent-swarm-builder",
model_name="claude-sonnet-4-6",
swarm_type="return-agents",
verbose=True
)
# Generate agent specifications
agent_specs = builder.run(
task="Create a team to analyze financial reports and generate investment recommendations"
)
print(agent_specs)
```
### Create Agent Objects
```python theme={null}
builder = AutoSwarmBuilder(
name="agent-factory",
swarm_type="return-agents-objects",
model_name="claude-sonnet-4-6"
)
# Get ready-to-use Agent objects
agents = builder.run(
task="Build a content creation team with research, writing, and editing capabilities"
)
# Use the agents
for agent in agents:
result = agent.run("Write an article about AI trends")
print(f"{agent.agent_name}: {result}")
```
### Generate SwarmRouter Config
```python theme={null}
builder = AutoSwarmBuilder(
name="swarm-architect",
swarm_type="return-swarm-router-config",
model_name="claude-sonnet-4-6"
)
config = builder.run(
task="Design a hierarchical swarm for comprehensive market research and analysis"
)
print(f"Swarm Type: {config['swarm_type']}")
print(f"Number of Agents: {len(config['agents'])}")
```
### Batch Processing
```python theme={null}
builder = AutoSwarmBuilder(
swarm_type="return-agents-objects"
)
tasks = [
"Create a customer service team",
"Build a data analysis team",
"Design a creative writing team"
]
results = builder.batch_run(tasks)
for i, agents in enumerate(results):
print(f"Team {i+1}: {len(agents)} agents created")
```
## Advanced Features
### Custom System Prompt
```python theme={null}
custom_prompt = """
You are an expert swarm architect specializing in financial analysis teams.
Design agents with deep expertise in financial modeling, risk assessment,
and investment strategy.
"""
builder = AutoSwarmBuilder(
system_prompt=custom_prompt,
model_name="claude-sonnet-4-6"
)
agents = builder.run("Create a financial analysis team")
```
### Additional LLM Arguments
```python theme={null}
builder = AutoSwarmBuilder(
model_name="claude-sonnet-4-6",
additional_llm_args={
"api_base": "https://custom-endpoint.com",
"api_key": "custom-key",
"timeout": 60
}
)
```
## Multi-Agent Architecture Types
The boss agent can design swarms using various architectures:
* **AgentRearrange**: Dynamic task reallocation
* **MixtureOfAgents**: Parallel specialized processing
* **SequentialWorkflow**: Linear task progression
* **ConcurrentWorkflow**: Parallel execution
* **GroupChat**: Collaborative discussion
* **HierarchicalSwarm**: Layered decision-making
* **HeavySwarm**: High-capacity specialized processing
* **MajorityVoting**: Democratic decision-making
* **And more...**
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/auto_swarm_builder.py)
# BatchedGridWorkflow
Source: https://docs.swarms.world/api/batched-grid-workflow
Multi-agent orchestration pattern that executes tasks in a batched grid format with parallel processing
## Overview
The `BatchedGridWorkflow` is a multi-agent orchestration pattern that executes tasks in a batched grid format, where each agent processes a different task simultaneously. This workflow is particularly useful for parallel processing scenarios where you have multiple agents and multiple tasks that can be distributed across them.
The BatchedGridWorkflow provides a structured approach to:
* Execute multiple tasks across multiple agents in parallel
* Manage conversation state across execution loops
* Handle error scenarios gracefully
* Control the number of execution iterations
## Architecture
```mermaid theme={null}
graph TD
A[Input Tasks] --> B[BatchedGridWorkflow]
B --> C[Initialize Agents]
C --> E[Start Execution Loop]
E --> F[Distribute Tasks to Agents]
F --> G[Agent 1: Task 1]
F --> H[Agent 2: Task 2]
F --> I[Agent N: Task N]
G --> J[Collect Results]
H --> J
I --> J
J --> L{More Loops?}
L -->|Yes| E
L -->|No| M[Return Final Results]
M --> N[Output]
```
## Installation
```bash theme={null}
pip install -U swarms
```
## Key Features
| Feature | Description |
| ---------------------- | ----------------------------------------------------------------- |
| **Parallel Execution** | Multiple agents work on different tasks simultaneously |
| **Error Handling** | Comprehensive error logging and exception handling |
| **Configurable Loops** | Control the number of execution iterations |
| **Agent Flexibility** | Supports any agent type that implements the `AgentType` interface |
## Attributes
Unique identifier for the workflow. Auto-generated via `generate_id("batched-grid-workflow")` if not provided, producing `batched-grid-workflow-<32 hex chars>`.
Name of the workflow.
Description of what the workflow does.
List of agents to execute tasks.
Maximum number of execution loops to run (must be >= 1).
`BatchedGridWorkflow` does not currently accept an `output_type` parameter — there is no earlier documented parameter in the constructor beyond the ones listed above, and it does not maintain a `Conversation` object internally.
## Methods
### step()
Execute one step of the batched grid workflow. Pairs each agent with the task at the same index and runs all agent/task pairs concurrently via `batched_grid_agent_execution`. The number of `tasks` must match the number of `agents`.
```python theme={null}
def step(self, tasks: List[str])
```
**Parameters:**
* `tasks` (List\[str]): List of tasks to execute, one per agent (must be the same length as `agents`)
**Returns:** `List[Any]` - Results from each agent, in the same order as `agents`. If an agent fails, the exception is included in the results.
### run()
Run the batched grid workflow with the given tasks for `max_loops` iterations. This is the main entry point that includes error handling (logs and re-raises any exception).
```python theme={null}
def run(self, tasks: List[str]) -> List[List[Any]]
```
**Parameters:**
* `tasks` (List\[str]): List of tasks to execute, one per agent
**Returns:** `List[List[Any]]` - A list with one entry per loop iteration; each entry is the list of per-agent results returned by `step()` for that loop.
### run\_()
Internal method that runs the workflow without the top-level try/except error handling.
```python theme={null}
def run_(self, tasks: List[str]) -> List[List[Any]]
```
**Parameters:**
* `tasks` (List\[str]): List of tasks to execute, one per agent
**Returns:** `List[List[Any]]` - A list with one entry per loop iteration; each entry is the list of per-agent results returned by `step()` for that loop.
## Usage Examples
### Basic Usage
```python theme={null}
from swarms import Agent, BatchedGridWorkflow
# Initialize the ETF-focused agent
agent = Agent(
agent_name="ETF-Research-Agent",
agent_description="Specialized agent for researching, analyzing, and recommending Exchange-Traded Funds (ETFs) across various sectors and markets.",
model_name="claude-sonnet-4-20250514",
dynamic_temperature_enabled=True,
max_loops=1,
dynamic_context_window=True,
)
# Create workflow with default settings
workflow = BatchedGridWorkflow(agents=[agent, agent])
# Define simple tasks
tasks = [
"What are the best GOLD ETFs?",
"What are the best american energy ETFs?",
]
# Run the workflow
result = workflow.run(tasks)
print(result)
```
### Multi-Loop Execution
```python theme={null}
from swarms import Agent, BatchedGridWorkflow
# Create workflow with multiple loops
workflow = BatchedGridWorkflow(
agents=[agent1, agent2, agent3],
max_loops=3,
)
# Execute tasks with multiple iterations
tasks = ["Task 1", "Task 2", "Task 3"]
result = workflow.run(tasks)
```
## Error Handling
The workflow includes comprehensive error handling:
* **Validation**: Ensures `max_loops` is a positive integer
* **Execution Errors**: Catches and logs exceptions during execution
* **Detailed Logging**: Provides detailed error information including traceback
## Best Practices
| Best Practice | Description |
| ----------------------- | ----------------------------------------------------------------------------- |
| **Agent Selection** | Choose agents with complementary capabilities for diverse task processing |
| **Task Distribution** | Ensure tasks are well-distributed and can be processed independently |
| **Loop Configuration** | Use multiple loops when iterative refinement is needed |
| **Error Monitoring** | Monitor logs for execution errors and adjust agent configurations accordingly |
| **Resource Management** | Consider computational resources when setting up multiple agents |
## Use Cases
| Use Case | Description |
| ----------------------- | ------------------------------------------------------------------------- |
| **Content Generation** | Multiple writers working on different topics |
| **Data Analysis** | Different analysts processing various datasets |
| **Research Tasks** | Multiple researchers investigating different aspects of a problem |
| **Parallel Processing** | Any scenario requiring simultaneous task execution across multiple agents |
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/batched_grid_workflow.py)
# ConcurrentWorkflow
Source: https://docs.swarms.world/api/concurrent-workflow
A concurrent workflow system for running multiple agents simultaneously on the same task
## Overview
The `ConcurrentWorkflow` class provides a framework for executing multiple agents concurrently on the same task, with optional dashboard monitoring, streaming callbacks, and various output formatting options. It uses ThreadPoolExecutor to manage concurrent execution and provides real-time status tracking for each agent.
## Key Features
* **Concurrent Execution**: Run multiple agents simultaneously on the same task
* **Real-time Dashboard**: Monitor agent status and outputs in real-time
* **Streaming Callbacks**: Get real-time updates as agents generate outputs
* **Flexible Output Formatting**: Multiple output format options
* **Auto-save Support**: Automatically save conversation history
* **Error Handling**: Graceful error handling with status tracking
* **Batch Processing**: Process multiple tasks sequentially with concurrent agents
## Installation
```bash theme={null}
pip install -U swarms
```
## Class Definition
```python theme={null}
class ConcurrentWorkflow:
def __init__(
self,
id: str = None,
name: str = "ConcurrentWorkflow",
description: str = "Execution of multiple agents concurrently",
agents: List[Union[Agent, Callable]] = None,
auto_save: bool = True,
output_type: str = "dict-all-except-first",
max_loops: int = 1,
auto_generate_prompts: bool = False,
show_dashboard: bool = False,
autosave: bool = True,
verbose: bool = False,
)
```
## Parameters
Unique identifier for the workflow instance. Auto-generated if not provided.
Human-readable name for the workflow
Description of the workflow's purpose
List of agents to execute concurrently. Must not be None or empty.
Whether to automatically save workflow metadata
Format for output formatting. Options include "dict-all-except-first", "dict", "list", "str"
Maximum number of execution loops (currently unused in concurrent execution)
Accepted and stored, but never read — setting it has no effect. The
`activate_auto_prompt_engineering()` method that once consumed it no longer
exists.
Whether to display real-time dashboard during execution
Whether to automatically save conversation history to workspace
How to handle an agent that raises. `"store"` records the error as that agent's output and lets the rest finish; `"raise"` propagates the first error and aborts the run.
Thread pool size. Defaults to `len(agents)` capped at 32. Agent calls are network-bound, so this is sized by agent count rather than CPU cores.
Whether to enable verbose logging
## Methods
### `run(task, img=None, imgs=None, streaming_callback=None)`
Execute all agents concurrently on the given task.
The task to be executed by all agents
Single image path for agents that support image input
List of image paths for agents that support multiple images
Callback function for streaming updates. Called with (agent\_name, chunk, is\_final) parameters.
Formatted conversation history based on output\_type
### `batch_run(tasks, imgs=None, streaming_callback=None)`
Execute workflow on multiple tasks sequentially.
List of tasks to be executed
List of image paths corresponding to each task
Callback function for streaming updates
List of results for each task
### `run_with_dashboard(task, img=None, imgs=None, streaming_callback=None)`
Execute agents with real-time dashboard monitoring.
The task to be executed by all agents
Single image path for agents that support image input
List of image paths for agents that support multiple images
Callback function for streaming updates
Formatted conversation history based on output\_type
### `fix_agents()`
Configure agents for dashboard mode. Disables printing (`agent.print_on = False`) for every agent when `show_dashboard=True`, to prevent console output from conflicting with the dashboard display. Called automatically during initialization when `show_dashboard=True`.
The configured list of agents
### `reliability_check()`
Validate workflow configuration.
**Raises:**
* `ValueError`: If no agents are provided or agents list is empty
### `display_agent_dashboard(title="ConcurrentWorkflow Dashboard", is_final=False)`
Display real-time dashboard showing agent status and outputs.
Title to display for the dashboard
Whether this is the final dashboard display
## Attributes
| Attribute | Type | Description |
| ---------------------- | ------------------------------ | --------------------------------------------------- |
| `id` | str | Unique identifier for the workflow instance |
| `name` | str | Human-readable name for the workflow |
| `description` | str | Description of the workflow's purpose |
| `agents` | List\[Union\[Agent, Callable]] | List of agents to execute concurrently |
| `agent_statuses` | dict | Dictionary tracking status and output of each agent |
| `conversation` | Conversation | Conversation object for storing agent interactions |
| `metadata_output_path` | str | Path for saving workflow metadata |
## Usage Examples
### Basic Concurrent Workflow
```python theme={null}
from swarms import Agent, ConcurrentWorkflow
# Create specialized agents with different perspectives
technical_analyst = Agent(
agent_name="Technical-Analyst",
model_name="claude-sonnet-4-6",
temperature=0.5,
max_loops=1,
system_prompt="You are a technical analyst. Analyze from a technical perspective."
)
business_analyst = Agent(
agent_name="Business-Analyst",
model_name="claude-sonnet-4-6",
temperature=0.5,
max_loops=1,
system_prompt="You are a business analyst. Analyze from a business perspective."
)
user_researcher = Agent(
agent_name="User-Researcher",
model_name="claude-sonnet-4-6",
temperature=0.5,
max_loops=1,
system_prompt="You are a user researcher. Analyze from a user experience perspective."
)
# Create concurrent workflow
workflow = ConcurrentWorkflow(
name="Multi-Perspective Analysis",
description="Analyze from multiple perspectives simultaneously",
agents=[technical_analyst, business_analyst, user_researcher],
verbose=True
)
# Run all agents concurrently on the same task
result = workflow.run("Analyze the potential of implementing AI chatbots in customer service")
print(result)
```
### With Real-Time Dashboard
```python theme={null}
# Create workflow with dashboard enabled
workflow = ConcurrentWorkflow(
name="Analysis with Dashboard",
agents=[technical_analyst, business_analyst, user_researcher],
show_dashboard=True, # Enable real-time dashboard
verbose=True
)
# Run and watch the dashboard update in real-time
result = workflow.run("Evaluate the impact of remote work on productivity")
```
### With Streaming Callbacks
```python theme={null}
def handle_stream(agent_name: str, chunk: str, is_final: bool):
"""Custom streaming callback to handle real-time updates"""
if is_final:
print(f"\n[{agent_name}] Completed!")
else:
print(f"[{agent_name}] {chunk}", end="", flush=True)
workflow = ConcurrentWorkflow(
name="Streaming Analysis",
agents=[technical_analyst, business_analyst],
)
# Get real-time streaming updates
result = workflow.run(
"Analyze cybersecurity trends",
streaming_callback=handle_stream
)
```
### Batch Processing
```python theme={null}
# Process multiple tasks sequentially, with agents running concurrently on each
tasks = [
"Analyze the impact of AI on healthcare",
"Evaluate renewable energy solutions",
"Assess blockchain technology trends"
]
workflow = ConcurrentWorkflow(
name="Batch Analysis",
agents=[technical_analyst, business_analyst, user_researcher],
)
results = workflow.batch_run(tasks)
for i, (task, result) in enumerate(zip(tasks, results), 1):
print(f"\nTask {i}: {task}")
print(f"Result: {result}")
print("-" * 80)
```
### With Image Input
```python theme={null}
from swarms import Agent, ConcurrentWorkflow
# claude-sonnet-4-6 is vision-capable — no separate vision wrapper needed
image_analyst1 = Agent(
agent_name="Image-Analyst-1",
model_name="claude-sonnet-4-6",
system_prompt="Analyze images for technical details"
)
image_analyst2 = Agent(
agent_name="Image-Analyst-2",
model_name="claude-sonnet-4-6",
system_prompt="Analyze images for aesthetic quality"
)
workflow = ConcurrentWorkflow(
agents=[image_analyst1, image_analyst2],
)
# Analyze image with multiple agents concurrently
result = workflow.run(
"Analyze this product image",
img="path/to/product.jpg"
)
```
### Custom Output Types
```python theme={null}
# Different output formats
workflow_dict = ConcurrentWorkflow(
agents=[technical_analyst, business_analyst],
output_type="dict" # Returns dict with all agent outputs
)
workflow_list = ConcurrentWorkflow(
agents=[technical_analyst, business_analyst],
output_type="list" # Returns list of outputs
)
workflow_dict_except_first = ConcurrentWorkflow(
agents=[technical_analyst, business_analyst],
output_type="dict-all-except-first" # Skip first agent in output dict
)
```
### With Autosave
```python theme={null}
import os
# Set workspace directory
os.environ["WORKSPACE_DIR"] = "./analysis_workspace"
workflow = ConcurrentWorkflow(
name="Saved-Analysis",
agents=[technical_analyst, business_analyst],
autosave=True, # Save conversation history
verbose=True
)
result = workflow.run("Analyze market trends")
# Conversation saved to ./analysis_workspace/swarms/ConcurrentWorkflow/
```
## Error Handling
```python theme={null}
try:
workflow = ConcurrentWorkflow(
agents=[technical_analyst, business_analyst],
show_dashboard=True
)
result = workflow.run("Analyze this topic")
except ValueError as e:
print(f"Configuration error: {e}")
except Exception as e:
print(f"Execution error: {e}")
finally:
# Cleanup is called automatically
pass
```
## Dashboard Output Example
When `show_dashboard=True`, you'll see real-time updates like:
```
╔═══════════════════════════════════════════════════════════════╗
║ ConcurrentWorkflow Dashboard ║
╠═══════════════════════════════════════════════════════════════╣
║ Agent: Technical-Analyst ║
║ Status: running ║
║ Output: Analyzing technical aspects... ║
╠═══════════════════════════════════════════════════════════════╣
║ Agent: Business-Analyst ║
║ Status: completed ║
║ Output: The business impact is significant... ║
╠═══════════════════════════════════════════════════════════════╣
║ Agent: User-Researcher ║
║ Status: pending ║
║ Output: ║
╚═══════════════════════════════════════════════════════════════╝
```
## Best Practices
1. **Agent Diversity**: Use agents with different perspectives for richer analysis
2. **Dashboard for Monitoring**: Enable dashboard during development to monitor agent progress
3. **Streaming Callbacks**: Use streaming callbacks for real-time feedback in production
4. **Error Handling**: Always wrap concurrent execution in try-except blocks
5. **Resource Management**: Be mindful of API rate limits when running many agents
6. **Task Design**: Ensure the task benefits from multiple concurrent perspectives
7. **Autosave**: Enable autosave for important analyses
## Common Use Cases
* **Multi-Perspective Analysis**: Get technical, business, and user perspectives simultaneously
* **Consensus Building**: Run multiple agents and aggregate their outputs
* **Parallel Research**: Research different aspects of a topic concurrently
* **Voting Systems**: Multiple agents vote on decisions
* **Quality Assurance**: Multiple agents review the same content
* **Competitive Analysis**: Different agents analyze competing solutions
## Performance Considerations
* **Concurrency**: Thread pool sized by agent count, capped at 32 (`MAX_CONCURRENT_AGENTS`). Agent calls are network-bound, so this does not derive from CPU core count. Override with `max_workers`.
* **Concurrent Execution**: All agents run truly concurrently using ThreadPoolExecutor
* **Memory Usage**: Each agent maintains its own context, consider memory for many agents
* **API Rate Limits**: Be aware of rate limits when using cloud-based LLMs
## Related Classes
* [SequentialWorkflow](/api/sequential-workflow): For sequential agent execution
* [AgentRearrange](/api/agent-rearrange): For complex orchestration patterns
* [GraphWorkflow](/api/graph-workflow): For DAG-based workflows
* [Agent](/api/agent): The base agent class used in workflows
# Conversation
Source: https://docs.swarms.world/api/conversation
A class to manage conversation history with in-memory storage, supporting multiple export formats and automatic token management
## Overview
The `Conversation` class manages conversation history for agents, allowing for addition, deletion, and retrieval of messages. It supports saving and loading in JSON/YAML formats, automatic token counting, and dynamic context window management.
## Installation
```bash theme={null}
pip install -U swarms
```
## Parameters
Unique identifier for the conversation.
Name of the conversation.
The system prompt for the conversation.
Enable ISO timestamps on each message.
Enable automatic saving of conversation history.
File path for saving the conversation history.
File path to load conversation history from on initialization.
Maximum number of tokens allowed in the conversation history. Used by token-based truncation and dynamic context windowing.
Rules injected into the conversation to govern participant behavior.
Custom prompt prepended alongside `rules`.
The user identifier used as the role for user messages.
When `True`, persisted history is written as YAML.
When `True`, persisted history is written as JSON.
Enable per-message token counting.
Attach a unique ID to every message.
Model name used by the tokenizer for token counting and truncation.
Directory used to persist and load named conversations.
Export format used by `export()`: `"json"` or `"yaml"`.
Enable dynamic context window management (grow/shrink the kept history based on token usage).
Enable token-count caching for repeated history reads.
Include per-message metadata in formatted output.
Path to the `MEMORY.md` file used for persistent-memory reads/writes.
## Methods
### add()
Add a message to the conversation history.
```python theme={null}
def add(
self,
role: str,
content: Union[str, dict, list, Any],
metadata: Optional[dict] = None,
category: Optional[str] = None,
)
```
**Parameters:**
* `role` (str): The role of the speaker (e.g., 'User', 'System', 'Agent')
* `content` (Union\[str, dict, list]): The content of the message
* `metadata` (Optional\[dict]): Optional metadata for the message
* `category` (Optional\[str]): Optional category for the message (e.g., 'input', 'output')
### return\_history\_as\_string()
Return the conversation history as a formatted string.
```python theme={null}
def return_history_as_string(self) -> str:
```
**Returns:** String representation of the conversation history
### compact()
Collapse the interaction history into a single summary message, preserving the agent's static context (`system_prompt` → `rules` → `custom_rules_prompt`) ahead of it. If `memory_md_path` is configured, the on-disk `MEMORY.md` is archived to `/archive/history_.md` and then wiped/re-seeded so the log doesn't keep growing across compressions.
```python theme={null}
def compact(
self,
summary: str,
summary_role: str = "System",
) -> None
```
**Parameters:**
* `summary` (str): The compressed summary content that replaces the raw history.
* `summary_role` (str): Role attached to the summary message. Defaults to `"System"`.
```python theme={null}
conv.compact(
summary="User asked about X. Assistant explained X.",
summary_role="System",
)
```
### export()
Export the conversation to a file based on the export method.
```python theme={null}
def export(self, force: bool = True)
```
**Parameters:**
* `force` (bool): If True, saves regardless of autosave setting
### load()
Load conversation history from a file (auto-detects format).
```python theme={null}
def load(self, filename: str)
```
**Parameters:**
* `filename` (str): Path to the file to load from
### search()
Search for messages containing a keyword.
```python theme={null}
def search(self, keyword: str) -> list
```
**Parameters:**
* `keyword` (str): The keyword to search for
**Returns:** List of messages containing the keyword
### truncate\_memory\_with\_tokenizer()
Truncate conversation history based on token count using tokenizer.
```python theme={null}
def truncate_memory_with_tokenizer(self)
```
### export\_and\_count\_categories()
Export all messages with category 'input' and 'output' and count their tokens.
```python theme={null}
def export_and_count_categories(self) -> Dict[str, int]
```
**Returns:** Dictionary with input\_tokens, output\_tokens, and total\_tokens
### Other Methods
| Method | Description |
| -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `query(index)` | Return the message dict at `index`, or `None` if out of range |
| `delete(index)` | Remove the message at `index` |
| `update(index, role, content)` | Replace the role/content of the message at `index` |
| `add_multiple(roles, contents)` / `add_multiple_messages(roles, contents)` | Add several messages concurrently (thread pool) |
| `batch_add(messages)` | Add a list of `{"role": ..., "content": ...}` dicts |
| `get_str()` | Alias for `return_history_as_string()` |
| `get_cache_stats()` | Returns `{hits, misses, cached_tokens, hit_rate}` for the history-string cache (only meaningful when `cache_enabled=True`) |
| `get_last_message_as_string()` | Returns the last message formatted as `"role: content"` |
| `get_final_message()` / `get_final_message_content()` | Returns the last message dict / just its content |
| `return_messages_as_list()` / `return_messages_as_dictionary()` | The history as `{"role", "content"}` dicts |
| `return_messages_as_strings()` | The history rendered as `"role: content"` strings |
| `return_all_except_first()` / `return_all_except_first_string()` | History excluding the first (system) message |
| `to_dict()` / `to_json()` / `to_yaml()` / `to_list()` | Serialize the conversation history only (no config/metadata) |
| `count_messages_by_role()` | Dict of message counts keyed by role |
| `clear()` | Empty the conversation history |
| `Conversation.load_conversation(name, conversations_dir=None, load_filepath=None)` | Classmethod: load a previously saved conversation by name or explicit file path |
| `Conversation.list_conversations(...)` / `Conversation.list_cached_conversations(...)` | Classmethods to enumerate saved/cached conversations |
## Usage Examples
### Basic Usage
```python theme={null}
from swarms.structs import Conversation
# Create a conversation
conversation = Conversation(
name="my-conversation",
system_prompt="You are a helpful assistant.",
time_enabled=True,
autosave=True,
token_count=True,
context_length=8192
)
# Add messages
conversation.add("user", "Hello, how are you?")
conversation.add("assistant", "I am doing well, thanks.")
conversation.add("user", "What is the weather in Tokyo?")
# Get conversation as string
print(conversation.return_history_as_string())
```
### Export and Load
```python theme={null}
# Export to JSON
conversation.export_method = "json"
conversation.export()
# Load from file
conversation = Conversation.load_conversation(
name="my-conversation",
load_filepath="conversation_my-conversation.json"
)
```
### Token Management
```python theme={null}
# Enable token counting and context management
conversation = Conversation(
token_count=True,
context_length=4096,
dynamic_context_window=True
)
# Add messages with categories for tracking
conversation.add("user", "My input", category="input")
conversation.add("assistant", "My response", category="output")
# Count tokens by category
tokens = conversation.export_and_count_categories()
print(f"Input tokens: {tokens['input_tokens']}")
print(f"Output tokens: {tokens['output_tokens']}")
print(f"Total tokens: {tokens['total_tokens']}")
```
### Search and Query
```python theme={null}
# Search for messages
results = conversation.search("weather")
# Get last message
last_message = conversation.get_last_message_as_string()
# Get specific message by index
message = conversation.query(0)
```
## Features
* **Automatic Saving**: Enable autosave to automatically persist conversation history
* **Token Management**: Track token counts and automatically truncate based on context length
* **Multiple Export Formats**: Save as JSON or YAML
* **Dynamic Context Window**: Automatically manage conversation length to fit context limits
* **Message Search**: Search through conversation history by keyword
* **Categorization**: Tag messages with categories for organized tracking
* **Time Tracking**: Optionally track timestamps for all messages
# CouncilAsAJudge
Source: https://docs.swarms.world/api/council-as-judge
A council of AI agents that evaluates task responses across multiple dimensions in parallel, then aggregates findings into a comprehensive report
## Overview
The `CouncilAsAJudge` implements a parallel evaluation system where multiple specialized judge agents evaluate different aspects of a task response simultaneously. Their findings are aggregated into a comprehensive technical report.
## Installation
```bash theme={null}
pip install -U swarms
```
## Evaluation Dimensions
The council evaluates responses across six key dimensions:
1. **Accuracy**: Factual correctness, source credibility, logical consistency
2. **Helpfulness**: Practical value, solution feasibility, problem-solving efficacy
3. **Harmlessness**: Safety assessment, ethical considerations, bias detection
4. **Coherence**: Structural integrity, logical flow, organization
5. **Conciseness**: Communication efficiency, precision, information density
6. **Instruction Adherence**: Compliance with requirements, constraint adherence
## Attributes
Unique identifier for the council
Display name of the council
Description of the council's purpose
Currently has no effect on judge selection. Judge agents are always built with `judge_agent_model_name` (see below); `reliability_check()` only ever overwrites this attribute with a random model string when `random_model_name=True`, and nothing reads it back afterward.
Type of output to return ("final", "dict", "list", etc.)
Size of the LRU cache for prompts
Currently has no effect on judge selection. When `True`, `reliability_check()` assigns a random model string to `self.model_name`, but `_create_judges()` never reads `self.model_name` -- judge models are controlled solely by `judge_agent_model_name`.
Maximum number of loops for agents
Model name for the aggregator agent. This one does correctly control the aggregator.
The model used to build every judge agent (`_create_judges()` passes it as `model_name` for each dimension judge). This is the only parameter that controls judge models. Since it defaults to `None`, judges are built with `model_name=None` unless you set this explicitly.
## Methods
### run()
Run the evaluation process using parallel execution.
```python theme={null}
def run(self, task: str)
```
**Parameters:**
* `task` (str): Task containing the response to evaluate
**Returns:** Formatted evaluation report based on output\_type
## Usage Examples
### Basic Evaluation
```python theme={null}
from swarms import CouncilAsAJudge
# Create council
council = CouncilAsAJudge(
name="Response-Evaluator",
output_type="final"
)
# Evaluate a response
task_response = """
Question: Explain how neural networks work.
Response: Neural networks are computational models inspired by the human brain.
They consist of layers of interconnected nodes (neurons) that process information.
Each connection has a weight that adjusts during training. The network learns by
adjusting these weights to minimize error between predictions and actual outputs.
This process is called backpropagation.
"""
evaluation = council.run(task_response)
print(evaluation)
```
### Custom Model Configuration
```python theme={null}
# Use specific models for evaluation.
# NOTE: model_name has no effect on judge agents -- use judge_agent_model_name
# to control the model judges run on (random_model_name also has no effect).
council = CouncilAsAJudge(
judge_agent_model_name="claude-sonnet-4-6", # For judge agents
aggregation_model_name="claude-sonnet-4-6", # For final synthesis
output_type="dict"
)
evaluation = council.run(task_response)
```
### Full Conversation History
```python theme={null}
# Get complete evaluation breakdown
council = CouncilAsAJudge(
output_type="dict-all-except-first"
)
full_evaluation = council.run(task_response)
# Access individual dimension evaluations
for message in full_evaluation:
print(f"\n{message['role']}:")
print(message['content'][:200])
```
### Specific Judge Model
```python theme={null}
# Use Claude for all judge agents
council = CouncilAsAJudge(
judge_agent_model_name="anthropic/claude-sonnet-4-5",
aggregation_model_name="claude-sonnet-4-6",
)
evaluation = council.run(task_response)
```
## Evaluation Report Structure
The final aggregated report includes:
### 1. Executive Summary
* Key strengths and weaknesses
* Critical issues requiring immediate attention
* Overall assessment
### 2. Detailed Analysis
* Cross-dimensional patterns
* Specific examples and their implications
* Technical impact assessment
### 3. Recommendations
* Prioritized improvement areas
* Specific technical suggestions
* Implementation considerations
## Dimension-Specific Evaluations
Each judge provides:
1. **Specific Observations**: References exact parts of the response
2. **Impact Analysis**: Explains how issues affect quality
3. **Concrete Examples**: Demonstrates strengths and weaknesses
4. **Improvement Suggestions**: Actionable recommendations
## Parallel Execution
The council uses `ThreadPoolExecutor` to evaluate all dimensions simultaneously:
* **Workers**: Automatically configured based on CPU count (75% of cores)
* **Concurrency**: All 6 dimensions evaluated in parallel
* **Error Handling**: Individual dimension failures don't stop other evaluations
* **Performance**: Significantly faster than sequential evaluation
## Example Output
```python theme={null}
evaluation = council.run(task_response)
# Output structure (when output_type="dict"):
[
{"role": "User", "content": "Task response..."},
{"role": "accuracy_judge", "content": "Accuracy analysis..."},
{"role": "helpfulness_judge", "content": "Helpfulness analysis..."},
{"role": "harmlessness_judge", "content": "Safety analysis..."},
{"role": "coherence_judge", "content": "Coherence analysis..."},
{"role": "conciseness_judge", "content": "Conciseness analysis..."},
{"role": "instruction_adherence_judge", "content": "Adherence analysis..."},
{"role": "aggregator_agent", "content": "Final comprehensive report..."}
]
```
## Features
* **Multi-Dimensional Evaluation**: Comprehensive assessment across 6 key dimensions
* **Parallel Processing**: All evaluations run concurrently for maximum speed
* **Expert Judge Agents**: Each dimension evaluated by specialized agent
* **Intelligent Aggregation**: Senior agent synthesizes all findings
* **Technical Analysis**: Detailed, actionable feedback for improvement
* **Flexible Models**: Support for any LLM model via LiteLLM
* **Caching**: LRU cache for frequently used prompts
* **Error Handling**: Robust exception handling for each dimension
* **Multiple Output Formats**: Choose from various output types
## Use Cases
1. **Response Quality Assessment**: Evaluate LLM outputs before deployment
2. **Model Comparison**: Compare different models' responses
3. **Training Data Evaluation**: Assess quality of training examples
4. **Content Review**: Evaluate generated content for publication
5. **Automated QA**: Build quality assurance pipelines
6. **A/B Testing**: Compare different prompt variations
## Best Practices
1. **Output Type Selection**:
* Use `"final"` for quick summary reports
* Use `"dict"` to analyze individual dimension evaluations
* Use `"json"` for integration with other systems
2. **Model Selection**:
* Set `judge_agent_model_name` to control which model judges run on -- `model_name` and `random_model_name` currently have no effect on judge selection
* Use stronger models (GPT-4, Claude) for critical evaluations
* Use faster models (GPT-4o-mini) for development/testing
3. **Performance**:
* Council auto-configures workers based on CPU count
* Consider cache\_size for repeated similar evaluations
* Monitor costs when using multiple premium models
4. **Integration**:
* Parse the aggregated report for actionable insights
* Use dimension-specific feedback for targeted improvements
* Store evaluations for tracking quality over time
# CronJob
Source: https://docs.swarms.world/api/cron-job
Schedule and run Swarms agents at specified intervals with cron-style scheduling
## Overview
The **CronJob** class wraps any callable (including Swarms agents) and turns it into a scheduled job that runs at specified intervals. It provides scheduling, failure handling, execution tracking, and optional callbacks for output customization.
One `CronJob` binds **one agent** to **one interval**. For several agents on different cadences, use [`run_many`](#run-many).
**Failure model.** A task that raises is logged and retried on the next tick, the way cron behaves. It does not take the schedule down. Set `max_consecutive_errors` to stop a job that is failing every time; when that budget is exhausted the job stops **and** `run()` raises, so a dead schedule is never mistaken for a healthy one.
## Constructor
Create a CronJob instance to schedule recurring agent executions.
```python theme={null}
from swarms.structs.cron_job import CronJob
from swarms import Agent
# Create an agent
agent = Agent(
agent_name="Financial-Analyst",
system_prompt="You are a financial analyst...",
model_name="gpt-4"
)
# Create scheduled job
cron = CronJob(
agent=agent,
interval="10minutes",
job_id="financial_analysis_job"
)
```
### Parameters
The Swarms Agent instance or callable to be scheduled
The interval string (e.g., "5seconds", "10minutes", "1hour")
Optional unique identifier for the job. If not provided, one will be generated.
Stop the job after this many back-to-back failed executions. `None` (the default) never gives up and retries forever, which is what cron does. When the budget is exhausted the job stops and `run()` raises `CronJobExecutionError`.
Optional callback function to customize output processing.
**Signature:** `callback(output: Any, task: str, metadata: dict) -> Any`
* `output`: The original output from the agent
* `task`: The task that was executed
* `metadata`: Dictionary containing job\_id, timestamp, execution\_count, etc.
* Returns: The customized output
### Attributes
Unique identifier for the job
Flag indicating if the job is currently running
Number of times the job has been executed
Timestamp when the job was started
Total number of failed executions over the job's life
Failures since the last success. Reset to `0` on any successful tick
The most recent failure, or `None` if the job has never failed
## Methods
### run
Schedule and run the job with a specified task.
```python theme={null}
cron.run(
task="Analyze Q4 earnings for AAPL",
img="/path/to/chart.png" # Optional image parameter
)
```
The task string to be executed by the agent
Additional parameters to pass to the agent's run method (e.g., `img`, `imgs`, `correct_answer`, `streaming_callback`)
**Raises:**
* `CronJobConfigError`: If agent or interval is not configured
* `CronJobExecutionError`: If scheduling failed, or if the job gave up after exhausting `max_consecutive_errors`. The message names the failure count and the last error.
**Behavior:**
* Schedules the task according to the configured interval
* Starts the background execution thread
* Blocks the calling thread until `stop()` is called, `KeyboardInterrupt` is received, or the job exhausts its error budget
* A task that raises is logged and retried on the next tick; it does not stop the schedule
### batched\_run
Run multiple tasks sequentially with the same schedule.
```python theme={null}
tasks = [
"Analyze AAPL stock",
"Analyze GOOGL stock",
"Analyze MSFT stock"
]
results = cron.batched_run(tasks)
```
List of task strings to execute
Additional parameters to pass to the agent's run method
List of results from each task execution
**Behavior:** every task in `tasks` is registered on the job's interval *before* blocking, so all of them run on each tick. This is one agent doing several things on one cadence.
Earlier versions scheduled only the first task: `batched_run` called `run()` per task, and `run()` blocked, so the loop never reached the second task. That is fixed — all tasks are scheduled, and the list of scheduled jobs is returned.
For several agents on **different** cadences, use [`run_many`](#run-many) instead.
### run\_many
Run several agents together, each on its own interval. A class method.
A `CronJob` binds one agent to one interval, so a fleet on mixed cadences needs one job per agent. `run_many` builds them, starts them all, and optionally blocks.
Each job keeps its own scheduler thread, so the agents are **isolated**: one failing does not delay or stop the others, and each carries its own error budget.
```python theme={null}
from swarms.structs.cron_job import CronJob
CronJob.run_many([
{"agent": price_agent, "interval": "30seconds", "task": "Check BTC price"},
{"agent": anomaly_agent, "interval": "10minutes", "task": "Scan for anomalies",
"max_consecutive_errors": 5},
{"agent": digest_agent, "interval": "1hour", "task": "Summarise the hour"},
])
```
One mapping per agent.
**Required keys:** `agent`, `interval`, `task`
**Optional keys:** `job_id`, `callback`, `max_consecutive_errors`, and `kwargs` (a dict forwarded to that agent's `run`)
Hold the calling thread until `KeyboardInterrupt` or until every job has stopped, then stop them all. Pass `False` to start the fleet and return immediately, leaving the caller responsible for `stop_many`.
The started jobs, in the order given, so they can be inspected via `get_execution_stats()` or stopped individually
**Raises:**
* `CronJobConfigError`: If `schedules` is empty, or an entry is missing `agent`, `interval` or `task`. The message names the index and the missing key.
* `CronJobExecutionError`: If, once blocking ends, any job had stopped because it exhausted `max_consecutive_errors`
**Non-blocking use:**
```python theme={null}
jobs = CronJob.run_many(schedules, block=False)
# ... your own main loop ...
for job in jobs:
print(job.get_execution_stats())
CronJob.stop_many(jobs)
```
### stop\_many
Stop every job in a list, continuing past any that fail to stop. A static method.
```python theme={null}
CronJob.stop_many(jobs)
```
The jobs to stop, typically the return value of `run_many(..., block=False)`
**Behavior:** one job refusing to stop is logged and does not strand the rest.
### start
Manually start the scheduled job.
```python theme={null}
cron.start()
```
**Raises:**
* `CronJobExecutionError`: If the job fails to start
**Behavior:**
* Creates a daemon thread for job execution
* Sets `is_running` to True
* Records `start_time`
* If already running, logs a warning
### stop
Stop the scheduled job.
```python theme={null}
cron.stop()
```
**Raises:**
* `CronJobExecutionError`: If the job fails to stop properly
**Behavior:**
* Sets `is_running` to False
* Waits up to 5 seconds for thread to terminate
* Clears the schedule
* Logs warning if thread doesn't terminate gracefully
### set\_callback
Set or update the callback function for output customization.
```python theme={null}
def custom_callback(output, task, metadata):
# Process output
processed = output.upper()
# Log execution info
print(f"Execution #{metadata['execution_count']}")
print(f"Task: {task}")
print(f"Timestamp: {metadata['timestamp']}")
return processed
cron.set_callback(custom_callback)
```
Callback function with signature: `callback(output, task, metadata) -> Any`
### get\_execution\_stats
Get execution statistics for the cron job.
```python theme={null}
stats = cron.get_execution_stats()
print(stats)
# {
# "job_id": "financial_analysis_job",
# "is_running": True,
# "execution_count": 42, # successes
# "start_time": 1234567890.123,
# "uptime": 3600.5,
# "interval": "10minutes",
# "error_count": 3, # total failures
# "consecutive_errors": 0, # since the last success
# "last_error": "upstream API timed out",
# "stopped_due_to_error": False # True only if it gave up
# }
```
Dictionary containing:
* `job_id`: Job identifier
* `is_running`: Current running status
* `execution_count`: Number of executions
* `start_time`: Start timestamp
* `uptime`: Time elapsed since start (seconds)
* `interval`: Configured interval string
* `error_count`: Total failed executions
* `consecutive_errors`: Failures since the last success
* `last_error`: Most recent failure as a string, or `None`
* `stopped_due_to_error`: `True` only when the job gave up after exhausting `max_consecutive_errors`
## Interval Formats
The `interval` parameter accepts strings in the format ``:
### Supported Units
* **Seconds**: `"5seconds"`, `"30second"`
* **Minutes**: `"10minutes"`, `"1minute"`
* **Hours**: `"2hours"`, `"1hour"`
### Examples
```python theme={null}
# Every 5 seconds
CronJob(agent=agent, interval="5seconds")
# Every 30 seconds
CronJob(agent=agent, interval="30seconds")
# Every 10 minutes
CronJob(agent=agent, interval="10minutes")
# Every 2 hours
CronJob(agent=agent, interval="2hours")
```
### Rejected at construction
These raise `CronJobConfigError` immediately rather than failing later:
| Value | Why |
| ------------------------- | ------------------------------------------------ |
| `"0second"`, `"0minutes"` | A zero interval schedules a job that never fires |
| `""`, `" "` | Empty is a bad interval, not an absent one |
| `"-1second"` | Negative |
| `"1day"` | Unsupported unit; use seconds, minutes or hours |
| `"1 second"` | No space between the number and the unit |
| `"second"` | Missing the number |
## Complete Examples
### Basic Scheduled Analysis
```python theme={null}
from swarms import Agent
from swarms.structs.cron_job import CronJob
# Create financial analyst agent
agent = Agent(
agent_name="Market-Analyst",
system_prompt="""You are an expert market analyst.
Provide concise daily market updates focusing on:
1. Major index movements
2. Notable sector performance
3. Key market drivers
""",
model_name="gpt-4",
max_loops=1,
verbose=True
)
# Schedule to run every hour
cron = CronJob(
agent=agent,
interval="1hour",
job_id="hourly_market_update"
)
# Run the scheduled job
try:
cron.run(task="Provide a market update for the current hour")
except KeyboardInterrupt:
print("Stopping scheduled job...")
cron.stop()
```
### Multi-Stock Analysis with Batching
```python theme={null}
from swarms import Agent
from swarms.structs.cron_job import CronJob
# Create stock analysis agent
stock_agent = Agent(
agent_name="Stock-Analyzer",
system_prompt="Analyze stock performance and provide investment insights.",
model_name="gpt-4",
max_loops=2
)
# Schedule every 30 minutes
cron = CronJob(
agent=stock_agent,
interval="30minutes",
job_id="stock_analysis"
)
# Analyze multiple stocks
stocks = ["AAPL", "GOOGL", "MSFT", "AMZN", "TSLA"]
tasks = [f"Analyze {symbol} stock performance" for symbol in stocks]
try:
results = cron.batched_run(tasks)
for symbol, result in zip(stocks, results):
print(f"\n{symbol} Analysis:")
print(result)
except KeyboardInterrupt:
print("Analysis stopped.")
cron.stop()
```
### Custom Callback for Output Processing
```python theme={null}
from swarms import Agent
from swarms.structs.cron_job import CronJob
import json
from datetime import datetime
def save_analysis_callback(output, task, metadata):
"""Save analysis results to file with metadata."""
result = {
"job_id": metadata["job_id"],
"execution_number": metadata["execution_count"],
"timestamp": datetime.fromtimestamp(metadata["timestamp"]).isoformat(),
"task": task,
"analysis": output,
"uptime_seconds": metadata.get("start_time", 0)
}
# Save to file
filename = f"analysis_{metadata['execution_count']}.json"
with open(filename, 'w') as f:
json.dump(result, f, indent=2)
print(f"Saved analysis #{metadata['execution_count']} to {filename}")
return output
# Create agent
agent = Agent(
agent_name="Crypto-Analyst",
system_prompt="Analyze cryptocurrency market trends.",
model_name="gpt-4"
)
# Create cron with callback
cron = CronJob(
agent=agent,
interval="15minutes",
job_id="crypto_analysis",
callback=save_analysis_callback
)
try:
cron.run(task="Analyze Bitcoin and Ethereum market trends")
except KeyboardInterrupt:
cron.stop()
```
### Image Analysis with Scheduling
```python theme={null}
from swarms import Agent
from swarms.structs.cron_job import CronJob
# Create vision-capable agent
vision_agent = Agent(
agent_name="Chart-Analyzer",
system_prompt="Analyze financial charts and provide technical insights.",
model_name="claude-sonnet-4-6", # Vision-capable model
max_loops=1
)
# Schedule chart analysis every 2 hours
cron = CronJob(
agent=vision_agent,
interval="2hours",
job_id="chart_analysis"
)
try:
cron.run(
task="Analyze this chart for support/resistance levels and trend direction",
img="/path/to/chart.png"
)
except KeyboardInterrupt:
cron.stop()
```
### Monitoring Execution Stats
```python theme={null}
from swarms import Agent
from swarms.structs.cron_job import CronJob
import time
agent = Agent(
agent_name="Monitor-Agent",
system_prompt="Monitor system metrics.",
model_name="gpt-4"
)
cron = CronJob(
agent=agent,
interval="10seconds",
job_id="monitor"
)
# Start the job in background
cron.start()
try:
# Monitor stats every 30 seconds
while True:
time.sleep(30)
stats = cron.get_execution_stats()
print(f"\nExecution Stats:")
print(f" Running: {stats['is_running']}")
print(f" Executions: {stats['execution_count']}")
print(f" Uptime: {stats['uptime']:.2f}s")
except KeyboardInterrupt:
print("Stopping monitor...")
cron.stop()
```
## Exception Handling
The CronJob class defines several custom exceptions:
### CronJobError
Base exception class for all CronJob errors.
### CronJobConfigError
Raised for configuration errors.
```python theme={null}
try:
cron = CronJob(agent=None, interval="10minutes")
except CronJobConfigError as e:
print(f"Configuration error: {e}")
```
### CronJobScheduleError
Raised for scheduling related errors.
```python theme={null}
try:
cron = CronJob(agent=agent, interval="invalid_format")
except CronJobConfigError as e:
print(f"Invalid interval: {e}")
```
### CronJobExecutionError
Raised for execution related errors.
```python theme={null}
try:
cron.run(task="")
except CronJobExecutionError as e:
print(f"Execution failed: {e}")
```
## Best Practices
1. **Use descriptive job IDs**: Make job identifiers meaningful for tracking
2. **Set appropriate intervals**: Choose intervals based on task complexity and resource availability
3. **Implement callbacks**: Use callbacks for logging, saving results, or sending notifications
4. **Monitor execution stats**: Regularly check stats to ensure jobs are running as expected
5. **Handle interrupts**: Always wrap `run()` in try-except to handle KeyboardInterrupt
6. **Consider agent limits**: Ensure your agent's `max_loops` is appropriate for scheduled tasks
7. **Set an error budget for flaky dependencies**: `max_consecutive_errors` stops a job that is failing every time. Leave it as `None` when a task should retry indefinitely
8. **Watch `consecutive_errors`, not just `error_count`**: occasional failures on a long-running job are normal; a rising consecutive count is the signal something is actually broken
9. **Use `run_many` for mixed cadences**: one job per agent keeps them isolated, so a failing agent cannot hold up the others
10. **Log failures**: Enable verbose mode and implement proper error logging
11. **Test intervals**: Start with longer intervals and optimize based on performance
12. **Resource management**: Be mindful of API rate limits and costs with frequent scheduling
13. **Graceful shutdown**: Always call `stop()` when terminating scheduled jobs
## Thread Safety
CronJob uses threading for background execution:
* Daemon threads are used to prevent blocking program exit
* Thread-safe scheduling with the `schedule` library
* Proper cleanup on stop() with timeout handling
## Callback Metadata
The callback function receives a metadata dictionary with:
```python theme={null}
{
"job_id": str, # Job identifier
"timestamp": float, # Unix timestamp of execution
"execution_count": int, # Number of times executed
"task": str, # The task that was run
"kwargs": dict, # Additional kwargs passed
"start_time": float, # Job start timestamp
"is_running": bool # Current running status
}
```
Use this metadata for:
* Logging execution history
* Conditional processing based on execution count
* Time-based analysis
* Debugging and monitoring
# DebateWithJudge
Source: https://docs.swarms.world/api/debate-with-judge
A debate architecture with iterative self-refinement through Pro, Con, and Judge agents
## Overview
The `DebateWithJudge` module provides a sophisticated debate architecture with self-refinement through a judge agent. This system enables two agents (Pro and Con) to debate a topic, with a Judge agent evaluating their arguments and providing refined synthesis. The process repeats for N rounds to progressively refine the answer.
## Installation
```bash theme={null}
pip install -U swarms
```
## Architecture
```mermaid theme={null}
graph TD
A[DebateWithJudge System] --> B[Initialize Pro, Con, and Judge Agents]
B --> C[Start with Initial Topic]
C --> D[Round Loop: max_rounds]
D --> E[Pro Agent Presents Argument]
E --> F[Con Agent Presents Counter-Argument]
F --> G[Judge Agent Evaluates Both]
G --> H[Judge Provides Synthesis]
H --> I{More Rounds?}
I -->|Yes| D
I -->|No| J[Format Final Output]
J --> K[Return Result]
```
### Key Concepts
| Concept | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------ |
| Debate Architecture | A structured process where two agents present opposing arguments on a topic |
| Pro Agent | The agent arguing in favor of a position |
| Con Agent | The agent arguing against a position |
| Judge Agent | An impartial evaluator that analyzes both arguments and provides synthesis |
| Iterative Refinement | The process repeats for multiple rounds, each round building upon the judge's previous synthesis |
| Progressive Improvement | Each round refines the answer by incorporating feedback and addressing weaknesses |
| Preset Agents | Built-in optimized agents that can be used without manual configuration |
## Attributes
The agent arguing in favor (Pro position). Not required if using `agents` list or `preset_agents`.
The agent arguing against (Con position). Not required if using `agents` list or `preset_agents`.
The judge agent that evaluates arguments and provides synthesis. Not required if using `agents` list or `preset_agents`.
A list of exactly 3 agents in order: `[pro_agent, con_agent, judge_agent]`. Takes precedence over individual agent parameters.
If `True`, creates default Pro, Con, and Judge agents automatically with optimized system prompts when no `agents` list or individual agents are supplied. Defaults to `True`, so `DebateWithJudge()` with no agent arguments works out of the box.
Maximum number of debate rounds to execute.
Format for the output conversation history.
Whether to enable verbose logging.
The model name to use for preset agents.
## Initialization Options
The `DebateWithJudge` class supports three ways to configure agents:
### Option 1: Preset Agents (Simplest)
Use built-in agents with optimized system prompts for debates:
```python theme={null}
from swarms import DebateWithJudge
# Create debate system with preset agents
debate = DebateWithJudge(
preset_agents=True,
max_loops=3,
model_name="gpt-5.4"
)
result = debate.run("Should AI be regulated?")
```
### Option 2: List of Agents
Provide a list of exactly 3 agents (Pro, Con, Judge):
```python theme={null}
from swarms import Agent, DebateWithJudge
# Create your custom agents
agents = [pro_agent, con_agent, judge_agent]
# Create debate system with agent list
debate = DebateWithJudge(
agents=agents,
max_loops=3
)
result = debate.run("Is remote work better than office work?")
```
### Option 3: Individual Agent Parameters
Provide each agent separately:
```python theme={null}
from swarms import Agent, DebateWithJudge
# Create debate system with individual agents
debate = DebateWithJudge(
pro_agent=my_pro_agent,
con_agent=my_con_agent,
judge_agent=my_judge_agent,
max_loops=3
)
result = debate.run("Should we colonize Mars?")
```
## Methods
### run()
Executes the debate with judge refinement process for a single task and returns the refined result.
```python theme={null}
def run(self, task: str) -> Union[str, List, dict]
```
**Parameters:**
* `task` (str): The initial topic or question to debate
**Returns:** The formatted conversation history or final refined answer, depending on `output_type`
**Process Flow:**
1. **Task Validation**: Validates that the task is a non-empty string
2. **Agent Initialization**: Initializes all three agents with their respective roles and the initial task context
3. **Multi-Round Execution**: For each round (up to `max_loops`):
* Pro agent presents an argument in favor
* Con agent presents a counter-argument
* Judge agent evaluates both arguments and provides synthesis
* Judge's synthesis becomes the topic for the next round
4. **Result Formatting**: Returns the final result formatted according to `output_type`
**Raises:**
* `ValueError`: If task is None or empty. (Invalid agent configuration or `max_loops < 1` raise `ValueError` at construction time, in `__init__`, not in `run()`.)
### batched\_run()
Executes the debate for multiple tasks sequentially.
```python theme={null}
def batched_run(self, tasks: List[str]) -> List[str]
```
**Parameters:**
* `tasks` (List\[str]): List of topics or questions to debate
**Returns:** List of final refined answers, one for each input task
## Output Types
The `output_type` parameter controls how the conversation history is formatted:
| Value | Description |
| ------------------------ | ----------------------------------------------------------------------- |
| `"str-all-except-first"` | Returns a formatted string with all messages except the first (default) |
| `"str"` | Returns all messages as a formatted string |
| `"dict"` | Returns messages as a dictionary |
| `"list"` | Returns messages as a list |
## Usage Examples
### Quick Start with Preset Agents
```python theme={null}
from swarms import DebateWithJudge
# Create the DebateWithJudge system with preset agents
debate_system = DebateWithJudge(
preset_agents=True,
max_loops=3,
model_name="gpt-5.4",
output_type="str-all-except-first",
verbose=True,
)
# Define the debate topic
topic = (
"Should artificial intelligence be regulated by governments? "
"Discuss the balance between innovation and safety."
)
# Run the debate -- with output_type="str-all-except-first" (default),
# result is already the formatted conversation history as a string
result = debate_system.run(task=topic)
print(result)
```
### Policy Debate with Custom Agents
```python theme={null}
from swarms import Agent, DebateWithJudge
# Create the Pro agent (arguing in favor of AI regulation)
pro_agent = Agent(
agent_name="Pro-Regulation-Agent",
system_prompt=(
"You are a policy expert specializing in technology regulation. "
"You argue in favor of government regulation of artificial intelligence. "
"You present well-reasoned arguments focusing on safety, ethics, "
"and public interest. You use evidence, examples, and logical reasoning. "
"You are persuasive and articulate, emphasizing the need for oversight "
"to prevent harm and ensure responsible AI development."
),
model_name="gpt-5.4",
max_loops=1,
)
# Create the Con agent (arguing against AI regulation)
con_agent = Agent(
agent_name="Anti-Regulation-Agent",
system_prompt=(
"You are a technology policy expert specializing in innovation. "
"You argue against heavy government regulation of artificial intelligence. "
"You present strong counter-arguments focusing on innovation, economic growth, "
"and the risks of over-regulation. You identify weaknesses in regulatory "
"proposals and provide compelling alternatives such as industry self-regulation "
"and ethical guidelines. You emphasize the importance of maintaining "
"technological competitiveness."
),
model_name="gpt-5.4",
max_loops=1,
)
# Create the Judge agent (evaluates and synthesizes)
judge_agent = Agent(
agent_name="Policy-Judge-Agent",
system_prompt=(
"You are an impartial policy analyst and judge who evaluates debates on "
"technology policy. You carefully analyze arguments from both sides, "
"identify strengths and weaknesses, and provide balanced synthesis. "
"You consider multiple perspectives including safety, innovation, economic impact, "
"and ethical considerations. You may declare a winner or provide a refined "
"answer that incorporates the best elements from both arguments, such as "
"balanced regulatory frameworks that protect public interest while fostering innovation."
),
model_name="gpt-5.4",
max_loops=1,
)
# Create the DebateWithJudge system
debate_system = DebateWithJudge(
pro_agent=pro_agent,
con_agent=con_agent,
judge_agent=judge_agent,
max_loops=3,
output_type="str-all-except-first",
verbose=True,
)
# Define the debate topic
topic = (
"Should artificial intelligence be regulated by governments? "
"Discuss the balance between innovation and safety, considering "
"both the potential benefits of regulation (safety, ethics, public trust) "
"and the potential drawbacks (stifling innovation, economic impact, "
"regulatory capture). Provide a nuanced analysis."
)
# Run the debate -- with output_type="str-all-except-first" (default),
# result is already the formatted conversation history as a string
result = debate_system.run(task=topic)
print(result)
```
### Using Agent List
```python theme={null}
from swarms import Agent, DebateWithJudge
# Create your agents
pro = Agent(
agent_name="Microservices-Pro",
system_prompt="You advocate for microservices architecture...",
model_name="gpt-5.4",
max_loops=1,
)
con = Agent(
agent_name="Monolith-Pro",
system_prompt="You advocate for monolithic architecture...",
model_name="gpt-5.4",
max_loops=1,
)
judge = Agent(
agent_name="Architecture-Judge",
system_prompt="You evaluate architecture debates...",
model_name="gpt-5.4",
max_loops=1,
)
# Create debate with agent list
debate = DebateWithJudge(
agents=[pro, con, judge],
max_loops=2,
verbose=True,
)
result = debate.run("Should a startup use microservices or monolithic architecture?")
print(result)
```
### Batch Processing Multiple Topics
```python theme={null}
from swarms import Agent, DebateWithJudge
# Create specialized technical agents
pro_agent = Agent(
agent_name="Microservices-Pro",
system_prompt=(
"You are a software architecture expert advocating for microservices architecture. "
"You present arguments focusing on scalability, independent deployment, "
"technology diversity, and team autonomy. You use real-world examples and "
"case studies to support your position."
),
model_name="gpt-5.4",
max_loops=1,
)
con_agent = Agent(
agent_name="Monolith-Pro",
system_prompt=(
"You are a software architecture expert advocating for monolithic architecture. "
"You present counter-arguments focusing on simplicity, reduced complexity, "
"easier debugging, and lower operational overhead. You identify weaknesses "
"in microservices approaches and provide compelling alternatives."
),
model_name="gpt-5.4",
max_loops=1,
)
judge_agent = Agent(
agent_name="Architecture-Judge",
system_prompt=(
"You are a senior software architect evaluating architecture debates. "
"You analyze both arguments considering factors like team size, project scale, "
"complexity, operational capabilities, and long-term maintainability. "
"You provide balanced synthesis that considers context-specific trade-offs."
),
model_name="gpt-5.4",
max_loops=1,
)
# Create the debate system
architecture_debate = DebateWithJudge(
pro_agent=pro_agent,
con_agent=con_agent,
judge_agent=judge_agent,
max_loops=2,
output_type="str-all-except-first",
verbose=True,
)
# Define multiple architecture questions
architecture_questions = [
"Should a startup with 5 developers use microservices or monolithic architecture?",
"Is serverless architecture better than containerized deployments for event-driven systems?",
"Should a financial application use SQL or NoSQL databases for transaction processing?",
"Is event-driven architecture superior to request-response for real-time systems?",
]
# Execute batch processing
results = architecture_debate.batched_run(architecture_questions)
# Display results
for result in results:
print(result)
```
### Business Strategy Debate with Conversation History
```python theme={null}
from swarms import Agent, DebateWithJudge
# Create business strategy agents
pro_agent = Agent(
agent_name="Growth-Strategy-Pro",
system_prompt=(
"You are a business strategy consultant specializing in aggressive growth strategies. "
"You argue in favor of rapid expansion, market penetration, and scaling. "
"You present arguments focusing on first-mover advantages, market share capture, "
"network effects, and competitive positioning."
),
model_name="gpt-5.4",
max_loops=1,
)
con_agent = Agent(
agent_name="Sustainable-Growth-Pro",
system_prompt=(
"You are a business strategy consultant specializing in sustainable, profitable growth. "
"You argue against aggressive expansion in favor of measured, sustainable growth. "
"You present counter-arguments focusing on profitability, unit economics, "
"sustainable competitive advantages, and avoiding overextension."
),
model_name="gpt-5.4",
max_loops=1,
)
judge_agent = Agent(
agent_name="Strategy-Judge",
system_prompt=(
"You are a seasoned business strategist and former CEO evaluating growth strategy debates. "
"You carefully analyze arguments from both sides, considering market conditions, "
"company resources, risk tolerance, and long-term sustainability vs. short-term growth."
),
model_name="gpt-5.4",
max_loops=1,
)
# Create the debate system with extended rounds
strategy_debate = DebateWithJudge(
pro_agent=pro_agent,
con_agent=con_agent,
judge_agent=judge_agent,
max_loops=4,
output_type="dict",
verbose=True,
)
# Define a complex business strategy question
strategy_question = (
"A SaaS startup with $2M ARR, 40% gross margins, and $500K in the bank "
"is considering two paths:\n"
"1. Aggressive growth: Raise $10M, hire 50 people, expand to 5 new markets\n"
"2. Sustainable growth: Focus on profitability, improve unit economics, "
"expand gradually with existing resources\n\n"
"Which strategy should they pursue?"
)
# Run the debate -- with output_type="dict", result is already the
# conversation history formatted as a dictionary; the final judge synthesis
# is the last entry
result = strategy_debate.run(task=strategy_question)
print(result)
```
## Best Practices
**Agent Configuration**: Use `preset_agents=True` for quick setup with optimized prompts. For specialized domains, create custom agents with domain-specific prompts. Consider using more powerful models for the Judge agent.
**Choosing an Initialization Method**: Use `preset_agents=True` for quick prototyping, `agents=[...]` list when you have agents from external sources, and individual parameters for maximum control.
**Loop Configuration**: Use 2-3 loops for most topics and 4-5 loops for complex, multi-faceted topics. More loops allow for deeper refinement but increase execution time.
**Output Format**: Use `"str-all-except-first"` for readable summaries (default), `"dict"` for structured analysis, `"list"` for conversation inspection, and `"str"` for complete history.
**Performance**: Batch processing is sequential -- consider parallel execution for large batches. Each round requires 3 agent calls (Pro, Con, Judge). Memory usage scales with conversation history length.
## Troubleshooting
| Issue | Solution |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| Agents not following their roles | Ensure system prompts clearly define each agent's role. Consider using `preset_agents=True` for well-tested prompts. |
| Judge synthesis not improving over loops | Increase `max_loops` or improve Judge agent's system prompt to emphasize refinement. |
| Debate results are too generic | Use more specific system prompts and provide detailed context in the task. Custom agents often produce better domain-specific results. |
| Execution time is too long | Reduce `max_loops`, use faster models, or process fewer topics in batch. |
| ValueError when initializing | Ensure you provide one of: (1) all three agents, (2) an agents list with exactly 3 agents, or (3) `preset_agents=True`. |
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/debate_with_judge.py)
# DynamicToolLoader
Source: https://docs.swarms.world/api/dynamic-tool-loader
A catalog of deferred tool schemas plus the tool_search tool that loads them on demand
## Overview
`DynamicToolLoader` keeps tools *deferred*: registered and executable, but absent from the schema list sent to the model. One extra tool is always present — `tool_search` — which matches the catalog by name and description and loads what it finds. Loaded tools stay loaded for the rest of the run and become callable on the next request.
Tool definitions live in the prompt's cached prefix, so a large tool set is paid for on every call. Selection accuracy also degrades as the list grows: a model choosing among 80 tools chooses worse than one choosing among 8.
```mermaid theme={null}
graph TD
A[Catalog: every registered tool] -->|deferred| B[schemas]
B --> C["always_loaded + tool_search + loaded"]
C --> D[Sent to model]
D -->|model calls tool_search| E[run_search]
E -->|rank and mark loaded| A
E --> F[Compact summary returned to model]
```
## Import
```python theme={null}
from swarms.tools.dynamic_tool_loader import (
DynamicToolLoader,
DeferredTool,
SEARCH_TOOL_NAME,
SEARCH_TOOL_SCHEMA,
DYNAMIC_TOOLS_NOTICE,
)
```
`DynamicToolLoader` is **not** re-exported from `swarms` or `swarms.tools`. Use the full module path shown above — `from swarms.tools import DynamicToolLoader` raises `ImportError`.
Most users never construct one directly. `Agent(dynamic_tools=True)` builds it and exposes it as `agent.tool_loader`. See [Dynamic Tool Loading](/agents/dynamic-tools) for the agent-level guide.
## Constructor
```python theme={null}
DynamicToolLoader(
tools: Iterable[Callable] = (),
schemas: Iterable[Dict[str, Any]] = (),
always_loaded: Iterable[Dict[str, Any]] = (),
)
```
Callables to defer. Each is converted to an OpenAI function schema once, at registration.
Pre-built schemas to defer, for tools that have no local callable — MCP tools, for instance.
Schemas that are never deferred. Control-flow tools belong here: an agent that has to search for its own `complete_task` cannot finish.
## Module Constants
The reserved name of the search tool. Registering a tool under this name is refused with a warning.
The OpenAI function schema for `tool_search`. Takes a required `query` string and an optional `max_results` integer. Its description instructs the model to load everything it expects to need in a single call.
The system-prompt block appended once when deferral activates, headed `## MOST TOOLS ARE NOT LOADED`. Tells the model that its visible tool list describes what exists, not what it can call right now.
## Methods
### register
Defer one or more Python callables. Chainable; `None` entries are filtered out.
```python theme={null}
def register(*tools: Callable) -> "DynamicToolLoader"
```
One or more callables. Each is converted to an OpenAI function schema at registration time.
The same loader, for chaining.
### register\_schema
Defer a pre-built OpenAI function schema, optionally binding a local callable to it.
```python theme={null}
def register_schema(
schema: Dict[str, Any],
func: Optional[Callable] = None,
) -> "DynamicToolLoader"
```
An OpenAI function schema. A schema with no `function.name` is ignored.
The callable that executes this tool. Leave as `None` for remotely-dispatched tools such as MCP.
The same loader, for chaining.
A schema named `tool_search` is **dropped** with a warning — that name is reserved, and both entries would appear in the tool list with the model unable to tell them apart.
### search
Rank catalog entries against a query. Does **not** load anything.
```python theme={null}
def search(
query: str,
limit: int = 5,
min_score_ratio: float = 0.0,
) -> List[DeferredTool]
```
Keywords, or `select:name1,name2` for exact names.
Maximum results returned.
Drop results scoring below this fraction of the best score. `0.0` keeps every match, which suits an explicit search where the model said what it wanted. Speculative callers should raise it — a long query contains enough common words to give weak matches a nonzero score.
Matching catalog entries, best first. Empty when nothing matches.
### load
Mark tools as loaded by name.
```python theme={null}
def load(names: Iterable[str]) -> List[DeferredTool]
```
Catalog names to load. Unknown names are ignored.
Only the tools that were **newly** loaded by this call.
### run\_search
The `tool_search` handler: search, load, and report. This is what the model's tool call invokes.
```python theme={null}
def run_search(
query: str,
max_results: int = 5,
min_score_ratio: float = 0.0,
**kwargs,
) -> str
```
Keywords, or `select:name1,name2` for exact names.
Maximum tools to load. A falsy value (`0` or `None`) silently becomes `5`.
Relative score cutoff, as in `search`.
A compact listing — one `name: description` line per match, then a blank line, then either `Loaded N: a, b. They are callable from your next turn.` or `All already loaded - call them directly.` On a miss, the available tool names plus a hint to retry with `select:`.
The result deliberately returns summaries rather than full schemas. The schemas are already going out in the request's tool array — repeating them here would pay for them twice.
### schemas
The tool list to send with the next request.
```python theme={null}
def schemas() -> List[Dict[str, Any]]
```
`always_loaded` first, then `SEARCH_TOOL_SCHEMA`, then every loaded tool sorted by name.
The ordering is load-bearing. Loading changes the tool list, which invalidates the provider's cached prompt prefix; a stable, name-sorted order means two runs that load the same tools produce an identical prefix.
### handlers
Name-to-callable mapping for dispatch.
```python theme={null}
def handlers() -> Dict[str, Callable]
```
Every loaded tool **that has a local callable**. Schema-only entries such as MCP tools are excluded by design — they are dispatched through the MCP manager.
### catalog\_listing
Every deferred tool, one per line. Useful for prompts and debugging.
```python theme={null}
def catalog_listing() -> str
```
Name-sorted `name: first line of description` lines for the whole catalog.
## Properties
Sorted names of tools that have been loaded.
Sorted names of tools still deferred.
The never-deferred schemas passed to the constructor. A public mutable list.
## Dunder Methods
| Expression | Meaning |
| ------------------ | ------------------------------------------------ |
| `len(loader)` | Catalog size. Does **not** count `tool_search`. |
| `"name" in loader` | Whether a name is in the catalog, loaded or not. |
| `repr(loader)` | `DynamicToolLoader(N tools, M loaded)` |
## The Search Algorithm
Matching is deliberately simple: token overlap, with a name match worth more than a description match. That is enough for the catalog sizes this targets, has no dependencies, and is deterministic — so it can be tested. Swap in embeddings only when this measurably fails.
A query starting with `select:` splits the remainder on commas and returns those exact catalog entries immediately — unranked, ignoring both `limit` and `min_score_ratio`. If none of the names match, the loader falls through to a keyword search over the guessed names rather than returning nothing.
Non-alphanumeric characters become spaces, so `get_weather` yields `get` and `weather`. Everything is lowercased, then single characters and stopwords are dropped.
Each catalog entry scores **3 points for a name-token match** and **1 point for a description or parameter-name match**, summed across the query's terms. Entries scoring zero are dropped.
Sort by descending score, then by name for stability. If `min_score_ratio > 0`, drop anything below `best_score * min_score_ratio`. Return the first `limit` results.
### Searchable Surface
An entry matches on its name, its description, **and its parameter property names**. Searching `"recipient subject"` finds a `send_email(recipient, subject, body)` tool even if neither word appears in its description.
### Stopwords
Common words and single characters are filtered before matching:
```txt theme={null}
a an the and or of to in on for with from by at as is are be it its
this that these those any some all please can could would should
```
Without this, a query like `"weather in a city"` would match every tool whose description contains `"a"` — loading the whole catalog and defeating the point.
## DeferredTool
One catalog entry: what it is, how to call it, and how to run it.
```python theme={null}
@dataclass
class DeferredTool:
name: str
description: str
schema: Dict[str, Any]
func: Optional[Callable] = None
loaded: bool = False
```
Property. `"name: first line of description"`, or just the name when the description is empty. This is the line shown in search results.
Property. The lowercased tokens this entry can be matched on — drawn from its name, description, and parameter property names.
## Usage Example
```python theme={null}
from swarms.tools.dynamic_tool_loader import DynamicToolLoader
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"{city}: 18C"
def send_email(recipient: str, subject: str, body: str) -> str:
"""Send an email to a recipient."""
return f"sent to {recipient}"
def read_csv(path: str) -> str:
"""Read a CSV file and return its contents."""
return open(path).read()
loader = DynamicToolLoader(tools=[get_weather, send_email, read_csv])
len(loader) # 3
len(loader.schemas()) # 1 - only tool_search is exposed
loader.deferred_names # ['get_weather', 'read_csv', 'send_email']
print(loader.run_search("weather"))
# get_weather: Get the current weather for a city.
#
# Loaded 1: get_weather. They are callable from your next turn.
len(loader.schemas()) # 2 - tool_search + get_weather
loader.loaded_names # ['get_weather']
loader.handlers() # {'get_weather': }
```
### Wiring It to a Custom Loop
Two steps: pass `loader.schemas()` as the tool list, and re-read it after each `tool_search` call so newly loaded tools are sent with the next request.
```python theme={null}
tools = loader.schemas()
while True:
response = call_model(messages, tools=tools)
for call in response.tool_calls:
if call.name == "tool_search":
result = loader.run_search(**call.arguments)
tools = loader.schemas() # re-read: the list just changed
else:
result = loader.handlers()[call.name](**call.arguments)
messages.append(tool_result(call.id, result))
```
Forgetting to re-read `schemas()` is the most common integration bug. The tool loads successfully, the search result says it is callable, and the model still cannot call it — because the request never carried its schema.
## Related Pages
* [Dynamic Tool Loading](/agents/dynamic-tools) — the agent-level guide
* [Dynamic Tool Usage examples](/examples/tools/dynamic-tool-usage) — runnable end-to-end scripts
* [Agent API reference](/api/agent) — `dynamic_tools`, `setup_dynamic_tools`, `defer_tool_schemas`, `defer_mcp_tools`
* [Tools API reference](/api/tools) — schema conversion and execution
## Source
[`swarms/tools/dynamic_tool_loader.py` on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/tools/dynamic_tool_loader.py)
# ForestSwarm
Source: https://docs.swarms.world/api/forest-swarm
A hierarchical multi-agent system that organizes agents into trees and uses embedding-based semantic similarity for intelligent task routing
## Overview
The `ForestSwarm` organizes agents into trees, where each agent specializes in processing specific tasks. Trees are collections of agents, each assigned based on their relevance to a task through keyword extraction and **litellm-based embedding similarity**.
The architecture allows for efficient task assignment by selecting the most relevant agent from a set of trees. Tasks are processed with agents selected based on task relevance, calculated by the similarity of system prompts and task keywords using **litellm embeddings** and cosine similarity calculations.
```mermaid theme={null}
graph TD
A[ForestSwarm] --> B[Financial Services Tree]
A --> C[Investment & Trading Tree]
B --> D[Financial Advisor]
B --> E[Tax Expert]
B --> F[Retirement Planner]
C --> G[Stock Analyst]
C --> H[Investment Strategist]
C --> I[ROTH IRA Specialist]
subgraph Embedding Process
J[litellm Embeddings] --> K[Cosine Similarity]
K --> L[Agent Selection]
end
subgraph Task Processing
M[Task Input] --> N[Generate Task Embedding]
N --> O[Find Relevant Tree]
O --> P[Find Relevant Agent]
P --> Q[Execute Task]
Q --> R[Log Results]
end
subgraph Batch Processing
S[Multiple Tasks] --> T[Process Each Task]
T --> U[Find Relevant Agent per Task]
U --> V[Execute All Tasks]
V --> W[Return Results List]
end
```
## Installation
```bash theme={null}
pip install -U swarms
```
## Utility Functions
### extract\_keywords()
Extracts relevant keywords from a text prompt using basic word splitting and frequency counting.
```python theme={null}
def extract_keywords(prompt: str, top_n: int = 5) -> List[str]
```
**Parameters:**
* `prompt` (str): The text to extract keywords from
* `top_n` (int): Maximum number of keywords to return
**Returns:** List of extracted keywords sorted by frequency
### cosine\_similarity()
Calculates the cosine similarity between two embedding vectors.
```python theme={null}
def cosine_similarity(vec1: List[float], vec2: List[float]) -> float
```
**Parameters:**
* `vec1` (List\[float]): First embedding vector
* `vec2` (List\[float]): Second embedding vector
**Returns:** Cosine similarity score between 0 and 1
## TreeAgent
`TreeAgent` represents an individual agent responsible for handling a specific task. Agents are initialized with a **system prompt** and use **litellm embeddings** to dynamically determine their relevance to a given task.
### TreeAgent Attributes
Name of the agent
Description of the agent
A string that defines the agent's area of expertise and task-handling capability
Name of the language model to use
The name of the agent
litellm-generated embedding of the system prompt for similarity-based task matching
Keywords dynamically extracted from the system prompt to assist in task matching
The computed distance between agents based on embedding similarity
Name of the litellm embedding model
Whether to enable verbose logging
### TreeAgent Methods
### calculate\_distance()
Calculates the cosine similarity distance between this agent and another agent.
```python theme={null}
def calculate_distance(self, other_agent: TreeAgent) -> float
```
**Parameters:**
* `other_agent` (TreeAgent): Another agent to compare with
**Returns:** Cosine similarity distance as a float
### run\_task()
Executes the task, logs the input/output, and returns the result.
```python theme={null}
def run_task(self, task: str, img: str = None, *args, **kwargs) -> Any
```
**Parameters:**
* `task` (str): The task to execute
* `img` (str, optional): Optional image input
**Returns:** The result of the task execution
### is\_relevant\_for\_task()
Checks if the agent is relevant for the task using keyword matching and litellm embedding similarity.
```python theme={null}
def is_relevant_for_task(self, task: str, threshold: float = 0.7) -> bool
```
**Parameters:**
* `task` (str): The task to check relevance for
* `threshold` (float): Similarity threshold (default: 0.7)
**Returns:** Boolean indicating if the agent is relevant for the task
## Tree
`Tree` organizes multiple agents into a hierarchical structure, where agents are sorted based on their relevance to tasks using litellm embeddings.
### Tree Attributes
The name of the tree (represents a domain of agents, e.g., "Financial Tree")
List of agents belonging to this tree, sorted by embedding-based distance
Whether to enable verbose logging
### Tree Methods
### calculate\_agent\_distances()
Calculates and assigns distances between agents based on litellm embedding similarity of prompts.
```python theme={null}
def calculate_agent_distances(self) -> None
```
### find\_relevant\_agent()
Finds the most relevant agent for a task based on keyword and litellm embedding similarity.
```python theme={null}
def find_relevant_agent(self, task: str) -> Optional[TreeAgent]
```
**Parameters:**
* `task` (str): The task to find a relevant agent for
**Returns:** The most relevant `TreeAgent`, or `None` if no relevant agent is found
### log\_tree\_execution()
Logs details of the task execution by the selected agent.
```python theme={null}
def log_tree_execution(self, task: str, selected_agent: TreeAgent, result: Any) -> None
```
**Parameters:**
* `task` (str): The executed task description
* `selected_agent` (TreeAgent): The agent that executed the task
* `result` (Any): The result of the execution
## ForestSwarm Attributes
Name of the forest swarm
Description of the forest swarm
List of trees containing agents organized by domain
Shared memory object for inter-tree communication
Rules governing the forest swarm behavior
Whether to enable verbose logging
File path for saving conversation logs
Conversation object for tracking interactions
## ForestSwarm Methods
### find\_relevant\_tree()
Searches across all trees to find the most relevant tree based on litellm embedding similarity.
```python theme={null}
def find_relevant_tree(self, task: str) -> Optional[Tree]
```
**Parameters:**
* `task` (str): The task to find a relevant tree for
**Returns:** The most relevant `Tree`, or `None` if no relevant tree is found
### run()
Executes the task by finding the most relevant agent from the relevant tree using litellm embeddings.
```python theme={null}
def run(self, task: str, img: str = None, *args, **kwargs) -> Any
```
**Parameters:**
* `task` (str): The task to execute
* `img` (str, optional): Optional image input
**Returns:** The result of the task execution
### batched\_run()
Executes multiple tasks by finding the most relevant agent for each task.
```python theme={null}
def batched_run(self, tasks: List[str], *args, **kwargs) -> List[Any]
```
**Parameters:**
* `tasks` (List\[str]): List of tasks to execute
**Returns:** List of results, one per task
## Usage Examples
### Full Working Example
```python theme={null}
from swarms.structs.tree_swarm import TreeAgent, Tree, ForestSwarm
# Create agents with varying system prompts and dynamically generated distances/keywords
agents_tree1 = [
TreeAgent(
name="Financial Advisor",
system_prompt="I am a financial advisor specializing in investment planning, retirement strategies, and tax optimization for individuals and businesses.",
agent_name="Financial Advisor",
verbose=True
),
TreeAgent(
name="Tax Expert",
system_prompt="I am a tax expert with deep knowledge of corporate taxation, Delaware incorporation benefits, and free tax filing options for businesses.",
agent_name="Tax Expert",
verbose=True
),
TreeAgent(
name="Retirement Planner",
system_prompt="I am a retirement planning specialist who helps individuals and businesses create comprehensive retirement strategies and investment plans.",
agent_name="Retirement Planner",
verbose=True
),
]
agents_tree2 = [
TreeAgent(
name="Stock Analyst",
system_prompt="I am a stock market analyst who provides insights on market trends, stock recommendations, and portfolio optimization strategies.",
agent_name="Stock Analyst",
verbose=True
),
TreeAgent(
name="Investment Strategist",
system_prompt="I am an investment strategist specializing in portfolio diversification, risk management, and market analysis.",
agent_name="Investment Strategist",
verbose=True
),
TreeAgent(
name="ROTH IRA Specialist",
system_prompt="I am a ROTH IRA specialist who helps individuals optimize their retirement accounts and tax advantages.",
agent_name="ROTH IRA Specialist",
verbose=True
),
]
# Create trees
tree1 = Tree(tree_name="Financial Services Tree", agents=agents_tree1, verbose=True)
tree2 = Tree(tree_name="Investment & Trading Tree", agents=agents_tree2, verbose=True)
# Create the ForestSwarm
forest_swarm = ForestSwarm(
name="Financial Services Forest",
description="A comprehensive financial services multi-agent system",
trees=[tree1, tree2],
verbose=True
)
# Run a task
task = "Our company is incorporated in Delaware, how do we do our taxes for free?"
output = forest_swarm.run(task)
print(output)
# Run multiple tasks
tasks = [
"What are the best investment strategies for retirement?",
"How do I file taxes for my Delaware corporation?",
"What's the current market outlook for tech stocks?"
]
results = forest_swarm.batched_run(tasks)
for i, result in enumerate(results):
print(f"Task {i+1} result: {result}")
```
## How It Works
1. **Create Agents**: Agents are initialized with varying system prompts, representing different areas of expertise (e.g., financial planning, tax filing).
2. **Generate Embeddings**: Each agent's system prompt is converted to litellm embeddings for semantic similarity calculations.
3. **Create Trees**: Agents are grouped into trees, with each tree representing a domain (e.g., "Financial Services Tree", "Investment & Trading Tree").
4. **Calculate Distances**: litellm embeddings are used to calculate semantic distances between agents within each tree.
5. **Run Task**: When a task is submitted, the system:
* Generates litellm embeddings for the task
* Searches through all trees using cosine similarity
* Finds the most relevant agent based on embedding similarity and keyword matching
6. **Task Execution**: The selected agent processes the task, and the result is returned and logged.
7. **Batched Processing**: Multiple tasks can be processed using the `batched_run` method for efficient batch processing.
## Key Features
### litellm Integration
* **Embedding Generation**: Uses litellm's `embedding()` function for generating high-quality embeddings
* **Model Flexibility**: Supports various embedding models (default: "text-embedding-ada-002")
* **Error Handling**: Robust fallback mechanisms for embedding failures
### Semantic Similarity
* **Cosine Similarity**: Implements efficient cosine similarity calculations for vector comparisons
* **Threshold-based Selection**: Configurable similarity thresholds for agent selection
* **Hybrid Matching**: Combines keyword matching with semantic similarity for optimal results
### Dynamic Agent Organization
* **Automatic Distance Calculation**: Agents are automatically organized by semantic similarity
* **Real-time Relevance**: Task relevance is calculated dynamically using current embeddings
* **Scalable Architecture**: Easy to add/remove agents and trees without manual configuration
### Batch Processing
* **Batched Execution**: Process multiple tasks efficiently using `batched_run` method
* **Parallel Processing**: Each task is processed independently with the most relevant agent
* **Result Aggregation**: All results are returned as a list for easy processing
## Logging Models
### AgentLogInput
Input log model for tracking agent task execution.
| Field | Type | Description |
| ------------ | ---------- | -------------------------------------- |
| `log_id` | `str` | Unique identifier for the log entry |
| `agent_name` | `str` | Name of the agent executing the task |
| `task` | `str` | Description of the task being executed |
| `timestamp` | `datetime` | When the task was started |
### AgentLogOutput
Output log model for tracking agent task completion.
| Field | Type | Description |
| ------------ | ---------- | ----------------------------------------- |
| `log_id` | `str` | Unique identifier for the log entry |
| `agent_name` | `str` | Name of the agent that completed the task |
| `result` | `Any` | Result/output from the task execution |
| `timestamp` | `datetime` | When the task was completed |
### TreeLog
Tree execution log model for tracking tree-level operations.
| Field | Type | Description |
| ---------------- | ---------- | ----------------------------------------- |
| `log_id` | `str` | Unique identifier for the log entry |
| `tree_name` | `str` | Name of the tree that executed the task |
| `task` | `str` | Description of the task that was executed |
| `selected_agent` | `str` | Name of the agent selected for the task |
| `timestamp` | `datetime` | When the task was executed |
| `result` | `Any` | Result/output from the task execution |
## Architecture Analysis
The ForestSwarm Architecture leverages a hierarchical structure (forest) composed of individual trees, each containing agents specialized in specific domains. This design allows for:
* **Modular and Scalable Organization**: By separating agents into trees, it is easy to expand or contract the system by adding or removing trees or agents.
* **Task Specialization**: Each agent is specialized, which ensures that tasks are matched with the most appropriate agent based on litellm embedding similarity and expertise.
* **Dynamic Matching**: The architecture uses both keyword-based and litellm embedding-based matching to assign tasks, ensuring a high level of accuracy in agent selection.
* **Logging and Accountability**: Each task execution is logged in detail, providing transparency and an audit trail of which agent handled which task and the results produced.
* **Batch Processing**: The architecture supports efficient batch processing of multiple tasks simultaneously.
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/tree_swarm.py)
# GraphWorkflow
Source: https://docs.swarms.world/api/graph-workflow
A powerful DAG-based workflow system for complex multi-agent orchestration with parallel execution
## Overview
The `GraphWorkflow` class represents a workflow graph where each node is an agent. It provides sophisticated capabilities for building, executing, and visualizing Directed Acyclic Graph (DAG) workflows with automatic parallel execution, topological sorting, and compilation optimization.
## Key Features
* **DAG-Based Workflows**: Build complex directed acyclic graphs of agent execution
* **Automatic Parallelization**: Automatically execute independent agents in parallel
* **Topological Execution**: Agents execute in topologically sorted layers
* **Compilation Optimization**: Pre-compute execution plans for faster multi-loop execution
* **Multiple Graph Backends**: Support for NetworkX and Rustworkx backends
* **Visualization**: Generate visual representations of workflows using Graphviz
* **Fan-Out/Fan-In Patterns**: Easy creation of parallel processing patterns
* **JSON Serialization**: Save and load workflows to/from JSON
* **Async Support**: Asynchronous execution for non-blocking operations
* **Cycle Detection**: Automatic detection and reporting of cycles
## Installation
```bash theme={null}
pip install -U swarms
# For visualization support
pip install graphviz
# For Rustworkx backend (optional, faster for large graphs)
pip install rustworkx
```
## Class Definition
```python theme={null}
class GraphWorkflow:
def __init__(
self,
id: Optional[str] = None,
name: Optional[str] = "Graph-Workflow-01",
description: Optional[str] = "A customizable workflow system for orchestrating and coordinating multiple agents.",
nodes: Optional[Dict[str, Node]] = None,
edges: Optional[List[Edge]] = None,
entry_points: Optional[List[str]] = None,
end_points: Optional[List[str]] = None,
max_loops: int = 1,
task: Optional[str] = None,
auto_compile: bool = True,
verbose: bool = False,
backend: str = "networkx",
checkpoint_dir: Optional[str] = None,
on_node_complete: Optional[Callable[[str, Any], None]] = None,
max_parallel_nodes: Optional[int] = None,
)
```
## Parameters
Unique identifier for the workflow. Auto-generated via `generate_id("graph-workflow")` if not provided, producing `graph-workflow-<32 hex chars>`.
Human-readable name for the workflow
Description of the workflow's purpose
Dictionary of nodes in the graph, where the key is the node ID and the value is the Node object
List of edges in the graph, where each edge is represented by an Edge object
List of node IDs that serve as entry points to the graph. Auto-detected if not provided.
List of node IDs that serve as end points of the graph. Auto-detected if not provided.
Maximum number of times to execute the workflow
The task to be executed by the workflow
Whether to automatically compile the graph for optimization
Whether to enable verbose logging
Graph backend to use. Options: "networkx", "rustworkx" (Rustworkx is faster for large graphs)
Directory for writing workflow checkpoints. When set, execution state can be persisted and resumed.
Callback fired after each node finishes, receiving `(node_id, result)`. Can also be passed per-call to `run()`.
Maximum number of nodes to execute concurrently within a layer. Defaults to the framework's worker count when `None`.
## Methods
### Graph Construction
#### `add_node(agent, **kwargs)`
Add an agent node to the workflow graph.
The agent to add as a node
Additional keyword arguments for the node
#### `add_nodes(agents, batch_size=10, **kwargs)`
Add multiple agents to the workflow graph concurrently in batches.
List of agents to add
Number of agents to add concurrently in a batch
#### `add_edge(edge_or_source, target=None, **kwargs)`
Add an edge by Edge object or by passing node objects/ids.
Either an Edge object or the source node/id
Target node/id (required if edge\_or\_source is not an Edge)
#### `add_edges_from_source(source, targets, **kwargs)`
Add multiple edges from a single source to multiple targets (fan-out pattern).
Source node/id that will send output to multiple targets
List of target node/ids that will receive the source output in parallel
List of created Edge objects
#### `add_edges_to_target(sources, target, **kwargs)`
Add multiple edges from multiple sources to a single target (fan-in pattern).
List of source node/ids that will send output to the target
Target node/id that will receive all source outputs
List of created Edge objects
#### `add_parallel_chain(sources, targets, **kwargs)`
Create a parallel processing chain (full mesh connection).
List of source node/ids
List of target node/ids
List of created Edge objects
### Execution
#### `run(task=None, img=None, on_node_complete=None, streaming_callback=None, *args, **kwargs)`
Run the workflow graph with optimized parallel agent execution. When `max_loops > 1`, end-point outputs from each loop are fed as additional context into the next loop so agents can iteratively refine their results.
Task to execute. Uses self.task if not provided.
Optional image path for multimodal tasks
Callback fired immediately when each agent finishes, before the layer completes. Receives `(node_id, output)`. Takes precedence over the instance-level callback set in `__init__`.
Callback fired for every token as agents generate output in real time. Receives `(node_id, token)`.
Execution results keyed by node ID. When `max_loops == 1`, returns the single loop's results. When `max_loops > 1`, returns a dict with per-loop results keyed as `{node_id}_loop_{loop_number}` plus the final loop's results under the plain `node_id` keys.
#### `arun(task=None, *args, **kwargs)`
Async version of run for better performance with I/O bound operations.
Task to execute. Uses self.task if not provided.
Execution results from all nodes
### Compilation and Optimization
#### `compile()`
Pre-compute expensive operations for faster execution. Results are cached.
#### `get_compilation_status()`
Get detailed compilation status information.
Compilation status including cache state, timestamps, and performance metrics
### Entry/Exit Points
#### `set_entry_points(entry_points)`
Set the entry points for the workflow.
List of node IDs to serve as entry points
#### `set_end_points(end_points)`
Set the end points for the workflow.
List of node IDs to serve as end points
#### `auto_set_entry_points()`
Automatically set entry points to nodes with no incoming edges.
#### `auto_set_end_points()`
Automatically set end points to nodes with no outgoing edges.
### Visualization
#### `visualize(format="png", view=True, engine="dot", show_summary=False)`
Visualize the workflow graph using Graphviz.
Output format: 'png', 'svg', 'pdf', 'dot'
Whether to open the visualization after creation
Graphviz layout engine: 'dot', 'neato', 'fdp', 'sfdp', 'twopi', 'circo'
Whether to print parallel processing summary
Path to the generated visualization file
#### `visualize_simple()`
Simple text-based visualization for environments without Graphviz.
Text representation of the workflow
### Serialization
#### `to_json(fast=True, include_conversation=False, include_runtime_state=False)`
Serialize the workflow to JSON.
Whether to use fast JSON serialization
Whether to include conversation history
Whether to include runtime state like compilation info
JSON representation of the workflow
#### `from_json(json_str, restore_runtime_state=False)` (classmethod)
Deserialize a workflow from JSON.
JSON string representation of the workflow
Whether to restore runtime state
A new GraphWorkflow instance
#### `save_to_file(filepath, include_conversation=False, include_runtime_state=False, overwrite=False)`
Save the workflow to a JSON file.
Path to save the JSON file
Whether to overwrite existing files
Path to the saved file
#### `load_from_file(filepath, restore_runtime_state=False)` (classmethod)
Load a workflow from a JSON file.
Path to the JSON file
Loaded workflow instance
### Validation
#### `validate(auto_fix=False, raise_on_error=False)`
Validate the workflow structure, checking for isolated nodes, cyclic dependencies, unreachable nodes, dead-end nodes, and missing entry/end points.
Whether to automatically fix simple issues (e.g. auto-setting missing entry/exit points, adding unreachable nodes to entry points)
When `True`, raises a `ValueError` if validation determines the workflow is invalid. Defaults to `False` so existing callers that inspect the returned dict are unaffected.
Dictionary containing `is_valid`, `errors`, `warnings`, `fixed`, and (when cycles are found) `cycles`
### Checkpoints and Spec Serialization
#### `clear_checkpoints(task)`
Delete all checkpoint files written for a specific task. Call after a workflow run completes successfully to reclaim disk space. Requires `checkpoint_dir` to have been set.
The task string whose checkpoints should be removed; must match the string passed to `run()` exactly
Number of checkpoint files deleted
**Raises:**
* `ValueError`: If `checkpoint_dir` was not set on this workflow instance
#### `to_spec()`
Serialize the workflow topology to a lightweight plain-dict spec. Unlike `to_json()`, this does not serialize the Agent objects themselves — it only records each agent's `agent_name`, so the spec can be version-controlled and shared.
Dict with `name`, `description`, `max_loops`, `nodes`, `edges`, `entry_points`, `end_points`
#### `save_spec(path)`
Save the topology spec produced by `to_spec()` to a JSON file.
Filesystem path to write the JSON file to
#### `from_topology_spec(spec, agent_registry, **kwargs)` (classmethod)
Reconstruct a `GraphWorkflow` from a topology spec (as produced by `to_spec()`/`save_spec()`) and an agent registry supplying the live `Agent` objects for each node.
A topology spec as returned by `to_spec()` or loaded from a file written by `save_spec()`
Mapping from `agent_name` to live `Agent` instance
A new GraphWorkflow instance
#### `export_summary()`
Generate a human-readable summary of the workflow structure for inspection.
Summary dictionary describing the workflow's nodes, edges, and layers
### Factory Method
#### `from_spec(agents, edges, entry_points=None, end_points=None, task=None, **kwargs)` (classmethod)
Construct a workflow from a list of agents and connections.
List of agents or Node objects
List of edges or edge tuples. Supports fan-out, fan-in, and parallel chain patterns.
List of entry point node IDs
List of end point node IDs
Task to be executed by the workflow
A new GraphWorkflow instance
## Usage Examples
### Basic Sequential Graph
```python theme={null}
from swarms import Agent, GraphWorkflow
# Create agents
researcher = Agent(
agent_name="Researcher",
model_name="claude-sonnet-4-6",
system_prompt="Research and gather information"
)
analyzer = Agent(
agent_name="Analyzer",
model_name="claude-sonnet-4-6",
system_prompt="Analyze the research findings"
)
writer = Agent(
agent_name="Writer",
model_name="claude-sonnet-4-6",
system_prompt="Write based on analysis"
)
# Create workflow
workflow = GraphWorkflow(
name="Research-Analyze-Write",
description="Sequential research workflow"
)
# Add nodes
workflow.add_node(researcher)
workflow.add_node(analyzer)
workflow.add_node(writer)
# Add edges
workflow.add_edge("Researcher", "Analyzer")
workflow.add_edge("Analyzer", "Writer")
# Compile and run
workflow.compile()
results = workflow.run("Research AI trends in healthcare")
```
### Fan-Out Pattern (Parallel Specialists)
```python theme={null}
# Create multiple specialist agents
technical = Agent(agent_name="Technical", llm=llm, system_prompt="Technical analysis")
business = Agent(agent_name="Business", llm=llm, system_prompt="Business analysis")
user_exp = Agent(agent_name="UX", llm=llm, system_prompt="User experience analysis")
synthesizer = Agent(agent_name="Synthesizer", llm=llm, system_prompt="Synthesize all analyses")
workflow = GraphWorkflow(name="Multi-Perspective")
# Add all nodes
for agent in [researcher, technical, business, user_exp, synthesizer]:
workflow.add_node(agent)
# Fan-out from researcher to specialists
workflow.add_edges_from_source(
"Researcher",
["Technical", "Business", "UX"]
)
# Fan-in to synthesizer
workflow.add_edges_to_target(
["Technical", "Business", "UX"],
"Synthesizer"
)
results = workflow.run("Analyze AI chatbot implementation")
```
### Complex DAG Workflow
```python theme={null}
# Create a complex multi-stage workflow
data_collector = Agent(agent_name="DataCollector", llm=llm)
preprocessor = Agent(agent_name="Preprocessor", llm=llm)
model_a = Agent(agent_name="ModelA", llm=llm)
model_b = Agent(agent_name="ModelB", llm=llm)
model_c = Agent(agent_name="ModelC", llm=llm)
ensemble = Agent(agent_name="Ensemble", llm=llm)
validator = Agent(agent_name="Validator", llm=llm)
workflow = GraphWorkflow(name="ML-Pipeline")
# Add all nodes
agents = [data_collector, preprocessor, model_a, model_b, model_c, ensemble, validator]
workflow.add_nodes(agents, batch_size=5)
# Build DAG
workflow.add_edge("DataCollector", "Preprocessor")
workflow.add_edges_from_source("Preprocessor", ["ModelA", "ModelB", "ModelC"])
workflow.add_edges_to_target(["ModelA", "ModelB", "ModelC"], "Ensemble")
workflow.add_edge("Ensemble", "Validator")
# Visualize before running
workflow.visualize(show_summary=True)
# Execute
results = workflow.run("Predict customer churn")
```
### Using from\_spec for Quick Construction
```python theme={null}
# Quick workflow construction using from_spec
agents = [researcher, analyzer, writer]
edges = [
("Researcher", "Analyzer"),
("Analyzer", "Writer")
]
workflow = GraphWorkflow.from_spec(
agents=agents,
edges=edges,
name="Quick-Workflow",
task="Analyze quantum computing trends"
)
results = workflow.run() # Uses task from initialization
```
### Advanced Edge Patterns in from\_spec
```python theme={null}
agents = [collector, analyst1, analyst2, analyst3, synthesizer]
edges = [
# Simple edge
("Collector", "Analyst1"),
# Fan-out
("Collector", ["Analyst2", "Analyst3"]),
# Fan-in
(["Analyst1", "Analyst2", "Analyst3"], "Synthesizer"),
]
workflow = GraphWorkflow.from_spec(
agents=agents,
edges=edges,
verbose=True
)
```
### Async Execution
```python theme={null}
import asyncio
async def run_workflow():
workflow = GraphWorkflow(name="Async-Workflow")
workflow.add_nodes([agent1, agent2, agent3])
workflow.add_edge("agent1", "agent2")
workflow.add_edge("agent2", "agent3")
results = await workflow.arun("Process this task asynchronously")
return results
results = asyncio.run(run_workflow())
```
### Save and Load Workflows
**`save_to_file` / `load_from_file` do not currently round-trip.** `to_json()` writes each node's type as `str(node.type)`, which renders as `"NodeType.AGENT"`, while `from_json()` parses it with `NodeType(...)`, which only accepts the enum *value* `"agent"`. Every node is dropped during load, and the first edge then fails with `ValueError: Source node '...' does not exist in GraphWorkflow`.
Use the topology-spec path instead, which is unaffected. It stores the graph shape only, so you supply the live agents on load:
```python theme={null}
import json
workflow.save_spec("my_workflow.json")
spec = json.load(open("my_workflow.json"))
loaded = GraphWorkflow.from_topology_spec(
spec,
{"alpha": alpha_agent, "beta": beta_agent}, # agent_name -> Agent
)
```
```python theme={null}
# Save workflow
workflow.save_to_file(
"my_workflow.json",
include_conversation=True,
include_runtime_state=True
)
# Load workflow
loaded_workflow = GraphWorkflow.load_from_file(
"my_workflow.json",
restore_runtime_state=True
)
# Continue execution
results = loaded_workflow.run("New task")
```
### Using Rustworkx Backend
```python theme={null}
# Use Rustworkx for better performance on large graphs
workflow = GraphWorkflow(
name="Large-Workflow",
backend="rustworkx", # Faster for large graphs
verbose=True
)
# Add many nodes
workflow.add_nodes(list_of_100_agents, batch_size=20)
# Build complex graph
# ...
results = workflow.run("Complex task")
```
### Workflow Validation
```python theme={null}
# Validate workflow before execution
validation = workflow.validate(auto_fix=True)
if validation["is_valid"]:
print("Workflow is valid!")
results = workflow.run(task)
else:
print("Errors:", validation["errors"])
print("Warnings:", validation["warnings"])
```
### Compilation for Multi-Loop Execution
```python theme={null}
workflow = GraphWorkflow(
name="Multi-Loop-Workflow",
max_loops=10, # Will run 10 times
auto_compile=True # Compilation cached for all loops
)
workflow.add_nodes([agent1, agent2, agent3])
workflow.add_edges_from_source("agent1", ["agent2", "agent3"])
# Compilation is cached and reused across all loops
results = workflow.run("Task to repeat 10 times")
# Check compilation status
status = workflow.get_compilation_status()
print(f"Compiled: {status['is_compiled']}")
print(f"Layers: {status['cached_layers_count']}")
```
### Custom Visualization
```python theme={null}
# Generate different visualization formats
workflow.visualize(
format="svg",
engine="fdp", # Force-directed layout
view=False,
show_summary=True
)
# Simple text visualization (no Graphviz needed)
text_viz = workflow.visualize_simple()
print(text_viz)
```
## Node and Edge Classes
### Node
```python theme={null}
from swarms import Node, NodeType
# Create node from agent
node = Node.from_agent(agent)
# Create node manually
node = Node(
id="my-node",
type=NodeType.AGENT,
agent=agent,
metadata={"custom_key": "custom_value"}
)
```
### Edge
```python theme={null}
from swarms import Edge
# Create edge from nodes
edge = Edge.from_nodes(source_agent, target_agent)
# Create edge from IDs
edge = Edge(source="agent1", target="agent2")
# With metadata
edge = Edge(
source="agent1",
target="agent2",
metadata={"weight": 1.0}
)
```
## Best Practices
1. **Compilation**: Always compile workflows before execution for optimal performance
2. **Visualization**: Use `visualize()` to understand your workflow structure
3. **Validation**: Validate workflows before production deployment
4. **Entry/Exit Points**: Let the system auto-detect entry/exit points or set them explicitly
5. **Backend Selection**: Use Rustworkx for large graphs (>100 nodes)
6. **Error Handling**: Wrap execution in try-except blocks
7. **Batching**: Use `add_nodes()` with appropriate batch sizes for many agents
8. **Caching**: Enable `auto_compile` for multi-loop workflows
9. **Save Progress**: Save complex workflows to JSON for reuse
## Performance Characteristics
* **Parallel Execution**: Independent agents in the same layer run concurrently
* **CPU Utilization**: Uses \~95% of available CPU cores
* **Compilation**: Pre-computes execution plan, cached for multi-loop runs
* **Memory**: Each agent maintains its own context
* **Graph Backend**: Rustworkx is faster for large graphs (>100 nodes)
## Common Patterns
### Research Pipeline
```python theme={null}
edges = [
("DataCollector", "Researcher"),
("Researcher", ["Analyst1", "Analyst2", "Analyst3"]),
(["Analyst1", "Analyst2", "Analyst3"], "Synthesizer")
]
```
### Ensemble Decision Making
```python theme={null}
edges = [
("Coordinator", ["Expert1", "Expert2", "Expert3", "Expert4"]),
(["Expert1", "Expert2", "Expert3", "Expert4"], "Aggregator"),
("Aggregator", "DecisionMaker")
]
```
### Multi-Stage Review
```python theme={null}
edges = [
("Creator", "TechnicalReviewer"),
("TechnicalReviewer", "BusinessReviewer"),
("BusinessReviewer", "LegalReviewer"),
("LegalReviewer", "FinalApprover")
]
```
## Related Classes
* [SequentialWorkflow](/api/sequential-workflow): For simple sequential execution
* [ConcurrentWorkflow](/api/concurrent-workflow): For parallel execution on same task
* [AgentRearrange](/api/agent-rearrange): For flexible flow-based orchestration
* [Agent](/api/agent): The base agent class used in workflows
# GroupChat
Source: https://docs.swarms.world/api/group-chat
A turn-based groupchat where every agent bids each turn and the single highest-scoring bidder above threshold speaks
## Overview
`GroupChat` runs a **turn-based, self-selecting** conversation. There is no fixed speaking order and no speaker-selection function, but exactly **one agent speaks per turn**.
Each turn, every agent is asked concurrently (via a forced `respond(score, message)` function call) how strongly it wants to speak, on a `0..1` scale, together with the reply it would give. The single highest bidder whose score — after a recency adjustment — clears `threshold` takes the floor; only that agent's reply is posted to the shared conversation, and every other bid from that turn is discarded. A `recency_penalty` is subtracted from the score of any agent that spoke within the last `recency_window` turns, so the floor rotates around the room instead of one agent monologuing.
The chat ends when either:
* `max_loops` total messages have been posted (the initial user task counts as the first), or
* no agent's bid clears `threshold` on a turn — a conversational lull.
This replaces the older speaker-function design. Parameters and methods such as `speaker_function`, `speaker_state`, `set_speaker_function`, `start_interactive_session`, `@mention` routing, and the `round-robin-speaker` / `random-speaker` / `priority-speaker` selectors **no longer exist**. The current API is the turn-based, bid/threshold model documented below. Note also that `idle_timeout` is accepted for backward compatibility but is **not** used to end the chat — see below.
## Import
```python theme={null}
from swarms import Agent, GroupChat, RESPOND_TOOL
```
Both `GroupChat` and `RESPOND_TOOL` are exported from the top level (the submodule path `from swarms.structs.groupchat import GroupChat, RESPOND_TOOL` also works).
## Constructor
```python theme={null}
GroupChat(
name: str = "dynamic-groupchat",
description: str = "Agents take turns; one speaker per turn.",
agents: Optional[List[Agent]] = None,
max_loops: int = 20,
threshold: float = 0.5,
recency_penalty: float = 0.3,
recency_window: int = 1,
idle_timeout: float = 8.0,
output_type: str = "str-all-except-first",
verbose: bool = False,
auto_equip: bool = True,
)
```
Human-readable name used in logs and serialized state.
Short description of the chat.
Agents participating in the conversation. **At least two are required** for a meaningful discussion. Fewer than two raises `ValueError`.
Hard cap on the total number of messages posted, including the initial user task. When this many messages have been published the chat stops.
Minimum (recency-adjusted) bid a reply must exceed to take the floor. Raise it for a more selective room; lower it for livelier chatter. A turn where no agent clears it ends the chat.
Amount subtracted from the bid of any agent that spoke within the last `recency_window` turns, so the floor rotates instead of one agent monologuing. Set to `0.0` to disable.
How many of the most recent speakers are subject to `recency_penalty`.
Accepted for backward compatibility only. **Not used** to end the chat in the current implementation — the chat now ends on a bidding lull (no agent clears `threshold` on a turn) rather than a wall-clock timeout.
Format passed to `history_output_formatter`. Common values: `"str-all-except-first"`, `"str"`, `"list"`, `"dict"`, `"json"`.
Emit internal log messages (bids, scores, stop events) and print each posted message to the terminal as a styled panel (the user task in green, agent replies in blue with their score).
When `True` (default), the `RESPOND_TOOL` schema is automatically injected into any agent that does not already carry it, and that agent's LLM client is rebuilt so the forced tool call works. Set to `False` only if you equip every agent with `RESPOND_TOOL` yourself.
## The `respond` tool
Every agent must carry `RESPOND_TOOL` so the chat can force a structured speaking decision instead of parsing free-form text. With `auto_equip=True` this is handled for you; otherwise add it explicitly:
```python theme={null}
from swarms import Agent, RESPOND_TOOL
agent = Agent(
agent_name="Researcher",
model_name="gpt-5.4",
max_loops=1,
persistent_memory=False,
tools_list_dictionary=[RESPOND_TOOL],
)
```
`RESPOND_TOOL` forces a call to `respond(score, message)`:
| Field | Type | Meaning |
| --------- | --------------- | ------------------------------------------------------------------------------ |
| `score` | number (`0..1`) | How much the agent wants to speak. `0` = stay silent, `1` = strongly wants to. |
| `message` | string | The reply to broadcast, or an empty string to stay silent. |
A bid only wins the floor when its (recency-adjusted) `score` clears `threshold` **and** `message` is non-empty — and only the single highest such bid each turn is posted; every other agent's bid for that turn is discarded.
## Methods
### `run(task, streaming_callback=None)`
Synchronously run the turn-based groupchat until a lull (no agent's bid clears `threshold`) or until `max_loops` messages have been posted. Posts `task` as the first message, then on each turn collects a concurrent `(score, message)` bid from every agent, lets the single highest (recency-adjusted) bidder speak, and returns the formatted conversation.
```python theme={null}
def run(
self,
task: str,
streaming_callback: Optional[Callable[[str, str, bool], None]] = None,
) -> Any
```
The initial user message that seeds the conversation.
Optional `(agent_name, chunk, is_final)` callback. Each posted message — the initial task and every winning speaker's reply — is replayed to it as whitespace-chunked tokens, with `is_final=True` marking the end of that speaker's turn. Matches the streaming signature used elsewhere in the framework (`ConcurrentWorkflow`, `HierarchicalSwarm`).
**Returns:** the conversation formatted per `output_type`.
```python theme={null}
result = chat.run("Should we adopt AI for medical diagnosis?")
```
***
### `run_batch(tasks)`
Run several independent groupchats sequentially, one per task.
```python theme={null}
def run_batch(self, tasks: List[str]) -> List[Any]
```
Tasks to run, each as its own fresh groupchat.
**Returns:** a list of formatted outputs, one per task.
## Usage Examples
### Basic dynamic groupchat
```python theme={null}
from swarms import Agent, GroupChat
optimist = Agent(
agent_name="Optimist",
system_prompt="You argue for the benefits.",
model_name="gpt-5.4",
max_loops=1,
persistent_memory=False,
)
pessimist = Agent(
agent_name="Pessimist",
system_prompt="You argue for the risks.",
model_name="gpt-5.4",
max_loops=1,
persistent_memory=False,
)
realist = Agent(
agent_name="Realist",
system_prompt="You seek a balanced analysis.",
model_name="gpt-5.4",
max_loops=1,
persistent_memory=False,
)
chat = GroupChat(
agents=[optimist, pessimist, realist],
max_loops=10, # stop after 10 total messages
threshold=0.5, # only the single highest bid above 0.5 wins each turn
)
result = chat.run("Should we adopt AI for medical diagnosis?")
print(result)
```
`auto_equip=True` injects the `respond` tool into each agent automatically, so you do not need to pass `tools_list_dictionary=[RESPOND_TOOL]` yourself.
### A more selective room
```python theme={null}
# Raise the threshold so only a strongly-motivated bid wins the floor each turn,
# and widen the recency window so agents rotate speaking turns more aggressively.
chat = GroupChat(
agents=[optimist, pessimist, realist],
max_loops=20,
threshold=0.7,
recency_penalty=0.4,
recency_window=2,
)
result = chat.run("Design the architecture for a real-time fraud-detection system.")
```
### Equipping the tool yourself
```python theme={null}
from swarms import Agent, GroupChat, RESPOND_TOOL
agents = [
Agent(
agent_name=name,
system_prompt=prompt,
model_name="gpt-5.4",
max_loops=1,
persistent_memory=False,
tools_list_dictionary=[RESPOND_TOOL],
)
for name, prompt in [
("Researcher", "You contribute research and evidence."),
("Critic", "You stress-test claims and find weaknesses."),
]
]
chat = GroupChat(agents=agents, auto_equip=False, max_loops=8)
result = chat.run("Discuss the tradeoffs of autonomous multi-agent systems.")
```
## How It Works
1. **Seed** — the user task is posted to the single shared conversation as the first message.
2. **Bid** — each turn, every agent is run concurrently (via `asyncio.gather` + `asyncio.to_thread`, so one slow model call never stalls the turn) and forced through the `respond` tool to return a `(score, message)` bid against a snapshot of the current transcript.
3. **Select** — the highest bid wins, after subtracting `recency_penalty` from any agent that spoke within the last `recency_window` turns. Bids with an empty message never win, and the turn ends with no winner if no adjusted score clears `threshold`.
4. **Post** — only the winning agent's reply is appended to the shared conversation; every other bid from that turn is discarded. All agents see the new message as context on the next turn.
5. **Stop** — the chat ends when `max_loops` messages have been posted, or a turn passes with no bid clearing `threshold` (a conversational lull), and the formatted transcript is returned. `idle_timeout` is accepted for backward compatibility but no longer used to end the chat.
## Tuning
* **`threshold`** — higher means fewer turns get a winning bid (more lulls, shorter chats); lower means livelier back-and-forth.
* **`recency_penalty`** / **`recency_window`** — control how strongly a recent speaker's next bid is discounted so the floor rotates instead of one agent dominating every turn. Set `recency_penalty=0.0` to disable.
* **`max_loops`** — the hard ceiling on total messages; the primary cost control.
* **`idle_timeout`** — accepted for backward compatibility only; it does **not** end the chat in the current implementation (the chat stops on a bidding lull instead of a wall-clock timeout).
* **`max_loops=1` per agent** — give each participating `Agent` `max_loops=1` and `persistent_memory=False` so each speaking decision is a clean, single-shot call.
## Notes
* `GroupChat` inherits `SerializableMixin`; `agents` and `conversation` are excluded from serialized state.
* Exactly one agent speaks per turn — the highest recency-adjusted bidder above `threshold` — not every agent that clears the bar. This is a turn-based design, not a free-for-all broadcast.
* There is no human-in-the-loop REPL in this implementation — `run` is fully autonomous and returns when the chat concludes.
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/groupchat.py).
# HeavySwarm
Source: https://docs.swarms.world/api/heavy-swarm
A sophisticated multi-agent system that decomposes tasks into specialized questions and executes them with synthesis
## Overview
The `HeavySwarm` class is a sophisticated multi-agent orchestration system that decomposes a complex task into specialized questions, runs a team of agents on them in parallel, and synthesizes the results into a comprehensive response. The `variant` parameter selects the agent line-up — from a five-agent default team up to a sixteen-agent deep-research team — and `max_loops` enables iterative refinement.
## Class Definition
```python theme={null}
from swarms import HeavySwarm
```
## Parameters
Name identifier for the swarm instance
Description of the swarm's purpose and capabilities
Maximum execution time per agent in seconds
Language model for question generation
Language model for specialized worker agents
Enable detailed logging and debug output
Enable rich dashboard with progress visualization
Enable individual agent output printing
Output format type for conversation history
Tools available to worker agents for enhanced functionality
Maximum number of execution loops for the entire swarm. Each loop builds upon previous results for iterative refinement
Which agent line-up to instantiate. See **Selecting a Variant** below. Passing an unknown variant raises `ValueError` during initialization
## Selecting a Variant
The `variant` parameter controls which agents are created and how many specialized questions the task is decomposed into.
```python theme={null}
# Five-agent default (Research / Analysis / Alternatives / Verification + Synthesis)
swarm = HeavySwarm(variant="default")
# Four-agent Grok-style team (Captain + Harper, Benjamin, Lucas)
swarm = HeavySwarm(variant="medium")
# Sixteen-agent deep team (Grok captain + 15 domain specialists)
swarm = HeavySwarm(variant="heavy")
```
`SwarmVariant` is exported from `swarms.agents.heavy_swarm_agents`.
| `variant` | Agents | Questions generated |
| ----------- | ------------------------------------------------------------- | ------------------- |
| `"default"` | 5 — Research, Analysis, Alternatives, Verification, Synthesis | 4 |
| `"medium"` | 4 — Captain Swarm + Harper, Benjamin, Lucas | 3 |
| `"heavy"` | 16 — Grok captain + 15 domain specialists | 15 |
### `"medium"` roster
| Agent | Role |
| ------------- | ------------------------------------------------------------------------------ |
| Captain Swarm | Leader and orchestrator |
| Harper | Research and facts — evidence gathering and fact verification |
| Benjamin | Logic, math, and code — rigorous reasoning and computational verification |
| Lucas | Creative and divergent thinking — contrarian analysis and blind-spot detection |
### `"heavy"` roster
A Grok captain decomposes the task into 15 domain-specific questions; the 15 specialists answer them in parallel, then the captain synthesizes a single response.
| Agent | Domain |
| --------- | ---------------------------------------------- |
| Grok | Lead coordinator and synthesizer |
| Harper | Creative writing and storytelling |
| Benjamin | Data, finance and economics |
| Lucas | Coding, programming and technical builds |
| Olivia | Literature, arts and culture |
| James | History, politics and philosophy |
| Charlotte | Math, statistics and logic |
| Henry | Engineering, robotics and innovation |
| Mia | Biology, health and medicine |
| William | Business strategy and entrepreneurship |
| Sebastian | Physics, astronomy and hard sciences |
| Jack | Psychology and human behavior |
| Owen | Environment, sustainability and global systems |
| Luna | Space exploration and futurism |
| Elizabeth | Ethics, policy and critical thinking |
| Noah | Long-term innovation and systems thinking |
## Specialized Agents (default variant)
With the default variant, the HeavySwarm creates and manages 5 specialized agents:
### Research Agent
Expert in comprehensive information gathering, data collection, market research, and source verification. Specializes in systematic literature reviews, competitive intelligence, and statistical data interpretation.
**System Prompt Focus:**
* Comprehensive task analysis
* Evidence-based research
* Source credibility assessment
* Reproducible methodologies
### Analysis Agent
Expert in advanced statistical analysis, pattern recognition, predictive modeling, and causal relationship identification. Specializes in regression analysis, forecasting, and performance metrics development.
**System Prompt Focus:**
* Data quality assessment
* Statistical rigor
* Quantified uncertainty
* Practical interpretation
### Alternatives Agent
Expert in strategic thinking, creative problem-solving, innovation ideation, and strategic option evaluation. Specializes in design thinking, scenario planning, and exploring diverse solutions.
**System Prompt Focus:**
* Diverse option generation
* Trade-off analysis
* Risk assessment
* Implementation planning
### Verification Agent
Expert in validation, feasibility assessment, fact-checking, and quality assurance. Specializes in risk assessment, compliance verification, and implementation barrier analysis.
**System Prompt Focus:**
* Fact-checking protocols
* Feasibility validation
* Risk identification
* Evidence triangulation
### Synthesis Agent
Expert in multi-perspective integration, comprehensive analysis, and executive summary creation. Specializes in strategic alignment, conflict resolution, and holistic solution development.
**System Prompt Focus:**
* Multi-input integration
* Consensus building
* Prioritized recommendations
* Stakeholder communication
## Methods
### `run()`
```python theme={null}
def run(self, task: str, img: Optional[str] = None) -> str
```
Executes the complete HeavySwarm orchestration flow with multi-loop functionality.
**Parameters:**
The main task to analyze and iterate upon
Image input if needed for visual analysis tasks
**Returns:**
The conversation history formatted according to `output_type` (default `"dict-all-except-first"`, which returns a `list` of message dicts covering the question-generation, agent, and synthesis output — excluding the initial task message — not just the synthesis agent's final string). Pass `output_type="str-all-except-first"` for a plain string, or `output_type="final"` / `"last"` to get only the last message's content.
**Workflow:**
1. For first loop: Execute original task with full orchestration
2. For subsequent loops: Combine previous results with original task as context
3. Question generation: Generate specialized questions for the active variant's agents
4. Parallel execution: Run the variant's specialized agents concurrently
5. Synthesis: Integrate all agent results into a comprehensive response
6. Iteration: Repeat for max\_loops, building upon previous results
***
### `reliability_check()`
```python theme={null}
def reliability_check(self) -> None
```
Performs reliability and configuration validation checks.
**Validates:**
* worker\_model\_name is set
* question\_agent\_model\_name is set
**Raises:**
* `ValueError`: If a required model name is missing, or if `variant` is unknown
***
### `show_swarm_info()`
```python theme={null}
def show_swarm_info(self) -> None
```
Displays swarm configuration information in rich dashboard format.
Shows:
* Swarm identification (name, description)
* Execution parameters (timeout)
* Model configurations (question and worker models)
* Selected variant
***
### `execute_question_generation()`
```python theme={null}
def execute_question_generation(self, task: str) -> Dict[str, str]
```
Generates the active variant's specialized questions for a task using the configured `question_agent_model_name`, without running the worker agents or synthesis. Returns the raw parsed tool-call output, including `thinking`, the per-agent `*_question` keys, `tool_call_id`, and `function_name` (or an `error` key if generation/parsing failed).
The main task to analyze and decompose into specialized questions
***
### `get_questions_only()`
```python theme={null}
def get_questions_only(self, task: str) -> Dict[str, str]
```
Generates the specialized questions for a task and returns only the clean `*_question` keys (filters out `thinking`, `tool_call_id`, and `function_name`). Useful for previewing or debugging question generation without running the full swarm.
The main task or query to decompose into specialized questions
**Returns:**
Clean dictionary of `*_question` keys for the active variant (e.g. `research_question`, `analysis_question`, `alternatives_question`, `verification_question` for the default variant), or `{"error": ...}` on failure
```python theme={null}
swarm = HeavySwarm()
questions = swarm.get_questions_only("Analyze market trends for EVs")
print(questions["research_question"])
```
***
### `get_questions_as_list()`
```python theme={null}
def get_questions_as_list(self, task: str) -> List[str]
```
Generates the specialized questions for a task and returns them as an ordered list instead of a dict — convenient for iteration or display. Internally calls `get_questions_only()`.
The main task or query to decompose into specialized questions
**Returns:**
Ordered list of the active variant's questions (for the default variant: research, analysis, alternatives, verification, in that order), or a single-item list containing an error message on failure
```python theme={null}
swarm = HeavySwarm()
questions = swarm.get_questions_as_list("Optimize supply chain efficiency")
for i, question in enumerate(questions):
print(f"Agent {i+1}: {question}")
```
## Question Generation Schema
The default variant decomposes the task into four specialized questions:
```python theme={null}
{
"thinking": str, # Reasoning process for question breakdown
"research_question": str, # Question for Research Agent
"analysis_question": str, # Question for Analysis Agent
"alternatives_question": str, # Question for Alternatives Agent
"verification_question": str # Question for Verification Agent
}
```
The `"medium"` and `"heavy"` variants use their own schemas (3 and 15 questions respectively).
## Usage Example
```python theme={null}
from swarms import HeavySwarm
# Default 5-agent variant with dashboard enabled
swarm = HeavySwarm(
name="Market-Analysis-Swarm",
description="Comprehensive market analysis swarm",
question_agent_model_name="claude-sonnet-4-6",
worker_model_name="claude-sonnet-4-6",
show_dashboard=True,
max_loops=3,
verbose=True,
)
# Execute a complex task
result = swarm.run(
task="Analyze the current cryptocurrency market trends, evaluate investment alternatives, and provide verified recommendations"
)
print(result)
```
## Multi-Loop Execution
The `max_loops` parameter enables iterative refinement:
* **Loop 1**: Initial analysis of the task
* **Loop 2+**: Refinement based on previous results
* Each loop builds upon context from previous iterations
* Enables deeper analysis and progressive refinement
**Example with 3 loops:**
```python theme={null}
swarm = HeavySwarm(
name="DeepAnalysis",
max_loops=3,
show_dashboard=True,
)
result = swarm.run("Analyze AI impact on healthcare")
# Loop 1: Initial analysis
# Loop 2: Refinement based on Loop 1 insights
# Loop 3: Final comprehensive synthesis
```
## Dashboard Features
When `show_dashboard=True`, the HeavySwarm displays:
1. **Configuration Panel**: Swarm parameters and settings
2. **Reliability Checks**: Animated validation with progress tracking
3. **Question Generation**: Real-time progress for specialized questions
4. **Agent Execution**: Individual progress bars for each agent
5. **Synthesis Phase**: Integration and final report generation
6. **Completion Summary**: Mission accomplished with professional styling
All dashboard elements use Swarms-inspired red/black styling with professional formatting.
## Performance Optimization
* **Parallel Execution**: The active variant's specialized agents run concurrently
* **Thread Pool**: Workers run across a pool sized to roughly 90% of the host's CPU cores
* **Timeout Management**: Per-agent timeout controls
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/heavy_swarm.py)
# HybridHierarchicalClusterSwarm
Source: https://docs.swarms.world/api/hhcs
An advanced AI orchestration architecture that combines hierarchical decision-making with parallel processing through dynamic task routing to specialized agent swarms
## Overview
The Hybrid Hierarchical-Cluster Swarm (HHCS) is an advanced AI orchestration architecture that combines hierarchical decision-making with parallel processing capabilities. HHCS enables complex task solving by dynamically routing tasks to specialized agent swarms based on their expertise and capabilities.
## Installation
```bash theme={null}
pip install -U swarms
```
## Purpose
HHCS addresses the challenge of efficiently solving diverse and complex tasks by:
* Intelligently routing tasks to the most appropriate specialized swarms
* Enabling parallel processing of multifaceted problems
* Maintaining a clear hierarchy for effective decision-making
* Combining outputs from multiple specialized agents for comprehensive solutions
## Architecture Diagram
The HHCS architecture follows a hierarchical structure with the router agent at the top level, specialized swarms at the middle level, and individual agents at the bottom level.
```mermaid theme={null}
flowchart TD
Start([Task Input]) --> RouterAgent[Router Agent]
RouterAgent --> Analysis{Task Analysis}
Analysis -->|Analyze Requirements| Selection[Swarm Selection]
Selection -->|Select Best Swarm| Route[Route Task]
Route --> Swarm1[Swarm 1]
Route --> Swarm2[Swarm 2]
Route --> SwarmN[Swarm N...]
Swarm1 -->|Process Task| Result1[Swarm 1 Output]
Swarm2 -->|Process Task| Result2[Swarm 2 Output]
SwarmN -->|Process Task| ResultN[Swarm N Output]
Result1 --> Conversation[Conversation History]
Result2 --> Conversation
ResultN --> Conversation
Conversation --> Output([Final Output])
subgraph Router Decision Process
Analysis
Selection
end
subgraph Parallel Task Processing
Swarm1
Swarm2
SwarmN
end
subgraph Results Collection
Result1
Result2
ResultN
Conversation
end
```
## Attributes
The name of the swarm instance
Brief description of the swarm's functionality
List of available swarm routers (or callables) that the HHCS can route tasks to
Maximum number of processing loops
Format for output (e.g., "list", "json")
LLM model used by the router agent for task analysis and routing decisions
## Methods
### run()
Processes a single task through the swarm system. The router agent analyzes the task and routes it to the most appropriate specialized swarm.
```python theme={null}
def run(self, task: str, *args, **kwargs)
```
**Parameters:**
* `task` (str): The task to process
**Returns:** The aggregated results from the selected swarm(s), formatted according to `output_type` (a list by default)
### batched\_run()
Processes multiple tasks in parallel through the swarm system.
```python theme={null}
def batched_run(self, tasks: List[str]) -> List[str]
```
**Parameters:**
* `tasks` (List\[str]): List of task strings to process
**Returns:** List of results, one for each task
### find\_swarm\_by\_name()
Retrieves a swarm by its name from the available swarms.
```python theme={null}
def find_swarm_by_name(self, swarm_name: str) -> SwarmRouter
```
**Parameters:**
* `swarm_name` (str): Name of the swarm to find
**Returns:** The matching SwarmRouter instance
### route\_task()
Routes a task to a specific swarm by name.
```python theme={null}
def route_task(self, swarm_name: str, task_description: str) -> None
```
**Parameters:**
* `swarm_name` (str): Name of the target swarm
* `task_description` (str): The task to route
`get_swarms_info()` is not a method on `HybridHierarchicalClusterSwarm`. It is a standalone helper (`from swarms.structs.multi_agent_exec import get_swarms_info`) that the constructor calls internally to build the router agent's system prompt from the `swarms` list.
## Usage Examples
### Full Legal Practice Example
```python theme={null}
from swarms import Agent, SwarmRouter
from swarms.structs.hybrid_hiearchical_peer_swarm import (
HybridHierarchicalClusterSwarm,
)
# Core Legal Agent Definitions
litigation_agent = Agent(
agent_name="Litigator",
system_prompt="You handle lawsuits. Analyze facts, build arguments, and develop case strategy.",
model_name="claude-sonnet-4-6",
max_loops=1,
)
corporate_agent = Agent(
agent_name="Corporate-Attorney",
system_prompt="You handle business law. Advise on corporate structure, governance, and transactions.",
model_name="claude-sonnet-4-6",
max_loops=1,
)
ip_agent = Agent(
agent_name="IP-Attorney",
system_prompt="You protect intellectual property. Handle patents, trademarks, copyrights, and trade secrets.",
model_name="claude-sonnet-4-6",
max_loops=1,
)
employment_agent = Agent(
agent_name="Employment-Attorney",
system_prompt="You handle workplace matters. Address hiring, termination, discrimination, and labor issues.",
model_name="claude-sonnet-4-6",
max_loops=1,
)
paralegal_agent = Agent(
agent_name="Paralegal",
system_prompt="You assist attorneys. Conduct research, draft documents, and organize case files.",
model_name="claude-sonnet-4-6",
max_loops=1,
)
doc_review_agent = Agent(
agent_name="Document-Reviewer",
system_prompt="You examine documents. Extract key information and identify relevant content.",
model_name="claude-sonnet-4-6",
max_loops=1,
)
# Practice Area Swarm Routers
litigation_swarm = SwarmRouter(
name="litigation-practice",
description="Handle all aspects of litigation",
agents=[litigation_agent, paralegal_agent, doc_review_agent],
swarm_type="SequentialWorkflow",
)
corporate_swarm = SwarmRouter(
name="corporate-practice",
description="Handle business and corporate legal matters",
agents=[corporate_agent, paralegal_agent],
swarm_type="SequentialWorkflow",
)
ip_swarm = SwarmRouter(
name="ip-practice",
description="Handle intellectual property matters",
agents=[ip_agent, paralegal_agent],
swarm_type="SequentialWorkflow",
)
employment_swarm = SwarmRouter(
name="employment-practice",
description="Handle employment and labor law matters",
agents=[employment_agent, paralegal_agent],
swarm_type="SequentialWorkflow",
)
# Cross-functional Swarm Routers
m_and_a_swarm = SwarmRouter(
name="mergers-acquisitions",
description="Handle mergers and acquisitions",
agents=[
corporate_agent,
ip_agent,
employment_agent,
doc_review_agent,
],
swarm_type="ConcurrentWorkflow",
)
dispute_swarm = SwarmRouter(
name="dispute-resolution",
description="Handle complex disputes requiring multiple specialties",
agents=[litigation_agent, corporate_agent, doc_review_agent],
swarm_type="ConcurrentWorkflow",
)
# Create the HHCS
hybrid_hierarchical_swarm = HybridHierarchicalClusterSwarm(
name="hybrid-hierarchical-swarm",
description="A hybrid hierarchical swarm that uses a hybrid hierarchical peer model to solve complex tasks.",
swarms=[
litigation_swarm,
corporate_swarm,
ip_swarm,
employment_swarm,
m_and_a_swarm,
dispute_swarm,
],
max_loops=1,
router_agent_model_name="claude-sonnet-4-6",
)
# Run a task
result = hybrid_hierarchical_swarm.run(
"What is the best way to file for a patent for AI technology?"
)
print(result)
```
## Features
* **Router-based task distribution**: Central router agent analyzes incoming tasks and directs them to appropriate specialized swarms
* **Hybrid architecture**: Combines hierarchical control with clustered specialization
* **Parallel processing**: Multiple swarms can work simultaneously on different aspects of complex tasks
* **Flexible swarm types**: Supports both sequential and concurrent workflows within swarms
* **Comprehensive result aggregation**: Collects and combines outputs from all contributing swarms
## How It Works
1. **Task Input**: A task is submitted to the HHCS
2. **Router Analysis**: The router agent analyzes the task requirements
3. **Swarm Selection**: The most appropriate specialized swarm is selected based on the task analysis
4. **Task Routing**: The task is routed to the selected swarm for processing
5. **Parallel Processing**: The selected swarm's agents process the task (sequentially or concurrently depending on swarm type)
6. **Result Collection**: Outputs from all contributing agents are collected into the conversation history
7. **Final Output**: The aggregated results are returned
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/hybrid_hiearchical_peer_swarm.py)
# HierarchicalStructuredCommunicationFramework
Source: https://docs.swarms.world/api/hierarchical-communication-framework
A multi-agent framework implementing structured communication and hierarchical evaluation based on the 'Talk Structurally, Act Hierarchically' approach
## Overview
The Hierarchical Structured Communication Framework implements the "Talk Structurally, Act Hierarchically" approach for LLM multi-agent systems, based on the research paper arXiv:2502.11098. It provides structured communication protocols with specialized agent classes for content generation, evaluation, refinement, and supervision.
## Installation
```bash theme={null}
pip install -U swarms
```
## Key Components
### Agent Classes
* `HierarchicalStructuredCommunicationGenerator` - Creates initial content
* `HierarchicalStructuredCommunicationEvaluator` - Evaluates content quality
* `HierarchicalStructuredCommunicationRefiner` - Improves content based on feedback
* `HierarchicalStructuredCommunicationSupervisor` - Coordinates workflow
### Main Framework
* `HierarchicalStructuredCommunicationFramework` - Main orchestrator class
## Attributes
Name of the framework instance
Main supervisor agent that coordinates the workflow. If not provided, a default `Agent` supervisor is created automatically.
List of generator agents for creating initial content. If not provided, a single default generator agent is created automatically.
List of evaluator agents for assessing content quality. If not provided (and `enable_hierarchical_evaluation=True`), a single default evaluator agent is created automatically.
List of refiner agents for improving content based on feedback. If not provided, a single default refiner agent is created automatically.
Dedicated supervisor that coordinates the hierarchical evaluation phase. Created automatically if not provided.
Maximum number of refinement loops
Format applied to the conversation history.
Display name for the main supervisor agent.
Display name for the evaluation supervisor agent.
Enable the structured communication protocol with Message (M\_ij), Background (B\_ij), and Intermediate Output (I\_ij)
Enable hierarchical evaluation with supervisor coordination
Enable shared memory between agents
LLM model name to use for the agents
Enable verbose logging
Route agent calls through a local Ollama server instead of a hosted provider.
Base URL for the Ollama server when `use_ollama=True`.
API key sent to the Ollama server when `use_ollama=True`.
## Methods
### run()
Execute the complete workflow for a given task, looping up to `max_loops` times (set at construction).
```python theme={null}
def run(self, task: str, img: str = None, *args, **kwargs) -> dict
```
**Parameters:**
* `task` (str): The task to execute
* `img` (str, optional): Optional image input
**Returns:** A dictionary containing `final_result`, `total_loops`, `conversation_history`, `evaluation_results`, and `intermediate_outputs`
`run()` does not accept a `max_loops` override — the number of refinement loops is fixed by the `max_loops` value passed to the constructor.
### step()
Execute a single workflow step (generate, evaluate, refine).
```python theme={null}
def step(self, task: str, img: str = None, *args, **kwargs) -> dict
```
**Parameters:**
* `task` (str): The task to execute for one step
* `img` (str, optional): Optional image input
**Returns:** A dictionary with `generator_result`, `evaluation_results`, `refined_result`, and `conversation_history` (or an `error` key on failure)
### send\_structured\_message()
Send a structured communication message between agents, following the Message (M\_ij) / Background (B\_ij) / Intermediate Output (I\_ij) protocol.
```python theme={null}
def send_structured_message(
self,
sender: str,
recipient: str,
message: str,
background: str = "",
intermediate_output: str = "",
) -> StructuredMessage
```
**Parameters:**
* `sender` (str): Name of the sending agent
* `recipient` (str): Name of the receiving agent
* `message` (str): Specific task message (M\_ij)
* `background` (str, optional): Background context (B\_ij)
* `intermediate_output` (str, optional): Intermediate output (I\_ij)
**Returns:** The `StructuredMessage` that was appended to `conversation_history`
### run\_hierarchical\_evaluation()
Run the hierarchical evaluation system with supervisor coordination.
```python theme={null}
def run_hierarchical_evaluation(
self, content: str, evaluation_criteria: List[str] = None
) -> List[EvaluationResult]
```
**Parameters:**
* `content` (str): Content to evaluate
* `evaluation_criteria` (List\[str], optional): Criteria to evaluate against. Defaults to `["accuracy", "completeness", "clarity", "relevance"]`.
**Returns:** A list of `EvaluationResult` objects, one per evaluator
## Usage Examples
### Quick Start
```python theme={null}
from swarms.structs.hierarchical_structured_communication_framework import (
HierarchicalStructuredCommunicationFramework,
HierarchicalStructuredCommunicationGenerator,
HierarchicalStructuredCommunicationEvaluator,
HierarchicalStructuredCommunicationRefiner,
HierarchicalStructuredCommunicationSupervisor
)
# Create specialized agents
generator = HierarchicalStructuredCommunicationGenerator(
agent_name="ContentGenerator"
)
evaluator = HierarchicalStructuredCommunicationEvaluator(
agent_name="QualityEvaluator"
)
refiner = HierarchicalStructuredCommunicationRefiner(
agent_name="ContentRefiner"
)
supervisor = HierarchicalStructuredCommunicationSupervisor(
agent_name="WorkflowSupervisor"
)
# Create the framework
framework = HierarchicalStructuredCommunicationFramework(
name="MyFramework",
supervisor=supervisor,
generators=[generator],
evaluators=[evaluator],
refiners=[refiner],
max_loops=3
)
# Run the workflow
result = framework.run("Create a comprehensive analysis of AI trends in 2024")
```
### Basic Usage with Default Supervisor
```python theme={null}
from swarms.structs.hierarchical_structured_communication_framework import (
HierarchicalStructuredCommunicationFramework,
HierarchicalStructuredCommunicationGenerator,
HierarchicalStructuredCommunicationEvaluator,
HierarchicalStructuredCommunicationRefiner
)
# Create agents with custom names
generator = HierarchicalStructuredCommunicationGenerator(agent_name="ContentGenerator")
evaluator = HierarchicalStructuredCommunicationEvaluator(agent_name="QualityEvaluator")
refiner = HierarchicalStructuredCommunicationRefiner(agent_name="ContentRefiner")
# Create framework with default supervisor
framework = HierarchicalStructuredCommunicationFramework(
generators=[generator],
evaluators=[evaluator],
refiners=[refiner],
max_loops=3,
verbose=True
)
# Execute task
result = framework.run("Write a detailed report on renewable energy technologies")
print(result["final_result"])
```
### Advanced Configuration
```python theme={null}
from swarms.structs.hierarchical_structured_communication_framework import (
HierarchicalStructuredCommunicationFramework
)
# Create framework with custom configuration
framework = HierarchicalStructuredCommunicationFramework(
name="AdvancedFramework",
max_loops=5,
enable_structured_communication=True,
enable_hierarchical_evaluation=True,
shared_memory=True,
model_name="claude-sonnet-4-6",
verbose=True
)
# Run the task (loops up to the max_loops set above)
result = framework.run(
"Analyze the impact of climate change on global agriculture"
)
```
## How It Works
The framework operates through a structured multi-phase workflow:
1. **Generation Phase**: Generator agents create initial content based on the task
2. **Evaluation Phase**: Evaluator agents assess the quality of generated content using structured communication protocols
3. **Refinement Phase**: Refiner agents improve content based on evaluation feedback
4. **Supervision**: The supervisor agent coordinates the entire workflow, deciding when to iterate or finalize
5. **Iteration**: Steps 1-4 repeat up to `max_loops` times until quality thresholds are met
### Structured Communication Protocol
The framework uses a formal communication protocol with three components:
* **Message (M\_ij)**: Direct communication between agents
* **Background (B\_ij)**: Contextual information shared between agents
* **Intermediate Output (I\_ij)**: Partial results passed between workflow stages
## Features
* **Structured Communication**: Formal protocol for inter-agent messaging
* **Hierarchical Evaluation**: Multi-level quality assessment with supervisor oversight
* **Iterative Refinement**: Content improves through generate-evaluate-refine loops
* **Specialized Agents**: Purpose-built agent classes for each workflow role
* **Configurable**: Flexible configuration for communication, evaluation, and memory
* **Shared Memory**: Optional shared memory between agents for context retention
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/hierarchical_structured_communication_framework.py)
# HierarchicalSwarm
Source: https://docs.swarms.world/api/hierarchical-swarm
A hierarchical multi-agent orchestrator that coordinates agents through a director
## Overview
The `HierarchicalSwarm` class implements a hierarchical architecture where a director agent creates plans and distributes tasks to worker agents. The director can provide feedback and iterate on results through multiple loops to achieve desired outcomes while maintaining conversation history throughout the process.
## Class Definition
```python theme={null}
from swarms import HierarchicalSwarm
```
## Parameters
The name identifier for this swarm instance
A description of the swarm's purpose and capabilities
The director agent that coordinates the swarm. If None, a default director will be created
List of worker agents available for task execution. Must not be empty
Maximum number of feedback loops the swarm can perform (must be > 0)
Format for the final output of the swarm
Model name for the feedback director
Name identifier for the director agent
Model name for the main director agent
Whether to add collaboration prompts to agents
Whether director feedback is enabled
Enable interactive dashboard with real-time monitoring
Custom system prompt for the director agent
Enable enhanced multi-agent collaboration prompts for worker agents
Temperature parameter for director agent's LLM
Top-p parameter for director agent's LLM
Whether to enable the planning phase before order distribution
Whether to enable autosaving of conversation history to workspace directory
Enable verbose logging output
When `True`, worker agents assigned in a single director order are executed concurrently; when `False`, they run one after another.
Thread pool size used when `parallel_execution` is `True`. Defaults to 95% of available CPU cores. Must be greater than zero if provided.
When `True`, a judge agent evaluates the worker outputs to inform the director's feedback loop.
Model used by the judge agent when `agent_as_judge=True`.
Additional `Agent` constructor settings for the automatically created director. Values in this dictionary override the legacy director parameters. Use `planning_system_prompt` to customize the optional planning pass. The swarm always forces the director's `output_type` to `"final"`.
Number of retry attempts after a worker's initial execution fails. After all attempts are exhausted, the worker is marked unavailable in the shared conversation and its failure is reported to the director. Must be greater than or equal to `0`.
Maximum number of recovery rounds in which the director can reassign failed tasks to healthy workers. The swarm continues running when recovery cannot complete a task. Must be greater than or equal to `0`.
Whether to print the director's plan and orders to the console at each step
`HierarchicalSwarm` forces every configurable director and worker agent to use `output_type="final"`. The swarm-level `output_type` parameter still controls the format returned by `HierarchicalSwarm.run()`.
## Methods
### `run()`
```python theme={null}
def run(
self,
task: Optional[str] = None,
img: Optional[str] = None,
*args,
**kwargs,
) -> Any
```
Executes the hierarchical swarm for the specified number of feedback loops.
**Parameters:**
The initial task to be processed by the swarm. If None and interactive mode is enabled, will prompt for input
Optional image input for the agents
**Returns:**
The formatted conversation history as output, formatted according to output\_type configuration
**Workflow:**
1. Director creates a plan and distributes orders to agents
2. Agents execute tasks and report back to director
3. Failed workers are retried up to `max_agent_retries`
4. Exhausted workers are marked unavailable in shared context
5. Director reassigns failed tasks to healthy workers, up to `max_reassignment_attempts`
6. Director evaluates results and issues new orders if needed (up to `max_loops`)
7. All context and conversation history is preserved throughout
8. Returns final output formatted per swarm-level `output_type`
***
### `step()`
```python theme={null}
def step(
self,
task: str,
img: str = None,
*args,
**kwargs,
) -> Any
```
Executes a single step of the hierarchical swarm workflow.
**Parameters:**
The task to be processed in this step
Optional image input for the task
**Returns:**
The results from this step, either agent outputs or director feedback
**Process:**
1. Director runs to create plan and orders
2. Orders are parsed and distributed
3. Agents execute assigned tasks
4. Optional director feedback on results
***
### `batched_run()`
```python theme={null}
def batched_run(
self,
tasks: List[str],
*args,
img: Optional[Union[str, List[Optional[str]]]] = None,
imgs: Optional[List[Optional[str]]] = None,
max_workers: Optional[int] = None,
return_agent_output_dict: bool = False,
return_exceptions: bool = False,
**kwargs,
)
```
Executes the hierarchical swarm for multiple tasks, calling `run()` once per task via the shared batch utility.
**Parameters:**
Tasks to execute
One image applied to every task, or one image per task
Images paired with tasks
Concurrent task limit; `None` runs tasks sequentially
Return results keyed by task instead of as a list
Return exceptions instead of raising them
**Returns:**
Results in task order, or keyed by task when `return_agent_output_dict=True`
***
### `display_hierarchy()`
```python theme={null}
def display_hierarchy(self) -> None
```
Displays the hierarchical structure of the swarm using Rich Tree visualization.
Shows the Director at the top level and all worker agents as children branches with their configurations.
***
### `reliability_checks()`
```python theme={null}
def reliability_checks(self) -> None
```
Performs validation checks to ensure the swarm is properly configured.
**Validates:**
* At least one agent is provided
* max\_loops is greater than 0
* max\_agent\_retries is greater than or equal to 0
* max\_reassignment\_attempts is greater than or equal to 0
* max\_workers is greater than 0 when provided
* Director is available (creates default if needed)
**Raises:**
* `ValueError`: If swarm configuration is invalid
## Data Models
### HierarchicalOrder
```python theme={null}
class HierarchicalOrder(BaseModel):
agent_name: str # Name of agent assigned to execute task
task: str # Specific task to be executed
```
### SwarmSpec
```python theme={null}
class SwarmSpec(BaseModel):
plan: str # Director's overall plan
orders: List[HierarchicalOrder] # Task assignments to agents
```
### JudgeReport
Used when `agent_as_judge=True`. A one-shot judge agent scores each worker agent's output instead of the director issuing free-form feedback.
```python theme={null}
class AgentScore(BaseModel):
agent_name: str
score: int # 0-10
reasoning: str
suggestions: str
class JudgeReport(BaseModel):
overall_quality: int # 0-10
scores: List[AgentScore]
summary: str
```
## Interactive Dashboard
When `interactive=True`, the HierarchicalSwarm displays a real-time dashboard with:
* **Operations Status**: Swarm name, description, current loop, agent count
* **Director Operations**: Current plan and active orders
* **Agent Monitoring Matrix**: Real-time agent status, tasks, and outputs
* **Progress Tracking**: Loop completion and runtime metrics
The dashboard uses Swarms Corporation styling with red/black color scheme and provides professional monitoring of swarm operations.
## Usage Example
```python theme={null}
from swarms import Agent, HierarchicalSwarm
# Create worker agents
research_agent = Agent(
agent_name="Research-Specialist",
system_prompt="Expert in research and data gathering",
model_name="claude-sonnet-4-6"
)
analysis_agent = Agent(
agent_name="Analysis-Specialist",
system_prompt="Expert in data analysis",
model_name="claude-sonnet-4-6"
)
writing_agent = Agent(
agent_name="Writing-Specialist",
system_prompt="Expert in writing and communication",
model_name="claude-sonnet-4-6"
)
# Create hierarchical swarm
swarm = HierarchicalSwarm(
name="Research-Analysis-Team",
description="A hierarchical team for research and analysis",
agents=[research_agent, analysis_agent, writing_agent],
max_loops=2,
director_settings={
"model_name": "claude-sonnet-4-6",
"temperature": 0.2,
"max_tokens": 4000,
"persistent_memory": False,
},
max_agent_retries=1,
max_reassignment_attempts=1,
interactive=True,
verbose=True
)
# Display the hierarchy
swarm.display_hierarchy()
# Execute a task
result = swarm.run(
task="Analyze the impact of AI on healthcare and create a comprehensive report"
)
print(result)
```
## Conversation Autosave
When `autosave=True`, conversation history is automatically saved to:
`workspace_dir/swarms/HierarchicalSwarm/{swarm-name}-{timestamp}/conversation_history.json`
This enables:
* Post-execution analysis
* Debugging and monitoring
* Historical tracking of swarm operations
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/hiearchical_swarm.py)
# LLMCouncil
Source: https://docs.swarms.world/api/llm-council
A collaborative council of LLM agents that independently answer queries, review each other's responses, and synthesize the best elements into a final answer
## Overview
The `LLMCouncil` creates a council of specialized LLM agents that collaborate through independent responses, peer review, and synthesis. Inspired by Andrej Karpathy's llm-council, it demonstrates how different models evaluate and rank each other's work.
## Installation
```bash theme={null}
pip install -U swarms
```
## Workflow
1. **Dispatch**: Query sent to all council members in parallel
2. **Respond**: Each member independently answers the query
3. **Evaluate**: All members review and rank anonymized responses
4. **Synthesize**: Chairman creates final answer based on responses and rankings
## Attributes
Unique identifier for the council
Name of the council
Description of the council's purpose
List of Agent instances representing council members. If None, creates default council with GPT-5.1, Gemini 3 Pro, Claude Sonnet 4.5, and Grok-4
Model name for the Chairman agent that synthesizes responses
Whether to print progress and intermediate results
Format for the output ("list", "dict", "string", "final", "json", "yaml", etc.)
## Methods
### run()
Execute the full LLM Council workflow.
```python theme={null}
def run(self, task: str = None, query: str = None)
```
**Parameters:**
* `task` (str): The user's task/query to process (preferred parameter)
* `query` (str): Alias for task (kept for backwards compatibility)
**Returns:** Formatted output containing conversation history with all responses, evaluations, and synthesis
### batched\_run()
Run the LLM Council workflow for a batch of tasks.
```python theme={null}
def batched_run(self, tasks: List[str]) -> list
```
**Parameters:**
* `tasks` (List\[str]): List of tasks to process
**Returns:** List of formatted outputs
## Usage Examples
### Basic Usage with Default Council
```python theme={null}
from swarms import LLMCouncil
# Create council with default members
council = LLMCouncil(
verbose=True,
output_type="final"
)
# Process a query
result = council.run(
task="What are the key considerations for building a production AI system?"
)
print(result)
```
### Custom Council Members
```python theme={null}
from swarms import Agent, LLMCouncil
# Define custom council members
council_members = [
Agent(
agent_name="Security-Expert",
agent_description="Security and privacy specialist",
system_prompt="You are a security expert. Focus on security implications.",
model_name="openai/gpt-5.4",
max_loops=1,
),
Agent(
agent_name="Performance-Expert",
agent_description="Performance and scalability specialist",
system_prompt="You are a performance expert. Focus on scalability.",
model_name="anthropic/claude-sonnet-4-5",
max_loops=1,
),
Agent(
agent_name="UX-Expert",
agent_description="User experience specialist",
system_prompt="You are a UX expert. Focus on user experience.",
model_name="gemini/gemini-2.5-flash",
max_loops=1,
),
]
council = LLMCouncil(
council_members=council_members,
chairman_model="claude-sonnet-4-6",
verbose=True
)
result = council.run(task="Design a mobile app for health tracking")
```
### Batch Processing
```python theme={null}
tasks = [
"Explain quantum computing in simple terms",
"What are best practices for API design?",
"How to optimize database queries?"
]
results = council.batched_run(tasks)
for i, result in enumerate(results):
print(f"\nTask {i+1} Result:")
print(result)
```
### Different Output Formats
```python theme={null}
# Get only final synthesized answer
council_final = LLMCouncil(output_type="final")
final_answer = council_final.run(task="Explain machine learning")
# Get full conversation history as dict
council_dict = LLMCouncil(output_type="dict")
full_conversation = council_dict.run(task="Explain machine learning")
# Get as JSON
council_json = LLMCouncil(output_type="json")
json_output = council_json.run(task="Explain machine learning")
```
### Non-Verbose Mode
```python theme={null}
# Run without printing progress
council = LLMCouncil(verbose=False)
result = council.run(task="Some query")
```
## Default Council Members
When no custom members are provided, the default council includes:
1. **GPT-5.1 Councilor**
* Specialization: Analytical and comprehensive responses
* Focus: Deep analysis, thorough exploration
2. **Gemini 3 Pro Councilor**
* Specialization: Concise and well-structured responses
* Focus: Clear structure, efficient information processing
3. **Claude Sonnet 4.5 Councilor**
* Specialization: Thoughtful and balanced responses
* Focus: Nuanced reasoning, ethical considerations
4. **Grok-4 Councilor**
* Specialization: Creative and innovative responses
* Focus: Unique perspectives, creative problem-solving
## Evaluation Process
Each council member evaluates all responses (anonymized) and provides:
1. **Rankings**: Ordered list from best to worst response
2. **Reasoning**: Explanation for each ranking
3. **Observations**: Additional insights about strengths/weaknesses
Example evaluation format:
```
RANKINGS:
1. Response B: Clear structure and comprehensive coverage
2. Response A: Good depth but could be more organized
3. Response D: Creative but lacks some technical details
4. Response C: Too verbose, missing key points
ADDITIONAL OBSERVATIONS:
Common strength: All responses addressed the core question
Area for improvement: More concrete examples needed
```
## Synthesis Process
The Chairman agent:
1. Reviews all original responses
2. Considers all evaluations and rankings
3. Identifies strongest elements from each response
4. Creates cohesive final answer incorporating best aspects
5. Acknowledges which perspectives influenced the synthesis
## Output Structure
The conversation history includes:
```python theme={null}
[
{"role": "User", "content": "Original query"},
{"role": "GPT-5.1-Councilor", "content": "Response..."},
{"role": "Gemini-3-Pro-Councilor", "content": "Response..."},
{"role": "Claude-Sonnet-4.5-Councilor", "content": "Response..."},
{"role": "Grok-4-Councilor", "content": "Response..."},
{"role": "GPT-5.1-Councilor-Evaluation", "content": "Evaluation..."},
{"role": "Gemini-3-Pro-Councilor-Evaluation", "content": "Evaluation..."},
{"role": "Claude-Sonnet-4.5-Councilor-Evaluation", "content": "Evaluation..."},
{"role": "Grok-4-Councilor-Evaluation", "content": "Evaluation..."},
{"role": "Chairman", "content": "Final synthesized answer"}
]
```
## Features
* **Parallel Execution**: All council members respond simultaneously
* **Anonymous Evaluation**: Responses are anonymized during peer review
* **Multi-Model Diversity**: Leverages different LLM strengths
* **Peer Review**: Each member evaluates all responses objectively
* **Intelligent Synthesis**: Chairman creates cohesive final answer
* **Transparent Process**: Full conversation history available
* **Flexible Output**: Multiple output format options
* **Batch Processing**: Handle multiple queries efficiently
## Best Practices
1. **Council Composition**: Include agents with complementary strengths
2. **Clear Queries**: Provide well-defined questions for best results
3. **Output Type**: Use "final" for end-user answers, "dict" for analysis
4. **Custom Members**: Tailor council to your domain/use case
5. **Verbose Mode**: Enable for understanding the decision process
# LLMManager
Source: https://docs.swarms.world/api/llm-manager
Model selection, LiteLLM construction, invocation, and fallback rotation for an agent
## Overview
`LLMManager` owns everything an `Agent` does with a language model: building the `LiteLLM` instance from configuration, rotating through fallback models when one fails, checking model capabilities, invoking the model across all streaming modes, and re-running a failed task down the fallback chain.
Every `Agent` builds one automatically as `agent.llm_manager`. You rarely construct it yourself — but it is where the behavior lives, and the agent's LLM methods are thin wrappers over it.
```python theme={null}
from swarms import Agent
agent = Agent(agent_name="Analyst", model_name="gpt-5.4-mini")
agent.llm_manager.get_current_model() # 'gpt-5.4-mini'
agent.llm_manager.get_available_models() # ['gpt-5.4-mini']
```
## Import
```python theme={null}
from swarms.agents.llm_manager import LLMManager
```
## Design
Unlike the agent's other collaborators, `LLMManager` holds a reference back to its owning agent and reads configuration **live** rather than snapshotting it.
That is deliberate. Agents mutate their own LLM configuration at run time: `system_prompt` grows when skills load, `tools_list_dictionary` changes when tools are registered, `streaming_on` is toggled per call by `run_stream`. A snapshot taken at construction would silently go stale.
Anything the manager writes — `model_name`, `current_model_index`, `llm` — is written back to the agent, so `agent.llm`, serialization, and `save()` / `load()` all behave exactly as before.
The owning `Agent`. Read for configuration; written to for `model_name`, `current_model_index`, and `llm`.
## Model selection and fallback
Configure fallbacks on the agent, and the manager handles rotation.
```python theme={null}
agent = Agent(
agent_name="Resilient",
fallback_models=["gpt-5.4-mini", "claude-sonnet-4-6", "gpt-5.4"],
)
```
### get\_available\_models
```python theme={null}
def get_available_models() -> List[str]
```
Models in preference order. Built from `fallback_models` when set, otherwise from `model_name` plus `fallback_model_name` (de-duplicated).
### get\_current\_model
```python theme={null}
def get_current_model() -> str
```
The model currently in use. Falls back to the first available model, then to `gpt-5.4`, if the index runs out of range.
### switch\_to\_next\_model
```python theme={null}
def switch_to_next_model() -> bool
```
Advance to the next model in the list, update `agent.model_name`, and rebuild `agent.llm` against it. Returns `False` when the list is exhausted. Model switches are always logged.
### reset\_model\_index
```python theme={null}
def reset_model_index() -> None
```
Return to the primary model and rebuild the LLM.
### is\_fallback\_available
```python theme={null}
def is_fallback_available() -> bool
```
`True` when more than one model is configured.
## Construction
### build
```python theme={null}
def build(*args, **kwargs) -> Optional[LiteLLM]
```
Assemble the `LiteLLM` instance from every configuration source: the agent's core settings, `llm_args`, `tools_list_dictionary`, MCP tool schemas, and anything passed here.
A single dict is merged directly into the configuration; anything else is stored under `additional_args`.
Merged into the LiteLLM configuration, taking precedence over defaults.
Returns the instance, or `None` if initialization raised `AgentLLMInitializationError`. `parallel_tool_calls` is enabled automatically when the agent has two or more tools or any MCP server configured.
### get\_parameters
```python theme={null}
def get_parameters() -> str
```
The current LiteLLM instance's attributes as a string.
### check\_model\_supports\_utilities
```python theme={null}
def check_model_supports_utilities(img: Optional[str] = None) -> None
```
Log an error for each capability the current model lacks — vision when an image is supplied, function calling when a tool schema is set, parallel function calling when more than two tools are registered. **Logging only; never raises.**
### randomize\_temperature
```python theme={null}
def randomize_temperature() -> None
```
Reset the LLM's temperature to a random value in `[0.0, 1.0]`. Used between loops when `dynamic_temperature_enabled` is set; falls back to `0.5` when the LLM exposes no temperature.
## Invocation
### call
```python theme={null}
def call(
task: str,
img: Optional[str] = None,
imgs: Optional[List[str]] = None,
current_loop: int = 0,
streaming_callback: Optional[Callable[[str], None]] = None,
*args,
**kwargs,
) -> Any
```
Call the model, selecting one of three modes from the agent's configuration:
Direct `llm.run()` returning the complete string. Used when neither `stream` nor `streaming_on` is set.
`agent.streaming_on = True`. Three sub-behaviors:
* With `streaming_callback` — tokens forwarded in real time
* With `print_on=False` — silent collection
* Otherwise — a live Rich streaming panel
`agent.stream = True`. Emits a `token_info` dict per token with full metadata: index, model, id, finish reason, citations, usage, logprobs, timestamp.
The prompt to send.
Image input for multimodal models — file path, URL, data URI, or raw base64.
Multiple image inputs for multimodal models, same accepted forms as `img`.
Loop iteration, used in streaming panel titles.
Receives `token_info` dicts in detailed streaming, token strings in panel streaming.
**Returns** the complete response string — or, when the model made tool calls mid-stream, the assembled tool-call list instead. `is_last` is stripped from `kwargs` before dispatch.
### Stream plumbing
```python theme={null}
def stream_with_tool_collection(stream, tool_calls_out: list)
def extract_thinking_from_stream(stream)
```
`stream_with_tool_collection` forwards every chunk unchanged while assembling fragmented `delta.tool_calls` deltas into a complete tool-call list. `extract_thinking_from_stream` swallows reasoning chunks from models that emit them, flushes them to a thinking panel, and yields only content chunks onward.
## Fallback execution
### handle\_fallback\_execution
```python theme={null}
def handle_fallback_execution(
task=None, img=None, imgs=None, correct_answer=None,
streaming_callback=None, original_error=None, *args, **kwargs,
) -> Any
```
Re-run a failed task against the next fallback model, recursing down the chain until it succeeds or every model is exhausted — at which point the original error goes to the agent's error handler and `None` is returned.
## Agent-level wrappers
Each of these delegates straight to the manager and remains the supported public API:
| `Agent` method | Delegates to |
| ------------------------------------------------------------- | ---------------------------------- |
| `llm_handling(*args, **kwargs)` | `build()` |
| `call_llm(task, img, imgs, current_loop, streaming_callback)` | `call()` |
| `get_available_models()` | `get_available_models()` |
| `get_current_model()` | `get_current_model()` |
| `switch_to_next_model()` | `switch_to_next_model()` |
| `reset_model_index()` | `reset_model_index()` |
| `is_fallback_available()` | `is_fallback_available()` |
| `check_model_supports_utilities(img)` | `check_model_supports_utilities()` |
| `dynamic_temperature()` | `randomize_temperature()` |
| `get_llm_parameters()` | `get_parameters()` |
| `_handle_fallback_execution(...)` | `handle_fallback_execution()` |
## Related
The class that owns the manager
Supported models and provider configuration
# Multi-Agent Blocks
Source: https://docs.swarms.world/api/ma-blocks
Small building blocks for multi-agent workflows: aggregate concurrent runs, run a single agent safely, and look up agents by name or id
## Overview
`swarms.structs.ma_blocks` is a small set of helper functions for composing multi-agent workflows without instantiating a full swarm class.
| Function | What it does |
| ------------------------------ | ------------------------------------------------------------------------------------------- |
| `aggregate` | Run a list of agents concurrently on the same task, then synthesize via an aggregator agent |
| `run_agent` | Run a single agent with argument validation and error wrapping |
| `find_agent_by_name` | Look up an agent by `.agent_name` in a list |
| `find_agent_by_id` | Look up an agent by `.id` in a list |
| `find_multiple_agents_by_name` | Look up several agents by `.agent_name` at once |
| `return_all_agent_names` | Return every agent's `.agent_name` |
`aggregate`, `run_agent`, and `find_agent_by_name` are exported from the top-level `swarms` package. The rest must be imported from `swarms.structs.ma_blocks`.
Reach for these when you want quick composability — a function call instead of `ConcurrentWorkflow(...).run(...)`.
## Installation
```bash theme={null}
pip install -U swarms
```
## aggregate()
Run every worker on the same task concurrently, then hand the combined transcript to an aggregator agent for synthesis.
```python theme={null}
def aggregate(
workers: List[Callable],
task: str = None,
type: HistoryOutputType = "all",
aggregator_model_name: str = "anthropic/claude-3-sonnet-20240229",
)
```
Agents (or any callables matching the `Agent` interface) to run on the task.
Task passed to every worker.
Output format passed to `history_output_formatter`.
Model used by the synthesizing aggregator agent.
**Raises:** `ValueError` if `task` is `None`, `workers` is `None`, or `workers` is not a list of callables.
**Behavior:**
1. All workers run concurrently via `run_agents_concurrently`.
2. Each worker's result is added to a shared `Conversation`, keyed by `worker.agent_name`.
3. A new `Aggregator` agent runs with `AGGREGATOR_SYSTEM_PROMPT` and produces a \~3,000-word synthesis of the worker outputs.
4. The aggregator's response is appended to the conversation.
5. The full conversation is returned formatted per `type`.
## run\_agent()
Run a single agent on a task with type-checking and error wrapping. Thin convenience over `agent.run(task)`.
```python theme={null}
def run_agent(
agent: Agent,
task: str,
type: HistoryOutputType = "all",
*args,
**kwargs,
)
```
Must be an instance of `swarms.structs.agent.Agent`.
Task passed to the agent.
Accepted but not currently consumed beyond the call — present for API parity with `aggregate`.
**Raises:**
| Exception | Condition |
| -------------- | -------------------------------------------------------------- |
| `ValueError` | `agent` or `task` is `None` |
| `TypeError` | `agent` is not an `Agent` instance |
| `RuntimeError` | Any exception raised by `agent.run()` is wrapped and re-raised |
**Returns:** Whatever `agent.run(task)` returns.
## find\_agent\_by\_name()
Look up an agent by name. Performs a plain linear scan over `agents`, matching each agent's `.agent_name` against `agent_name` and returning the first match — O(n) per call, with no caching and no fallback to `.name`.
```python theme={null}
def find_agent_by_name(
agents: List[Union[Agent, Callable]],
agent_name: str,
) -> Agent
```
Non-empty list of agent-like objects.
Name to match against each agent's `.agent_name`.
**Raises:**
| Exception | Condition |
| ------------ | ---------------------------------------------------------------------- |
| `ValueError` | `agents` is empty, `agent_name` is empty/whitespace, or no match found |
| `TypeError` | `agent_name` is not a string |
## find\_agent\_by\_id()
Linear search for an agent by its `.id` attribute. Unlike `find_agent_by_name`, this does not raise on a miss.
```python theme={null}
def find_agent_by_id(
agents: List[Union[Agent, Callable]],
agent_id: str,
) -> Agent
```
List of agent-like objects to search through.
The `.id` value to match.
**Returns:** The matching agent, or `None` if no agent has that `.id`.
**Import:** not exported from top-level `swarms` — use `from swarms.structs.ma_blocks import find_agent_by_id`.
## find\_multiple\_agents\_by\_name()
Look up several agents by `.agent_name` in one call.
```python theme={null}
def find_multiple_agents_by_name(
agents: List[Union[Agent, Callable]],
agent_names: List[str],
) -> List[Agent]
```
List of agent-like objects to search through.
Names to match against each agent's `.agent_name`.
**Returns:** The subset of `agents` whose `.agent_name` is in `agent_names`. Names with no match are silently dropped — no exception is raised.
**Import:** not exported from top-level `swarms` — use `from swarms.structs.ma_blocks import find_multiple_agents_by_name`.
## return\_all\_agent\_names()
Return every agent's `.agent_name`.
```python theme={null}
def return_all_agent_names(
agents: List[Union[Agent, Callable]],
) -> List[str]
```
List of agent-like objects.
**Returns:** `List[str]` — `agent.agent_name` for every agent, in order.
**Import:** not exported from top-level `swarms` — use `from swarms.structs.ma_blocks import return_all_agent_names`.
## Usage Examples
### Aggregate Concurrent Analyses
```python theme={null}
from swarms import Agent, aggregate
analysts = [
Agent(agent_name="Bull-Case", model_name="claude-sonnet-4-6", max_loops=1,
system_prompt="Argue the bull case using data."),
Agent(agent_name="Bear-Case", model_name="claude-sonnet-4-6", max_loops=1,
system_prompt="Argue the bear case using data."),
Agent(agent_name="Macro-Lens", model_name="claude-sonnet-4-6", max_loops=1,
system_prompt="Frame the question in macro context."),
]
result = aggregate(
workers=analysts,
task="Is now a good time to invest in industrial automation stocks?",
)
```
The returned value is the full conversation — three analyst responses plus the aggregator's synthesis.
### Safe Single-Agent Run
```python theme={null}
from swarms import Agent, run_agent
agent = Agent(
agent_name="Drafter",
model_name="claude-sonnet-4-6",
max_loops=1,
)
# Raises TypeError if the first argument isn't an Agent
result = run_agent(agent, "Write a release-note bullet for the v12.1 streaming API")
```
### Look Up an Agent by Name
```python theme={null}
from swarms import Agent, find_agent_by_name
agents = [
Agent(agent_name="Researcher", model_name="claude-sonnet-4-6"),
Agent(agent_name="Writer", model_name="claude-sonnet-4-6"),
Agent(agent_name="Editor", model_name="claude-sonnet-4-6"),
]
# Matches against .agent_name by default
writer = find_agent_by_name(agents, "Writer")
```
`find_agent_by_name` matches only against `.agent_name` -- there is no fallback to `.name`.
### Other Lookup Helpers
```python theme={null}
from swarms import Agent
from swarms.structs.ma_blocks import (
find_agent_by_id,
find_multiple_agents_by_name,
return_all_agent_names,
)
agents = [
Agent(agent_name="Researcher", model_name="claude-sonnet-4-6"),
Agent(agent_name="Writer", model_name="claude-sonnet-4-6"),
Agent(agent_name="Editor", model_name="claude-sonnet-4-6"),
]
print(return_all_agent_names(agents))
# ['Researcher', 'Writer', 'Editor']
subset = find_multiple_agents_by_name(agents, ["Writer", "Editor"])
by_id = find_agent_by_id(agents, agents[0].id)
```
## Source Code
View the [source on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/ma_blocks.py).
# MajorityVoting
Source: https://docs.swarms.world/api/majority-voting
A multi-loop consensus building system where multiple agents iteratively refine responses through majority voting
## Overview
The `MajorityVoting` module provides a sophisticated multi-loop consensus building system for agents. Unlike simple majority voting, this system enables iterative consensus building where agents can refine their responses across multiple loops, with each subsequent loop considering the previous consensus. This approach leads to more robust and well-reasoned final decisions by leveraging the collective intelligence of multiple specialized agents.
## Installation
```bash theme={null}
pip install -U swarms
```
## Architecture
```mermaid theme={null}
graph TD
A[MajorityVoting System] --> B[Initialize Agents & Consensus Agent]
B --> C[Process Task]
C --> D{Execution Mode}
D --> E[Single Task]
D --> F[Batch Tasks]
D --> G[Concurrent Tasks]
E --> H[Multi-Loop Execution]
F --> H
G --> H
H --> I[Run All Agents Concurrently]
I --> J[Collect Agent Responses]
J --> K[Run Consensus Agent]
K --> L[Add to Conversation History]
L --> M{More Loops?}
M -->|Yes| I
M -->|No| N[Format Final Output]
N --> O[Return Result]
```
### Key Concepts
* **Multi-Loop Consensus Building**: An iterative process where agents can refine their responses across multiple loops, with each loop building upon the previous consensus.
* **Agents**: Specialized entities (e.g., models, algorithms) that provide expert responses to tasks or queries.
* **Consensus Agent**: An automatically created agent that analyzes and synthesizes responses from all agents to determine the final consensus.
* **Conversation History**: A comprehensive record of all agent interactions, responses, and consensus building across all loops.
* **Concurrent Execution**: Agents run simultaneously for improved performance and efficiency.
## Attributes
Unique identifier for the majority voting system.
Name of the majority voting system.
Description of the system.
A list of agents to be used in the majority voting system.
Whether to autosave conversations.
Whether to enable verbose logging.
Maximum number of consensus building loops.
Output format: "str", "dict", "list", or other.
System prompt for the consensus agent.
Name for the automatically created consensus agent.
Description for the consensus agent.
Model name for the consensus agent.
Additional keyword arguments passed to the consensus agent.
## Methods
### run()
Executes the multi-loop majority voting system for a single task and returns the consensus result.
```python theme={null}
def run(self, task: str, streaming_callback: Optional[Callable[[str, str, bool], None]] = None, *args, **kwargs) -> Any
```
**Parameters:**
* `task` (str): The task or question to be analyzed by the agent panel
* `streaming_callback` (Optional\[Callable\[\[str, str, bool], None]]): Optional callback invoked as `(agent_name, chunk, is_final)` while the consensus agent streams its response
* `*args` (Any): Variable length argument list passed to individual agents
* `**kwargs` (Any): Arbitrary keyword arguments passed to individual agents
**Returns:** The consensus result formatted according to the specified `output_type`
**Raises:**
* `ValueError`: If the agents list is empty or None
**Process Flow:**
1. Adds the input task to the conversation history
2. For each loop (up to `max_loops`):
* Runs all agents concurrently on the current conversation state
* Collects agent responses and adds them to conversation history
* Runs the consensus agent to analyze and synthesize responses
* Adds consensus output to conversation history
3. Returns the final result in the specified output format
### batch\_run()
Executes the majority voting system for multiple tasks sequentially.
```python theme={null}
def batch_run(self, tasks: List[str], *args, **kwargs) -> List[Any]
```
**Parameters:**
* `tasks` (List\[str]): List of tasks or questions to be processed
* `*args` (Any): Variable length argument list passed to each task execution
* `**kwargs` (Any): Arbitrary keyword arguments passed to each task execution
**Returns:** List of consensus results, one for each input task
### run\_concurrently()
Executes the majority voting system for multiple tasks concurrently using thread pooling.
```python theme={null}
def run_concurrently(self, tasks: List[str], *args, **kwargs) -> List[Any]
```
**Parameters:**
* `tasks` (List\[str]): List of tasks or questions to be processed
* `*args` (Any): Variable length argument list passed to each task execution
* `**kwargs` (Any): Arbitrary keyword arguments passed to each task execution
**Returns:** List of consensus results in **input order**, so element *i* is the vote for `tasks[i]`
Results are read in submission order, so element *i* is always the vote for `tasks[i]`.
### reliability\_check()
Performs validation checks on the majority voting system configuration.
```python theme={null}
def reliability_check(self) -> None
```
**Raises:**
* `ValueError`: If agents list is empty or None
* `ValueError`: If `max_loops` is less than or equal to `0`
## Consensus Agent
The MajorityVoting system automatically creates a specialized consensus agent that analyzes and synthesizes responses from all participating agents. This consensus agent:
1. **Comprehensively evaluates** each agent's response across accuracy, depth of analysis, relevance, clarity, and unique perspectives
2. **Performs comparative analysis** by identifying overlapping themes, divergent viewpoints, and strengths/weaknesses
3. **Builds consensus** by identifying the most effective responses and synthesizing best elements
4. **Delivers actionable results** that are fair, balanced, evidence-based, and well-supported
The consensus agent can be customized through the constructor parameters:
* `consensus_agent_prompt`: Custom system prompt
* `consensus_agent_name`: Name for the agent
* `consensus_agent_description`: Description
* `consensus_agent_model_name`: Model to use
* `additional_consensus_agent_kwargs`: Additional configuration
## Usage Examples
### Financial Analysis with Specialized Agents
```python theme={null}
from swarms import Agent, MajorityVoting
# Technical Analysis Agent
TECHNICAL_ANALYSIS_PROMPT = """
You are a Quantitative Technical Analysis Specialist with deep expertise in
market chart patterns, technical indicators, and algorithmic trading signals.
Focus on price action, volume analysis, and statistical patterns.
Provide specific price levels, timeframes, and probability assessments.
Include risk management parameters (stop losses, take profits, position sizing).
"""
# Fundamental Analysis Agent
FUNDAMENTAL_ANALYSIS_PROMPT = """
You are a Quantitative Fundamental Analysis Specialist with expertise in
financial statement analysis, valuation models, and company performance metrics.
Focus on intrinsic value, financial health, and long-term investment potential.
Calculate and interpret key financial ratios and metrics.
"""
# Risk Management Agent
RISK_MANAGEMENT_PROMPT = """
You are a Quantitative Risk Management Specialist with expertise in portfolio
optimization, risk metrics, and hedging strategies. Focus on risk-adjusted
returns, diversification, and capital preservation.
Calculate comprehensive risk metrics and performance ratios.
"""
# Initialize specialized agents
technical_agent = Agent(
agent_name="Technical-Analysis-Quant",
system_prompt=TECHNICAL_ANALYSIS_PROMPT,
max_loops=1,
model_name="gpt-5.4",
)
fundamental_agent = Agent(
agent_name="Fundamental-Analysis-Quant",
system_prompt=FUNDAMENTAL_ANALYSIS_PROMPT,
max_loops=1,
model_name="gpt-5.4",
)
risk_agent = Agent(
agent_name="Risk-Management-Quant",
system_prompt=RISK_MANAGEMENT_PROMPT,
max_loops=1,
model_name="gpt-5.4",
)
# Create the majority voting swarm
swarm = MajorityVoting(
name="Quant-Analysis-Swarm",
description="Analysis of current market conditions with investment recommendations.",
agents=[technical_agent, fundamental_agent, risk_agent],
)
# Run the analysis
result = swarm.run(
"Analyze the current market conditions and provide investment recommendations "
"for a $40k portfolio. Focus on AI and technology sectors with emphasis on "
"risk management and diversification."
)
print("Quant Analysis Results:")
print(result)
```
### Investment Analysis with Consensus Agent
```python theme={null}
from swarms import Agent, MajorityVoting
# Initialize multiple specialized agents
agents = [
Agent(
agent_name="Market-Analysis-Agent",
agent_description="Market trend analyst",
system_prompt="You are a market analyst specializing in identifying growth opportunities and market trends.",
max_loops=1,
model_name="gpt-5.4"
),
Agent(
agent_name="Risk-Assessment-Agent",
agent_description="Risk analysis expert",
system_prompt="You are a risk assessment expert focused on evaluating investment risks and volatility.",
max_loops=1,
model_name="gpt-5.4"
),
Agent(
agent_name="Portfolio-Strategy-Agent",
agent_description="Portfolio optimization specialist",
system_prompt="You are a portfolio strategist focused on diversification and long-term growth strategies.",
max_loops=1,
model_name="gpt-5.4"
)
]
# Create majority voting system (consensus agent is automatically created)
investment_system = MajorityVoting(
name="Investment-Analysis-System",
description="Multi-agent investment analysis with consensus evaluation",
agents=agents,
verbose=True,
output_type="dict"
)
# Execute investment analysis
result = investment_system.run(
task="""Analyze the following investment scenario and provide recommendations:
- Budget: $50,000
- Risk tolerance: Moderate
- Time horizon: 5-7 years
- Focus areas: Technology, Healthcare, Renewable Energy
Provide specific ETF/index fund recommendations with allocation percentages."""
)
print("Investment Analysis Results:")
print(result)
```
### Content Creation with Batch Processing
```python theme={null}
from swarms import Agent, MajorityVoting
# Initialize content creation agents with different styles
content_agents = [
Agent(
agent_name="Creative-Writer",
system_prompt="You are a creative writer who produces engaging, story-driven content with vivid descriptions.",
max_loops=1,
model_name="gpt-5.4"
),
Agent(
agent_name="Technical-Writer",
system_prompt="You are a technical writer who focuses on clarity, accuracy, and structured information.",
max_loops=1,
model_name="gpt-5.4"
),
Agent(
agent_name="SEO-Optimized-Writer",
system_prompt="You are an SEO specialist who creates content optimized for search engines while maintaining quality.",
max_loops=1,
model_name="gpt-5.4"
),
Agent(
agent_name="Conversational-Writer",
system_prompt="You are a conversational writer who creates relatable, engaging content that connects with readers.",
max_loops=1,
model_name="gpt-5.4"
)
]
# Create majority voting system
content_system = MajorityVoting(
name="Content-Creation-System",
description="Multi-style content creation with majority voting",
agents=content_agents,
verbose=True,
output_type="str"
)
# Define multiple content tasks
content_tasks = [
"Write a blog post about the benefits of renewable energy adoption",
"Create social media content for a new fitness app launch",
"Develop a product description for eco-friendly water bottles",
"Write an email newsletter about artificial intelligence trends"
]
# Execute batch processing
batch_results = content_system.batch_run(content_tasks)
print("Batch Content Creation Results:")
for i, result in enumerate(batch_results, 1):
print(f"\nTask {i} Result:")
print(result[:500] + "..." if len(str(result)) > 500 else result)
```
### Research Analysis with Concurrent Processing
```python theme={null}
from swarms import Agent, MajorityVoting
# Initialize research agents with different methodologies
research_agents = [
Agent(
agent_name="Quantitative-Researcher",
system_prompt="You are a quantitative researcher who analyzes data, statistics, and numerical evidence.",
max_loops=1,
model_name="gpt-5.4"
),
Agent(
agent_name="Qualitative-Researcher",
system_prompt="You are a qualitative researcher who focuses on patterns, themes, and contextual understanding.",
max_loops=1,
model_name="gpt-5.4"
),
Agent(
agent_name="Literature-Review-Specialist",
system_prompt="You are a literature review specialist who synthesizes existing research and identifies knowledge gaps.",
max_loops=1,
model_name="gpt-5.4"
),
Agent(
agent_name="Methodology-Expert",
system_prompt="You are a methodology expert who evaluates research design, validity, and reliability.",
max_loops=1,
model_name="gpt-5.4"
),
Agent(
agent_name="Ethics-Reviewer",
system_prompt="You are an ethics reviewer who ensures research practices are responsible and unbiased.",
max_loops=1,
model_name="gpt-5.4"
)
]
# Create majority voting system for research
research_system = MajorityVoting(
name="Research-Analysis-System",
description="Concurrent multi-perspective research analysis",
agents=research_agents,
verbose=True,
output_type="list"
)
# Define research questions for concurrent analysis
research_questions = [
"What are the environmental impacts of electric vehicle adoption?",
"How does remote work affect employee productivity and well-being?",
"What are the economic implications of universal basic income?",
"How can AI be used to improve healthcare outcomes?",
"What are the social effects of social media on mental health?"
]
# Execute concurrent research analysis
concurrent_results = research_system.run_concurrently(research_questions)
print("Concurrent Research Analysis Results:")
print(f"Total questions analyzed: {len(concurrent_results)}")
for i, result in enumerate(concurrent_results, 1):
print(f"\nResearch Question {i}:")
print(f"Result: {str(result)[:300]}...")
```
### Majority Voting with Custom Streaming
```python theme={null}
from swarms import Agent
from swarms.prompts.finance_agent_sys_prompt import (
FINANCIAL_AGENT_SYS_PROMPT,
)
from swarms.structs.majority_voting import MajorityVoting
def streaming_callback(agent_name: str, chunk: str, is_final: bool):
if not hasattr(streaming_callback, "_buffer"):
streaming_callback._buffer = ""
streaming_callback._buffer_size = 0
min_chunk_size = 512
if chunk:
streaming_callback._buffer += chunk
streaming_callback._buffer_size += len(chunk)
if streaming_callback._buffer_size >= min_chunk_size or is_final:
if streaming_callback._buffer:
print(streaming_callback._buffer, end="", flush=True)
streaming_callback._buffer = ""
streaming_callback._buffer_size = 0
if is_final:
print()
# Initialize the agent
agent = Agent(
agent_name="Financial-Analysis-Agent",
agent_description="Personal finance advisor agent",
system_prompt=FINANCIAL_AGENT_SYS_PROMPT,
max_loops=1,
model_name="gpt-5.4",
dynamic_temperature_enabled=True,
max_tokens=4000,
streaming_on=True,
)
swarm = MajorityVoting(agents=[agent, agent, agent])
swarm.run(
"Create a table of super high growth opportunities for AI. "
"I have $40k to invest in ETFs, index funds, and more. "
"Please create a table in markdown.",
streaming_callback=streaming_callback,
)
```
## Usage Patterns
### Single Task Analysis
```python theme={null}
# Simple single task execution
result = swarm.run("What are the key risks in the current market?")
# With custom parameters
result = swarm.run(
"Analyze this investment opportunity",
temperature=0.7,
max_tokens=1000
)
```
### Batch Processing
```python theme={null}
# Process multiple sectors
sectors = ["Technology", "Healthcare", "Energy", "Finance"]
tasks = [f"Analyze {sector} sector opportunities" for sector in sectors]
results = swarm.batch_run(tasks)
```
### Concurrent Processing
```python theme={null}
# Process multiple research questions concurrently
questions = [
"What are the environmental impacts of AI?",
"How will quantum computing affect cryptography?",
"What are the economic implications of space exploration?"
]
results = swarm.run_concurrently(questions)
```
## Performance Considerations
| Consideration | Description |
| ------------------------------------------ | ------------------------------------------------------------------- |
| Sequential Processing (`batch_run`) | Tasks are processed one after another, not in parallel |
| Concurrent Processing (`run_concurrently`) | Tasks run simultaneously using all available CPU cores |
| Independent Conversation History | Each task maintains its own conversation history |
| Memory Usage | Scales with the number of tasks and the length of each conversation |
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/majority_voting.py)
# MCPManager
Source: https://docs.swarms.world/api/mcp-manager
The single entry point for Model Context Protocol servers — discovery, auth, transport, and tool routing
## Overview
`MCPManager` is the one class handling [MCP](https://modelcontextprotocol.io) in Swarms. Point it at one or more servers and it takes care of transport selection, authentication, tool discovery, schema caching, and routing each tool call to the server that owns it.
An `Agent` builds one as `agent.mcp_manager` whenever you set `mcp_url` or `mcp_urls`. You can also use it directly, with no agent involved.
```python theme={null}
from swarms.tools.mcp_manager import MCPManager
manager = MCPManager(mcp_url="http://localhost:8000/mcp")
manager.list_tool_names() # what's available
manager.get_tools() # OpenAI schemas for an LLM
manager.call_tool("get_crypto_price", {"coin_id": "btc"}) # call one directly
manager.execute_tool_calls(llm_response) # run what a model asked for
```
`swarms.tools.mcp_client_tools` and its standalone functions have been **removed**. See [Migration](#migration) for direct replacements.
## Import
```python theme={null}
from swarms.tools.mcp_manager import MCPManager
```
## Constructor
A single server — URL string, connection object, or dict.
Several servers. Entries may mix forms, so different servers can use different authentication.
Full configuration for one server.
Full configuration for several servers.
API key applied to every server that does not define its own.
Bearer token applied to every server that does not define its own.
OAuth 2.1 configuration.
Extra headers merged into every request.
Force `streamable_http`, `sse`, or `stdio`. Auto-detected otherwise; hyphenated forms like `streamable-http` are normalized.
Request timeout in seconds, applied to every configured connection. Left unset by default — a `None` value falls through to `MCPConnection.timeout`'s own default of `30` seconds.
Name used in log messages.
Verbose logging.
Retries per operation before raising.
## Discovery
### get\_tools
```python theme={null}
def get_tools(format="openai", force_refresh=False) -> List[Dict[str, Any]]
```
Fetch tools from every configured server. Returns OpenAI function-calling schemas by default, ready to hand to an LLM. Results are cached; pass `force_refresh=True` to re-fetch.
```python theme={null}
tools = manager.get_tools() # OpenAI schemas
raw = manager.get_tools(format="mcp") # raw MCP schemas
fresh = manager.get_tools(force_refresh=True) # bypass cache
```
Async form: `await manager.aget_tools(...)`.
`aget_tools` only populates `self._tools_cache` / `self._tool_routes` when `format == "openai"`. On a multi-server manager, calling `get_tools(format="mcp")` alone leaves tool routing unpopulated, and a later `call_tool()` can fail with "No configured MCP server exposes a tool named …" until `get_tools()` (the default `"openai"` format) has been called at least once.
### list\_tool\_names
```python theme={null}
def list_tool_names() -> List[str]
```
Every tool name across all configured servers — the cheapest way to see what is available.
## Execution
### call\_tool
```python theme={null}
def call_tool(name: str, arguments: Optional[Dict[str, Any]] = None) -> Dict[str, Any]
```
Call one tool directly, no LLM involved. Returns a result envelope:
```python theme={null}
{
"tool": "get_crypto_price",
"server": "http://localhost:8000/mcp",
"arguments": {"coin_id": "bitcoin"},
"is_error": False,
"result": "Current price of Bitcoin: $64,601.00",
}
```
Async form: `await manager.acall_tool(...)`.
### execute\_tool\_calls
```python theme={null}
def execute_tool_calls(response, output_type="dict") -> Union[List[Dict], str]
```
Run the tool calls contained in an LLM response. Each call is routed to the server that advertised the tool, and results come back in call order. This is the step an `Agent` performs between LLM turns.
An LLM response, a single call dict, or a list of calls.
Result format.
Async form: `await manager.aexecute_tool_calls(...)`. To re-render results you already hold, use the static `MCPManager.format_results(results, output_type)`.
Under the default `output_type="dict"`, `result` is already a native Python value, not a JSON string — a `str` for text content, or a `dict` for structured content (`structuredContent` / `structured_content`, or a text+content mix). Use it directly:
```python theme={null}
payload = results[0]["result"]
```
Calling `json.loads()` on it will raise `TypeError` when `result` is a dict. JSON-string framing only applies when the whole envelope is serialized via `output_type="json"` (or `MCPManager.format_results(..., output_type="json")`).
## Configuration management
| Member | Description |
| -------------------- | ----------------------------------------------------------- |
| `enabled` | Property — `True` when at least one server is configured |
| `add_server(server)` | Register another server and invalidate the tool cache |
| `clear_cache()` | Drop cached tool schemas and routing information |
| `clear_auth_cache()` | Forget in-process OAuth providers and cached tokens |
| `to_dict()` | Serializable, **secret-redacted** view of the configuration |
## Authentication
```python theme={null}
from swarms.schemas.mcp_schemas import MCPConnection, MCPOAuthConfig
# API key
MCPManager(mcp_url="https://api.example.com/mcp", api_key="sk-...")
# Bearer token
MCPManager(mcp_url="https://api.example.com/mcp", authorization_token="ey...")
# Headers, transport, timeouts
MCPManager(mcp_config=MCPConnection(
url="https://api.example.com/mcp",
headers={"X-Tenant": "acme"},
transport="streamable_http",
timeout=20,
))
# Secrets resolved from the environment at connection time
MCPConnection(url="https://api.example.com/mcp", api_key="env:EXAMPLE_MCP_KEY")
# OAuth 2.1 client credentials
MCPConnection(url="https://api.example.com/mcp", oauth=MCPOAuthConfig(
grant_type="client_credentials",
client_id="example-client",
client_secret="env:EXAMPLE_CLIENT_SECRET",
token_url="https://api.example.com/oauth/token",
))
```
Both `env:NAME` and `${NAME}` indirection are resolved when the connection is made, so secrets stay out of source.
### Mixed auth across servers
```python theme={null}
MCPManager(mcp_urls=[
"http://localhost:8000/mcp", # local, no auth
MCPConnection(url="https://api.example.com/mcp", api_key="sk-..."),
])
```
## Errors
| Exception | Raised when |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `AgentMCPConnectionError` | The server is unreachable, or authentication fails |
| `AgentMCPToolError` | Raised at call time only when no configured server exposes the requested tool name (a routing failure) — not when the tool itself fails |
| `AgentMCPError` | Base class for both |
An execution or session failure on the server side is never raised — it's captured and returned as an `is_error: True` result envelope (from `call_tool`/`execute_tool_calls` and their async forms) so a batch of calls can't be aborted by one failing tool.
All live in `swarms.schemas.agent_mcp_errors`. Operations retry with backoff up to `retry_attempts` before raising.
## Migration
The standalone functions in `swarms.tools.mcp_client_tools` were removed once everything moved onto this class.
| Removed function | Replacement |
| --------------------------------------------------------------------- | --------------------------------------------------------------- |
| `aget_mcp_tools(server_path=URL)` | `await MCPManager(mcp_url=URL).aget_tools()` |
| `get_mcp_tools_sync(server_path=URL)` | `MCPManager(mcp_url=URL).get_tools()` |
| `get_tools_for_multiple_mcp_servers(urls=URLS)` | `MCPManager(mcp_urls=URLS).get_tools()` |
| `execute_tool_call_simple(response=R, server_path=URL)` | `await MCPManager(mcp_url=URL).aexecute_tool_calls(R)` |
| `execute_multiple_tools_on_multiple_mcp_servers(...)` | `await MCPManager(mcp_urls=URLS).aexecute_tool_calls(R)` |
| `MCPError`, `MCPConnectionError`, `MCPToolError`, `MCPExecutionError` | `AgentMCPError`, `AgentMCPConnectionError`, `AgentMCPToolError` |
Two behavioral differences to be aware of:
1. **`output_type` on tool fetching is gone.** `get_tools_for_multiple_mcp_servers` accepted the argument but never applied it. Use `format="openai" | "mcp"` to pick the schema shape.
2. **Execution results are wrapped.** The old functions returned the raw MCP `CallToolResult` dump. `execute_tool_calls` returns one envelope per call, so results from several servers stay attributable. Read `result["result"]` for the tool's own payload.
## Related
Using MCP servers from an agent
Set `mcp_url` / `mcp_urls` to wire this in automatically
# MixtureOfAgents
Source: https://docs.swarms.world/api/mixture-of-agents
A multi-agent system that runs agents in parallel layers and aggregates their responses
## Overview
The `MixtureOfAgents` class manages and executes multiple agents in parallel layers, aggregating their responses through a specialized aggregator agent. This architecture enables sophisticated multi-perspective analysis by running agents concurrently and synthesizing their outputs.
## Class Definition
```python theme={null}
from swarms import MixtureOfAgents
```
## Parameters
Unique identifier for the mixture of agents instance. Auto-generated via `generate_id("mixture-of-agents")` if not provided, producing `mixture-of-agents-<32 hex chars>`.
The name of the mixture of agents
A description of the mixture of agents purpose and functionality
A list of reference agents to be used in the mixture. These agents will be executed in parallel layers
The aggregator agent to be used for synthesizing responses from all agents. If None, a default aggregator agent will be created
The system prompt for the aggregator agent that guides how responses are synthesized
The number of processing layers to execute. Each layer runs all agents and passes context forward
Maximum number of execution loops for the aggregator agent
Output format type. Options: "final", "all", "list", etc.
The model name for the aggregator agent
Cap on concurrent worker agents per layer. Defaults to the executor's own
behaviour when omitted.
Extra keyword arguments forwarded to the aggregator `Agent` when one is built
for you.
The parameter is spelled `aggegrator_args` in the code — the letters are
transposed. That misspelling is the name you must type; `aggregator_args`
raises `TypeError`.
## Methods
### `reliability_check()`
```python theme={null}
def reliability_check(self) -> None
```
Performs a reliability check on the Mixture of Agents class configuration.
**Raises:**
* `ValueError`: If no agents are provided
* `ValueError`: If no aggregator system prompt is provided
* `ValueError`: If no layers are specified
***
### `step()`
```python theme={null}
def step(
self,
task: str,
img: Optional[str] = None,
) -> Dict[str, str]
```
Executes a single step by running all agents concurrently with the given task.
**Parameters:**
The task to be executed by all agents
Optional image input for the task
**Returns:**
Dictionary mapping agent names to their output responses
***
### `run()`
```python theme={null}
def run(
self,
task: str,
img: Optional[str] = None,
) -> str
```
Executes the complete mixture of agents workflow with multiple layers and aggregation.
**Parameters:**
The task to be executed by the mixture of agents
Optional image input for the task
**Returns:**
The aggregated response from all agents after processing through all layers
`run()` catches exceptions internally and returns the string `"Error: {e}"` instead of raising, so callers should check the returned value rather than wrapping the call in a try/except.
**Workflow:**
1. Adds initial task to conversation history
2. For each layer:
* Runs all agents concurrently. Layer 0 receives the task; later layers receive the task plus the previous layer's synthesis, not the full transcript
* Adds each agent's output to conversation
* Updates context with latest conversation history
3. Runs aggregator agent on complete conversation
4. Returns formatted output based on output\_type
***
### `run_batched()`
```python theme={null}
def run_batched(self, tasks: List[str]) -> List[str]
```
Runs the mixture of agents for a batch of tasks sequentially.
**Parameters:**
A list of tasks to be executed by the mixture of agents
**Returns:**
A list of aggregated responses from the mixture of agents, one for each task
***
### `run_concurrently()`
```python theme={null}
def run_concurrently(self, tasks: List[str]) -> List[str]
```
Runs the mixture of agents for a batch of tasks concurrently using ThreadPoolExecutor.
**Parameters:**
A list of tasks to be executed concurrently
**Returns:**
A list of aggregated responses from the mixture of agents
## Usage Example
```python theme={null}
from swarms import Agent, MixtureOfAgents
# Create specialized agents
research_agent = Agent(
agent_name="Research-Agent",
system_prompt="You are a research expert...",
model_name="claude-sonnet-4-6"
)
analysis_agent = Agent(
agent_name="Analysis-Agent",
system_prompt="You are an analysis expert...",
model_name="claude-sonnet-4-6"
)
writing_agent = Agent(
agent_name="Writing-Agent",
system_prompt="You are a writing expert...",
model_name="claude-sonnet-4-6"
)
# Create mixture of agents
mixture = MixtureOfAgents(
name="Research-Analysis-Writing-Team",
description="A team that researches, analyzes, and writes reports",
agents=[research_agent, analysis_agent, writing_agent],
layers=3,
output_type="final"
)
# Run a task
result = mixture.run(
task="Analyze the impact of AI on healthcare and write a comprehensive report"
)
print(result)
```
## Architecture
The MixtureOfAgents architecture works as follows:
1. **Layer Processing**: Each layer runs all agents concurrently with the full conversation context
2. **Context Accumulation**: Agent outputs are added to the conversation history after each layer
3. **Iterative Refinement**: Subsequent layers build upon previous outputs, enabling deeper analysis
4. **Final Aggregation**: An aggregator agent synthesizes all responses into a coherent final output
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/mixture_of_agents.py)
# ModelRouter
Source: https://docs.swarms.world/api/model-router
Intelligent routing system that automatically selects and executes AI models based on task requirements
## Overview
The `ModelRouter` is an intelligent routing system that automatically selects and executes AI models based on task requirements. It leverages a function-calling architecture to analyze tasks and recommend the optimal model and provider combination for each specific use case.
## Key Features
* Dynamic model selection based on task complexity and requirements
* Multi-provider support (OpenAI, Anthropic, Google, etc.)
* Concurrent and asynchronous execution capabilities
* Batch processing with memory
* Automatic error handling and retries
* Provider-aware routing
* Cost optimization
## Installation
1. Install the latest version of swarms:
```bash theme={null}
pip install -U swarms
```
2. Set up your API keys in your `.env` file:
```bash theme={null}
OPENAI_API_KEY=your_openai_api_key
ANTHROPIC_API_KEY=your_anthropic_api_key
GOOGLE_API_KEY=your_google_api_key
# Add more API keys as needed following litellm format
```
## Attributes
Custom prompt for guiding model selection behavior.
Maximum token limit for model outputs.
Control parameter for response randomness (0.0-1.0).
Maximum concurrent workers. Use `"auto"` for CPU count.
API key for model access.
Maximum number of refinement iterations.
## Methods
### step()
Runs a single routing step: selects a model/provider for the task, executes it, and returns the output. `run()` calls this internally in a loop up to `max_loops` times.
```python theme={null}
def step(self, task: str) -> str
```
**Parameters:**
* `task` (str): The task to be executed
**Returns:** `str` - The result of the single routing step
### run()
Executes a single task through the model router with memory and refinement capabilities.
```python theme={null}
def run(self, task: str) -> str
```
**Parameters:**
* `task` (str): The task to be executed
**Returns:** `str` - The result of task execution
### batch\_run()
Executes multiple tasks sequentially with result aggregation.
```python theme={null}
def batch_run(self, tasks: list) -> list
```
**Parameters:**
* `tasks` (list): List of task strings to be executed
**Returns:** `list` - List of results, one for each task
### concurrent\_run()
Parallel execution of multiple tasks using thread pooling.
```python theme={null}
def concurrent_run(self, tasks: list) -> list
```
**Parameters:**
* `tasks` (list): List of task strings to be executed
**Returns:** `list` - List of results from parallel execution
### async\_run()
`async_run()` is currently broken and should not be used. Its implementation is `return asyncio.create_task(self.run(task, *args, **kwargs))`, but `run()` is a plain **sync** `def` -- so `self.run(...)` executes eagerly (blocking the event loop) and returns a plain `str` before `asyncio.create_task()` ever sees it. Passing that string to `create_task()` raises `TypeError: a coroutine was expected`, which `async_run()` catches and re-raises as `RuntimeError: Async execution failed: ...`. Every `await router.async_run(...)` call site fails. Use the synchronous `run()` (optionally wrapped in `asyncio.to_thread()` from an async context) or `concurrent_run()` / `batch_run()` for parallel execution instead.
Documented (broken) signature:
```python theme={null}
async def async_run(self, task: str) -> asyncio.Task
```
**Working alternative from an async context:**
```python theme={null}
import asyncio
from swarms import ModelRouter
router = ModelRouter()
async def run_task(task: str):
# Offloads the blocking, synchronous run() call to a thread
# so it doesn't block the event loop.
return await asyncio.to_thread(router.run, task)
result = asyncio.run(run_task("Analyze the sentiment in this feedback"))
```
## Usage Examples
### Basic Usage
```python theme={null}
from swarms import ModelRouter
router = ModelRouter()
# Simple text analysis
result = router.run("Analyze the sentiment and key themes in this customer feedback")
# Complex reasoning task
complex_result = router.run("""
Evaluate the following business proposal:
- Initial investment: $500,000
- Projected ROI: 25% annually
- Market size: $2B
- Competition: 3 major players
Provide detailed analysis and recommendations.
""")
```
### Batch Processing
```python theme={null}
from swarms import ModelRouter
router = ModelRouter()
# Multiple analysis tasks
tasks = [
"Analyze Q1 financial performance",
"Predict Q2 market trends",
"Evaluate competitor strategies",
"Generate growth recommendations"
]
results = router.batch_run(tasks)
# Process results
for task, result in zip(tasks, results):
print(f"Task: {task}\nResult: {result}\n")
```
### Concurrent Execution
```python theme={null}
from swarms import ModelRouter
router = ModelRouter()
# Define multiple concurrent tasks
analysis_tasks = [
"Perform technical analysis of AAPL stock",
"Analyze market sentiment from social media",
"Generate trading signals",
"Calculate risk metrics"
]
# Execute tasks concurrently
results = router.concurrent_run(analysis_tasks)
# Process results with error handling
for task, result in zip(analysis_tasks, results):
try:
processed_result = process_analysis(result)
save_to_database(processed_result)
except Exception as e:
log_error(f"Error processing {task}: {str(e)}")
```
### Asynchronous Execution
`async_run()` is currently broken (see the [Warning above](#async-run)). To call `ModelRouter` from an async context without blocking the event loop, offload the synchronous `run()` to a thread with `asyncio.to_thread()`:
```python theme={null}
import asyncio
from swarms import ModelRouter
async def process_data_stream():
router = ModelRouter()
tasks = []
async for data in data_stream:
tasks.append(asyncio.to_thread(router.run, f"Process data: {data}"))
results = await asyncio.gather(*tasks)
return results
# Usage in async context
async def main():
results = await process_data_stream()
```
### Financial Analysis System
```python theme={null}
from swarms import ModelRouter
from typing import Dict, List
import pandas as pd
class FinancialAnalysisSystem:
def __init__(self):
self.router = ModelRouter(
temperature=0.3, # Lower temperature for more deterministic outputs
max_tokens=8000, # Higher token limit for detailed analysis
max_loops=2 # Allow for refinement iteration
)
def analyze_company_financials(self, financial_data: Dict) -> Dict:
analysis_task = f"""
Perform comprehensive financial analysis:
Financial Metrics:
- Revenue: ${financial_data['revenue']}M
- EBITDA: ${financial_data['ebitda']}M
- Debt/Equity: {financial_data['debt_equity']}
- Working Capital: ${financial_data['working_capital']}M
Required Analysis:
1. Profitability assessment
2. Liquidity analysis
3. Growth projections
4. Risk evaluation
5. Investment recommendations
Provide detailed insights and actionable recommendations.
"""
result = self.router.run(analysis_task)
return self._parse_analysis_result(result)
def _parse_analysis_result(self, result: str) -> Dict:
# Implementation of result parsing
pass
# Usage
analyzer = FinancialAnalysisSystem()
company_data = {
'revenue': 150,
'ebitda': 45,
'debt_equity': 0.8,
'working_capital': 25
}
analysis = analyzer.analyze_company_financials(company_data)
```
### Healthcare Data Processing Pipeline
```python theme={null}
import asyncio
from swarms import ModelRouter
from typing import List, Dict
class MedicalDataProcessor:
def __init__(self):
self.router = ModelRouter(
max_workers="auto", # Automatic worker scaling
temperature=0.2, # Conservative temperature for medical analysis
system_prompt="""You are a specialized medical data analyzer focused on:
1. Clinical terminology interpretation
2. Patient data analysis
3. Treatment recommendation review
4. Medical research synthesis"""
)
async def process_patient_records(self, records: List[Dict]) -> List[Dict]:
analysis_tasks = []
for record in records:
task = f"""
Analyze patient record:
- Age: {record['age']}
- Symptoms: {', '.join(record['symptoms'])}
- Vital Signs: {record['vitals']}
- Medications: {', '.join(record['medications'])}
- Lab Results: {record['lab_results']}
Provide:
1. Symptom analysis
2. Medication interaction check
3. Lab results interpretation
4. Treatment recommendations
"""
analysis_tasks.append(task)
# async_run() is currently broken -- offload the synchronous
# run() to a thread instead (see the Warning under async_run()).
results = await asyncio.gather(*[
asyncio.to_thread(self.router.run, task) for task in analysis_tasks
])
return [self._parse_medical_analysis(r) for r in results]
def _parse_medical_analysis(self, analysis: str) -> Dict:
# Implementation of medical analysis parsing
pass
# Usage
async def main():
processor = MedicalDataProcessor()
patient_records = [
{
'age': 45,
'symptoms': ['fever', 'cough', 'fatigue'],
'vitals': {'bp': '120/80', 'temp': '38.5C'},
'medications': ['lisinopril', 'metformin'],
'lab_results': 'WBC: 11,000, CRP: 2.5'
}
# More records...
]
analyses = await processor.process_patient_records(patient_records)
```
### NLP Processing Pipeline
```python theme={null}
from swarms import ModelRouter
from typing import List, Dict
class NLPPipeline:
def __init__(self):
self.router = ModelRouter(
temperature=0.4,
max_loops=2
)
def process_documents(self, documents: List[str]) -> List[Dict]:
tasks = [self._create_nlp_task(doc) for doc in documents]
results = self.router.concurrent_run(tasks)
return [self._parse_nlp_result(r) for r in results]
def _create_nlp_task(self, document: str) -> str:
return f"""
Perform comprehensive NLP analysis:
Text: {document}
Required Analysis:
1. Entity recognition
2. Sentiment analysis
3. Topic classification
4. Key phrase extraction
5. Intent detection
Provide structured analysis with confidence scores.
"""
def _parse_nlp_result(self, result: str) -> Dict:
# Implementation of NLP result parsing
pass
# Usage
pipeline = NLPPipeline()
documents = [
"We're extremely satisfied with the new product features!",
"The customer service response time needs improvement.",
"Looking to upgrade our subscription plan next month."
]
analyses = pipeline.process_documents(documents)
```
## Available Models and Use Cases
| Model | Provider | Optimal Use Cases | Characteristics |
| ----------------- | --------- | ------------------------------------------------------------- | --------------------------------------- |
| gpt-4-turbo | OpenAI | Complex reasoning, Code generation, Creative writing | High accuracy, Latest knowledge cutoff |
| claude-3-opus | Anthropic | Research analysis, Technical documentation, Long-form content | Strong reasoning, Detailed outputs |
| gemini-pro | Google | Multimodal tasks, Code generation, Technical analysis | Fast inference, Strong coding abilities |
| mistral-large | Mistral | General tasks, Content generation, Classification | Open source, Good price/performance |
| deepseek-reasoner | DeepSeek | Mathematical analysis, Logic problems, Scientific computing | Specialized reasoning capabilities |
## Provider Capabilities
| Provider | Strengths | Best For | Integration Notes |
| --------- | ---------------------------------------- | --------------------------------- | ------------------------------- |
| OpenAI | Consistent performance, Strong reasoning | Production systems, Complex tasks | Requires API key setup |
| Anthropic | Safety features, Detailed analysis | Research, Technical writing | Claude-specific formatting |
| Google | Technical tasks, Multimodal support | Code generation, Analysis | Vertex AI integration available |
| Groq | High-speed inference | Real-time applications | Optimized for specific models |
| DeepSeek | Specialized reasoning | Scientific computing | Custom API integration |
| Mistral | Open source flexibility | General applications | Self-hosted options available |
## Performance Optimization Tips
1. **Token Management**
* Set appropriate `max_tokens` based on task complexity
* Monitor token usage for cost optimization
* Use streaming for long outputs
2. **Concurrency Settings**
* Adjust `max_workers` based on system resources
* Use `"auto"` workers for optimal CPU utilization
* Monitor memory usage with large batch sizes
3. **Temperature Tuning**
* Lower (0.1-0.3) for factual/analytical tasks
* Higher (0.7-0.9) for creative tasks
* Mid-range (0.4-0.6) for balanced outputs
4. **System Prompts**
* Customize for specific domains
* Include relevant context
* Define clear output formats
## Dependencies
* `asyncio`: Asynchronous I/O support
* `concurrent.futures`: Thread pool execution
* `pydantic`: Data validation
* `litellm`: LLM interface standardization
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/model_router.py)
# Multi-Agent Execution Utilities
Source: https://docs.swarms.world/api/multi-agent-execution-utilities
Utility functions for running multiple agents using various execution strategies including synchronous, asynchronous, concurrent, and batch processing
## Overview
The `multi_agent_exec` module provides a comprehensive set of utility functions for running multiple agents using various execution strategies. It includes synchronous and asynchronous execution methods, concurrent batch processing, and utility functions for information retrieval.
## Installation
```bash theme={null}
pip install -U swarms
```
## Function Overview
| Function | Category | Description |
| -------------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------- |
| `run_single_agent` | Single Agent | Runs a single agent synchronously |
| `run_agent_async` | Single Agent | Runs a single agent asynchronously using asyncio |
| `run_agents_concurrently_async` | Concurrent | Runs multiple agents concurrently using asyncio |
| `run_agents_concurrently` | Concurrent | Optimized concurrent runner with image support and flexible output formats |
| `run_agents_concurrently_multiprocess` | Concurrent | Manages agents concurrently in batches with optimized performance |
| `batched_grid_agent_execution` | Batched & Grid | Runs multiple agents with different tasks concurrently |
| `batch_agent_execution` | Batched & Grid | Runs a 1:1 list of agents against a parallel list of tasks (from `swarms.structs.batch_agent_execution`) |
| `run_agents_with_different_tasks` | Batched & Grid | Runs agents with different tasks concurrently in batches |
| `get_swarms_info` | Utility | Fetches and formats information about available swarms |
| `get_agents_info` | Utility | Fetches and formats information about available agents |
## Single Agent Functions
### run\_single\_agent()
Runs a single agent synchronously.
```python theme={null}
def run_single_agent(agent: AgentType, task: str, *args, **kwargs) -> Any
```
**Parameters:**
* `agent` (AgentType): Agent instance to run
* `task` (str): Task string to execute
* `*args` (Any): Additional positional arguments
* `**kwargs` (Any): Additional keyword arguments
**Returns:** Agent execution result
```python theme={null}
from swarms import Agent
from swarms.structs.multi_agent_exec import run_single_agent
agent = Agent(
agent_name="Financial-Analyst",
system_prompt="You are a financial analysis expert",
model_name="claude-sonnet-4-6",
max_loops=1
)
result = run_single_agent(agent, "Analyze the current stock market trends")
print(result)
```
### run\_agent\_async()
Runs a single agent asynchronously using asyncio.
```python theme={null}
async def run_agent_async(agent: AgentType, task: str) -> Any
```
**Parameters:**
* `agent` (AgentType): Agent instance to run
* `task` (str): Task string to execute
**Returns:** Agent execution result
```python theme={null}
import asyncio
from swarms import Agent
from swarms.structs.multi_agent_exec import run_agent_async
async def main():
agent = Agent(
agent_name="Researcher",
system_prompt="You are a research assistant",
model_name="claude-sonnet-4-6",
max_loops=1
)
result = await run_agent_async(agent, "Research AI advancements in 2024")
print(result)
asyncio.run(main())
```
## Concurrent Execution Functions
### run\_agents\_concurrently\_async()
Runs multiple agents concurrently using asyncio.
```python theme={null}
async def run_agents_concurrently_async(
agents: List[AgentType],
task: str
) -> List[Any]
```
**Parameters:**
* `agents` (List\[AgentType]): List of Agent instances to run concurrently
* `task` (str): Task string to execute by all agents
**Returns:** List of outputs from each agent
```python theme={null}
import asyncio
from swarms import Agent
from swarms.structs.multi_agent_exec import run_agents_concurrently_async
async def main():
agents = [
Agent(
agent_name=f"Analyst-{i}",
system_prompt="You are a market analyst",
model_name="claude-sonnet-4-6",
max_loops=1
)
for i in range(3)
]
task = "Analyze the impact of AI on job markets"
results = await run_agents_concurrently_async(agents, task)
for i, result in enumerate(results):
print(f"Agent {i+1} result: {result}")
asyncio.run(main())
```
### run\_agents\_concurrently()
Optimized concurrent agent runner using ThreadPoolExecutor with image support and flexible output formats.
```python theme={null}
def run_agents_concurrently(
agents: List[AgentType],
task: str,
img: Optional[str] = None,
max_workers: Optional[int] = None,
return_agent_output_dict: bool = False,
) -> Union[List[Any], Dict[str, Any]]
```
**Parameters:**
* `agents` (List\[AgentType]): List of Agent instances to run concurrently
* `task` (str): Task string to execute
* `img` (Optional\[str]): Optional image data to pass to agent `run()` if supported
* `max_workers` (Optional\[int]): Maximum number of threads in the executor. Defaults to 95% of CPU cores
* `return_agent_output_dict` (bool): If True, returns a dict mapping agent names to outputs
**Returns:**
* If `return_agent_output_dict=False`: List of outputs from each agent in **input order**, so `results[i]` is `agents[i]`'s (exceptions included if agents fail)
* If `return_agent_output_dict=True`: Dictionary mapping agent names to outputs, preserving agent input order
```python theme={null}
from swarms import Agent
from swarms.structs.multi_agent_exec import run_agents_concurrently
# Create multiple agents
agents = [
Agent(
agent_name="Tech-Analyst",
system_prompt="You are a technology analyst",
model_name="claude-sonnet-4-6",
max_loops=1
),
Agent(
agent_name="Finance-Analyst",
system_prompt="You are a financial analyst",
model_name="claude-sonnet-4-6",
max_loops=1
),
Agent(
agent_name="Market-Strategist",
system_prompt="You are a market strategist",
model_name="claude-sonnet-4-6",
max_loops=1
)
]
task = "Analyze the future of electric vehicles in 2025"
# Basic concurrent execution
results = run_agents_concurrently(agents, task, max_workers=4)
for i, result in enumerate(results):
print(f"Agent {i+1} ({agents[i].agent_name}): {result}")
# Return results as dictionary with agent names as keys
results_dict = run_agents_concurrently(
agents, task, return_agent_output_dict=True
)
for agent_name, result in results_dict.items():
print(f"{agent_name}: {result}")
```
### run\_agents\_concurrently\_multiprocess()
Manages and runs multiple agents concurrently in batches with optimized performance.
```python theme={null}
def run_agents_concurrently_multiprocess(
agents: List[Agent],
task: str,
batch_size: int = os.cpu_count()
) -> List[Any]
```
**Parameters:**
* `agents` (List\[Agent]): List of Agent instances to run concurrently
* `task` (str): Task string to execute by all agents
* `batch_size` (int): Number of agents to run in parallel in each batch. Defaults to CPU count
**Returns:** List of outputs from each agent
```python theme={null}
import os
from swarms import Agent
from swarms.structs.multi_agent_exec import run_agents_concurrently_multiprocess
agents = [
Agent(
agent_name=f"Research-Agent-{i}",
system_prompt="You are a research specialist",
model_name="claude-sonnet-4-6",
max_loops=1
)
for i in range(5)
]
task = "Research the benefits of renewable energy"
batch_size = os.cpu_count()
results = run_agents_concurrently_multiprocess(agents, task, batch_size)
print(f"Completed {len(results)} agent executions")
```
## Batched and Grid Execution
### batched\_grid\_agent\_execution()
Runs multiple agents with different tasks concurrently using batched grid execution.
```python theme={null}
def batched_grid_agent_execution(
agents: List[AgentType],
tasks: List[str],
max_workers: int = None,
) -> List[Any]
```
**Parameters:**
* `agents` (List\[AgentType]): List of agent instances
* `tasks` (List\[str]): List of tasks, one for each agent
* `max_workers` (int): Maximum number of threads to use. Defaults to 90% of CPU cores
**Returns:** List of results from each agent
**Raises:** `ValueError` if the number of agents doesn't match the number of tasks
```python theme={null}
from swarms import Agent
from swarms.structs.multi_agent_exec import batched_grid_agent_execution
agents = [
Agent(
agent_name="Data-Scientist",
system_prompt="You are a data science expert",
model_name="claude-sonnet-4-6",
max_loops=1
),
Agent(
agent_name="ML-Engineer",
system_prompt="You are a machine learning engineer",
model_name="claude-sonnet-4-6",
max_loops=1
),
Agent(
agent_name="AI-Researcher",
system_prompt="You are an AI researcher",
model_name="claude-sonnet-4-6",
max_loops=1
)
]
tasks = [
"Analyze machine learning algorithms performance",
"Design a neural network architecture",
"Research latest AI breakthroughs"
]
results = batched_grid_agent_execution(agents, tasks, max_workers=3)
for i, result in enumerate(results):
print(f"Task {i+1}: {tasks[i]}")
print(f"Result: {result}\n")
```
### batch\_agent\_execution()
**Currently broken — every call raises.** `batch_agent_execution` builds its future map from `zip(agents, tasks, imgs)` while `imgs` defaults to `None`, so it fails with `TypeError: zip argument #3 must support iteration` before any agent runs. It also stores 3-tuples but unpacks only two values when collecting results.
Use [`run_agents_with_different_tasks`](#run-agents-with-different-tasks) for the same 1:1 agent-to-task pairing until this is fixed.
Runs a list of agents on a parallel list of tasks. Each `agents[i]` runs `tasks[i]` — unlike `batched_grid_agent_execution` (which runs every agent on every task), pairings are 1:1.
```python theme={null}
def batch_agent_execution(
agents: List[Union[Agent, Callable]],
tasks: List[str] = None,
imgs: List[str] = None,
max_workers: int = max(1, int(os.cpu_count() * 0.9)),
) -> List[Any]
```
**Parameters:**
* `agents` (List\[Agent | Callable]): Agents to run.
* `tasks` (List\[str]): One task per agent. Must have the same length as `agents`.
* `imgs` (List\[str]): One optional image input per agent. Must be the same length as `agents` when provided.
* `max_workers` (int): Thread pool size. Defaults to \~90% of CPU cores.
**Returns:** List of results in the order the input pairings were submitted; failed tasks yield `None` in that slot.
**Raises:** `BatchAgentExecutionError` wrapping any internal failure. Mismatched `len(agents)` vs `len(tasks)` is wrapped from the inner `ValueError`.
```python theme={null}
from swarms import Agent
from swarms.structs.batch_agent_execution import batch_agent_execution
agents = [
Agent(agent_name="Summarizer", model_name="claude-sonnet-4-6", max_loops=1),
Agent(agent_name="Translator", model_name="claude-sonnet-4-6", max_loops=1),
Agent(agent_name="Classifier", model_name="claude-sonnet-4-6", max_loops=1),
]
tasks = [
"Summarize the article at https://example.com/post.",
"Translate 'Bonjour le monde' to English.",
"Classify this review as positive, negative, or neutral: 'Loved it!'",
]
results = batch_agent_execution(agents=agents, tasks=tasks, imgs=[None, None, None])
for agent, result in zip(agents, results):
print(f"{agent.agent_name}: {result}")
```
Pair this with `run_agents_concurrently` (every agent runs the same task) and `batched_grid_agent_execution` (every agent runs every task) to cover the three common shapes of "run a bunch of agents".
### run\_agents\_with\_different\_tasks()
Runs multiple agents with different tasks concurrently, processing them in batches.
```python theme={null}
def run_agents_with_different_tasks(
agent_task_pairs: List[tuple[AgentType, str]],
batch_size: int = 10,
max_workers: int = None,
) -> List[Any]
```
**Parameters:**
* `agent_task_pairs` (List\[tuple\[AgentType, str]]): List of (agent, task) tuples
* `batch_size` (int): Number of agents to run in parallel in each batch. Default: 10
* `max_workers` (int): Maximum number of threads
**Returns:** List of outputs from each agent, in the same order as input pairs
```python theme={null}
from swarms import Agent
from swarms.structs.multi_agent_exec import run_agents_with_different_tasks
# Create agents
agents = [
Agent(
agent_name="Content-Writer",
system_prompt="You are a content writer",
model_name="claude-sonnet-4-6",
max_loops=1
),
Agent(
agent_name="Editor",
system_prompt="You are an editor",
model_name="claude-sonnet-4-6",
max_loops=1
),
Agent(
agent_name="SEO-Specialist",
system_prompt="You are an SEO specialist",
model_name="claude-sonnet-4-6",
max_loops=1
)
]
# Create agent-task pairs
agent_task_pairs = [
(agents[0], "Write a blog post about sustainable living"),
(agents[1], "Edit and improve this article draft"),
(agents[2], "Optimize this content for SEO")
]
results = run_agents_with_different_tasks(agent_task_pairs, batch_size=2)
for i, result in enumerate(results):
agent, task = agent_task_pairs[i]
print(f"{agent.agent_name} - {task}: {result}")
```
## Utility Functions
### get\_swarms\_info()
Fetches and formats information about all available swarms in the system.
```python theme={null}
def get_swarms_info(swarms: List[Callable]) -> str
```
**Parameters:**
* `swarms` (List\[Callable]): List of swarm objects to get information about
**Returns:** Formatted string containing names and descriptions of all swarms
```python theme={null}
from swarms.structs.multi_agent_exec import get_swarms_info
swarms = [
# Your swarm objects here
]
info = get_swarms_info(swarms)
print(info)
# Output:
# Available Swarms:
#
# [Swarm 1]
# Name: ResearchSwarm
# Description: A swarm for research tasks
# Length of Agents: 3
# Swarm Type: hierarchical
```
### get\_agents\_info()
Fetches and formats information about all available agents in the system.
```python theme={null}
def get_agents_info(
agents: List[Union[Agent, Callable]],
team_name: str = None
) -> str
```
**Parameters:**
* `agents` (List\[Union\[Agent, Callable]]): List of agent objects to get information about
* `team_name` (str, optional): Optional team name to display
**Returns:** Formatted string containing names and descriptions of all agents
```python theme={null}
from swarms import Agent
from swarms.structs.multi_agent_exec import get_agents_info
agents = [
Agent(
agent_name="Research-Agent",
system_prompt="You are a research assistant",
model_name="claude-sonnet-4-6",
max_loops=2,
role="Researcher"
),
Agent(
agent_name="Analysis-Agent",
system_prompt="You are a data analyst",
model_name="claude-sonnet-4-6",
max_loops=1,
role="Analyst"
)
]
info = get_agents_info(agents, team_name="Data Team")
print(info)
```
## Advanced Multi-Agent Workflow Example
```python theme={null}
from swarms import Agent
from swarms.structs.multi_agent_exec import (
run_agents_concurrently,
run_agents_with_different_tasks,
batched_grid_agent_execution,
get_agents_info
)
# Create specialized agents
agents = [
Agent(
agent_name="Market-Researcher",
system_prompt="You are a market research expert specializing in consumer behavior",
model_name="claude-sonnet-4-6",
max_loops=1,
role="Researcher"
),
Agent(
agent_name="Data-Analyst",
system_prompt="You are a data analyst expert in statistical analysis",
model_name="claude-sonnet-4-6",
max_loops=1,
role="Analyst"
),
Agent(
agent_name="Strategy-Consultant",
system_prompt="You are a strategy consultant specializing in business development",
model_name="claude-sonnet-4-6",
max_loops=1,
role="Consultant"
),
Agent(
agent_name="Financial-Advisor",
system_prompt="You are a financial advisor specializing in investment strategies",
model_name="claude-sonnet-4-6",
max_loops=1,
role="Advisor"
)
]
# Display agent information
print("=== Agent Information ===")
print(get_agents_info(agents, "Business Intelligence Team"))
# Same task for all agents (concurrent execution)
task = "Analyze the impact of remote work trends on commercial real estate market"
results = run_agents_concurrently(agents, task, max_workers=4)
for i, result in enumerate(results):
print(f"\n{agents[i].agent_name} Analysis:")
print(f"Result: {result}")
# Dictionary output format
results_dict = run_agents_concurrently(
agents, task, return_agent_output_dict=True, max_workers=4
)
for agent_name, result in results_dict.items():
print(f"\n{agent_name} Analysis:")
print(f"Result: {result}")
# Different tasks for different agents
agent_task_pairs = [
(agents[0], "Research consumer preferences for electric vehicles"),
(agents[1], "Analyze sales data for EV market penetration"),
(agents[2], "Develop marketing strategy for EV adoption"),
(agents[3], "Assess financial viability of EV charging infrastructure")
]
results = run_agents_with_different_tasks(agent_task_pairs, batch_size=2)
# Grid execution with matched agents and tasks
grid_agents = agents[:3]
grid_tasks = [
"Forecast market trends for renewable energy",
"Evaluate risk factors in green technology investments",
"Compare traditional vs sustainable investment portfolios"
]
grid_results = batched_grid_agent_execution(grid_agents, grid_tasks, max_workers=3)
```
## Error Handling and Best Practices
```python theme={null}
from swarms import Agent
from swarms.structs.multi_agent_exec import run_agents_concurrently
import logging
# Set up logging
logging.basicConfig(level=logging.INFO)
# Create agents with error handling
agents = [
Agent(
agent_name=f"Agent-{i}",
system_prompt="You are a helpful assistant",
model_name="claude-sonnet-4-6",
max_loops=1
)
for i in range(5)
]
task = "Perform a complex analysis task"
try:
results = run_agents_concurrently(agents, task, max_workers=4)
# Handle results (some may be exceptions)
for i, result in enumerate(results):
if isinstance(result, Exception):
print(f"Agent {i+1} failed with error: {result}")
else:
print(f"Agent {i+1} succeeded: {result}")
except Exception as e:
print(f"Execution failed: {e}")
```
## Performance Considerations
| Technique | Best Use Case / Description |
| ----------------------- | ------------------------------------------------------------------------------------------------- |
| **ThreadPoolExecutor** | Best for CPU-bound tasks with moderate I/O, supports image processing and flexible output formats |
| **Batch Processing** | Prevents system overload with large numbers of agents, maintains order with grid execution |
| **Resource Monitoring** | Adjust worker counts based on system capabilities (defaults to 95% of CPU cores) |
| **Async/Await** | Use async functions for better concurrency control and platform optimizations |
| **Image Support** | Pass image data to agents that support multimodal processing for enhanced capabilities |
| **Dictionary Output** | Use `return_agent_output_dict=True` for structured results with agent name mapping |
| **Error Handling** | All functions include comprehensive exception handling with graceful fallbacks |
## Best Practices
1. Always handle exceptions in results, as some agents may fail
2. Use appropriate `max_workers` based on system resources
3. Monitor memory usage for large agent counts
4. Consider batch processing for very large numbers of agents
5. Use `return_agent_output_dict=True` for structured, named results
6. Pass image data to agents that support multimodal processing
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/multi_agent_exec.py)
# MultiAgentRouter
Source: https://docs.swarms.world/api/multi-agent-router
Routes tasks to specialized agents based on their capabilities using an intelligent boss agent
## Overview
The `MultiAgentRouter` uses a boss agent powered by LLMs to intelligently route tasks to the most appropriate specialized agent(s). The boss agent analyzes task requirements and agent capabilities to make routing decisions, supporting both single and multiple agent assignments.
## Installation
```bash theme={null}
pip install -U swarms
```
## Attributes
Unique identifier for the router instance. When left as `None`, resolves to `generate_id("multi-agent-router")`
The name of the router
A description of the router's purpose
A list of agents to be managed by the router
The model to use for the boss agent
The temperature for the boss agent's model
A shared memory system for agents to query
The type of output expected from the agents
Whether to print the boss agent's decision
Custom system prompt for the router
Whether to skip executing agents when their assigned task is null or None
## Methods
### route\_task()
Routes a task to the appropriate agent(s) and returns their response.
```python theme={null}
def route_task(self, task: str) -> dict
```
**Parameters:**
* `task` (str): The task to be routed
**Returns:** The formatted conversation history (shaped by `output_type`), containing the user task and the response(s) that were appended to it.
When the boss selects multiple agents, `handle_multiple_handoffs()` runs all of them concurrently but only appends the **first** selected agent's response to the conversation — every other agent's output is computed and then discarded. The boss's `reasoning` is never added to the conversation either (it is only printed to the console when `print_on=True`), so it is not present in the returned result.
### run()
Alias for route\_task().
```python theme={null}
def run(self, task: str) -> dict
```
### batch\_run()
Batch route tasks to the appropriate agents sequentially.
```python theme={null}
def batch_run(self, tasks: List[str] = []) -> list
```
**Parameters:**
* `tasks` (List\[str]): List of tasks to route
**Returns:** List of routing results
### concurrent\_batch\_run()
Concurrently route tasks to the appropriate agents.
```python theme={null}
def concurrent_batch_run(self, tasks: List[str] = []) -> list
```
**Parameters:**
* `tasks` (List\[str]): List of tasks to route
**Returns:** List of routing results from concurrent execution
### query\_ragent()
Query the router's `shared_memory_system` directly.
```python theme={null}
def query_ragent(self, task: str) -> str
```
**Parameters:**
* `task` (str): The query string to forward to `shared_memory_system`
**Returns:** The response returned by the shared memory system
**Raises:** `AttributeError` if no `shared_memory_system` was configured on the router
## Usage Examples
### Basic Routing
```python theme={null}
from swarms import Agent, MultiAgentRouter
# Define specialized agents
agents = [
Agent(
agent_name="ResearchAgent",
description="Specializes in researching topics and providing detailed, factual information",
system_prompt="You are a research specialist. Provide detailed, well-researched information.",
model_name="openai/gpt-5.4",
),
Agent(
agent_name="CodeExpertAgent",
description="Expert in writing, reviewing, and explaining code",
system_prompt="You are a coding expert. Write and review code with best practices.",
model_name="openai/gpt-5.4",
),
Agent(
agent_name="WritingAgent",
description="Skilled in creative and technical writing",
system_prompt="You are a writing specialist. Create and edit content.",
model_name="openai/gpt-5.4",
),
]
# Initialize router
router = MultiAgentRouter(agents=agents)
# Route a task
task = "Write a Python function to calculate fibonacci numbers"
result = router.route_task(task)
print(result)
```
### Custom System Prompt
```python theme={null}
router = MultiAgentRouter(
name="custom-router",
agents=agents,
system_prompt="You are an expert task router. Always select the most qualified agent.",
model="claude-sonnet-4-6",
temperature=0.2
)
result = router.run("Explain quantum computing")
```
### Batch Processing
```python theme={null}
tasks = [
"Research the latest AI developments",
"Write a function to sort an array",
"Create a blog post about technology trends"
]
# Sequential batch processing
results = router.batch_run(tasks)
# Concurrent batch processing
results_concurrent = router.concurrent_batch_run(tasks)
```
### Multiple Agent Assignment
```python theme={null}
# The router can assign complex tasks to multiple agents
task = "Research quantum computing and write a tutorial with code examples"
# The boss agent will intelligently split this across multiple agents:
# - ResearchAgent for the research
# - CodeExpertAgent for the code examples
# - WritingAgent for the tutorial writing
result = router.route_task(task)
# NOTE: all selected agents run concurrently, but only the FIRST selected
# agent's response is appended to the conversation and present in `result`.
# The other agents' outputs are computed but discarded.
```
### Skip Null Tasks
```python theme={null}
router = MultiAgentRouter(
agents=agents,
skip_null_tasks=True # Skip agents with null/None tasks
)
# If boss agent assigns null task to an agent, it will be skipped
result = router.route_task("Simple task")
```
## Response Format
The boss agent returns routing decisions in this JSON format:
```json theme={null}
{
"handoffs": [
{
"reasoning": "This agent is best suited because...",
"agent_name": "ResearchAgent",
"task": "Research the latest AI developments in detail"
}
]
}
```
For multiple agents:
```json theme={null}
{
"handoffs": [
{
"reasoning": "Research capabilities needed for background",
"agent_name": "ResearchAgent",
"task": "Research quantum computing fundamentals"
},
{
"reasoning": "Code expertise for implementation examples",
"agent_name": "CodeExpertAgent",
"task": "Create code examples demonstrating quantum algorithms"
}
]
}
```
## Features
* **Intelligent Routing**: Boss agent analyzes task requirements and agent capabilities
* **Single or Multiple Agents**: Automatically determines if task requires one or multiple agents
* **Custom Routing Logic**: Override system prompt to customize routing behavior
* **Batch Processing**: Process multiple tasks sequentially or concurrently
* **Flexible Output**: Support for various output formats (dict, string, json, etc.)
* **Null Task Handling**: Option to skip agents with null/empty task assignments
# Multi-Swarm Orchestration
Source: https://docs.swarms.world/api/multi-swarm-orchestration
Hierarchical agent orchestration architectures for organizing multiple agents in structured layers
## Overview
Hierarchical agent orchestration involves organizing multiple agents in structured layers to efficiently handle complex tasks. There are several key architectures available, each with distinct characteristics and use cases.
## Installation
```bash theme={null}
pip install -U swarms
```
## Architecture Comparison
| Architecture | Strengths | Weaknesses |
| ------------------ | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| HHCS | Clear task routing, specialized swarm handling, parallel processing capability, good for complex multi-domain tasks | More complex setup, overhead in routing, requires careful swarm design |
| Auto Agent Builder | Dynamic agent creation, flexible scaling, self-organizing, good for evolving tasks | Higher resource usage, potential creation overhead, may create redundant agents |
| SwarmRouter | Multiple workflow types, simple configuration, flexible deployment, good for varied task types | Less specialized than HHCS, limited inter-swarm communication, may require manual type selection |
## Core Architectures
### Hybrid Hierarchical-Cluster Swarm (HHCS)
Hybrid Hierarchical-Cluster Swarm (HHCS) is an architecture that uses a Router Agent to analyze and distribute tasks to other swarms.
* Tasks are routed to specialized swarms based on their requirements
* Enables parallel processing through multiple specialized swarms
* Ideal for complex, multi-domain tasks and enterprise-scale operations
* Provides clear task routing but requires more complex setup
```mermaid theme={null}
flowchart TD
Start([Task Input]) --> RouterAgent[Router Agent]
RouterAgent --> Analysis{Task Analysis}
Analysis -->|Analyze Requirements| Selection[Swarm Selection]
Selection -->|Select Best Swarm| Route[Route Task]
Route --> Swarm1[Specialized Swarm 1]
Route --> Swarm2[Specialized Swarm 2]
Route --> SwarmN[Specialized Swarm N]
Swarm1 -->|Process| Result1[Output 1]
Swarm2 -->|Process| Result2[Output 2]
SwarmN -->|Process| ResultN[Output N]
Result1 --> Final[Final Output]
Result2 --> Final
ResultN --> Final
```
### Auto Agent Builder
Auto Agent Builder is a dynamic agent architecture that creates specialized agents on-demand.
* Analyzes tasks and automatically builds appropriate agents for the job
* Maintains an agent pool that feeds into task orchestration
* Best suited for evolving requirements and dynamic workloads
* Self-organizing but may have higher resource usage
```mermaid theme={null}
flowchart TD
Task[Task Input] --> Builder[Agent Builder]
Builder --> Analysis{Task Analysis}
Analysis --> Create[Create Specialized Agents]
Create --> Pool[Agent Pool]
Pool --> Agent1[Specialized Agent 1]
Pool --> Agent2[Specialized Agent 2]
Pool --> AgentN[Specialized Agent N]
Agent1 --> Orchestration[Task Orchestration]
Agent2 --> Orchestration
AgentN --> Orchestration
Orchestration --> Result[Final Result]
```
### SwarmRouter
SwarmRouter is a flexible system supporting multiple swarm architectures through a simple interface:
* Sequential workflows
* Concurrent workflows
* Hierarchical swarms
* Group chat interactions
* Simpler to configure and deploy compared to other architectures
* Best for general-purpose tasks and smaller scale operations
* Recommended for 5-20 agents
```mermaid theme={null}
flowchart TD
Input[Task Input] --> Router[Swarm Router]
Router --> TypeSelect{Swarm Type Selection}
TypeSelect -->|Sequential| Seq[Sequential Workflow]
TypeSelect -->|Concurrent| Con[Concurrent Workflow]
TypeSelect -->|Hierarchical| Hier[Hierarchical Swarm]
TypeSelect -->|Group| Group[Group Chat]
Seq --> Output[Task Output]
Con --> Output
Hier --> Output
Group --> Output
```
## Use Case Recommendations
### HHCS
Best for:
* Enterprise-scale operations
* Multi-domain problems
* Complex task routing
* Parallel processing needs
### Auto Agent Builder
Best for:
* Dynamic workloads
* Evolving requirements
* Research and development
* Exploratory tasks
### SwarmRouter
Best for:
* General purpose tasks
* Quick deployment
* Mixed workflow types
* Smaller scale operations
## Best Practices for Selection
### Evaluate Task Complexity
* Simple tasks: SwarmRouter
* Complex, multi-domain tasks: HHCS
* Dynamic, evolving tasks: Auto Agent Builder
### Consider Scale
* Small scale: SwarmRouter
* Large scale: HHCS
* Variable scale: Auto Agent Builder
### Resource Availability
* Limited resources: SwarmRouter
* Abundant resources: HHCS or Auto Agent Builder
* Dynamic resources: Auto Agent Builder
### Development Time
* Quick deployment: SwarmRouter
* Complex system: HHCS
* Experimental system: Auto Agent Builder
## Related Documentation
* [Hybrid Hierarchical-Cluster Swarm (HHCS)](/api/hhcs)
* [SwarmRouter](/api/swarm-router)
* [Auto Swarm Builder](/api/auto-swarm-builder)
# Orchestration Methods
Source: https://docs.swarms.world/api/orchestration-methods
A comprehensive suite of multi-agent orchestration methods for structured conversations, debates, negotiations, and decision-making
## Overview
`swarms.structs.multi_agent_debates` provides structured conversation orchestrators for coordinating multiple agents in turn-based discussions. Each orchestrator takes a list of `Agent` instances, drives them through a scripted exchange, and returns the resulting conversation history.
Both classes live in `swarms.structs.multi_agent_debates` and are imported from that module directly — they are not re-exported from the top-level `swarms` package.
## Installation
```bash theme={null}
pip install -U swarms
```
## Available Methods
| Method | Description | Use Case |
| ----------------------- | -------------------------------------------- | ------------------------------------------------ |
| `OneOnOneDebate` | Turn-based debate between exactly two agents | Philosophical discussions, adversarial arguments |
| `ExpertPanelDiscussion` | Expert panel with a moderator guiding rounds | Professional discussions, expert opinions |
## OneOnOneDebate
Simulates a turn-based debate between two agents for a specified number of loops. Both agents are first given a short introduction naming their opponent, then they alternate: each agent's response becomes the next agent's prompt.
### Attributes
Number of conversational turns. One agent speaks per loop, alternating.
Exactly two agents. `run()` raises `ValueError` if the list does not contain exactly two entries.
Optional image passed to each agent's `run()` call.
Format for the returned conversation history.
### run()
Executes the debate between the two agents.
```python theme={null}
def run(self, task: str)
```
The debate topic used as the opening prompt.
The conversation history, formatted according to `output_type`.
`agents` must contain exactly two agents. Any other number raises `ValueError` when `run()` is called.
### Example
```python theme={null}
from swarms import Agent
from swarms.structs.multi_agent_debates import OneOnOneDebate
# Create debating agents
agent1 = Agent(agent_name="Philosopher1", model_name="gpt-5.4")
agent2 = Agent(agent_name="Philosopher2", model_name="gpt-5.4")
# Initialize debate
debate = OneOnOneDebate(
max_loops=3,
agents=[agent1, agent2],
)
# Run debate
result = debate.run("Is artificial intelligence consciousness possible?")
```
## ExpertPanelDiscussion
Simulates an expert panel discussion with a moderator guiding the conversation. Each round, the moderator introduces the topic, every expert responds in turn, and the moderator then synthesises the responses into a follow-up question that becomes the next round's topic.
### Attributes
Number of discussion rounds. Note this is `max_rounds`, not `max_loops`.
Expert panel participants. At least two are required.
The moderator agent who introduces each round and synthesises responses.
Format for the returned conversation history.
### run()
Executes the panel discussion.
```python theme={null}
def run(self, task: str)
```
The main topic for discussion, used as the first round's topic.
The conversation history, formatted according to `output_type`.
`run()` raises `ValueError` if fewer than two experts are supplied in `agents`, or if `moderator` is not set.
### Example
Full example: [Healthcare Panel Discussion](https://github.com/kyegomez/swarms/blob/master/examples/multi_agent/orchestration_examples/healthcare_panel_discussion.py)
```python theme={null}
from swarms import Agent
from swarms.structs.multi_agent_debates import ExpertPanelDiscussion
# Create expert agents
moderator = Agent(agent_name="Moderator", model_name="gpt-5.4")
expert1 = Agent(agent_name="AI_Expert", model_name="gpt-5.4")
expert2 = Agent(agent_name="Ethics_Expert", model_name="claude-sonnet-4-6")
expert3 = Agent(agent_name="Neuroscience_Expert", model_name="gpt-5.4")
# Initialize panel
panel = ExpertPanelDiscussion(
max_rounds=2,
agents=[expert1, expert2, expert3],
moderator=moderator,
)
# Run panel discussion
result = panel.run("What are the ethical implications of AGI development?")
```
## Other Conversation Patterns
Eight further scripted conversation patterns — interview series, peer review, mediation, brainstorming, trial simulation, council meeting, mentorship, and negotiation — ship as standalone example scripts rather than as part of the library. They are built entirely from the public `Agent` and `Conversation` APIs, so they are meant to be copied into your project and adapted, not imported from `swarms`.
Browse them at [`examples/multi_agent/alternate_debates/`](https://github.com/kyegomez/swarms/tree/master/examples/multi_agent/alternate_debates) on GitHub — each file contains one pattern plus a runnable demo.
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/multi_agent_debates.py)
# PlannerGeneratorEvaluator
Source: https://docs.swarms.world/api/planner-generator-evaluator
A GAN-style three-agent orchestration harness with iterative generate-evaluate feedback loops for high-quality output
## Overview
The `PlannerGeneratorEvaluator` is a domain-agnostic three-agent orchestration harness inspired by the GAN-style architecture described in [Anthropic's harness design research](https://www.anthropic.com/engineering/harness-design-long-running-apps). It coordinates long-running autonomous tasks from a short natural-language prompt, using an iterative generate-evaluate feedback loop to converge on high-quality output across any domain.
All three agents communicate through a single shared file on disk.
```mermaid theme={null}
graph TD
A[User Prompt] --> B[Planner]
B --> C[Plan + Evaluation Criteria]
C --> D{For Each Step}
D --> E[Generator Proposes Contract]
E --> F[Evaluator Reviews Contract]
F --> G[Generator Executes Step]
G --> H[Generator Self-Assessment]
H --> I[Evaluator Scores Output]
I --> J{All Criteria Pass?}
J -->|Yes| D
J -->|No| K{Retries Left?}
K -->|Yes + Scores Improving| L[REFINE: Fix Issues]
K -->|Yes + Scores Declining| M[PIVOT: New Approach]
L --> G
M --> G
K -->|No| D
D -->|Done| N[Final Output + Shared State File]
```
The harness follows this workflow:
1. **Planning**: Planner expands a short prompt into an ambitious plan with steps and evaluation criteria
2. **Contract Negotiation**: Generator proposes what "done" looks like for each step; Evaluator reviews
3. **Execution**: Generator produces concrete output and self-assesses before handoff
4. **Evaluation**: Evaluator scores output per-criterion with hard thresholds -- any criterion below its threshold fails the step
5. **Feedback Loop**: On failure, Generator receives scores + trajectory signal (refine or pivot) and retries
6. **All state on disk**: The shared state file is the single append-only record of the entire run
## Installation
```bash theme={null}
pip install -U swarms
```
## Key Features
| Feature | Description |
| ------------------------------ | -------------------------------------------------------------------------- |
| **GAN-Style Separation** | Distinct Generator and Evaluator agents prevent self-evaluation bias |
| **Step Contracts** | Generator and Evaluator agree on success criteria before execution |
| **Hard Threshold Enforcement** | Any single criterion below its threshold fails the step |
| **Score Trajectory** | Tracks score trends across retries -- signals Generator to refine or pivot |
| **Self-Assessment** | Generator self-evaluates before Evaluator handoff |
| **Shared State File** | Single append-only `.md` file for all inter-agent communication |
| **Domain-Agnostic** | Planner defines evaluation criteria tailored to the task domain |
| **Custom Agents** | Pass pre-configured agents with tools, MCP, or any Agent settings |
| **Configurable Thresholds** | Default thresholds plus Planner-defined per-criterion thresholds |
## Attributes
Unique identifier for this harness instance. Auto-generated via `generate_id("planner-generator-evaluator")` if not provided.
Human-readable name for this harness.
Description of the harness purpose.
Model identifier for all three agents
Override model for the Planner
Override model for the Generator
Override model for the Evaluator
Upper bound on plan steps to execute
Max evaluation failures before advancing
Directory where output is produced
Path for the shared state file (auto-generated if None)
Fallback score thresholds by criterion name
Format for output (dict, str, list, final, json, yaml)
Enable verbose logging
System prompt for the Planner agent. Defaults to the built-in planner prompt.
System prompt for the Generator agent. Defaults to the built-in generator prompt.
System prompt for the Evaluator agent. Defaults to the built-in evaluator prompt.
Pre-configured Agent for planning
Pre-configured Agent for generation (e.g., with file/code tools)
Pre-configured Agent for evaluation (e.g., with Playwright MCP)
**Raises:**
| Exception | Condition |
| ------------ | ------------------------------------------------------------------------ |
| `ValueError` | If `max_steps < 1`, `max_retries_per_step < 0`, or `model_name` is empty |
## Methods
### run()
Execute the full PGE harness pipeline from a short prompt to completed output.
```python theme={null}
def run(self, task: str) -> Any
```
**Parameters:**
* `task` (str): A short natural-language description of the desired task
**Returns:** Formatted conversation history according to `output_type`
After `run()` completes, access `harness.last_result` for structured metadata:
| Field | Type | Description |
| ----------------------- | ------------ | --------------------------------------------- |
| `output_path` | `str` | Path to the shared state file |
| `plan` | `str` | The generated plan text |
| `step_logs` | `List[Dict]` | Per-step metadata (contract, scores, retries) |
| `total_duration` | `float` | Wall-clock time in seconds |
| `total_steps_completed` | `int` | Number of steps that passed evaluation |
| `total_retries` | `int` | Total retry attempts across all steps |
### batched\_run()
Run the harness on multiple tasks sequentially.
```python theme={null}
def batched_run(self, tasks: List[str]) -> List[Any]
```
**Parameters:**
* `tasks` (List\[str]): List of task prompts to process
**Returns:** List of results, one per task
### get\_harness\_result()
Return the current state of the harness as a dictionary.
```python theme={null}
def get_harness_result(self) -> Dict[str, Any]
```
**Returns:** Dictionary with `id`, `name`, `shared_state_path`, and `conversation` (the full conversation history as a dict)
### `__call__()`
Makes the harness callable directly, as a convenience alias for `run()`.
```python theme={null}
def __call__(self, task: str, *args, **kwargs) -> Any
```
**Parameters:**
* `task` (str): A short natural-language description of the desired task
* `*args`, `**kwargs`: Forwarded to `run()`
**Returns:** Same as `run()`
```python theme={null}
harness = PlannerGeneratorEvaluator(model_name="gpt-5.4")
result = harness("Write a short guide on sourdough starters") # same as harness.run(...)
```
## Return Types
The PGE harness produces three structured return types that are also re-exported from `swarms.structs` so you can type-annotate against them.
### StepContract
A negotiated agreement between the Generator and the Evaluator for one step of the plan — the title and acceptance criteria the Generator commits to, plus an `approved` flag and any `amendments` the Evaluator pushed back with.
```python theme={null}
from swarms import StepContract
contract = StepContract(
step_number=1,
title="Draft outline",
acceptance_criteria="Three sections, each with bullet points",
approved=True,
amendments="",
)
```
1-indexed position in the plan.
Short step title.
What the Generator's output must satisfy for the Evaluator to approve.
Whether the Evaluator approved this contract.
Evaluator-suggested changes when not approved.
### EvaluationReport
Per-step evaluation produced by the Evaluator agent — criterion scores, threshold checks, pass/fail, and feedback used to drive retries.
```python theme={null}
from swarms import EvaluationReport
report = EvaluationReport(
step_number=1,
criterion_scores={"completeness": 0.9, "accuracy": 0.85},
criterion_thresholds={"completeness": 0.8, "accuracy": 0.8},
passed=True,
actionable_feedback="Tighten the second paragraph for clarity",
summary="Meets thresholds; minor stylistic notes",
raw_evaluation="...",
)
```
Step this report belongs to.
Map of criterion name to score, typically in `[0, 1]`.
Minimum scores needed to pass each criterion.
Whether the step met every threshold.
Specific, retry-targeted feedback for the Generator.
Short prose summary of the evaluation.
Unparsed Evaluator output, retained for debugging.
### HarnessResult
Final result container — populated after `run()` and accessible via `harness.last_result`.
```python theme={null}
from swarms import HarnessResult
result = HarnessResult(
output_path="runs/2026-05-28/plan.md",
plan="...",
step_logs=[{"step": 1, "passed": True}, ...],
total_duration=42.7,
total_steps_completed=3,
total_retries=1,
)
```
Where the harness wrote artifacts (plan, logs, final output).
The full plan the harness executed against.
Per-step structured log: which Generator/Evaluator turns ran, scores, retries.
Wall-clock seconds for the full run.
Number of steps that hit `passed=True`.
Total retries across all steps.
## Usage Examples
### Basic Usage
```python theme={null}
from swarms import PlannerGeneratorEvaluator
harness = PlannerGeneratorEvaluator(
model_name="gpt-5.4",
max_steps=3,
max_retries_per_step=2,
output_type="final",
verbose=True,
)
result = harness.run(
"Write a comprehensive guide on the benefits and risks of intermittent fasting"
)
print(result)
print(f"Steps completed: {harness.last_result.total_steps_completed}")
print(f"Duration: {harness.last_result.total_duration:.1f}s")
```
### Custom Agents with Tools
Pass pre-configured agents with tools so the Generator can write files and the Evaluator can verify them on disk:
```python theme={null}
from swarms import Agent, PlannerGeneratorEvaluator
def write_file(filename: str, content: str) -> str:
"""Write content to a file."""
with open(filename, "w") as f:
f.write(content)
return f"Written: {filename}"
def read_file(filename: str) -> str:
"""Read content from a file."""
with open(filename, "r") as f:
return f.read()
generator = Agent(
agent_name="PGE-Generator",
model_name="gpt-5.4",
max_loops=1,
tools=[write_file],
)
evaluator = Agent(
agent_name="PGE-Evaluator",
model_name="gpt-5.4",
max_loops=1,
tools=[read_file],
)
harness = PlannerGeneratorEvaluator(
model_name="gpt-5.4",
generator_agent=generator,
evaluator_agent=evaluator,
max_steps=3,
)
result = harness.run("Create a Python module for string manipulation utilities")
```
### Evaluator with Playwright MCP (Web App Testing)
For web application development, give the Evaluator browser automation via Playwright MCP so it can test the running app like a real user:
```python theme={null}
from swarms import Agent, PlannerGeneratorEvaluator
evaluator = Agent(
agent_name="PGE-Evaluator",
model_name="gpt-5.4",
max_loops=1,
mcp_config={"url": "http://localhost:3000/playwright"},
)
harness = PlannerGeneratorEvaluator(
model_name="gpt-5.4",
evaluator_agent=evaluator,
max_steps=5,
max_retries_per_step=3,
)
result = harness.run("Build a todo app with React frontend and FastAPI backend")
```
### Custom Thresholds
Provide default score thresholds that apply when the Planner doesn't define them:
```python theme={null}
from swarms import PlannerGeneratorEvaluator
harness = PlannerGeneratorEvaluator(
model_name="gpt-5.4",
default_thresholds={
"accuracy": 8.0,
"clarity": 7.0,
"completeness": 7.0,
},
max_retries_per_step=4,
)
result = harness.run("Write a technical specification for a rate-limiting middleware")
```
## Architecture Details
### Shared State File
All inter-agent communication flows through a single append-only markdown file. Each section is timestamped and labeled:
```
# PGE Harness Shared State
## User Prompt
[original prompt]
---
### [PLANNER OUTPUT] (2026-03-25 10:30:00)
[plan with steps and evaluation criteria]
---
### [STEP 1 CONTRACT PROPOSAL] (2026-03-25 10:30:15)
[Generator's proposed contract]
---
### [STEP 1 CONTRACT REVIEW] (2026-03-25 10:30:25)
[Evaluator's review -- APPROVED or AMENDMENTS REQUIRED]
---
### [STEP 1 WORK LOG] (2026-03-25 10:30:45)
[Generator's output + self-assessment]
---
### [STEP 1 EVALUATION] (2026-03-25 10:31:00)
[Evaluator's per-criterion scores, findings, and feedback]
```
### Refine vs. Pivot
When a step fails evaluation, the harness computes a score trajectory across retries:
* **Scores improving** -- REFINE: keep the current direction, fix specific issues
* **Scores declining or stagnant** -- PIVOT: take a fundamentally different approach
This signal is passed to the Generator alongside the Evaluator's feedback.
### Evaluation Criteria
The Planner defines domain-appropriate criteria as part of the plan. Each criterion has:
| Field | Description |
| --------------- | ------------------------------------------------------------------------ |
| **Name** | Short label (e.g., "accuracy", "clarity") |
| **Weight** | Relative importance (high, standard, low) |
| **Description** | What it measures and what good/bad looks like |
| **Threshold** | Minimum passing score (1-10). Any criterion below threshold = step fails |
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/planner_generator_evaluator.py)
# PlannerWorkerSwarm
Source: https://docs.swarms.world/api/planner-worker-swarm
A planner-worker-judge architecture for parallel multi-agent task execution with optimistic concurrency
## Overview
The `PlannerWorkerSwarm` implements a planner-worker-judge architecture for parallel multi-agent task execution. Based on Cursor's ["Scaling long-running autonomous coding"](https://cursor.com/blog/scaling-agents) research, it separates planning from execution: a planner decomposes goals into prioritized tasks, worker agents claim and execute tasks concurrently from a shared queue, and a judge evaluates the cycle results.
```mermaid theme={null}
graph TD
A[User Task] --> B[Planner Agent]
B --> C[TaskQueue]
C --> D1[Worker 1]
C --> D2[Worker 2]
C --> D3[Worker N]
D1 --> E[Results]
D2 --> E
D3 --> E
E --> F[Judge Agent]
F -->|Complete| G[Output]
F -->|Gaps| H[Replan with feedback]
F -->|Drift| I[Fresh Start]
H --> B
I --> B
```
The swarm follows a cycle-based workflow:
1. **Planning**: A planner agent decomposes the goal into concrete, prioritized tasks with dependencies
2. **Execution**: Worker agents independently claim tasks from a shared queue and execute them concurrently via `ThreadPoolExecutor` -- no worker-to-worker coordination
3. **Evaluation**: A judge agent evaluates the combined results and decides: complete, fill gaps, or fresh start
4. **Iteration**: If not complete, the planner receives judge feedback and produces new tasks for the next cycle
## Installation
```bash theme={null}
pip install -U swarms
```
## Attributes
Name identifier for this swarm instance
Description of the swarm's purpose
Worker agents that execute tasks. Must not be empty.
Maximum planner-worker-judge cycles (must be greater than 0)
Model for the planner agent
Model for the judge agent
Max recursive sub-planner depth. `1` = no sub-planners; `2` = CRITICAL tasks are decomposed once.
Max seconds for the entire worker pool per cycle
Max seconds per individual task execution
Max concurrent worker threads. Defaults to `min(len(agents), os.cpu_count())`.
Format for the final result
Whether to save conversation history
Enable verbose logging
**Raises:**
| Exception | Condition |
| ------------ | --------------------------------------------- |
| `ValueError` | If no agents are provided or `max_loops <= 0` |
## Methods
### run()
Executes the planner-worker-judge cycle up to `max_loops` times or until the judge declares the goal complete.
```python theme={null}
def run(self, task: Optional[str] = None, img: Optional[str] = None) -> Any
```
**Parameters:**
* `task` (str): The goal to accomplish
* `img` (str, optional): Optional image input
**Returns:** Formatted conversation history per `output_type`
**Raises:**
* `ValueError`: If `task` is not provided
### get\_status()
Returns a structured status report of the swarm and its task queue.
```python theme={null}
def get_status(self) -> Dict[str, Any]
```
**Returns:** Status dict with `name`, `original_task`, and `queue` (containing `total`, `progress`, `status_counts`, and per-task details)
## Usage Examples
### Quick Start
```python theme={null}
from swarms import Agent
from swarms.structs.planner_worker_swarm import PlannerWorkerSwarm
swarm = PlannerWorkerSwarm(
agents=[
Agent(agent_name="Research", agent_description="Gathers information", model_name="gpt-5.4", max_loops=1),
Agent(agent_name="Analysis", agent_description="Analyzes data", model_name="gpt-5.4", max_loops=1),
],
max_loops=1,
max_workers=2,
worker_timeout=120,
)
result = swarm.run("What are the top 3 benefits of renewable energy?")
print(result)
```
### Multi-Cycle with Judge Feedback
Set `max_loops > 1` so the judge can request additional planning cycles when the goal is not yet achieved:
```python theme={null}
from swarms import Agent
from swarms.structs.planner_worker_swarm import PlannerWorkerSwarm
workers = [
Agent(
agent_name="Research-Agent",
agent_description="Gathers factual information and data",
model_name="gpt-5.4",
max_loops=1,
),
Agent(
agent_name="Analysis-Agent",
agent_description="Analyzes data and identifies patterns",
model_name="gpt-5.4",
max_loops=1,
),
]
swarm = PlannerWorkerSwarm(
name="Research-Swarm",
agents=workers,
max_loops=3, # up to 3 planner-worker-judge cycles
max_workers=5,
worker_timeout=120,
)
result = swarm.run(
task="Produce a comprehensive market report on the EV industry "
"covering manufacturers, technology trends, adoption challenges, "
"regional differences, and a 5-year outlook."
)
print(result)
```
The judge evaluates each cycle:
* **Cycle 1**: Judge finds gaps ("missing regional analysis") -- planner creates targeted tasks
* **Cycle 2**: Judge finds remaining issues ("outlook section too shallow") -- planner fills gaps
* **Cycle 3**: Judge marks complete with quality 9/10
### Recursive Sub-Planners
Set `max_planner_depth > 1` to automatically decompose CRITICAL-priority tasks via sub-planner agents:
```python theme={null}
swarm = PlannerWorkerSwarm(
agents=workers,
max_planner_depth=2, # CRITICAL tasks decomposed once
)
result = swarm.run(
task="Design and implement a complete REST API for a task management system"
)
```
When the top-level planner produces a CRITICAL task (e.g., "Design the database schema and API endpoints"), it gets cancelled and replaced by the sub-planner's more granular subtasks.
### Timeouts
```python theme={null}
swarm = PlannerWorkerSwarm(
agents=workers,
worker_timeout=120, # 2 min max for entire worker phase per cycle
task_timeout=30, # 30s max per individual task (detects stuck workers)
)
```
* `worker_timeout`: Total wall time for the worker pool per cycle. Workers stop claiming new tasks after this deadline.
* `task_timeout`: Per-task execution limit. If exceeded, the task fails with a `TimeoutError` and may be retried.
### Checking Swarm Status
```python theme={null}
status = swarm.get_status()
print(f"Progress: {status['queue']['progress']}")
for task in status["queue"]["tasks"]:
print(f" [{task['status']}] {task['title']} -> {task['assigned_worker']}")
```
### SwarmRouter Integration
`PlannerWorkerSwarm` is available as a swarm type in `SwarmRouter`:
```python theme={null}
from swarms import Agent
from swarms.structs.swarm_router import SwarmRouter
workers = [
Agent(agent_name="W1", model_name="gpt-5.4", max_loops=1),
Agent(agent_name="W2", model_name="gpt-5.4", max_loops=1),
]
router = SwarmRouter(agents=workers, swarm_type="PlannerWorkerSwarm")
result = router.run("Analyze the competitive landscape of cloud computing providers")
```
## Architecture
### Design Principles (from the Cursor blog)
| Cursor Principle | Implementation |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Planners plan, workers execute | `_run_planner()` produces `PlannerTaskSpec`; workers get `WORKER_SYSTEM_PROMPT` enforcing "only execute, never plan" |
| No worker-to-worker coordination | Workers interact only with `TaskQueue.claim()` -- atomic, no shared state |
| No locks / optimistic concurrency | `TaskQueue` uses a version field per task; `claim()` is atomic under a minimal lock, but workers never block each other |
| Judge-driven cycles with fresh start | `CycleVerdict.needs_fresh_start` triggers `TaskQueue.clear()` to combat accumulated drift |
| Prompts matter more than infrastructure | `WORKER_SYSTEM_PROMPT`, `PLANNER_SYSTEM_PROMPT`, and `JUDGE_SYSTEM_PROMPT` enforce strict role boundaries |
| Horizontal scaling | `ThreadPoolExecutor(max_workers=N)` -- tested with 200 tasks across 100 threads, zero double-claims |
### Task State Machine
```
PENDING --> CLAIMED --> RUNNING --> COMPLETED
|
v
FAILED --> PENDING (retry)
|
v (retries exhausted)
FAILED (permanent)
Any non-terminal --> CANCELLED
```
### Cycle Flow
```
Cycle 1:
Planner receives: original task
Workers execute: tasks from queue
Judge evaluates: complete? gaps? drift?
Cycle 2+ (if not complete):
If fresh start: clear ALL tasks, planner starts from scratch with judge feedback
If gap fill: clear non-terminal tasks, preserve completed results
Planner receives: original task + judge feedback + identified gaps
Workers execute: new tasks
Judge re-evaluates
```
### How It Works
**Planner Agent**: Created internally each cycle. Uses structured output (`PlannerTaskSpec`) to produce a plan narrative and a list of concrete tasks with title, description, priority (0-3), and dependency titles. On subsequent cycles, the planner receives the judge's feedback (gaps + follow-up instructions) appended to the original task.
**Worker Execution**: Each worker runs in a `ThreadPoolExecutor` thread, independently claiming tasks from a shared `TaskQueue`. Workers never coordinate with each other. Each worker loop: claims a task, resets agent memory, builds context (`WORKER_SYSTEM_PROMPT` + task description + dependency results), executes via `agent.run()`, and marks the task complete or failed.
**Optimistic concurrency**: every task has a `version` field. State transitions check the expected version -- if another worker modified the task, the operation is rejected. This avoids lock-based coordination problems (deadlocks, forgotten releases).
**Claim priority**: highest priority first, then oldest first, with dependency satisfaction required.
**Judge Agent**: Created internally after workers complete. Evaluates the cycle results and produces a `CycleVerdict`:
| Field | Type | Description |
| ------------------------ | --------------- | ------------------------------------------------------------ |
| `is_complete` | `bool` | Whether the goal has been fully achieved |
| `overall_quality` | `int` (0-10) | Quality score of the combined results |
| `summary` | `str` | Brief assessment of what was accomplished |
| `gaps` | `List[str]` | Specific missing items or issues |
| `follow_up_instructions` | `Optional[str]` | Instructions for the planner if another cycle is needed |
| `needs_fresh_start` | `bool` | Whether accumulated drift requires discarding all prior work |
### Fresh Start vs Gap Fill
| | Gap Fill (`needs_fresh_start=False`) | Fresh Start (`needs_fresh_start=True`) |
| -------------------- | ------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| **When** | Some tasks succeeded but gaps remain | Systemic drift, contradictory results, fundamentally flawed plan |
| **What happens** | Only non-terminal tasks are cleared; completed results are preserved as context | ALL tasks are discarded |
| **Planner receives** | Original task + feedback + gaps | Original task + feedback (clean slate) |
## Schemas
### PlannerTask
Represents a single task in the shared queue.
| Field | Type | Default | Description |
| ----------------- | ------------------- | -------------- | ----------------------------------------------- |
| `id` | `str` | auto-generated | Unique task identifier (`ptask-{uuid}`) |
| `title` | `str` | required | Short, descriptive title |
| `description` | `str` | required | Detailed description for the worker |
| `priority` | `TaskPriority` | `NORMAL` | `LOW(0)`, `NORMAL(1)`, `HIGH(2)`, `CRITICAL(3)` |
| `depends_on` | `List[str]` | `[]` | Task IDs that must complete first |
| `parent_task_id` | `Optional[str]` | `None` | Parent task ID if decomposed by sub-planner |
| `status` | `PlannerTaskStatus` | `PENDING` | Current status |
| `assigned_worker` | `Optional[str]` | `None` | Name of the worker that claimed this task |
| `result` | `Optional[str]` | `None` | Execution result |
| `error` | `Optional[str]` | `None` | Error message if failed |
| `retries` | `int` | `0` | Retry attempts so far |
| `max_retries` | `int` | `2` | Max retries before permanent failure |
| `version` | `int` | `0` | Optimistic concurrency counter |
| `created_at` | `float` | `time.time()` | Unix timestamp |
| `completed_at` | `Optional[float]` | `None` | Completion timestamp |
| `metadata` | `Dict` | `{}` | Arbitrary metadata |
### TaskPriority
| Value | Name | Description |
| ----- | ---------- | ----------------------------------------------------------------------------------- |
| 0 | `LOW` | Background or optional tasks |
| 1 | `NORMAL` | Standard priority (default) |
| 2 | `HIGH` | Important tasks that should be prioritized |
| 3 | `CRITICAL` | Must-do tasks; also triggers sub-planner decomposition when `max_planner_depth > 1` |
## Best Practices
| Best Practice | Description |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Agent Specialization** | Give each worker a specific expertise area (research, analysis, writing) so the planner can match tasks to strengths |
| **Agent Descriptions** | Provide clear `agent_description` fields -- the planner uses these to understand what each worker can do |
| **Single-Loop Workers** | Set `max_loops=1` on worker agents -- the swarm's outer loop handles iteration |
| **Model Selection** | Use a capable model for the planner and judge (task decomposition and evaluation are harder than execution) |
| **Reasonable max\_loops** | 1-3 cycles is typical; diminishing returns after that |
| **Timeouts** | Always set `worker_timeout` in production to prevent runaway execution |
| **Worker Count** | `max_workers` should roughly match agent count -- more threads than agents won't help |
| **Dependencies** | Use task dependencies when output from one task is needed as input to another |
| **Fresh Start** | Trust the judge's fresh start mechanism -- it's designed to combat the drift problem identified in Cursor's research |
## Error Handling
| Issue | Solution |
| --------------------------------- | ---------------------------------------------------------------------------------- |
| No agents provided | Pass at least one `Agent` in the `agents` list |
| `max_loops <= 0` | Set `max_loops` to a positive integer |
| No task provided | Pass a non-empty `task` string to `run()` |
| Planner output parsing fails | Check that `planner_model_name` supports structured output (function calling) |
| Judge output parsing fails | Defaults to `is_complete=False` with quality 0, so the cycle continues safely |
| Worker stuck on a task | Set `task_timeout` to detect and fail stuck tasks |
| All workers idle but tasks remain | Tasks may be blocked on unmet dependencies -- check for circular dependency chains |
## Performance Considerations
| Consideration | Description |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Parallelism** | The primary performance advantage -- N workers execute N tasks simultaneously instead of sequentially |
| **Planner/Judge Overhead** | Each cycle adds 2 LLM calls (planner + judge) on top of the worker calls. Use smaller/faster models for these roles |
| **Sub-Planner Cost** | `max_planner_depth > 1` adds one planner call per CRITICAL task. Only enable when tasks genuinely need decomposition |
| **Memory Reset** | Worker memory is reset between tasks, which adds a small overhead but prevents context pollution |
| **Task Timeout** | Per-task timeout spawns a nested thread -- slight overhead, but essential for detecting stuck workers |
| **Queue Contention** | The `TaskQueue` lock is held only during claim/transition operations (microseconds). Tested with 200 tasks across 100 threads with zero contention issues |
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/planner_worker_swarm.py)
# Prompts
Source: https://docs.swarms.world/api/prompts
Complete reference for the Swarms prompts module including the Prompt class and pre-built prompt templates
## Overview
The `swarms.prompts` module provides tools for creating, managing, and versioning prompts with comprehensive history tracking, autosaving capabilities, and integration with agent systems.
## Prompt Class
A powerful class for managing prompts with version control, edit history, and autosaving features.
```python theme={null}
from swarms.prompts import Prompt
prompt = Prompt(
name="analysis_prompt",
description="Financial analysis prompt",
content="Analyze the following financial data...",
autosave=True,
autosave_folder="prompts"
)
```
### Constructor
Unique identifier for the prompt
Name of your prompt
Description of the prompt
The main content of the prompt (minimum 1 character)
Timestamp when the prompt was created
Timestamp when the prompt was last modified
Number of times the prompt has been edited
History of all prompt versions
Enable automatic saving of the prompt
Folder path within WORKSPACE\_DIR for autosaving
Enable auto-generation of prompts
Parent folder for the autosave folder
Optional LLM instance for prompt generation
### Methods
#### edit\_prompt
Edit the prompt content and update version control.
```python theme={null}
prompt.edit_prompt("Updated prompt content here")
```
The updated content of the prompt
**Raises:**
* `ValueError`: If the new content is identical to the current content
**Thread-safe**: This method is safe for concurrent access.
#### rollback
Roll back the prompt to a previous version.
```python theme={null}
# Rollback to the first version
prompt.rollback(version=0)
```
The version index to roll back to (0 is the first version)
**Raises:**
* `IndexError`: If the version number is out of range
#### get\_prompt
Return the current prompt content as a string.
```python theme={null}
content = prompt.get_prompt()
print(content)
```
The current prompt content
#### return\_json
Return the prompt as a JSON string.
```python theme={null}
json_data = prompt.return_json()
print(json_data)
```
JSON representation of the prompt with all metadata
#### add\_tools
Add tool schemas to the prompt content.
```python theme={null}
from swarms.tools import BaseTool
def my_tool(x: int) -> int:
"""Double the input."""
return x * 2
prompt.add_tools([my_tool])
```
List of callable functions to add as tools
## Pre-built Prompt Templates
The module includes numerous pre-built prompt templates for common agent roles:
### Finance Prompts
#### FINANCE\_AGENT\_PROMPT
Comprehensive prompt for financial analysis agents.
```python theme={null}
from swarms.prompts import FINANCE_AGENT_PROMPT
agent = Agent(
agent_name="Financial-Analyst",
system_prompt=FINANCE_AGENT_PROMPT,
# ... other config
)
```
### Legal Prompts
#### LEGAL\_AGENT\_PROMPT
Prompt template for legal analysis and research agents.
```python theme={null}
from swarms.prompts import LEGAL_AGENT_PROMPT
agent = Agent(
agent_name="Legal-Advisor",
system_prompt=LEGAL_AGENT_PROMPT,
# ... other config
)
```
### Product & Operations
#### PRODUCT\_AGENT\_PROMPT
Prompt for product management agents.
```python theme={null}
from swarms.prompts import PRODUCT_AGENT_PROMPT
```
#### OPERATIONS\_AGENT\_PROMPT
Prompt for operations management agents.
```python theme={null}
from swarms.prompts import OPERATIONS_AGENT_PROMPT
```
#### GROWTH\_AGENT\_PROMPT
Prompt for growth and marketing agents.
```python theme={null}
from swarms.prompts import GROWTH_AGENT_PROMPT
```
### Development Prompts
#### CODE\_INTERPRETER
Prompt for code interpretation and execution agents.
```python theme={null}
from swarms.prompts import CODE_INTERPRETER
agent = Agent(
agent_name="Code-Interpreter",
system_prompt=CODE_INTERPRETER,
# ... other config
)
```
#### DOCUMENTATION\_WRITER\_SOP
Standard operating procedure for documentation writing agents.
```python theme={null}
from swarms.prompts import DOCUMENTATION_WRITER_SOP
```
### Autonomous Agent Prompts
#### AUTONOMOUS\_AGENT\_SYSTEM\_PROMPT
Base system prompt for autonomous agents.
```python theme={null}
from swarms.prompts import AUTONOMOUS_AGENT_SYSTEM_PROMPT
```
#### get\_autonomous\_agent\_prompt
Generate an autonomous agent prompt.
```python theme={null}
from swarms.prompts import get_autonomous_agent_prompt
prompt = get_autonomous_agent_prompt()
```
#### get\_autonomous\_agent\_prompt\_with\_context
Generate an autonomous agent prompt customized with agent identity and available tools.
```python theme={null}
from swarms.prompts import get_autonomous_agent_prompt_with_context
prompt = get_autonomous_agent_prompt_with_context(
agent_name="MarketAnalyst",
agent_description="Analyzes financial markets with a focus on tech stocks",
available_tools=["search_web", "get_stock_price"],
)
```
Name of the agent to embed in the prompt
Description of the agent's role to embed in the prompt
List of tool names available to the agent
## Example: Complete Prompt Management
```python theme={null}
from swarms.prompts import Prompt
from swarms.tools import BaseTool
import os
# Set workspace directory
os.environ["WORKSPACE_DIR"] = "./workspace"
# Create a prompt with autosave
prompt = Prompt(
name="market_analysis",
description="Financial market analysis prompt",
content="""You are a financial analyst. Analyze the following:
1. Market trends
2. Risk factors
3. Investment opportunities
""",
autosave=True,
autosave_folder="financial_prompts"
)
# Edit the prompt
prompt.edit_prompt("""
You are an expert financial analyst specializing in equity markets.
Analyze the following aspects:
1. Current market trends and momentum
2. Key risk factors and hedging strategies
3. High-conviction investment opportunities
4. Portfolio allocation recommendations
Provide detailed analysis with supporting data.
""")
print(f"Edit count: {prompt.edit_count}") # 1
print(f"Total versions: {len(prompt.edit_history)}") # 2
# Add tools to the prompt
def calculate_sharpe_ratio(returns: float, risk_free_rate: float, std_dev: float) -> float:
"""Calculate Sharpe ratio for investment analysis."""
return (returns - risk_free_rate) / std_dev
prompt.add_tools([calculate_sharpe_ratio])
# Rollback if needed
prompt.rollback(version=0) # Back to original version
# Get the current prompt
current = prompt.get_prompt()
print(current)
# Export as JSON
json_export = prompt.return_json()
print(json_export)
```
## Best Practices
1. **Enable autosave**: Always enable autosave for important prompts to prevent data loss
2. **Use descriptive names**: Give prompts clear, descriptive names for easy identification
3. **Version control**: Leverage the built-in version control to track prompt evolution
4. **Add context**: Include detailed descriptions to document the prompt's purpose
5. **Organize by folder**: Use the `autosave_folder` parameter to organize prompts by category
6. **Regular rollbacks**: Test different prompt versions using rollback functionality
7. **Tool integration**: Use `add_tools()` to seamlessly integrate function calling
## Thread Safety
The Prompt class implements thread-safe operations for:
* Edit operations
* Rollback operations
* Autosaving
This makes it safe to use in concurrent environments and multi-agent systems.
## Autosave Behavior
When autosave is enabled:
1. Prompts are saved to `{WORKSPACE_DIR}/{autosave_folder}/prompt-id-{id}.json`
2. Each edit automatically triggers a save
3. Rollback operations also trigger saves
4. The entire prompt state (including history) is preserved
## Integration with Agents
```python theme={null}
from swarms import Agent
from swarms.prompts import Prompt, FINANCE_AGENT_PROMPT
# Using pre-built prompts
agent1 = Agent(
agent_name="Financial-Analyst",
system_prompt=FINANCE_AGENT_PROMPT,
model_name="gpt-4"
)
# Using custom Prompt class
custom_prompt = Prompt(
name="custom_analyst",
content="You are a specialized quantitative analyst...",
autosave=True
)
agent2 = Agent(
agent_name="Quant-Analyst",
system_prompt=custom_prompt.get_prompt(),
model_name="gpt-4"
)
```
# RoundRobinSwarm
Source: https://docs.swarms.world/api/round-robin-swarm
A swarm that executes a task across agents in deterministic round-robin order, each agent building on the shared transcript
## Overview
`RoundRobinSwarm` visits agents in their **declared insertion order**, cycling through the full roster once per loop. The schedule is deterministic and identical on every loop:
```
turn t -> agents[t % N] for t in range(max_loops * N)
```
Every agent reads the full conversation transcript accumulated by the agents that spoke before it, and each agent receives exactly `max_loops` turns. Before each turn the swarm injects a role header telling the agent its position, the current loop, the previous/next speaker, and the other participants, then asks it to build on the prior contribution.
Earlier versions of `RoundRobinSwarm` shuffled agents randomly each loop and supported `callback` / `max_retries` parameters. Those are **removed** — the order is now strictly deterministic and those parameters no longer exist.
## Installation
```bash theme={null}
pip install -U swarms
```
## Import
```python theme={null}
from swarms import Agent, RoundRobinSwarm
```
The per-turn prompt builders are also importable for inspection or reuse:
```python theme={null}
from swarms.structs.round_robin import (
RoundRobinSwarm,
build_turn_header,
build_collaborative_task,
)
```
## Constructor
```python theme={null}
RoundRobinSwarm(
name: str = "RoundRobinSwarm",
description: str = "A swarm implementation that executes tasks in a round-robin fashion.",
agents: List[Agent] = None,
verbose: bool = False,
max_loops: int = 1,
output_type: OutputType = "final",
)
```
Name of the swarm. Also used to name the internal conversation.
Description of the swarm's purpose.
Agents that take turns in declared order. **Required** — constructing the swarm without agents raises `ValueError`.
Enable verbose logging of each turn and loop.
Number of full passes over the roster. Each agent speaks exactly once per loop, so with `N` agents and `max_loops` loops the swarm runs `N * max_loops` turns total.
Output format applied to the conversation history. Common values: `"final"` (last message only), `"list"`, `"dict"`, `"str"`, `"json"`.
## Methods
### `run(task, *args, **kwargs)`
Execute the task across the agents in deterministic round-robin order. Returns the conversation in the format specified by `output_type`.
```python theme={null}
def run(self, task: str, *args, **kwargs) -> Union[str, dict, list]
```
The task to execute. Posted as the opening `User` message that the first agent responds to.
`*args` / `**kwargs` are forwarded to each underlying `agent.run()` call.
**Returns:** the task result formatted per `output_type`.
**Raises:** re-raises any exception thrown by an agent during execution.
***
### `run_batch(tasks)`
Execute multiple tasks sequentially. Each task runs through its own full round-robin cycle.
```python theme={null}
def run_batch(self, tasks: List[str]) -> List[Union[str, dict, list]]
```
Tasks to execute, one full round-robin run per task.
**Returns:** a list of results in the same order as `tasks`.
## Usage Examples
### Basic round-robin execution
```python theme={null}
from swarms import Agent, RoundRobinSwarm
agents = [
Agent(
agent_name="Analyst",
system_prompt="You are a data analyst. Analyze information critically.",
model_name="gpt-5.4",
max_loops=1,
),
Agent(
agent_name="Strategist",
system_prompt="You are a strategist. Think about long-term implications.",
model_name="gpt-5.4",
max_loops=1,
),
Agent(
agent_name="Implementer",
system_prompt="You are an implementer. Focus on practical execution.",
model_name="gpt-5.4",
max_loops=1,
),
]
swarm = RoundRobinSwarm(agents=agents, max_loops=1, verbose=True)
result = swarm.run("How should we approach building a new AI product?")
print(result)
```
### Multiple loops
```python theme={null}
# Two full passes: each agent speaks twice, in the same order each loop.
swarm = RoundRobinSwarm(
agents=agents,
max_loops=2,
verbose=True,
)
result = swarm.run("Develop a comprehensive marketing strategy.")
```
### Different output types
```python theme={null}
# Final message only (default)
final_swarm = RoundRobinSwarm(agents=agents, output_type="final")
final_result = final_swarm.run("Analyze this problem.")
# Full conversation as a list of messages
list_swarm = RoundRobinSwarm(agents=agents, output_type="list")
list_result = list_swarm.run("Analyze this problem.")
# Full conversation as a dict
dict_swarm = RoundRobinSwarm(agents=agents, output_type="dict")
dict_result = dict_swarm.run("Analyze this problem.")
```
### Batch processing
```python theme={null}
tasks = [
"Analyze market trends in AI",
"Develop a product roadmap",
"Create a risk assessment",
]
results = swarm.run_batch(tasks)
for i, result in enumerate(results):
print(f"\nTask {i + 1} Result:\n{result}")
```
## How It Works
1. **Opening message** — the user task is added to the conversation as the first `User` message.
2. **Deterministic schedule** — for `max_loops` loops, the swarm iterates `agents` in insertion order: turn `t` goes to `agents[t % N]`.
3. **Full context** — before each turn, the current full transcript is read and passed to the agent.
4. **Role header** — a per-turn header (see below) tells the agent its position, loop, previous/next speaker, and peers.
5. **Collaborative reply** — the agent is asked to build on the prior speaker's contribution (or address the task directly if it opens), and its response is appended to the transcript.
6. **Formatted output** — after all loops complete, the conversation is returned per `output_type`.
## Per-turn prompt
Each agent receives a generated header and a standing instruction, produced by `build_turn_header` and `build_collaborative_task`. The running transcript is **not** concatenated into this prompt string — `run()` calls `build_collaborative_task(conversation_context="", turn_header=turn_header)`, so the prior-turns transcript is delivered separately to the agent via the `messages` argument of `agent.run()`, not as literal text in the task prompt:
```
You are Analyst, agent 1 of 3 in loop 1 of 2. Previous speaker:
(none — you open the conversation). Next speaker: Strategist.
Other participants: Strategist, Implementer.
Review the transcript above and build on the prior speaker's contribution.
Add your own perspective concisely; if you are the opening speaker, address
the original task directly.
Your response:
```
## Features
* **Deterministic order** — agents always speak in declared insertion order, identically every loop.
* **Full context** — each agent sees the complete transcript accumulated so far.
* **Collaborative prompting** — agents are told their position and neighbors and asked to build on prior turns.
* **Flexible output** — choose `"final"`, `"list"`, `"dict"`, `"str"`, or `"json"`.
* **Batch processing** — `run_batch` runs many tasks, one full cycle each.
* **Serializable** — inherits `SerializableMixin` for config serialization.
## Best Practices
1. **Order matters** — place agents in the sequence you want them to speak; the opener sets the framing for everyone after.
2. **Agent diversity** — use complementary roles so each turn adds a distinct perspective.
3. **Loop count** — start with `max_loops=1`; increase only when deeper back-and-forth is needed (cost scales with `N * max_loops`).
4. **Output type** — use `"final"` for a single answer, `"list"`/`"dict"` to inspect the whole collaboration.
5. **Verbose mode** — enable `verbose=True` while debugging to trace each turn.
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/round_robin.py).
# Schemas
Source: https://docs.swarms.world/api/schemas
Pydantic schemas for agents, conversations, and API interactions in Swarms
## Overview
The `swarms.schemas` module provides Pydantic models and exception classes used for structured data validation across the framework. Everything importable from `swarms.schemas` falls into three groups:
| Group | Exports |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **MCP schemas** | `MCPConnection`, `MCPOAuthConfig` |
| **Agent errors** | `AgentError`, `AgentInitializationError`, `AgentRunError`, `AgentLLMError`, `AgentLLMInitializationError`, `AgentToolExecutionError`, `AgentMCPError`, `AgentMCPConnectionError`, `AgentMCPToolError` |
| **Planner/worker schemas** | `TaskPriority`, `PlannerTaskStatus`, `PlannerTask`, `PlannerTaskOutput`, `PlannerTaskSpec`, `CycleVerdict` |
```python theme={null}
from swarms.schemas import (
MCPConnection,
MCPOAuthConfig,
AgentError,
PlannerTask,
CycleVerdict,
)
```
These 17 names are the complete public surface of `swarms.schemas`.
## MCP Schemas
### MCPConnection
Defines connection parameters for a Model Context Protocol (MCP) server.
```python theme={null}
from swarms.schemas import MCPConnection
mcp = MCPConnection(
url="http://localhost:8000/mcp",
name="filesystem",
transport="streamable_http",
authorization_token="secret-token",
headers={"X-Custom-Header": "value"},
timeout=30,
)
```
The type of connection
The URL endpoint for the MCP server
Human readable name for the server, used in logs and tool routing
Dictionary containing configuration settings for MCP tools
Bearer token for accessing the MCP server
API key for the MCP server. Sent using `api_key_header` / `api_key_prefix`
Header used to send the API key, e.g. `"Authorization"` or `"X-API-Key"`
Prefix prepended to the API key value. Set to `None`/`""` for raw keys
Explicit auth mode. Inferred from the other fields when omitted
OAuth 2.1 configuration for this server
Transport protocol: `"streamable_http"`, `"sse"`, `"stdio"`, or `"auto"`
Headers to send to the MCP server
Request timeout (in seconds) for the MCP server
How long to wait for streamed events before giving up
How long a single tool call may run before timing out. Separate from `timeout`, which bounds HTTP requests
Executable to launch for the `stdio` transport
Arguments passed to the `stdio` command
Environment variables for the `stdio` command
This model allows extra fields (`extra = "allow"`), so additional keys will not raise a validation error, but only the fields above are read by the framework.
### MCPOAuthConfig
OAuth 2.1 configuration for an MCP server, passed as `MCPConnection.oauth`. Three flavours are supported:
1. `grant_type="authorization_code"` (default) — the interactive browser flow. PKCE and RFC 7591 dynamic client registration are handled by the MCP SDK, so `client_id` is optional. Tokens are cached on disk so the browser prompt only happens once.
2. `grant_type="client_credentials"` — a headless machine-to-machine flow. Requires `client_id`/`client_secret`.
3. `access_token=...` — a token obtained elsewhere. No flow is run; the token is sent as a bearer credential.
Any string field may use `"env:MY_VAR"` or `"${MY_VAR}"` to read the value from the environment instead of hardcoding a secret.
```python theme={null}
from swarms.schemas import MCPConnection, MCPOAuthConfig
mcp = MCPConnection(
url="https://mcp.example.com/mcp",
oauth=MCPOAuthConfig(
grant_type="client_credentials",
client_id="env:MCP_CLIENT_ID",
client_secret="env:MCP_CLIENT_SECRET",
scopes=["mcp:tools"],
),
)
```
OAuth grant to use when no static `access_token` is supplied
OAuth client id. Optional for `authorization_code` when the server supports dynamic client registration
OAuth client secret. Required for `client_credentials`
Scopes to request, e.g. `['mcp:tools', 'offline_access']`
Loopback redirect URI used to capture the authorization code
Client name sent during dynamic client registration
Client homepage sent during dynamic client registration
Explicit authorization endpoint. Discovered automatically when omitted
Explicit token endpoint. Discovered automatically when omitted
Pre-obtained access token. When set, no OAuth flow is performed
Pre-obtained refresh token, paired with `access_token`
File used to cache OAuth tokens. Defaults to `~/.swarms/mcp_auth/.json`
Persist tokens to disk so the browser flow is only run once
Open the system browser for the authorization step. When `False` the URL is logged instead
Seconds to wait for the user to complete the browser flow
## Agent Error Schemas
Exception classes raised by agents. All of them are plain Python exceptions — not Pydantic models — so they are caught with ordinary `try`/`except`.
Two independent hierarchies are exported:
```
AgentError AgentMCPError
├── AgentInitializationError ├── AgentMCPConnectionError
├── AgentRunError └── AgentMCPToolError
├── AgentLLMError
├── AgentLLMInitializationError
└── AgentToolExecutionError
```
`AgentMCPError` inherits from `Exception`, **not** from `AgentError`. Catching `AgentError` will not catch MCP failures — catch both if you want blanket coverage.
| Exception | Raised when |
| ----------------------------- | ---------------------------------------------------------------------------------- |
| `AgentError` | Base class for all agent-related exceptions |
| `AgentInitializationError` | The agent fails to initialize; check configuration and parameters |
| `AgentRunError` | The agent errors during execution; check the task and environment |
| `AgentLLMError` | There is an issue with the language model; verify availability and compatibility |
| `AgentLLMInitializationError` | The LLM fails to initialize; check configuration and parameters |
| `AgentToolExecutionError` | The agent fails to execute a tool; check the tool's configuration and availability |
| `AgentMCPError` | Base class for MCP-related failures |
| `AgentMCPConnectionError` | Connecting to an MCP server fails |
| `AgentMCPToolError` | An MCP tool call fails |
```python theme={null}
from swarms import Agent
from swarms.schemas import (
AgentError,
AgentLLMError,
AgentMCPConnectionError,
AgentMCPError,
)
agent = Agent(agent_name="Analyst", model_name="gpt-5.4", max_loops=1)
try:
result = agent.run("Summarise Q4 earnings.")
except AgentLLMError as e:
print(f"Model problem: {e}")
except AgentMCPConnectionError as e:
print(f"Could not reach the MCP server: {e}")
except (AgentError, AgentMCPError) as e:
print(f"Agent failed: {e}")
```
## Planner/Worker Schemas
Schemas used by `PlannerWorkerSwarm` to represent tasks in the shared task queue.
### TaskPriority
`IntEnum` of task priority levels: `LOW = 0`, `NORMAL = 1`, `HIGH = 2`, `CRITICAL = 3`.
### PlannerTaskStatus
`str, Enum` of task statuses: `PENDING`, `CLAIMED`, `RUNNING`, `COMPLETED`, `FAILED`, `CANCELLED`.
Valid transitions:
```
PENDING -> CLAIMED -> RUNNING -> COMPLETED
PENDING -> CLAIMED -> RUNNING -> FAILED -> PENDING (retry)
any non-terminal -> CANCELLED
```
### PlannerTask
A single task in the shared planner-worker task queue. Created by planner agents, consumed by worker agents. The `version` field enables optimistic concurrency control.
```python theme={null}
from swarms.schemas import PlannerTask, TaskPriority
task = PlannerTask(
title="Research competitors",
description="Gather competitor pricing data",
priority=TaskPriority.HIGH,
)
```
Unique task identifier
Short, descriptive title of the task
Detailed description of what needs to be done
Task priority level
List of task IDs that must complete before this task can start
ID of the parent task if decomposed from a larger task
Current task status
Name of the worker agent that claimed this task
Result of task execution
Error message if task failed
Number of retry attempts so far
Maximum retry attempts before permanent failure
Optimistic concurrency version counter
Unix timestamp of task creation
Unix timestamp of task completion
Arbitrary metadata
### PlannerTaskOutput
A single task definition as output from a planner agent.
Short, descriptive title
Detailed description of what a worker agent should do
Priority: 0=LOW, 1=NORMAL, 2=HIGH, 3=CRITICAL
Titles of other tasks in this plan that must complete first
### PlannerTaskSpec
Structured output from a planner agent: a plan narrative plus a list of concrete tasks.
```python theme={null}
from swarms.schemas import PlannerTaskOutput, PlannerTaskSpec
spec = PlannerTaskSpec(
plan="Research the market, then summarise the findings.",
tasks=[
PlannerTaskOutput(
title="Research competitors",
description="Gather competitor pricing data",
priority=2,
),
PlannerTaskOutput(
title="Write summary",
description="Summarise the pricing research",
depends_on_titles=["Research competitors"],
),
],
)
```
Narrative explanation of the plan: what needs to be done, in what order, and why
List of concrete tasks to add to the queue
### CycleVerdict
Structured output from the judge agent after evaluating a planning cycle.
True if the overall goal has been satisfactorily achieved
Quality score 0-10 of the combined results
Summary assessment of the cycle results
Specific gaps or issues that need addressing in a follow-up cycle
Instructions for the planner if another cycle is needed
True if accumulated drift or systemic issues require a complete restart rather than incremental gap-filling. When True, all prior tasks are discarded and the planner begins from scratch with the original goal plus judge feedback
## Example: MCP Connection Setup
```python theme={null}
from swarms import Agent
from swarms.schemas import MCPConnection
# Describe a server with a full connection object
filesystem_mcp = MCPConnection(
url="http://localhost:8000/mcp",
name="filesystem",
timeout=30,
)
agent = Agent(
agent_name="MultiTool-Agent",
mcp_url=filesystem_mcp,
model_name="gpt-5.4",
)
# For multiple servers, Agent takes a list of URL strings via `mcp_urls`
# (not MCPConnection objects):
agent = Agent(
agent_name="MultiServer-Agent",
mcp_urls=["http://localhost:8000/mcp", "http://localhost:8001/mcp"],
model_name="gpt-5.4",
)
```
## Example: Tracking Planner Tasks
```python theme={null}
import time
from swarms.schemas import PlannerTask, PlannerTaskStatus, TaskPriority
queue = [
PlannerTask(
title="Collect filings",
description="Download the last four 10-Q filings",
priority=TaskPriority.HIGH,
),
PlannerTask(
title="Summarise filings",
description="Write a one-page summary of the filings",
),
]
# A worker claims and completes the first task
task = queue[0]
task.status = PlannerTaskStatus.RUNNING
task.assigned_worker = "Worker-1"
task.result = "Downloaded 4 filings."
task.status = PlannerTaskStatus.COMPLETED
task.completed_at = time.time()
task.version += 1
print(f"{task.id}: {task.status.value} by {task.assigned_worker}")
```
## Best Practices
1. **Type Safety**: Use the provided schemas for type-safe data handling
2. **Validation**: Leverage Pydantic's validation to catch errors early
3. **Serialization**: Use `.model_dump()` and `.model_dump_json()` for serialization
4. **Error Handling**: Catch the narrowest agent exception that fits, and remember `AgentError` and `AgentMCPError` are separate hierarchies
5. **MCP Configuration**: Use `MCPConnection` for consistent tool integration, and `MCPOAuthConfig` with `"env:VAR"` references instead of hardcoded secrets
6. **Concurrency**: Bump `PlannerTask.version` on every mutation so optimistic concurrency checks work
## Schema Inheritance
The Pydantic models above (`MCPConnection`, `MCPOAuthConfig`, `PlannerTask`, `PlannerTaskOutput`, `PlannerTaskSpec`, `CycleVerdict`) inherit from Pydantic's `BaseModel`, providing:
* Automatic validation
* JSON serialization/deserialization
* Schema generation
* IDE autocomplete support
* Type checking
```python theme={null}
from swarms.schemas import PlannerTask
task = PlannerTask(title="Research", description="Do research")
# Serialization
task_dict = task.model_dump()
task_json = task.model_dump_json(indent=2)
# Deserialization
task_from_dict = PlannerTask(**task_dict)
task_from_json = PlannerTask.model_validate_json(task_json)
```
# SelfMoASeq
Source: https://docs.swarms.world/api/self-moa-seq
Sequential Self-Mixture of Agents that generates multiple candidate responses and synthesizes them using a sliding window approach
## Overview
`SelfMoASeq` (Self-MoA-Seq: Sequential Self-Mixture of Agents) is an ensemble method that generates multiple candidate responses from a single high-performing model and synthesizes them sequentially using a sliding window approach. This keeps context within bounds while leveraging diversity across samples for a high-quality final output.
* **Phase 1**: Generate `num_samples` responses using a proposer agent.
* **Phase 2**: Aggregate responses in windows with an aggregator agent, biasing toward the current best.
* **Phase 3**: Iterate until all samples are processed or `max_loops` is reached.
## Installation
```bash theme={null}
pip install -U swarms
```
## Attributes
Human-readable name for this orchestrator
Short description of the orchestrator
Base model used when specific proposer/aggregator models are not provided
Sampling temperature for the proposer; must be in \[0, 2]
Total window size used during aggregation. Must be at least 2.
Number of slots reserved for the current best (and possibly other fixed items) in the window. Must be less than `window_size`.
Maximum aggregation loops. Must be at least 1.
Token budget to consider for downstream consumers. Not enforced internally.
Number of candidate responses to generate overall; must be at least 2
Enable internal logging via `loguru`
Log level string
If True, prints a run summary after completion
Overrides the model for the proposer agent; falls back to `model_name` if not provided
Overrides the model for the aggregator agent; falls back to `model_name` if not provided
Stored and range-validated (must be at least 0) at construction time. Not currently applied to retry any operation.
Stored and range-validated (must be at least 0) at construction time. Not currently applied to retry any operation.
Stored and range-validated (must be at least 1) at construction time. Not currently applied to retry any operation.
Stored and range-validated (must be at least `retry_delay`) at construction time. Not currently applied to retry any operation.
Accepted by the constructor but not currently stored or forwarded to the proposer/aggregator agents.
Top-p (nucleus) sampling parameter passed to the model. Left unset when `None`.
**Raises:**
* `ValueError` for invalid parameter ranges (e.g., `window_size < 2`, `reserved_slots >= window_size`, temperature outside \[0, 2], etc.)
## Methods
### run()
Execute the full Self-MoA-Seq process: sample generation, sliding-window aggregation, and final synthesis.
```python theme={null}
def run(self, task: str) -> Dict[str, Any]
```
**Parameters:**
* `task` (str): The task to process; must be a non-empty string
**Returns:** A dictionary with the following keys:
| Key | Type | Description |
| ------------------- | ---------------- | -------------------------------------------- |
| `final_output` | `str` | The final synthesized best response |
| `all_samples` | `List[str]` | All generated candidate responses |
| `aggregation_steps` | `int` | Number of aggregation iterations executed |
| `metrics` | `Dict[str, Any]` | Snapshot of performance metrics for this run |
| `task` | `str` | Echoes the original task |
| `timestamp` | `str` | ISO 8601 timestamp of completion |
**Raises:**
* `ValueError` if `task` is not a non-empty string
* Propagates any exceptions from generation/aggregation without retrying
### get\_metrics()
Get a snapshot of the internal metrics counters.
```python theme={null}
def get_metrics(self) -> Dict[str, Any]
```
**Returns:** A copy of the current metrics dictionary
### to\_dict()
Inherited from `SerializableMixin`. Serializes the instance's `__dict__` into a JSON-friendly dictionary (callables are represented by name/docstring, nested objects with their own `to_dict()` are recursed into, non-serializable values are stringified).
```python theme={null}
def to_dict(self) -> Dict[str, Any]
```
**Returns:** A dictionary representation of the instance's attributes
### Internal Methods
Methods prefixed with `_` are internal but documented here for completeness.
### \_generate\_samples()
Generate `num_samples` candidate responses using the proposer agent.
```python theme={null}
def _generate_samples(self, task: str, num_samples: int) -> List[str]
```
**Parameters:**
* `task` (str): The task description to pass to the proposer agent
* `num_samples` (int): Number of samples to generate
**Returns:** The generated samples in generation order
### \_format\_aggregation\_prompt()
Create the prompt that the aggregator agent will receive for a given window.
```python theme={null}
def _format_aggregation_prompt(self, task: str, samples: List[str], best_so_far: Optional[str] = None) -> str
```
**Parameters:**
* `task` (str): The original task string
* `samples` (List\[str]): Window of candidate responses to synthesize
* `best_so_far` (Optional\[str]): Previously synthesized best output, if any
**Returns:** Aggregation prompt text to be sent to the aggregator agent
### \_aggregate\_window()
Aggregate a window of samples using the aggregator agent, biased by `best_so_far`.
```python theme={null}
def _aggregate_window(self, task: str, window_samples: List[str], best_so_far: Optional[str] = None) -> str
```
**Parameters:**
* `task` (str): The original task string
* `window_samples` (List\[str]): Current window, typically `[best_output] + current_window`
* `best_so_far` (Optional\[str]): Current best aggregation to bias the synthesizer
**Returns:** The synthesized output for this window
## Usage Examples
### Basic Usage
```python theme={null}
from swarms import SelfMoASeq
# Initialize
moa_seq = SelfMoASeq(
model_name="gpt-5.4",
temperature=0.7,
window_size=6,
verbose=True,
num_samples=4,
)
# Run
task = (
"Describe an effective treatment plan for a patient with a broken rib. "
"Include immediate care, pain management, expected recovery timeline, and potential complications to watch for."
)
result = moa_seq.run(task)
print(result)
```
### Medical Diagnosis with High Sample Count
This example demonstrates using SelfMoASeq for a complex medical diagnosis task with a larger number of samples for comprehensive analysis.
```python theme={null}
from swarms import SelfMoASeq
# Initialize with medical-focused configuration
medical_moa = SelfMoASeq(
model_name="claude-sonnet-4-6",
temperature=0.8, # Higher creativity for diverse medical perspectives
window_size=8, # Larger window for complex medical reasoning
num_samples=12, # More samples for comprehensive analysis
max_loops=15,
verbose=True,
proposer_model_name="claude-sonnet-4-6", # Use same model for consistency
aggregator_model_name="claude-sonnet-4-6"
)
# Complex medical case
medical_case = """
Patient: 45-year-old female
Symptoms:
- Chest pain for 3 days, worse with deep breathing
- Shortness of breath
- Low-grade fever (100.2°F)
- Recent travel to Southeast Asia
- History of smoking (quit 5 years ago)
Vital signs: BP 140/90, HR 95, RR 22, O2 sat 94% on room air
Physical exam: Decreased breath sounds in right lower lobe, no JVD, no peripheral edema
Lab results pending: CBC, CMP, D-dimer, troponin
Chest X-ray: Small pleural effusion on right side
Provide a comprehensive differential diagnosis, immediate management plan,
and follow-up recommendations.
"""
result = medical_moa.run(medical_case)
print("Medical Diagnosis Analysis:")
print("=" * 50)
print(result["final_output"])
print(f"\nGenerated {len(result['all_samples'])} samples in {result['aggregation_steps']} iterations")
print(f"Execution time: {result['metrics']['execution_time_seconds']:.2f} seconds")
```
### Creative Writing with Different Models
This example shows how to use different models for the proposer and aggregator, with a creative writing task.
```python theme={null}
from swarms import SelfMoASeq
# Initialize with different models for proposer and aggregator
creative_moa = SelfMoASeq(
model_name="gpt-5.4", # Base model (fallback)
temperature=1.2, # High creativity for writing
window_size=4, # Smaller window for focused synthesis
num_samples=6, # Moderate number of samples
max_loops=8,
verbose=True,
proposer_model_name="claude-sonnet-4-6", # Creative model for generation
aggregator_model_name="gpt-5.4", # Efficient model for synthesis
max_retries=2,
retry_delay=0.5
)
# Creative writing prompt
writing_prompt = """
Write a compelling opening chapter for a science fiction novel set in 2150.
The story should involve:
- A protagonist who discovers they can manipulate time in small ways
- A mysterious organization that's been monitoring them
- A world where AI and humans coexist but tensions are rising
- An unexpected twist that challenges the reader's assumptions
Focus on:
- Strong character development
- Immersive world-building
- A hook that makes readers want to continue
- Balance between action and character moments
"""
result = creative_moa.run(writing_prompt)
print("Creative Writing Result:")
print("=" * 40)
print(result["final_output"])
print(f"\nWriting samples generated: {len(result['all_samples'])}")
print(f"Synthesis iterations: {result['aggregation_steps']}")
```
## Retry Configuration
The constructor accepts `max_retries`, `retry_delay`, `retry_backoff_multiplier`, and `retry_max_delay`, and validates them in `setup()` (e.g. `max_retries >= 0`, `retry_backoff_multiplier >= 1`, `retry_max_delay >= retry_delay`). These values are stored on the instance but are not currently used to retry `run()`, `_generate_samples()`, or `_aggregate_window()` — exceptions from those methods are logged and re-raised immediately without a retry loop.
## When to Choose SelfMoASeq
Choose `SelfMoASeq` when you need:
* High-quality outputs that benefit from multiple perspectives
* To work within context length constraints
* Reliable, production-ready ensemble methods
* Fine-grained control over the generation and synthesis process
* Comprehensive observability and error handling
For simpler tasks or when context limits are not a concern, consider using single-agent approaches or other ensemble methods like `MixtureOfAgents` for more straightforward aggregation strategies.
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/self_moa_seq.py)
# SequentialWorkflow
Source: https://docs.swarms.world/api/sequential-workflow
A workflow system for executing agents in a sequential, ordered chain
## Overview
The `SequentialWorkflow` class orchestrates the execution of a sequence of agents in a defined workflow. This class enables the construction and execution of a workflow where multiple agents (or callables) are executed in a specified order, passing tasks and optional data through the chain.
## Key Features
* **Sequential Execution**: Agents execute one after another in a defined order
* **Synchronous and Asynchronous Support**: Both blocking and non-blocking execution modes
* **Batched Processing**: Execute multiple tasks through the same workflow
* **Concurrent Task Processing**: Run multiple tasks concurrently using thread pools
* **Team Awareness**: Agents can be aware of their position in the team structure
* **Auto-save Support**: Automatically save conversation history to workspace
* **Flexible Output Types**: Support for various output formats (dict, list, string)
## Installation
```bash theme={null}
pip install -U swarms
```
## Class Definition
```python theme={null}
class SequentialWorkflow:
def __init__(
self,
id: str = "sequential_workflow",
name: str = "SequentialWorkflow",
description: str = "Sequential Workflow, where agents are executed in a sequence.",
agents: List[Union[Agent, Callable]] = None,
max_loops: int = 1,
output_type: OutputType = "dict",
shared_memory_system: callable = None,
multi_agent_collab_prompt: bool = False,
collab_prompt: Optional[str] = None,
team_awareness: bool = False,
autosave: bool = True,
verbose: bool = False,
drift_detection: bool = False,
drift_threshold: float = 0.75,
drift_model: str = "claude-sonnet-4-5",
drift_max_retries: int = 3,
*args,
**kwargs,
)
```
## Parameters
Unique identifier for the workflow instance
Human-readable name for the workflow
Description of the workflow's purpose
List of agents or callables to execute in sequence. Cannot be None or empty.
Maximum number of times to execute the workflow. Must be greater than 0.
Format of the output from the workflow. Options include "dict", "list", "str", etc.
Optional callable for managing shared memory between agents
If True, each agent receives a collaboration preamble as a system turn for the
duration of the run.
Overrides the default preamble text. Ignored unless `multi_agent_collab_prompt`
is `True`.
This used to append the preamble to every agent's `system_prompt` with `+=`, on
the caller's live `Agent` objects, at construction time — so constructing the
workflow twice appended it twice, and the text never reached the model because
the prompt is baked into the LLM when it is built. It is now passed through to
`AgentRearrange` and delivered as a system turn instead.
Whether agents are aware of the team structure and their position
Whether to enable autosaving of conversation history to workspace
Whether to enable verbose logging
If `True`, a judge agent scores the final output's semantic alignment with the original task after the pipeline completes. If the score falls below `drift_threshold`, the pipeline reruns and the cycle repeats until the score meets the threshold. If the judge output cannot be parsed, drift checking is skipped and the last result is returned as-is.
Minimum alignment score (0.0–1.0) to consider the output acceptable. A warning is logged when the score falls below this value, and the pipeline reruns. Used only when `drift_detection=True`.
Model used by the drift detection judge agent. Used only when `drift_detection=True`.
Maximum number of pipeline reruns when the alignment score stays below
`drift_threshold`. Used only when `drift_detection=True`. Must be `>= 0`;
a negative value raises `ValueError`.
## Methods
### `run(task, img=None, imgs=None, *args, **kwargs)`
Executes a specified task through the agents in the dynamically constructed flow.
If `drift_detection` is configured, a judge agent scores the final output's semantic alignment with the original task after the pipeline completes. If the score falls below `drift_threshold`, the pipeline reruns and the cycle repeats until the score meets the threshold.
The task for the agents to execute
An optional image input forwarded to every agent that supports it
Optional list of images. Accepted for API compatibility; only `img` is currently forwarded to the underlying flow.
The final result, formatted per `output_type`
### `run_batched(tasks)`
Executes a batch of tasks through the agents sequentially.
A list of tasks for the agents to execute. Must be a non-empty list of strings.
A list of final results after processing through all agents
### `run_async(task)`
Executes the specified task through the agents asynchronously.
The task for the agents to execute. Must be a non-empty string.
The final result after processing through all agents
### `async run_concurrent(tasks)`
Executes a batch of tasks through the agents concurrently using ThreadPoolExecutor. This method is `async` and must be awaited.
A list of tasks for the agents to execute. Must be a non-empty list of strings.
A list of final results after processing through all agents
### `run_stream(task, img=None, with_events=False, **kwargs)`
Stream tokens from each agent in pipeline order, in real time. Each agent's tokens are yielded the moment the LLM produces them; once an agent finishes, its full output is handed off to the next agent — the same hand-off as `run()`, just streamed.
Delegates to `AgentRearrange.run_stream` internally.
Initial task passed to the first agent in the pipeline.
Optional image input forwarded to every agent.
When `False`, yield plain token strings. When `True`, yield structured event dicts (`agent_start`, `token`, `agent_end`) — useful for per-agent UI panels or attributing each token to its emitting agent.
Sync generator. Yields plain token strings by default, or event dicts when `with_events=True`.
```python theme={null}
for token in workflow.run_stream("Analyse NVDA"):
print(token, end="", flush=True)
```
### `arun_stream(task, img=None, with_events=False, **kwargs)`
Async generator version of `run_stream`. Drop-in for any async caller (FastAPI's `StreamingResponse`, async background workers, etc.). Same parameter and yield semantics as the sync version.
Async generator. Yields plain token strings by default, or event dicts when `with_events=True`.
```python theme={null}
async for token in workflow.arun_stream("Analyse NVDA"):
print(token, end="", flush=True)
```
#### Structured events
When called with `with_events=True`, both methods yield three event types:
| Type | Fields | When emitted |
| ------------- | ----------------- | ------------------------------------------------- |
| `agent_start` | `agent` | Right before an agent begins streaming |
| `token` | `agent`, `token` | For every token the agent emits |
| `agent_end` | `agent`, `output` | After the agent finishes; carries the full output |
```python theme={null}
async for evt in workflow.arun_stream(task, with_events=True):
if evt["type"] == "agent_start":
print(f"--- {evt['agent']} starting ---")
elif evt["type"] == "token":
print(evt["token"], end="", flush=True)
elif evt["type"] == "agent_end":
print(f"\n--- {evt['agent']} finished ({len(evt['output'])} chars) ---")
```
`max_loops > 1` and `drift_detection` are not applied in streaming mode. Use `run()` if you need those.
### `sequential_flow()`
Constructs a string representation of the agent execution order.
A string showing the order of agent execution (e.g., "AgentA -> AgentB -> AgentC")
### `reliability_check()`
Validates the workflow configuration and prepares agents for execution.
**Raises:**
* `ValueError`: If the agents list is None or empty, or if max\_loops is set to 0
## Attributes
| Attribute | Type | Description |
| --------------------------- | ------------------------------ | ----------------------------------------------------------------------- |
| `id` | str | Unique identifier for the workflow instance |
| `name` | str | Human-readable name for the workflow |
| `description` | str | Description of the workflow's purpose |
| `agents` | List\[Union\[Agent, Callable]] | List of agents or callables to execute in sequence |
| `max_loops` | int | Maximum number of times to execute the workflow |
| `output_type` | OutputType | Format of the output from the workflow |
| `shared_memory_system` | callable | Optional shared memory helper |
| `multi_agent_collab_prompt` | bool | Whether each agent receives the collaboration preamble as a system turn |
| `team_awareness` | bool | Whether team-awareness is enabled on the underlying `AgentRearrange` |
| `autosave` | bool | Whether conversation history is autosaved to disk |
| `verbose` | bool | Whether verbose logging is on |
| `drift_threshold` | float | Minimum alignment score required when `drift_detection=True` |
| `drift_agent` | Optional\[Agent] | Judge agent used for drift detection; `None` when disabled |
| `swarm_workspace_dir` | Optional\[str] | Workspace directory used for autosave; populated by `_setup_autosave()` |
| `flow` | str | String representation of the agent execution order |
| `agent_rearrange` | AgentRearrange | Internal helper for managing agent execution |
## Usage Examples
### Basic Sequential Workflow
```python theme={null}
from swarms import Agent, SequentialWorkflow
# Create specialized agents
researcher = Agent(
agent_name="Researcher",
model_name="claude-sonnet-4-6",
temperature=0.5,
max_loops=1,
system_prompt="You are a research specialist. Gather and analyze information."
)
writer = Agent(
agent_name="Writer",
model_name="claude-sonnet-4-6",
temperature=0.5,
max_loops=1,
system_prompt="You are a content writer. Create engaging content based on research."
)
editor = Agent(
agent_name="Editor",
model_name="claude-sonnet-4-6",
temperature=0.5,
max_loops=1,
system_prompt="You are an editor. Review and polish the content."
)
# Create sequential workflow
workflow = SequentialWorkflow(
name="Content Creation Pipeline",
description="Research -> Write -> Edit pipeline",
agents=[researcher, writer, editor],
max_loops=1,
verbose=True
)
# Run the workflow
result = workflow.run("Create a blog post about artificial intelligence")
print(result)
```
### Batched Task Processing
```python theme={null}
# Process multiple tasks through the same workflow
tasks = [
"Analyze the impact of AI on healthcare",
"Discuss the future of renewable energy",
"Examine cybersecurity trends"
]
results = workflow.run_batched(tasks)
for task, result in zip(tasks, results):
print(f"Task: {task}")
print(f"Result: {result}")
print("-" * 50)
```
### Concurrent Task Execution
`run_concurrent` is `async`, so it must be awaited:
```python theme={null}
import asyncio
# Run multiple tasks concurrently
tasks = [
"Research quantum computing",
"Research blockchain technology",
"Research machine learning"
]
async def main():
results = await workflow.run_concurrent(tasks)
print(f"Processed {len(results)} tasks concurrently")
return results
results = asyncio.run(main())
```
### Async Execution
```python theme={null}
import asyncio
async def process_task():
result = await workflow.run_async("Analyze climate change solutions")
return result
# Run async
result = asyncio.run(process_task())
print(result)
```
### With Team Awareness
```python theme={null}
# Create workflow with team awareness
workflow = SequentialWorkflow(
name="Collaborative Pipeline",
agents=[researcher, writer, editor],
team_awareness=True, # Agents know about each other
multi_agent_collab_prompt=True, # Add collaboration prompt
verbose=True
)
result = workflow.run("Create a comprehensive market analysis")
```
### Custom Output Types
```python theme={null}
# Different output formats
workflow_dict = SequentialWorkflow(
agents=[researcher, writer],
output_type="dict" # Returns dict format
)
workflow_list = SequentialWorkflow(
agents=[researcher, writer],
output_type="list" # Returns list format
)
workflow_str = SequentialWorkflow(
agents=[researcher, writer],
output_type="str" # Returns string format
)
```
### With Autosave
```python theme={null}
import os
# Set workspace directory for autosave
os.environ["WORKSPACE_DIR"] = "./my_workspace"
workflow = SequentialWorkflow(
name="SavedWorkflow",
agents=[researcher, writer, editor],
autosave=True, # Automatically save conversation history
verbose=True
)
result = workflow.run("Generate a report")
# Conversation history saved to ./my_workspace/swarms/SequentialWorkflow/
```
## Error Handling
```python theme={null}
try:
workflow = SequentialWorkflow(
agents=[researcher, writer],
max_loops=1
)
result = workflow.run("Process this task")
except ValueError as e:
print(f"Configuration error: {e}")
except Exception as e:
print(f"Execution error: {e}")
```
## Best Practices
1. **Agent Design**: Ensure each agent has a clear, specific role in the sequence
2. **Error Handling**: Use try-except blocks around workflow execution
3. **Verbose Mode**: Enable verbose logging during development for debugging
4. **Autosave**: Enable autosave for important workflows to preserve conversation history
5. **Task Clarity**: Provide clear, specific tasks to get the best results
6. **Resource Management**: Use `run_concurrent` for I/O-bound tasks to improve performance
7. **Team Awareness**: Enable team awareness for complex workflows where context matters
## Common Use Cases
* **Content Creation Pipelines**: Research -> Write -> Edit workflows
* **Data Processing**: Extract -> Transform -> Load (ETL) pipelines
* **Analysis Workflows**: Collect -> Analyze -> Report sequences
* **Quality Assurance**: Create -> Review -> Approve chains
* **Multi-Stage Reasoning**: Break complex problems into sequential steps
## Related Classes
* [AgentRearrange](/api/agent-rearrange): For more complex, non-linear agent orchestration
* [ConcurrentWorkflow](/api/concurrent-workflow): For parallel agent execution
* [GraphWorkflow](/api/graph-workflow): For DAG-based agent workflows
* [Agent](/api/agent): The base agent class used in workflows
# SkillsManager
Source: https://docs.swarms.world/api/skills-manager
Loads Agent Skills from disk and renders them into an agent system prompt
## Overview
`SkillsManager` implements Agent Skills: `SKILL.md` files on disk, discovered and folded into an agent's system prompt. It supports the tiered loading model — name/description metadata kept in memory for context-aware activation (Tier 1), and a skill's full body pulled on demand (Tier 2).
Every `Agent` builds one automatically as `agent.skills`. It is also usable standalone.
```python theme={null}
from swarms import Agent
agent = Agent(agent_name="Analyst", skills_dir="./skills")
agent.run("Build a DCF model") # relevant skills load into the prompt
```
## Import
```python theme={null}
from swarms.agents.skills_manager import SkillsManager
```
## Design
The manager **never mutates the agent**. It returns prompt text and the caller decides what to do with it, which keeps prompt mutation in one visible place and makes the class testable on its own:
```python theme={null}
# Agent.handle_skills is a single line
self.system_prompt += self.skills.prompt_for_task(task)
```
## Constructor
```python theme={null}
SkillsManager(skills_dir=None, similarity_threshold=0.3)
```
Directory containing skill folders, each holding a `SKILL.md` file with YAML frontmatter. `None` disables skills entirely.
Minimum task/skill similarity for a skill to be selected during dynamic loading.
### Attributes
The configured skills directory.
Metadata for the skills loaded so far.
Read-only. `True` when a directory is configured **and** exists on disk.
## Skill format
Each skill is a folder containing a `SKILL.md` with YAML frontmatter:
```
skills/
├── financial-analysis/
│ └── SKILL.md
└── code-review/
└── SKILL.md
```
```markdown SKILL.md theme={null}
---
name: financial-analysis
description: DCF modeling, ratio analysis, and valuation techniques
---
When performing financial analysis, always start by identifying the
company's revenue drivers, then build a three-statement model...
```
Malformed skills are skipped, never fatal — a file with no frontmatter, unterminated frontmatter, invalid YAML, or one that cannot be read is logged and passed over. A skill with no `name` in its frontmatter falls back to its folder name.
## Methods
### prompt\_for\_task
```python theme={null}
def prompt_for_task(task: Optional[str] = None) -> str
```
Build the skills prompt section. The task argument selects the loading strategy:
When provided, only skills whose description is similar to the task are loaded (dynamic). When `None`, every skill is loaded (static).
Returns the formatted prompt section, or `""` when nothing loaded. Populates `metadata` as a side effect.
```python theme={null}
skills = SkillsManager(skills_dir="./skills")
section = skills.prompt_for_task("Build a DCF valuation model")
# only financial-analysis is selected
```
Uses `DynamicSkillsLoader`, which scores each skill's description against the task by cosine similarity and keeps those above `similarity_threshold`. The loader is built lazily on first use and reused afterwards.
```python theme={null}
section = skills.prompt_for_task(None)
# every skill in the directory is included
```
### load\_metadata
```python theme={null}
def load_metadata(skills_dir: Optional[str] = None) -> List[Dict[str, str]]
```
Tier 1 loading — scan a directory and return one dict per skill with `name`, `description`, `path`, and `content`. Defaults to the configured directory. Returns `[]` when the directory is missing. Entries are returned in sorted order for determinism.
`load_metadata()` **returns** metadata without assigning it to `self.metadata`. Only `prompt_for_task()` populates that attribute — and `load_full_skill()` reads from it. Calling `load_metadata()` alone and then `load_full_skill()` will always return `None`.
### build\_prompt
```python theme={null}
def build_prompt(skills: List[Dict[str, str]]) -> str
```
Render skill metadata as a prompt section. Returns `""` for an empty list. The `# Available Skills` header is emitted exactly once, followed by each skill's name, description, and body.
### load\_full\_skill
```python theme={null}
def load_full_skill(skill_name: str) -> Optional[str]
```
Tier 2 loading — the complete markdown below the frontmatter for one skill, found by name in `metadata`. Returns `None` when the skill is unknown or the file has since become unreadable.
### set\_skills\_dir
```python theme={null}
def set_skills_dir(skills_dir: Optional[str]) -> None
```
Point the manager at a different directory, discarding cached `metadata` and the dynamic loader.
## Agent integration
| `Agent` member | Behavior |
| --------------------------------------------- | ---------------------------------------------------------- |
| `agent.skills` | The `SkillsManager` instance |
| `agent.skills_dir` | Property reading through to `skills.skills_dir` (settable) |
| `agent.skills_metadata` | Property reading through to `skills.metadata` (settable) |
| `agent.handle_skills(task=None)` | Appends `prompt_for_task(task)` to the system prompt |
| `agent.load_skills_metadata(skills_dir=None)` | Delegates to `load_metadata()` |
| `agent.load_full_skill(name)` | Delegates to `load_full_skill()` |
Skills load at `run()` time, not construction, so an agent's recorded system prompt at init does not yet include them.
## Standalone use
```python theme={null}
from swarms.agents.skills_manager import SkillsManager
skills = SkillsManager(skills_dir="./skills")
print(skills.enabled) # True
print([s["name"] for s in skills.load_metadata()])
print(skills.prompt_for_task("review this Python code"))
print(skills.load_full_skill("code-review"))
```
## Related
Guide to authoring and using skills
The class that owns the manager
# SocialAlgorithms
Source: https://docs.swarms.world/api/social-algorithms
A flexible framework for defining custom social algorithms that control how agents communicate and interact in multi-agent systems
## Overview
The Social Algorithms framework provides a flexible system for defining custom social algorithms that control how agents communicate and interact with each other in multi-agent systems. This framework allows you to upload any arbitrary social algorithm as a callable that defines the sequence of communication between agents.
| Feature | Description |
| ----------------------------- | ------------------------------------------------------------- |
| Custom Communication Patterns | Define custom communication patterns between agents |
| Complex Multi-Agent Workflows | Implement complex multi-agent workflows |
| Emergent Behaviors | Create emergent behaviors through agent interactions |
| Communication Logging | Log and track all communication between agents |
| Timeout & Error Handling | Execute algorithms with timeout protection and error handling |
## Installation
```bash theme={null}
pip install -U swarms
```
## Class Definition
```python theme={null}
from swarms import SocialAlgorithms
```
## Attributes
Unique identifier for the algorithm. If None, a UUID will be generated.
Human-readable name for the algorithm.
Description of what the algorithm does.
List of agents that will participate in the algorithm.
The callable that defines the communication sequence. Must accept (agents, task, \*\*kwargs) as parameters.
Maximum time allowed for algorithm execution in seconds.
Format of the output from the algorithm.
Whether to enable verbose logging.
`enable_communication_logging`, `parallel_execution` and `max_workers` were
removed. Agent messages are now always recorded, and the two parallel options
were stored but never used. Passing them is accepted and ignored.
## Attributes
The transcript of every agent message, kept across runs. Read it with the
standard Conversation API, for example `social_alg.conversation.get_str()`.
### Constructor Validation
The constructor calls `_validate_inputs()` before returning, which raises:
| Exception | Condition |
| ----------------------- | ------------------------------------------------------------------------ |
| `ValueError` | `agents` is empty, or any element of `agents` is not an `Agent` instance |
| `ValueError` | `max_execution_time` is not positive (`<= 0`) |
| `InvalidAlgorithmError` | `social_algorithm` is set but not callable |
## Methods
### run()
Execute the social algorithm with the given task.
```python theme={null}
def run(self, task: str, algorithm_args: Optional[Dict[str, Any]] = None, **kwargs) -> SocialAlgorithmResult
```
**Parameters:**
* `task` (str): The task to execute using the social algorithm.
* `algorithm_args` (Dict\[str, Any]): Additional arguments for the algorithm.
**Returns:** `SocialAlgorithmResult` — The result of executing the social algorithm.
**Raises:**
* `InvalidAlgorithmError`: If no social algorithm is defined.
* `TimeoutError`: If the algorithm execution exceeds max\_execution\_time.
***
### add\_agent()
Add an agent to the social algorithm.
```python theme={null}
def add_agent(self, agent: Agent) -> None
```
**Parameters:**
* `agent` (Agent): The agent to add.
**Raises:**
* `ValueError`: If agent is not an instance of the Agent class.
***
### remove\_agent()
Remove an agent from the social algorithm.
```python theme={null}
def remove_agent(self, agent_name: str) -> None
```
**Parameters:**
* `agent_name` (str): Name of the agent to remove.
**Raises:**
* `AgentNotFoundError`: If no agent with `agent_name` is found.
***
### get\_communication\_history()
Get the recorded agent messages, oldest first.
```python theme={null}
def get_communication_history(self) -> List[Dict[str, Any]]
```
**Returns:** The conversation messages, each a `{"role", "content", ...}` dict.
***
### clear\_communication\_history()
Clear the communication history.
```python theme={null}
def clear_communication_history(self) -> None
```
***
### get\_algorithm\_info()
Get information about the social algorithm.
```python theme={null}
def get_algorithm_info(self) -> Dict[str, Any]
```
**Returns:** Information about the algorithm including ID, name, description, agent count, and configuration.
## Data Models
### SocialAlgorithmResult
Result of executing a social algorithm.
| Attribute | Type | Description |
| ----------------------- | ---------------------- | ---------------------------------------------- |
| `algorithm_id` | `str` | Unique identifier for the algorithm |
| `execution_time` | `float` | Time taken to execute the algorithm in seconds |
| `total_steps` | `int` | Total number of communication steps |
| `successful_steps` | `int` | Number of successful communication steps |
| `failed_steps` | `int` | Number of failed communication steps |
| `communication_history` | `List[Dict[str, Any]]` | Every agent message, as conversation dicts |
| `final_outputs` | `Any` | The final output, shaped by `output_type` |
| `metadata` | `Dict[str, Any]` | Additional metadata about the execution |
Only the `SocialAlgorithms` class itself is exported from the top-level `swarms` package. `SocialAlgorithmResult` and the exception classes below must be imported from the submodule:
```python theme={null}
from swarms.structs.social_algorithms import (
SocialAlgorithmResult,
SocialAlgorithmError,
InvalidAlgorithmError,
AgentNotFoundError,
)
```
## Exception Classes
* `SocialAlgorithmError` — Base exception for social algorithm errors
* `InvalidAlgorithmError` — Raised when an invalid algorithm is provided
* `AgentNotFoundError` — Raised when a required agent is not found
## Usage Examples
### Basic Social Algorithm
```python theme={null}
from swarms import Agent, SocialAlgorithms
# Define a custom social algorithm
def custom_communication_algorithm(agents, task, **kwargs):
# Agent 1 researches the topic
research_result = agents[0].run(f"Research: {task}")
# Agent 2 analyzes the research
analysis = agents[1].run(f"Analyze this research: {research_result}")
# Agent 3 synthesizes the findings
synthesis = agents[2].run(f"Synthesize: {research_result} + {analysis}")
return {
"research": research_result,
"analysis": analysis,
"synthesis": synthesis
}
# Create agents
researcher = Agent(agent_name="Researcher", model_name="gpt-5.4")
analyst = Agent(agent_name="Analyst", model_name="gpt-5.4")
synthesizer = Agent(agent_name="Synthesizer", model_name="gpt-5.4")
# Create social algorithm
social_alg = SocialAlgorithms(
name="Research-Analysis-Synthesis",
agents=[researcher, analyst, synthesizer],
social_algorithm=custom_communication_algorithm,
verbose=True
)
# Run the algorithm
result = social_alg.run("The impact of AI on healthcare")
```
### Research and Development Team
```python theme={null}
from swarms import Agent, SocialAlgorithms
def research_development_algorithm(agents, task, **kwargs):
"""
A comprehensive R&D team algorithm with multiple phases.
"""
project_manager = next(a for a in agents if "ProjectManager" in a.agent_name)
researcher = next(a for a in agents if "Researcher" in a.agent_name)
analyst = next(a for a in agents if "Analyst" in a.agent_name)
developer = next(a for a in agents if "Developer" in a.agent_name)
tester = next(a for a in agents if "Tester" in a.agent_name)
reviewer = next(a for a in agents if "Reviewer" in a.agent_name)
# Phase 1: Project Planning
project_plan = project_manager.run(f"""
Create a comprehensive project plan for: {task}
Include objectives, deliverables, timeline, and risk assessment.
""")
# Phase 2: Research
research_findings = researcher.run(f"""
Conduct comprehensive research on: {task}
Cover current state of the art, existing solutions, and emerging trends.
""")
# Phase 3: Analysis and Design
analysis_results = analyst.run(f"""
Analyze the research findings and design the solution:
Research: {research_findings}
Include requirements analysis, architecture design, and implementation strategy.
""")
# Phase 4: Development
prototype = developer.run(f"""
Create a prototype based on the analysis:
Analysis: {analysis_results}
Requirements: {project_plan}
""")
# Phase 5: Testing
test_results = tester.run(f"""
Create test plans and execute testing:
Prototype: {prototype}
Requirements: {project_plan}
""")
# Phase 6: Final Review
final_review = reviewer.run(f"""
Conduct final review of the entire project:
Plan: {project_plan}, Research: {research_findings},
Analysis: {analysis_results}, Prototype: {prototype},
Testing: {test_results}
""")
# Phase 7: Project Closure
deliverables = project_manager.run(f"""
Create final project deliverables including executive summary,
documentation, and lessons learned.
""")
return {
"task": task,
"project_plan": project_plan,
"research": research_findings,
"analysis": analysis_results,
"prototype": prototype,
"test_results": test_results,
"review": final_review,
"deliverables": deliverables,
}
# Create specialized agents
agents = [
Agent(agent_name="ProjectManager", system_prompt="You are an experienced project manager.", model_name="gpt-5.4", max_loops=1),
Agent(agent_name="Researcher", system_prompt="You are a research specialist.", model_name="gpt-5.4", max_loops=1),
Agent(agent_name="Analyst", system_prompt="You are a systems analyst.", model_name="gpt-5.4", max_loops=1),
Agent(agent_name="Developer", system_prompt="You are a senior developer.", model_name="gpt-5.4", max_loops=1),
Agent(agent_name="Tester", system_prompt="You are a QA specialist.", model_name="gpt-5.4", max_loops=1),
Agent(agent_name="Reviewer", system_prompt="You are a technical reviewer.", model_name="gpt-5.4", max_loops=1),
]
rd_algorithm = SocialAlgorithms(
name="Research-Development-Team",
description="Complete R&D workflow with specialized team members",
agents=agents,
social_algorithm=research_development_algorithm,
verbose=True,
max_execution_time=600
)
result = rd_algorithm.run("Develop a sustainable energy management system for smart cities")
```
### Competitive Evaluation
```python theme={null}
from swarms import Agent, SocialAlgorithms
def competitive_evaluation_algorithm(agents, task, **kwargs):
"""Agents compete and are evaluated by a judge."""
if len(agents) < 3:
raise ValueError("Requires at least 3 agents (2 competitors + 1 judge)")
competitors = agents[:-1]
judge = agents[-1]
# Each competitor works on the task
competitor_results = {}
for i, competitor in enumerate(competitors):
result = competitor.run(f"Solve this task as best as you can: {task}")
competitor_results[f"competitor_{i+1}_{competitor.agent_name}"] = result
# Judge evaluates all solutions
evaluation_prompt = "Evaluate these solutions and rank them:\n\n"
for name, result in competitor_results.items():
evaluation_prompt += f"{name}:\n{result}\n\n"
evaluation_prompt += "Provide rankings, scores, and detailed feedback."
evaluation = judge.run(evaluation_prompt)
return {
"competitor_solutions": competitor_results,
"judge_evaluation": evaluation,
"task": task,
}
social_alg = SocialAlgorithms(
name="Competitive-Evaluation",
description="Competitive evaluation where agents compete and are judged",
agents=[competitor1, competitor2, judge],
social_algorithm=competitive_evaluation_algorithm,
verbose=True,
)
result = social_alg.run("Design the most efficient algorithm for sorting large datasets")
```
### Negotiation Algorithm
```python theme={null}
from swarms import Agent, SocialAlgorithms
def negotiation_algorithm(agents, task, **kwargs):
"""Agents engage in back-and-forth negotiation with mediation."""
negotiating_parties = agents[:-2]
mediator_agent = agents[-2]
legal_agent = agents[-1]
max_rounds = kwargs.get("max_rounds", 8)
# Phase 1: Initial Position Statements
current_positions = {}
for party in negotiating_parties:
initial_position = party.run(
f"As {party.agent_name}, state your initial position for: {task}"
)
current_positions[party.agent_name] = initial_position
# Phase 2: Negotiation Rounds
negotiation_history = []
for round_num in range(1, max_rounds + 1):
mediation_guidance = mediator_agent.run(
f"Analyze positions for round {round_num}"
)
round_responses = {}
for party in negotiating_parties:
response = party.run(
f"Respond to other positions in round {round_num}"
)
round_responses[party.agent_name] = response
current_positions[party.agent_name] = response
legal_review = legal_agent.run(
f"Review proposals for round {round_num}"
)
negotiation_history.append({
"round": round_num,
"mediation_guidance": mediation_guidance,
"responses": round_responses,
"legal_review": legal_review,
})
return {
"task": task,
"negotiation_history": negotiation_history,
"current_positions": current_positions,
}
```
## Advanced Features
### Communication Logging
Every `agent.run()` and `agent.talk_to()` call made while the algorithm runs is recorded into `conversation`, under the calling agent's own name. This is always on; the algorithm does not have to report anything itself.
### Timeout Protection
Algorithms are executed with timeout protection to prevent infinite loops. The default is 300 seconds (5 minutes), customizable via `max_execution_time`.
The timeout is implemented with `signal.SIGALRM`, which only works on the main
thread of the main interpreter and does not exist on Windows. Calling `run()`
from a worker thread raises `ValueError: signal only works in main thread`.
`signal.alarm` also truncates to whole seconds, so a sub-second
`max_execution_time` rounds to `alarm(0)` and disables the timeout entirely.
### Error Handling
Comprehensive error handling with `InvalidAlgorithmError`, `AgentNotFoundError`, `TimeoutError`, and graceful handling of agent execution failures.
### Output Formatting
Results can be formatted as `"dict"` (default), `"list"`, or `"str"`.
## Integration
| Component | Integration |
| ------------- | -------------------------------------------------------------------- |
| **Agents** | Use any Swarms Agent in your social algorithms |
| **Tools** | Agents can use tools within social algorithms |
| **Memory** | Agents can access long-term memory during execution |
| **Workflows** | Social algorithms can be used as steps in larger workflows |
| **Routers** | Social algorithms can be used with SwarmRouter for dynamic selection |
## Best Practices
1. **Algorithm Design**: Design algorithms to be modular and reusable. Break complex algorithms into smaller, composable functions
2. **Error Handling**: Always include proper error handling. Check for required agents and validate inputs
3. **Logging**: Use the built-in logging system to track execution and debug issues
4. **Timeout Management**: Set appropriate timeouts based on algorithm complexity
5. **Agent Roles**: Clearly define roles for each agent to ensure proper communication patterns
6. **Testing**: Test with different agent configurations and edge cases
7. **Documentation**: Document custom algorithms thoroughly, including expected inputs and outputs
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/social_algorithms.py)
# SpreadSheetSwarm
Source: https://docs.swarms.world/api/spreadsheet-swarm
A swarm that processes tasks concurrently using multiple agents and saves metadata to CSV files
## Overview
The `SpreadSheetSwarm` processes tasks concurrently across multiple agents and automatically saves execution metadata to CSV files. It supports loading agent configurations from CSV files and running tasks either from configuration or on-demand.
## Installation
```bash theme={null}
pip install -U swarms
```
## Attributes
The name of the swarm
The description of the swarm
The agents participating in the swarm. Required — the constructor runs a reliability check before any CSV loading happens, so a non-empty `agents` list must be supplied even if `load_path` is also set
Whether to enable autosave of swarm metadata
The file path to save the swarm metadata as a CSV file (auto-generated if None)
The number of times to repeat the swarm tasks
Path to a CSV file mapping `agent_name` to `task`. Call `load_from_csv()` explicitly after construction to populate per-agent tasks from it before calling `run_from_config()`
Enable verbose logging
## Methods
### run()
Run the swarm with the specified task.
```python theme={null}
def run(self, task: str = None, *args, **kwargs) -> dict
```
**Parameters:**
* `task` (str): The task to be executed by the swarm. If None, uses tasks from config
**Returns:** Dictionary containing run summary with outputs and metadata
### run\_from\_config()
Run all agents with their configured tasks concurrently.
```python theme={null}
def run_from_config(self) -> dict
```
**Returns:** Dictionary containing execution summary
### load\_from\_csv()
Load agent configurations from a CSV file.
```python theme={null}
def load_from_csv(self)
```
Expected CSV format:
```
agent_name,description,system_prompt,task,model_name,max_loops
```
### export\_to\_json()
Export the swarm outputs to JSON.
```python theme={null}
def export_to_json(self) -> str
```
**Returns:** JSON string representation of swarm outputs
### data\_to\_json\_file()
Save the swarm outputs (via `export_to_json()`) to a JSON file in the workspace directory. Called automatically after each run when `autosave=True`.
```python theme={null}
def data_to_json_file(self)
```
**Returns:** None. Writes the JSON metadata file to disk.
## Usage Examples
### Basic Usage with Agents
```python theme={null}
from swarms import Agent, SpreadSheetSwarm
# Create agents
agents = [
Agent(
agent_name="Research-Agent",
system_prompt="You are a research agent.",
model_name="openai/gpt-5.4",
),
Agent(
agent_name="Analysis-Agent",
system_prompt="You are an analysis agent.",
model_name="openai/gpt-5.4",
),
]
# Create swarm
swarm = SpreadSheetSwarm(
name="My-Swarm",
agents=agents,
max_loops=1,
autosave=True
)
# Run with a task
result = swarm.run("Analyze the latest AI trends")
print(result)
```
### Load from CSV Configuration
`agents` must be provided at construction. The constructor runs a reliability check before any CSV loading occurs, so calling `SpreadSheetSwarm(load_path="agents_config.csv", ...)` without `agents` raises `ValueError("No agents are provided.")`. Pass real `Agent` instances in `agents`, then call `load_from_csv()` explicitly to map tasks from the CSV onto those agents by `agent_name`.
Create a CSV file (`agents_config.csv`) mapping each agent name to a task:
```csv theme={null}
agent_name,description,system_prompt,task
Research-Agent,Research specialist,You are a research agent,Research quantum computing
Analysis-Agent,Data analyst,You are an analysis agent,Analyze the research findings
```
Then construct with agents, load the task mapping, and run:
```python theme={null}
swarm = SpreadSheetSwarm(
name="CSV-Swarm",
agents=agents, # non-empty list of Agent instances, e.g. from the example above
load_path="agents_config.csv",
max_loops=1
)
# Populate self.agent_tasks from the CSV (matches rows to agents by agent_name)
swarm.load_from_csv()
# Run each configured agent with its mapped task
result = swarm.run_from_config()
```
### Multiple Loops
```python theme={null}
# Run each agent multiple times
swarm = SpreadSheetSwarm(
agents=agents,
max_loops=3 # Each agent runs 3 times
)
result = swarm.run("Process this task multiple times")
```
### Custom Save Path
```python theme={null}
swarm = SpreadSheetSwarm(
name="Custom-Swarm",
agents=agents,
save_file_path="./results/swarm_outputs.csv",
autosave=True
)
result = swarm.run("Custom task")
```
### Export Results
```python theme={null}
# Run swarm
result = swarm.run("Some task")
# Export to JSON
json_output = swarm.export_to_json()
print(json_output)
# Results are automatically saved to CSV if autosave=True
```
## Output Format
The `run()` method returns a dictionary:
```python theme={null}
{
"run_id": "spreadsheet_swarm_run_abc123",
"name": "My-Swarm",
"description": "A swarm that processes tasks...",
"start_time": "2024-01-01T12:00:00",
"end_time": "2024-01-01T12:05:00",
"tasks_completed": 6,
"number_of_agents": 3,
"outputs": [
{
"agent_name": "Research-Agent",
"task": "Analyze the latest AI trends",
"result": "...",
"timestamp": "2024-01-01T12:01:00"
},
# ... more outputs
]
}
```
## CSV Output Format
Results are automatically saved to CSV with these columns:
```csv theme={null}
Run ID,Agent Name,Task,Result,Timestamp
abc-123,Research-Agent,Analyze trends,...,2024-01-01T12:00:00
abc-123,Analysis-Agent,Analyze trends,...,2024-01-01T12:00:05
```
## Features
* **Concurrent Execution**: All agents run tasks in parallel for maximum performance
* **Automatic CSV Logging**: All executions are logged to CSV files automatically
* **CSV Configuration**: Load agent configurations from CSV files
* **Multiple Loops**: Run each agent multiple times with `max_loops`
* **Workspace Integration**: Automatically uses workspace directory from environment
* **JSON Export**: Export results to JSON format
* **Metadata Tracking**: Tracks timestamps, run IDs, and execution metadata
# Multi-Agent Architectures Overview
Source: https://docs.swarms.world/api/structs-overview
A comprehensive overview of all available multi-agent architectures in Swarms, their use cases, and functionality
## Overview
Swarms provides a wide range of multi-agent architectures designed for different use cases, from simple round-robin task distribution to complex hierarchical orchestration. This page provides a comprehensive overview to help you select the right architecture for your needs.
## Installation
```bash theme={null}
pip install -U swarms
```
## Core Architectures
| Architecture | Use Case | Key Functionality |
| ------------------------------------------- | --------------------------------- | ------------------------------------------------------------------- |
| [MajorityVoting](/api/majority-voting) | Decision making through consensus | Combines multiple agent opinions and selects the most common answer |
| [AgentRearrange](/api/agent-rearrange) | Optimizing agent order | Dynamically reorders agents based on task requirements |
| [RoundRobin](/api/round-robin-swarm) | Equal task distribution | Cycles through agents in a fixed order |
| [Mixture of Agents](/api/mixture-of-agents) | Complex problem solving | Combines diverse expert agents for comprehensive analysis |
| [GroupChat](/api/group-chat) | Collaborative discussions | Simulates group discussions with multiple agents |
| [SpreadSheetSwarm](/api/spreadsheet-swarm) | Data processing | Collaborative data processing and analysis |
| [SwarmRouter](/api/swarm-router) | Task routing | Routes tasks to appropriate agents based on requirements |
| [MultiAgentRouter](/api/multi-agent-router) | Advanced task routing | Routes tasks to specialized agents based on capabilities |
## Workflow Architectures
| Architecture | Use Case | Key Functionality |
| ------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------- |
| [ConcurrentWorkflow](/api/concurrent-workflow) | Parallel task execution | Executes multiple tasks simultaneously |
| [SequentialWorkflow](/api/sequential-workflow) | Step-by-step processing | Executes tasks in a specific sequence |
| [GraphWorkflow](/api/graph-workflow) | Complex task dependencies | Manages tasks with complex dependencies |
| [BatchedGridWorkflow](/api/batched-grid-workflow) | Grid-style parallel task distribution | Pairs each agent with a different task and runs them concurrently |
## Hierarchical Architectures
| Architecture | Use Case | Key Functionality |
| ----------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------ |
| [HierarchicalSwarm](/api/hierarchical-swarm) | Hierarchical task orchestration | Director agent coordinates specialized worker agents |
| [Hybrid Hierarchical-Cluster Swarm](/api/hhcs) | Complex organization | Combines hierarchical and cluster-based organization |
| [Auto Swarm Builder](/api/auto-swarm-builder) | Automated swarm creation | Automatically creates and configures swarms |
| [PlannerWorkerSwarm](/api/planner-worker-swarm) | Plan-then-delegate execution | A planner agent generates a step-by-step plan that worker agents execute |
## Reasoning and Decision Architectures
| Architecture | Use Case | Key Functionality |
| ----------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------- |
| [HeavySwarm](/api/heavy-swarm) | Deep, research-grade analysis | Runs agents through many reasoning loops for intensive analysis |
| [CouncilAsAJudge](/api/council-as-judge) | High-stakes rulings with deliberation | A council of agents deliberates, then a judge agent delivers a verdict |
| [DebateWithJudge](/api/debate-with-judge) | Structured adversarial debate | Agents argue opposing positions over multiple rounds; a judge rules |
| [LLMCouncil](/api/llm-council) | Consensus-based decision making | An LLM-based council deliberates to reach a decision |
## Communication Structure
The [Conversation](/api/conversation) documentation details the communication protocols and structures used between agents in these architectures.
## Choosing the Right Architecture
**Task Complexity** -- Simple tasks may only need basic architectures like RoundRobin, while complex tasks might require Hierarchical or Graph-based approaches.
**Parallelization Needs** -- If tasks can be executed in parallel, consider ConcurrentWorkflow or SpreadSheetSwarm.
**Decision Making Requirements** -- For consensus-based decisions, MajorityVoting is ideal.
**Resource Optimization** -- If you need to optimize agent usage, consider SwarmRouter or MultiAgentRouter.
**Dynamic Adaptation** -- For tasks requiring dynamic adaptation, consider Auto Swarm Builder.
## Architecture Selection Guide
### By Task Type
| Task Type | Recommended Architecture |
| --------------------------- | ------------------------------------ |
| Simple, sequential tasks | SequentialWorkflow, RoundRobin |
| Parallel, independent tasks | ConcurrentWorkflow, SpreadSheetSwarm |
| Consensus-based decisions | MajorityVoting |
| Complex multi-domain tasks | HierarchicalSwarm, HHCS |
| Dynamic, evolving tasks | Auto Swarm Builder |
| Collaborative analysis | GroupChat, Mixture of Agents |
| Task routing | SwarmRouter, MultiAgentRouter |
### By Scale
| Scale | Recommended Architecture |
| ---------------- | ---------------------------------------------- |
| 2-5 agents | RoundRobin, SequentialWorkflow, AgentRearrange |
| 5-20 agents | SwarmRouter, GroupChat, ConcurrentWorkflow |
| 20+ agents | HierarchicalSwarm, HHCS, SpreadSheetSwarm |
| Variable/dynamic | Auto Swarm Builder |
For more detailed information about each architecture, refer to their respective documentation pages linked in the tables above.
# SwarmRearrange
Source: https://docs.swarms.world/api/swarm-rearrange
Orchestrate multiple swarms in sequential or parallel flow patterns with thread-safe operations
## Overview
`SwarmRearrange` is a class for orchestrating multiple swarms in a sequential or parallel flow pattern. It provides thread-safe operations for managing swarm execution, history tracking, and flow validation.
## Installation
```bash theme={null}
pip install -U swarms
```
## Attributes
Unique identifier for the swarm arrangement, e.g. `swarm-rearrange-<32 hex>` — not a UUID.
Name of the swarm arrangement.
Description of the arrangement.
List of swarm objects to be managed. Despite the default of `[]`, the constructor runs `reliability_checks()` and raises `ValueError` if `swarms` is empty — a non-empty list is effectively required.
Flow pattern for swarm execution. Uses arrow notation to define execution order. Despite the default of `None`, `reliability_checks()` raises `ValueError` if `flow` is falsy — a flow string is effectively required.
Maximum number of execution loops.
Enable detailed logging.
Enable human intervention during execution.
Custom function for human interaction.
Return results in JSON format.
Currently has no effect: `self.output_type` is stored but never read. `run()` never calls `history_output_formatter` and always returns `current_task`, a plain string (see `run()` below).
## Methods
### add\_swarm()
Adds a single swarm to the arrangement.
```python theme={null}
def add_swarm(self, swarm: Any)
```
**Parameters:**
* `swarm` (Any): The swarm object to add
### remove\_swarm()
Removes a swarm by name from the arrangement.
```python theme={null}
def remove_swarm(self, swarm_name: str)
```
**Parameters:**
* `swarm_name` (str): Name of the swarm to remove
### add\_swarms()
Adds multiple swarms to the arrangement.
```python theme={null}
def add_swarms(self, swarms: List[Any])
```
**Parameters:**
* `swarms` (List\[Any]): List of swarm objects to add
### validate\_flow()
Validates the flow pattern syntax and swarm names.
```python theme={null}
def validate_flow(self) -> bool
```
**Returns:** `True` if the flow is valid.
**Raises:** `ValueError` if `"->"` is missing from the flow, a referenced swarm name isn't registered (and isn't `"H"`), or the flow contains duplicate swarm names.
### set\_custom\_flow()
Overrides the current flow pattern.
```python theme={null}
def set_custom_flow(self, flow: str)
```
**Parameters:**
* `flow` (str): The new flow pattern string
### track\_history()
Appends a result to a swarm's execution history. Called internally; can also be invoked directly for custom tracking.
```python theme={null}
def track_history(self, swarm_name: str, result: str)
```
**Parameters:**
* `swarm_name` (str): Name of the swarm whose history to update
* `result` (str): Result to append to that swarm's history
### run()
Executes the swarm arrangement according to the flow pattern.
```python theme={null}
def run(self, task: str = None, img: str = None, custom_tasks: Dict[str, str] = None, *args, **kwargs)
```
**Parameters:**
* `task` (str, optional): The task to be executed
* `img` (str, optional): Image input for the task
* `custom_tasks` (Dict\[str, str], optional): Custom tasks mapped to specific swarms
* `*args`, `**kwargs`: Forwarded to each swarm's `run()` call
**Returns:** A plain `str` -- always `current_task` (the final swarm's textual output), regardless of `output_type`. `run()` catches all exceptions internally and, on failure, returns `str(e)` instead of raising -- so callers must check the returned string for error text rather than relying on a `try`/`except` around `run()`.
## Flow Pattern Syntax
The flow pattern uses arrow notation (`->`) to define execution order:
* **Sequential**: `"SwarmA -> SwarmB -> SwarmC"`
* **Parallel**: `"SwarmA, SwarmB -> SwarmC"`
* **Human intervention**: Use `"H"` in the flow
## Usage Examples
### Basic Sequential Flow
```python theme={null}
import os
from swarms import Agent, AgentRearrange, SwarmRearrange
company = "TGSC"
# Initialize the Managing Director agent
managing_director = Agent(
agent_name="Managing-Director",
system_prompt=f"""
As the Managing Director at Blackstone, your role is to oversee the entire investment analysis process for potential acquisitions.
Your responsibilities include:
1. Setting the overall strategy and direction for the analysis
2. Coordinating the efforts of the various team members and ensuring a comprehensive evaluation
3. Reviewing the findings and recommendations from each team member
4. Making the final decision on whether to proceed with the acquisition
For the current potential acquisition of {company}, direct the tasks for the team to thoroughly analyze all aspects of the company, including its financials, industry position, technology, market potential, and regulatory compliance. Provide guidance and feedback as needed to ensure a rigorous and unbiased assessment.
""",
model_name="gpt-5.4",
max_loops=1,
)
# Initialize the Vice President of Finance
vp_finance = Agent(
agent_name="VP-Finance",
system_prompt=f"""
As the Vice President of Finance at Blackstone, your role is to lead the financial analysis of potential acquisitions.
For the current potential acquisition of {company}, your tasks include:
1. Conducting a thorough review of {company}' financial statements
2. Analyzing key financial metrics such as revenue growth, profitability margins, liquidity ratios, and debt levels
3. Assessing the company's historical financial performance and projecting future performance
4. Identifying any financial risks or red flags that could impact the acquisition decision
5. Providing a detailed report on your findings and recommendations to the Managing Director
""",
model_name="gpt-5.4",
max_loops=1,
)
# Initialize the Industry Analyst
industry_analyst = Agent(
agent_name="Industry-Analyst",
system_prompt=f"""
As the Industry Analyst at Blackstone, your role is to provide in-depth research and analysis on the industries and markets relevant to potential acquisitions.
For the current potential acquisition of {company}, your tasks include:
1. Conducting a comprehensive analysis of the industrial robotics and automation solutions industry
2. Identifying the major players in the industry and assessing their market share
3. Evaluating {company}' competitive position within the industry
4. Analyzing the key drivers and restraints for the industry
5. Identifying potential risks and opportunities for {company} based on the industry analysis
""",
model_name="gpt-5.4",
max_loops=1,
)
# Initialize the Technology Expert
tech_expert = Agent(
agent_name="Tech-Expert",
system_prompt=f"""
As the Technology Expert at Blackstone, your role is to assess the technological capabilities, competitive advantages, and potential risks of companies being considered for acquisition.
For the current potential acquisition of {company}, your tasks include:
1. Conducting a deep dive into {company}' proprietary technologies
2. Assessing the uniqueness, scalability, and defensibility of {company}' technology stack
3. Comparing {company}' technologies to those of its competitors
4. Evaluating {company}' research and development capabilities
5. Identifying any potential technology risks or disruptive threats
""",
model_name="gpt-5.4",
max_loops=1,
)
# Initialize the Market Researcher
market_researcher = Agent(
agent_name="Market-Researcher",
system_prompt=f"""
As the Market Researcher at Blackstone, your role is to analyze the target company's customer base, market share, and growth potential.
For the current potential acquisition of {company}, your tasks include:
1. Analyzing {company}' current customer base
2. Assessing {company}' market share within its target markets
3. Conducting a detailed market sizing and segmentation analysis
4. Evaluating the demand drivers and sales cycles
5. Developing financial projections and estimates for revenue growth potential
""",
model_name="gpt-5.4",
max_loops=1,
)
# Initialize the Regulatory Specialist
regulatory_specialist = Agent(
agent_name="Regulatory-Specialist",
system_prompt=f"""
As the Regulatory Specialist at Blackstone, your role is to identify and assess any regulatory risks, compliance requirements, and potential legal liabilities.
For the current potential acquisition of {company}, your tasks include:
1. Identifying all relevant regulatory bodies and laws that govern the operations
2. Reviewing {company}' current compliance policies, procedures, and track record
3. Assessing the potential impact of any pending or proposed changes to relevant regulations
4. Evaluating the potential legal liabilities and risks
5. Providing recommendations on regulatory or legal due diligence steps
""",
model_name="gpt-5.4",
max_loops=1,
)
# Create a list of agents
agents = [
managing_director,
vp_finance,
industry_analyst,
tech_expert,
market_researcher,
regulatory_specialist,
]
# Define multiple flow patterns
flows = [
"Industry-Analyst -> Tech-Expert -> Market-Researcher -> Regulatory-Specialist -> Managing-Director -> VP-Finance",
"Managing-Director -> VP-Finance -> Industry-Analyst -> Tech-Expert -> Market-Researcher -> Regulatory-Specialist",
"Tech-Expert -> Market-Researcher -> Regulatory-Specialist -> Industry-Analyst -> Managing-Director -> VP-Finance",
]
# Create instances of AgentRearrange for each flow pattern
blackstone_acquisition_analysis = AgentRearrange(
name="Blackstone-Acquisition-Analysis",
description="A system for analyzing potential acquisitions",
agents=agents,
flow=flows[0],
)
blackstone_investment_strategy = AgentRearrange(
name="Blackstone-Investment-Strategy",
description="A system for evaluating investment opportunities",
agents=agents,
flow=flows[1],
)
blackstone_market_analysis = AgentRearrange(
name="Blackstone-Market-Analysis",
description="A system for analyzing market trends and opportunities",
agents=agents,
flow=flows[2],
)
swarm_arrange = SwarmRearrange(
swarms=[
blackstone_acquisition_analysis,
blackstone_investment_strategy,
blackstone_market_analysis,
],
flow=f"{blackstone_acquisition_analysis.name} -> {blackstone_investment_strategy.name} -> {blackstone_market_analysis.name}",
)
print(
swarm_arrange.run(
"Analyze swarms, 150k revenue with 45m+ agents build, with 1.4m downloads since march 2024"
)
)
```
### Human-in-the-Loop
```python theme={null}
from swarms import SwarmRearrange
def custom_human_input(task):
return input(f"Review {task} and provide feedback: ")
# Create arrangement with human intervention
arrangement = SwarmRearrange(
name="HumanAugmented",
swarms=[swarm1, swarm2],
flow="SwarmA -> H -> SwarmB",
human_in_the_loop=True,
custom_human_in_the_loop=custom_human_input
)
# Execute with human intervention
result = arrangement.run("Initial task")
```
## Best Practices
| Best Practice | Description |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Flow Validation** | Always validate flows before execution |
| **Error Handling** | `run()` never raises -- it catches all exceptions internally and returns `str(e)`. Inspect the returned string for error text rather than wrapping `run()` in try/catch |
| **History Tracking** | Use `track_history()` for monitoring swarm execution |
| **Resource Management** | Set appropriate `max_loops` to prevent infinite execution |
| **Logging** | Enable verbose mode during development for detailed logging |
## Source Code
View the [source code on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/swarm_rearrange.py)
# SwarmRouter
Source: https://docs.swarms.world/api/swarm-router
Universal router that dispatches a task to any supported swarm architecture through a single, uniform interface
## Overview
The `SwarmRouter` class dispatches tasks to any supported multi-agent architecture through a single, uniform interface. Set `swarm_type` to choose the architecture; pass the same agent list and call `run(task)` regardless of which architecture you select.
It also handles:
* Validated construction of the underlying swarm (`reliability_check`)
* Optional autosave of config / state / metadata to the workspace
* Multi-agent collaboration prompt injection
* Optional rules / shared-memory injection
* O(1) factory dispatch with internal caching
## Import
```python theme={null}
from swarms.structs.swarm_router import (
SwarmRouter,
SwarmType,
SwarmRouterConfig,
SwarmRouterRunError,
SwarmRouterConfigError,
)
```
## `SwarmType`
`SwarmType` is a `typing.Literal` enumerating every accepted `swarm_type` string. Any value outside this set raises `SwarmRouterConfigError` at construction time.
```python theme={null}
SwarmType = Literal[
"AgentRearrange",
"MixtureOfAgents",
"SequentialWorkflow",
"ConcurrentWorkflow",
"GroupChat",
"MultiAgentRouter",
"HierarchicalSwarm",
"MajorityVoting",
"CouncilAsAJudge",
"HeavySwarm",
"LLMCouncil",
"DebateWithJudge",
"RoundRobin",
"PlannerWorkerSwarm",
]
```
`"AutoSwarmBuilder"` is **not** in the `SwarmType` Literal — passing it raises `SwarmRouterConfigError` at construction. Neither `"auto"` nor `"BatchedGridWorkflow"` is a member either (14 values total) — passing either raises `SwarmRouterConfigError` at construction time, the same as any other invalid value.
## Constructor
```python theme={null}
SwarmRouter(
id: Optional[str] = None, # resolves to generate_id("swarm-router") when not set
name: str = "swarm-router",
description: str = "Routes your task to the desired swarm",
max_loops: int = 1,
agents: List[Union[Agent, Callable]] = [],
swarm_type: SwarmType = "SequentialWorkflow",
autosave: bool = False,
rearrange_flow: Optional[str] = None,
output_type: OutputType = "dict",
multi_agent_collab_prompt: bool = False,
list_all_agents: bool = False,
conversation: Any = None,
agents_config: Optional[Dict[Any, Any]] = None,
heavy_swarm_question_agent_model_name: str = "gpt-5.4",
heavy_swarm_worker_model_name: str = "gpt-5.4",
heavy_swarm_swarm_show_output: bool = True,
heavy_swarm_variant: SwarmVariant = "default",
heavy_swarm_max_loops: int = 1,
heavy_swarm_timeout: int = 900,
council_judge_model_name: str = "gpt-5.4",
verbose: bool = False,
worker_tools: Optional[List[Callable]] = None,
chairman_model: str = "gpt-5.1",
autosave_use_timestamp: bool = True,
director_model_name: str = "gpt-5.4",
director_settings: Optional[Dict[str, Any]] = None,
*args,
**kwargs,
)
```
### Core parameters
Unique identifier for the router instance. When left as `None`, resolves to `generate_id("swarm-router")`. Used for autosave directory naming and telemetry.
Human-readable name. Used for autosave directory naming.
Free-form description of the router's purpose.
Agents the router will pass to the selected swarm. Some swarm types require a specific minimum count (e.g. `DebateWithJudge` needs at least three).
Which architecture to instantiate. See the `SwarmType` Literal above.
Maximum execution loops where supported by the underlying swarm (e.g. `HierarchicalSwarm`, `GroupChat`).
Output formatter applied to the conversation. One of `'list'`, `'dict'`, `'dictionary'`, `'string'`, `'str'`, `'final'`, `'last'`, `'json'`, `'all'`, `'yaml'`, `'xml'`, `'dict-all-except-first'`, `'str-all-except-first'`, `'basemodel'`, `'dict-final'`, `'list-final'`.
### Behavior modifiers
Deliver the built-in collaboration prompt to each agent so they understand they are part of a multi-agent team. It is passed to the swarm at construction and reaches the agents as a **system turn** at run time; the caller's `Agent` objects are never modified.
Only `SequentialWorkflow` and `AgentRearrange` can deliver it. For any other `swarm_type` a warning is logged and the flag has no effect.
When `True`, every agent receives a manifest of its peers (name + description) in the same system turn as the collaboration prompt.
Pre-existing `Conversation` instance to reuse instead of starting fresh.
Per-agent configuration overrides applied during swarm setup.
Emit detailed logs during construction and execution.
### Autosave
When enabled, persist `config.json` on construction and `state.json` + `metadata.json` after each run to `{workspace_dir}/swarms/SwarmRouter/{swarm-name}-{stamp}/`.
Use an ISO timestamp in the directory name when `True`; use a UUID when `False`.
### Per-architecture parameters
These are only consulted when the corresponding `swarm_type` is selected.
#### AgentRearrange
Flow DSL string, e.g. `"researcher -> writer, editor"`. Required for `swarm_type="AgentRearrange"`.
#### GroupChat
`GroupChat` is asynchronous and self-selecting — there are **no speaker-selection functions**. The router passes `agents`, `max_loops`, `output_type`, and `verbose` through to it; agents decide on their own whether to speak. See the [GroupChat API reference](/api/group-chat) for `threshold` / `idle_timeout` tuning (configure those by constructing the `GroupChat` directly).
#### HeavySwarm
Model used by the question-generation agent.
Model used by every worker agent.
Print per-agent output during execution (`agent_prints_on`). The live dashboard is forced off when `HeavySwarm` is created through the router.
Which agent line-up to instantiate: `"default"` → 5 agents, `"medium"` → 4 agents (Captain + Harper / Benjamin / Lucas), `"heavy"` → 16 agents (Grok captain + 15 specialists). `SwarmVariant` is exported from `swarms.agents.heavy_swarm_agents`.
Number of iterative-refinement loops for `HeavySwarm`.
Per-worker wall-clock cap, in seconds, for `HeavySwarm`.
Tools made available to every worker agent in `HeavySwarm`.
#### HierarchicalSwarm
Model used by the auto-created director agent. Forwarded to `HierarchicalSwarm` by `_create_hierarchical_swarm()`.
Extra `Agent` keyword arguments for the auto-created director. `HierarchicalSwarm` reads the keys `agent_name`, `model_name`, `system_prompt`, `temperature`, and `top_p` from this dict, and each one overrides the corresponding default — including `director_model_name`.
#### CouncilAsAJudge
Model used by the judge agent.
#### LLMCouncil
Model used by the chairman that synthesizes the council members' responses.
### Additional kwargs
The constructor accepts arbitrary `*args` / `**kwargs` for forward-compatibility, but they are **not** stored on the router or forwarded to the underlying swarm — extra constructor kwargs are effectively ignored. Configure the underlying swarm through the router's explicit parameters listed above.
For `MixtureOfAgents`, the aggregator is **not** passed as a kwarg; the **last agent** in `agents` is used as the aggregator automatically:
```python theme={null}
router = SwarmRouter(
swarm_type="MixtureOfAgents",
agents=[worker_1, worker_2, aggregator], # aggregator = agents[-1]
)
```
## Exceptions
Raised by `reliability_check()` when construction inputs are invalid: unknown `swarm_type`, missing required parameter for the chosen type (e.g. `rearrange_flow` for `AgentRearrange`), `max_loops <= 0`, etc.
Raised by `run()` / `batch_run()` / `concurrent_run()` when task execution fails inside the underlying swarm. Wraps the original traceback.
## Methods
### `run(task=None, img=None, tasks=None, *args, **kwargs)`
Execute a single task using the configured swarm.
The task to be executed. Required for most `swarm_type` values.
Optional image input forwarded to vision-capable agents.
Batch-style task list, forwarded as `tasks=` to the underlying swarm's `run()` in place of `task` when provided. Only meaningful for swarm types whose `run()` accepts a `tasks` argument.
**Returns:** `Any` — shape depends on `output_type` and the underlying swarm.
**Raises:** `SwarmRouterRunError` on execution failure.
```python theme={null}
result = router.run("Analyse Q1 market trends.")
```
***
### `__call__(task, *args, **kwargs)`
Alias for `run`. Lets you treat a router as a callable.
```python theme={null}
result = router("Analyse Q1 market trends.")
```
***
### `batch_run(tasks, img=None, imgs=None, *args, **kwargs)`
Execute many tasks sequentially. Each task gets a fresh execution against the same router instance.
Tasks to process.
Single image applied to every task.
Per-task images aligned to `tasks` by index.
**Returns:** `List[Any]` — results in the same order as `tasks`.
```python theme={null}
results = router.batch_run([
"Summarize Q1.",
"Summarize Q2.",
"Summarize Q3.",
])
```
***
### `concurrent_run(task, img=None, imgs=None, *args, **kwargs)`
Execute one task in a separate thread using a `ThreadPoolExecutor`. Useful when calling the router from synchronous code that should not block.
```python theme={null}
result = router.concurrent_run("Summarize Q1.")
```
***
### `reliability_check()`
Validates the configuration (swarm type, per-type required parameters, `max_loops`) and then runs `setup()`. Called automatically at the end of `__init__`; you do not normally call it yourself. Raises `SwarmRouterConfigError` on invalid input.
***
### `setup()`
Applies pre-run configuration to the agents: the multi-agent collaboration prompt (`multi_agent_collab_prompt`) and the agent roster (`list_all_agents`). Called automatically during construction via `reliability_check()`. The underlying swarm itself is created lazily on the first `run()`.
***
### `to_dict()`
Serialize the router's configuration and current state to a dictionary suitable for logging or persistence.
**Returns:** `Dict[str, Any]`.
```python theme={null}
config = router.to_dict()
```
***
### `fetch_message_history_as_string()`
Return the underlying conversation as a single formatted string.
***
### `list_agents_to_eachother()`
Internal helper. Points `self.conversation` at the underlying swarm's conversation. Called after each run, because the swarm is built lazily on the first `run()` and several structures replace their conversation object per task. Rarely called directly.
`update_system_prompt_for_agent_in_swarm()` was removed. It appended the collaboration prompt to each agent's `system_prompt` **after** the LLM had been built, so the text never reached the model, while accumulating on the caller's live agents on every construction. The preamble is now passed through the swarm constructor and delivered as a system turn instead.
## Required parameters by `swarm_type`
| `swarm_type` | Additional required parameters |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| `SequentialWorkflow` | `agents` (≥1) |
| `ConcurrentWorkflow` | `agents` (≥1) |
| `AgentRearrange` | `agents`, `rearrange_flow` |
| `MixtureOfAgents` | `agents` (workers + aggregator as the **last** element) |
| `HierarchicalSwarm` | `agents` (workers); director is created automatically |
| `GroupChat` | `agents` (≥2; asynchronous, self-selecting — no speaker function) |
| `MajorityVoting` | `agents` (≥3 recommended) |
| `CouncilAsAJudge` | `council_judge_model_name` (builds its own agents) |
| `LLMCouncil` | `agents` (council members), `chairman_model` |
| `DebateWithJudge` | `agents` (≥3: pro, con, judge) |
| `HeavySwarm` | `heavy_swarm_worker_model_name`, `heavy_swarm_question_agent_model_name`, `heavy_swarm_variant` |
| `RoundRobin` | `agents` (≥2) |
| `MultiAgentRouter` | `agents` |
| `PlannerWorkerSwarm` | `agents` (workers); planner is created automatically |
`"AutoSwarmBuilder"`, `"auto"`, and `"BatchedGridWorkflow"` are **not** members of the `SwarmType` Literal — passing any of them raises `SwarmRouterConfigError` at construction time, before `run()` is ever reached.
## Autosave layout
When `autosave=True`, the router writes to:
```
{workspace_dir}/swarms/SwarmRouter/{name}-{timestamp_or_uuid}/
├── config.json # written on __init__
├── state.json # rewritten after each run
└── metadata.json # rewritten after each run
```
`workspace_dir` resolves to the `SWARMS_WORKSPACE_DIR` env var if set, otherwise to the configured Swarms workspace.
## Usage Example
```python theme={null}
from swarms.structs.agent import Agent
from swarms.structs.swarm_router import SwarmRouter
researcher = Agent(
agent_name="Research-Agent",
system_prompt="You are a research specialist.",
model_name="claude-sonnet-4-6",
)
analyst = Agent(
agent_name="Analysis-Agent",
system_prompt="You analyze research findings into actionable insights.",
model_name="claude-sonnet-4-6",
)
router = SwarmRouter(
name="research-analysis-swarm",
description="A swarm for research + analysis tasks",
agents=[researcher, analyst],
swarm_type="SequentialWorkflow",
max_loops=1,
autosave=True,
verbose=True,
)
result = router.run("Research recent trends in AI hardware and analyze them.")
print(result)
```
## Related Pages
* [SwarmRouter architecture overview](/architectures/swarm-router)
* [SwarmRouter example walkthrough](/examples/swarm-router-example)
* [MultiAgentRouter API reference](/api/multi-agent-router) — task-aware routing to one of N agents
* [AutoSwarmBuilder API reference](/api/auto-swarm-builder) — LLM-driven swarm construction
## Source
[`swarms/structs/swarm_router.py` on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/swarm_router.py)
# Swarming Architectures
Source: https://docs.swarms.world/api/swarming-architectures
Topology functions describing how agents pass tasks among each other — circular, grid, star, mesh, pyramid, one-to-one, and broadcast
## Overview
`swarms.structs.swarming_architectures` is a set of lightweight functions implementing common message-passing topologies between agents. Each function takes a list of `Agent` objects, a task or task list, and an `output_type`, then drives the agents through the topology and returns a formatted conversation history.
These are functional building blocks — no shared class, no orchestration object. Reach for them when you want a one-off interaction pattern without instantiating a full swarm class. All seven functions are exported from the top-level `swarms` package.
| Function | Topology | Per-call shape |
| ---------------- | ------------------------------------------------------------------------------------------ | -------------------------- |
| `circular_swarm` | Ring — every agent processes every task in order | `(agents, tasks)` |
| `grid_swarm` | Agents laid out in a √N×√N grid; one task per cell | `(agents, tasks)` |
| `star_swarm` | Star — a central agent processes every task first, then every other agent processes it too | `(agents, tasks)` |
| `mesh_swarm` | Mesh — agents pull from a shared FIFO task queue until it's empty | `(agents, tasks)` |
| `pyramid_swarm` | Pyramid — agents arranged in triangular levels; one task per cell | `(agents, tasks)` |
| `one_to_one` | A → B handoff for `max_loops` turns | `(sender, receiver, task)` |
| `broadcast` | One sender → many receivers, async | `(sender, agents, task)` |
All functions return whatever shape `output_type` selects via `history_output_formatter` — `"dict"` (default), `"list"`, `"str"`, etc.
## Installation
```bash theme={null}
pip install -U swarms
```
## circular\_swarm()
Every agent runs every task, in order. Each agent sees the running conversation context.
```python theme={null}
def circular_swarm(
agents: AgentListType,
tasks: List[str],
output_type: OutputType = "dict",
) -> Union[Dict[str, Any], List[str]]
```
Flat list of `Agent` instances (or list-of-lists; the function flattens once).
Tasks processed sequentially. Each agent runs each task.
Format for the returned conversation history.
**Raises:** `ValueError` if `agents` or `tasks` is empty.
## grid\_swarm()
Place agents in a √N×√N grid, pop tasks one by one, assign to cells row-by-row.
```python theme={null}
def grid_swarm(
agents: AgentListType,
tasks: List[str],
output_type: OutputType = "dict",
) -> Union[Dict[str, Any], List[str]]
```
Best when `len(agents)` is a perfect square and `len(tasks)` matches the cell count. Extra tasks are dropped; extra agents are idle.
## star\_swarm()
`agents[0]` acts as the central agent: it processes each task first (seeing the running conversation), then every other agent processes the same task independently.
```python theme={null}
def star_swarm(
agents: AgentListType,
tasks: List[str],
output_type: OutputType = "dict",
) -> Union[Dict[str, Any], List[str]]
```
**Raises:** `ValueError` if `agents` or `tasks` is empty.
## mesh\_swarm()
All tasks are pushed onto a shared FIFO queue. Agents repeatedly loop over the `agents` list, each popping the next task off the front of the queue, until the queue is empty. (Despite the name, task assignment is deterministic FIFO order, not randomized.)
```python theme={null}
def mesh_swarm(
agents: AgentListType,
tasks: List[str],
output_type: OutputType = "dict",
) -> Union[Dict[str, Any], List[str]]
```
**Raises:** `ValueError` if `agents` or `tasks` is empty.
## pyramid\_swarm()
Agents are arranged into triangular levels (level `i` holds `i + 1` agents), and tasks are popped one at a time and assigned to each cell in the pyramid, level by level.
```python theme={null}
def pyramid_swarm(
agents: AgentListType,
tasks: List[str],
output_type: OutputType = "dict",
) -> Union[Dict[str, Any], List[str]]
```
Best when `len(agents)` is a triangular number (1, 3, 6, 10, ...) and `len(tasks)` matches the cell count. Extra tasks are dropped; extra agents are idle.
**Raises:** `ValueError` if `agents` or `tasks` is empty.
## one\_to\_one()
Two-agent handoff: `sender` processes the task, `receiver` processes the sender's output, repeat for `max_loops`.
```python theme={null}
def one_to_one(
sender: Agent,
receiver: Agent,
task: str,
max_loops: int = 1,
output_type: OutputType = "dict",
) -> Union[Dict[str, Any], List[str]]
```
Agent that processes the task first each loop.
Agent that processes the sender's output.
Task for the sender on the first turn.
Number of sender→receiver round trips.
## broadcast()
**Async function.** One sender produces a message based on the conversation context; every agent in `agents` then processes the sender's broadcast independently.
```python theme={null}
async def broadcast(
sender: Agent,
agents: AgentListType,
task: str,
output_type: OutputType = "dict",
) -> Union[Dict[str, Any], List[str]]
```
Must be awaited:
```python theme={null}
import asyncio
result = asyncio.run(broadcast(sender, agents, task))
```
**Raises:** `ValueError` if `sender`, `agents`, or `task` is empty.
## Usage Examples
### Circular: Every Agent Reviews Every Document
```python theme={null}
from swarms import Agent, circular_swarm
reviewers = [
Agent(agent_name="Legal", model_name="claude-sonnet-4-6", max_loops=1),
Agent(agent_name="Security", model_name="claude-sonnet-4-6", max_loops=1),
Agent(agent_name="Privacy", model_name="claude-sonnet-4-6", max_loops=1),
]
result = circular_swarm(
agents=reviewers,
tasks=[
"Review draft TOS section 4.",
"Review draft TOS section 5.",
],
)
```
Each reviewer sees the running conversation, so later reviewers can build on earlier comments.
### One-to-One: Generator/Critic Loop
```python theme={null}
from swarms import Agent, one_to_one
generator = Agent(agent_name="Generator", model_name="claude-sonnet-4-6", max_loops=1)
critic = Agent(agent_name="Critic", model_name="claude-opus-4-6", max_loops=1)
result = one_to_one(
sender=generator,
receiver=critic,
task="Draft a one-paragraph announcement for v12.1",
max_loops=3,
)
```
### Broadcast: Notify a Pool of Workers
```python theme={null}
import asyncio
from swarms import Agent, broadcast
dispatcher = Agent(agent_name="Dispatcher", model_name="claude-sonnet-4-6", max_loops=1)
workers = [
Agent(agent_name=f"Worker-{i}", model_name="claude-sonnet-4-6", max_loops=1)
for i in range(5)
]
result = asyncio.run(
broadcast(
sender=dispatcher,
agents=workers,
task="Status check: report your current workload.",
)
)
```
## Choosing a Topology
| Pattern | When to use |
| ---------------- | ---------------------------------------------------------------------------------- |
| `circular_swarm` | Each agent should see every task and the accumulating context |
| `grid_swarm` | Tasks map cleanly to a 2D layout you already have |
| `star_swarm` | One agent should weigh in first on every task, then the rest respond independently |
| `mesh_swarm` | A pool of interchangeable agents should drain a shared task queue |
| `pyramid_swarm` | Tasks map cleanly to a triangular/hierarchical layout you already have |
| `one_to_one` | Two-agent loops — generator/critic, proposer/judge |
| `broadcast` | Fan-out where one message needs to reach many workers |
For richer orchestration (planning, voting, hierarchies) see [SwarmRouter](/api/swarm-router), [HierarchicalSwarm](/api/hierarchical-swarm), or [MajorityVoting](/api/majority-voting).
## Source Code
View the [source on GitHub](https://github.com/kyegomez/swarms/blob/master/swarms/structs/swarming_architectures.py).
# Tools & Utilities
Source: https://docs.swarms.world/api/tools
Comprehensive reference for Swarms tools, function calling, and schema conversion utilities
## Overview
The `swarms.tools` module provides a comprehensive toolkit for function calling, schema conversion, and tool management. It enables seamless integration with OpenAI-style function calling, MCP (Model Context Protocol) tools, and Pydantic-based schema validation.
## BaseTool
A comprehensive tool management system for function calling, schema conversion, and execution.
```python theme={null}
from swarms.tools import BaseTool
tool_manager = BaseTool(
verbose=True,
tools=[my_function],
base_models=[MyModel]
)
```
### Constructor
Enable detailed logging output
List of Pydantic models to manage
Enable automatic validation checks
Enable automatic tool execution
List of callable functions to manage
System prompt for tool operations
Mapping of function names to callables
List of dictionary representations of tool schemas
### Methods
#### func\_to\_dict
Convert a callable function to OpenAI function calling schema dictionary.
```python theme={null}
schema = tool.func_to_dict(my_function)
```
The function to convert
OpenAI function calling schema dictionary
**Raises:**
* `FunctionSchemaError`: If function schema conversion fails
* `ToolValidationError`: If function validation fails
#### base\_model\_to\_dict
Convert a Pydantic BaseModel to OpenAI function calling schema.
```python theme={null}
schema = tool.base_model_to_dict(MyModel, output_str=False)
```
The Pydantic model class to convert
Whether to return string output format
OpenAI function calling schema dictionary or JSON string
#### execute\_tool
Execute a tool based on a response string.
```python theme={null}
result = tool.execute_tool('{"name": "my_function", "parameters": {...}}')
```
JSON response string containing tool execution details
Result of the tool execution
**Raises:**
* `ToolValidationError`: If response validation fails
* `ToolExecutionError`: If tool execution fails
* `ToolNotFoundError`: If specified tool is not found
#### convert\_funcs\_into\_tools
Convert all functions in the tools list into OpenAI function calling format.
```python theme={null}
tool.convert_funcs_into_tools()
```
This method processes all functions in the tools list, validates them for proper documentation and type hints, and converts them to OpenAI schemas.
**Raises:**
* `ToolValidationError`: If tools are not properly configured
* `ToolDocumentationError`: If functions lack required documentation
* `ToolTypeHintError`: If functions lack required type hints
#### execute\_tool\_by\_name
Search for a tool by name and execute it with the provided response.
```python theme={null}
result = tool.execute_tool_by_name("add", '{"a": 1, "b": 2}')
```
The name of the tool to execute
JSON response string containing execution parameters
The result of executing the tool
## Tool Registry
`swarms.tools` exports a small registry pair: the `ToolStorage` class, which holds named tool callables, and the `tool_registry` decorator, which registers a function into a `ToolStorage` instance at import time.
```python theme={null}
from swarms.tools import ToolStorage, tool_registry
storage = ToolStorage(
name="Math Tools",
description="Arithmetic helpers for the agent",
)
@tool_registry(storage)
def add(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b
# Look the tool back up by name and call it
add_fn = storage.get_tool("add")
print(add_fn(2, 3)) # 5
```
There is no `tool` decorator in `swarms.tools`. To hand a plain Python function to an agent, pass it directly via `Agent(tools=[my_function])` — the framework generates the OpenAI schema from the function's type hints and docstring. Use `tool_registry` only when you also want name-based lookup through a `ToolStorage`.
### ToolStorage
Name of the registry
Description of the registry
Enable detailed logging output
Initial list of tool functions
#### Methods
| Method | Description |
| ------------------------- | ----------------------------------------------------------------------------------------------------- |
| `add_tool(func)` | Add a single tool. Raises `ValueError` if a tool with the same name already exists |
| `add_many_tools(funcs)` | Add a list of tools concurrently |
| `get_tool(name)` | Return the callable registered under `name`. Raises `ValueError` if not found |
| `list_tools()` | Return the registry contents as a formatted JSON string (name, documentation, creation time per tool) |
| `set_setting(key, value)` | Store an arbitrary setting on the registry |
| `get_setting(key)` | Read a setting back. Raises `KeyError` if not set |
`list_tools()` returns a JSON **string** built from the registry's metadata schema, not a list of tool names.
### tool\_registry
The storage instance to register the decorated function in
A decorator that registers the function and returns a logging wrapper around it
## Utility Functions
### get\_openai\_function\_schema\_from\_func
Convert a Python function to OpenAI function calling schema.
```python theme={null}
from swarms.tools import get_openai_function_schema_from_func
def add(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b
schema = get_openai_function_schema_from_func(
add,
name="add_numbers",
description="Add two integers"
)
```
### base\_model\_to\_openai\_function
Convert a Pydantic BaseModel to OpenAI function schema.
```python theme={null}
from swarms.tools import base_model_to_openai_function
from pydantic import BaseModel
class UserInput(BaseModel):
name: str
age: int
schema = base_model_to_openai_function(UserInput)
```
### scrape\_tool\_func\_docs
Extract documentation from a tool function.
```python theme={null}
from swarms.tools import scrape_tool_func_docs
docs = scrape_tool_func_docs(my_function)
```
### tool\_find\_by\_name
Find a tool by name in a list of tools.
```python theme={null}
from swarms.tools import tool_find_by_name
tool = tool_find_by_name("calculator", tools_list)
```
## MCP Tools Integration
MCP integration is handled by a single class, [`MCPManager`](/api/mcp-manager). Point it at one or more servers and it manages transport, authentication, tool discovery, caching, and routing each call to the server that owns the tool.
```python theme={null}
from swarms.tools.mcp_manager import MCPManager
manager = MCPManager(mcp_url="http://localhost:8000/mcp")
manager.list_tool_names() # discover
manager.get_tools() # OpenAI schemas for an LLM
manager.call_tool("get_crypto_price", {"coin_id": "btc"}) # call one directly
manager.execute_tool_calls(llm_response) # run what a model asked for
```
`MCPManager` and `MCPFileTokenStorage` are exported from `swarms.tools`. See the [MCPManager reference](/api/mcp-manager) for the full API, and the [MCP integration guide](/integrations/mcp) for using it from an agent.
**Removed in favor of `MCPManager`.** The standalone functions previously documented here — `get_mcp_tools_sync`, `aget_mcp_tools`, `execute_tool_call_simple`, `get_tools_for_multiple_mcp_servers`, and `execute_multiple_tools_on_multiple_mcp_servers` — no longer exist, along with the `swarms.tools.mcp_client_tools` module.
| Removed | Replacement |
| ------------------------------------------------------- | -------------------------------------------------------- |
| `get_mcp_tools_sync(server_path=URL)` | `MCPManager(mcp_url=URL).get_tools()` |
| `aget_mcp_tools(server_path=URL)` | `await MCPManager(mcp_url=URL).aget_tools()` |
| `get_tools_for_multiple_mcp_servers(urls=URLS)` | `MCPManager(mcp_urls=URLS).get_tools()` |
| `execute_tool_call_simple(response=R, server_path=URL)` | `await MCPManager(mcp_url=URL).aexecute_tool_calls(R)` |
| `execute_multiple_tools_on_multiple_mcp_servers(...)` | `await MCPManager(mcp_urls=URLS).aexecute_tool_calls(R)` |
Full migration notes, including the two behavioral differences, are in the [MCPManager reference](/api/mcp-manager#migration).
## Additional Utilities
A few other symbols are exported from `swarms.tools` for less common use cases:
* **`multi_base_model_to_openai_function`** — Convert several Pydantic `BaseModel` classes to a combined OpenAI function schema.
* **`Function`** / **`ToolFunction`** — Pydantic models describing an OpenAI function and a tool wrapping one.
* **`load_basemodels_if_needed`** / **`get_load_param_if_needed_function`** — Coerce raw dict arguments into the Pydantic models a tool's signature declares.
* **`get_parameters`** / **`get_required_params`** — Extract the JSON-schema parameter block and the list of required parameter names from a callable.
* **`ToolStorage`** / **`tool_registry`** — Register and look up tools by name; see [Tool Registry](#tool-registry) above.
* **`MCPManager`** / **`MCPFileTokenStorage`** — MCP transport, auth, discovery, and routing; see the [MCPManager reference](/api/mcp-manager).
## Exceptions
`BaseTool` raises the exceptions below. They are defined in `swarms.tools.base_tool` and are **not** re-exported from `swarms.tools`, so import them from the module directly:
```python theme={null}
from swarms.tools.base_tool import (
BaseToolError,
ToolValidationError,
ToolExecutionError,
ToolNotFoundError,
FunctionSchemaError,
ToolDocumentationError,
ToolTypeHintError,
)
```
All of them subclass `BaseToolError`.
### BaseToolError
Base exception class for all BaseTool related errors.
### ToolValidationError
Raised when tool validation fails.
### ToolExecutionError
Raised when tool execution fails.
### ToolNotFoundError
Raised when a requested tool is not found.
### FunctionSchemaError
Raised when function schema conversion fails.
### ToolDocumentationError
Raised when tool documentation is missing or invalid.
### ToolTypeHintError
Raised when tool type hints are missing or invalid.
## Best Practices
1. **Always add type hints**: Functions must have type hints for reliable schema generation
2. **Include docstrings**: Comprehensive docstrings improve tool descriptions
3. **Validate inputs**: Use Pydantic models for complex input validation
4. **Handle errors**: Wrap tool execution in try-catch blocks
5. **Use caching**: BaseTool caches expensive operations for performance
6. **Enable verbose mode**: During development, enable verbose logging to debug issues
## Example: Complete Tool Setup
```python theme={null}
from swarms.tools import BaseTool
from pydantic import BaseModel
# Define a Pydantic model
class MathInput(BaseModel):
a: int
b: int
operation: str
# Define a function with type hints and docstring
def calculate(a: int, b: int, operation: str) -> int:
"""Perform arithmetic operations on two numbers.
Args:
a: First number
b: Second number
operation: Operation to perform (add, subtract, multiply, divide)
Returns:
Result of the operation
"""
if operation == "add":
return a + b
elif operation == "subtract":
return a - b
elif operation == "multiply":
return a * b
elif operation == "divide":
return a // b
else:
raise ValueError(f"Unknown operation: {operation}")
# Create tool manager
tool_manager = BaseTool(
verbose=True,
tools=[calculate],
base_models=[MathInput]
)
# Convert tools to OpenAI schema
tool_manager.convert_funcs_into_tools()
# Execute a tool
result = tool_manager.execute_tool_by_name(
"calculate",
'{"a": 10, "b": 5, "operation": "multiply"}'
)
print(result) # 50
```
# Utilities
Source: https://docs.swarms.world/api/utils
Essential utility functions and classes for file processing, logging, formatting, and token management
## Overview
The `swarms.utils` module provides essential utilities for file operations, logging, output formatting, token counting, and data processing. These utilities support core agent functionality and framework operations.
## Logging
### initialize\_logger
Initialize a Loguru logger with custom formatting and output configuration.
```python theme={null}
from swarms.utils.loguru_logger import initialize_logger
logger = initialize_logger(log_folder="my_logs")
logger.info("Application started")
logger.error("An error occurred")
logger.debug("Debug information")
```
Legacy parameter, kept only for backwards compatibility — it no longer sets the log directory. Logs are always written to `{WORKSPACE_DIR}/logs` (via `get_log_dir()`), regardless of what is passed here.
Configured Loguru logger instance
**Features:**
* Colored console output
* Timestamp formatting
* Function and line number tracking
* Backtrace and diagnostics enabled
* Thread-safe enqueuing
## Formatting & Output
### Formatter
Rich-based formatter for beautiful console output with markdown support.
````python theme={null}
from swarms.utils.formatter import Formatter
formatter = Formatter(md=True)
# Print formatted panels
formatter.print_panel(
"Analysis complete",
title="Status",
style="bold green"
)
# Print markdown with syntax highlighting
formatter.print_markdown(
"# Results\n\n```python\nprint('hello')\n```",
title="Code Output"
)
````
#### Constructor
Enable markdown output rendering
#### Methods
##### print\_panel
Print content in a styled panel.
```python theme={null}
formatter.print_panel(
content="Task completed successfully",
title="Success",
style="bold green"
)
```
Content to display in the panel
Panel title
Panel style (color and formatting)
##### print\_markdown
Render markdown content with syntax highlighting.
```python theme={null}
formatter.print_markdown(
content="# Analysis\n\nResults are **positive**",
title="Report",
border_style="blue"
)
```
Markdown content to render
Panel title
Border color style
##### print\_streaming\_panel
Display real-time streaming response with live updates.
```python theme={null}
response = formatter.print_streaming_panel(
streaming_response=llm_stream,
title="Agent Response",
collect_chunks=True
)
```
Streaming response generator from LLM
Panel title
Panel style (uses random color if None)
Whether to collect individual chunks
Callback function for each chunk
Complete accumulated response text
##### print\_agent\_dashboard
Display a live dashboard showing agent statuses.
```python theme={null}
agents_data = [
{"name": "Agent-1", "status": "running", "output": "Processing..."},
{"name": "Agent-2", "status": "completed", "output": "Done!"}
]
formatter.print_agent_dashboard(
agents_data=agents_data,
title="Swarm Dashboard",
is_final=False
)
```
List of agent information dictionaries with name, status, and output
Dashboard title
Whether this is the final update
## Data Structure Formatting
### format\_dict\_to\_string
Recursively format a dictionary into a readable, multi-line string.
```python theme={null}
from swarms.utils import format_dict_to_string
text = format_dict_to_string({"name": "Agent", "config": {"loops": 3}})
print(text)
```
The dictionary to format
Current indentation level for nested structures
If `True`, use `"key: value"` formatting; if `False`, use `"key value"`
### format\_data\_structure
Format any Python data structure (dict, list, tuple, set, or object) into a readable, indented, multi-line string.
```python theme={null}
from swarms.utils import format_data_structure
text = format_data_structure({"agents": ["A", "B"], "count": 2})
print(text)
```
The data structure to format
Current indentation level
Maximum depth to recurse
### exists
Check if a value is not `None`.
```python theme={null}
from swarms.utils import exists
exists(None) # False
exists("value") # True
```
## File Processing
### create\_file\_in\_folder
Create a file with content in a specified folder.
```python theme={null}
from swarms.utils import create_file_in_folder
file_path = create_file_in_folder(
folder_path="./reports",
file_name="analysis.txt",
content="Financial analysis results..."
)
```
Path to the folder (created if doesn't exist)
Name of the file to create
Content to write to the file
Path to the created file
### sanitize\_file\_path
Clean and sanitize file paths for cross-platform compatibility.
```python theme={null}
from swarms.utils import sanitize_file_path
safe_path = sanitize_file_path("`C:/Users/file.txt`")
# Returns: C__Users_file_name_.txt
# `:`, `/`, `\`, `<`, `>`, `"`, `|`, `?`, `*`, and backticks are all replaced with `_`
```
File path to sanitize
Sanitized file path safe for all platforms
### load\_json
Load and parse a JSON string.
```python theme={null}
from swarms.utils import load_json
json_str = '{"name": "Agent", "status": "active"}'
data = load_json(json_str)
print(data["name"]) # "Agent"
```
JSON string to parse
Parsed Python object (dict, list, etc.)
### zip\_workspace
Zip an entire workspace directory.
```python theme={null}
from swarms.utils import zip_workspace
zip_path = zip_workspace(
workspace_path="./my_workspace",
output_filename="workspace_backup"
)
```
Path to workspace directory to zip
Name for output zip file (without .zip extension)
Path to created zip file
### zip\_folders
Zip multiple folders into a single archive.
```python theme={null}
from swarms.utils import zip_folders
zip_folders(
folder1_path="./data",
folder2_path="./logs",
zip_file_path="combined_backup"
)
```
Path to first folder
Path to second folder
Output zip file path
## Token Management
### count\_tokens
Count tokens in text using LiteLLM tokenizer.
```python theme={null}
from swarms.utils import count_tokens
text = "Analyze the financial statements"
token_count = count_tokens(
text=text,
model="gpt-4"
)
print(f"Tokens: {token_count}")
```
Text to count tokens for
Model to use for tokenization
Fallback encoder used if tokenizing with `model` fails
Number of tokens in the text
**Raises:** `ValueError` if both the primary model and the fallback encoder fail to tokenize the text.
### get\_supported\_models
Get the list of models supported by LiteLLM.
```python theme={null}
from swarms.utils.litellm_tokenizer import get_supported_models
models = get_supported_models()
print(models)
```
List of supported model name strings
## Agent Loading
### load\_agent\_from\_markdown
Load agent configuration from markdown file.
```python theme={null}
from swarms.utils import load_agent_from_markdown
agent = load_agent_from_markdown("agent_config.md")
```
### load\_agents\_from\_markdown
Load multiple agents from markdown files.
```python theme={null}
from swarms.utils import load_agents_from_markdown
agents = load_agents_from_markdown([
"agent1.md",
"agent2.md",
"agent3.md"
])
```
### MarkdownAgentLoader
Class for loading agents from markdown with advanced options. `load_agent_from_markdown` and `load_agents_from_markdown` are thin wrappers around it.
```python theme={null}
from swarms.utils import MarkdownAgentLoader
loader = MarkdownAgentLoader(max_workers=4)
agent = loader.load_single_agent("agent_config.md")
agents = loader.load_multiple_agents("./agent_configs")
```
Worker count used when loading multiple files concurrently
| Method | Description |
| -------------------------------------------- | ------------------------------------------------------------------------------ |
| `load_single_agent(file_path, **kwargs)` | Load one agent from a markdown file |
| `load_multiple_agents(file_paths, **kwargs)` | Load agents from a directory path or a list of file paths |
| `parse_markdown_file(file_path)` | Parse a markdown file into a `MarkdownAgentConfig` without building an `Agent` |
| `parse_yaml_frontmatter(content)` | Parse just the YAML frontmatter out of markdown content |
## Context Window Management
### Conversation.dynamic\_auto\_chunking
Trim the conversation history from the beginning so the remainder fits within the conversation's token budget, using a binary search over token counts. It returns a single trimmed string (the tail of the history that fits), not a list of chunks.
This is a **method on `Conversation`**, not a standalone helper — there is no `dynamic_auto_chunking` in `swarms.utils`. The budget and tokenizer come from the `Conversation`'s own `context_length` and `tokenizer_model_name`, so the method itself takes no arguments.
```python theme={null}
from swarms.structs.conversation import Conversation
conversation = Conversation(
context_length=4000,
tokenizer_model_name="gpt-5.4",
)
conversation.add("user", "...very long document...")
conversation.add("assistant", "...long analysis...")
trimmed = conversation.dynamic_auto_chunking()
print(f"Trimmed length: {len(trimmed)} chars")
```
The conversation history trimmed to fit within `context_length` tokens. Returns the full history unchanged if it already fits, or if chunking fails.
Relevant `Conversation` constructor parameters:
Maximum number of tokens allowed in the conversation history
Model used for token counting
## Output History Formatting
### history\_output\_formatter
Format a `Conversation` object's history into one of several output formats.
```python theme={null}
from swarms.utils import history_output_formatter
formatted = history_output_formatter(
conversation=conversation_history,
type="str",
)
print(formatted)
```
A conversation object exposing methods like `return_messages_as_list()`, `to_dict()`, `get_str()`, etc.
Output format. One of: `"list"`, `"dict"`/`"dictionary"`, `"string"`/`"str"`, `"final"`/`"last"`, `"json"`, `"all"`, `"yaml"`, `"xml"`, `"dict-all-except-first"`, `"str-all-except-first"`, `"dict-final"`, `"list-final"`
**Raises:** `ValueError` if `type` is not one of the supported values.
## LiteLLM Wrapper
### LiteLLM
Wrapper class for LiteLLM with error handling.
```python theme={null}
from swarms.utils import LiteLLM
llm = LiteLLM(
model_name="gpt-5.4",
temperature=0.7,
max_tokens=1000
)
response = llm.run("Analyze this data")
```
The constructor parameter is `model_name`, not `model` — because `LiteLLM.__init__` absorbs unrecognized keywords via `**kwargs`, passing `model=` silently fails to set the model instead of raising an error.
### NetworkConnectionError
Exception raised for network connection issues.
```python theme={null}
from swarms.utils import NetworkConnectionError
try:
response = llm.run(prompt)
except NetworkConnectionError as e:
print(f"Network error: {e}")
# Handle retry logic
```
### LiteLLMException
General exception for LiteLLM errors.
```python theme={null}
from swarms.utils import LiteLLMException
try:
response = llm.run(prompt)
except LiteLLMException as e:
print(f"LiteLLM error: {e}")
```
## Workspace Management
### WorkspaceManager
Creates a swarm's autosave directory once and writes to it on demand. The directory is `{WORKSPACE_DIR}/swarms/{ClassName}/{name}-{stamp}`, created eagerly so `dir` is usable straight after construction.
```python theme={null}
from swarms.utils import WorkspaceManager
manager = WorkspaceManager(owner=my_swarm, verbose=True)
print(manager.dir)
```
The swarm instance. Its class name and `name` attribute pick the directory, and it is the default source for conversation and config data
Overrides `owner.name` in the path
Timestamp in the directory name when `True`, otherwise a short UUID
Log the directory and each successful write
When `False` nothing is created or written and `dir` stays `None`
Path segments joined onto the workspace directory in place of the default `swarms/{ClassName}/{name}-{stamp}` layout — e.g. `("agents", "my-agent-a1b2c3d4e5f6")`
Base fields merged into `_autosave_metadata` on every write, in place of the default `{class_name, swarm_name, swarm_id}`
## Example: Complete Utility Usage
```python theme={null}
from swarms.utils import (
initialize_logger,
create_file_in_folder,
count_tokens,
sanitize_file_path,
)
from swarms.utils.formatter import Formatter
# Initialize logging
logger = initialize_logger("my_app")
logger.info("Starting application")
# Create formatter for output
formatter = Formatter(md=True)
# Process some data
markdown_content = """
# Analysis Results
The quarter closed **above** forecast.
"""
# Count tokens
tokens = count_tokens(markdown_content, model="gpt-5.4")
formatter.print_panel(
f"Report has {tokens} tokens",
title="Token Count",
style="bold cyan"
)
# Save to file
safe_path = sanitize_file_path("./reports/analysis_results.txt")
file_path = create_file_in_folder(
folder_path="./reports",
file_name="analysis_results.txt",
content=markdown_content
)
logger.info(f"Saved to: {file_path}")
# Display markdown
formatter.print_markdown(
markdown_content,
title="Analysis Report",
border_style="green"
)
```
## Best Practices
1. **Use logging extensively**: Initialize logger in all modules for debugging
2. **Sanitize paths**: Always sanitize file paths before file operations
3. **Count tokens**: Monitor token usage to stay within model limits
4. **Format output**: Use Formatter for consistent, beautiful CLI output
5. **Handle errors**: Wrap file operations in try-catch blocks
6. **Chunk large texts**: Use `Conversation.dynamic_auto_chunking()` to keep long histories inside the context window
7. **Stream responses**: Use print\_streaming\_panel for real-time output
# Agent Rearrange
Source: https://docs.swarms.world/architectures/agent-rearrange
Define complex multi-agent workflows with custom flow patterns using arrow and comma syntax
The `AgentRearrange` system enables sophisticated multi-agent orchestration through custom flow patterns. Define how agents communicate using simple syntax: `->` for sequential execution and `,` for concurrent execution.
## When to Use
* **Flexible workflows**: Mix sequential and parallel execution
* **Dynamic routing**: Tasks need different paths through agents
* **Complex coordination**: Multiple agents with custom relationships
* **Adaptive workflows**: Flow changes based on task requirements
* **Team awareness**: Agents need context about team structure
## Flow Syntax
* `agent1 -> agent2`: Sequential execution (agent2 runs after agent1)
* `agent1, agent2`: Concurrent execution (both run simultaneously)
* `agent1 -> agent2, agent3`: Combined (agent1 first, then agent2 and agent3 in parallel)
## Basic Example
```python theme={null}
from swarms import Agent, AgentRearrange
# Define specialized agents
researcher = Agent(
agent_name="researcher",
system_prompt="Research topics and gather information.",
model_name="gpt-5.4",
)
writer = Agent(
agent_name="writer",
system_prompt="Write engaging content based on research.",
model_name="gpt-5.4",
)
reviewer = Agent(
agent_name="reviewer",
system_prompt="Review and provide feedback on content.",
model_name="gpt-5.4",
)
# Define flow: researcher first, then writer and reviewer in parallel
flow = "researcher -> writer, reviewer"
# Create the system
rearrange = AgentRearrange(
agents=[researcher, writer, reviewer],
flow=flow,
max_loops=1,
)
# Execute
result = rearrange.run("Analyze quantum computing trends")
print(result)
```
## Complex Flow Patterns
### Fan-Out Pattern
One agent distributes to multiple agents:
```python theme={null}
# Data collector sends to three analysts simultaneously
flow = "data_collector -> technical_analyst, fundamental_analyst, sentiment_analyst"
rearrange = AgentRearrange(
agents=[data_collector, technical_analyst, fundamental_analyst, sentiment_analyst],
flow=flow,
)
```
### Fan-In Pattern
Multiple agents converge to one:
```python theme={null}
# Multiple researchers feed into synthesizer
flow = "researcher1, researcher2, researcher3 -> synthesizer"
rearrange = AgentRearrange(
agents=[researcher1, researcher2, researcher3, synthesizer],
flow=flow,
)
```
### Multi-Stage Pipeline
```python theme={null}
# Research → parallel analysis → synthesis
flow = "researcher -> analyst1, analyst2, analyst3 -> synthesizer"
rearrange = AgentRearrange(
agents=[researcher, analyst1, analyst2, analyst3, synthesizer],
flow=flow,
)
```
## Key Parameters
Name for the agent rearrange system
List of agents to orchestrate
Flow pattern defining agent execution (e.g., "agent1 -> agent2, agent3")
Maximum number of execution loops
Enable agents to know their position in workflow
Output format (all, final, list, dict)
Optional memory system for persistence
Log every flow step and agent transition. **This defaults to `True`**, so a fresh `AgentRearrange` is noisy out of the box — pass `verbose=False` for quiet runs.
Persist workflow state. Defaults to `True`.
Record an ISO timestamp on every conversation message.
Attach a unique id to every conversation message.
## Methods
### run()
Execute the defined flow with a task.
```python theme={null}
result = rearrange.run(
task="Analyze market trends",
img=None, # Optional image input
)
```
### batch\_run()
Process multiple tasks in batches.
```python theme={null}
tasks = ["Task 1", "Task 2", "Task 3"]
results = rearrange.batch_run(
tasks=tasks,
batch_size=10,
)
```
### concurrent\_run()
Run multiple tasks concurrently.
```python theme={null}
tasks = ["Task 1", "Task 2", "Task 3"]
results = rearrange.concurrent_run(
tasks=tasks,
max_workers=5,
)
```
### run\_async()
Asynchronous task execution.
```python theme={null}
import asyncio
async def main():
result = await rearrange.run_async("Task description")
return result
result = asyncio.run(main())
```
### run\_stream() / arun\_stream()
Stream tokens as agents execute, in flow order. Sequential segments (`A -> B`) stream one agent at a time; parallel segments (`A, B`) interleave tokens from concurrent agents fairly.
```python theme={null}
# Sync generator
for agent_name, token in rearrange.run_stream("Analyse quantum computing trends"):
print(f"[{agent_name}] {token}", end="", flush=True)
```
```python theme={null}
# Async generator
import asyncio
async def main():
async for agent_name, token in rearrange.arun_stream("Analyse quantum computing trends"):
print(f"[{agent_name}] {token}", end="", flush=True)
asyncio.run(main())
```
Pass `with_events=True` to receive structured `agent_start` / `token` / `agent_end` event dicts instead of `(agent_name, token)` tuples.
`max_loops > 1` and `custom_tasks` are not supported in streaming mode. Use `run()` for those.
### explain()
Print or return the resolved execution plan for the current flow. It validates the flow, then lists every step in order and marks each as sequential or parallel. No agents or LLMs are invoked, which makes it cheap enough for CI smoke tests and pre-flight checks.
When `True`, return the plan as a string. When `False`, print it and return `None`.
The plan string when `return_str=True`; otherwise `None`.
```python theme={null}
rearrange = AgentRearrange(
agents=[ingestor, tech, business, legal, synthesizer],
flow="Ingestor -> Tech, Business, Legal -> Synthesizer",
)
rearrange.explain()
# Flow: Ingestor -> Tech, Business, Legal -> Synthesizer
#
# Step 1: Ingestor [sequential]
# Step 2: Tech, Business, Legal [parallel, 3 agents]
# Step 3: Synthesizer [sequential]
#
# 3 steps, 5 agent invocations across 1 loop(s).
plan = rearrange.explain(return_str=True)
```
`explain()` validates the flow first and raises if it is invalid — the same error `run()` would raise.
## Team Awareness
Enable agents to understand their position in the workflow:
```python theme={null}
rearrange = AgentRearrange(
agents=agents,
flow="agent1 -> agent2 -> agent3",
team_awareness=True, # Agents know who comes before/after
)
```
With team awareness, agents receive context like:
* "Agent ahead: agent1"
* "Agent behind: agent3"
* Sequential flow structure information
## Use Cases
### Content Creation Pipeline
```python theme={null}
# Research → Write → (Edit, Fact-Check) → Publish
flow = "researcher -> writer -> editor, fact_checker -> publisher"
pipeline = AgentRearrange(
agents=[researcher, writer, editor, fact_checker, publisher],
flow=flow,
)
article = pipeline.run("AI in healthcare")
```
### Software Development
```python theme={null}
# Design → (Frontend, Backend) → Testing → Review
flow = "architect -> frontend_dev, backend_dev -> tester -> reviewer"
dev_pipeline = AgentRearrange(
agents=[architect, frontend_dev, backend_dev, tester, reviewer],
flow=flow,
)
code = dev_pipeline.run("Build user authentication system")
```
### Market Analysis
```python theme={null}
# Data Collection → (Technical, Fundamental, Sentiment) → Synthesis
flow = "collector -> tech_analyst, fund_analyst, sent_analyst -> synthesizer"
analysis = AgentRearrange(
agents=[collector, tech_analyst, fund_analyst, sent_analyst, synthesizer],
flow=flow,
)
report = analysis.run("NVIDIA stock analysis")
```
## Dynamic Flow Management
### Change Flow at Runtime
```python theme={null}
rearrange = AgentRearrange(agents=agents, flow="agent1 -> agent2")
# Update flow dynamically
rearrange.set_custom_flow("agent1 -> agent2, agent3")
result = rearrange.run("New task")
```
### Add/Remove Agents
```python theme={null}
# Add new agent
new_agent = Agent(agent_name="new_agent", ...)
rearrange.add_agent(new_agent)
# Remove agent
rearrange.remove_agent("old_agent")
```
## Sequential Awareness
Agents can understand their workflow position:
```python theme={null}
# Get awareness info for specific agent
awareness = rearrange.get_agent_sequential_awareness("agent2")
print(awareness)
# Output: "Sequential awareness: Agent ahead: agent1 | Agent behind: agent3"
# Get full flow structure
structure = rearrange.get_sequential_flow_structure()
print(structure)
# Output:
# Sequential Flow Structure:
# Step 1: agent1 (leads to: agent2)
# Step 2: agent2 (follows: agent1) (leads to: agent3)
# Step 3: agent3 (follows: agent2)
```
## Advanced Features
### Custom Tasks for Specific Agents
```python theme={null}
# Override task for specific agent
custom_tasks = {
"researcher": "Focus on recent developments",
}
result = rearrange.run(
task="Main task",
custom_tasks=custom_tasks,
)
```
### Output Formatting
```python theme={null}
# Different output types
rearrange_all = AgentRearrange(
agents=agents,
flow=flow,
output_type="all", # All agent responses
)
rearrange_final = AgentRearrange(
agents=agents,
flow=flow,
output_type="final", # Only final agent's response
)
rearrange_list = AgentRearrange(
agents=agents,
flow=flow,
output_type="list", # List of responses
)
```
## Best Practices
**Flow Design**: Start simple and add complexity as needed. Test with "agent1 -> agent2" before complex patterns.
1. **Clear Flow Logic**: Ensure flow makes sense for your task
2. **Agent Naming**: Use descriptive names for clarity in flow definitions
3. **Validate Flow**: Use `validate_flow()` before production
4. **Team Awareness**: Enable when agents benefit from position context
5. **Start Simple**: Begin with sequential, add concurrency where beneficial
Flow validation happens at runtime - ensure all agent names in flow exist in the agents list
## Flow Validation
Construction only checks that `flow` is a non-empty string — it does **not** verify that every agent name in the flow is registered. Call `validate_flow()` explicitly (or `explain()`, which calls it internally) to catch typos before running:
```python theme={null}
rearrange = AgentRearrange(
agents=[agent1, agent2],
flow="agent1 -> agent3", # agent3 doesn't exist
)
try:
rearrange.validate_flow()
except ValueError as e:
print(f"Invalid flow: {e}")
# Output: "Agent 'agent3' is not registered."
```
`run()` will also raise a similar `ValueError` at execution time if it reaches a step referencing an unregistered agent, so validation happens automatically before any agent work is wasted — just not at construction time.
## Related Architectures
* [Sequential Workflow](/architectures/sequential-workflow) - Simpler linear flows
* [Concurrent Workflow](/architectures/concurrent-workflow) - Pure parallel execution
* [Graph Workflow](/architectures/graph-workflow) - DAG-based complex flows
* [Social Algorithms](/architectures/social-algorithms) - Custom communication patterns
# Concurrent Workflow
Source: https://docs.swarms.world/architectures/concurrent-workflow
Execute multiple agents simultaneously for maximum throughput and parallel processing
The `ConcurrentWorkflow` runs multiple agents simultaneously on the same task, enabling parallel execution and high-throughput processing. This architecture is ideal when you need multiple perspectives or rapid parallel analysis.
## When to Use
* **High-throughput tasks**: Process large volumes simultaneously
* **Multiple perspectives**: Get diverse viewpoints on the same input
* **Parallel analysis**: Market, financial, and risk analysis at once
* **Time-critical operations**: Minimize total execution time
* **Independent processing**: Tasks with no dependencies
## Key Features
* True parallel execution with ThreadPoolExecutor
* Real-time dashboard monitoring (optional)
* Agent status tracking
* Streaming callbacks support
* Thread pool sized by agent count, capped at 32
* Conversation history aggregation
## Basic Example
```python theme={null}
from swarms import Agent, ConcurrentWorkflow
# Create specialized analysts
market_analyst = Agent(
agent_name="Market-Analyst",
system_prompt="Analyze market trends and opportunities.",
model_name="gpt-5.4",
)
financial_analyst = Agent(
agent_name="Financial-Analyst",
system_prompt="Provide financial analysis and projections.",
model_name="gpt-5.4",
)
risk_analyst = Agent(
agent_name="Risk-Analyst",
system_prompt="Assess and quantify potential risks.",
model_name="gpt-5.4",
)
# Create concurrent workflow
workflow = ConcurrentWorkflow(
agents=[market_analyst, financial_analyst, risk_analyst],
max_loops=1,
)
# All agents run simultaneously
results = workflow.run(
"Analyze the potential impact of AI on the healthcare industry"
)
print(results)
```
## With Dashboard Monitoring
```python theme={null}
workflow = ConcurrentWorkflow(
name="AnalysisTeam",
description="Concurrent analysis team",
agents=[market_analyst, financial_analyst, risk_analyst],
show_dashboard=True, # Enable real-time dashboard
max_loops=1,
)
results = workflow.run("Evaluate cryptocurrency market trends")
```
## With Streaming Callbacks
```python theme={null}
def streaming_callback(agent_name: str, chunk: str, is_final: bool):
"""Receive real-time updates from agents"""
if is_final:
print(f"\n[{agent_name}] Complete!")
else:
print(f"[{agent_name}]: {chunk}", end="", flush=True)
results = workflow.run(
task="Analyze Q4 performance",
streaming_callback=streaming_callback,
)
```
## Key Parameters
Name identifier for the workflow
List of agents to execute concurrently
Reserved for future use — currently stored but not applied. Each call to `run()` executes every agent exactly once regardless of this value; use `batch_run()` to process multiple tasks.
Enable real-time dashboard display
Output format for results
Enable automatic prompt engineering
Automatically save conversation history to the workflow workspace directory after each run
`ConcurrentWorkflow.__init__` accepts **two** similarly named parameters: `autosave` and `auto_save` (both default `True`). Only `autosave` has any effect — it is the flag that enables the workspace writer. `auto_save` is stored on the instance and never read, so setting `auto_save=False` does **not** turn saving off. Always use `autosave`.
Emit debug-level logging for workspace and autosave operations
How to handle an agent that raises. `"store"` records the error as that agent's output and lets the rest finish; `"raise"` propagates the first error and aborts the run.
Thread pool size. Defaults to `len(agents)` capped at 32. Agent calls are network-bound, so this is sized by agent count rather than CPU cores.
## Methods
### run()
Execute all agents concurrently on a task.
```python theme={null}
result = workflow.run(
task="Analyze market conditions",
img=None, # Optional image input
streaming_callback=None, # Optional callback
)
```
### batch\_run()
Process multiple tasks sequentially (each task runs agents concurrently).
```python theme={null}
tasks = [
"Analyze tech sector",
"Analyze healthcare sector",
"Analyze energy sector"
]
results = workflow.batch_run(tasks)
```
## Dashboard Features
When `show_dashboard=True`, you get:
* **Real-time Status**: See each agent's current state (pending, running, completed)
* **Output Preview**: Monitor agent outputs as they generate
* **Progress Tracking**: Visual progress indicators
* **Error Detection**: Immediate error visibility
* **Completion Summary**: Final dashboard with all results
## Use Cases
### Multi-Perspective Analysis
```python theme={null}
# Get technical, fundamental, and sentiment analysis simultaneously
technical_agent = Agent(agent_name="Technical-Analyst", ...)
fundamental_agent = Agent(agent_name="Fundamental-Analyst", ...)
sentiment_agent = Agent(agent_name="Sentiment-Analyst", ...)
analysis_team = ConcurrentWorkflow(
agents=[technical_agent, fundamental_agent, sentiment_agent]
)
insights = analysis_team.run("NVIDIA stock analysis")
```
### Parallel Research
```python theme={null}
# Research multiple aspects simultaneously
literature_researcher = Agent(agent_name="Literature-Researcher", ...)
market_researcher = Agent(agent_name="Market-Researcher", ...)
competitor_researcher = Agent(agent_name="Competitor-Researcher", ...)
research_team = ConcurrentWorkflow(
agents=[literature_researcher, market_researcher, competitor_researcher]
)
research = research_team.run("Electric vehicle market landscape")
```
### Batch Document Processing
```python theme={null}
# Process documents with multiple analyzers
summary_agent = Agent(agent_name="Summarizer", ...)
sentiment_agent = Agent(agent_name="Sentiment-Analyzer", ...)
key_points_agent = Agent(agent_name="Key-Points-Extractor", ...)
processing_team = ConcurrentWorkflow(
agents=[summary_agent, sentiment_agent, key_points_agent]
)
documents = ["doc1.txt", "doc2.txt", "doc3.txt"]
results = processing_team.batch_run(documents)
```
## Performance Optimization
### CPU Core Utilization
The thread pool is sized by agent count, capped at 32, since agent calls are network-bound rather than CPU-bound:
```python theme={null}
import os
# Automatically calculated
max_workers = max(1, min(len(self.agents), MAX_CONCURRENT_AGENTS)) # MAX_CONCURRENT_AGENTS = 32
```
### Agent Configuration for Concurrency
```python theme={null}
# Disable printing for dashboard mode
if show_dashboard:
for agent in agents:
agent.print_on = False
```
## Advanced Features
### Agent Status Tracking
```python theme={null}
workflow = ConcurrentWorkflow(
agents=[agent1, agent2, agent3],
show_dashboard=True,
)
# Internal status tracking for each agent
# - status: "pending" | "running" | "completed" | "error"
# - output: Current agent output
print(workflow.agent_statuses)
```
### Conversation Aggregation
```python theme={null}
result = workflow.run("Task")
# Access aggregated conversation
history = workflow.conversation.conversation_history
# Format:
# [{"role": "User", "content": "Task"},
# {"role": "Agent1", "content": "Response1"},
# {"role": "Agent2", "content": "Response2"}]
```
## Output Types
Supported output formats:
* `"dict-all-except-first"`: Dictionary excluding initial user message
* `"dict"`: Complete conversation dictionary
* `"str"`: Concatenated string output
* `"list"`: List of all messages
```python theme={null}
workflow = ConcurrentWorkflow(
agents=agents,
output_type="dict",
)
```
## Best Practices
**Performance Tip**: Use concurrent workflow when agents can truly work independently
1. **Independent Agents**: Ensure agents don't need each other's outputs
2. **Appropriate Size**: 3-8 agents typically optimal for most systems
3. **Dashboard Usage**: Enable for debugging, disable for production
4. **Resource Management**: Monitor CPU/memory with large agent counts
5. **Error Handling**: One agent failure doesn't stop others
Concurrent execution means agents run simultaneously - ensure your LLM API can handle parallel requests
## Error Handling
```python theme={null}
try:
results = workflow.run("Analyze market")
except Exception as e:
print(f"Workflow error: {e}")
# Individual agent errors are captured in results
```
## Related Architectures
* [Sequential Workflow](/architectures/sequential-workflow) - For ordered execution
* [Mixture of Agents](/architectures/mixture-of-agents) - For synthesis of parallel outputs
* [Agent Rearrange](/architectures/agent-rearrange) - For mixed patterns
# Graph Workflow
Source: https://docs.swarms.world/architectures/graph-workflow
Orchestrate complex agent workflows using Directed Acyclic Graphs (DAGs) with parallel and sequential execution
The `GraphWorkflow` orchestrates agents using a Directed Acyclic Graph (DAG) structure, enabling complex workflows with dependencies, parallel branches, and convergence points. Ideal for sophisticated pipelines with intricate task relationships.
## When to Use
* **Complex dependencies**: Tasks with intricate dependency graphs
* **Parallel branches**: Multiple independent paths that converge
* **Pipeline optimization**: Maximize parallelism while respecting dependencies
* **Software builds**: Compile, test, and deploy pipelines
* **Data processing**: ETL workflows with multiple stages
## Key Features
* DAG-based execution with topological sorting
* Automatic parallelization of independent nodes
* Support for NetworkX and Rustworkx backends
* Fan-out and fan-in patterns
* Entry and exit point management
* Graph visualization (with Graphviz)
* Auto-compilation for performance
* Graph validation and cycle detection
## Basic Example
```python theme={null}
from swarms import Agent, GraphWorkflow, Node, Edge, NodeType
# Define agents
data_collector = Agent(
agent_name="DataCollector",
system_prompt="Collect and validate data from sources.",
model_name="gpt-5.4",
)
processor = Agent(
agent_name="Processor",
system_prompt="Process and clean collected data.",
model_name="gpt-5.4",
)
analyzer = Agent(
agent_name="Analyzer",
system_prompt="Analyze processed data for insights.",
model_name="gpt-5.4",
)
# Create graph workflow
workflow = GraphWorkflow(
name="Data-Pipeline",
description="ETL workflow for data processing",
)
# Add agents as nodes
workflow.add_node(data_collector)
workflow.add_node(processor)
workflow.add_node(analyzer)
# Define dependencies
workflow.add_edge("DataCollector", "Processor") # Collector -> Processor
workflow.add_edge("Processor", "Analyzer") # Processor -> Analyzer
# Compile and run
workflow.compile()
result = workflow.run("Process Q4 sales data")
print(result)
```
## Creating from Spec
Simplified workflow creation:
```python theme={null}
from swarms import GraphWorkflow
# Define agents
agents = [collector, processor, analyzer, reporter]
# Define edges (dependencies)
edges = [
("DataCollector", "Processor"),
("Processor", "Analyzer"),
("Analyzer", "Reporter"),
]
# Create workflow
workflow = GraphWorkflow.from_spec(
agents=agents,
edges=edges,
task="Process data",
)
result = workflow.run()
```
## Advanced Edge Patterns
### Fan-Out Pattern
One node distributes to multiple nodes:
```python theme={null}
# Single edge to multiple targets
workflow.add_edges_from_source(
source="DataCollector",
targets=["TechnicalAnalyst", "FundamentalAnalyst", "SentimentAnalyst"]
)
# Equivalent to:
# DataCollector -> TechnicalAnalyst
# DataCollector -> FundamentalAnalyst
# DataCollector -> SentimentAnalyst
# (All three analysts run in parallel)
```
### Fan-In Pattern
Multiple nodes converge to one:
```python theme={null}
# Multiple sources to single target
workflow.add_edges_to_target(
sources=["TechnicalAnalyst", "FundamentalAnalyst", "SentimentAnalyst"],
target="SynthesisAgent"
)
# Equivalent to:
# TechnicalAnalyst -> SynthesisAgent
# FundamentalAnalyst -> SynthesisAgent
# SentimentAnalyst -> SynthesisAgent
# (Synthesis waits for all three)
```
### Parallel Chain Pattern
Full mesh connection:
```python theme={null}
# Multiple sources to multiple targets
workflow.add_parallel_chain(
sources=["Collector1", "Collector2"],
targets=["Analyst1", "Analyst2", "Analyst3"]
)
# Creates:
# Collector1 -> Analyst1, Analyst2, Analyst3
# Collector2 -> Analyst1, Analyst2, Analyst3
```
### Tuple-Based Patterns
Simplified edge definitions:
```python theme={null}
edges = [
# Simple edge
("agent1", "agent2"),
# Fan-out
("agent1", ["agent2", "agent3"]),
# Fan-in
(["agent1", "agent2"], "agent3"),
# Parallel chain
(["agent1", "agent2"], ["agent3", "agent4"]),
]
workflow = GraphWorkflow.from_spec(
agents=agents,
edges=edges,
)
```
## Key Parameters
Name for the workflow
Description of the workflow's purpose
Dictionary of nodes (agents)
List of edges (dependencies)
Node IDs with no predecessors (auto-detected if not set)
Node IDs with no successors (auto-detected if not set)
Maximum execution loops
Automatically compile on initialization
Graph backend ("networkx" or "rustworkx")
Enable verbose logging
Default task used by `run()` when no `task` argument is passed.
Directory used to persist run checkpoints for later inspection/resumption.
Instance-level callback fired as `(node_id, output)` immediately after each node finishes. A callback passed directly to `run()` takes precedence over this one.
Caps how many nodes execute concurrently within a layer. Defaults to `max(1, int(get_cpu_cores() * 0.95))` when not set.
## Methods
### add\_node()
Add an agent to the graph:
```python theme={null}
workflow.add_node(
agent=my_agent,
metadata={"priority": "high"} # Optional metadata
)
```
### add\_nodes()
Add multiple agents concurrently:
```python theme={null}
workflow.add_nodes(
agents=[agent1, agent2, agent3],
batch_size=10,
)
```
### add\_edge()
Add a dependency between nodes:
```python theme={null}
# Using agent objects
workflow.add_edge(source_agent, target_agent)
# Using node IDs
workflow.add_edge("Agent1", "Agent2")
# Using Edge object
from swarms import Edge
edge = Edge(source="Agent1", target="Agent2", metadata={"type": "data"})
workflow.add_edge(edge)
```
### compile()
Pre-compute expensive operations:
```python theme={null}
# Manual compilation
workflow.compile()
# Auto-compilation (default)
workflow = GraphWorkflow(auto_compile=True)
```
Compilation:
* Auto-sets entry/exit points
* Computes topological layers
* Caches for performance
* Validates graph structure
### run()
Execute the workflow:
```python theme={null}
result = workflow.run(
task="Process data pipeline",
img=None, # Optional image input
)
```
`run()` also accepts `on_node_complete` (fired as `(node_id, output)` right after each node finishes, before its layer completes) and `streaming_callback` (fired as `(node_id, token)` for every token an agent generates). A callback passed to `run()` overrides the instance-level `on_node_complete` set in the constructor.
```python theme={null}
def on_done(node_id: str, output) -> None:
print(f"[{node_id}] finished")
result = workflow.run(
task="Process data pipeline",
on_node_complete=on_done,
streaming_callback=lambda node_id, token: print(token, end=""),
)
```
Return shape: with `max_loops == 1` (the default), `run()` returns a `Dict[str, Any]` keyed by node ID. With `max_loops > 1`, it returns per-loop results keyed as `{node_id}_loop_{loop_number}` plus the final loop's results under the plain `node_id` keys.
## Use Cases
### Software Build Pipeline
```python theme={null}
compile_agent = Agent(agent_name="Compiler", ...)
test_agent = Agent(agent_name="Tester", ...)
lint_agent = Agent(agent_name="Linter", ...)
security_agent = Agent(agent_name="SecurityScanner", ...)
package_agent = Agent(agent_name="Packager", ...)
deploy_agent = Agent(agent_name="Deployer", ...)
build_pipeline = GraphWorkflow(name="CI-CD-Pipeline")
# Add all nodes
for agent in [compile_agent, test_agent, lint_agent, security_agent, package_agent, deploy_agent]:
build_pipeline.add_node(agent)
# Define dependencies
build_pipeline.add_edge("Compiler", "Tester")
build_pipeline.add_edges_from_source("Compiler", ["Linter", "SecurityScanner"])
build_pipeline.add_edges_to_target(["Tester", "Linter", "SecurityScanner"], "Packager")
build_pipeline.add_edge("Packager", "Deployer")
build_pipeline.compile()
result = build_pipeline.run("Build and deploy version 2.0")
```
### Data Science Pipeline
```python theme={null}
edges = [
# Data collection phase
("APICollector", "DataValidator"),
("DatabaseCollector", "DataValidator"),
# Parallel processing
("DataValidator", ["Cleaner", "Transformer", "FeatureEngineer"]),
# Convergence for modeling
(["Cleaner", "Transformer", "FeatureEngineer"], "ModelTrainer"),
# Evaluation and deployment
("ModelTrainer", "ModelEvaluator"),
("ModelEvaluator", "Deployer"),
]
ml_pipeline = GraphWorkflow.from_spec(
agents=[api_collector, db_collector, validator, cleaner, transformer,
feature_eng, trainer, evaluator, deployer],
edges=edges,
)
result = ml_pipeline.run("Train and deploy customer churn model")
```
### Content Creation Workflow
```python theme={null}
# Diamond pattern: Research -> (Write, Design) -> Review
edges = [
("Researcher", ["Writer", "Designer"]),
(["Writer", "Designer"], "Reviewer"),
("Reviewer", "Publisher"),
]
content_workflow = GraphWorkflow.from_spec(
agents=[researcher, writer, designer, reviewer, publisher],
edges=edges,
)
result = content_workflow.run("Create marketing campaign for product launch")
```
## Entry and Exit Points
### Auto-Detection
```python theme={null}
workflow = GraphWorkflow()
workflow.add_node(agent1)
workflow.add_node(agent2)
workflow.add_node(agent3)
workflow.add_edge("agent1", "agent2")
workflow.add_edge("agent2", "agent3")
workflow.compile()
# Automatically detects:
# - entry_points: ["agent1"] (no incoming edges)
# - end_points: ["agent3"] (no outgoing edges)
```
### Manual Setting
```python theme={null}
workflow.set_entry_points(["StartAgent"])
workflow.set_end_points(["FinalAgent"])
```
## Backend Selection
### NetworkX (Default)
```python theme={null}
workflow = GraphWorkflow(backend="networkx")
```
Benefits:
* Pure Python
* Rich ecosystem
* Extensive algorithms
* Easy debugging
### Rustworkx (Performance)
```python theme={null}
workflow = GraphWorkflow(backend="rustworkx")
```
Benefits:
* Rust-based performance
* Faster graph operations
* Lower memory usage
* Better for large graphs
Requires: `pip install rustworkx`
## Topological Execution
The workflow executes in topological layers:
```python theme={null}
# Graph:
# A -> B, C
# B -> D
# C -> D
# Execution layers:
# Layer 0: [A]
# Layer 1: [B, C] (parallel)
# Layer 2: [D]
```
Parallel execution within layers using ThreadPoolExecutor.
## Graph Validation
### Cycle Detection
`compile()` never raises on a cycle by itself — internally it calls `validate(auto_fix=False, raise_on_error=False)` and only logs a warning. To turn cycle detection into an exception, call `validate(raise_on_error=True)` explicitly: a detected cycle counts as a "serious warning" that marks the workflow invalid (unless `auto_fix=True`), so `raise_on_error=True` will raise `ValueError` for it.
```python theme={null}
workflow.add_edge("A", "B")
workflow.add_edge("B", "C")
workflow.add_edge("C", "A") # Creates cycle
workflow.compile() # succeeds silently — cycles only warn here
result = workflow.validate()
if result["cycles"]:
print(f"Cycle(s) detected: {result['cycles']}")
try:
workflow.validate(raise_on_error=True)
except ValueError as e:
print(f"Invalid workflow: {e}")
```
### Dependency Validation
`validate()` checks for (each reported as a warning or error in the returned dict):
* Referenced nodes existing / valid agent instances on every node (error)
* Isolated nodes (no incoming or outgoing edges)
* Cyclic dependencies (detected via `simple_cycles()`, returned under `result["cycles"]`)
* Unreachable nodes (not reachable from any entry point)
* Dead-end nodes (cannot reach any end point)
* Missing entry points / end points
```python theme={null}
result = workflow.validate(auto_fix=True)
print(result["errors"], result["warnings"], result["fixed"])
```
## Performance Optimization
### Compilation Caching
```python theme={null}
# First run: compiles
result1 = workflow.run("Task 1")
# Subsequent runs: uses cache
result2 = workflow.run("Task 2")
result3 = workflow.run("Task 3")
# Manual recompilation (if graph changed)
workflow.compile()
```
### Concurrent Node Addition
```python theme={null}
# Add many nodes efficiently
workflow.add_nodes(
agents=agent_list,
batch_size=10, # Process in batches
)
```
## Best Practices
**Graph Design**: Keep graphs acyclic - use multiple workflows for iterative processes
1. **Clear Dependencies**: Only add edges for true dependencies
2. **Maximize Parallelism**: Let independent nodes run concurrently
3. **Compilation**: Always compile before running
4. **Entry/Exit Points**: Let auto-detection work unless specific control needed
5. **Backend Choice**: Use Rustworkx for large graphs (>100 nodes)
Graph compilation is cached - manually recompile if graph structure changes after initial compilation
## Error Handling
```python theme={null}
try:
workflow.add_edge("NonExistentAgent", "TargetAgent")
except ValueError as e:
print(f"Invalid edge: {e}")
# Source or target node doesn't exist
try:
workflow.compile()
except Exception as e:
print(f"Compilation failed: {e}")
# Cycle detected or invalid graph structure
```
## Visualization
With Graphviz installed:
```python theme={null}
# Requires: pip install graphviz
path = workflow.visualize(
format="png", # "png", "svg", "pdf", or "dot"
view=True, # open the file after generating it
engine="dot", # graphviz layout engine
show_summary=False,
)
```
`visualize()` renders nodes and edges with Graphviz (auto-detecting fan-out/fan-in patterns for clearer styling) and returns the path to the generated file. It raises `ImportError` if `graphviz` is not installed. For a dependency-free text view, use `workflow.visualize_simple()`, which returns an ASCII representation of the graph.
## Related Architectures
* [Agent Rearrange](/architectures/agent-rearrange) - Simpler flow patterns
* [Sequential Workflow](/architectures/sequential-workflow) - Linear execution
* [Concurrent Workflow](/architectures/concurrent-workflow) - Pure parallel
* [Hierarchical Swarm](/architectures/hierarchical-swarm) - Director coordination
# Group Chat
Source: https://docs.swarms.world/architectures/group-chat
An asynchronous, self-selecting multi-agent conversation for debate, brainstorming, and decision-making
`GroupChat` runs a **turn-based, self-selecting** conversation: there is no fixed speaking order and no speaker-selection function, but exactly one agent speaks per turn. Each turn, every agent privately "bids" — via a forced `respond(score, message)` tool call — on how much it wants the floor; the single highest (recency-adjusted) bidder above `threshold` speaks, and only that reply is posted. A `recency_penalty` discourages the same agent from speaking twice in a row, so the floor moves around the room even though there's no explicit rotation.
## When to Use
* **Debate and discussion**: multiple perspectives on a complex topic
* **Collaborative problem-solving**: agents build on each other through conversation
* **Brainstorming**: emergent ideas from parallel contributions
* **Negotiation**: back-and-forth between stakeholders
* **Peer review**: evaluating work from several angles at once
This is a rewrite of the older speaker-function design. `speaker_function`, `speaker_state`, `set_speaker_function`, `start_interactive_session`, `@mention` routing, and the `round-robin-speaker` / `random-speaker` / `priority-speaker` selectors **no longer exist**. Use `threshold` / `recency_penalty` / `max_loops` to shape the conversation instead. See the [GroupChat API reference](/api/group-chat).
## How It Works
1. **Seed** — the task is posted to the shared conversation as the first message; every agent sees it.
2. **Bid (in parallel)** — each turn, every agent is asked concurrently (via a forced `respond(score, message)` tool call) how much it wants to speak, on a `0..1` scale, along with the reply it would give.
3. **Select one speaker** — the single highest *recency-adjusted* bidder that clears `threshold` and has a non-empty reply takes the floor. Only that one reply is posted to the conversation for this turn.
4. **Recency penalty** — an agent that spoke within the last `recency_window` turns has `recency_penalty` subtracted from its bid, so the floor tends to move around the room instead of one agent monologuing.
5. **Stop** — the chat ends when `max_loops` total messages have been posted, or a turn arrives where no agent's adjusted bid clears `threshold` (a conversational lull).
`idle_timeout` is accepted for backward compatibility but is currently unused — the chat stops on a bidding lull (step 5 above), not a wall-clock timeout.
## Key Features
* Turn-based self-selection: bids are collected in parallel, but exactly one agent speaks per turn (no fixed speaking order)
* Self-selection: silence is the default; agents speak only when they add value
* Forced `respond(score, message)` decision via `RESPOND_TOOL`
* Threshold-based speaker selection with a recency penalty to rotate the floor
* Auto-equips the `respond` tool into agents (`auto_equip=True`)
* Conversation history tracking and flexible output formats
## Basic Example
```python theme={null}
from swarms import Agent, GroupChat
tech_optimist = Agent(
agent_name="TechOptimist",
system_prompt="You argue for the benefits of AI in society.",
model_name="gpt-5.4",
max_loops=1,
persistent_memory=False,
)
tech_critic = Agent(
agent_name="TechCritic",
system_prompt="You argue against unchecked AI advancement.",
model_name="gpt-5.4",
max_loops=1,
persistent_memory=False,
)
realist = Agent(
agent_name="Realist",
system_prompt="You weigh both sides and seek a balanced view.",
model_name="gpt-5.4",
max_loops=1,
persistent_memory=False,
)
chat = GroupChat(
name="AI-Ethics-Debate",
description="Discussion on AI's societal impact",
agents=[tech_optimist, tech_critic, realist],
max_loops=8, # hard cap on total messages
threshold=0.5, # only the top bidder above 0.5 takes the floor each turn
recency_penalty=0.3, # discourage the same agent speaking twice in a row
)
result = chat.run("Should we prioritize AI development or AI regulation?")
print(result)
```
`auto_equip=True` (the default) injects the `respond` tool into each agent, so you do not need to add `tools_list_dictionary=[RESPOND_TOOL]` yourself.
## Shaping the Conversation
There is no speaker function — you steer the room with three parameters.
### Threshold
```python theme={null}
# Livelier: more agents chime in on each message.
lively = GroupChat(agents=agents, max_loops=20, threshold=0.4)
# More selective: only strongly-motivated, high-value replies are published.
focused = GroupChat(agents=agents, max_loops=12, threshold=0.75)
```
### Recency penalty
```python theme={null}
# Rotate the floor more aggressively so no agent can speak twice in a row.
rotating = GroupChat(agents=agents, max_loops=16, recency_penalty=0.5, recency_window=1)
# Allow an agent to keep the floor across consecutive turns if it keeps winning bids.
persistent = GroupChat(agents=agents, max_loops=16, recency_penalty=0.0)
```
### Max loops (total messages)
`max_loops` caps the **total number of messages** posted (the seed task counts as the first), not turns per agent — it's the primary cost control.
```python theme={null}
# At most 6 messages total, then the chat stops.
quick = GroupChat(agents=[proponent, opponent], max_loops=6)
```
## Key Parameters
Name for the group chat.
Description of the group chat's purpose.
Participating agents. **At least two are required** — each message is broadcast to the other agents.
Hard cap on total messages posted, including the initial user task.
Minimum recency-adjusted decision score (`0..1`) required for an agent to take the floor for a turn.
Amount subtracted from an agent's bid if it spoke within the last `recency_window` turns. Discourages one agent from monologuing; set to `0.0` to disable.
How many of the most recent speakers are subject to `recency_penalty`.
Accepted for backward compatibility but currently **unused** — the chat now stops on a bidding lull (no agent clears `threshold`) rather than a wall-clock timeout.
History format. Use `"list"` or `"dict"` to iterate individual messages.
Auto-inject the `respond` tool into agents that lack it.
Emit internal log messages (decision scores, broadcasts, stop events) and print each posted message as a styled panel.
## Methods
### run()
Run the group chat until no agent's bid clears `threshold` (a lull) or `max_loops` is hit.
```python theme={null}
result = chat.run("Discuss the future of quantum computing")
```
By default the result is a formatted string. For per-message iteration, set `output_type="list"` and read `role` / `content`:
```python theme={null}
chat = GroupChat(agents=agents, max_loops=8, output_type="list")
for message in chat.run("Discuss the tradeoffs of multi-agent systems."):
print(f"[{message['role']}]: {message['content']}")
```
### run\_batch()
Run several independent group chats sequentially, one per task.
```python theme={null}
results = chat.run_batch([
"Topic A to discuss",
"Topic B to discuss",
])
```
## The `respond` Tool
Every agent must carry `RESPOND_TOOL` so the chat can force a structured speaking decision. With `auto_equip=True` this is automatic; otherwise add it yourself:
```python theme={null}
from swarms import Agent
from swarms.structs.groupchat import GroupChat, RESPOND_TOOL
agents = [
Agent(
agent_name=name,
system_prompt=prompt,
model_name="gpt-5.4",
max_loops=1,
persistent_memory=False,
tools_list_dictionary=[RESPOND_TOOL],
)
for name, prompt in [
("Researcher", "You contribute research and evidence."),
("Critic", "You stress-test claims and find weaknesses."),
]
]
chat = GroupChat(agents=agents, auto_equip=False, max_loops=8)
result = chat.run("Debate the tradeoffs of autonomous agents.")
```
The tool forces a call to `respond(score, message)`: `score` (`0..1`) is how much the agent wants to speak, and `message` is the reply (empty string to stay silent). Each turn, only the single agent with the highest recency-adjusted `score` above `threshold` gets its `message` published.
## Use Cases
### Debate
```python theme={null}
pro = Agent(agent_name="Pro", system_prompt="Argue for the motion.",
model_name="gpt-5.4", max_loops=1, persistent_memory=False)
con = Agent(agent_name="Con", system_prompt="Argue against the motion.",
model_name="gpt-5.4", max_loops=1, persistent_memory=False)
moderator = Agent(agent_name="Moderator", system_prompt="Summarize and find common ground.",
model_name="gpt-5.4", max_loops=1, persistent_memory=False)
debate = GroupChat(
name="AI-Debate",
agents=[pro, con, moderator],
max_loops=10,
threshold=0.5,
)
verdict = debate.run("Should AI development be regulated?")
```
### Expert Panel
```python theme={null}
research_chat = GroupChat(
name="Research-Collaboration",
agents=[literature_expert, data_scientist, statistician, writer],
max_loops=14,
threshold=0.6, # specialists stay quiet outside their domain
)
paper = research_chat.run("Collaborate on a paper about machine learning.")
```
## Best Practices
**Tuning over speaker functions**: shape participation with `threshold` (selectivity), `recency_penalty` (how aggressively the floor rotates), and `max_loops` (total length) — there is no speaker-selection function.
1. **Distinct roles**: give each agent a specific perspective so its `respond` decision is meaningful.
2. **`max_loops=1` + `persistent_memory=False` per agent**: keep each speaking decision a clean single-shot call.
3. **Tune threshold to room size**: lower (`~0.4–0.5`) for 2–3 agents, higher (`~0.6–0.75`) for 4+.
4. **Pick the right `output_type`**: a transcript string by default, or `"list"`/`"dict"` to iterate messages.
Conversation length grows with agents and turns — use `max_loops` to bound total messages and watch context limits.
## When NOT to Use
* **Simple tasks** — use a single `Agent`.
* **Independent analysis** — when agents shouldn't influence each other, use [ConcurrentWorkflow](/architectures/concurrent-workflow).
* **Strict ordering** — when a fixed sequence is required, use [SequentialWorkflow](/architectures/sequential-workflow).
* **Director-led delegation** — use [HierarchicalSwarm](/architectures/hierarchical-swarm).
## Related Architectures
* [Hierarchical Swarm](/architectures/hierarchical-swarm) - Structured coordination
* [Mixture of Agents](/architectures/mixture-of-agents) - Parallel with synthesis
* [Social Algorithms](/architectures/social-algorithms) - Custom communication patterns
* [Agent Rearrange](/architectures/agent-rearrange) - Custom flows
# Heavy Swarm
Source: https://docs.swarms.world/architectures/heavy-swarm
Multi-phase orchestration that decomposes a task into specialized questions, runs them through expert agents in parallel, and synthesizes a final answer
The `HeavySwarm` is a multi-agent orchestration system inspired by X.AI's Grok Heavy implementation. It decomposes a task into role-specific questions, runs those questions through specialized expert agents in parallel, and then synthesizes the outputs into a single comprehensive answer. The exact set of experts is controlled by the `variant` parameter.
## When to Use
* **Complex research tasks** — in-depth investigation across multiple angles
* **Financial analysis** — investment decisions requiring multiple viewpoints
* **Strategic planning** — comprehensive evaluation of options and trade-offs
* **Due diligence** — thorough verification and risk assessment
* **Multi-faceted problems** — issues that need research, analysis, and synthesis combined
## Key Features
* Intelligent question generation tailored to each agent role
* Three preset variants — `default` (5 agents), `medium` (4 Grok-style agents), `heavy` (16 agents)
* True parallel execution via a `ThreadPoolExecutor`
* Synthesis agent that integrates expert outputs into a final answer
* Optional real-time `rich` dashboard
* Multi-loop iterative refinement (each loop builds on the previous result)
* Tool integration through `worker_tools`
* Inherits `SerializableMixin` — `to_dict()` is available for telemetry / persistence
## Architecture
```
1. Question Generation
- Director model analyzes the task
- Emits a JSON schema with one question per expert role
2. Parallel Expert Execution (variant-dependent)
- default : Research, Analysis, Alternatives, Verification
- medium : Captain + Harper, Benjamin, Lucas
- heavy : Grok captain + 15 domain specialists
3. Synthesis
- Synthesis agent integrates all expert outputs
- Produces the final report
4. Optional Multi-Loop Refinement
- Each subsequent loop receives the previous synthesis as context
```
## Basic Example
```python theme={null}
from swarms import HeavySwarm
swarm = HeavySwarm(
name="Investment-Research-Team",
description="Comprehensive investment analysis",
question_agent_model_name="gpt-5.4",
worker_model_name="gpt-5.4",
show_dashboard=True,
max_loops=1,
)
result = swarm.run(
"Should we invest in NVIDIA stock? Provide detailed analysis."
)
print(result)
```
## With Tool Integration
```python theme={null}
from swarms import HeavySwarm
from swarms_tools import exa_search
swarm = HeavySwarm(
name="Market-Research-Team",
description="Research team with web search capabilities",
question_agent_model_name="gpt-5.4",
worker_model_name="claude-sonnet-4-6",
worker_tools=[exa_search], # tools available to every worker
show_dashboard=True,
max_loops=2, # iterative refinement
)
result = swarm.run(
"Find the best 3 gold ETFs with current data from the web"
)
```
## Selecting a Variant
The `variant` parameter controls which agents are instantiated.
```python theme={null}
# Five-agent default (Research / Analysis / Alternatives / Verification + Synthesis)
swarm = HeavySwarm(variant="default")
# Four-agent Grok-style team (Captain + Harper, Benjamin, Lucas)
swarm = HeavySwarm(variant="medium")
# Sixteen-agent deep team (Grok captain + 15 domain specialists)
swarm = HeavySwarm(variant="heavy")
```
`SwarmVariant` is exported from `swarms.agents.heavy_swarm_agents`. Passing an unknown variant raises `ValueError` during initialization.
## Specialized Agents (default variant)
### Research Agent
* Comprehensive information gathering
* Data collection and validation
* Source verification
* Literature review
* Statistical data interpretation
### Analysis Agent
* Pattern recognition
* Statistical analysis
* Predictive modeling
* Data interpretation
* Performance metrics
### Alternatives Agent
* Strategic thinking
* Creative problem-solving
* Option generation
* Trade-off evaluation
* Scenario planning
### Verification Agent
* Fact-checking
* Feasibility assessment
* Risk analysis
* Compliance verification
* Quality assurance
### Synthesis Agent
* Multi-perspective integration
* Comprehensive analysis
* Executive summary creation
* Strategic alignment
* Actionable recommendations
## Key Parameters
Identifier for the swarm instance.
Description of the swarm's purpose.
Maximum execution time per agent in seconds.
Model used by the question-generation agent.
Model used by every specialized worker agent.
Enable detailed logging output.
Enable the real-time `rich` progress dashboard.
Print each agent's individual output.
Format of the returned conversation history.
Tools made available to all worker agents.
Number of full swarm iterations. Each loop refines the previous synthesis.
Which agent line-up to instantiate. See **Selecting a Variant** above.
## Methods
### `run(task, img=None)`
Execute the full multi-phase workflow.
```python theme={null}
result = swarm.run(
task="Analyze cryptocurrency market trends",
img=None, # optional image input
)
```
### `to_dict()`
Inherited from `SerializableMixin`. Returns a JSON-friendly snapshot of the swarm's config. The `agents`, `conversation`, `dashboard`, and `worker_tools` attributes are excluded via `_to_dict_exclude` to keep the snapshot lightweight.
```python theme={null}
snapshot = swarm.to_dict()
```
## Question Generation
The question agent emits a JSON object whose schema depends on the variant. For the default variant it looks like:
```python theme={null}
{
"thinking": "Reasoning for how to break down the task",
"research_question": "Question for Research Agent",
"analysis_question": "Question for Analysis Agent",
"alternatives_question": "Question for Alternatives Agent",
"verification_question": "Question for Verification Agent"
}
```
Example generated questions for *"Invest in NVIDIA?"*:
```json theme={null}
{
"thinking": "Need to evaluate financials, market position, alternatives, and risks",
"research_question": "Research NVIDIA's financial performance, product pipeline, and market position in AI chips",
"analysis_question": "Analyze NVIDIA's revenue growth, profit margins, and competitive advantages in the AI accelerator market",
"alternatives_question": "What are alternative semiconductor investments with similar growth potential?",
"verification_question": "Verify NVIDIA's claimed AI leadership and assess risks to their market dominance"
}
```
## Multi-Loop Refinement
With `max_loops > 1` the swarm iterates, each loop feeding the previous synthesis back as context:
```python theme={null}
swarm = HeavySwarm(
name="Deep-Analysis-Team",
worker_model_name="claude-sonnet-4-6",
max_loops=3,
)
result = swarm.run("Complex strategic decision")
```
Per-loop semantics:
1. Loop 1: original task only
2. Loop 2: `"Previous loop results: