Skip to content

C1 · lesson 3 · 10 min read

Orchestrator–worker and parallel subagents

Split a task across focused subagents that run in parallel, each with its own context and tools, and keep the fan-out bounded.

Ընտրեք տեքստը՝ հայերեն թարգմանությունը տեսնելու համար։Highlight text to see Armenian. Machine-assisted translation; English is the source of truth.

Official video by Anthropic on YouTube. Pressing play loads it from youtube-nocookie.com. ·open on YouTube

In the orchestrator–worker pattern, one model breaks a task down at run time, hands the pieces to workers, and combines what they report back. The key words are “at run time”. If you know the subtasks in advance, a fixed parallel workflow is simpler (see lesson 6). Orchestrator–worker fits when the split depends on the input: which services a change touches, or which logs look suspicious.

orchestratorplans, mergeslog-scanner · Read, Grepdeploy-differ · Bash(git diff *)metrics-checker · MCP read-onlybrief →brief →← summary
The orchestrator sends each worker a brief and gets back a summary. Each worker reads in its own context with its own narrow tools.

What a subagent gives you

In the Agent SDK, workers are subagents: separate agent instances that Claude starts through the Agent tool. Each one has:

  • Its own context. It starts fresh, apart from forks. Its tool calls and file reads stay inside it, and only its final message goes back to the parent. A worker can read forty log files and return eight lines.
  • Its own instructions. It gets its own system prompt (prompt), not the parent’s.
  • Its own tools. If you list tools, that’s all it gets. A tool you leave out isn’t in its session at all.
  • Parallelism. Independent workers run at the same time, so the fan-out takes as long as the slowest worker, not the sum of all of them.

Defining workers

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition

WORKERS = {
    "log-scanner": AgentDefinition(
        description="Finds error bursts and stack traces in logs/. Use for any log question.",
        prompt="Scan only the paths you are given. Return at most 10 lines: timestamp, file:line, error.",
        tools=["Read", "Grep", "Glob"],
        model="haiku",
    ),
    "manifest-reviewer": AgentDefinition(
        description="Reviews Kubernetes manifests for probe, resource and image changes.",
        prompt="Report risky settings with file:line. Never propose kubectl apply.",
        tools=["Read", "Grep", "Glob"],
    ),
}


async def main():
    async for msg in query(
        prompt="Checkout API returns 502 since 14:10. Triage.",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Grep", "Glob", "Agent"],
            agents=WORKERS,
            max_budget_usd=2.0,
            env={"CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH": "1",
                 "CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS": "4"},
        ),
    ):
        if hasattr(msg, "result"):
            print(msg.result)

asyncio.run(main())

AgentDefinition requires only description and prompt. The optional fields include tools, disallowedTools, model (an alias such as haiku, inherit, or a full model ID), maxTurns, skills, mcpServers, effort, background and permissionMode. Claude picks a worker by matching the task against its description, so write descriptions like routing rules. To force a particular worker, name it in the prompt.

Keeping the fan-out bounded

Claude decides how many subagents to start, and subagents can start their own. One prompt can grow into a tree of agents. Three limits keep it in check:

Limit How you set it Default
Depth CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH 3 layers
Concurrency CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS 20 at once
Spend max_budget_usd / maxBudgetUsd No limit

Subagent spend counts toward the parent’s budget. When the cap is reached, new spawns fail with Budget limit reached, background workers are stopped, and the query ends with error_max_budget_usd.

When it’s worth it

Good fits: reviews that split by concern (security, cost, tests), incident triage across several independent sources, and research over many files where the parent only needs conclusions. Poor fits: steps that depend on each other (worker B needs A’s output), tiny tasks where spawning costs more than doing, and anything that writes to the same files or resources in parallel. Two workers editing one Terraform state is a race, not a speed-up.

Recap

  • Orchestrator–worker means a model splits the work at run time, delegates it, and merges the results.
  • Subagents give context isolation, their own prompt and tools, and parallel execution. Only the final message comes back.
  • Define them with agents and AgentDefinition. The description drives delegation.
  • Bound the tree with depth, concurrency and max_budget_usd, and never let workers write to shared state in parallel.

$ ./try-it.sh

Try it: parallel incident triage

  1. Save the orchestrator from this lesson as triage.py in a repo that has a logs/ folder and some Kubernetes manifests.
  2. Run it with the prompt "Checkout API returns 502 since 14:10. Triage." and print every tool_use block named Agent (also match Task for older versions) together with its subagent_type.
  3. Print each message that has a parent_tool_use_id. Confirm that the workers' file reads appear there, not in the orchestrator's own turns.
  4. Set CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS to 1 in env and compare the wall-clock time with the parallel run.
  5. Lower max_budget_usd to 0.10 and check that the run ends with error_max_budget_usd instead of spawning more workers.

Check yourself

5 questions. Original practice questions, not taken from the real exam.

  1. Your orchestrator delegates a log scan to a subagent that reads 30 files.

    1. What does the orchestrator get back?

  2. You defined a log-scanner subagent, but Claude keeps doing the log analysis itself in the main conversation.

    2. What should you try first?

  3. You're deciding where parallel subagents would actually help your platform team.

    3. Which two tasks are good fits? (Choose two.)

    Choose 2.

  4. An "audit every service" prompt made Claude spawn dozens of subagents, some of which spawned their own. The bill spiked.

    4. Which controls bound this most directly?

  5. In a single turn, Claude asks to Read four manifests and Edit one values file.

    5. How does the SDK run these calls?

Answer every question to check.