You want Claude Code's main session on Opus 5 with the effort level kept high. But running jobs like translation or checking piles of files on that same model feels wasteful. So the question is: can you run just the subagents on Sonnet or Haiku?

Short answer: yes. A subagent's model is decided separately from the main session, and you can change it with a model passed at invocation, with model in the definition file, or with an environment variable. Effort can also be set to a different value for each subagent.

In this article I lay out the behavior described in the official documentation as of September 15, 2026, and then share what happened when I actually launched subagents on different models and checked the conversation logs. I gave the same translation job to Opus 5, Sonnet 5 and Haiku 4.5, twice each, and compared time, cost and translation quality.

A subagent's model is the first match, checked from the top down

If none applies, it runs on the main conversation's model

1
The model passed at invocation: the model Claude attaches when it launches the subagent
2
model in the definition file: inherit means the same as the main session
3
The CLAUDE_CODE_SUBAGENT_MODEL environment variable: the default when nothing else decided it
4
The main session's model

Source: Claude Code documentation, Create custom subagents (Choose a model). Before v2.1.251, item 3 was at the top

1. What you can do: run subagents on a different model and effort

A subagent is a worker with its own separate context that Claude Code launches to hand off part of a task. It does not share conversation history with the main session, and when it finishes it returns only its result (how it differs from Agent Teams is covered in Claude Code Subagents vs Agent Teams: Which to Use).

For subagents, the official documentation says you can set the following two things independently.

Model (model)

sonnet, opus, haiku, fable, a full model ID, or inherit

A full model ID looks like claude-opus-5. inherit means the same model as the main session. If you leave it out, the order above decides.

Effort (effort)

low, medium, high, xhigh, max

If you leave it out, the subagent inherits the main session's effort. The available levels vary by model, and Haiku 4.5 does not support effort. If the CLAUDE_CODE_EFFORT_LEVEL environment variable is set, it takes precedence.

In other words, a combination like "main session on Opus 5 at high effort, translator on Sonnet 5 at medium effort" is something you can build as is, within the official behavior. For what effort itself means, see What Is Claude Code's Effort Setting (Faster vs Smarter)?

Source: Claude Code documentation, Create custom subagents (Supported frontmatter fields), Model configuration (effort precedence)

2. The order in which the model is decided

As the figure at the top shows, a subagent's model is the first match in this order: the model passed at invocation, then model in the definition file, then the CLAUDE_CODE_SUBAGENT_MODEL environment variable, then the main session's model. Three points are worth watching.

First, the order depends on the version. Before v2.1.251 the environment variable was at the top, overriding even the model passed at invocation and model in the definition file (including inherit). If you wrote model: sonnet in a definition and it seems to have no effect, check your version and your environment variables first.

Second, there is a separate setting for forcing everything onto one model. The environment variable alone does not affect subagents whose definition file sets model. To force all of them, set CLAUDE_CODE_SUBAGENT_MODEL_FORCE to 1 in addition to CLAUDE_CODE_SUBAGENT_MODEL (v2.1.257 and later).

{
  "env": {
    "CLAUDE_CODE_SUBAGENT_MODEL": "haiku",
    "CLAUDE_CODE_SUBAGENT_MODEL_FORCE": "1"
  }
}

When forced, model in definition files is ignored, including for the built-in Explore and Plan, and Claude can no longer pass a model when it invokes a subagent. There are two exceptions that stay on the main session's model: a fork, which carries over the entire conversation, and a skill with model: inherit running in a subagent.

Third, where sonnet and opus point depends on your provider. Even if you write the same sonnet, the model you get changes as follows.

Provideropussonnet
Anthropic APIOpus 5Sonnet 5
Claude Platform on AWSOpus 5Sonnet 4.6
Amazon Bedrock, Google Cloud Agent PlatformOpus 5Sonnet 4.5
Microsoft FoundryOpus 4.6Sonnet 4.5

Source: Claude Code documentation, Model configuration (table as of September 15, 2026). To pin a specific version, write the full model ID rather than an alias

If your organization's managed settings restrict which models can be used (availableModels), subagent model values and the environment variable are subject to that restriction too.

3. How to set it (five ways)

1. Write it in a definition file (for roles that should always use the same model)

The most practical approach is a definition file per role. Put it in your project's .claude/agents/ to share it through git, or in ~/.claude/agents/ to use it across all your projects.

---
name: translator
description: Translates Japanese articles into English. Use when asked for a translation
model: sonnet
effort: medium
tools: Read, Write, Grep
---
You are a translator of technical articles. Do not change HTML tags or attributes;
turn only the visible text into natural English.

When several definitions share the same name, precedence goes organization managed settings, then --agents at launch, then project, then user, then plugins. Since v2.1.198 the /agents command no longer opens a creation screen, so either ask Claude to create the file or write it yourself.

2. Pass it at invocation (to change it just this once)

Even without a definition, Claude can attach a model when it launches a subagent. If you say something like "hand this check to a Haiku subagent" in the conversation, Claude launches the subagent with that model attached to the call. This takes precedence over the definition file. To confirm it was really attached, use the method in section 5.

3. Set a default with an environment variable (to change everything without a model at once)

{
  "env": {
    "CLAUDE_CODE_SUBAGENT_MODEL": "sonnet"
  }
}

Put it under env in settings.json and it applies to subagents whose model was not decided some other way. According to the official documentation, agent team members and workflow agents are covered as well. However, this alone does not change the model of the built-in Explore and Plan (section 4).

4. Pass it with --agents at launch (for that session only)

claude --agents '{
  "translator": {
    "description": "Translates Japanese articles into English.",
    "prompt": "You are a technical translator. Keep all HTML tags.",
    "model": "sonnet",
    "effort": "medium"
  }
}'

Nothing is saved to a file; the definition lasts only for that session.

5. Define it in the Claude Agent SDK

from claude_agent_sdk import ClaudeAgentOptions, AgentDefinition

options = ClaudeAgentOptions(
    agents={
        "translator": AgentDefinition(
            description="Translates Japanese articles into English.",
            prompt="You are a technical translator. Keep all HTML tags.",
            tools=["Read", "Write"],
            model="sonnet",
            effort="medium",
        ),
    }
)

In the SDK's AgentDefinition, too, model accepts an alias, inherit or a full model ID. If you leave it out, the order above decides. The official documentation also notes that Opus 5 delegates work to subagents more readily than earlier models, and points to settings that cap how many run at once (20 by default) and how much they can spend.

Source: Claude Code documentation, Create custom subagents (locations and precedence, --agents, the change to /agents, environment variables), Model configuration (what CLAUDE_CODE_SUBAGENT_MODEL applies to), Subagents in the SDK (AgentDefinition, limit settings)

4. Which models the built-in subagents use

Even if you define nothing yourself, Claude Code ships with several subagents. Their models are as follows.

NameModelNotes
ExploreInherits the main session's model; capped at Opus on the Claude APIRead-only. Does not read CLAUDE.md or git status
PlanInherits the main session's modelUsed in plan mode. Read-only. Does not read CLAUDE.md or git status
general-purposeWithout a model set at invocation, the environment variable's model; if that is not set either, the main session'sHandles both research and edits
claude-code-guideHaikuWhen you ask about Claude Code features
claudeHas no model of its own; decided by the order in section 2General-purpose fallback when no other role fits
statusline-setupSonnetWhen you run /statusline

Source: Claude Code documentation, Create custom subagents (Built-in subagents, as of September 15, 2026)

Since v2.1.198, Explore no longer always runs on Haiku. It inherits the main session's model, capped at Opus on the Claude API. If the main session is on a higher model such as Fable, Explore runs on Opus; if the main session is on Sonnet or Haiku, Explore runs on that model. To put it back on Haiku, the official documentation suggests creating a definition file named Explore with model: haiku (your own definition takes precedence over the built-in one of the same name).

To change the model of Explore and Plan with the environment variable, you also need to set CLAUDE_CODE_SUBAGENT_MODEL_FORCE from section 2.

5. Measured (1): did it really run on that model?

I checked whether it behaves as documented in my own environment (main session on Opus 5, effort high). I gave the built-in general-purpose subagent the same small task, "read the README and summarize it in three lines", in three variants: with the model set to sonnet, set to haiku, and not set at all.

There are two ways to check. While it is running, the /tasks list shows the subagent's model (as stated in the official documentation). After it finishes, look at message.model on each response in the agent-*.jsonl files in the subagents/ folder of your local conversation logs. Where the logs live and how to read them is covered in detail in Claude Code Usage by Session: How to Measure It.

Model passed at invocationModel recorded in the log
sonnetclaude-sonnet-5
haikuclaude-haiku-4-5-20251001
Not setclaude-opus-5 (same as the main session)

Source: my own measurements (September 15, 2026, desktop app on Windows. Every response from each subagent recorded the same model)

Each ran on the model I specified, and the one without a model inherited the main session's. The agent-*.meta.json file in the same folder records the requested value, such as "model": "sonnet", only when a model was specified.

6. Measured (2): tens of thousands of tokens just to start

The same logs revealed something else. A subagent reads tens of thousands of tokens in its very first response, before it starts any work. Its own system prompt, the tool definitions, CLAUDE.md and so on all go in first.

ModelLaunched with no cache
(cache write)
Same model launched about 1 minute later
(read / write)
Sonnet 583,00744,846 / 38,385
Haiku 4.565,95834,008 / 32,122
Opus 577,23539,159 / 38,298

Source: my own measurements (September 15, 2026. Token counts from each subagent's first response. All writes were to the 5-minute cache)

Three things can be read from these numbers.

First, subagents on the same model read their shared prefix from the cache. On the second launch, about 45,000 tokens for Sonnet 5 were cache reads (0.1x the input price). The official documentation also says requests on the same model with the same prefix share the cache. Conversely, the cache is separate for each model, and subagents do not read the main session's cache either (because the prefix content differs).

Second, even on a subscription, the subagent cache expires after 5 minutes. According to the official documentation, when you use Claude Code within a plan the main conversation gets 1 hour, but subagents get 5 minutes. If you wait more than 5 minutes before launching the next subagent, it starts again with a write. To make it 1 hour, set the subagentPromptCacheTtl setting or the CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL environment variable to 1h (v2.1.242 and later). To decide per subagent, write cacheTtl under experimental in the definition file (v2.1.248 and later; while a subscription is drawing on usage credits, a 1h there is ignored). 1-hour cache writes cost twice the input price (5-minute writes cost 1.25 times).

Third, Haiku 4.5 shows fewer tokens for the same text. According to the official pricing page, Claude 4.7 and later models use a new tokenizer that counts about 30% more tokens for the same text. Haiku 4.5 belongs to a generation before 4.7 and is not listed as using the new tokenizer. If you compare the table's numbers directly, Haiku looks lighter than it really is.

Caveats about these numbers

  • My project has a large CLAUDE.md (about 57,000 bytes), so these numbers run higher than in a typical project. The size of CLAUDE.md is added directly to what every single subagent reads
  • Setting omitClaudeMd: true in a definition file keeps that subagent from loading the user, project and local CLAUDE.md files (your organization's managed policy files are still loaded; v2.1.271 and later). The built-in Explore and Plan never read it in the first place
  • 🟡 The breakdown of how many tokens are read at launch has not been published officially. What I show here are totals from my environment

If you split small tasks across many subagents, this "cost of just starting" is added for each one. Handing work to a cheaper model makes this part cheaper too, not just the work itself.

Source: Claude Code documentation, How Claude Code uses prompt caching (per-model caches, subagents and caching, cache lifetime), Claude Platform Docs, Pricing (tokenizer, cache multipliers), Claude Code documentation, Create custom subagents (omitClaudeMd)

7. Measured (3): the same translation, twice on each of three models

I actually tried the idea from the opening, "move only the translation down a tier." I picked one section from the Japanese version of an article on this site (6,265 characters of HTML, including a table, stat cards and code snippets) and gave each model the job of translating it into English without changing the tag structure, twice each with identical instructions, six runs in total. Opus 5 and Sonnet 5 ran at high effort, inherited from the main session (Haiku 4.5 does not support effort).

ModelTime taken
(run 1 / run 2)
Tag countAll 49 numbersCost (input and cache)
Opus 546 s / 45 sMatched the source both timesAll present both times$0.46 / $0.46
Sonnet 539 s / 74 sMatched the source both timesAll present both times$0.23 / $0.25
Haiku 4.599 s / 94 sOne <strong> missing in run 1All present both times$0.10 / $0.10

Source: my own measurements (September 15, 2026. Cost is list price, computed from the token counts in the conversation logs multiplied by the official rates. Output is not included; see the note below)

The cost column leaves out output because the output token counts in the logs could not be trusted. In one case, a response that wrote out a translation of about 8,800 characters to a file was recorded as 18 output tokens. Output pricing per million tokens is $25 for Opus 5, $10 for Sonnet 5 and $5 for Haiku 4.5, and every English translation came to about 8,500 to 8,900 characters.

I checked translation quality myself, comparing each run sentence by sentence against the Japanese source.

  • None of the six runs had a mistranslation of meaning. Numbers, tables and internal links were all preserved correctly. That said, text heavy on numbers and bullet points is on the easy side to translate
  • The differences were in readability and consistency of wording. Haiku 4.5 mixed "my" and "the author's" for the first person in run 1, and in run 2 produced stiff word order such as "G from 9th rises to 6th." Sonnet 5 wrote natural English, but spelled "subagent" as "Sub-agent" in run 1 and "Subagent" in run 2, so its wording drifted between runs. Opus 5 kept its terminology consistent both times
  • The slowest was the cheapest, Haiku 4.5. Sonnet 5's two runs differed in time by nearly a factor of two. With so few runs, treat the speed ranking only as a rough guide

What this comparison does not tell you

  • This was one section, translated twice per model. The gap could widen with long articles, languages with very different word order, right-to-left languages such as Arabic, or text dense with technical terms
  • I did not measure the ability to notice errors in the source. On this site, an Opus subagent handling a translation has pointed out factual errors in the Japanese source (such as a wrong per-plan character limit). How much this kind of catch varies by model is outside the scope of this experiment

8. How it affects cost and usage limits

How much you gain by moving subagents to a cheaper model depends on whether you pay per use through the API or use a subscription such as Pro or Max.

Pay-as-you-go API: the price ratio applies directly

ModelInputOutput5-minute cache writeCache read
Claude Opus 5$5$25$6.25$0.50
Claude Sonnet 5$2$10$2.50$0.20
Claude Haiku 4.5$1$5$1.25$0.10

Source: Claude Platform Docs, Pricing (per million tokens, as of September 15, 2026. Sonnet 5's introductory price became its standard price)

Sonnet 5 costs two-fifths of Opus 5 per token, and Haiku 4.5 one-fifth. In the section 7 measurements, the input and cache cost for Sonnet 5 was about half of Opus 5, and for Haiku 4.5 about one-fifth. Haiku 4.5 lands close to the price ratio, while Sonnet 5 comes out higher than two-fifths, because the number of responses and the amount read per response differed by model (Sonnet 5 made 4 and 6 responses, Opus 5 made 4 both times; Haiku 4.5 also uses a different tokenizer).

Subscriptions: some limits don't come back when you switch models

On Pro and Max, the session limit and the weekly limit are shared across all models. Once you have used them up, switching models with /model will not let you continue. Separately, there are per-model-family limits such as an "Opus limit" and a "Sonnet limit", and only when you hit one of those can you keep going by switching to a model outside that family.

🟡 How much longer your plan limits last when subagents run on Sonnet or Haiku has not been published. The API price ratio gives a rough guide, but nothing says limits are consumed in that same proportion. To see which subagents use the most, check the plan breakdown in /usage (shares by skill, subagent, plugin and MCP server).

Source: Claude Code documentation, Error reference (You've hit your session limit: limits shared across all models and per-model-family limits), Manage costs effectively (the plan breakdown in /usage)

9. Which work to move to a cheaper model

As a rule of thumb, the official documentation says that "Sonnet handles most coding tasks well and costs less than Opus. Reserve Opus for complex architectural decisions or multi-step reasoning," and "For simple subagent tasks, specify model: haiku in your subagent configuration." It also recommends Sonnet for agent team members.

Building on that, here are three things to weigh, drawn from the section 7 measurements and how I run this site.

Easy to move down

Work whose results can be checked mechanically

Conversion into a fixed format, searching and reading files, high-volume routine checks. The missing <strong> in section 7 was also caught by counting tags mechanically.

Move down only with checks

Work where readability and consistent wording matter

Work like translation, where the meaning can be right while the wording drifts. You need safeguards such as putting a glossary in the instructions or adding a step that unifies wording afterward.

Better not to move down

Work that relies on judgment or noticing that something is off

Work where you want errors in the source or the design caught, or whose results are hard to check mechanically. This ability may differ between models, and this experiment did not measure it.

When in doubt, the reliable approach is to give just one of your usual tasks to the cheaper model and compare the result side by side with your current model's. It takes a one-line change to model in the definition file, and if it doesn't work out you can switch back right away. If what you want to split is the main session's model rather than a subagent's, using Opus only for planning and Sonnet for implementation, opusplan does that; see What Is Claude Code's opusplan?

FAQ

Q1. If I change the main session's /model mid-conversation, do subagents change too?
Subagents whose model is decided by the invocation, model in the definition file (other than inherit), or the environment variable do not change. Subagents with none of those, and subagents whose definition file says inherit, follow the main session's model. Note that switching the main session's model means the main session's cache has to be rebuilt.

Q2. Can I lower only the effort and keep the model?
Yes. Write something like effort: medium in the definition file, and that effort applies only while that subagent is running. However, if the CLAUDE_CODE_EFFORT_LEVEL environment variable is set, it takes precedence.

Q3. On Amazon Bedrock, which model does model: sonnet give me?
According to the official documentation as of September 15, 2026, Sonnet 4.5. On the Anthropic API it is Sonnet 5, so the same definition file gives different results depending on the provider. To pin a version, write the full model ID.

Q4. Is it better to set the subagent cache to 1 hour?
It depends on how you work. If you launch the same kind of subagent many times with gaps of more than 5 minutes, it cuts down on repeated writes. On the other hand, 1-hour cache writes cost twice the input price (5-minute writes cost 1.25 times), so if you only run subagents in short bursts, the 5-minute cache is cheaper. The settings for a 1-hour cache and their conditions are covered in section 6.

Q5. I specified a model, but it doesn't seem to be taking effect.
Check these in order: (1) whether CLAUDE_CODE_SUBAGENT_MODEL_FORCE is enabled (it makes Claude Code ignore what the definition file says), (2) whether you are on a version before v2.1.251 with the environment variable set, and (3) whether your organization's managed settings allow that model. To see which model it actually ran on, use /tasks while it is running, or message.model in the conversation logs after it finishes.

Sources