A single Claude Managed Agent can already run bash, edit files and call MCP servers on its own. Multiagent orchestration is the layer above that: one agent, the coordinator, delegates well-scoped pieces of a task to other agents running in the same session, each with its own isolated context. Anthropic frames it around two patterns that show up constantly in practice, parallelising independent subtasks and routing to a domain specialist rather than loading every capability into one system prompt.
This piece covers how a coordinator is configured, what a session thread actually is, the advisor pattern (a model you consult without delegating to it), and the hard limits worth knowing before you architect around this.
How it works
Every agent in a multiagent session shares the same sandbox, filesystem and vault credentials, but each runs in its own session thread: a context-isolated event stream with its own conversation history. The coordinator's own activity appears on the primary thread (the same stream as the session-level event stream you already read for a normal session); additional threads spin up at runtime whenever the coordinator delegates.
Threads persist. The coordinator can send a follow-up to an agent it called three turns ago, and that agent still has everything from its earlier turns in context.
What does not carry over automatically is configuration. Each agent uses its own model, system prompt, tools, MCP servers and skills. The one exception is session-level agent configuration overrides: those apply to the coordinator and to any self copies it spawns (see below), but not to roster agents referenced by ID.
What actually benefits from this
Anthropic's own guidance names three patterns that work well:
- Parallelisation. Fan out independent subtasks at once, searching several sources, analysing separate files, and have the coordinator synthesise the results afterward.
- Specialisation. Route to an agent with a narrow, domain-focused system prompt and toolset, a security reviewer or a documentation writer, rather than one agent trying to be all of them at once.
- Escalation. Hand a genuinely hard subtask to a more capable model for just that piece, instead of running the whole session at the expensive model's rate.
Configuring the coordinator
Set multiagent on the coordinator's agent config to declare its roster:
name: Engineering Lead
model: claude-opus-5
system: You coordinate engineering work. Delegate code review to the reviewer agent and test writing to the test agent.
tools:
- type: agent_toolset_20260401
multiagent:
type: coordinator
agents:
- type: agent
id: $REVIEWER_AGENT_ID
- type: agent
id: $TEST_WRITER_AGENT_ID
ant beta:agents create < coordinator.agent.yaml
multiagent.agents accepts four entry shapes:
| Entry | What it does |
|---|---|
{type: agent, id: <agent id>} | References an existing agent, pinned to whatever version was latest when the coordinator was created or last updated. |
{type: agent, id: <agent id>, version: <n>} | References a specific, explicit version of that agent. |
{type: self} | Lets the coordinator spawn copies of itself. Session-level overrides apply to these copies. |
{type: advisor, model: <model id>} | Gives the primary thread a consultable model rather than a delegatable subagent. At most one per roster. |
Rosters snapshot at save time. A coordinator's multiagent.agents list resolves referenced agents' versions when the coordinator is created or updated, and it does not automatically pick up later edits to those agents. To have the coordinator delegate to a newer version of a roster member, you have to update the coordinator itself so the roster entry points at that version.
Delegation is exactly one level deep. A roster agent that itself has a multiagent.agents roster configured makes the create or update request fail validation. You can't nest coordinators.
The roster caps at 20 unique agents, though the coordinator can spin up multiple concurrent copies of any one of them, each getting its own thread.
Inference geography pins must agree across the whole roster. If agents pin an inference geography via model.inference_geo, the coordinator's pin and every roster member's pin must all match or all be unset. A mismatch is rejected with a 400, both when the agent is saved and when a session-create override changes a pin.
The advisor: consultation without delegation
An advisor entry gives the session's primary thread a model to consult mid-turn, for planning an approach, getting unstuck, or a review pass before finishing, without making it a roster agent the coordinator can hand tasks to:
{
"name": "Backend engineer",
"model": "claude-sonnet-5",
"system": "You implement backend features end to end. Consult the advisor before major backend design decisions.",
"multiagent": {
"type": "coordinator",
"agents": [{"type": "advisor", "model": "claude-opus-5"}]
}
}
A few rules specific to this entry type:
- The advisor must be at least as capable as the agent it advises. An invalid pairing (advisor weaker than the agent's own model) is rejected with a 400 at save time; models of equal capability can pair.
- Consultations run as a self-terminating thread named
anthropic.advisor, delivering the advice back to the primary thread as anagent.thread_message_receivedevent. Noagent.tool_useevents appear for a consultation, since the platform composes the consultation input rather than the agent. - Whether you can read the advice back depends on the advisor model's result policy. Advisor models that return plaintext results on the equivalent Messages API tool deliver readable advice here too; models that return redacted results deliver a
[{"type": "redacted"}]placeholder to your client, even though the calling agent still reads the full advice server-side. Choosing Claude Opus 4.8 over Claude Opus 5 as the advisor, for instance, is the difference between your client seeing the advice or a placeholder. - Advisor threads don't count against the 25-thread limit.
- A failed consultation never fails the agent's turn; the agent just gets a generic failure notice and continues.
To remove an advisor, update the agent with a roster that omits the advisor entry, or clear multiagent entirely with null if it was the only entry.
Creating the session
Once the coordinator exists, create a session against it exactly like any other Managed Agents session:
ant beta:sessions create \
--agent "$COORDINATOR_ID" \
--environment-id "$ENVIRONMENT_ID"
The coordinator delegates to its roster as the task calls for it. Nothing about session creation itself changes for a multiagent coordinator versus a single agent.
MCP servers are agent-scoped, credentials are session-scoped
This is the detail most likely to trip up a first multiagent setup. MCP servers are declared per agent, each agent config lists its own mcp_servers and the tools built on them, while vault credentials are attached once, at session creation, and apply across every thread. Two consequences:
- To authenticate an MCP server anywhere in the session, include a vault credential for it in the session's
vault_ids, even if only one roster agent actually uses that server. - To limit an agent's reach, only declare the servers it actually needs on that agent's own config. A coordinator that doesn't declare a server can't call it, even if a roster agent it delegates to has full access.
# researcher.agent.yaml: only this agent gets the GitHub MCP server
name: researcher
model: claude-haiku-4-5
mcp_servers:
- type: url
name: github
url: https://api.githubcopilot.com/mcp/
tools:
- type: mcp_toolset
mcp_server_name: github
# subagent-coordinator.agent.yaml: the coordinator itself has no GitHub access
name: coordinator
model: claude-opus-5
tools:
- type: agent_toolset_20260401
multiagent:
type: coordinator
agents:
- type: agent
id: $research_agent_id
Session creation then supplies the shared vault credential the researcher thread needs:
research_agent_id=$(ant beta:agents create --transform id --raw-output < researcher.agent.yaml)
coordinator_id=$(ant beta:agents create --transform id --raw-output < subagent-coordinator.agent.yaml)
session_id=$(ant beta:sessions create \
--agent "$coordinator_id" \
--environment-id "$environment_id" \
--vault-id "$vault_id" \
--transform id --raw-output)
Threads: the session's real unit of concurrency
A session's status aggregates across every thread: if even one thread is running, the whole session reads as running. A session budget is a single cap shared across every thread; as it's approached, threads pause independently, each priced at whatever model actually served it.
The hard ceiling is 25 concurrent threads per session, primary thread included, though a coordinator calling several copies of one roster agent gets one thread per copy against that same cap. Advisor threads are exempt.
ant beta:sessions:threads list --session-id "$SESSION_ID"
Two operations manage threads directly:
- Interrupt.
user.interruptwith asession_thread_idstops one specific thread; omitting it interrupts every non-archived thread including the primary. Interrupting a thread parked onrequires_action(waiting on a tool confirmation) closes the pending tool calls with an error result and marks the thread idle without sampling the model again. - Archive. Frees a thread's slot against the 25-thread cap. Only succeeds against an
idlethread (a thread waiting onrequires_actioncounts as idle); arunningthread has to be interrupted first.
Primary thread events worth watching
| Event | What it tells you |
|---|---|
session.thread_created | A new thread started, with session_thread_id and agent_name. |
session.thread_status_running / session.thread_status_idle | A thread started or finished a turn (idle carries a stop_reason). |
session.thread_status_terminated | A thread was archived, or hit a terminal error. |
agent.thread_message_received | A subagent reported back to the coordinator. |
agent.thread_message_sent | The coordinator sent a task or follow-up to a subagent. |
If a subagent needs something only your client can provide, a tool confirmation or a custom tool result, that request is cross-posted to the primary thread with session_thread_id identifying which subagent is waiting, so a single handler on the primary event stream can route responses to the right thread without you separately watching every subagent's own stream.
When not to reach for this
Multiagent orchestration adds real overhead: more threads to monitor, more agents to version and keep in sync, and a session budget that now has to stretch across everything running concurrently. It earns its complexity when subtasks are genuinely independent or genuinely need different tools and prompts. It's the wrong tool for a task one well-configured agent with a good system prompt can already do in a single thread. Anthropic's own guidance on when to use multiagent systems is worth reading before committing an architecture to this, and it pairs directly with Claude Code's agent teams if you're weighing the same coordinate-vs-single-agent decision on the CLI side rather than the API.
Where to go next
Anthropic's own multiagent orchestration page is the full reference this article draws from. For the underlying Managed Agents concepts, see Claude Managed Agents explained, and for running a coordinator unattended, scheduled deployments. The ant beta:agents and ant beta:sessions commands used throughout are covered in full in Anthropic's ant CLI. Browse the wider catalogue at getclaudeskills.com/skills or by category.
Verified 25 August 2026 directly against Anthropic's multiagent orchestration documentation at platform.claude.com/docs/en/managed-agents/multiagent-orchestration, read in full.
