> ## Documentation Index
> Fetch the complete documentation index at: https://docs.labelbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Multi-agent

> Choose between one agent, delegation, a team, or an advisor, and control exactly what each child agent can use.

One session can split work across several agents. The agent you start, called the root, can hand a focused task to a child agent, run a team of copies on a shared task board, or ask an advisor for a second opinion. Every agent in the tree works in the same sandbox, and cost rolls up to the root.

This page covers choosing a pattern, delegation, the roster, what a child inherits, limits, and how to inspect the tree. For the shared task board, see [Teams](/managed-agents/teams).

The TypeScript samples assume the `rl` client from [Client setup](/managed-agents/api#client-setup).

## Before you begin

* To create agents and start sessions, you need the Developer or Admin role in the organization. The User role can read session trees and threads. See [Organizations and roles](/managed-agents/organizations-and-roles).
* You need an agent and an environment. See [Agents](/managed-agents/agents) and [Environments](/managed-agents/environments).
* Every session can delegate to copies of its own agent without any setup. You only need a roster to delegate to other agents or to add an advisor.

## Choose a pattern

Start with one agent. Add agents only when the work splits into pieces that don't depend on each other.

| Pattern   | Use it when                                                                                          | Example                                                                       | Avoid it when                                                          |
| --------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| One agent | The steps are short, or each step feeds the next.                                                    | Fix a failing test, then update the changelog.                                | Never; it's the default.                                               |
| Delegate  | One hand-off is self-contained and clearly defined.                                                  | "Read the three RFCs in `/workspace/rfcs` and list every breaking change."    | The child would need most of the parent's conversation to do the work. |
| Team      | There are two or more independent, substantial pieces, or the work benefits from independent review. | Compare three caching strategies, each with its own benchmark, then pick one. | Each piece takes a few minutes, or the pieces must happen in order.    |
| Advisor   | You want a second opinion on a decision, not more hands.                                             | Check a migration plan before the agent starts it.                            | You need the advisor to read files or run commands. It can't.          |

A piece is worth a separate agent when it has its own build-and-test loop, its own sources, or its own approach to evaluate. Splitting a short, sequential task across agents costs more and usually finishes later, because each child starts without the parent's context.

<Note>
  Delegation and teams combine. A team member can still delegate a focused sub-task, within the depth limit.
</Note>

## How delegation works

The root delegates with the `delegate_subagent` tool, which you see in the transcript. Each child is a separate session with its own conversation, called a thread.

```mermaid theme={"theme":"css-variables"}
flowchart TD
  root["Root session (depth 0)"]
  selfCopy["Copy of the root: self"]
  roster["Roster agent: researcher"]
  advisor["Advisor (no tools)"]
  nested["Nested child (depth 2, needs max_depth 2)"]
  sandbox[("Shared sandbox /workspace")]
  root -->|delegate_subagent| selfCopy
  root -->|delegate_subagent| roster
  root -.->|consult_advisor| advisor
  roster -->|delegate_subagent| nested
  root --- sandbox
  selfCopy --- sandbox
  roster --- sandbox
  nested --- sandbox
```

What to expect:

* **The task must stand alone.** A child receives only the task text, not the parent's conversation. Name the files, the goal, and what a good result contains.
* **Hand work over by file path.** Children share the root's sandbox and environment, so a child can read what the parent wrote and the parent can read what the child wrote.
* **Children report a result.** A child finishes with `submit_result` and a status of `done`, `partial`, or `blocked`, a summary, and the paths it produced. The parent reads exactly that summary.
* **Threads stay reachable.** After a child reports, the parent can send it a follow-up with `send_to_agent`, and the child continues with its earlier context. The parent can also wait for children with `wait_for`, stop one with `interrupt_agent`, and close an idle one with `archive_thread`.
* **Failures stay contained.** A child that fails, or a roster agent that can't be resolved, returns an error to the parent. Its siblings keep working.
* **Everything is inspectable.** The console session page and the API show every child session, its thread, and a merged timeline. See [Inspect the session tree](#inspect-the-session-tree).

## What a child inherits

What a child can use depends on who the child is. A copy of the root acts as the root under another name. A different agent from the roster is its own principal and gets only what its own definition grants.

|                                                            | Copy of the root (`self`, any name not on the roster, and automatic teammates) | Different agent from the roster                               |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------- |
| Sandbox, environment, and workspace files                  | Shared with the root                                                           | Shared with the root                                          |
| [Referenced sessions](/managed-agents/referenced-sessions) | Inherited                                                                      | Inherited                                                     |
| Delegation limits                                          | Inherited; can only be tightened                                               | Inherited; can only be tightened by its own roster            |
| Model                                                      | The root's model                                                               | Its own model                                                 |
| System prompt                                              | The root's prompt for `self`; a general worker prompt for any other name       | Its own prompt                                                |
| Skills                                                     | The root's skills                                                              | Its own skills                                                |
| MCP servers                                                | The root's servers                                                             | Its own servers                                               |
| Vaults and credentials                                     | Exactly the same grants as the root                                            | Only its own default vaults and credentials, never the root's |
| Roster                                                     | The root's roster                                                              | Its own roster                                                |

Two rules apply to credentials across the whole tree:

* **Environment-variable credentials come only from the vaults granted to the root session.** They're set as plaintext environment variables in the shared sandbox when it starts, every agent in the tree can read them, and nothing adds to them later. If a roster agent's own vaults hold environment-variable credentials that the root doesn't have, the child's log shows a `session_status` warning with the code `delegated_env_credentials_unavailable` and the missing variable names. To make a variable available, grant its vault to the root session.
* **MCP server credentials work for each agent individually.** A roster agent's MCP servers authenticate with its own grants, and the root's credentials never authenticate a roster agent's servers.

```mermaid theme={"theme":"css-variables"}
flowchart LR
  rootVaults["Vaults granted to the root session"]
  childVaults["Roster agent's default vaults"]
  sandboxEnv["Shared sandbox environment variables"]
  rootMcp["Root's MCP servers"]
  childMcp["Roster agent's MCP servers"]
  selfCopy["Copies of the root"]
  rootVaults -->|"set when the sandbox starts"| sandboxEnv
  rootVaults -->|authenticate| rootMcp
  rootVaults -->|"same grants"| selfCopy
  selfCopy --> rootMcp
  childVaults -->|authenticate| childMcp
  childVaults -.->|"not added"| sandboxEnv
```

<Warning>
  The shared sandbox holds the root's environment-variable credentials, and every agent in the tree runs its commands in that sandbox. Don't rely on a roster agent to keep a sandbox credential away from other agents in the same tree. To share a credential on purpose, attach the same vault to both agents.
</Warning>

## Configure a roster

A roster lists the agents a coordinator can delegate to, and at most one advisor. It's part of the agent version, so a running session keeps the roster it started with.

| Field                             | Description                                                                                                                                                                                                                                              |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `multiagent.type`                 | Required. Always `coordinator`.                                                                                                                                                                                                                          |
| `multiagent.agents`               | Roster entries, at most 20 including the advisor.                                                                                                                                                                                                        |
| `multiagent.team.mode`            | `auto` (default), `on`, or `off`. See [Teams](/managed-agents/teams#choose-a-team-mode).                                                                                                                                                                 |
| `multiagent.limits`               | Delegation limits. See [Set delegation limits](#set-delegation-limits).                                                                                                                                                                                  |
| `multiagent.interventionist.mode` | What happens when the service notices a session may be stuck. `shadow` records an `advisor_intervention` event only. `active` also sends the agent a short notice it reads on its next turn. `off` turns both off. Omit it to use the default, `active`. |

Each roster entry has these fields:

| Field     | Description                                                                                                    |
| --------- | -------------------------------------------------------------------------------------------------------------- |
| `type`    | Required. `agent` for another agent, `advisor` for the advisor, or `self` to rename copies of the coordinator. |
| `id`      | Required for `agent`. The agent's id.                                                                          |
| `version` | Pins an agent version. Omit it to use the agent's current version at the moment of delegation.                 |
| `name`    | The name the coordinator delegates to. Omit it to use the agent id. Names are unique, ignoring case.           |
| `model`   | Required for `advisor`. A model id from the [models list](/managed-agents/agents).                             |

This coordinator can delegate to a researcher agent and consult one advisor.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Agents**, then open the coordinator agent.
    2. On the **Configuration** tab, find **Multiagent**.
    3. Click **Add subagent**, then choose the agent under **Subagent**.
    4. Click **Add advisor**, choose the **Advisor model**, then click **Add**.
    5. Click **Save new version**.

    The console doesn't edit delegation limits or entry names. Use the API for those.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const coordinator = await rl.managedAgents.createAgent({
      body: {
        name: 'Release coordinator',
        model: 'anthropic/claude-sonnet-5',
        system: 'Plan the release review. Delegate independent research, then write one recommendation.',
        multiagent: {
          type: 'coordinator',
          agents: [
            { type: 'agent', id: '2b8c4d16-7a95-4e30-b1f2-6d9c0a5e3b74', name: 'researcher' },
            { type: 'advisor', model: 'anthropic/claude-opus-5-5' },
          ],
          limits: { max_depth: 2, max_concurrent_threads: 4 },
        },
      },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/agents' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "name": "Release coordinator",
        "model": "anthropic/claude-sonnet-5",
        "system": "Plan the release review. Delegate independent research, then write one recommendation.",
        "multiagent": {
          "type": "coordinator",
          "agents": [
            {"type": "agent", "id": "2b8c4d16-7a95-4e30-b1f2-6d9c0a5e3b74", "name": "researcher"},
            {"type": "advisor", "model": "anthropic/claude-opus-5-5"}
          ],
          "limits": {"max_depth": 2, "max_concurrent_threads": 4}
        }
      }'
    ```
  </Tab>
</Tabs>

The response is the agent with its first version, and the roster under `multiagent`. Some fields are omitted.

```json theme={"theme":"css-variables"}
{
  "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
  "latest_agent_version_id": "c1a94e07-2f6b-4d18-b3a5-0e7d8c6f4a21",
  "name": "Release coordinator"
}
```

To change the roster later, create a new agent version. A version request replaces the whole definition, so resend every field you want to keep. See [Agents](/managed-agents/agents).

### Use the advisor

The advisor answers questions the agent asks with `consult_advisor`. It sees a digest of the session's recent activity and its own earlier advice, and it returns guidance only. It has no tools, can't read files, and doesn't do work. Ask the agent to consult it at decision points, for example: "Before you change the schema, consult the advisor with your migration plan."

## Set delegation limits

Limits belong to the coordinator's roster, not to a session start request. A child carries the root's limits down the tree. A child agent's own roster can tighten them but never widen them.

| Field                    | Default | Allowed      | What it bounds                                                                                                   |
| ------------------------ | ------- | ------------ | ---------------------------------------------------------------------------------------------------------------- |
| `max_depth`              | `1`     | `0` to `3`   | The deepest child level. The root is depth 0. `1` means children can't delegate further; `0` forbids delegation. |
| `max_concurrent_threads` | `8`     | `1` to `25`  | Children one coordinator can run at once. It can't exceed `max_threads`. It is also the team size.               |
| `max_threads`            | `25`    | `1` to `100` | Live children, running or idle, that one coordinator can hold. Archiving a child frees its slot.                 |

When a limit is reached, the delegation is refused with a tool error that the agent reads, such as "3 threads are already running, the most allowed at once". The agent then waits for a child to report, reuses an idle child, or archives one. The session itself keeps running.

`max_tree_cost_usd` in `limits` caps what an [evaluation](/managed-agents/evaluations) run spends; it doesn't cap an ordinary session tree. To watch spend, see [Usage and cost](/managed-agents/usage-and-cost) and [Analytics](/managed-agents/analytics).

## Inspect the session tree

The tree view shows every session in the tree, every thread, and the first page of one merged timeline. The thread list is the complete list of children, ordered by position in the tree.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Sessions**, then open the root session.
    2. The transcript shows each child's work in its own lane.
    3. Open the **Work** tab to see members, the board, and messages between agents.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const tree = await rl.managedAgents.getSessionTree({
      session_id: 'b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38',
    });
    const { threads } = await rl.managedAgents.listSessionThreads({
      session_id: 'b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/sessions/b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38/tree' \
      -H "Authorization: Bearer $RECURSION_API_KEY"

    curl 'https://api.recursion.labelbox.com/managed-agents/v1/sessions/b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38/threads' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

Both calls accept any session id in the tree and resolve to its root. A tree response looks like this, with `events` shortened:

```json theme={"theme":"css-variables"}
{
  "root_session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
  "sessions": [
    {
      "session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
      "root_session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
      "kind": "api_call",
      "status": "active",
      "execution_state": "idle",
      "stop_reason": "awaiting_subagents"
    },
    {
      "session_id": "4a9f2c61-0e3b-4d87-b5a2-7c1e6f9d3b40",
      "parent_session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
      "root_session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
      "agent_id": "2b8c4d16-7a95-4e30-b1f2-6d9c0a5e3b74",
      "kind": "subagent",
      "status": "active",
      "execution_state": "running"
    }
  ],
  "threads": [
    {
      "thread_id": "4a9f2c61-0e3b-4d87-b5a2-7c1e6f9d3b40",
      "session_id": "4a9f2c61-0e3b-4d87-b5a2-7c1e6f9d3b40",
      "root_session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
      "parent_session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
      "agent_id": "2b8c4d16-7a95-4e30-b1f2-6d9c0a5e3b74",
      "name": "researcher",
      "role": "subagent",
      "status": "running",
      "session_path": "/4a9f2c61-0e3b-4d87-b5a2-7c1e6f9d3b40",
      "thread_path": "/4a9f2c61-0e3b-4d87-b5a2-7c1e6f9d3b40",
      "created_at": "2026-09-25T17:02:11Z",
      "updated_at": "2026-09-25T17:04:37Z"
    }
  ],
  "events": [],
  "next_event_id": "0192d4e7-5b1a-7c3e-9f20-6a8b4c1d2e37"
}
```

A root with `stop_reason` `awaiting_subagents` is waiting on its children, not stuck. When `next_event_id` is present, read the rest of the timeline with the events API. See [Events](/managed-agents/events).

## Track cost across the tree

Every child's model cost counts toward the root session. Read one total for the tree, or a row per session to see which child spent what, with `listSessionModelCostNodes` and `scope=tree`. See [Usage and cost](/managed-agents/usage-and-cost).

Child sessions don't take a slot under the agent's `max_concurrent_sessions`; only root sessions do.

## What can go wrong

| Symptom or code                                                  | Cause                                                                                                                        | Fix                                                                                                         |
| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `400 invalid_request` on create                                  | The roster has more than 20 entries, two advisors, a duplicate name, an `agent` entry without `id`, or a limit out of range. | Correct the named field.                                                                                    |
| `409 revision_conflict` when you save a new version              | Someone else saved a version after the one you based yours on.                                                               | Read the agent, rebuild the full definition from its latest version, and retry.                             |
| A delegation fails with "could not be resolved"                  | The roster names an agent or pinned version that was deleted or is outside your organization.                                | Fix the roster entry and save a new version.                                                                |
| "may not delegate" in a child's tool result                      | The child is at `max_depth`.                                                                                                 | Raise `max_depth` on the root's roster, or have the child do the work itself.                               |
| "threads are already running" or "live threads" in a tool result | A thread limit was reached.                                                                                                  | Expected under load. The agent waits, reuses, or archives children. Raise the limit if the work needs more. |
| `delegated_env_credentials_unavailable` warning in a child       | A roster agent expected environment-variable credentials that the root's vaults don't provide.                               | Grant that vault to the root session.                                                                       |
| A roster agent can't reach an MCP server the root can            | Roster agents use only their own servers and grants.                                                                         | Add the server and grant to the roster agent's own definition.                                              |
| A child did the wrong thing                                      | Its task depended on context it never received.                                                                              | Write tasks that stand alone: goal, input paths, output path, and what done means.                          |

## Limits

| Limit                               | Value                             |
| ----------------------------------- | --------------------------------- |
| Roster entries                      | 20, including at most one advisor |
| Depth                               | Default 1, maximum 3              |
| Concurrent children per coordinator | Default 8, maximum 25             |
| Live children per coordinator       | Default 25, maximum 100           |

See [Limits](/managed-agents/limits) for every product limit.

## Next steps

<CardGroup cols={2}>
  <Card title="Teams" href="/managed-agents/teams">
    Run copies of an agent on a shared task board.
  </Card>

  <Card title="Deliverables and artifacts" href="/managed-agents/artifacts">
    Where children write outputs and how they're kept.
  </Card>

  <Card title="Research team tutorial" href="/managed-agents/use-cases/research-team">
    Run a team end to end with a graded deliverable.
  </Card>

  <Card title="Vaults" href="/managed-agents/vaults">
    Grant credentials to the root and to roster agents.
  </Card>
</CardGroup>
