Thinking
Understand how Claude's thinking works: turn it on, read thinking output, steer thinking depth with effort, and use thinking with tools, caching, and streaming.
A model that answers in a single pass has to get everything right on the first try: no scratch work, no checking, no changing course halfway through. For a proof, a tricky bug, or a long agentic task, the first approach is often not the best one.
Thinking removes that constraint. When thinking is active, Claude works through the problem in its own words before answering: it restates what is being asked, tries approaches, checks intermediate results, and abandons paths that do not hold up. That reasoning arrives in thinking content blocks ahead of the response, and Claude draws on it to produce the final answer. This is why thinking improves performance on complex tasks like math, coding, analysis, and long-running agentic work, where the quality of the answer depends on intermediate work that would otherwise be compressed into the response itself or skipped.
Thinking has a cost: the tokens Claude spends reasoning are billed as output tokens, even when the thinking text isn't returned to you, and they count toward max_tokens alongside the response text. This page covers how thinking behaves across the API surface: turning it on, reading its output, and managing its interactions with tools, streaming, caching, and the context window.
How thinking works
Whether Claude thinks on a given request, and how deeply, depends on your thinking configuration and the complexity of the request.
Here is what thinking looks like in a response: one or more thinking content blocks arrive before the text blocks. The thinking block is still generated content, like the text block that follows it, but it is separated from the canonical response. Each thinking block also carries a signature field, an encrypted copy of the full reasoning that you pass back unchanged in multi-turn and tool-use conversations (see Thinking encryption):
{
"content": [
{
"type": "thinking",
"thinking": "Let me break this down. The question has two parts, so I'll start with the simpler one and use its result to constrain the second...",
"signature": "WaUjzkypQ2mUEVM36O2Txu...."
},
{
"type": "text",
"text": "Based on my analysis..."
}
]
}You don't always see this text, and what you see is never the raw chain of thought: the text in a thinking block is a summary of Claude's reasoning. The display field on the thinking configuration controls whether that summary is returned at all: "summarized" returns it, while "omitted", the default on many models, returns thinking blocks with an empty thinking field. Either way the block is billed the same and passed back the same in multi-turn conversations. See Controlling thinking display for per-model defaults and details.
If Claude uses tools, thinking can also appear between tool calls. See Thinking with tool use. For the full response format, see the Messages API reference.
Configuring thinking
On most models, thinking is on by default or one parameter away. Which configuration each model accepts, and what it defaults to, is listed in the per-model configuration table on the Troubleshooting page.
On Claude Opus 5, Claude Sonnet 5, Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, and Claude Mythos Preview, thinking is already on and needs no configuration. display defaults to "omitted" on these models, so the thinking text is hidden until you opt in. Opt in with thinking: {"type": "adaptive", "display": "summarized"}, which is exactly the following request with the model string swapped.
On Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, and Claude Sonnet 4.6, thinking is off until you set thinking: {type: "adaptive"}, which lets Claude decide when and how deeply to think based on the request. The following examples do that, set display: "summarized" so the thinking text is visible, and use a roomy max_tokens:
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=16000,
thinking={"type": "adaptive", "display": "summarized"},
messages=[
{
"role": "user",
"content": "What is the greatest common divisor of 1071 and 462?",
}
],
)
for block in response.content:
if block.type == "thinking":
print(f"\nThinking: {block.thinking}")
elif block.type == "text":
print(f"\nResponse: {block.text}")Running the example prints the summarized thinking, then the answer:
Thinking: Use Euclidean algorithm.
1071 = 2*462 + 147
462 = 3*147 + 21
147 = 7*21 + 0
GCD = 21
Response: ## Finding GCD of 1071 and 462
I'll use the **Euclidean algorithm**, repeatedly dividing and taking remainders...Thinking tokens count toward max_tokens, so set it high enough to leave room for both the thinking and the response text. See Cost control on the steering page and Thinking and the context window.
Turning thinking off
On Claude Sonnet 5, where thinking is on by default, you can turn it off:
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=4096,
thinking={"type": "disabled"},
messages=[{"role": "user", "content": "Summarize this article in one sentence."}],
)Claude Opus 5 also has thinking on by default and accepts thinking: {type: "disabled"} at effort high or below. At xhigh or max effort, thinking cannot be turned off: requests that combine thinking: {type: "disabled"} with those effort levels return a 400 error. This restriction applies to Claude Opus 5 and later models and is enforced on each request. With thinking disabled, Claude Opus 5 can occasionally emit tool calls as plain text or include internal XML tags in its visible output. See Running with thinking disabled for prompting mitigations.
Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, and Claude Mythos Preview reject thinking: {type: "disabled"}. Thinking can't be turned off on these models.
If your model supports only extended thinking (see the per-model configuration table), configure it with type: "enabled" and a budget_tokens value instead. The Extended thinking page covers that configuration. And if any thinking configuration comes back with a 400 error, Troubleshooting thinking matches each error message to its fix.
Reading thinking output
Controlling thinking display
The display field on the thinking configuration controls how thinking content is returned in API responses. display works in both modes: set it alongside type: "adaptive" or type: "enabled". It accepts these values:
"summarized": thinking blocks contain summarized thinking text, a readable summary of Claude's reasoning. This is the default on Claude Opus 4.6, Claude Sonnet 4.6, and earlier models."omitted": thinking blocks are returned with an emptythinkingfield. Thesignaturefield still carries the encrypted full thinking for multi-turn continuity (see Thinking encryption). This is the default on Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, Claude Opus 5, Claude Sonnet 5, Claude Opus 4.8, Claude Opus 4.7, and Claude Mythos Preview."updates"(beta): reasoning blocks are returned with an emptythinkingfield, as with"omitted", and the short progress updates some models write between tool calls come back as readable text. Requires the beta headerthinking-display-updates-2026-08-18.
Set display: "omitted" when your application doesn't surface thinking content to users. The primary benefit is faster time-to-first-text-token when streaming: the server skips streaming thinking tokens entirely and delivers only the signature, so the final text response begins streaming sooner.
With display: "omitted", the response contains thinking blocks with an empty thinking field:
{
"content": [
{
"type": "thinking",
"thinking": "",
"signature": "EosnCkYICxIMMb3LzNrMu..."
},
{
"type": "text",
"text": "The answer is 12,231."
}
]
}Keep the following in mind when working with omitted thinking:
- You're still charged for the full thinking tokens. Omitting reduces latency, not cost.
- If you pass thinking blocks back in multi-turn conversations, pass them unchanged. The server decrypts the
signatureto reconstruct the original thinking for prompt construction (see Preserving thinking blocks). Any text you place in thethinkingfield of a round-tripped omitted block is ignored. displayis invalid withthinking.type: "disabled"(there is nothing to display).- When using
thinking.type: "adaptive"and the model skips thinking for a simple request, no thinking block is produced regardless ofdisplay. - When streaming with
display: "omitted", nothinking_deltaevents are emitted. Withdisplay: "updates", only progress-update blocks streamthinking_deltaevents. See Streaming thinking for the event sequence.
In the Ruby SDK, plain hashes take display: as the examples show. The typed ThinkingConfigAdaptive class names the parameter display_ (trailing underscore, to avoid shadowing Ruby's Kernel#display). Either way, the wire field is still display.
Summarized thinking
When display is "summarized", the thinking text you receive is a summary of Claude's full thinking process rather than the raw chain of thought. Summarized thinking provides the full intelligence benefits of thinking while preventing misuse. No display setting returns the raw chain of thought.
Keep the following in mind when working with summarized thinking:
- You're charged for the full thinking tokens generated by the original request, not the summary tokens. The billed output token count does not match the count of tokens you see in the response.
- On Claude Opus 4.6, Claude Sonnet 4.6, and earlier models, the first few lines of thinking output are more verbose, providing detailed reasoning that's particularly helpful for prompt engineering purposes. Claude Mythos Preview summarizes from the first token, so its thinking blocks do not show this verbose preamble.
- Summarization preserves the key ideas of Claude's thinking process with minimal added latency, so summaries can stream as they arrive.
- Summarization is processed by a different model from the one you target in your requests. The thinking model does not see the summarized output.
- As Anthropic seeks to improve the thinking feature, summarization behavior is subject to change.
To see the model's reasoning, read the thinking blocks rather than prompting for reasoning in the response text. On Claude Fable 5.1 and Claude Fable 5, a request that attempts to elicit the model's internal reasoning as part of the response text can be refused with stop_details.category: "reasoning_extraction". See Refusal categories for the field reference and handling guidance.
Streaming thinking
Thinking works with streaming. Thinking blocks stream as thinking_delta events inside content_block_delta events, followed by a single signature_delta event just before the block's content_block_stop. Text blocks stream afterward as usual.
The following examples stream a response with adaptive thinking, printing thinking and text deltas as they arrive:
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-opus-4-8",
max_tokens=16000,
thinking={"type": "adaptive", "display": "summarized"},
messages=[
{
"role": "user",
"content": "What is the greatest common divisor of 1071 and 462?",
}
],
) as stream:
for event in stream:
if event.type == "content_block_start":
print(f"\nStarting {event.content_block.type} block...")
elif event.type == "content_block_delta":
if event.delta.type == "thinking_delta":
print(event.delta.thinking, end="", flush=True)
elif event.delta.type == "text_delta":
print(event.delta.text, end="", flush=True)To reassemble complete thinking blocks with their signatures after streaming, use your SDK's message-accumulation helper where one exists (for example, stream.get_final_message() in Python or stream.finalMessage() in TypeScript) instead of concatenating deltas yourself.
event: message_start
data: {"type": "message_start", "message": {"id": "msg_01...", "type": "message", "role": "assistant", "content": [], "model": "claude-opus-4-8", "stop_reason": null, "stop_sequence": null}}
event: content_block_start
data: {"type": "content_block_start", "index": 0, "content_block": {"type": "thinking", "thinking": "", "signature": ""}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "I need to find the GCD of 1071 and 462 using the Euclidean algorithm.\n\n1071 = 2 × 462 + 147"}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\n462 = 3 × 147 + 21\n147 = 7 × 21 + 0\n\nSo GCD(1071, 462) = 21"}}
// Additional thinking deltas...
event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "signature_delta", "signature": "EqQBCgIYAhIM1gbcDa9GJwZA2b..."}}
event: content_block_stop
data: {"type": "content_block_stop", "index": 0}
event: content_block_start
data: {"type": "content_block_start", "index": 1, "content_block": {"type": "text", "text": ""}}
event: content_block_delta
data: {"type": "content_block_delta", "index": 1, "delta": {"type": "text_delta", "text": "The greatest common divisor of 1071 and 462 is **21**."}}
// Additional text deltas...
event: content_block_stop
data: {"type": "content_block_stop", "index": 1}
event: message_delta
data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence": null}}
event: message_stop
data: {"type": "message_stop"}When display: "omitted" is set, the thinking block opens, a single signature_delta arrives, and the block closes without any thinking_delta events. Text streaming begins immediately after:
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":"","signature":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"signature_delta","signature":"EosnCkYICxIMMb3LzNrMu..."}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"text","text":""}}With display: "updates" (beta), reasoning blocks stream as they do under "omitted". Each progress-update block streams its text as thinking_delta events before the tool_use block it introduces. A pause of several seconds before the progress-update block opens is normal:
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"thinking","thinking":"","signature":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"thinking_delta","thinking":"Confirmed the retry path never refreshes the expired token. Editing auth.py to add the refresh call."}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"signature_delta","signature":"Es8CCkYICxIM..."}}
event: content_block_stop
data: {"type":"content_block_stop","index":1}
event: content_block_start
data: {"type":"content_block_start","index":2,"content_block":{"type":"tool_use","id":"toolu_01D7FLrfh4GYq7yT1ULFeyMV","name":"edit_file","input":{}}}Under "updates", treat a block as a progress update as soon as one of its thinking_delta events carries non-empty text.
For general streaming mechanics, see Streaming Messages.
Thinking and effort
The thinking parameter controls whether Claude thinks in thinking blocks before answering; the effort parameter controls how much work Claude puts into the whole response, which in adaptive mode includes how often and how deeply it thinks. Don't pass adaptive as an effort value: adaptive is a thinking mode, not an effort level.
To learn what each effort level does to thinking behavior, see the per-level thinking behavior table on the Steering thinking page. The Effort page documents the parameter itself, including which levels each model supports. On Claude Opus 4.5, the only extended-thinking-only model that supports effort, effort composes with budget_tokens. See Budget rules and tuning.
With the two controls separated this way, pick the one that matches your goal:
- Lower cost or latency on a thinking-enabled workload: lower
effortfirst. It scales the whole response down, thinking included. - Claude is thinking too rarely or too shallowly: raise
effort, or see Steering how often Claude thinks on the steering page. - You need thinking fully off: use
thinking: {type: "disabled"}on models that allow it (see the per-model configuration table). - You need a hard ceiling on spend: use
max_tokens. Effort is soft guidance.max_tokensis a strict limit.
Thinking with tool use
Thinking works alongside tool use, letting Claude reason through tool selection and process tool results. Two constraints apply:
- Tool choice limitation (manual mode): tool use with manual extended thinking (
thinking: {type: "enabled"}) only supportstool_choice: {"type": "auto"}(the default) ortool_choice: {"type": "none"}. Usingtool_choice: {"type": "any"}ortool_choice: {"type": "tool", "name": "..."}results in an error because these options force tool use, which is incompatible with manual extended thinking. Adaptive thinking, including on models where thinking is on by default, supports forced tool use, except on Claude Fable 5.1 and Claude Mythos 5.1 (see Response prefill and forced tool use). - Preserving thinking blocks: when you return tool results, you must pass the thinking blocks from the assistant message back to the API, complete and unmodified. See Preserving thinking blocks.
A tool-use loop is one assistant turn. From the model's perspective, an assistant turn doesn't complete until Claude finishes its full response, which may include multiple tool calls and results. This whole sequence is a single assistant turn:
User: "What's the weather in Paris?"
Assistant: [thinking] + [tool_use: get_weather]
User: [tool_result: "20°C, sunny"]
Assistant: [text: "The weather in Paris is 20°C and sunny"]The entire turn runs in a single thinking mode: you can't toggle thinking in the middle of a turn, including during the tool-use loop. In extended (manual) mode, the API additionally enforces that the final assistant turn of a thinking-enabled request begins with a thinking block. Adaptive mode relaxes this: no assistant turn needs to start with one.
Mid-turn conflicts degrade gracefully. If you toggle thinking mid-turn (for example, between sending a tool call and returning its result), the API doesn't error. Instead, it silently disables thinking for that request. To preserve model quality, the API may strip thinking blocks that would create an invalid turn structure, or disable thinking when the conversation history is incompatible with thinking being enabled. To confirm whether thinking was active, check for the presence of thinking blocks in the response.
Toggle between turns, not within them. Plan your thinking strategy at the start of each turn. Complete the assistant turn, then change the thinking configuration for the next one:
User: "What's the weather?"
Assistant: [tool_use] (thinking disabled)
User: [tool_result]
Assistant: [text: "It's sunny"]
User: "What about tomorrow?"
Assistant: [thinking] + [text: "..."] (thinking enabled - new turn)Toggling thinking modes also invalidates prompt caching. See Thinking and prompt caching.
Preserving thinking blocks
When Claude invokes a tool, it pauses construction of its response to await external information. When you return the tool result, Claude continues building that same response, so its earlier reasoning must still be present. Pass every thinking block back to the API complete and unmodified, alongside the tool_use block it accompanied. This matters for two reasons:
- Reasoning continuity: the thinking blocks capture the step-by-step reasoning that led to the tool requests. Including them lets Claude continue reasoning from where it left off.
- Context maintenance: tool results appear as user messages in the API structure, but they're part of one continuous reasoning flow. Preserving thinking blocks maintains that flow across API calls.
In short:
- Required: within a tool-use turn, pass thinking blocks back.
- Recommended: across turns, pass everything back.
- Allowed: outside tool use, omit prior turns' thinking.
You don't need to prune old thinking yourself. Pass all thinking blocks back in multi-turn conversations, and the API automatically filters them, keeps the blocks needed to preserve the model's reasoning, and bills input tokens only for the blocks actually shown to Claude. Which prior-turn blocks are kept is per-model. See Thinking block preservation by model. To override the default, use the clear_thinking_20251015 context-editing strategy.
Within the latest assistant message, the sequence of consecutive thinking blocks must match what the model generated in the original request: you can't rearrange, edit, or partially drop them. This includes redacted_thinking blocks.
For a complete two-turn walkthrough with code in every SDK, see Thinking in tool and multi-turn workflows. It defines a tool, receives a thinking-plus-tool-use response, and echoes the assistant turn back with the tool result.
Interleaved thinking
Interleaved thinking lets Claude think between tool calls, reasoning about each tool result before acting on it. With interleaved thinking, Claude can:
- Reason about the results of a tool call before deciding what to do next
- Chain multiple tool calls with reasoning steps in between
- Make more nuanced decisions based on intermediate results
With adaptive thinking, interleaved thinking is automatic on every model that supports adaptive thinking. No beta header is needed. On Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, Claude Mythos Preview, Claude Opus 5, Claude Opus 4.8, and Claude Opus 4.7, reasoning between tool calls always appears in thinking blocks. Claude Haiku 4.5 does not support interleaved thinking. On models using manual extended thinking, interleaving requires a beta header and changes how the thinking budget is counted. Interleaved thinking in manual mode covers the per-model rules and platform-specific header behavior.
With interleaved thinking, the thinking allocation can span the entire assistant turn rather than a single response. Interleaved thinking is only supported for tools used through the Messages API.
For a worked comparison showing what interleaved thinking changes in a two-tool workflow, see How interleaved thinking changes the flow.
Progress updates between tool calls
On Claude Fable 5.1, Claude Mythos 5.1, and Claude Fable 5, the model can write a progress update between tool calls. A progress update is a sentence or two on what the model just found and what it's about to do next, written for the person watching the agent rather than as reasoning. Each one comes back as its own thinking block with its own signature, separate from any reasoning block at the same point. It sits immediately before the tool_use or server_tool_use block it introduces. At most one progress update precedes each tool call, and the model can skip any of them. Progress updates aren't interleaved thinking: they appear whether or not reasoning blocks appear between tool calls, and a response can contain both.
What a progress-update block contains depends on display:
display | Reasoning blocks | Progress-update blocks |
|---|---|---|
"omitted" (the default on these models) | Empty thinking field | Empty thinking field |
"updates" (beta) | Empty thinking field | Summary text |
"summarized" | Summary text | Summary text, not distinguishable from a reasoning block |
Use display: "updates" for an agent interface that keeps reasoning hidden and shows the user a status line at each step. Under it, any thinking block with non-empty text is a progress update, so render those and nothing else. It's in beta and requires the beta header thinking-display-updates-2026-08-18 (on Amazon Bedrock, Google Cloud, and Microsoft Foundry, pass the beta value as described in Beta headers). Without it, the value is rejected with the same 400 invalid_request_error as an unknown display value.
{
"model": "claude-fable-5-1",
"max_tokens": 16000,
"thinking": { "type": "adaptive", "display": "updates" },
"tools": [
{
"name": "edit_file",
"description": "Replace the contents of a file in the repository.",
"input_schema": {
"type": "object",
"properties": {
"path": { "type": "string" },
"content": { "type": "string" }
},
"required": ["path", "content"]
}
}
],
"messages": [
{
"role": "user",
"content": "The login test fails after an hour of uptime. Find out why and fix it."
}
]
}Under "updates", the start of the response that follows a tool_result looks like this. The first block is reasoning and stays empty, as it would under "omitted". The second carries text, so it's a progress update. Under "summarized" both blocks carry text, and under "omitted" both are empty.
{
"content": [
{
"type": "thinking",
"thinking": "",
"signature": "EqMBCkYICxIM..."
},
{
"type": "thinking",
"thinking": "Confirmed the retry path never refreshes the expired token. Editing auth.py to add the refresh call.",
"signature": "Es8CCkYICxIM..."
},
{
"type": "tool_use",
"id": "toolu_01D7FLrfh4GYq7yT1ULFeyMV",
"name": "edit_file",
"input": { "path": "auth.py", "content": "..." }
}
]
}Keep the following in mind when working with progress updates:
- Pass progress-update blocks back unchanged with the rest of the assistant turn, like any other
thinkingblock. - The text you receive is a summary of the progress update, normally a sentence or two. Don't rely on its length. The progress update counts toward
usage.output_tokensat its full length, not the summary's. - A progress-update block can come back with an empty
thinkingfield under anydisplayvalue. Render nothing for an empty block. Under"updates"it looks the same as an empty reasoning block and needs no separate handling. - When a response stops on
max_tokens,model_context_window_exceeded, orstop_sequencesoon after a tool call or tool result, its last block can be a progress-update block standing in for the work the model hadn't finished. Under"updates"and"summarized"its text is exactlyThis part of the response was interrupted before it finished.and you can show it like any other update. Under"omitted"it's empty. To continue, pass the assistant turn back unchanged and append a newusermessage (with atool_resultfor eachtool_useblock in that turn). - When streaming, expect a pause of several seconds before a progress-update block opens. See the
"updates"trace in Streaming thinking. - These models write fewer progress updates at higher effort and in long tool chains. If your interface depends on them, see Ask for user-facing progress updates.
Thinking block preservation by model
Whether thinking blocks from previous assistant turns stay in context by default depends on the model:
- Keep all prior turns: Claude Opus 4.5 and later Opus models, Claude Sonnet 4.6 and later Sonnet models, Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, and Claude Mythos Preview.
- Keep the last turn only: earlier Opus and Sonnet models, and all Haiku models through Claude Haiku 4.5. When you pass older thinking blocks back, the API strips them automatically. You don't need to remove them yourself.
Preservation brings two benefits:
- Cache optimization: preserved thinking blocks enable cache hits during tool use, as they are passed back with tool results and cached incrementally across the assistant turn, resulting in token savings in multistep workflows.
- No intelligence impact: preserving thinking blocks has no negative effect on model performance.
The tradeoff is context usage: long conversations consume more context space on keep-all models, because retained thinking blocks count as input like any other conversation history (see Thinking and the context window). The behavior is automatic in both regimes. No code changes or beta headers are required, and you should keep passing complete, unmodified thinking blocks back as described in Preserving thinking blocks. To override the default in either direction, use thinking block clearing.
Switching models mid-conversation. Keep passing thinking blocks back unchanged when you switch models, for example after a classifier refusal fallback. A thinking block is readable only by the model that produced it or a newer one, and the API ignores or drops the blocks the target model can't read. On Claude Fable 5.1 and Claude Mythos 5.1 the direction matters: they read every earlier model's thinking blocks and no earlier model reads theirs, so switching up to them keeps the conversation's reasoning and switching down drops it (see Preserved thinking for the exact list and for how dropped blocks are billed and reported). Strip prior thinking and redacted_thinking blocks yourself only to save input tokens on models that ignore rather than drop them, and never when redeeming a fallback credit, which requires the body unchanged.
Preserved thinking
Preserved thinking decides whether the model can use a thinking block that you send back from an earlier turn. Starting with Claude Fable 5.1, the API checks the signature of every thinking or redacted_thinking block in a request for two things:
- The model that produced it. A model reads its own thinking blocks and those of earlier models, never those of a newer model. Claude Fable 5.1 reads blocks from Claude Opus 5, but Claude Opus 5 can't read blocks from Claude Fable 5.1. The API drops a block the current model can't read, without an error and without billing it. See Switching models mid-conversation.
- Everything sent before it. A block stays valid only while the top-level
systemprompt, thetools, and the messages before it are unchanged. If any of them changes, that block and every later thinking block are invalid, and the API rejects the request with a 400 error or drops the invalid blocks, whichever you choose. See Keeping the prefix unchanged.
The model check applies to every account. The API enforces the prefix check by default for accounts created on or after August 31, 2026, 00:00 UTC. On older accounts it enforces the check only on requests that set thinking.block_binding.prefix_mismatch_behavior. Later models will enforce it for all accounts, so make your integration append-only now.
To keep thinking valid, send every assistant turn back exactly as you received it and add new messages only at the end of messages. If your code builds the messages array itself, the Preserved thinking page covers:
- What counts as an edit, and how to check whether your code makes one.
- The API feature that replaces each common edit: mid-conversation system messages for new instructions and per-turn reminders,
tool_additionandtool_removalblocks for tool changes, per-messageoutput_configfor effort changes, and server-side compaction and context editing for trimming. - Client-side compaction: which patterns keep thinking valid and which don't.
- The
thinking-binding-controls-2026-08-01beta header. It adds aninput_transformationsarray to every response that lists the blocks the API dropped, and ablock_binding.prefix_mismatch_behaviorfield on the thinking configuration that accepts"error"or"drop_block".
Thinking and prompt caching
Prompt caching interacts with thinking in a few specific ways. The following rules apply in both thinking modes.
Configuration changes invalidate caching. The thinking configuration and the resolved effort level are rendered into the prompt itself, so changing any of them starts a new cache prefix. Switching between adaptive, enabled, and disabled, changing budget_tokens, and changing the effort value all invalidate cache breakpoints: message-level breakpoints always miss, and tool and system-prompt breakpoints can miss too, depending on where the model renders the configuration. Treat any thinking or top-level effort change as starting the cache over. On models that support per-message effort, an effort change carried in a role: "system" message inside messages leaves the cached prefix intact. Consecutive requests that keep the same configuration preserve the cache, and setting a parameter explicitly to its default value is equivalent to omitting it. A thinking block the API drops under either preserved-thinking condition changes the cached prefix from that block's position onward. Blocks passed back unchanged keep the cache intact. A worked demonstration with usage output is on the Steering thinking page.
Thinking blocks are cached with tool results. During a tool-use loop, caching occurs when you make a follow-up request that includes tool results. At that point the previous conversation history, including its thinking blocks, can be cached, and those cached thinking blocks count as input tokens in your usage metrics when read from the cache. This occurs automatically, even without explicit cache_control markers, and behaves the same for regular and interleaved thinking. The tradeoff: thinking blocks you never see again in responses still contribute to input token usage when read from cache.
Whether prior blocks are in context at all is per-model. The preservation default governs this. On keep-all models, previous turns' thinking blocks stay cached and in context. On last-turn-only models, once you send a user message that isn't a tool result, all previous thinking blocks are stripped from context. On those models, a conversation like this:
User: ["What's the weather in Paris?"],
Assistant: [thinking_block_1] + [tool_use block 1],
User: [tool_result_1, cache=True],
Assistant: [thinking_block_2] + [text block 2],
User: [Text response, cache=True]is processed as if the thinking blocks were never there:
User: ["What's the weather in Paris?"],
Assistant: [tool_use block 1],
User: [tool_result_1, cache=True],
Assistant: [text block 2],
User: [Text response, cache=True]On keep-all models, the same request keeps thinking_block_1 and thinking_block_2 in context and in the cache.
Degradation strips thinking from the cacheable history. If thinking becomes disabled mid-turn and you pass thinking content in the current tool-use turn, the thinking content is stripped and thinking remains disabled for that request (see graceful degradation). Interleaved thinking amplifies cache invalidation effects, because thinking blocks can occur between multiple tool calls.
Thinking and the context window
max_tokens, which includes all thinking Claude generates in the current turn, is enforced as a strict limit. On Claude 4.5 models and newer, if input tokens plus max_tokens exceeds the context window size, the API accepts the request. If generation then reaches the context window limit, it stops with stop_reason: "model_context_window_exceeded" instead of returning an error. On earlier models, the API returns a validation error instead. See Handling stop reasons.
How thinking counts against the window depends on when it was generated:
- Current-turn thinking always counts toward
max_tokens, is billed as output tokens, and occupies context window space for the turn that generated it. - Prior-turn thinking depends on the preservation default. On models that keep all prior turns, previous thinking blocks remain in context, count toward the window, and are billed as input tokens like the rest of the conversation history. On models that keep only the last turn, the API strips older thinking blocks automatically when you pass them back, so they don't consume window space or input tokens.
In practice:
- On keep-all models, budget your context window as if thinking were ordinary conversation history, because it is. Long agentic sessions accumulate thinking in context. Use thinking block clearing if you need to reclaim space.
- On last-turn-only models, thinking is a per-turn cost only: each turn's thinking counts against that turn's
max_tokensand then drops out of the window.
The following diagrams illustrate the last-turn-only (stripping) regime. The first shows a multi-turn conversation: each turn's thinking block is generated in the output but not carried into later turns' input.
The second shows the same regime with tool use: thinking stays in context alongside its tool result for the duration of the assistant turn, then drops out on the next user turn.
Use the token counting API to get accurate counts for your specific use case, especially for multi-turn conversations that include thinking.
Thinking encryption
Full thinking content is encrypted and returned in the signature field on each thinking block. The API uses the signature to verify that thinking blocks were generated by Claude when you pass them back.
Keep the following in mind when working with signatures:
- It is only strictly necessary to send back thinking blocks when using tools with thinking. Otherwise you can omit thinking blocks from previous turns. If you do pass them back, whether the API keeps or strips them depends on the model (see Thinking block preservation by model). Use context editing to configure this.
- When sending back thinking blocks, pass everything back exactly as you received it, for consistency and to avoid potential issues.
- When streaming responses, the signature arrives as a
signature_deltainside acontent_block_deltaevent just before thecontent_block_stopevent. signaturevalues are significantly longer in Claude 4 and later models than in previous models.- The
signaturefield is opaque: don't interpret or parse it. signaturevalues are compatible across platforms (the Claude API, Amazon Bedrock, and Google Cloud). Values generated on one platform work on another.
Redacted thinking blocks
In addition to regular thinking blocks, the API may return redacted_thinking blocks when portions of Claude's reasoning are safety-redacted. A redacted_thinking block contains encrypted thinking content in a data field, with no readable text:
{
"type": "redacted_thinking",
"data": "..."
}The data field is opaque and encrypted. Like the signature field on regular thinking blocks, pass redacted_thinking blocks back to the API unchanged when continuing a multi-turn conversation with tools.
Limits and feature compatibility
Sampling parameters
On Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, Claude Mythos Preview, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, and Claude Sonnet 5, non-default temperature, top_p, or top_k values return a 400 error on every request, regardless of whether thinking is used. On older models, the restriction applies only while thinking is on: temperature and top_k are incompatible with thinking, and top_p is allowed at values between 0.95 and 1.
Response prefill and forced tool use
You can't prefill the assistant response while thinking is on. Forced tool use (tool_choice: {"type": "any"} or {"type": "tool", ...}) is incompatible with manual extended thinking but works with adaptive thinking. The exceptions are Claude Fable 5.1 and Claude Mythos 5.1, which reject forced tool use on every request with a 400 error. On those models, use tool_choice: {"type": "auto"} with strict tool use or structured outputs instead. See Thinking with tool use.
Output limits
Each model accepts max_tokens up to the ceiling listed here. On the Message Batches API, the output-300k-2026-03-24 beta header raises that ceiling for the models with a batches ceiling listed.
| Model | Max output tokens | Batches beta ceiling |
|---|---|---|
| Claude Fable 5.1 | 128k | — |
| Claude Mythos 5.1 | 128k | — |
| Claude Fable 5 | 128k | — |
| Claude Mythos 5 | 128k | — |
| Claude Mythos Preview | 128k | Not available |
| Claude Opus 5 | 128k | 300k |
| Claude Opus 4.8 | 128k | 300k |
| Claude Opus 4.7 | 128k | 300k |
| Claude Sonnet 5 | 128k | 300k |
| Claude Opus 4.6 | 128k | 300k |
| Claude Sonnet 4.6 | 128k | 300k |
| Claude Haiku 4.5 | 64k | Not available |
| Claude Sonnet 4.5 | 64k | Not available |
| Claude Opus 4.5 | 64k | Not available |
See the models overview for limits on legacy models.
Long requests
The SDKs require streaming when max_tokens is greater than 21,333, to avoid HTTP timeouts on long-running requests. This is a client-side validation, not an API restriction. If you don't need to process events incrementally, use .stream() with .get_final_message() (Python) or .finalMessage() (TypeScript) to get the complete Message object without handling individual events. See Streaming Messages. Expect longer response times when thinking is active, because generating thinking blocks adds processing time. For workloads that push thinking above roughly 32k tokens per request, use batch processing to avoid networking issues: such requests can run long enough to hit system timeouts and open connection limits.
Next steps
Steer how often and how deeply Claude thinks with effort levels, system prompt guidance, and per-message steering, and understand thinking's cost and pricing.
Walk through a complete two-turn tool-use round trip that preserves thinking blocks correctly, and see how interleaved thinking changes the flow.
Find out whether your Messages API integration edits conversation history, and replace each edit with the API feature that keeps earlier thinking blocks valid.
Diagnose and fix the most common thinking failures: configuration 400 errors, empty or missing thinking blocks, max_tokens stops, and cache misses.
Control how many tokens Claude uses when responding with the effort parameter, trading off between response thoroughness and token efficiency.
Was this page helpful?