Saltar al contenido principal

Effort tuning: 5 levels, model defaults, and the cache trap

Intermedio

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.

What you'll learn
  • 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:

LevelWhat it doesWhen to reach for it
lowMost 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
mediumBalanced. Moderate token savings vs high.Agentic tasks that need speed + cost + quality in balance; cost-conscious step-down from high
highHigh capability. Equivalent to omitting the parameter.Complex reasoning, difficult coding, agentic tasks where quality matters more than speed
xhighExtended 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
maxAbsolute 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.

Pro tip
  • 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.

Pro tip

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.

Guided walkthrough1 of 6
  1. 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.

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.

Pro tip
  • 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-wide xhigh and grants standing permission for Claude Code to launch multi-agent workflows (via mid-conversation system messages). The API has no ultracode value — it's a CLI convenience that composes xhigh with 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

Pulsa Intro o Espacio para girar la tarjeta. Usa las flechas izquierda y derecha para moverte entre las tarjetas.Término mostrado.
1 / 8

Check yourself

0/6
  1. Which of these is NOT a valid effort value on the Messages API?
  2. You're running a cached 20-turn conversation. What happens if you flip effort from high to xhigh on turn 21?
  3. You're on Claude Code and want just the NEXT turn to reason harder without touching your session's effort setting. Best move?
  4. On Opus 4.8 at effort='xhigh', your responses keep truncating with stop_reason='max_tokens' after long thinking. Most likely fix?
  5. Where does effort go when creating a Claude Managed Agents agent (the July 2026 update)?
  6. Which change makes Sonnet 5 'medium' behave closest to Sonnet 4.6 at 'high'?

Sources & further reading