blog
Claude Code subagent cost: cut 40-78% per implementer call
A Claude Code subagent loads tens of thousands of tokens of rules and skills at every start, then repeats them over dozens of turns. I measured it from transcripts, replaced it with a dedicated agent, and compared 3 real subagent-driven-development runs.
- Published
A Claude Code subagent is expensive because 3 things multiply: the context loaded at startup, the number of turns, and the model picked at call time. The delegation prompt barely matters. A dedicated agent cut startup context from 68,168 to 6,781 tokens in a measurement on a scratch repo; in 3 real runs, cost per Sonnet implementer call dropped 40-78% against the old baseline for the same role.
Subagent cost sits in startup context, not in the delegation prompt
I run about 20 Claude Code sessions in parallel on a single Mac, a separate session per project. The superpowers plugin is on by default, so long work follows the subagent-driven-development (SDD) skill: the main session orchestrates, each task gets a fresh implementer subagent and its own reviewer, and the fix loop has a round cap. When the plan is done, the strongest model reviews the whole branch. A turn is one round trip between the subagent and the model plus its tools.
7 days of numbers for the general-purpose agent, read only from usage fields in transcripts:
| Model | Calls | Avg turns | Startup context | Tokens read from cache |
|---|---|---|---|---|
| Opus | 249 | 41 | ~60k | 1.54 billion |
| Sonnet | 352 | 25 | ~65k | 1.13 billion |
A different sample of 10 subagents gave startup context (called ctx0 from here on) averaging ~83k tokens, while the delegation prompt was 1-2 thousand characters. The rest is what the subagent loads on its own, measured in characters:
- User-level
CLAUDE.md, ~11.5k characters. - The repo's
AGENTS.md, the biggest part: one repo has a 95k-character file, about 50k tokens. My repos pull it in through an@AGENTS.mdline inCLAUDE.md. - The skill list, ~25k characters.
SessionStarthook output, the agent list, tool definitions.
Every turn the subagent re-reads that context plus what has piled up since (tool output, earlier turns), 130-150k tokens per turn on average.
Cache reads inflate raw token counts, so use cost_units
Cache reads cost 0.1 times the input price. The 1.54 billion figure sounds scary, but most of it is cheap cache reads. What multiplies cost is the number of turns and the tool output carried through each one. So I measure with a weighted cost, in units of the model's base input price:
cost_units = input + 1.25 × cache_write_5m + 2 × cache_write_1h
+ 0.1 × cache_read + 5 × output
Compare cost_units within one model. Do not draw conclusions from raw tokens.
Measure ctx0 and cost_units from transcripts
Each subagent has its own transcript at subagents/agent-*.jsonl. ctx0 is input + cache_read + cache_creation of the first assistant message. The agent-*.meta.json file gives the agent type, model and call id; match that id to the Agent call in the parent session's transcript to see whether a model was passed.
To compare configurations I used a scratch repo that copies the rules of a real repo (the real repo stays untouched) and ran claude -p with a Sonnet parent session and an empty MCP set (--strict-mcp-config). The parent calls exactly 1 subagent for 1 fixed job: read go.mod, return 3 lines. Each configuration ran 2 times, and ctx0 matched to the token across the 2 runs. Whether the skill list reaches a subagent comes from grepping the skill_listing attachment in the transcript, not from asking the model.
Drop CLAUDE.md and the Skill tool: ctx0 down 93% in the measurement
Scratch repo carrying the rules of a repo with a 95k-character AGENTS.md:
| Configuration | ctx0 |
|---|---|
general-purpose | 68,168 |
Dedicated agent, narrow tools, still loads CLAUDE.md | 55,437 (-19%) |
Dedicated agent, omitClaudeMd: true, with Skill tool | 13,009 |
Dedicated agent, omitClaudeMd: true, no Skill tool | 4,857 (-93%) |
| Built-in Explore | 15,338 |
Custom Explore, omitClaudeMd, no Skill | ~4.2k |
The 2 middle rows show the skill list weighs ~8k tokens and only appears when the agent has the Skill tool. The SDD prompts call no skill, so dropping the tool costs nothing.
Per the subagent docs, the frontmatter supports omitClaudeMd (start without the user, project and local CLAUDE.md files in initial context), tools, maxTurns and effort. The docs say omitClaudeMd needs Claude Code v2.1.271 or later, and a subdirectory's CLAUDE.md still loads when the agent works with files there. My implementer agent, trimmed:
---
name: sdd-implementer
description: Implements one plan task from its brief file
model: sonnet
effort: high
maxTurns: 60
omitClaudeMd: true
tools: Read, Edit, Write, Bash, Grep, Glob
---
The reviewer has only Read, Grep, Glob, Bash, no Write or Edit, and a 20-turn cap. After installing them, the probe gave ctx0 6,781 for the implementer and 6,208 for the reviewer, against 68,168 before. In the 2 real runs ctx0 was higher than the probe (10.9-11.8k); I have not isolated the cause.
The agent no longer loads AGENTS.md, so the delegation prompt has to name which AGENTS.md sections matter, by heading, plus the files to read. The agent lists the headings and reads only those sections, not the whole 95k-character file.
Most Claude Code subagent Opus cost comes from picking Opus at call time
Only 22% of 7-day Opus cost came from calls that passed no model. Only that slice can be changed with CLAUDE_CODE_SUBAGENT_MODEL, because per the docs (since v2.1.251) the model resolves in this order: the model parameter at call time, then model in the frontmatter, then the environment variable, then the main session's model. Most of the rest is Opus picked at call time: SDD in one repo took 52% of Opus cost (implementer, reviewer and final review all on Opus), and writing plans added 20%.
The built-in Explore uses the main session's model. Per the docs, when the main session runs Fable through a subscription plan, Explore runs on Opus. To change it, define an agent with the same name, Explore, and it overrides the built-in.
The model rules per role that I kept:
- Implementer: Sonnet. Escalate to Opus at rounds 4-5 of the fix loop or for an architectural task.
- Reviewer: Sonnet, but Opus when the diff touches security, permissions, concurrency or a data migration. The reviewer is the quality gate, so it does not get downgraded where the risk is.
- Whole-branch final review: Opus.
CLAUDE_CODE_SUBAGENT_MODELset to Sonnet as the default. I do not use the_FORCEvariant (it forces every subagent onto one model) because the final review needs Opus.
I do not edit superpowers files (an upstream update would overwrite them) and I do not override general-purpose (every other subagent would lose CLAUDE.md). I also do not build business-role agents: an earlier test cost ~2.4 times the tokens, and the model delegated to the right role 0 of 5 times.
3 real runs: a direction, not an A/B test
Runs 1 and 2 were in the same Go repo with a web app, on the night of 4 Nov. Run 3 started after every session restarted with the new configuration. All numbers come from a script that reads usage from transcripts. The tasks differ in each run, so treat the numbers as a direction.
The baseline is the 7 days before the configuration change (up to 4 Nov 01:23 local time), in the same repo, on the old SDD setup with general-purpose. I split the baseline by role by reading the text of each call's description and delegation prompt. This is a heuristic classification that matched 251 of 252 Sonnet calls:
| Role | Model | Calls | Avg turns | ctx0 | cost_units per call |
|---|---|---|---|---|---|
| Implementer | Sonnet | 137 | 40.7 | 69.4k | 1.13M |
| Reviewer | Sonnet | 99 | 8.4 | 70.2k | 0.24M |
| Implementer | Opus | 41 | 71.0 | 71.1k | 2.27M |
| Reviewer | Opus | 44 | 24.5 | 67.9k | 0.78M |
| Final review | Opus | 25 | 37.7 | 70.2k | 1.06M |
cost_units on each row is in the base input price of that row's model, so Opus and Sonnet rows are not comparable.
Run 1: 1 SDD plan with 8 tasks, a whole-branch final review, and a fix pass after it. Sonnet implementer, Sonnet reviewer (Opus for 3 risky tasks: a migration, seeding real data, a data-exposure boundary), Opus final review.
| Role | Calls | Avg turns | ctx0 | cost_units per call |
|---|---|---|---|---|
| Sonnet implementer | 9 | 19.2 | 10.9k | 0.25M |
| Sonnet reviewer | 6 | 5.7 | 10.2k | 0.08M |
| Opus reviewer | 3 | 7.3 | 10.2k | 0.12M |
Opus final review (general-purpose, still loads the rules) | 1 | 34 | 86.7k | 0.89M |
The Sonnet implementer against the baseline for its role: cost_units per call from 1.13M to 0.25M (-78%), turns from 40.7 to 19.2, ctx0 from 69.4k to 10.9k. The Sonnet reviewer went from 0.24M to 0.08M (-67%).
Quality in run 1 (there is no earlier quality baseline to compare): 0 fix-loop rounds across all 8 tasks, no Critical or Important findings. The Opus final review found 8 Minor issues, 7 of which the per-task reviewers had already flagged; the fix pass handled 6 and the re-review confirmed them.
Run 2: 5 plan streams in parallel through a workflow, one worktree each. Each branch gets a final review, then they merge one by one into an integration branch and the full e2e suite runs.
| Role | Calls | Avg turns | ctx0 | cost_units per call |
|---|---|---|---|---|
| Sonnet implementer | 18 | 24.2 | 11.8k | 0.33M |
| Sonnet reviewer | 12 | 8.1 | 11.1k | 0.09M |
| Opus reviewer (risky diffs) | 3 | 6.3 | 11.2k | 0.08M |
general-purpose Opus (final review, branch merges, e2e) | 5 | 49 | 88.8k | 1.09M |
The Sonnet implementer: 1.13M down to 0.33M (-71%), 27 implementer calls in runs 1 and 2 combined.
Run 3: one orchestrating session drove 4-5 plans in parallel for about 5 hours, after every session restarted with the new configuration. In total 126 subagent calls and 56.9M cost_units; the table lists 4 roles, 119 of the 126 calls.
| Role | Calls | cost_units per call | Old baseline, same role |
|---|---|---|---|
| Sonnet implementer | 45 | 0.68M (0.43M without the 5 capped tasks) | 1.13M |
| Sonnet reviewer | 35 | 0.11M | 0.24M |
| Opus reviewer (diffs touching security, concurrency) | 31 | 0.23M | |
general-purpose Opus (final reviews, re-reviews, 1 plan) | 8 | 1.01M |
The Sonnet implementer is down 40% against the 1.13M baseline, and 62% if you leave out the 5 capped tasks (0.43M). The Sonnet reviewer is down 54%. The 2 Opus rows have no same-role baseline to compare. Every implementer and reviewer went to the right slim agent, starting at a ctx0 of 10-12k against 70-90k before, and every call named a model, even though the rule was only a paragraph in CLAUDE.md, with no enforcing hook.
What broke in the 3 runs: maxTurns, repo rules, diff bundles
The general-purpose Opus agent is the next bottleneck. In run 2 it made 5 of 38 calls but used 5.46M of 12.8M cost_units (43%), because it still loads ~89k of rules context every turn. The 12.8M total adds Sonnet and Opus units, each in its own model's base price, so in money terms Opus's share is larger. The next job is a dedicated agent for final review and branch merges.
ctx0 is now only 7% of an implementer's cost. Most of the remaining cost is probably tool output carried through every turn, such as e2e logs and screenshots. That is a hypothesis; I have not measured it.
A maxTurns cap of 40 is too low for long tasks. In run 2, 4 of 5 streams stopped with the message "completed without calling StructuredOutput". The real cause was 5 implementers hitting exactly the 40-turn cap mid-task, counted by message id in the transcript. 40 is not a workflow cap: general-purpose in the same workflow ran up to 138 turns.
5 cap hits gave 4 stopped streams because one stream had 2 implementers hit the cap, on task 1 and task 5. On task 1 the script retries once with a stronger model when an agent returns an empty result, and that retry rescued it; on task 5 it did not, so the stream stopped. 3 other streams had 1 implementer hit the cap each and stopped. The fifth stream ran through to the merge.
The web task in run 1, with an 18.7-minute e2e run, already used 39 of 40 turns. I raised the cap to 60 at 03:03 after run 1, but the orchestrating session in run 2, opened at 02:20, kept cutting implementers at 40 turns from 07:41 to 08:17, which is 4.5-5 hours after the agent file was edited. With the cap at 60, run 3 still had 5 of 45 implementers hit it (web screen tasks with e2e): 60 is still tight when a task has e2e. 3 lessons:
- Editing an agent in a plugin may not reach a running session. Another session picked up the new agent and its edited body right away while the orchestrating session kept the old cap, and I cannot explain why. Per the docs, agents in
~/.claude/agents/are file-watched so an edit takes effect right away, while plugins load when a session opens or when you run/reload-plugins(plugin loading). The safe move per the docs, which I have not tried myself: after an edit, run/reload-pluginsor reopen the session. - The orchestration script should treat a null result as a hit cap and call again with "continue the unfinished part". Through the regular Agent tool, a subagent that hits
maxTurnsreturns output marked partial and the main session can resume that agent, per the docs. Inside a workflow the result becomes null; a community issue describes exactly this misreport (I could not read the issue's content). In run 3, all 5 implementers that hit the cap of 60 were resumed by the orchestrating session through the Agent tool and finished. - The error message names no cause; you have to count turns in the transcript to find it.
Agents missing repo rules. Run 1 had 3 Minor issues of this kind: leaving orphaned CSS although the rule existed, using git stash to prove a test fails before the fix, and editing a demo fixture to match a key that a new test catches.
The git stash case is the dangerous one, because the stash stack is shared across every worktree and session of the repo: another session pops it and takes your changes. I added a ban on git stash to the implementer agent and require it to prove the test fails by running the new test before writing code. Across 66 subagent transcripts after the rule was added, git stash was used exactly once, in the run 2 orchestrating session that still ran the old agent definition, so the rule's effect is not proven. Sessions opened after the restart: 0 uses.
The orchestrator does not know what the agent already carries. The main session assumed the agent lacked the temp-file rules and pasted them into each prompt, while the agent already had them. The lesson: list for the orchestrator exactly which rules each agent ships with.
The diff bundle for the reviewer balloons. The script that packs a diff for the reviewer produced 113-133 KB bundles when the diff had very long lines, such as one-line JSON. The fix I propose (not done yet): drop long-line files from the plain diff and print a separate word-diff.
Rules drift between agents. To keep the rules from drifting between copies, the agent body is generated from one shared rules file with a <!-- include: rules.md#Section name --> marker, and the build script errors if a section is renamed. Including a whole section is too coarse for a read-only agent: Explore got file-writing rules it cannot use.
After run 2: step-by-step reports and a dedicated final review
2 more changes followed run 2:
- The implementer now writes its report from the start and commits after each green test step, so the next run reads the report and
git logand carries on. The idea matches Anthropic's article on harnesses for long-running agents: a progress file plus git history tells a fresh session where the work stands. This went in around 10:30 on 4 Nov, I have not measured its effect on its own, but in run 3 all 5 implementers that hit the cap finished after a resume, and the orchestrating session credits this rule. - A dedicated final-review agent (Opus, no
CLAUDE.md, read-only) ran as a canary next togeneral-purpose. The threshold to switch: it catches every Critical and Important finding of the old setup, and cost drops by at least 30%. Results below.
Canary for final review: the dedicated agent is 28% cheaper but missed 1 Important finding
The canary ran on one branch of a side project (Go backend, TypeScript web UI), reviewed after all tasks were done. All 3 versions got the same review package (diff, plan, ledger) and the same prompt. The project session checked every finding against the code.
| Version | Real Important findings caught | Turns | ctx0 | cost_units | Time |
|---|---|---|---|---|---|
general-purpose Opus (current) | 2/2 | 20 | 85.6k | 0.61M | 226 s |
Dedicated final-review agent, Opus, no CLAUDE.md | 1/2 | 27 | 9.5k | 0.44M (-28%) | 254 s |
| Same dedicated agent, Fable | 0/2 | 36 | 9.5k | 0.58M (-5%) | 397 s |
The dedicated agent failed both thresholds. It missed 1 real Important finding: a config field written as null, or as a folded multi-line string, was classed as less privileged than it really is. Cost dropped only 28%, under the 30% bar.
The smaller ctx0 (9.5k against 85.6k) did not pay for itself here. Without the repo rules loaded up front, the agent spent more turns reading (27 against 20), which ate most of the saving and came with a lost real finding. For per-task implementers and reviewers the same trick still pays, as the tables above show. My explanation for the difference: a whole-branch review touches many rule sections at once. I did not measure that separately.
Fable as the final reviewer gave no gain: 0 of the 2 real Important findings caught, the slowest run, and cost close to Opus. Each version still caught a few real Minor findings the other versions missed, so a second opinion has some value, just not enough to replace the current one.
Decision: the final review stays general-purpose on Opus. The dedicated agent stays in the kit, unused. Small sample: 1 branch, 1 run per version, 2 Important findings.
Run 3 in full: 4 places that still cost money
- The turn cap keeps the work, not the cost. 5 of 45 implementers (web screen tasks with e2e) hit the 60-turn cap. The orchestrating session resumed each one, and the work finished thanks to the rule "write the report early, commit after each green step". But a resumed agent keeps its growing context, so these 5 tasks cost 44% of all implementer spend; the 2 biggest ran about 100 turns each. Fix: when writing the plan, split any task likely to need more than about 40 turns.
- Fix loops can grow in scope. One branch's final review led to 5 fix rounds, one escalated to Opus, about 7M in total (about 13% of the run). The code was a hand-written parser behind a security rule, "never report a lower permission level". Each re-review probed further and found one more input shape that slipped through. Every one was a real bug, but each one opened a new round. The right fix only came in round 4: treat any non-simple input as the most privileged level (fail-closed). The rule I took from it: a re-review checks only the previous round's findings, and new findings go to the ledger instead of a new round; if a hand-written parser or guard still leaks at round 2, switch to fail-closed instead of patching shape after shape.
- Side jobs still went to the fat agent. Re-reviews after the final review and branch merges ran as
general-purpose, starting at about 87-90k context: about 6M across 6 calls. A slim agent does the same work at about 0.25M per re-review. - The orchestrator is the next cost. The orchestrator alone cost 22.7M, about 29% of the run's total cost (on top of the 56.9M for subagents). Its average context was 219k, with a peak of 367k and 8 compactions in 5 hours, because one session held 4-5 parallel plans. I have not changed anything here yet; it is an open point.
I folded the first 3 lessons into one general rule for every repo that runs plans with subagents: scoped re-reviews on the slim reviewer, branch merges on the slim implementer, fail-closed at round 2, and splitting tasks over about 40 turns. I have not measured that rule's effect.
Not measured yet: total savings across the whole system
3 runs show cost per implementer call and ctx0 dropping clearly; run 1 quality passed, but there is no earlier baseline to compare. They do not show total savings for the whole system. Run 2 lacks full quality numbers because 4 streams stopped before the final review step; the stream that ran through had 0 fix rounds on its task, and there is nothing more. Run 3 ran its full 5 hours, but the orchestrator cost (22.7M) sits outside the per-call numbers above. The 7-days-before versus 7-days-after numbers for the whole system should be ready around 11 Nov.
Update 11 Nov: the 7-day before and after totals will be added here.
Related posts
all posts →- Mac compressed pages jumped from 5% to 30% because of a log-wait loopA Claude Code subagent waited on an e2e log with a loop that reads /dev/zero. One bash process grew to 47.7 GB and the Mac compressed page count jumped from 5% to 30% of its limit while RAM still showed 71% available.read more →
- A Mac with 65% RAM free nearly panicked: the compressor, IOSurface and Playwright's WebKitA 32 GB Mac Studio panicked with 100% of compressed pages limit, then came close to a second panic that evening while RAM still showed 65% free. The page count in the compressor had filled up, and the culprit was IOSurface that Playwright WebKit left in the kernel.read more →
- REA: letting an agent do reverse engineering, then testing the oracle tooREA lets a coding agent read a program that has no source, down to machine code, then rebuild that feature in its own code. Whether the rebuild is right is up to the oracle, and the oracle is code too, with its own bugs.read more →
- Top 10 Claude Code skills by GitHub stars: what each one does and which ones overlapThe 10 Claude Code skill sets with the most GitHub stars on 29 Oct 2026: Superpowers, Matt Pocock Skills, Karpathy Skills, Anthropic Skills, Ponytail, UI UX Pro Max, Graphify, Caveman, Agent Skills, Taste Skill. Each one with its install command, what it does and where it overlaps with another set.read more →