Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 106 additions & 11 deletions docs/concepts/multi-agent/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,33 @@ Complex tasks benefit from specialization. Instead of one monolithic agent tryin

Each agent has its own model, tools, and instructions — optimized for its specific role.

## How Delegation Works
## Two Patterns: Delegation vs. Handoffs

Agents delegate tasks using the built-in `transfer_task` tool, which is automatically available to any agent with sub-agents. This smart delegation means agents can automatically route tasks to the most suitable specialist.
docker-agent supports two multi-agent patterns:

| | **Delegation** (`sub_agents`) | **Handoffs** (`handoffs`) |
|---|---|---|
| **Topology** | Hierarchical (parent → child → parent) | Peer-to-peer graph (A → B → C → A) |
| **Session** | Child runs in a **sub-session** | Conversation stays in the **same session** |
| **Context** | Child gets a clean task description | Next agent sees the **full conversation history** |
| **Control flow** | Parent blocks until child finishes, then continues | Active agent switches — previous agent is no longer in the loop |
| **Tool** | `transfer_task` | `handoff` |
| **Best for** | Task delegation to specialists | Pipeline workflows, conversational routing |

You can combine both patterns in the same configuration — an agent can have both `sub_agents` and `handoffs`.

<div class="callout callout-tip">
<div class="callout-title">💡 When to use which
</div>
<p><strong><code>sub_agents</code></strong> — Use when a coordinator needs to send tasks to specialists and synthesize their results.</p>
<p><strong><code>handoffs</code></strong> — Use when agents should take turns processing the same conversation (pipelines, routing).</p>
<p><strong><code>background_agents</code></strong> — Use when multiple independent tasks can run simultaneously.</p>

</div>

## Delegation with `sub_agents`

Agents delegate tasks using the built-in `transfer_task` tool, which is automatically available to any agent with `sub_agents`. The parent agent sends a task to a child agent, waits for the result, and then continues.

1. **User** sends a message to the root agent
2. **Root agent** analyzes the request and decides which sub-agent should handle it
Expand All @@ -45,11 +69,89 @@ transfer_task(

</div>

## Handoffs Routing

Handoffs are a peer-to-peer routing pattern where agents **hand off the entire conversation** to another agent. Unlike delegation, there is no sub-session — the conversation stays in a single session and the active agent simply switches.

This pattern is ideal for:

- **Pipeline workflows** — data flows through a chain of specialized agents
- **Conversational routing** — a coordinator routes the user to the right specialist, who can route back when done
- **Graph topologies** — agents can form cycles (A → B → C → A), enabling iterative workflows

### How It Works

1. **User** sends a message to the starting agent
2. **Agent A** processes the message, then calls `handoff` to route to **Agent B**
3. **Agent B** becomes the active agent and sees the **full conversation history**
4. **Agent B** can respond, use its own tools, or hand off to another agent
5. This continues until an agent responds directly without handing off

```bash
# The handoff tool call looks like:
handoff(
agent="summarizer"
)
```

<div class="callout callout-info">
<div class="callout-title">ℹ️ Scoped Handoff Targets
</div>
<p>Each agent can only hand off to agents listed in its own <code>handoffs</code> array. The <code>handoff</code> tool is automatically injected — you don't need to add it manually.</p>

</div>

### Example

A coordinator routes to a researcher, who hands off to a summarizer, who returns to the coordinator:

```
Root ──→ Researcher ──→ Summarizer ──→ Root
```

```yaml
agents:
root:
model: anthropic/claude-sonnet-4-5
description: Coordinator that routes queries
instruction: |
Route research queries to the researcher.
handoffs:
- researcher

researcher:
model: openai/gpt-4o
description: Web researcher
instruction: |
Search the web, then hand off to the summarizer.
toolsets:
- type: mcp
ref: docker:duckduckgo
handoffs:
- summarizer

summarizer:
model: openai/gpt-4o-mini
description: Summarizes findings
instruction: |
Summarize the research results, then hand off
back to root.
handoffs:
- root
```

<div class="callout callout-tip">
<div class="callout-title">💡 Full pipeline example
</div>
<p>For a more complex handoff graph with branching and multiple processing stages, see <a href="https://github.com/docker/docker-agent/blob/main/examples/handoff.yaml"><code>examples/handoff.yaml</code></a>.</p>

</div>

## Parallel Delegation with Background Agents

`transfer_task` is **sequential** — the coordinator waits for the sub-agent to finish before continuing. When you need to fan out work to multiple agents at the same time, use the `background_agents` toolset instead.

Add it to your coordinators toolsets:
Add it to your coordinator's toolsets:

```yaml
agents:
Expand Down Expand Up @@ -81,14 +183,6 @@ list_background_agents()
view_background_agent(task_id="agent_task_abc123")
```

<div class="callout callout-tip">
<div class="callout-title">💡 When to use which
</div>
<p><strong><code>transfer_task</code></strong> — simple, sequential delegation. Best when the coordinator needs the result before deciding what to do next.</p>
<p><strong><code>background_agents</code></strong> — parallel, async delegation. Best when multiple independent tasks can run simultaneously.</p>

</div>

## Example: Development Team

```yaml
Expand Down Expand Up @@ -213,6 +307,7 @@ toolsets:
- **Give minimal tools** — Only give each agent the tools it needs for its specific role
- **Use the think tool** — Give coordinators the think tool so they reason about delegation
- **Use the right model** — Use capable models for complex reasoning, cheap models for simple tasks
- **Choose the right pattern** — Use `sub_agents` for hierarchical task delegation, `handoffs` for pipeline workflows and conversational routing

<div class="callout callout-info">
<div class="callout-title">ℹ️ Beyond docker-agent
Expand Down
4 changes: 2 additions & 2 deletions docs/configuration/agents/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ agents:
commands: # Optional: named prompts
name: "prompt text"
welcome_message: string # Optional: message shown at session start
handoffs: [list] # Optional: list of A2A handoff agents
handoffs: [list] # Optional: agent names this agent can hand off to
hooks: # Optional: lifecycle hooks
pre_tool_use: [list]
post_tool_use: [list]
Expand Down Expand Up @@ -77,7 +77,7 @@ agents:
| `skills` | boolean | ✗ | Enable automatic skill discovery from standard directories. |
| `commands` | object | ✗ | Named prompts that can be run with `docker agent run config.yaml /command_name`. |
| `welcome_message` | string | ✗ | Message displayed to the user when a session starts. Useful for providing context or instructions. |
| `handoffs` | array | ✗ | List of A2A agent configurations this agent can delegate to. See [A2A Protocol]({{ '/features/a2a/' | relative_url }}). |
| `handoffs` | array | ✗ | List of agent names this agent can hand off the conversation to. Enables the `handoff` tool. See [Handoffs Routing]({{ '/concepts/multi-agent/#handoffs-routing' | relative_url }}). |
| `hooks` | object | ✗ | Lifecycle hooks for running commands at various points. See [Hooks]({{ '/configuration/hooks/' | relative_url }}). |
| `structured_output` | object | ✗ | Constrain agent output to match a JSON schema. See [Structured Output]({{ '/configuration/structured-output/' | relative_url }}). |

Expand Down
10 changes: 6 additions & 4 deletions docs/guides/tips/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,18 +259,20 @@ Understand the difference between `sub_agents` and `handoffs`:
<div class="cards">
<div class="card" style="cursor:default;">
<h3>sub_agents (transfer_task)</h3>
<p>Delegates task to a child, waits for result, then continues. The parent remains in control.</p>
<p>Delegates task to a child in a sub-session, waits for result, then continues. Hierarchical — the parent remains in control.</p>
<pre style="margin-top:12px"><code class="language-yaml">sub_agents: [researcher, writer]</code></pre>
</div>
<div class="card" style="cursor:default;">
<h3>handoffs (A2A)</h3>
<p>Transfers control entirely to another agent (possibly remote). One-way handoff.</p>
<h3>handoffs (peer-to-peer)</h3>
<p>Hands off the entire conversation to another agent in the same session. The active agent switches and sees the full history. Agents can form cycles.</p>
<pre style="margin-top:12px"><code class="language-yaml">handoffs:
- specialist
- namespace/remote-agent</code></pre>
- summarizer</code></pre>
</div>
</div>

See <a href="{{ '/concepts/multi-agent/' | relative_url }}">Multi-Agent Systems</a> for a detailed comparison.

### Give Sub-Agents Clear Descriptions

The root agent uses descriptions to decide which sub-agent to delegate to:
Expand Down
Loading