Overview
Extended thinking gives Claude an explicit, step-by-step reasoning pass before it writes its final answer. When you enable it, Claude emits thinking content blocks that contain its internal reasoning, then uses that reasoning to craft the response. It is most useful for problems where a single forward pass tends to be brittle: multi-step math and logic, complex code changes, careful analysis, and tasks where you would normally ask a person to "show their work."
There are two ways you typically interact with it:
- Through the API, where you turn on extended thinking by adding a
thinking object with a token budget to your request.
- Inside Claude Code, where you can nudge Claude to spend more reasoning effort using natural-language keywords like "think" and "ultrathink." This keyword tiering is a prompting convention, not a documented API parameter (more on that below).
This guide covers both, sticking to what the official docs actually specify.
Enabling extended thinking via the API
To turn on extended thinking, add a thinking block to your Messages API request. The block takes type: "enabled" and a budget_tokens value:
{
"model": "claude-sonnet-4-6",
"max_tokens": 16000,
"thinking": {
"type": "enabled",
"budget_tokens": 10000
},
"messages": [
{
"role": "user",
"content": "Your question here"
}
]
}
The two required fields:
type — set to "enabled" to activate extended thinking.
budget_tokens — the maximum number of tokens Claude may spend on internal reasoning. This is separate from, and must be less than, max_tokens. budget_tokens caps the thinking; max_tokens caps the whole response.
A few important consequences of that relationship:
- Claude does not always consume the entire budget. The docs note this especially at larger ranges (above ~32k), where the model may stop reasoning before hitting the cap.
- Because
budget_tokens must be below max_tokens, you cannot combine extended thinking with max_tokens: 0 (the prompt-caching pre-warming pattern).
- You are billed for the full thinking tokens generated, even when the response only shows summarized thinking. The billed output token count therefore will not match the visible token count in the response.
Not every model supports manual extended thinking. The newest models (for example claude-opus-4-8) instead use adaptive thinking (thinking: {"type": "adaptive"}), where the model decides on its own when and how much to think rather than taking a fixed budget_tokens. Check the current model support list in the docs before wiring a specific model to a budget_tokens value.
Streaming
Streaming is not required at any size threshold, but it is useful for long thinking passes so you can surface progress instead of waiting for the full response. When streaming is enabled, thinking text arrives via thinking_delta events:
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 10000},
messages=[...],
) as stream:
for event in stream:
if event.type == "content_block_delta":
if event.delta.type == "thinking_delta":
print(event.delta.thinking, end="", flush=True)
Passing thinking blocks back during tool use and multi-turn
This is the rule that most often trips people up. During tool use and multi-turn conversations, you must pass any thinking blocks back to the API unmodified, in their original order. Each thinking block carries a signature field (encrypted reasoning state); rearranging, editing, or dropping blocks in a turn that used them causes a validation error.
# First request
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 10000},
tools=[weather_tool],
messages=[{"role": "user", "content": "What's the weather in Paris?"}],
)
# Extract the thinking and tool_use blocks from the response
thinking_block = next((b for b in response.content if b.type == "thinking"), None)
tool_use_block = next((b for b in response.content if b.type == "tool_use"), None)
# Second request — the thinking block MUST be passed back with the tool result
continuation = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 10000},
tools=[weather_tool],
messages=[
{"role": "user", "content": "What's the weather in Paris?"},
{"role": "assistant", "content": [thinking_block, tool_use_block]},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": tool_use_block.id,
"content": "Current temperature: 88°F",
}
],
},
],
)
Two related tool-use constraints with thinking enabled: only tool_choice: {"type": "auto"} (the default) or tool_choice: {"type": "none"} are allowed — forcing a specific tool returns an error — and you cannot toggle thinking on or off partway through a tool-use loop.
Summarized vs. omitted thinking
On Claude 4 models the Messages API returns summarized thinking by default: a condensed version of the full reasoning. You still pay for the full thinking tokens; the summary is produced by a separate model. You can also set display: "omitted" so no thinking text comes over the wire (the signature still carries the encrypted reasoning needed for multi-turn continuity), which gives faster time-to-first-text in streaming pipelines that never surface reasoning to a user.
{
"thinking": {
"type": "enabled",
"budget_tokens": 10000,
"display": "omitted"
}
}
When to spend more thinking
Larger budgets can improve quality on genuinely hard problems by giving Claude room for more thorough analysis — but more thinking is not free (you pay for every thinking token) and it adds latency. The docs' guidance is to start with a reasonable value such as 10000 and adjust by problem complexity. Use the table below as a starting heuristic.
| Task profile |
Suggested approach |
Why |
| Simple lookups, formatting, short rewrites |
Leave thinking off |
A direct answer is faster and cheaper; reasoning adds little |
| Moderate reasoning: multi-step questions, small refactors |
Start near budget_tokens: 10000 |
The docs' recommended starting point; usually enough headroom |
| Hard problems: tricky math/logic, complex multi-file changes, deep analysis |
Raise the budget, then measure |
Bigger budgets help on complex work; verify the gain is real for your task |
| Very large budgets (above ~32k) |
Raise only if measurements justify it |
Claude often won't use the whole budget here, so extra budget may not pay off |
Always confirm budget_tokens stays below max_tokens, and treat budget tuning empirically: raise it only while quality keeps improving on your own evals.
The think / ultrathink convention in Claude Code
In Claude Code you don't set budget_tokens directly. Instead, people use natural-language cues in the prompt — "think", "think hard", "think harder", "ultrathink" — to signal that they want Claude to spend more effort reasoning before acting.
Important caveats, so you don't build on shaky assumptions:
- These keyword tiers are a community/prompting convention, not a documented API parameter. The official Claude Code best-practices page does not define them or publish their exact token budgets.
- Because the budgets are not published, treat the tiers as relative effort levels rather than precise numbers. Do not hard-code or quote specific token counts for them — any such figures circulating online are unofficial.
| Keyword cue |
Relative effort |
Good fit for |
| (no cue) |
Default |
Routine edits, questions, small fixes |
| "think" |
More than default |
Tasks that benefit from a brief planning pass |
| "think hard" / "think harder" |
Higher |
Trickier changes, ambiguous requirements |
| "ultrathink" |
Highest |
The hardest problems where you explicitly want maximum deliberation |
What the official Claude Code best-practices do recommend, and which pairs naturally with more reasoning:
- Explore, then plan, then code. Use plan mode to let Claude read the relevant files and produce an implementation plan before it edits anything, so it doesn't solve the wrong problem.
- Give Claude a way to verify its work. A test suite, a build, a linter, or a screenshot comparison closes the loop so Claude can iterate to a pass on its own instead of relying on "looks done."
- Provide specific context. Reference exact files with
@, name constraints, point to existing patterns, and describe the symptom and what "fixed" looks like.
- Add an adversarial review step. Have a fresh subagent review the diff against your plan and report gaps before you treat the task as done.
Reasoning effort is most worthwhile precisely where these practices say planning matters: multi-file changes, unfamiliar code, and tasks where the approach is uncertain.
Troubleshooting
- Validation error on a follow-up request. You almost certainly dropped, edited, or reordered a
thinking block from a previous turn. Pass thinking blocks back unmodified, in original order, including their signature.
- Forced tool choice fails with thinking on. Only
auto or none tool choice is supported with extended thinking. Remove the forced tool / any choice, or disable thinking for that call.
- Billed token count doesn't match what you see. Expected with summarized thinking — you are billed for the full thinking tokens, not the visible summary.
max_tokens: 0 rejected with thinking enabled. budget_tokens must be below max_tokens, so the cache pre-warming pattern can't be combined with extended thinking.
- Your model rejects
budget_tokens. The newest models use adaptive thinking (type: "adaptive") instead of a manual budget. Confirm your model is on the manual-thinking support list.
References