Skip to content

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.

Most people don’t. Before orchestrating, ask:

QuestionIf 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

Claude can spawn subagents to do isolated work. This is the easiest form of orchestration.

# 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 found
Avoid WhenWhy
Tasks need back-and-forthSubagents can’t ask you questions
Work is interdependentChanges will conflict
You need to review incrementallyNo visibility into subagent work
Simple tasksOverhead isn’t worth it

For more control, run multiple Claude sessions yourself:

Terminal window
# Terminal 1: Backend work
cd myproject
claude "add pagination to all list endpoints"
# Terminal 2: Frontend work
cd myproject
claude "update the UI to handle paginated responses"
# Terminal 3: Tests
cd myproject
claude "write tests for the new pagination"

File-based handoff:

Terminal window
# Session 1 writes
claude -p "document the API changes" > api-changes.md
# Session 2 reads
claude -p "update frontend based on $(cat api-changes.md)"

Git-based coordination:

Terminal window
# Each session works on a branch
# Terminal 1
git checkout -b feature/backend-pagination
claude "implement backend"
git commit -am "backend done"
# Terminal 2
git checkout -b feature/frontend-pagination
claude "implement frontend"
git commit -am "frontend done"
# Merge when both complete
git checkout main
git merge feature/backend-pagination
git merge feature/frontend-pagination

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:

Terminal window
# Execute each chunk
claude "execute chunk 1 from preferences-plan.md"
exit
claude "execute chunk 2 from preferences-plan.md"
exit
# ...

For automated orchestration, use the SDK:

import asyncio
from 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())
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())
┌─ Task A ─┐
Input ──┼─ Task B ─┼── Aggregate
└─ Task C ─┘
# Fan out
tasks = ["auth/", "api/", "utils/"]
results = await asyncio.gather(
*[claude.run(prompt=f"add tests to {dir}") for dir in tasks]
)
# Fan in
await claude.run(
prompt=f"summarize these results: {chr(10).join(r.output for r in results)}"
)
Input → Stage 1 → Stage 2 → Stage 3 → Output
context = 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}")
┌─ Worker 1
Supervisor ───┼─ Worker 2
└─ Worker 3
async 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 results
# Bad: Both sessions modify same file
Session 1: "update src/api/routes.py"
Session 2: "update src/api/routes.py" # Conflict!
# Good: Clear ownership
Session 1: "update src/api/routes.py"
Session 2: "update src/api/handlers.py"
# Option 1: Explicit handoff files
Session 1: > save changes summary to /tmp/session1-output.md
Session 2: > read /tmp/session1-output.md and continue
# Option 2: Git commits
Session 1: > commit changes with detailed message
Session 2: > read the last commit message to understand changes
# Option 3: CLAUDE.md updates
Session 1: > update CLAUDE.md with new patterns we established
Session 2: [automatically gets updated context]
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 results
SymptomCauseFix
Conflicting changesOverlapping scopeBetter chunking
Lost contextHandoffs not workingExplicit state passing
Worse results than single sessionOverhead > benefitDon’t orchestrate
Coordination overheadToo fine-grainedBigger chunks
Terminal window
# Parallel test writing for independent modules
claude "add tests to auth/" &
claude "add tests to payments/" &
claude "add tests to notifications/" &
wait
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 consistency
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