Effort tuning: 5 levels, model defaults, and the cache trap
On 22 July 2026 Anthropic rolled effort into Claude Managed Agents' model configuration, closing the loop on a control the Messages API has quietly grown to five levels. If you're still copying effort="high" at the top level of messages.create from an early-2026 blog post, your request looks valid but Claude may not be honoring the field you think it is — the parameter lives inside output_config now, and the API only enforces the levels documented on the model's card.
This is the practical tuning guide: where effort actually goes in a request, what the five levels really do (they change tool-call count, not just thinking depth), the per-model defaults that will surprise you, and the one gotcha that quietly blows up spend — changing effort mid-conversation invalidates prompt cache.
- Place the effort field correctly — inside output_config on the Messages API, in the model object on Managed Agents, via /effort or CLAUDE_CODE_EFFORT_LEVEL in Claude Code
- Pick a starting level per model — high is the API default but the recommended starting effort varies by model (Sonnet 5 high, Sonnet 4.6 medium, Opus 4.7/4.8 xhigh, Fable 5 high)
- Understand that effort affects ALL tokens — text, tool calls, and (when active) thinking — so lowering effort reduces tool-call count, not just verbosity
- Avoid the cache trap — varying effort inside one conversation invalidates prompt caching and can double your bill silently
- Know the Claude Code effort surface — /effort, ultrathink (one-turn), ultracode (xhigh + standing multiagent permission), CLAUDE_CODE_EFFORT_LEVEL env override
The five levels (and where "ultracode" fits)
The effort scale as of 22 July 2026 has five values that the API accepts:
| Level | What it does | When to reach for it |
|---|---|---|
low | Most efficient. Significant token savings with some capability reduction. Fewer tool calls, terse confirmations, no preamble. | Simple classification, high-volume workloads, chat, latency-sensitive UX, subagents doing scoped work |
medium | Balanced. Moderate token savings vs high. | Agentic tasks that need speed + cost + quality in balance; cost-conscious step-down from high |
high | High capability. Equivalent to omitting the parameter. | Complex reasoning, difficult coding, agentic tasks where quality matters more than speed |
xhigh | Extended capability for long-horizon work. Expect meaningfully higher token usage than high. | Long-running (30+ min) agentic and coding tasks, token budgets in the millions, deep multi-file refactors |
max | Absolute maximum capability, no constraint on token spend. | Genuine frontier problems only. Can overthink on structured-output tasks. |
max is universal across the models that support effort. xhigh is newer and only supported on Fable 5, Mythos 5, Opus 4.8, Opus 4.7, and Sonnet 5. Older effort-capable models (Sonnet 4.6, Opus 4.6, Opus 4.5) understand max but not xhigh.
- Setting effort='high' produces exactly the same behavior as omitting the parameter — don't set it 'just to be explicit' in a cached conversation, because writing the field on some requests and not others invalidates the cache.
- 'ultracode' is not a sixth level. It is xhigh + a standing permission for Claude Code to launch multiagent workflows, granted through mid-conversation system messages. The API accepts five values.
The field structure most blog posts get wrong
Early-2026 write-ups of the effort parameter show a top-level field:
# WRONG on current models — silently ignored or 400
client.messages.create(
model="claude-opus-4-8",
effort="medium",
...
)
The current API places effort inside an output_config object, and passes it as a sibling of messages/model:
Correct effort placement — Messages API
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=4096,
output_config={"effort": "medium"},
messages=[{
"role": "user",
"content": "Analyse the trade-offs between microservices and monoliths."
}],
)
print(response.content[0].text)On Claude Managed Agents (the 22 July 2026 change), effort goes inside the agent's model object at creation time. The session doesn't set it — the agent version does.
Correct effort placement — Managed Agents (POST /v1/agents)
# Effort travels with the versioned agent config,
# not the per-run session. Every session pinned to
# this agent version runs at xhigh.
POST https://api.anthropic.com/v1/agents
{
"name": "code-reviewer",
"model": {
"id": "claude-opus-4-8",
"effort": "xhigh"
},
"system_prompt": "You review pull requests for security issues.",
"tools": [...],
"mcp_servers": [...]
}Effort is not a thinking control
This is the second big misconception. Effort works whether or not thinking is enabled, and it changes tokens Claude spends on parts of the response that aren't thinking:
- Tool calls. Lower effort → fewer tool calls. Claude combines operations into single calls, skips optional exploration, and proceeds to action without preamble.
- Text length. Lower effort → tighter output. Terse confirmations after tool calls rather than detailed summaries. Fewer code comments.
- Thinking depth (when thinking is on). Lower effort → skips thinking on easy prompts entirely; still thinks on genuinely hard ones, just less.
That last point matters: at low effort Claude will still think on a proof problem, because the task demands it. Effort is a behavioral signal, not a strict token budget. Don't expect a hard cap.
The thinking parameter and the effort parameter answer different questions. thinking decides whether Claude produces thinking blocks at all. effort decides how much work goes into the whole response — including how often and how deeply Claude thinks when adaptive thinking is on. Passing effort="adaptive" is a common mistake; adaptive is a thinking mode, not an effort level.
On Opus 4.5 — the only extended-thinking-only model that supports effort — you set effort and budget_tokens together. Pick the effort level for your task, then size the thinking token budget for the reasoning depth. Every other effort-capable model uses adaptive thinking and doesn't take budget_tokens.
Per-model starting points that surprise teams
The API default is high on every model that supports the parameter. But Anthropic's recommended starting effort varies by model, and the mismatch is where teams over- or under-spend.
- Sonnet 5 defaults to high on both the API and Claude Code, and the recommendation matches. Step up to xhigh only for the hardest coding and agentic tasks. Step down to medium as a cost-saving move — Sonnet 5 medium is comparable to Sonnet 4.6 at high. Use low for chat and non-coding, latency-sensitive workloads.
- Sonnet 4.6 defaults to high but Anthropic's own guidance recommends medium as the balanced default for most applications, including agentic coding. Explicitly set effort='medium' — otherwise you inherit high and pay for latency you didn't ask for.
- The default is high but the recommendation for coding and agentic work is xhigh. Use high as the minimum for intelligence-sensitive workloads. Step to medium only when your evals show quality holds. Reserve max for genuinely frontier problems — on most workloads max adds significant cost for small quality gains, and on structured-output tasks it can overthink.
- Opus 4.7 (and 4.8) scope work more tightly at low/medium than Opus 4.6 did. If you observe shallow reasoning on a complex prompt at low, raise effort rather than prompting around it. If latency forces you to stay at low, add a targeted line like 'This task involves multistep reasoning. Think carefully before responding.'
- Effort is the primary intelligence/latency/cost lever on Fable 5. Start at high (the default), use xhigh for the most capability-sensitive work, and drop to medium or low for routine tasks — lower levels on Fable 5 still exceed prior models at xhigh. Set a large max_tokens at high/xhigh since it caps thinking plus response text combined.
- Both models can spend heavily across subagents and tool calls at xhigh/max. Anthropic recommends starting max_tokens at 64k and tuning from there. Leave it at 4096 and you'll get a truncated response with stop_reason='max_tokens' after a promising start.
The cache trap — the one that silently doubles your bill
Prompt caching gives you cache reads at roughly 10% of standard input price. Changing effort between requests in the same conversation invalidates the cache, exactly like switching models does. On a long context, that's the difference between a $0.03 cache read and a $0.30 full-price re-read of your entire history — on every single follow-up turn.
- Vary effort ACROSS workloads, not WITHIN a cached conversation. Pick the level at conversation start; keep it constant until you /clear.
- In Claude Code, /effort mid-session is the equivalent of switching models — expect a big cache miss on the next turn.
- If you need to escalate depth for one turn only, use 'ultrathink' in Claude Code (a one-turn deeper-reasoning bump) rather than /effort xhigh — it avoids changing session config.
- If you must escalate for the rest of the session, do it early. A switch at turn 3 is cheap; a switch at turn 30 re-reads 30 turns of context at full price.
The corollary: setting effort="high" explicitly on some cached requests and omitting it on others invalidates cache the same way — since the two are behaviorally equivalent but textually different. Pick one convention (always set, or always omit) and hold it.
Claude Code — the CLI surface
Claude Code exposes effort as an interactive command, a launch flag, and an environment variable (highest priority wins in that reverse order):
# In-session (interactive slider, or direct)
/effort
/effort xhigh
/effort auto # reset to model default
# At launch
claude --effort low
# Environment (overrides everything else)
CLAUDE_CODE_EFFORT_LEVEL=high claude
Two related commands are worth knowing because they're not effort levels but they behave adjacent to them:
ultrathink— a one-turn deeper reasoning bump that does not change session effort. Use it when you want the next turn to think harder without invalidating cache on all subsequent turns.ultracode— sets session-widexhighand grants standing permission for Claude Code to launch multi-agent workflows (via mid-conversation system messages). The API has noultracodevalue — it's a CLI convenience that composesxhighwith an orchestration permission.
Persistence rules to remember: low, medium, high, and xhigh persist across Claude Code sessions once you set them. max applies to the current session only — you have to reapply it next time.
A tuning walkthrough — one prompt, three efforts
To calibrate intuition, run the same prompt at three levels and compare the output shape:
Tuning-calibration prompt (run at low, high, xhigh)
Task: Review this pull request for security issues. <pr_diff> [paste a real diff — 300+ lines, multi-file, at least one auth-touching change] </pr_diff> Report: severity-tagged findings + a one-line fix per finding. Do not restate what the diff does.
Expect roughly:
- low — catches the obvious high-severity issues (SQL string concatenation, unchecked user input in a header). Misses subtle logic bugs. 1-2 tool calls if tools are available. Short output. Fast.
- high — full analysis. Catches most vulnerabilities including subtle ones. Multiple targeted tool calls to read related files. Structured findings. This is where most teams stop.
- xhigh — exhaustive. Considers novel attack vectors and defence-in-depth. Reads adjacent files that low/high didn't touch. Many more tool calls. Meaningfully higher token usage.
If your evals show high and xhigh produce the same findings on your codebase, ship at high. Xhigh's value shows up specifically when the task benefits from repeated tool calls and detailed exploration — which is exactly when Anthropic recommends it.
Sonnet 5 shifted the calibration — don't port levels blindly
If you were running Sonnet 4.6 at high and migrated to Sonnet 5, keeping the same level makes Sonnet 5 spend closer to what Sonnet 4.6 spent at max — Sonnet 5's effort scale is shifted. Anthropic's own guidance: Sonnet 5 medium ≈ Sonnet 4.6 high. That's a per-request-cost swing worth checking if you replayed traffic without adjusting effort. See the Sonnet 5 field guide for the full migration story.
Lock it in
Check yourself
0/6Sources & further reading
- Anthropic — Effort (build-with-claude/effort) — authoritative reference for the five levels,
output_config.effort, and per-model recommendations - Anthropic — Thinking (build-with-claude/thinking) — how effort interacts with adaptive thinking and when to reach for which control
- Anthropic Platform release notes — 22 July 2026 entry — the Managed Agents
effortrollout and the webhook / session-seeding changes shipped the same day - Prompting Claude Sonnet 5 — calibrating effort and thinking depth — the Sonnet 5 effort scale shift and when to reach for xhigh
- Anthropic — Task budgets — advisory token budgets for full agentic loops, a complement to effort for long runs
- AILmanac — Extended Thinking & Effort — the introductory framing this page assumes
- AILmanac — Claude Sonnet 5: The Field Guide — the migration and re-calibration story
- AILmanac — Prompt caching — the cache economics that make the mid-conversation effort change so expensive