

# Preserved thinking
<a name="claude-messages-thinking-block-binding"></a>

## Overview
<a name="claude-messages-thinking-block-binding-overview"></a>

On Claude Fable 5.1, each thinking block is tied to the conversation that produced it. The API checks that the system prompt, the tool list, and all messages before the block are unchanged when you replay that block in a later request. This protects the integrity of Claude's reasoning: reasoning produced under one set of instructions cannot be replayed under a different set.

If your harness sends conversation history back exactly as it received it, nothing changes for you. If you edit history between requests — injecting per-turn reminders, summarizing older turns, or rebuilding the system prompt — the API rejects the request by default.

**What is checked on replay**


| **Check** | **Description** | 
| --- | --- | 
| Model | The model reading the block is allowed to read the producer's thinking. A model cannot read another model's thinking unless the two are explicitly compatible. This check applies on any thinking-capable model. | 
| Conversation prefix | The top-level system prompt, tools, and all message content before the block are unchanged from the request that produced it. Claude Fable 5.1 runs this check. Claude Mythos 5.1 records the same signature but doesn't run it. | 
| Organization | The thinking block was produced by the same AWS account, or an account in the same customer group. A block replayed from a different account — or one minted in a Claude app (claude.ai or Claude Code) — is removed before the model runs; the request still succeeds. Applies on Claude Sonnet 5.5. | 

**Note**  
A thinking block whose signature has been altered or cannot be decrypted always returns a 400, regardless of these checks or the beta value.

## The block\_binding request object (beta)
<a name="claude-messages-thinking-block-binding-request-object"></a>

Add `block_binding` to the `thinking` object and include the beta value in `anthropic_beta` to control what happens when a prefix mismatch is detected:

```
{
    "anthropic_version": "bedrock-2023-05-31",
    "anthropic_beta": ["thinking-binding-controls-2026-08-01"],
    "max_tokens": 16000,
    "thinking": {
        "type": "adaptive",
        "block_binding": {
            "prefix_mismatch_behavior": "drop_block"
        }
    },
    "messages": [{ "role": "user", "content": "Your prompt here" }]
}
```

`block_binding` accepts one field, `prefix_mismatch_behavior`, which controls what the API does with a thinking block that fails the conversation prefix check. `mismatch_behavior` is accepted as a deprecated alias for this field. Setting both `prefix_mismatch_behavior` and `mismatch_behavior` in the same request returns a `400 invalid_request_error`: `cannot set both block_binding.prefix_mismatch_behavior and block_binding.mismatch_behavior; send only prefix_mismatch_behavior`. Sent without the beta value, `block_binding` returns a 400. Malformed values also return a 400 naming the field.

## Controlling mismatch behavior
<a name="claude-messages-thinking-block-binding-mismatch-behavior"></a>


| **Value** | **Behavior on a failed check** | 
| --- | --- | 
| "error" (default) | Request fails with 400 invalid\_request\_error naming the failed block. Not retryable; returned before any streaming events. | 
| "drop\_block" | Request succeeds with 200. The failing block is removed before the model, along with every later thinking block in the conversation, and each removed block is listed in input\_transformations. | 

Neither value changes the model check, which always drops.

## The input\_transformations response array
<a name="claude-messages-thinking-block-binding-input-transformations"></a>

When the beta value is sent, the response may include a top-level `input_transformations` array describing any blocks that were removed:

```
{
    "type": "message", "role": "assistant", "content": [ ... ],
    "stop_reason": "end_turn",
    "usage": {"input_tokens": 18234, "output_tokens": 911},
    "input_transformations": [
        {"type": "thinking_dropped", "path": "messages.3.content.0", "reason": "prefix_binding_mismatch"}
    ]
}
```

This is a top-level array (a sibling of `usage`), present only with the beta value; `[]` when no blocks were removed and absent otherwise. Each entry contains a `path` identifying the removed block and a `reason`: `model_binding_mismatch` (created by a different model), `prefix_binding_mismatch` (the conversation prefix changed), `organization_binding_mismatch` (created by another account or customer group), or `end_user_binding_mismatch` (created in a Claude app). In streaming responses, the array appears within the message object inside the `message_start` event. Removed blocks do not count toward `input_tokens`.

## Organization-locked thinking
<a name="claude-messages-thinking-block-binding-organization-locked"></a>

On Claude Sonnet 5.5, each thinking block is also bound to the AWS account (or customer group) that produced it, in addition to the model and conversation-prefix checks. A block replayed from a different account, or one minted in a Claude app (claude.ai or Claude Code), is dropped before the model runs; the request still succeeds and the model does not see that earlier reasoning.

By default the drop is silent. With the `thinking-binding-controls-2026-08-01` beta, each dropped block is listed in the top-level `input_transformations` array:

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

Replaying thinking blocks within the same AWS account (or customer group) is unaffected. Without the `thinking-binding-controls-2026-08-01` beta, the response does not include an `input_transformations` field. In the same-account case with the beta, the field is present as an empty array (`[]`).

This binding applies on Claude Sonnet 5.5; earlier models are unaffected.

## Error responses
<a name="claude-messages-thinking-block-binding-error-responses"></a>

When `prefix_mismatch_behavior` is `"error"`, a prefix mismatch returns:

```
{
    "type": "error",
    "error": {
        "type": "invalid_request_error",
        "message": "messages.3.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\". The system prompt differs."
    }
}
```

This error is permanent for that request — an automatic retry loop will not clear it. When you catch it, either strip all thinking blocks from history and retry, or retry with `prefix_mismatch_behavior: "drop_block"` and the beta header.

## Guidance for multi-turn and agentic applications
<a name="claude-messages-thinking-block-binding-guidance"></a>
+ Replay assistant turns exactly as they were returned, and keep the system prompt and tools stable within a conversation.
+ Avoid one-off content injected into earlier turns (for example, a transient system message or reminder text appended to the last user turn). These change the conversation prefix and invalidate later thinking blocks. Use mid-conversation system messages instead.
+ If your application rewrites conversation history, drop thinking blocks from the rewritten point onward, or set `prefix_mismatch_behavior` to `"drop_block"`.
+ When using the Converse API with a model that supports it, pass the beta value and `thinking.block_binding` through `additionalModelRequestFields`.