When the work exceeds what a flat master->agent dispatch can handle, the master delegates orchestration itself. A sub-orchestrator is an agent whose job is not to do work, but to manage agents that do work.
| Scenario | Flat dispatch (master->agents) | Sub-orchestrator |
|---|---|---|
| 5-15 independent tasks | Yes | Overkill |
| 15-30 tasks, same type | Maybe (wave dispatching) | Better |
| 30+ tasks, same type | No (master context bloats) | Yes |
| Mixed task types (audit + fix + validate) | Yes (one per type) | Per-type sub-orchestrator |
| Tasks with complex inter-dependencies | Case by case | Yes (orchestrator manages ordering) |
Rule of thumb: If you need more than 2 waves of dispatch, or the tracking logic itself is complex, promote the tracking to a sub-orchestrator.
MASTER (thin -- routes, approves, reviews)
|
|-- SUB-ORCHESTRATOR (manages N workers in batches)
| |-- Worker Agent 1
| |-- Worker Agent 2
| |-- ...
| |-- Worker Agent N
| |
| |-- Writes: progress log (.md file)
| |-- Returns: summary + log path + aggregate scores
|
|-- (other agents or sub-orchestrators)
|
MASTER: reviews summary, approves, next action
| Role | Reads files? | Writes code? | Manages agents? | Talks to owner? | Heavy lifting? |
|---|---|---|---|---|---|
| Master | No (summaries only) | No | Yes (dispatches sub-orchestrators) | Yes | None -- routes and approves |
| Sub-orchestrator | Index file only | No | Yes (manages worker pool) | No (returns to master) | Aggregation only |
| Worker agent | Yes (all of them) | Yes (if needed) | No | No (returns to orchestrator) | ALL of it |
The deeper you go, the more work is assigned. Master decides WHAT. Sub-orchestrator manages WHEN and HOW MANY. Workers do ALL the actual work -- reading, analyzing, fixing, writing reports, building summaries. Results flow up as thin pointers and executive summaries. Detail stays at the bottom in files on disk.
Master defines:
- What: the overall goal (e.g., "score and fix all 77 blog posts")
- Rules: quality criteria, scoring rubric, pass/fail thresholds
- Batch size: how many workers to run concurrently (default: 10)
- Log file: path where the sub-orchestrator writes progress
- Return format: what master needs back (summary stats, category breakdown, log path)
Master prompt to sub-orchestrator:
You are a sub-orchestrator managing blog post quality scoring.
GOAL: Score all 77 blog posts against the quality rubric. Fix any scoring below 85.
RUBRIC: [SEO score, AEO score, Quality score -- all must be 85+]
POSTS: [list of 77 file paths]
BATCH SIZE: 10 concurrent workers
LOG FILE: <workspace-path>/<project>/.logs/quality-audit-2026-03-26.md
DIVERGENT MODE: AUTO
Instructions:
1. Dispatch workers in batches of 10
2. Each worker scores one post, returns: filename, SEO/AEO/Quality scores, pass/fail, issues found
3. If a post fails (<85 on any metric): dispatch a fix agent, then re-score
4. Log every result to the log file as workers complete (append, don't overwrite)
5. After all 77 are done, aggregate results and return summary to master
Return format:
STATUS: OK (or PARTIAL if some posts couldn't be fixed)
LOG: [path to log file]
SUMMARY:
Total: 77 | Pass: 63 | Fixed: 11 | Failed: 3
By category: [table]
Lowest scores: [bottom 5]
FILES_CHANGED: [list of modified post files]
The sub-orchestrator maintains a rolling pool of concurrent workers:
remaining = [all 77 posts]
active = []
max_concurrent = 10
# Initial fill -- launch up to max_concurrent
while len(active) < max_concurrent and remaining is not empty:
task = remaining.pop(0)
agent = dispatch worker (background)
active.append(agent)
# Rolling loop -- as each completes, backfill immediately
while active is not empty:
completed = wait for any one agent to complete
log result to .md file
if failed:
dispatch fix agent, re-score, log fix result
active.remove(completed)
if remaining is not empty:
task = remaining.pop(0)
agent = dispatch worker (background)
active.append(agent)
This is a rolling pool, not batch-and-wait. The sub-orchestrator launches 10 workers initially. When worker #1 finishes, worker #11 launches immediately -- there are always 10 running (until the remaining queue empties). This maximizes throughput because fast workers don't wait for slow ones in the same batch.
Key behaviors:
- Maintains max_concurrent active workers at all times (rolling, not batch-and-wait)
- Logs results as they arrive (progress is visible even if sub-orchestrator crashes)
- Fix-and-rescore happens inline when a worker completes, before backfilling the slot
- Sub-orchestrator itself stays thin -- it reads worker summaries, not file content
Sizing max_concurrent: The right pool size depends on the machine's resources and the work each agent does:
- CPU/memory: Each agent consumes runtime memory. Monitor system resources and reduce pool size if the machine is under pressure.
- Agent weight: Lightweight agents (score one file, return 10 lines) can run 10-15 concurrently. Heavy agents (read 20+ files, write code, run tests) may need a pool of 3-5.
- Claude Code heap: The sub-orchestrator's own context grows with each result it processes. Workers should write heavy output to files and return only a pointer + executive summary (see "Write to File, Return the Pointer" below).
- Start conservative: Begin with 5, observe resource usage, scale up. Better to run 8 smoothly than 15 with thrashing.
Core principle: the deeper you go, the more work is assigned. Workers do ALL the heavy lifting -- reading files, analyzing, fixing, writing reports, building summaries. The orchestrator layer above them should never have to dig into details to make routing decisions.
Each worker gets a self-contained prompt:
Score this blog post against the quality rubric.
FILE: <workspace-path>/<project>/content-drafts/ai-security-basics.md
RUBRIC:
SEO: [criteria]
AEO: [criteria]
Quality: [criteria]
Write your full analysis to: <workspace-path>/<project>/.logs/scores/ai-security-basics.md
Start the file with an EXECUTIVE SUMMARY section (scores, pass/fail, issues -- everything
the orchestrator needs to act without reading the rest of the file).
Append the log index file: <workspace-path>/<project>/.logs/quality-audit-2026-03-26.md
Return to orchestrator (keep under 5 lines):
STATUS: OK
SCORES: SEO=87 AEO=91 Quality=83
PASS: false (Quality below 85)
DETAIL: .logs/scores/ai-security-basics.md
Workers are disposable. They read files, do the analysis, write the output to disk, update the shared log, and return a minimal pointer. Their context is fully consumed and freed.
This is the most important pattern for keeping orchestrator context thin.
Workers and sub-orchestrators should never pass heavy output up the chain. Instead:
- Worker writes full results to an .md file -- analysis, findings, fix details, everything
- Worker writes an executive summary as the FIRST section of that file -- scores, pass/fail, action needed. The orchestrator can read just this section if it needs more than the return line.
- Worker appends a one-line entry to a shared index/log file -- the sub-orchestrator reads this file for aggregate status without collecting individual returns
- Worker returns to orchestrator: status + scores + file path -- 3-5 lines max
Output hierarchy (worker produces all three):
1. Full report: .logs/scores/ai-security-basics.md (owner reads later)
[EXECUTIVE SUMMARY at top -> full analysis below]
2. Index entry: .logs/quality-audit-2026-03-26.md (orchestrator reads for aggregate)
| ai-security-basics.md | SEO=87 | AEO=91 | Quality=83 | FAIL | .logs/scores/ai-security-basics.md |
3. Return message: STATUS: OK / SCORES / PASS / DETAIL path (orchestrator receives directly)
[3-5 lines, just enough to route]
Why the executive summary matters: If the sub-orchestrator needs to make a decision about a worker's output (retry? escalate? skip?), it reads the executive summary section of the output file -- NOT the full report, and NOT a verbose return message. The worker already did the thinking and distilled it. The orchestrator just acts on the distillation.
Why the index file matters: The sub-orchestrator doesn't need to collect and assemble results from 77 individual returns. Workers append to a shared log as they complete. When all workers finish, the log IS the aggregate report. The sub-orchestrator reads it once, builds the final summary for master, done.
This pattern scales to any depth. A sub-orchestrator returning to master follows the same rule: write the detailed aggregate to a file, return the pointer + executive summary.
The sub-orchestrator follows the same "write to file, return the pointer" pattern. Workers already built the index file as they ran. The sub-orchestrator reads that index, builds an executive summary, writes the detailed aggregate report to disk, and returns a thin summary to master.
After all 77 posts are processed:
STATUS: OK
LOG: <log-path>/quality-audit-2026-03-26.md
SUMMARY:
Total: 77 | Pass: 63 | Fixed: 11 | Failed: 3
By category:
| Category | Count | Pass | Fixed | Failed | Avg SEO | Avg AEO | Avg Quality |
|-------------|-------|------|-------|--------|---------|---------|-------------|
| Product A | 15 | 12 | 3 | 0 | 91 | 89 | 88 |
| Product B | 12 | 10 | 2 | 0 | 88 | 87 | 86 |
| Product C | 10 | 8 | 1 | 1 | 85 | 84 | 82 |
| Product D | 8 | 5 | 2 | 1 | 83 | 86 | 84 |
| Product E | 6 | 5 | 1 | 0 | 90 | 92 | 89 |
| Product F | 26 | 23 | 2 | 1 | 86 | 85 | 85 |
Failed posts (could not reach 85+):
1. post-with-structural-issues.md -- Quality=79 (structural issues)
2. post-missing-key-points.md -- AEO=78 (missing key_points)
3. post-with-keyword-stuffing.md -- SEO=74 (keyword stuffing)
FILES_CHANGED:
- [list of 11 modified post files]
Master reviews the summary, decides what to do about the 3 failures (manual fix, different approach, or accept).
The sub-orchestrator's log file is critical. It serves three purposes:
- Progress visibility: Owner can read it mid-run to see how things are going
- Crash recovery: If the sub-orchestrator dies, the log shows what completed
- Audit trail: Post-run record of every score, fix, and decision
# Quality Audit Log
**Started:** 2026-03-26 14:00
**Rubric:** SEO/AEO/Quality, threshold 85+
**Total posts:** 77
## Batch 1 (posts 1-10)
| # | File | SEO | AEO | Quality | Pass | Action |
|---|------|-----|-----|---------|------|--------|
| 1 | ai-security-basics.md | 87 | 91 | 83 | FAIL | Fixed -> 87 |
| 2 | aibm-marina-marketing.md | 92 | 88 | 90 | PASS | -- |
| 3 | ... | ... | ... | ... | ... | ... |
## Batch 2 (posts 11-20)
...
## Summary
[populated after all batches complete]Sub-orchestrators follow the divergent mode rules:
- Workers: Always serial. They score one file against a rubric -- no ambiguity, no multi-path evaluation needed.
- Sub-orchestrator: Serial for batch management. Divergent mode doesn't add value to "dispatch 10, collect, dispatch 10 more."
- Master: Divergent when deciding WHAT to do with the results (fix strategy, priority order, which failures to accept vs retry).
The divergent mode prompt (DIVERGENT MODE: <MODE>) passes from master to sub-orchestrator to worker only when the task type warrants it. Scoring against a rubric doesn't warrant it. Deciding how to fix a failing post might.
For very large operations, sub-orchestrators can dispatch their own sub-orchestrators:
MASTER
|-- Sub-Orchestrator: "Audit all 6 content categories"
|-- Sub-Orchestrator: "Audit category-A posts (15)"
| |-- Workers (batches of 10)
|-- Sub-Orchestrator: "Audit category-B posts (12)"
| |-- Workers (batches of 10)
|-- ...
Use sparingly. Each nesting level adds dispatch overhead and return aggregation complexity. Two levels (master -> sub-orch -> workers) handles most real workloads. Three levels is the practical maximum.
- Less than 15 tasks: Flat dispatch from master is simpler and faster
- Tasks require owner decisions mid-stream: Use flat dispatch so master can ask the owner between agents
- Tasks are highly heterogeneous: Different task types with different prompts are better as separate flat dispatches
- Debugging: When something is going wrong, flatten the hierarchy so you can see each agent's behavior directly
| Aspect | Flat (master->agents) | Sub-orchestrator |
|---|---|---|
| Master context cost | O(N) -- one dispatch + result per task | O(1) -- one dispatch + result total |
| Tracking complexity | Master tracks all N tasks | Sub-orchestrator tracks, master sees summary |
| Crash recovery | Master re-dispatches failed agents | Sub-orchestrator handles retries internally |
| Owner visibility | Owner sees each result as it arrives | Owner sees summary after completion (log file for mid-run visibility) |
| Batch management | Master manages waves manually | Sub-orchestrator manages waves automatically |
| Latency | Lower for small N (no orchestrator overhead) | Lower for large N (master doesn't bottleneck) |
Problem: 77 blog posts needed scoring against SEO/AEO/Quality rubric. Posts below 85 needed automated fixes. Owner wanted category-level reporting.
Solution: Master dispatched one sub-orchestrator with the full post list, rubric, and batch size of 10. Sub-orchestrator managed 8 batches of workers. Each worker scored one post. Failed posts got a fix-and-rescore cycle within the same batch. Sub-orchestrator maintained a log file throughout. After completion, returned aggregate scores by category with visual breakdown.
Result: 63 passed, 11 auto-fixed to passing, 3 required manual attention. Owner reviewed the summary and log file, spent 15 minutes on the 3 failures instead of hours on all 77.
Problem: 22 repos needed checking for outdated dependencies, security advisories, and version alignment.
Solution: Master dispatched a sub-orchestrator with the repo list. Sub-orchestrator ran workers in batches of 8 (lighter than content scoring -- no file writes). Each worker ran npm audit, checked package.json versions against the tech stack standard, and returned a risk score. Sub-orchestrator aggregated by severity.
Problem: Generate draft content across 6 business verticals, each with different voice, audience, and keyword targets.
Solution: Master dispatched 6 sub-orchestrators (one per vertical). Each sub-orchestrator managed its own batch of content-generation workers. Each worker drafted one post. Sub-orchestrators scored drafts against vertical-specific rubrics and fixed below-threshold content. Master received 6 summaries with per-vertical quality metrics.
When setting up a sub-orchestrator:
- Define the goal (one sentence)
- Define the worker prompt template (what each worker does)
- Define the scoring/success criteria
- Set batch size (default 10, lower for heavy workers, higher for lightweight)
- Define log file path and format
- Define the return summary format (what master needs)
- Define fix-and-retry behavior (auto-fix? how many retries? escalation threshold?)
- Include DIVERGENT MODE in the prompt chain if applicable
- Test with 2-3 items before scaling to full set