# Claude Fable 5.1 tightens restrictions on reusing thinking blocks

> Source: <https://platform.claude.com/docs/en/build-with-claude/thinking>
> Published: 2026-09-02 01:13:42+00:00

[Messages](/docs/en/intro)Thinking

# 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](#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](#summarized-thinking). 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](#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](#thinking-with-tool-use). For the full response format, see the [Messages API reference](/docs/en/api/messages/create).

## 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](/docs/en/build-with-claude/thinking-troubleshooting#supported-models) 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](/docs/en/models/overview) 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](/docs/en/build-with-claude/thinking-steering-and-cost#cost-control) on the steering page and [Thinking and the context window](#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](/docs/en/build-with-claude/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](/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5#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](/docs/en/build-with-claude/thinking-troubleshooting#supported-models)), configure it with `type: "enabled"`

and a `budget_tokens`

value instead. The [Extended thinking](/docs/en/build-with-claude/extended-thinking) page covers that configuration. And if any thinking configuration comes back with a 400 error, [Troubleshooting thinking](/docs/en/build-with-claude/thinking-troubleshooting) 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](#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 empty`thinking`

field. The`signature`

field still carries the encrypted full thinking for multi-turn continuity (see[Thinking encryption](#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](https://anthropic.com/glasswing).`"updates"`

(beta): reasoning blocks are returned with an empty`thinking`

field, as with`"omitted"`

, and the short[progress updates](#progress-updates)some models write between tool calls come back as readable text. Requires the beta header`thinking-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
`signature`

to reconstruct the original thinking for prompt construction (see[Preserving thinking blocks](#preserving-thinking-blocks)). Any text you place in the`thinking`

field of a round-tripped omitted block is ignored. `display`

is invalid with`thinking.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 of`display`

. - When streaming with
`display: "omitted"`

, no`thinking_delta`

events are emitted. With`display: "updates"`

, only[progress-update blocks](#progress-updates)stream`thinking_delta`

events. See[Streaming thinking](#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](https://anthropic.com/glasswing)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](/docs/en/build-with-claude/refusals-and-fallback#refusal-response) for the field reference and handling guidance.

### Streaming thinking

Thinking works with [streaming](/docs/en/build-with-claude/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.

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](#progress-updates) 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](/docs/en/build-with-claude/streaming).

## Thinking and effort

The `thinking`

parameter controls whether Claude thinks in [thinking blocks](/docs/en/build-with-claude/thinking) 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](/docs/en/build-with-claude/thinking-steering-and-cost#effort-levels) on the [Steering thinking](/docs/en/build-with-claude/thinking-steering-and-cost) page. The [Effort](/docs/en/build-with-claude/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](/docs/en/build-with-claude/extended-thinking#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`effort`

first. 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](/docs/en/build-with-claude/thinking-steering-and-cost#tuning-thinking-behavior)on the steering page.**You need thinking fully off:** use`thinking: {type: "disabled"}`

on models that allow it (see the[per-model configuration table](/docs/en/build-with-claude/thinking-troubleshooting#supported-models)).**You need a hard ceiling on spend:** use`max_tokens`

. Effort is soft guidance.`max_tokens`

is a strict limit.

## Thinking with tool use

Thinking works alongside [tool use](/docs/en/agents-and-tools/tool-use/overview), 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 supports`tool_choice: {"type": "auto"}`

(the default) or`tool_choice: {"type": "none"}`

. Using`tool_choice: {"type": "any"}`

or`tool_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](#limits-and-feature-compatibility)).**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](#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](#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](#thinking-block-preservation-by-model). To override the default, use the [ clear_thinking_20251015 context-editing strategy](/docs/en/build-with-claude/context-editing#thinking-block-clearing).

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](#redacted-thinking-blocks).

For a complete two-turn walkthrough with code in every SDK, see [Thinking in tool and multi-turn workflows](/docs/en/build-with-claude/thinking-tool-workflows#two-turn-tool-use-round-trip). 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](/docs/en/build-with-claude/extended-thinking#interleaved-thinking) 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](/docs/en/agents-and-tools/tool-use/overview).

For a worked comparison showing what interleaved thinking changes in a two-tool workflow, see [How interleaved thinking changes the flow](/docs/en/build-with-claude/thinking-tool-workflows#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](#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](#controlling-thinking-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](/docs/en/api/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
`thinking`

block. - 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_tokens`

at its full length, not the summary's. - A progress-update block can come back with an empty
`thinking`

field under any`display`

value. 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`

, or`stop_sequence`

soon 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 exactly`This 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 new`user`

message (with a`tool_result`

for each`tool_use`

block in that turn). - When
[streaming](#streaming-thinking), expect a pause of several seconds before a progress-update block opens. See the`"updates"`

trace in[Streaming thinking](#streaming-thinking). - These models write fewer progress updates at higher
[effort](/docs/en/build-with-claude/effort)and in long tool chains. If your interface depends on them, see[Ask for user-facing progress updates](/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#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](#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](#preserving-thinking-blocks). To override the default in either direction, use [thinking block clearing](/docs/en/build-with-claude/context-editing#thinking-block-clearing).

**Switching models mid-conversation.** Keep passing thinking blocks back unchanged when you switch models, for example after a [classifier refusal fallback](/docs/en/build-with-claude/refusals-and-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](#preserved-for-model) 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](/docs/en/build-with-claude/fallback-credit), which requires the body unchanged.

## Preserved thinking

Claude preserves a thinking block, keeping it usable on later turns, only under the conditions it was created in. Starting with Claude Fable 5.1 and Claude Mythos 5.1, a `thinking`

or `redacted_thinking`

block is preserved only:

**For the model that produced it, or a newer one.** An earlier model can't use the block, and the API drops it from that request. See[Only for the model that produced it, or a newer one](#preserved-for-model).**In the conversation that produced it (Claude Fable 5.1 only).** If the`system`

prompt, the`tools`

, or any earlier message changes, the block is no longer valid, and the API rejects the request or drops the block. See[Only in the conversation that produced it](#preserved-in-conversation).

The block's `signature`

records both conditions on both models. The API checks it whenever the block comes back in a later request, including a request to a different model; Claude Mythos 5.1 checks only the model condition.

**Pass blocks back unchanged.** Send every assistant turn exactly as you received it, thinking blocks included, and let the API decide which blocks the model can use.

### Only for the model that produced it, or a newer one

This condition is one-way: Claude Fable 5.1 and Claude Mythos 5.1 read earlier models' thinking blocks, and no earlier model reads theirs.

**A conversation that moves onto Claude Fable 5.1 or Claude Mythos 5.1 keeps its reasoning.** The earlier model's thinking blocks stay readable, so the model thinks as usual from the first turn after the switch.**A conversation that moves from them to any earlier model loses it.** The earlier model can't read their blocks, the API drops them for that request, and the earlier model reasons again from the visible messages. If the conversation later returns to Claude Fable 5.1 with the same history, its own blocks are readable again.

In full, Claude Fable 5.1 and Claude Mythos 5.1 read thinking blocks produced by each other, by Claude Opus 5, Claude Fable 5, and Claude Mythos 5, and by Claude Opus 4.8 and earlier Opus models, Claude Sonnet models, and Claude Haiku 4.5. No model other than these two can read a block produced by Claude Fable 5.1 or Claude Mythos 5.1.

**A block the receiving model can't read is dropped.** The API removes it before the prompt reaches the model. It doesn't count toward `input_tokens`

and isn't billed. When you fall back from Claude Fable 5.1 to an older model mid-conversation, for example after a [classifier refusal fallback](/docs/en/build-with-claude/refusals-and-fallback), the older model reasons again from the visible conversation. With the [controls beta header](#preserved-thinking-controls) the drop is reported in `input_transformations`

as `model_binding_mismatch`

. Without it the drop is silent. A [server-side fallback](/docs/en/build-with-claude/refusals-and-fallback#server-side-fallback) drops unreadable blocks the same way.

### Only in the conversation that produced it

A thinking block from Claude Fable 5.1 is preserved only while the conversation prefix it was produced from stays unchanged. Its `signature`

covers the `system`

prompt, the `tools`

, and the messages that preceded the block. Claude Mythos 5.1 records the same `signature`

but doesn't run this check.

This check is enforced for new accounts created on or after August 31, 2026. For accounts created earlier, the API records the condition in the signature but doesn't act on a mismatch unless the request sets [ thinking.block_binding.prefix_mismatch_behavior](#preserved-thinking-controls), which opts into enforcement. Anthropic plans to enforce this condition for every organization on future models. If your account was created earlier, make your application compatible now: the same append-only patterns keep the

[prompt cache](/docs/en/build-with-claude/prompt-caching)warm, and you can test against the check by sending

`prefix_mismatch_behavior: "error"`

. If you ship a tool or framework that people run with their own API key, test that way: your users on new accounts are enforced before you are. [Preserved thinking](/docs/en/build-with-claude/preserved-thinking)has the integration checklist: how to tell whether your code edits history, and the API feature that replaces each kind of edit.

Where the check is enforced, a request that replays a block against a changed prefix is rejected with a 400 `invalid_request_error`

:

```
messages.5.content.0: Invalid `signature` in `thinking` block. The block is bound to a different conversation. Remove the block, or set `thinking.block_binding.prefix_mismatch_behavior` to "drop_block". That setting requires the `thinking-binding-controls-2026-08-01` value in the `anthropic-beta` header.
```

The last sentence appears only when the request didn't send the beta header. The message can end with one more sentence naming the first message that changed. Retrying the same request body fails the same way. To continue without the invalidated reasoning instead, send the `thinking-binding-controls-2026-08-01`

beta header and set `prefix_mismatch_behavior`

to `"drop_block"`

. The API then drops the failing block and every thinking block after it in the conversation, and reports each one in `input_transformations`

as `prefix_binding_mismatch`

. The [token counting](/docs/en/build-with-claude/token-counting) endpoint runs the same check and returns the same 400.

What invalidates later thinking blocks:

- Editing, reordering, or removing an earlier message, including removing a per-turn reminder you injected into an earlier user turn.
- Changing the content of the top-level
`system`

prompt, or adding, removing, or editing a tool in the`tools`

array, between requests. - Client-side compaction or truncation that keeps recent assistant turns verbatim, thinking included, while rewriting the turns before them.
- An image or document URL in an earlier turn that serves different bytes on a later request. The check covers the bytes, not the URL string, so a rotating signed URL for the same file is fine. For content you reference across turns, upload it once with the
[Files API](/docs/en/build-with-claude/files)and send the`file_id`

, or send base64.

What doesn't:

- Removing a leading run of thinking blocks, oldest first: the first thinking block in the conversation (or the first one after the most recent compaction block), then the next, and so on. Removing a thinking block from anywhere else invalidates every thinking block after it, in that turn and in every later turn.
- Changing
`output_config.effort`

,`max_tokens`

, or other sampling settings between requests. `cache_control`

markers, wherever you place or move them.- Server-side
[compaction](/docs/en/build-with-claude/compaction)and[context editing](/docs/en/build-with-claude/context-editing): they don't count as edits, because the check compares the conversation as you sent it, not the server's edited copy. After a compaction, the checked prefix starts from the compaction block.

Patterns that keep thinking blocks valid:

**Append only.** Add new messages at the end of`messages`

and leave earlier turns byte-for-byte unchanged.**Use** and mid-conversation tool changes to add instructions or change tool availability partway through, instead of editing the top-level[mid-conversation system messages](/docs/en/build-with-claude/mid-conversation-system-messages)`system`

field or`tools`

array. For a reminder that should apply to one turn only, send it as a[turn-scoped system message](/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages)and leave it in the history rather than deleting it later. This also preserves the prompt cache.**Use server-side context management** rather than trimming history yourself.**If a request is rejected for a prefix mismatch and you can't repair the history,** resend it with the beta header and`prefix_mismatch_behavior: "drop_block"`

, or strip every`thinking`

and`redacted_thinking`

block from the history and retry once.

When earlier thinking is dropped, the model answers that turn without those blocks. A client that repeatedly invalidates its own history restarts the prompt cache each time, which raises cost.

**Client-side compaction.** This check doesn't rule out compacting on the client. The rule is narrower: don't keep a thinking block behind a prefix you've rewritten. Server-side [compaction](/docs/en/build-with-claude/compaction) is the simplest way to satisfy it. If you compact on the client, use one of these shapes:

**Simple compaction (recommended):** summarize the conversation into one message and start the next request with that summary plus the new user turn, replaying no earlier turns and no earlier thinking blocks. No earlier thinking remains, so nothing fails, and the model thinks afresh on the compacted conversation. Claude models are trained on long-horizon tasks with this scheme, and it performs comparably to more elaborate ones for most workloads. It resets the prompt cache, as any compaction does.**Keep-tail compaction:** summarize older turns and keep the most recent turns verbatim. The kept turns' thinking blocks were produced against the full history and fail behind the summary. Strip`thinking`

and`redacted_thinking`

from every turn you carry across (their text and tool calls can stay), or set`prefix_mismatch_behavior: "drop_block"`

and let the API discard them.**Background compaction:** build the summary off the critical path and swap it in while the conversation continues. Every turn produced in the meantime has thinking that predates the swap. Send`"drop_block"`

on every request that still carries thinking blocks produced before the swap (or strip those blocks yourself;`input_transformations`

on the first response after the swap lists exactly which ones), or compact synchronously.

Snipping individual turns out of the middle of the transcript invalidates every thinking block after them, and no client-side shape avoids that. Use a mid-conversation system message for the instruction change you were making, or server-side [context editing](/docs/en/build-with-claude/context-editing) for selective removal.

### Controls for blocks that aren't preserved (beta)

Send the [beta header](/docs/en/api/beta-headers) `thinking-binding-controls-2026-08-01`

to get two things: an `input_transformations`

array on every response that lists any thinking blocks the API dropped, and a `block_binding`

object on the thinking configuration with one field.

| Field | Type | Default | Description |
|---|---|---|---|
`prefix_mismatch_behavior` | `"error"` or `"drop_block"` | `"error"` | What the API does with a thinking block that fails the
`"error"` rejects the request with a 400 error. `"drop_block"` removes the block and every later thinking block in the conversation, reports each in `input_transformations` , and continues. Neither value changes the model check, which always drops. |

`block_binding`

is accepted alongside `thinking.type: "adaptive"`

and `thinking.type: "enabled"`

. Sending it without the beta header returns a 400 error. Models that don't run the conversation check accept the object and report only model-check drops, so one request body works across models. On Amazon Bedrock and Google Cloud, pass beta names as described in [Beta headers](/docs/en/api/beta-headers).

The following request opts into dropping rather than rejecting. On a first turn there is nothing to replay, so `input_transformations`

comes back empty:

```
client = anthropic.Anthropic()

response = client.beta.messages.create(
    model="claude-fable-5-1",
    max_tokens=16000,
    thinking={
        "type": "adaptive",
        "block_binding": {"prefix_mismatch_behavior": "drop_block"},
    },
    messages=[
        {
            "role": "user",
            "content": "What is the greatest common divisor of 1071 and 462?",
        }
    ],
    betas=["thinking-binding-controls-2026-08-01"],
)

for block in response.content:
    if block.type == "text":
        print(block.text)

print(f"Input transformations: {len(response.input_transformations or [])}")
The greatest common divisor of 1071 and 462 is 21.
Input transformations: 0
```

**Dropped blocks are reported in input_transformations.** Under the beta header, every response from a thinking-capable model carries this top-level array. It's empty when nothing was dropped and never

`null`

. Each entry names the position of a dropped block and the check it failed:

```
{
  "input_transformations": [
    {
      "type": "thinking_dropped",
      "path": "messages.1.content.0",
      "reason": "model_binding_mismatch"
    }
  ]
}
```

The `reason`

field is `model_binding_mismatch`

or `prefix_binding_mismatch`

. Ignore entries whose `type`

or `reason`

you don't recognize, because later checks add values. When [streaming](/docs/en/build-with-claude/streaming), `input_transformations`

arrives on the `message`

object in the `message_start`

event. After a mid-stream server-side fallback, the final `message_delta`

event carries the array again with the serving model's entries. Without the beta header the field is absent.

A tampered or undecryptable signature is a different failure: it always returns a 400 (`Invalid `signature` in `thinking` block`

, with no reason clause) and `prefix_mismatch_behavior`

doesn't apply to it. In a [message batch](/docs/en/build-with-claude/batch-processing), an item whose block fails the conversation check under `"error"`

resolves as `errored`

.

## Thinking and prompt caching

[Prompt caching](/docs/en/build-with-claude/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](/docs/en/build-with-claude/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](/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta), 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](#preserved-thinking)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](/docs/en/build-with-claude/thinking-steering-and-cost#prompt-caching)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](#thinking-block-preservation-by-model) 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](#thinking-with-tool-use)). [Interleaved thinking](#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](/docs/en/build-with-claude/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](#thinking-block-preservation-by-model). On[models that keep all prior turns](#thinking-block-preservation-by-model), 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](/docs/en/build-with-claude/context-editing#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_tokens`

and 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](/docs/en/build-with-claude/token-counting) 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](#thinking-with-tool-use). 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](#thinking-block-preservation-by-model)). Use[context editing](/docs/en/build-with-claude/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](#streaming-thinking), the signature arrives as a`signature_delta`

inside a`content_block_delta`

event just before the`content_block_stop`

event. `signature`

values are significantly longer in Claude 4 and later models than in previous models.- The
`signature`

field is opaque: don't interpret or parse it. `signature`

values are compatible across platforms (the Claude API,[Amazon Bedrock](/docs/en/build-with-claude/claude-in-amazon-bedrock), and[Google Cloud](/docs/en/build-with-claude/claude-on-vertex-ai)). 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](#thinking-with-tool-use).

## 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](/docs/en/agents-and-tools/tool-use/strict-tool-use) or [structured outputs](/docs/en/build-with-claude/structured-outputs) instead. See [Thinking with tool use](#thinking-with-tool-use).

### Output limits

Each model accepts `max_tokens`

up to the ceiling listed here. On the [Message Batches API](/docs/en/build-with-claude/batch-processing#extended-output-beta), the `output-300k-2026-03-24`

[beta header](/docs/en/api/beta-headers) 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](/docs/en/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](/docs/en/build-with-claude/streaming#get-the-final-message-without-handling-events). 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](/docs/en/build-with-claude/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?
