Orchestration
Orchestration is running multiple Claude instances—subagents, parallel sessions, or coordinated workflows—to tackle work that’s too big or complex for a single session.
Do You Actually Need This?
Section titled “Do You Actually Need This?”Most people don’t. Before orchestrating, ask:
| Question | If Yes… |
|---|---|
| Can this be done in one session? | Don’t orchestrate |
| Is this just a long task? | Use /compact and continue |
| Am I trying to parallelize for speed? | Often not worth the complexity |
| Is this independent work that truly benefits from isolation? | Consider orchestration |
Orchestration is for:
- Truly parallel, independent work
- Context isolation (keeping main session clean)
- Very large tasks that would overflow context
Subagents: The Simple Path
Section titled “Subagents: The Simple Path”Claude can spawn subagents to do isolated work. This is the easiest form of orchestration.
When Subagents Help
Section titled “When Subagents Help”# Research that would pollute context> Use a subagent to research the best React state management> libraries and give me a one-paragraph recommendation
# Parallel independent tasks> Use subagents to:> 1. Add tests to src/services/user.py> 2. Add tests to src/services/product.py> 3. Add tests to src/services/order.py
# Heavy work with minimal context return> Use a subagent to refactor src/legacy/ to use async/await> Report back only the files changed and any issues foundWhen to Avoid Subagents
Section titled “When to Avoid Subagents”| Avoid When | Why |
|---|---|
| Tasks need back-and-forth | Subagents can’t ask you questions |
| Work is interdependent | Changes will conflict |
| You need to review incrementally | No visibility into subagent work |
| Simple tasks | Overhead isn’t worth it |
Manual Parallel Sessions
Section titled “Manual Parallel Sessions”For more control, run multiple Claude sessions yourself:
# Terminal 1: Backend workcd myprojectclaude "add pagination to all list endpoints"
# Terminal 2: Frontend workcd myprojectclaude "update the UI to handle paginated responses"
# Terminal 3: Testscd myprojectclaude "write tests for the new pagination"Coordination Strategies
Section titled “Coordination Strategies”File-based handoff:
# Session 1 writesclaude -p "document the API changes" > api-changes.md
# Session 2 readsclaude -p "update frontend based on $(cat api-changes.md)"Git-based coordination:
# Each session works on a branch# Terminal 1git checkout -b feature/backend-paginationclaude "implement backend"git commit -am "backend done"
# Terminal 2git checkout -b feature/frontend-paginationclaude "implement frontend"git commit -am "frontend done"
# Merge when both completegit checkout maingit merge feature/backend-paginationgit merge feature/frontend-paginationThe Orchestrator Pattern
Section titled “The Orchestrator Pattern”For complex multi-step work, use one Claude session to coordinate others:
> I need to add a complete user preferences feature.>> Create a plan that breaks this into independent chunks.> For each chunk:> 1. Define the scope clearly> 2. List files involved> 3. Identify dependencies on other chunks>> Then I'll execute each chunk in a separate session.Claude produces a plan. Then:
# Execute each chunkclaude "execute chunk 1 from preferences-plan.md"exitclaude "execute chunk 2 from preferences-plan.md"exit# ...SDK-Based Orchestration
Section titled “SDK-Based Orchestration”For automated orchestration, use the SDK:
import asynciofrom claude_code_sdk import ClaudeCode
async def parallel_tasks(): claude = ClaudeCode()
# Run in parallel results = await asyncio.gather( claude.run(prompt="add tests to src/auth/"), claude.run(prompt="add tests to src/api/"), claude.run(prompt="add tests to src/utils/") )
# Aggregate results summary = "\n\n".join(r.output for r in results) print(summary)
asyncio.run(parallel_tasks())Sequential with State
Section titled “Sequential with State”async def sequential_pipeline(): claude = ClaudeCode()
# Step 1: Analysis analysis = await claude.run( prompt="analyze src/legacy/ and identify refactoring opportunities" )
# Step 2: Plan based on analysis plan = await claude.run( prompt=f"create a refactoring plan based on: {analysis.output}" )
# Step 3: Execute plan for step in parse_plan(plan.output): await claude.run(prompt=f"execute: {step}")
asyncio.run(sequential_pipeline())Common Orchestration Patterns
Section titled “Common Orchestration Patterns”Fan-Out / Fan-In
Section titled “Fan-Out / Fan-In” ┌─ Task A ─┐Input ──┼─ Task B ─┼── Aggregate └─ Task C ─┘# Fan outtasks = ["auth/", "api/", "utils/"]results = await asyncio.gather( *[claude.run(prompt=f"add tests to {dir}") for dir in tasks])
# Fan inawait claude.run( prompt=f"summarize these results: {chr(10).join(r.output for r in results)}")Pipeline
Section titled “Pipeline”Input → Stage 1 → Stage 2 → Stage 3 → Outputcontext = await claude.run(prompt="analyze the codebase")context = await claude.run(prompt=f"plan based on: {context.output}")context = await claude.run(prompt=f"implement: {context.output}")await claude.run(prompt=f"test: {context.output}")Supervisor
Section titled “Supervisor” ┌─ Worker 1Supervisor ───┼─ Worker 2 └─ Worker 3async def supervised_work(tasks: list[str]): results = []
for task in tasks: result = await claude.run(prompt=task)
# Supervisor reviews review = await claude.run( prompt=f"review this work: {result.output}. Any issues?" )
if "issue" in review.output: # Retry with feedback await claude.run( prompt=f"redo: {task}. Issues found: {review.output}" )
results.append(result)
return resultsCoordination Challenges
Section titled “Coordination Challenges”Avoiding Conflicts
Section titled “Avoiding Conflicts”# Bad: Both sessions modify same fileSession 1: "update src/api/routes.py"Session 2: "update src/api/routes.py" # Conflict!
# Good: Clear ownershipSession 1: "update src/api/routes.py"Session 2: "update src/api/handlers.py"Sharing Context
Section titled “Sharing Context”# Option 1: Explicit handoff filesSession 1: > save changes summary to /tmp/session1-output.mdSession 2: > read /tmp/session1-output.md and continue
# Option 2: Git commitsSession 1: > commit changes with detailed messageSession 2: > read the last commit message to understand changes
# Option 3: CLAUDE.md updatesSession 1: > update CLAUDE.md with new patterns we establishedSession 2: [automatically gets updated context]Error Handling
Section titled “Error Handling”async def resilient_orchestration(tasks: list[str]): results = []
for task in tasks: try: result = await claude.run(prompt=task) results.append({"task": task, "success": True, "output": result.output}) except Exception as e: results.append({"task": task, "success": False, "error": str(e)}) # Decide: continue or abort
# Report failures failures = [r for r in results if not r["success"]] if failures: print("Failed tasks:", failures)
return resultsWhen Orchestration Fails
Section titled “When Orchestration Fails”| Symptom | Cause | Fix |
|---|---|---|
| Conflicting changes | Overlapping scope | Better chunking |
| Lost context | Handoffs not working | Explicit state passing |
| Worse results than single session | Overhead > benefit | Don’t orchestrate |
| Coordination overhead | Too fine-grained | Bigger chunks |
Real-World Use Cases
Section titled “Real-World Use Cases”Test Coverage Sprint
Section titled “Test Coverage Sprint”# Parallel test writing for independent modulesclaude "add tests to auth/" &claude "add tests to payments/" &claude "add tests to notifications/" &waitDocumentation Overhaul
Section titled “Documentation Overhaul”Supervisor session:> Create a list of all modules needing documentation
Worker sessions (parallel):> Document src/auth/ module> Document src/api/ module> Document src/utils/ module
Supervisor session:> Review all new documentation for consistencyLarge Migration
Section titled “Large Migration”Planning session:> Analyze migration from REST to GraphQL> Break into independent chunks
Execution sessions (sequential):> Migrate users endpoint> Migrate products endpoint> Migrate orders endpoint
Verification session:> Run full test suite> Compare API responses old vs new