Quick Start
How It Works
| Phase | What happens |
|---|---|
| 1. Fan-out | AgentFlow dispatches all workers in parallel (thread pool) |
| 2. Collect | All StepResult objects gathered into ctx.variables["parallel_outputs"] |
| 3. Aggregate | Next step (aggregator) receives the combined list and produces one response |
| Pattern | When to use |
|---|---|
parallel([a, b, c]) | Tasks do not depend on each other’s output |
| Sequential steps | Each step needs the previous result |
| Aggregator agent | Combine parallel outputs into one answer |
Configuration Options
parallel() accepts a list of agents or step callables. Each worker receives the same workflow context; results are collected in ctx.variables["parallel_outputs"] for the next step.
| Option | Type | Default | Description |
|---|---|---|---|
| Workers | List[Agent | Callable] | — | Agents or functions run concurrently |
| Context key | str | "parallel_outputs" | Where aggregated results are stored |
| Async | astart() | — | Use workflow.astart() for async execution |
Best Practices
Keep parallel tasks independent
Keep parallel tasks independent
Only parallelise work that does not need another worker’s output mid-flight. Route dependent steps after the aggregator.
Use an aggregator for synthesis
Use an aggregator for synthesis
A dedicated agent (or function step) after
parallel() turns multiple raw outputs into one coherent response.Prefer astart for I/O-heavy workers
Prefer astart for I/O-heavy workers
When workers call external APIs, use
await workflow.astart() so concurrent I/O does not block the event loop.Watch rate limits
Watch rate limits
Parallel LLM calls multiply token usage and API requests. Cap worker count or add a rate limiter if needed.
Related
Orchestrator Worker
Route tasks to specialised workers from a central orchestrator
AgentFlow
Build multi-step agent pipelines

