One of four places decides which model actually runs when you trigger a subagent in Claude Code, and which of those four wins changed in the summer of 2026. An orchestration flow built on a wrong assumption can end up running even a simple file-scan task on the most expensive model — a leak that's hard to notice and shows up fast on the bill. This guide walks through the current resolution chain, why inherit quietly turns expensive, and how to match the right model to the right task type, step by step.
💡 Pro Tip: Whenever you don't explicitly pass amodelparameter on a subagent call, and the agent frontmatter andCLAUDE_CODE_SUBAGENT_MODELare both empty, that call inherits the model of the main conversation — forgetting this is the most common source of hidden cost.
Table of Contents
- The model resolution chain: call parameter > agent frontmatter > env default > parent
- Why this ordering matters
- What 'inherit' means and why it quietly turns expensive
- Practical checklist
- The task-to-model matching table (discovery/mechanical · well-specified code · hard verify)
- The default behavior of the general-purpose subagent
- Three questions to ask when deciding
- [The silent trap: an agent dropping to a 200K context when the
[1m]tag gets ignored](#the-silent-trap-an-agent-dropping-to-a-200k-context-when-the-1m-tag-gets-ignored) - Why this is especially dangerous in subagents
- Behaviors that miss prompt cache, and /cost's new 'why it missed' line
- The new signal in /cost and the status line
- Passing a long subagent prompt from a file (--append-subagent-system-prompt-file)
- The token overhead of agent teams and when it's worth it
- A simple decision rule
- Verification: proving which model actually ran with /tasks and modelUsage
- FAQ
- Which model does a subagent use in Claude Code, and how do I force it?
- How expensive does it get if I call a subagent without specifying a model?
- Why does prompt cache get missed, and how do I see why?
- Is agent teams or a single subagent cheaper?
- [Why can the
[1m]tag get ignored?](#why-can-the-1m-tag-get-ignored) - Which task should go to which model class?
- Conclusion
- Sources
The model resolution chain: call parameter > agent frontmatter > env default > parent
Claude Code decides which model a subagent runs on by checking four points in order. Per the official documentation, the order is: first the per-invocation model parameter on the Agent call, then the model field in the subagent definition's YAML frontmatter, then the CLAUDE_CODE_SUBAGENT_MODEL environment variable, and finally — if none of those are set — the main conversation's (parent) model kicks in.
This ordering wasn't always this way. Before v2.1.251, the CLAUDE_CODE_SUBAGENT_MODEL environment variable sat at the front of the chain — overriding both the per-invocation model parameter and a model: inherit setting in the frontmatter. A team that set the env variable thinking it was just a "default" was actually force-binding every call to that model, no matter what a call explicitly requested. v2.1.251 reversed this and demoted the env variable to a true default: a floor that kicks in only when nothing else is explicitly set.
Why this ordering matters
In practice, this means you can choose the model at three different layers:
- At call time (the
modelparameter inside theAgenttool or workflowagent()) — most specific, and always wins while the force flag is off. - In the agent definition (the
model:field in.claude/agents/*.mdfrontmatter) — a fixed preference that applies every time you call that agent. - In the environment variable (
CLAUDE_CODE_SUBAGENT_MODEL) — the last-resort default that kicks in only when nothing else is explicitly set.
If all three are empty, the subagent inherits the main conversation's model — this applies to the built-in Explore and Plan agents too. One more note for Explore: on the Claude API, the inherited model is capped at Opus.
What 'inherit' means and why it quietly turns expensive
When an agent definition says model: inherit, that subagent uses the main conversation's model. This looks like a quick default, but in practice it can surprise you in two different ways.
The first is simple: if the env variable isn't set (or the frontmatter already says inherit) and the main conversation is running on an expensive model, then the subagent you called for "just scan the files" runs on that same expensive model. For discovery and mechanical work, this means an unnecessarily costly turn.
The second is a lesser-known trap: CLAUDE_CODE_SUBAGENT_MODEL alone doesn't affect built-in agents like Explore and Plan. To also bind those, you need CLAUDE_CODE_SUBAGENT_MODEL_FORCE set to 1. The flag's semantics: (a) with both set, subagents run on the model in CLAUDE_CODE_SUBAGENT_MODEL — while the flag is on, every subagent's model field, including Explore and Plan, is ignored, and the per-invocation parameter can't be passed either; (b) with only CLAUDE_CODE_SUBAGENT_MODEL_FORCE set, subagents run on the main model, while Explore keeps its own ceiling; (c) even with both set, a fork and a subagent-run skill with model: inherit still stay on the main model; (d) the flag requires Claude Code v2.1.257+.
Practical checklist
- Review every agent definition that says
model: inherit— this is a cost decision tied to how expensive the main model is. - If you want to steer built-in agents like Explore/Plan,
CLAUDE_CODE_SUBAGENT_MODELalone isn't enough; you needCLAUDE_CODE_SUBAGENT_MODEL_FORCE=1(v2.1.257+), and account for the fact that while the flag is on, a fork and amodel: inheritskill still stay on the main model. - Don't assume the env variable is a rule that "overrides everything" — after v2.1.251 it's only the last-resort default.
The task-to-model matching table (discovery/mechanical · well-specified code · hard verify)
The official cost guide recommends specifying a cheap model in the subagent configuration for simple subagent tasks. The bundled claude-api skill clarified this further: even when choosing cheap worker/subagent models, they still need to be "current-generation." The record doesn't say more than that: cheapness alone isn't a sufficient criterion — the model also has to be current-generation.
Task type | Example work | Recommended model class | Why |
|---|---|---|---|
Discovery / mechanical | File scanning, grep inventory, link checking, simple format conversion | Cheap, current-generation model | Low reasoning, high volume — running it on an expensive model is pure waste |
Well-specified code | Writing a function/endpoint to a defined interface, a migration with a clear schema | Mid-to-upper-tier model | If the spec is clear, you don't need the "strongest" model, but accuracy still needs to beat a cheap model |
Hard verify / adversarial judge | Verifying a security-critical flow, post-migration integrity checks, an adversarial review | Strongest / highest-effort model | The cost of a false negative (a missed bug) is highest here |
The default behavior of the general-purpose subagent
A general-purpose subagent, with no explicit model setting and an empty env variable, falls straight through to the main conversation's model. In a flow that frequently calls it, you need to explicitly control which model it gets rather than assuming — especially if the main model is expensive.
This becomes especially visible in a multi-step orchestration script. If a workflow calls general-purpose dozens of times without ever passing a model parameter, its total cost hinges on a single variable — which model the main conversation opened with. Run the same script one day with an expensive main model and the next with a cheap one, and total cost can differ significantly though the code never changed. That's why adding a task-appropriate model value to every agent() call is the one practical step that makes a workflow's cost predictable at the code level.
Three questions to ask when deciding
Three questions, asked in order, turn the table above into practice:
- How much reasoning does this task require? A mechanical file scan and verifying a security flow don't deserve the same model class.
- How costly is a wrong result? A file a discovery agent misses is usually caught in the next step; a security vulnerability a verify agent misses is far more costly.
- How often will this call repeat? A high-volume, frequently repeated task turns even a small price difference between model classes into a large aggregate impact.
The silent trap: an agent dropping to a 200K context when the `[1m]` tag gets ignored
In a setup using a long-context pin (the [1m] tag on ANTHROPIC_DEFAULT_FABLE_MODEL), agents defined as model: fable were, for a while, ignoring this tag and silently dropping to a 200K context window. The insidious part: the agent didn't error out, it just worked with a shorter context — a subagent scanning a large codebase could produce a result based on half the information, unnoticed.
This has since been fixed; but the lesson remains: verify which model a subagent actually runs on, rather than assuming. Your definitive signal is the modelUsage field in the result message — it gives the actual model identity; "I set a pin, it must be working" isn't sufficient evidence. Keep the distinction clear: modelUsage reports which model identity ran, not the context window.
Why this is especially dangerous in subagents
It's easier to notice a context narrowing in the main conversation because you're following it directly. But when a subagent runs in the background, in its own isolated window, and quietly returns with a narrowed context, you only realize the result is incomplete afterward — maybe when a later step reveals an inconsistency. For a subagent task needing a long context (say, a discovery agent scanning an entire codebase), verifying once which model identity actually ran is far cheaper than debugging it after the fact.
Behaviors that miss prompt cache, and /cost's new 'why it missed' line
Prompt cache lowers cost by avoiding reprocessing the previous context on consecutive requests sharing the same system prompt and tool definitions. But it's fragile: even a small change in the request prefix can miss the cache. The first four items below are concrete behaviors from the official changelog; the last is a direct consequence of this general caching mechanic:
- Tool definitions or the system prompt changing — using a different tool set or a different system prompt between subagent calls changes the request's prefix and invalidates the cache.
- TTL expiring — the cache drops after a certain time (TTL); a session sitting idle through that window misses the cache on its next request.
- First-turn announcements being re-sent in agent teams — in-process teammates were re-sending first-turn tool and skill announcements on the second turn, changing the request prefix and missing the cache. This behavior has since been fixed.
- Post-tool context not being cached in Fable 5.1 — in Fable 5.1 sessions, context added after a tool result was previously left outside the cache scope, and got re-sent as uncached input on every tool-call turn. This is another one of the behaviors that has been fixed.
- Small prompt variations breaking the same prefix — a system prompt phrased slightly differently on each call counts as a different request for caching purposes, even if it's technically "the same job."
The new signal in /cost and the status line
Now, /cost output and the status line's prompt_cache field also show a possible reason when a miss happens — e.g. "tool definitions changed" or "TTL expired." A signal that previously only said "cache missed, total cost is X" now says "here's why it missed." Know its scope: it only covers the main conversation, not subagents. When cost unexpectedly spikes, check this line first to see which tool-set or system-prompt change broke the cache.
Passing a long subagent prompt from a file (--append-subagent-system-prompt-file)
The text form of appending a long, reusable system prompt to a subagent (--append-subagent-system-prompt) has been around a while; it's passed in non-interactive (headless) mode and appended to every subagent's system prompt, including nested ones. It has one permanent limitation: a forked subagent doesn't receive it, since it reuses the conversation's own prompt. --append-subagent-system-prompt-file doesn't remove that limitation — it only solves the case where the text is too long for the command line; you save the prompt to a file and pass its path instead. Requires Claude Code v2.1.261+.
This has two practical benefits:
- Readability — instead of embedding a string hundreds of characters long into the command line, you can keep the prompt in a separate file tracked in version control.
- Reusability — by referencing the same file across different subagent calls, you can update the prompt from a single place.
1# Append a long subagent system prompt from a file2claude --append-subagent-system-prompt-file ./prompts/security-reviewer.md \3 -p "Review the auth changes in this PR"It's an ergonomic improvement for teams who, in an orchestration script, want the same long instruction set kept in one central file rather than repeated inline, updated from a single place when it changes.
The token overhead of agent teams and when it's worth it
Agent teams is an experimental mode letting multiple agents work together at once (enabled with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1, off by default). The official documentation warns directly: this mode consumes significantly more tokens than a single session — each teammate carries its own independent context window, making it structurally more expensive than doing the same work synchronously with one subagent.
That's why, instead of making agent teams your default, reserve it for work that genuinely requires real-time coordination — agents that need to see each other's intermediate output as they progress. For sequential work or work on the same file, it isn't recommended; that completes far more cheaply with a single Agent tool call (fire-and-return).
A simple decision rule
1Is the task parallel AND do the agents genuinely need2each other's intermediate results in real time?3 YES → agent teams (accepting the token overhead)4 NO → single subagent / sequential Agent callsThe cache-miss fix in v2.1.261 (eliminating the repeated second-turn announcements) somewhat reduces agent teams' cost disadvantage, but it doesn't eliminate the structural token gap — the fact that each teammate carries a separate context window hasn't changed.
Verification: proving which model actually ran with /tasks and modelUsage
A configuration "looking right" and it "actually working that way" are different things. Verify which model a subagent ran on with two concrete signals, rather than assuming:
/tasks— shows which model a running or finished subagent ran on.- The
modelUsagefield in--output-format jsonoutput — the definitive signal carrying the actual model identity; since the stderr model warning is suppressed in JSON mode, read the real model from here.
Checking the model doesn't stop at the env variable or the call parameter — it also has to cover the model: field in the subagent's own frontmatter, since frontmatter comes before env in the chain.
Signal | Where to look | What it shows |
|---|---|---|
/tasks | Terminal command | Which model a running/finished subagent ran on |
modelUsage | --output-format json output | The actual model identity (a definitive signal independent of stderr warnings) |
prompt_cache field | /cost or status line | The likely reason if a cache miss happened — main conversation only; doesn't cover subagents |
1# Read the running model identities (use /tasks for per-subagent breakdown)2claude -p "..." --output-format json | jq '.modelUsage'After configuring model assignment in an orchestration flow, checking one of these signals at least once — especially for a cost-critical subagent — turns "I set it, it must be working" into "I set it, I verified it." That difference prevents a mismatch between the final bill and what you expected.
GOLDEN TIP
The most valuable insight in this article
This tip holds the article's most important takeaway.
Easter Egg
You found a hidden gem!
There's a hidden detail in this section. Want to uncover it?
Reader Reward
Below is a single checklist for putting this guide into practice. Check off each item in your own setup and you can be sure your model assignment is both correct and verified.
FAQ
Which model does a subagent use in Claude Code, and how do I force it?
The resolution order has four steps: the per-invocation model parameter, then the YAML frontmatter model field (inherit picks the main model), then CLAUDE_CODE_SUBAGENT_MODEL, and finally the main conversation's model. The env variable is now only a default kicking in when nothing else is set; for real forcing, set CLAUDE_CODE_SUBAGENT_MODEL_FORCE to 1 (v2.1.257+) — with both set, every subagent, including Explore and Plan, runs on the env model.
How expensive does it get if I call a subagent without specifying a model?
If no model is specified, the subagent inherits the main conversation's model — Explore and Plan behave this way too. In a session on an expensive main model, even a simple discovery task runs there. Verify which model ran with /tasks or the modelUsage field in --output-format json output.
Why does prompt cache get missed, and how do I see why?
The prompt_cache field in /cost and the status line directly shows the likely reason (tool definitions or system prompt changed, TTL expired, etc.); it covers the main conversation only, not subagents. Also fixed in agent teams: in-process teammates were re-sending first-turn announcements on the second turn, changing the request prefix and missing the cache.
Is agent teams or a single subagent cheaper?
A single subagent (a synchronous Agent tool call) is structurally cheaper — it carries one context window. Agent teams, per the official docs, consumes significantly more tokens than a single session, since each teammate carries its own window. Prefer it only when genuine real-time coordination is needed; not recommended for sequential or same-file work.
Why can the `[1m]` tag get ignored?
The [1m] tag on a long-context pin was a behavior where agents defined as model: fable would, for a while, ignore this tag and silently drop to a 200K context window. This has since been fixed, but the core lesson remains: verifying which model identity actually ran via modelUsage is safer than assuming.
Which task should go to which model class?
Routing discovery and mechanical work (file scanning, inventory, format conversion) to a cheap, current-generation model, well-specified code writing to a mid-to-upper-tier model, and hard verify/adversarial judge work like security-critical verification to the strongest/highest-effort model balances both cost and accuracy.
Conclusion
Subagent model assignment in Claude Code now relies on a predictable chain: call parameter, agent frontmatter, env default, then the main model. Knowing this order isn't enough — verify via modelUsage, /tasks, and /cost when inherit quietly turns expensive, which model identity actually ran, and which behaviors miss the prompt cache. Turning on agent teams only for work needing real-time coordination, and using a single subagent elsewhere, also minimizes the structural token gap.
If you want to go deeper on your orchestration setup, check out the guide to multi-agent teams and parallel work in Claude Code or architectural planning with plan mode. To go deeper on prompt caching on the API side, the guide to cutting cost 10x with Claude prompt caching is a complementary resource. If you want to set up hook-based automation, the Claude Code hooks automation guide can help, and for MCP integrations, the Claude Code MCP guide is also a resource.
Sources
- Claude Code sub-agents documentation — the model resolution order and the
--append-subagent-system-prompt-fileflag - Claude Code model-config documentation — model configuration and environment variables
- Claude Code cost documentation — the cheap-model recommendation for simple subagent tasks and the scope of the
Prompt cache (main)line - Claude Code agent-teams documentation — the token overhead warning and usage conditions
- Claude Code prompt caching documentation — actions that invalidate the cache and the prefix mechanic
- Claude Code official CHANGELOG (GitHub) — v2.1.251, v2.1.260, v2.1.261 release notes
- Claude Code changelog (docs mirror) — release history view
Tags
iOS Development News
Weekly Swift tips, SwiftUI tricks and iOS best practices. No spam, only valuable content.
We respect your privacy. You can unsubscribe at any time.

