---
title: "Sub-agents"
description: "Delegate subtasks to child agent sessions"
---

An agent can spawn **sub-agents** to delegate work to independent child sessions. Each sub-agent gets its own LLM session and tool access, runs concurrently with the parent, and returns its result when finished.

<Note>
Sub-agents are only available with the [API backend](/core-concepts/agents#api-backend-default) (the default). Agents using the [CLI backend](/core-concepts/agents#cli-backend) cannot spawn sub-agents.
</Note>

## Tools

Sub-agent management is exposed through four built-in tools:

| Tool | Description |
|---|---|
| `spawn_agent` | Create a new sub-agent with a task prompt |
| `send_input` | Send follow-up input to a running sub-agent |
| `wait` | Block until a sub-agent completes and return its result |
| `close_agent` | Cancel and remove a running sub-agent |

These tools are registered automatically when the session starts. They inherit the parent's permissions.

## Session isolation

Each sub-agent runs in its own session:

- **Own conversation** -- the child starts with a fresh LLM history
- **Own tool access** -- the child can use the same tools as the parent
- **Concurrent execution** -- the parent can continue working before calling `wait`

The parent can spawn multiple sub-agents and synchronize with them later.

## Depth limits

Sub-agents can themselves spawn sub-agents, creating a hierarchy. `max_subagent_depth` limits how deep that tree can grow. By default the depth limit is `1`.

If a child tries to exceed the limit, `spawn_agent` returns an error immediately.

## Error handling

Sub-agent failures do not automatically fail the parent stage. The parent receives the failure through `wait` and decides how to respond.

Common cases:

- **Hits `max_turns`** -- returns normally with its last output
- **Panics or errors** -- returned as a failed `wait` result
- **`spawn_agent` fails** -- returned immediately as a tool result

## Event forwarding

Sub-agent observability now uses **session linkage**, not wrapper events.

Parent-owned lifecycle events:

| Event | When |
|---|---|
| `agent.sub.spawned` | A sub-agent was created |
| `agent.sub.completed` | A sub-agent finished successfully |
| `agent.sub.failed` | A sub-agent failed |
| `agent.sub.closed` | A sub-agent was cancelled |

Forwarded child activity:

- Child tool calls, assistant messages, warnings, and other non-noisy session events are forwarded into the parent run's event stream as normal agent events.
- The forwarded event keeps the child's `session_id`.
- `parent_session_id` points to the child's immediate parent session.

Example envelope:

```json
{
  "event": "agent.tool.started",
  "session_id": "ses_child",
  "parent_session_id": "ses_parent",
  "node_id": "code",
  "properties": {
    "tool_name": "read_file"
  }
}
```

Nested sub-agents preserve the immediate parent-child relationship. A grandchild forwarded through multiple parents still carries its own `session_id`, and `parent_session_id` remains set to the grandchild's direct parent rather than the root.

High-volume streaming events such as text deltas and tool output deltas are filtered out of the forwarded stream to reduce noise.

## When to use sub-agents

Sub-agents are most useful for:

- **Parallel research** -- inspect multiple code paths at once
- **Isolation** -- try a risky approach without polluting the parent's context
- **Divide and conquer** -- split an independent task into smaller pieces
- **Context management** -- offload work when the parent session is getting crowded

<Note>
Sub-agents run with no turn limit by default. Pass `max_turns` when you want predictable cost or time bounds. All active sub-agents are cleaned up automatically when the parent session closes.
</Note>
