Follow Discord
Sweep 10 Nov 2026 · 02:18Z Build v2.1.322 539 read Stable v2.1.311 Latest v2.1.322 Next v2.1.322 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One capture · api

One read of Claude Developer Platformapi-20261112T160709Z

52 pages moved out of 904 read.

Pages moved 52 significant first
Pages read 904 in this capture
Captured 16:07 UTC
Corpus hash 0908a26ac580 corpus-hash

What this read moved

1-25 of 52, page 1 of 3

This capture is too large to show at once. Changes 1-25 of 52 are below, significant first; the rest are on the following screens.

about-claude/models/optimizing-for-cost-and-intelligence Changed · +6 / -6 lines

from line 192
192192 
193193#### What breaks the cache
194194 
195Put per-request text, such as a status line, at the end of the newest user turn, after the last cache breakpoint. On later requests, leave each earlier turn as you sent it, with its old status line still in it. Make cache-invalidating changes at a natural break, such as the first request after a compaction. On models that run the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check), a request that edits the system prompt or `tools` can get a 400 error even at such a break. Send those changes in `messages` instead, where your platform supports it (see [Make changes without editing the prefix](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#replace-prefix-edits)). The cache is a byte-exact prefix match over the request in order (tools, then system prompt, then messages), so a change anywhere invalidates everything after it.
195Put per-request text, such as a status line, at the end of the newest user turn, after the last cache breakpoint. On later requests, leave each earlier turn as you sent it, with its old status line still in it. Make cache-invalidating changes at a natural break, such as the first request after a compaction. On [models that run the prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#enforcement), a request that edits the system prompt or `tools` can get a [400 error](https://platform.claude.com/docs/en/api/errors#thinking-block-conversation-mismatch) even at such a break. Send those changes in `messages` instead, where your platform supports it (see [Change tools or instructions without failing the prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions)). The cache is a byte-exact prefix match over the request in order (tools, then system prompt, then messages), so a change anywhere invalidates everything after it.
196196 
197197When something must change mid-conversation, send it in the form that keeps the cache, where the model supports it. Anthropic tested each change both ways on Claude Fable 5.1, Claude Opus 5.5, and Claude Sonnet 5.5, on a cached conversation of about 100,000 tokens that held the model’s first reply with its thinking. Editing the system prompt cost about 25 to 50 times what the same text cost as a mid-conversation system message. Changing effort at the top level cost 20 to 40 times what changing it in a message cost<sup>[18](https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence#refs)</sup>:
198198 
from line 202
202202 
203203When a change invalidates the cache, the part of the prefix it affects is written again instead of read. A write to the 5-minute cache costs 1.25x the input price, and a cache read costs a small fraction of the input price. At list prices, that write costs 50 times a read on Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, and Claude Mythos 5.1, where a cache read costs 0.025x the input price. That write costs 25 times a read on Claude Opus 5.5 and Claude Sonnet 5.5 (0.05x), and 12.5 times on Claude Haiku 5.5 (0.1x). The chart’s figures are from the Messages API.
204204 
205A request that edits the system prompt or `tools` can also fail outright. On models that run the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check), a request that makes either edit and sends earlier thinking blocks back can get a 400 error<sup>[18](https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence#refs)</sup>. In a separate Anthropic test, waiting for a compaction didn’t avoid the error: on Claude Opus 5.5 and Claude Fable 5.2, such a request still got it as the first request after a compaction at a token threshold<sup>[18](https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence#refs)</sup>. By default on the Claude API, a request that fails the check gets the error on every account if the model is Claude Fable 5.2, Claude Mythos 5.2, or Claude Mythos 5.1. If the model is Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5, or Claude Haiku 5.5, the request gets the error on some accounts and no error on others. For the outcomes by model and account, see [When `prefix_mismatch_behavior` is unset](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement).
205In a separate Anthropic test on Claude Opus 5.5 and Claude Fable 5.2, requests that edited the system prompt or `tools` and sent earlier thinking blocks back still got the 400 error. They got it even as the first request after a compaction at a token threshold<sup>[18](https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence#refs)</sup>.
206206 
207207**What to do.**
208208 
from line 211
211211* Check which models support each form: [mid-conversation system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages), and [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message), which is in beta.
212212* After a cache-invalidating change, confirm cache reads have not dropped; if they have, [cache diagnostics](https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics) shows where the prefix diverged.
213213 
214On an earlier model, Anthropic measured when to make such a change, on long sessions of the issue-triage agent described in [Trim input and context tokens](https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence#trim-input-and-context-tokens)<sup>[18](https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence#refs)</sup>. The sessions that made changes started at low effort, then switched to the default effort and added one tool. Making the two changes mid-session cost the most. Making them on the request that triggered the compaction cost nearly as much, because that request still carried the whole conversation and wrote it to the cache again. Making them on the next request, the first after the compaction, cost the least. Accuracy was within run-to-run noise. That model doesn’t run the prefix check. On a model that does, add the tool in a message instead: see [Add or remove tools with `tool_addition` and `tool_removal`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#tool-changes), which is in beta. The following chart also shows sessions with no changes. They aren’t a like-for-like baseline, because they ran at the default effort throughout and two of them compacted a second time:
214On an earlier model, Anthropic measured when to make such a change, on long sessions of the issue-triage agent described in [Trim input and context tokens](https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence#trim-input-and-context-tokens)<sup>[18](https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence#refs)</sup>. The sessions that made changes started at low effort, then switched to the default effort and added one tool. Making the two changes mid-session cost the most. Making them on the request that triggered the compaction cost nearly as much, because that request still carried the whole conversation and wrote it to the cache again. Making them on the next request, the first after the compaction, cost the least. Accuracy was within run-to-run noise. That model doesn’t run the prefix check. On a model that does, add the tool in a message instead: see [Add, remove, or turn off tools](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#tool-changes), which is in beta. The following chart also shows sessions with no changes. They aren’t a like-for-like baseline, because they ran at the default effort throughout and two of them compacted a second time:
215215 
216216<Frame>
217217 ![Bar chart, cost per triage session: $0.81 USD no changes, $0.95 USD mid-session, $0.92 USD at compaction, $0.75 USD after](https://platform.claude.com/docs/images/cost-intel/compaction-timing.svg)
from line 277
277277* If you use context editing, [clear in a few large batches](https://platform.claude.com/docs/en/build-with-claude/context-editing#context-editing-and-prompt-caching), because each clear costs a cache write.
278278 
279279<Note>
280 Don’t use the prune on Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Sonnet 5.5, or Claude Haiku 5.5. On these models, if your application rewrites an earlier tool result, that invalidates every thinking block already in the history after the result (see [Keeping the prefix unchanged](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check)), and the request might fail (see [When `prefix_mismatch_behavior` is unset](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement)). The prune was measured on an earlier model without [preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking). Use [compaction](https://platform.claude.com/docs/en/build-with-claude/compaction) instead: in the same test, it also cut the cost of the long run. Compaction and [context editing](https://platform.claude.com/docs/en/build-with-claude/context-editing) both run on the server, so neither invalidates thinking blocks. [Send assistant turns back exactly as returned](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#append-assistant-turns-exactly-as-returned): dropping their thinking blocks costs output tokens on every turn, because Claude [re-creates the reasoning](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#drop-block-cost).
280 Don’t use the prune on Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Sonnet 5.5, or Claude Haiku 5.5. On these models, if your application rewrites an earlier tool result, that invalidates every thinking block already in the history after the result (see [What must stay the same, and why](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check)), and the request might fail (see [What each model does when the prefix check fails](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes)). The prune was measured on an earlier model without [preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking). Use [compaction](https://platform.claude.com/docs/en/build-with-claude/compaction) instead: in the same test, it also cut the cost of the long run. Compaction and [context editing](https://platform.claude.com/docs/en/build-with-claude/context-editing) both run on the server, so neither invalidates thinking blocks. [Send assistant turns back exactly](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#append-assistant-turns-exactly-as-returned): dropping their thinking blocks costs output tokens on every turn, because Claude [re-creates the reasoning](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#drop-block-cost).
281281</Note>
282282 
283283### Batch work that can wait
from line 1011
10111011 
10121012 * **October 2026 test, one change to a long conversation:** Measured October 20, 2026, on Claude Fable 5.1, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5, on the Messages API with no tools, adaptive thinking, each model’s default effort, the 5-minute cache, a cache breakpoint on the system prompt, and [automatic caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching). The conversation held about 101,000 tokens: a 20,000-token system prompt, 13 user turns of filler text, the model’s own reply to the first turn with its thinking block, and one-word replies to the rest. Once one request had cached the conversation, a second added one short turn, and each measured request sent that longer conversation with one change. Two conversations per model gave the same result.
10131013 * **October 2026 test, tokens read and written:** With no change, and with a per-message effort change, the request read all 101,000 tokens and wrote none. With a 25-token mid-conversation system message, or a 25-token status line at the end of the newest user turn, it read them all and wrote only the new text. A top-level effort change (to `low` on Claude Fable 5.1 and Claude Sonnet 5.5, to `high` on Claude Opus 5.5 and Claude Haiku 5.5) read the 20,000-token system prompt and wrote 81,000 tokens. The same 25 tokens at the front or the end of the system prompt read nothing and wrote all 101,000. The request after a mid-conversation system message, a top-level effort change, or 25 tokens added to the end of the system prompt read the new prefix; a new status line at the front wrote everything again. A further test on October 21, 2026, on the same four models with conversations of 5,000 tokens, and on all but Claude Fable 5.1 with conversations of 100,000 tokens, all with one-word replies, sent a beta header for the first time mid-conversation, as a first per-message effort change may: that request read everything the request before it had cached, all 54 times. A system message sent with no beta header did the same, all 15 times.
1014 * **October 2026 test, how priced:** The chart gives the prompt side of one request, from its `usage` fields at list prices. The chart’s values, in the order system prompt edit, system message, top-level effort change, and per-message effort change: Claude Fable 5.1 $1.26 USD, $0.026 USD, $1.02 USD, and $0.025 USD; Claude Opus 5.5 $0.50 USD, $0.020 USD, $0.41 USD, and $0.020 USD; Claude Sonnet 5.5 $0.25 USD, $0.010 USD, $0.20 USD, and $0.010 USD. The unchanged request repeated an earlier request byte for byte; a new turn of about 25 tokens adds under $0.001 USD. On Claude Haiku 5.5, whose requests were over 100,000 prompt tokens and so at its [long context prices](https://platform.claude.com/docs/en/about-claude/pricing#long-context-pricing): $0.063 USD for the system prompt edit, $0.052 USD for the effort change, and $0.005 USD for the read. The requests ran on an Anthropic-internal organization whose usage is metered the same way as a customer organization’s. For that organization, the API lets failing thinking blocks through when a request leaves `prefix_mismatch_behavior` unset, so the system prompt edits in these tests were accepted. On an account created on or after August 31, 2026, 00:00 UTC, the same edit gets a 400 error on all four models, because each request sends an earlier thinking block back.
1015 * **November 2026 test, edits after a compaction:** Run November 9, 2026, on Claude Opus 5.5 and Claude Fable 5.2, on the Messages API with adaptive thinking, `high` effort, no caching, one tool defined, `tool_choice` set to `none`, [`prefix_mismatch_behavior`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#mismatch-behavior) set to `"error"`, and [compaction at a token threshold](https://platform.claude.com/docs/en/build-with-claude/compaction-threshold) with a trigger of 50,000 tokens. A first request of about 55,700 tokens triggered a compaction, and its reply held a compaction block followed by a thinking block. The next request sent that reply back with one new user turn. Unchanged, it succeeded. With one tool added to `tools`, or with the system prompt reworded, it got the 400 error. In a conversation with no compaction, the same two edits got the 400 error, and so did removing a text block from an earlier user turn. One conversation of each kind per model. On Claude Fable 5.2, the first large conversation’s reply held no thinking block. A second conversation replaced the first, with a harder question, a higher `max_tokens`, and custom compaction `instructions`, and only the second counts. The requests ran on the Claude API.
1014 * **October 2026 test, how priced:** The chart gives the prompt side of one request, from its `usage` fields at list prices. The chart’s values, in the order system prompt edit, system message, top-level effort change, and per-message effort change: Claude Fable 5.1 $1.26 USD, $0.026 USD, $1.02 USD, and $0.025 USD; Claude Opus 5.5 $0.50 USD, $0.020 USD, $0.41 USD, and $0.020 USD; Claude Sonnet 5.5 $0.25 USD, $0.010 USD, $0.20 USD, and $0.010 USD. The unchanged request repeated an earlier request byte for byte; a new turn of about 25 tokens adds under $0.001 USD. On Claude Haiku 5.5, whose requests were over 100,000 prompt tokens and so at its [long context prices](https://platform.claude.com/docs/en/about-claude/pricing#long-context-pricing): $0.063 USD for the system prompt edit, $0.052 USD for the effort change, and $0.005 USD for the read. The requests ran on an Anthropic-internal organization whose usage is metered the same way as a customer organization’s. The requests left `prefix_mismatch_behavior` unset, and the API let their failing thinking blocks through, so it accepted the system prompt edits in these tests. Each request sent an earlier thinking block back. On the Claude API, the same edit can get a 400 error on all four models. See [Prefix checks on thinking blocks](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks).
1015 * **November 2026 test, edits after a compaction:** Run November 9, 2026, on Claude Opus 5.5 and Claude Fable 5.2, on the Messages API with adaptive thinking, `high` effort, no caching, one tool defined, `tool_choice` set to `none`, [`prefix_mismatch_behavior`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#mismatch-behavior) set to `"error"`, and [compaction at a token threshold](https://platform.claude.com/docs/en/build-with-claude/compaction-threshold) with a trigger of 50,000 tokens. A first request of about 55,700 tokens triggered a compaction, and its reply held a compaction block followed by a thinking block. The next request sent that reply back with one new user turn. Unchanged, it succeeded. With one tool added to `tools`, or with the system prompt reworded, it got the 400 error. In a conversation with no compaction, the same two edits got the 400 error, and so did removing a text block from an earlier user turn. One conversation of each kind per model. On Claude Fable 5.2, the first large conversation’s reply held no thinking block. A second conversation replaced the first, with a harder question, a higher `max_tokens`, and custom compaction `instructions`, and only the second counts. The requests ran on the Claude API.
10161016 * **What was measured:** The triage agent’s long variant from [Trim input and context tokens](https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence#trim-input-and-context-tokens), run August 24, 2026, on Claude Sonnet 5 with the 5-minute cache, cost from the usage fields at list prices, five sessions per arm: a no-change arm at the default effort throughout ($0.81 USD per session), and two arms that start at low effort and make the same two cache-breaking changes, a switch to the default effort and one added tool, either mid-session at requests 12 and 17 ($0.95 USD) or together on the first request after the first compaction ($0.75 USD).
10171017 * **Fourth arm:** A fourth arm of six sessions, run August 25, 2026, made the same two changes on the request that triggered the first compaction ($0.92 USD per session): that request’s summarization pass wrote the 81,000-token context to the cache instead of reading it, so that pass cost $0.21 USD against $0.04 USD for the same pass in the boundary arm.
10181018 * **Compaction:** Sessions first compacted at request 21 to 25 (16 of the 21 sessions at request 22), once the prompt passed the 80,000-token compaction trigger, and two no-change sessions compacted a second time near the end. The boundary arm’s lower total than the no-change arm reflects its low-effort requests before the change and those second compactions rather than caching: the two arms’ re-write costs differ by under $0.01 USD.

agents-and-tools/tool-use/advisor-tool Changed · +8 / -9 lines

from line 323
323323 
324324The `caching` object has the shape `{"type": "ephemeral", "ttl": "5m" | "1h"}`. Unlike `cache_control` on content blocks, this is not a breakpoint marker. It is an on/off switch. The server determines where cache boundaries go.
325325 
326The advisor tool also accepts the generic properties available on any tool definition: `cache_control`, `allowed_callers`, `defer_loading`, and `strict` (covered in [structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)). See [Tool definition properties](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference#tool-definition-properties) in the Tool reference for their semantics.
326The advisor tool also accepts the generic properties available on any tool definition: `cache_control`, `allowed_callers`, `defer_loading`, and `strict` (covered in [Structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)). See [Tool definition properties](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference#tool-definition-properties) in the Tool reference for their semantics.
327327 
328328## Response structure
329329 
from line 757
757757* **No advisor call is still pending.** See [Resuming a paused turn](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool#resuming-a-paused-turn).
758758* **You still send the `advisor-tool-2026-03-01` beta header.** The API needs it to accept those history blocks. That header covers the `advisor_tool_result` blocks, not thinking blocks.
759759 
760**Exception: a history that also contains thinking blocks.** Removing the advisor tool is an [edit to `tools`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#what-counts-as-an-edit). So is changing its `model` or `caching`. An edit to `tools` invalidates the thinking blocks already in the history.
760**Exception: a history that also contains thinking blocks.** Removing the advisor tool is an [edit to `tools`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#what-counts-as-an-edit). So is changing its `model`, `max_uses`, `max_tokens`, or `caching`. An edit to `tools` invalidates the thinking blocks already in the history.
761761 
762* **What happens:** Where the API enforces the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check), the request returns a 400 error.
763* **Where the API enforces it:** On every account when the executor is Claude Fable 5.2 or Claude Mythos 5.2. For other executors, see the table in [When `prefix_mismatch_behavior` is unset](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement).
762* **What happens:** If the executor model [runs the prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#enforcement), the request can get a [400 error](https://platform.claude.com/docs/en/api/errors#thinking-block-conversation-mismatch).
764763* **How to continue:** Set `thinking.block_binding.prefix_mismatch_behavior` to `"drop_block"` on that request and on every later request in the conversation. The API then drops those thinking blocks. This setting is in beta and needs the `thinking-binding-controls-2026-08-01` beta header.
765764 
766765<Note>
767 The advisor tool has no built-in conversation-level cap. To limit advisor calls across a conversation, count them client-side. When you reach your ceiling, remove the advisor tool from your `tools` array. You do not need to strip `advisor_tool_result` blocks from your message history. If your history also contains thinking blocks, read the preceding exception first. In that case, where the prefix check is enforced, the request returns a 400 error unless you set `"drop_block"`.
766 The advisor tool has no built-in conversation-level cap. To limit advisor calls across a conversation, count them client-side. When you reach your ceiling, remove the advisor tool from your `tools` array. You do not need to strip `advisor_tool_result` blocks from your message history. If your history also contains thinking blocks, read the preceding exception first. In that case, unless you set `"drop_block"`, the request can get a [400 error](https://platform.claude.com/docs/en/api/errors#thinking-block-conversation-mismatch).
768767</Note>
769768 
770769### Resuming a paused turn
from line 1451
14521451**Keep it consistent:** Set `caching` once and leave it for the whole conversation. Toggling it off and on mid-conversation causes cache misses. Each toggle is also an edit to `tools`. That edit can make the next request return a 400 error. [Multi-turn conversations](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool#multi-turn-conversations) explains when this happens and what to set.
14531452 
14541453<Warning>
1455 [`clear_thinking`](https://platform.claude.com/docs/en/build-with-claude/context-editing) with a `keep` value other than `"all"` shifts the advisor’s quoted transcript each turn, causing advisor-side cache misses. This is a cost degradation only. Advice quality is unaffected. When thinking is on without explicit `clear_thinking` configuration, the API defaults to `keep: {type: "thinking_turns", value: 1}`, which triggers this behavior (the default on earlier Opus and Sonnet models and on Haiku models through Claude Haiku 4.5, whereas on Claude Opus 4.5 and later Opus models, Claude Sonnet 4.6 and later Sonnet models, and Claude Haiku 5.5, the default is to keep all turns). Set `keep: "all"` to preserve advisor cache stability.
1454 [`clear_thinking`](https://platform.claude.com/docs/en/build-with-claude/context-editing) with a `keep` value other than `"all"` shifts the advisor’s quoted transcript each turn, causing advisor-side cache misses. This is a cost degradation only. Advice quality is unaffected. When thinking is on without explicit `clear_thinking` configuration, Opus models before Claude Opus 4.5, Sonnet models before Claude Sonnet 4.6, and Haiku models through Claude Haiku 4.5 default to `keep: {type: "thinking_turns", value: 1}`, which triggers this behavior. Claude Opus 4.5 and later Opus models, Claude Sonnet 4.6 and later Sonnet models, Claude Haiku 5.5, and Claude Fable and Claude Mythos models keep all turns by default. Set `keep: "all"` to preserve advisor cache stability.
14561455</Warning>
14571456 
14581457## Combining with other tools
from line 1721
17221721(Advisor: please keep your guidance under 80 words. I need a focused starting point, not a comprehensive plan.)
17231722```
17241723 
1725Your agent framework can prefix this line programmatically before sending the request. The limit is a soft constraint. The advisor occasionally exceeds it, so ask for roughly 80 percent of your true ceiling.
1724Your agent framework can prefix this line once and keep it there. The limit is a soft constraint. The advisor can exceed it, so ask for roughly 80 percent of your true ceiling.
17261725 
17271726<Note>
17281727 In Anthropic’s testing this line also increased how often the executor consults the advisor, but the net effect was still lower total cost (more consults, each shorter).
from line 1852
18531852 
18541853### Cost control
18551854 
1856* For conversation-level budgets, count advisor calls client-side. When you reach your cap, remove the advisor tool from `tools`. You do not need to strip `advisor_tool_result` blocks from your message history (see the note in [Multi-turn conversations](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool#multi-turn-conversations)). If you send earlier thinking blocks back, removing the tool can return a 400 error where the API enforces the prefix check. To avoid it, set `prefix_mismatch_behavior` to `"drop_block"`, as [Multi-turn conversations](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool#multi-turn-conversations) explains. The API enforces the check for every account when the executor is Claude Fable 5.2 or Claude Mythos 5.2.
1855* For conversation-level budgets, count advisor calls client-side. When you reach your cap, remove the advisor tool from `tools`. You do not need to strip `advisor_tool_result` blocks from your message history. If you send earlier thinking blocks back, removing the tool can return a 400 error. To avoid it, set `prefix_mismatch_behavior` to `"drop_block"`, as [Multi-turn conversations](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool#multi-turn-conversations) explains.
18571856* Enable `caching` only for conversations where you expect three or more advisor calls.
18581857 
18591858## Model compatibility

agents-and-tools/tool-use/computer-use-tool Changed · +10 / -12 lines

from line 709
709709 
710710### Optimize model performance with prompting
711711 
7121. Specify simple, well-defined tasks and provide explicit instructions for each step.
7121. Specify well-defined tasks and provide explicit instructions for each step.
7137132. Claude sometimes acts as if its actions succeeded without explicitly checking their results. To prevent this, you can prompt Claude with `After each step, take a screenshot and carefully evaluate if you have achieved the right outcome. State in one sentence what the screenshot shows and whether the step succeeded. If it didn't, try again. Only when you confirm a step was executed correctly should you move on to the next one.`
7147143. Some UI elements (such as dropdowns and scrollbars) might be tricky for Claude to manipulate using mouse movements. If you experience this, try prompting the model to use keyboard shortcuts.
7157154. For repeatable tasks or UI interactions, include example screenshots and tool calls of successful outcomes in your prompt.
from line 718
7187187. Claude uses the `zoom` action to inspect a region at full resolution when asked about small text or specific UI elements that aren’t legible at the screenshot’s default resolution, such as file names in a sidebar, tab titles, status-bar text, line numbers, or button labels. If Claude isn’t zooming when you expect, ask about a specific region or element rather than the screen as a whole.
7197198. If you want every [batch action](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#batch-actions) to end with a screenshot, say so in the system prompt, for example, `End each group of actions with a screenshot so you can verify the result before continuing.`
720720 
721<Tip>
722 If you repeatedly encounter a clear set of issues or know in advance the tasks Claude will need to complete, use the system prompt to provide Claude with explicit tips or instructions on how to do the tasks successfully.
723</Tip>
721If you repeatedly encounter a clear set of issues, or know in advance the tasks Claude has to complete, give Claude explicit tips or instructions for them in the system prompt.
724722 
725<Tip>
726 For agents that span multiple sessions, run end-to-end verification at the start of each session, not only after implementation. Browser-based checks catch regressions from prior sessions that code-level review alone misses. See [Effective harnesses for long-running agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents) for details.
727</Tip>
723For agents that span multiple sessions, run end-to-end verification at the start of each session, not only after implementation. Browser-based checks catch regressions from prior sessions that code-level review alone misses. See [Effective harnesses for long-running agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents) for details.
728724 
729725### System prompts
730726 
from line 1820
18241820 
18251821### Manage screenshot history
18261822 
1827Long agent loops accumulate screenshots quickly (roughly 1,000–1,800 input tokens each). The API’s [request limits](https://platform.claude.com/docs/en/build-with-claude/vision#request-limits) also apply. Once a single request carries more than 20 images, every image in it is held to a stricter per-side limit. A loop that keeps its screenshot history reaches that count within a few dozen turns, so either resize each screenshot to stay under that limit or prune older screenshots to keep 20 or fewer in the request.
1823Long agent loops accumulate screenshots quickly (roughly 1,000–1,800 input tokens each). The API’s [request limits](https://platform.claude.com/docs/en/build-with-claude/vision#request-limits) also apply.
18281824 
1825Once a single request carries more than 20 images, every image in it is held to a stricter per-side limit. A loop that keeps its screenshot history can reach that count. Either resize each screenshot to stay under that limit, or prune older screenshots to keep 20 or fewer in the request.
1826 
18291827To keep [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) effective while bounding context:
18301828 
18311829* Place one `cache_control` breakpoint after the system prompt and tool definitions, and up to three more on the last `tool_result` block of each of the most recent turns, advancing them each turn. Within a [batch action](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#batch-actions), markers on several blocks act as a single breakpoint, but each still counts toward the limit of four, so use at most one in any turn.
from line 1832
18341832 
18351833* Avoid client-side pruning on Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, and Claude Mythos 5.1. The same goes for Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5. On these models, removing an earlier screenshot from a request [invalidates every later thinking block already in the history](https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation) of that and every later request.
18361834 
1837 * **Instead:** Resize screenshots to stay under the stricter limit. Use server-side [tool result clearing](https://platform.claude.com/docs/en/build-with-claude/context-editing#tool-result-clearing) to drop old ones from the context.
1838 * **If you must prune:** Keep [`prefix_mismatch_behavior: "drop_block"`](https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-thinking-controls) set from then on. After each prune, the API drops the invalidated thinking blocks, on that request and every later one. So Claude continues without the thinking that it produced after the pruned screenshot.
1835 * **Instead:** Resize screenshots to stay under the stricter limit. [Tool result clearing](https://platform.claude.com/docs/en/build-with-claude/context-editing#tool-result-clearing) saves tokens, but cleared screenshots still count toward [request limits](https://platform.claude.com/docs/en/build-with-claude/vision#request-limits), so use [on-demand compaction](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand) before a loop reaches them.
1836 * **If you must prune:** Keep [`prefix_mismatch_behavior: "drop_block"`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#preserved-thinking-controls) set from then on. After each prune, the API drops the invalidated thinking blocks, on that request and every later one. So Claude continues without the thinking that it produced after the pruned screenshot.
18391837 * **If you must prune on Claude Sonnet 5.5 or Claude Haiku 5.5:** `prefix_mismatch_behavior` works only with `thinking: {"type": "adaptive"}`. With any other thinking setting on those models, keep the history append-only or strip every `thinking` and `redacted_thinking` block after the pruned screenshot.
18401838 
18411839### Diagnose click issues
from line 2121
21232121 
21242122## Migrate from `computer_20251124`
21252123 
2126A `computer_20251124` integration works without changes on the models listed for that version under [Earlier tool versions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#earlier-tool-versions). Upgrade the integration before you move it to a model that doesn’t accept `computer_20251124`, such as a Claude 5.5 model on the Claude API.
2124A `computer_20251124` integration works without changes on the models listed for that version under [Earlier tool versions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#earlier-tool-versions). Upgrade the integration before you move it to a model that doesn’t accept `computer_20251124`, such as Claude Opus 5.5 on the Claude API.
21272125 
21282126To upgrade, make the following changes together:
21292127 

agents-and-tools/tool-use/tool-use-with-prompt-caching Changed · +10 / -10 lines

from line 48
4848 
4949Deferred tools are not included in the system-prompt prefix. When the model discovers a deferred tool through [tool search](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool), the definition is appended inline as a `tool_reference` block in the conversation history. The prefix is untouched, so prompt caching is preserved.
5050 
51This means adding tools dynamically through tool search does not break your cache. You can start a conversation with a small set of always-loaded tools (cached), let the model discover additional tools as needed, and keep the same cache hit across every turn.
51You can start a conversation with a small set of always-loaded tools (cached), let the model discover additional tools as needed, and keep the same cache hit across every turn.
5252 
5353`defer_loading` also acts independently of grammar construction for [strict mode](https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use). The grammar builds from the full list of tools regardless of which tools are deferred, so prompt caching and grammar caching are both preserved when tools load dynamically.
5454 
from line 56
5656 
5757The cache follows a prefix hierarchy (`tools` → `system` → `messages`), so a change at one level invalidates that level and everything after it:
5858 
59| Change | Invalidates |
60| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
61| Modifying tool definitions | Entire cache (tools, system, messages) |
62| Toggling web search or citations | System and messages caches |
63| Changing `tool_choice` | Messages cache |
64| Changing `disable_parallel_tool_use` | Messages cache |
65| Toggling images present/absent | Messages cache |
66| Changing thinking parameters | Messages cache always; tool and system caches too on models that render the thinking configuration ahead of them (see [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching)) |
67| Changing `output_config.effort` | Same as thinking parameters; setting the model’s default explicitly is equivalent to omitting it |
59| Change | Invalidates |
60| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
61| Modifying tool definitions | Entire cache (tools, system, messages) |
62| Toggling web search or citations | System and messages caches |
63| Changing `tool_choice` | Messages cache |
64| Changing `disable_parallel_tool_use` | Messages cache |
65| Toggling images present/absent | Messages cache |
66| Changing thinking parameters | Messages cache always; tool and system caches too on models that render the thinking configuration ahead of them (see [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching)) |
67| Changing `output_config.effort` | Can invalidate the messages cache, and on some models the tool and system caches too (see [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching)); sending the default explicitly equals omitting it |
6868 
6969<Note>
7070 If you need to vary `tool_choice` mid-conversation, consider placing cache breakpoints before the variation point.

api/errors Changed · +16 / -13 lines

from line 8
88 
99The API follows a predictable HTTP error code format:
1010 
11* 400 - `invalid_request_error`: There was an issue with the format or content of your request. This error type may also be used for other 4XX status codes not listed in this section. The API also returns a 400 when usage reaches an organization or workspace [spend limit you set](https://platform.claude.com/docs/en/api/rate-limits#setting-your-own-spend-limit), except limits on the [Claude Code workspace](https://platform.claude.com/docs/en/manage-claude/workspaces#claude-code-workspace), which can return a 429 instead.
11* 400 - `invalid_request_error`: There’s an issue with the format or content of your request. The API might also use this error type for other 4XX status codes not listed in this section. The API also returns a 400 when usage reaches an organization or workspace [spend limit you set](https://platform.claude.com/docs/en/api/rate-limits#setting-your-own-spend-limit). Limits on the [Claude Code workspace](https://platform.claude.com/docs/en/manage-claude/workspaces#claude-code-workspace) are the exception: they can return a 429 instead. If the message names a problem with your request, look for it in [Common validation errors](https://platform.claude.com/docs/en/api/errors#common-validation-errors).
1212 
1313* 401 - `authentication_error`: There’s an issue with your [API key](https://platform.claude.com/docs/en/get-api-key) (for example, it’s malformed, revoked, or expired; see [Key expiration](https://platform.claude.com/docs/en/manage-claude/authentication#key-expiration)). On Claude Platform on AWS, this can also indicate a problem with your AWS credentials or SigV4 signature.
1414 
from line 24
2424 
2525* 413 - `request_too_large`: Request exceeds the maximum allowed number of bytes. See [Request size limits](https://platform.claude.com/docs/en/api/errors#request-size-limits) for per-endpoint maximums.
2626 
27* 429 - `rate_limit_error`: Your organization has hit a [rate limit](https://platform.claude.com/docs/en/api/rate-limits), reached its usage tier’s monthly spend cap, or reached a spend limit on the Claude Code workspace. A tier spend-cap 429 has no `retry-after` header and keeps failing until access resumes; see [Reaching your spend cap](https://platform.claude.com/docs/en/api/rate-limits#reaching-your-spend-cap) for how to recognize it.
27* 429 - `rate_limit_error`: Your organization has hit a [rate limit](https://platform.claude.com/docs/en/api/rate-limits), reached its usage tier’s monthly spend cap, or reached a spend limit on the Claude Code workspace. A tier spend-cap 429 has no `retry-after` header and keeps failing until access resumes; see [Reaching your spend cap](https://platform.claude.com/docs/en/api/rate-limits#reaching-your-spend-cap) for how to recognize it. A sharp increase in usage can also cause a 429 even while you’re under your rate limits; see [Ramp limits](https://platform.claude.com/docs/en/api/rate-limits#ramp-limits).
2828 
2929* 500 - `api_error`: An unexpected error has occurred internal to Anthropic’s systems. Retry the request with exponential backoff; if the error persists, contact support with the [request ID](https://platform.claude.com/docs/en/api/errors#request-id). If the error type is `timeout_error` instead, see the 504 entry.
3030 
from line 34
3434 
3535 <Warning>
3636 A 529 error can occur when the API experiences high traffic across all users.
37 
38 In rare cases, if your organization has a sharp increase in usage, you might see 429 errors because of acceleration limits on the API. To avoid hitting acceleration limits, increase your traffic gradually and maintain consistent usage patterns.
3937 </Warning>
4038 
4139The official SDK automatically retries transient failures (such as connection errors, rate limits, and 5xx server errors) with exponential backoff, twice by default, honoring the `retry-after` header when present. The SDK client accepts `max_retries` (typescript, php: `maxRetries`; java: `.maxRetries()`; csharp: `MaxRetries`; go: `option.WithMaxRetries()`) to configure or disable this behavior.
from line 68
7068}
7169```
7270 
73In accordance with the [versioning](https://platform.claude.com/docs/en/api/versioning) policy, the values within these objects may expand, and it is possible that the `type` values will grow over time.
71Under the [API versioning policy](https://platform.claude.com/docs/en/api/versioning), the values within these objects can expand, and new `type` values can appear.
7472 
7573## SDK error types
7674 
from line 444
446444 
447445### Thinking blocks cannot be modified
448446 
449If the most recent assistant message contains `thinking` or `redacted_thinking` blocks that were edited, reordered, filtered out, or reconstructed before being sent back to the API, the request returns a 400 `invalid_request_error`. The error message starts with the position of the offending block (for example, `messages.1.content.0`) and contains:
447If thinking blocks in the request don’t match what the API returned, the request can get a 400 `invalid_request_error`. The error message starts with the position of the offending block (for example, `messages.1.content.0`) and contains:
450448 
451449```text wrap
452450`thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response.
453451```
454452 
455With tool use, pass back every `thinking` and `redacted_thinking` block from the assistant turn exactly as received, including blocks whose `thinking` field is empty. If your application filters content blocks by type before resending, include both `thinking` and `redacted_thinking`. See the [fix for modified thinking blocks](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting#error-thinking-blocks-modified) in Troubleshooting thinking, and also [Preserving thinking blocks](https://platform.claude.com/docs/en/build-with-claude/thinking#preserving-thinking-blocks) and [Preserved thinking](https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-thinking).
453With tool use, pass back every `thinking` and `redacted_thinking` block from the assistant turn exactly as received, including blocks whose `thinking` field is empty. If your application filters content blocks by type before resending, include both `thinking` and `redacted_thinking`. This is a different failure from the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check), whose error says that a block is bound to a different conversation. Setting `prefix_mismatch_behavior` might not clear it. See the [fix for modified thinking blocks](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting#error-thinking-blocks-modified) in Troubleshooting thinking.
456454 
457455### Extended thinking not supported
458456 
from line 460
462460"thinking.type.enabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.
463461```
464462 
465Use [adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/thinking) instead. [Migrating to adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking#migrating-to-adaptive-thinking) shows the parameter mapping, and Troubleshooting thinking covers the [symptom-first fix for the extended thinking error](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting#error-thinking-type-enabled).
463Use [adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/thinking) instead. For the parameter mapping, see [Migrating to adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking#migrating-to-adaptive-thinking). To fix the error from its symptom, see [A 400 error says `"thinking.type.enabled"` is not supported](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting#error-thinking-type-enabled).
466464 
467465### Adaptive thinking not supported
468466 
from line 492
494492To turn thinking off on this model, send "thinking": {"type": "between_tools"} instead of {"type": "disabled"}. The model does not think before responding. The short updates it writes between tool calls come back as thinking blocks.
495493```
496494 
497At `xhigh` or `max` [effort](https://platform.claude.com/docs/en/build-with-claude/effort), a request with `between_tools` also returns a 400 `invalid_request_error`. The message says thinking is disabled because `between_tools` has no up-front thinking:
495At `xhigh` or `max` [effort](https://platform.claude.com/docs/en/build-with-claude/effort), a request with `between_tools` also returns a 400 `invalid_request_error`. The error message says thinking is disabled because `between_tools` has no up-front thinking:
498496 
499497```text wrap
500498output_config.effort 'xhigh' is not supported when thinking is disabled on this model. Use effort 'high' or below, or enable thinking.
from line 538
540538 
541539The Claude API returns the same message for any Anthropic-defined tool type that the requested model doesn’t support. Claude Fable 5.2, Claude Mythos 5.2, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5 support computer use through the `computer_toolset_20260801` toolset. Declare `{"type": "computer_toolset_20260801"}` without the beta header and update your agent loop as described in [Migrate from `computer_20251124`](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#migrate-from-computer-20251124). To move from `computer_20250124`, see [Move computer use to the toolset](https://platform.claude.com/docs/en/models/haiku-5-5/migration-guide#computer-use-toolset) in the Claude Haiku 5.5 migration guide.
542540 
543On Amazon Bedrock, Claude Fable 5.2, Claude Mythos 5.2, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5 also accept the `computer_20251124` tool with the `computer-use-2025-11-24` beta header. With Amazon Bedrock’s InvokeModel API, send `computer-use-2025-11-24` in the `anthropic_beta` array of the request body instead of in a header. For that API, see [Claude on Amazon Bedrock (bedrock-runtime)](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy). [Earlier tool versions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#earlier-tool-versions) lists the models to use with each earlier version.
541On Amazon Bedrock, Claude Fable 5.2, Claude Mythos 5.2, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5 also accept the `computer_20251124` tool with the `computer-use-2025-11-24` beta header. With Amazon Bedrock’s InvokeModel API, send `computer-use-2025-11-24` in the `anthropic_beta` array of the request body instead of in a header. For that API, see [Claude on Amazon Bedrock (`bedrock-runtime`)](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy). For the models to use with each earlier version, see [Earlier tool versions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#earlier-tool-versions).
544542 
545543### Thinking block bound to a different conversation
546544 
547This 400 `invalid_request_error` usually means a thinking block you sent back failed the prefix check: something before the block changed after the block was produced, such as the `system` prompt, `tools`, or an earlier message. Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5 run this check. For requests that don’t set `prefix_mismatch_behavior`, whether they get this error depends on the model and the account. See [When `prefix_mismatch_behavior` is unset](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement). The message starts with the position of the first failing block:
545This 400 `invalid_request_error` means a thinking block you sent back failed the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check). Compare `system`, `tools`, and the messages before the block with what you sent when the model produced it. For which changes matter, see [What counts as a change](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#what-counts-as-an-edit). The error message starts with the position of the first failing block:
548546 
549547```text wrap
550548messages.{i}.content.{j}: 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".
551549```
552550 
553Without the `thinking-binding-controls-2026-08-01` beta header, the message also names that header. Resending a history that holds the edit fails the same way, even after you fix the code that made the edit. To continue the conversation, send the beta header with `prefix_mismatch_behavior: "drop_block"` on the retry and on every later request. Alternatively, strip the block the error names and every later `thinking` and `redacted_thinking` block, leave them out of later requests, and retry. On Claude Sonnet 5.5 and Claude Haiku 5.5, `block_binding` works only with `thinking: {"type": "adaptive"}`, so with any other thinking setting, strip the blocks. To stop new conversations from failing, keep the history append-only. A block from a model the target model can’t read is dropped rather than rejected. See [Keeping the prefix unchanged](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check) and the [fix for an invalid thinking block signature](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting#error-thinking-block-signature) in Troubleshooting thinking.
551Resending the same history fails the same way. Fixing the code that made the edit doesn’t help this conversation if the edit is still in its history. To continue, do one of the following:
554552 
553* Send the `thinking-binding-controls-2026-08-01` beta header and set `thinking.block_binding.prefix_mismatch_behavior` to `"drop_block"`, on the retry and on every later request in that conversation. On Claude Sonnet 5.5 and Claude Haiku 5.5, `block_binding` works only with `thinking: {"type": "adaptive"}`.
554* Strip the block the error names and every `thinking` and `redacted_thinking` block after it, in that message and in every later message. Retry, and leave the stripped blocks out of later requests.
555 
556To stop new conversations from failing, [keep the history append-only](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#what-to-check). See the [fix for an invalid thinking block signature](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting#error-thinking-block-signature) in Troubleshooting thinking.
557 
555558Sending `thinking.block_binding` without the `thinking-binding-controls-2026-08-01` [beta header](https://platform.claude.com/docs/en/api/beta-headers) returns a 400 `invalid_request_error` whose message ends in:
556559 
557560```text wrap
from line 561
558561block_binding: Extra inputs are not permitted
559562```
560563 
561Add the header, or remove the field.
564Add the header, turn thinking on, or remove the field.
562565 
563566### Outbound web identity federation disabled (Claude Platform on AWS)
564567 

api/rate-limits Changed · +42 / -22 lines

### Ramp limits

from line 89
8989The rate limits for the Messages API are measured in requests per minute (RPM), input tokens per minute (ITPM), and output tokens per minute (OTPM) for each model class. If you exceed any of the rate limits, you get a [429 error](https://platform.claude.com/docs/en/api/errors) describing which rate limit was exceeded. When the response has a `retry-after` header, wait that many seconds before retrying.
9090 
9191<Note>
92 You might also encounter 429 errors because of acceleration limits on the API if your organization has a sharp increase in usage. To avoid hitting acceleration limits, increase your traffic gradually and maintain consistent usage patterns.
92 A sharp increase in usage can also cause 429 errors. See [Ramp limits](https://platform.claude.com/docs/en/api/rate-limits#ramp-limits).
9393</Note>
9494 
9595### Cache-aware ITPM
from line 185
185185 
186186*<sup>3 Sonnet 4.x rate limit is a total limit that applies to combined traffic across Sonnet 4.6 and Sonnet 4.5 (deprecated; see [Model deprecations](https://platform.claude.com/docs/en/about-claude/model-deprecations)). Claude Sonnet 5.5 and Claude Sonnet 5 each have a separate rate limit and are not part of this combined bucket.</sup>*
187187 
188### Ramp limits
189 
190A ramp limit caps how fast your organization’s token usage on a model can grow. After a sharp increase in usage, requests can return a 429 error even while you’re under your ITPM and OTPM rate limits. A burst of requests within a few seconds can also count as a sharp increase.
191 
192Your ramp limit is your organization’s highest per-minute usage of the model in the recent past, plus a step. Each minute you can go up to a step above that peak, so the limit rises as your successful usage grows. It stops rising at your rate limit. After a period of lower usage, the ramp limit comes back down. The limit never drops below a starting amount, even if you haven’t used the model recently.
193 
194* Ramp limits can apply to any model.
195* Input tokens and output tokens are counted separately.
196* [Fast mode](https://platform.claude.com/docs/en/api/rate-limits#fast-mode-rate-limits) usage has its own ramp limits, separate from standard usage of the same model.
197* As with [cache-aware ITPM](https://platform.claude.com/docs/en/api/rate-limits#cache-aware-itpm), tokens read from the cache don’t count toward a ramp limit. Uncached input tokens and tokens written to the cache do.
198* The step and the starting amount vary by model and can change. The error message usually states your current ramp limit, the step, and your rate limit.
199* The error type is `rate_limit_error`, the same as for a rate limit. On the Messages API, `error.details.error_code` is `ramp_limit_exceeded`. Use it to tell this response apart from a rate limit.
200* The [Message Batches API](https://platform.claude.com/docs/en/api/rate-limits#message-batches-api) isn’t subject to ramp limits.
201 
202If you get a 429 from a ramp limit:
203 
204* Wait at least the number of seconds in the `retry-after` header before retrying.
205* Hold your traffic at a level where requests succeed, then increase it by at most one step per minute.
206* Start scheduled or bulk jobs at a low rate and spread requests evenly, rather than sending everything at once.
207 
188208### Message Batches API
189209 
190210The Message Batches API has its own set of rate limits, which are shared across all models. These include a requests per minute (RPM) limit to all API endpoints and a limit on the number of batch requests that can be in the processing queue at the same time. A “batch request” here refers to part of a Message Batch. You can create a Message Batch containing thousands of batch requests, each of which counts toward this limit. A batch request stays in the processing queue until the model has successfully processed it.
from line 304
284304 
285305The following headers are returned:
286306 
287| Header | Description |
288| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
289| `retry-after` | The number of seconds to wait until you can retry the request. Earlier retries fail. Not every 429 carries it; the spend-cap 429 never does (see [Reaching your spend cap](https://platform.claude.com/docs/en/api/rate-limits#reaching-your-spend-cap)). |
290| `anthropic-ratelimit-requests-limit` | The maximum number of requests allowed within any rate limit period. |
291| `anthropic-ratelimit-requests-remaining` | The number of requests remaining before being rate limited. |
292| `anthropic-ratelimit-requests-reset` | The time when the request rate limit is fully replenished, provided in RFC 3339 format. |
293| `anthropic-ratelimit-tokens-limit` | The maximum number of tokens allowed within any rate limit period. |
294| `anthropic-ratelimit-tokens-remaining` | The number of tokens remaining (rounded to the nearest thousand) before being rate limited. |
295| `anthropic-ratelimit-tokens-reset` | The time when the token rate limit is fully replenished, provided in RFC 3339 format. |
296| `anthropic-ratelimit-input-tokens-limit` | The maximum number of input tokens allowed within any rate limit period. |
297| `anthropic-ratelimit-input-tokens-remaining` | The number of input tokens remaining (rounded to the nearest thousand) before being rate limited. |
298| `anthropic-ratelimit-input-tokens-reset` | The time when the input token rate limit is fully replenished, provided in RFC 3339 format. |
299| `anthropic-ratelimit-output-tokens-limit` | The maximum number of output tokens allowed within any rate limit period. |
300| `anthropic-ratelimit-output-tokens-remaining` | The number of output tokens remaining (rounded to the nearest thousand) before being rate limited. |
301| `anthropic-ratelimit-output-tokens-reset` | The time when the output token rate limit is fully replenished, provided in RFC 3339 format. |
302| `anthropic-priority-input-tokens-limit` | The maximum number of Priority Tier input tokens allowed within any rate limit period. (Priority Tier only) |
303| `anthropic-priority-input-tokens-remaining` | The number of Priority Tier input tokens remaining (rounded to the nearest thousand) before being rate limited. (Priority Tier only) |
304| `anthropic-priority-input-tokens-reset` | The time when the Priority Tier input token rate limit is fully replenished, provided in RFC 3339 format. (Priority Tier only) |
305| `anthropic-priority-output-tokens-limit` | The maximum number of Priority Tier output tokens allowed within any rate limit period. (Priority Tier only) |
306| `anthropic-priority-output-tokens-remaining` | The number of Priority Tier output tokens remaining (rounded to the nearest thousand) before being rate limited. (Priority Tier only) |
307| `anthropic-priority-output-tokens-reset` | The time when the Priority Tier output token rate limit is fully replenished, provided in RFC 3339 format. (Priority Tier only) |
307| Header | Description |
308| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
309| `retry-after` | The number of seconds to wait until you can retry the request. Earlier retries might fail. Not every 429 carries it; the spend-cap 429 never does (see [Reaching your spend cap](https://platform.claude.com/docs/en/api/rate-limits#reaching-your-spend-cap)). |
310| `anthropic-ratelimit-requests-limit` | The maximum number of requests allowed within any rate limit period. |
311| `anthropic-ratelimit-requests-remaining` | The number of requests remaining before being rate limited. |
312| `anthropic-ratelimit-requests-reset` | The time when the request rate limit is fully replenished, provided in RFC 3339 format. |
313| `anthropic-ratelimit-tokens-limit` | The maximum number of tokens allowed within any rate limit period. |
314| `anthropic-ratelimit-tokens-remaining` | The number of tokens remaining (rounded to the nearest thousand) before being rate limited. |
315| `anthropic-ratelimit-tokens-reset` | The time when the token rate limit is fully replenished, provided in RFC 3339 format. |
316| `anthropic-ratelimit-input-tokens-limit` | The maximum number of input tokens allowed within any rate limit period. |
317| `anthropic-ratelimit-input-tokens-remaining` | The number of input tokens remaining (rounded to the nearest thousand) before being rate limited. |
318| `anthropic-ratelimit-input-tokens-reset` | The time when the input token rate limit is fully replenished, provided in RFC 3339 format. |
319| `anthropic-ratelimit-output-tokens-limit` | The maximum number of output tokens allowed within any rate limit period. |
320| `anthropic-ratelimit-output-tokens-remaining` | The number of output tokens remaining (rounded to the nearest thousand) before being rate limited. |
321| `anthropic-ratelimit-output-tokens-reset` | The time when the output token rate limit is fully replenished, provided in RFC 3339 format. |
322| `anthropic-priority-input-tokens-limit` | The maximum number of Priority Tier input tokens allowed within any rate limit period. (Priority Tier only) |
323| `anthropic-priority-input-tokens-remaining` | The number of Priority Tier input tokens remaining (rounded to the nearest thousand) before being rate limited. (Priority Tier only) |
324| `anthropic-priority-input-tokens-reset` | The time when the Priority Tier input token rate limit is fully replenished, provided in RFC 3339 format. (Priority Tier only) |
325| `anthropic-priority-output-tokens-limit` | The maximum number of Priority Tier output tokens allowed within any rate limit period. (Priority Tier only) |
326| `anthropic-priority-output-tokens-remaining` | The number of Priority Tier output tokens remaining (rounded to the nearest thousand) before being rate limited. (Priority Tier only) |
327| `anthropic-priority-output-tokens-reset` | The time when the Priority Tier output token rate limit is fully replenished, provided in RFC 3339 format. (Priority Tier only) |
308328 
309329The `anthropic-ratelimit-tokens-*` headers display the values for the most restrictive limit currently in effect. For instance, if you have exceeded the workspace per-minute token limit, the headers contain the workspace per-minute token rate limit values. If workspace limits do not apply, the headers return the total tokens remaining, where total is the sum of input and output tokens. To see which workspace a request counted against, read the `anthropic-workspace-id` [response header](https://platform.claude.com/docs/en/api/overview#response-headers), which carries the ID of the workspace that your API key or access token resolved to.
310330 

build-with-claude/batch-processing Changed · +18 / -18 lines

from line 40
4040* You want to optimize for cost efficiency
4141* You’re running large-scale evaluations or analyses
4242 
43The Message Batches API is Anthropic’s first implementation of this pattern.
43The Message Batches API implements this pattern.
4444 
4545# Message Batches API
4646 
from line 67
6767 
6868* A Message Batch is limited to either 100,000 Message requests or 256 MB in size, whichever is reached first.
6969* The system processes each batch as fast as possible, with most batches completing within 1 hour. You can access batch results when all messages have completed or after 24 hours, whichever comes first. Batches expire if processing does not complete within 24 hours.
70* Batch results are available for 29 days after creation. After that, you can still view the Batch, but its results will no longer be available for download.
71* Batches are scoped to a [Workspace](https://platform.claude.com/settings/workspaces) in the Claude Console. You may view all batches (and their results) that were created within the Workspace your request runs in.
70* Batch results are available for 29 days after creation. After that, you can still view the batch, but its results are no longer available for download.
71* Batches are scoped to a [Workspace in the Claude Console](https://platform.claude.com/settings/workspaces). You can view all batches (and their results) that were created within the Workspace your request runs in.
7272* Rate limits apply to both Batches API HTTP requests and the number of requests within a batch waiting to be processed. See [Message Batches API rate limits](https://platform.claude.com/docs/en/api/rate-limits#message-batches-api). Additionally, processing might be slowed down based on current demand and your request volume. In that case, you might see more requests expiring after 24 hours.
7373* Because of high throughput and concurrent processing, batches might go slightly over the [spend limit](https://platform.claude.com/docs/en/manage-claude/workspaces#setting-workspace-limits) configured in the Claude Console for your Workspace.
7474* Each batched request must have [`max_tokens`](https://platform.claude.com/docs/en/api/messages/create#create.max_tokens) of at least `1`. `max_tokens: 0` ([cache pre-warming](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#pre-warming-the-cache)) is not supported inside a batch, because an ephemeral cache entry written during batch processing would likely expire before the follow-up request runs.
from line 442
442442<Tip>
443443 **Test your batch requests with the Messages API**
444444 
445 Validation of the `params` object for each message request is performed asynchronously, and validation errors are returned when processing of the entire batch has ended. You can ensure that you are building your input correctly by verifying your request shape with the [Messages API](https://platform.claude.com/docs/en/api/messages/create) first.
445 The API validates the `params` object of each message request asynchronously, and returns validation errors when processing of the entire batch has ended. To check that you build your input correctly, verify your request shape with the [Messages API](https://platform.claude.com/docs/en/api/messages/create) first.
446446</Tip>
447447 
448448When a batch is first created, the response has a processing status of `in_progress`.
from line 622
622622 
623623### Listing all Message Batches
624624 
625You can list all Message Batches in your Workspace using the [list endpoint](https://platform.claude.com/docs/en/api/messages/batches/list). The API supports pagination, automatically fetching additional pages as needed:
625You can list all Message Batches in your Workspace using the [list endpoint](https://platform.claude.com/docs/en/api/messages/batches/list). Results are paginated. The SDK fetches additional pages as needed:
626626 
627627<CodeGroup>
628628 ```bash cURL
from line 730
730730 
731731Once batch processing has ended, each Messages request in the batch has a result. There are four result types:
732732 
733| Result type | Description |
734| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
735| `succeeded` | Request was successful. Includes the message result. |
736| `errored` | Request encountered an error and a message was not created. Possible errors include invalid requests and internal server errors. You will not be billed for these requests. |
737| `canceled` | User canceled the batch before this request could be sent to the model. You will not be billed for these requests. |
738| `expired` | Batch reached its 24-hour expiration before this request could be sent to the model. You will not be billed for these requests. |
733| Result type | Description |
734| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
735| `succeeded` | Request was successful. Includes the message result. |
736| `errored` | Request encountered an error and a message was not created. Possible errors include invalid requests and internal server errors. You aren’t billed for these requests. |
737| `canceled` | User canceled the batch before this request could be sent to the model. You aren’t billed for these requests. |
738| `expired` | Batch reached its 24-hour expiration before this request could be sent to the model. You aren’t billed for these requests. |
739739 
740740The batch’s `request_counts` object counts the requests still processing and the requests with each result type.
741741 
742742(See `message_batch.request_counts` on `messages/batches/retrieve` in [the API reference](https://platform.claude.com/docs/en/api/messages/batches/retrieve#message_batch.request_counts).)
743743 
744Results of the batch are available for download at the [`results_url`](https://platform.claude.com/docs/en/api/messages/batches/retrieve#message_batch.results_url) property on the Message Batch, and if the organization permission allows, in the Console. Because of the potentially large size of the results, it’s recommended to [stream results](https://platform.claude.com/docs/en/api/messages/batches/results) back rather than download them all at once.
744Results of the batch are available for download at the [`results_url`](https://platform.claude.com/docs/en/api/messages/batches/retrieve#message_batch.results_url) property on the Message Batch and, if your organization’s permissions allow, in the Console. Because the results can be large, [stream results](https://platform.claude.com/docs/en/api/messages/batches/results) back rather than download them all at once.
745745 
746746<CodeGroup>
747747 ```bash cURL
from line 958
958958Batch results use the API version of the request that created the batch.
959959 
960960<Tip>
961 **Batch results may not match input order**
961 **Batch results might not match input order**
962962 
963 Batch results can be returned in any order, and may not match the ordering of requests when the batch was created. In the preceding example, the result for the second batch request is returned before the first. To correctly match results with their corresponding requests, always use the `custom_id` field.
963 Batch results can be returned in any order, and might not match the ordering of requests when the batch was created. In the preceding example, the result for the second batch request is returned before the first. To correctly match results with their corresponding requests, always use the `custom_id` field.
964964</Tip>
965965 
966966### Canceling a Message Batch
967967 
968You can cancel a Message Batch that is currently processing using the [cancel endpoint](https://platform.claude.com/docs/en/api/messages/batches/cancel). Immediately after cancellation, a batch’s `processing_status` will be `canceling`. You can use the same polling technique described earlier to wait until cancellation is finalized. Canceled batches end up with a status of `ended` and may contain partial results for requests that were processed before cancellation.
968You can cancel a Message Batch that is currently processing using the [cancel endpoint](https://platform.claude.com/docs/en/api/messages/batches/cancel). Immediately after cancellation, a batch’s `processing_status` is `canceling`. You can use the same polling technique described earlier to wait until cancellation is finalized. Canceled batches end up with a status of `ended` and might contain partial results for requests that were processed before cancellation.
969969 
970970<CodeGroup>
971971 ```bash cURL
from line 1582
15821582The `output-300k-2026-03-24` beta header raises the `max_tokens` cap to 300,000 for batch requests using Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 5.5, Claude Sonnet 5, Claude Sonnet 4.6, or Claude Haiku 5.5. Include the header to generate outputs far longer than the standard 128k `max_tokens` limit in a single turn.
15831583 
15841584<Note>
1585 Extended output is available on the Message Batches API only, not the synchronous Messages API. It is supported on the Claude API and Claude Platform on AWS, and is not currently available on Amazon Bedrock, Claude Models on Google Cloud (Google managed), or Microsoft Foundry.
1585 Extended output is available on the Message Batches API only, not the synchronous Messages API. It is available on the Claude API and Claude Platform on AWS.
15861586</Note>
15871587 
15881588Use extended output for long-form generation such as book-length drafts and technical documentation, exhaustive structured data extraction, large code-generation scaffolds, and long reasoning chains.
from line 1831
18311831* Verify that the total batch request size doesn’t exceed 256 MB. If the request size is too large, you might get a 413 `request_too_large` error.
18321832* Check that you’re using [supported models](https://platform.claude.com/docs/en/build-with-claude/batch-processing#supported-models) for all requests in the batch.
18331833* Ensure each request in the batch has a unique `custom_id`.
1834* Ensure that it has been less than 29 days since batch `created_at` (not processing `ended_at`) time. If over 29 days have passed, results will no longer be viewable.
1834* Ensure that it has been less than 29 days since batch `created_at` (not processing `ended_at`) time. After 29 days, results are no longer available for download.
18351835* Confirm that the batch has not been canceled.
18361836 
18371837Note that the failure of one request in a batch does not affect the processing of other requests.

build-with-claude/cache-diagnostics Changed · +104 / -71 lines

from line 194
194194 ```
195195 
196196 ```csharp C#
197 using Anthropic.Models.Beta;
198 using Anthropic.Models.Beta.Messages;
199 using Messages = Anthropic.Models.Messages;
200 
197201 AnthropicClient client = new();
198202 
199203 var system = "You are an AI assistant analyzing a large document. <document>...</document>";
from line 295
291295 ```
292296 
293297 ```java Java
294 var client = AnthropicOkHttpClient.fromEnv();
298 import com.anthropic.models.beta.messages.BetaCacheControlEphemeral;
299 import com.anthropic.models.beta.messages.BetaDiagnosticsParam;
300 import com.anthropic.models.beta.messages.MessageCreateParams;
301 import com.anthropic.models.messages.Model;
295302 
296 var system = "You are an AI assistant analyzing a large document. <document>...</document>";
303 void main() {
304 var client = AnthropicOkHttpClient.fromEnv();
297305 
298 var r1 = client.beta().messages().create(
299 MessageCreateParams.builder()
300 .model(Model.CLAUDE_OPUS_5_5)
301 .maxTokens(1024)
302 .cacheControl(BetaCacheControlEphemeral.builder().build())
303 .system(system)
304 .addUserMessage("Summarize section 1.")
305 // Pass null on the first turn to opt in without a prior message to compare.
306 .diagnostics(BetaDiagnosticsParam.builder().previousMessageId((String) null).build())
307 .build()
308 );
306 var system = "You are an AI assistant analyzing a large document. <document>...</document>";
309307 
310 var r2 = client.beta().messages().create(
311 MessageCreateParams.builder()
312 .model(Model.CLAUDE_OPUS_5_5)
313 .maxTokens(1024)
314 .cacheControl(BetaCacheControlEphemeral.builder().build())
315 .system(system)
316 .addUserMessage("Summarize section 1.")
317 .addMessage(r1)
318 .addUserMessage("Now summarize section 2.")
319 .diagnostics(BetaDiagnosticsParam.builder().previousMessageId(r1.id()).build())
320 .build()
321 );
308 var r1 = client.beta().messages().create(
309 MessageCreateParams.builder()
310 .model(Model.CLAUDE_OPUS_5_5)
311 .maxTokens(1024)
312 .cacheControl(BetaCacheControlEphemeral.builder().build())
313 .system(system)
314 .addUserMessage("Summarize section 1.")
315 // Pass null on the first turn to opt in without a prior message to compare.
316 .diagnostics(BetaDiagnosticsParam.builder().previousMessageId((String) null).build())
317 .build()
318 );
322319 
323 if (r2.diagnostics().isEmpty()) {
324 IO.println("No divergence detected.");
325 } else if (r2.diagnostics().get().cacheMissReason().isEmpty()) {
326 IO.println("Comparison still pending.");
327 } else {
328 var reason = r2.diagnostics().get().cacheMissReason().get();
329 IO.println("cache_miss_reason: " + reason.type().asString());
320 var r2 = client.beta().messages().create(
321 MessageCreateParams.builder()
322 .model(Model.CLAUDE_OPUS_5_5)
323 .maxTokens(1024)
324 .cacheControl(BetaCacheControlEphemeral.builder().build())
325 .system(system)
326 .addUserMessage("Summarize section 1.")
327 .addMessage(r1)
328 .addUserMessage("Now summarize section 2.")
329 .diagnostics(BetaDiagnosticsParam.builder().previousMessageId(r1.id()).build())
330 .build()
331 );
332 
333 if (r2.diagnostics().isEmpty()) {
334 IO.println("No divergence detected.");
335 } else if (r2.diagnostics().get().cacheMissReason().isEmpty()) {
336 IO.println("Comparison still pending.");
337 } else {
338 var reason = r2.diagnostics().get().cacheMissReason().get();
339 IO.println("cache_miss_reason: " + reason.type().asString());
340 }
330341 }
331342 ```
332343 
333344 ```php PHP
345 use Anthropic\Beta\Messages\BetaCacheControlEphemeral;
346 use Anthropic\Beta\Messages\BetaDiagnosticsParam;
347 use Anthropic\Messages\Model;
348 
334349 $client = new Client();
335350 
336351 $system = 'You are an AI assistant analyzing a large document. <document>...</document>';
from line 772
757772 ```
758773 
759774 ```typescript TypeScript
775 import type { BetaMessage, BetaMessageParam } from "@anthropic-ai/sdk/resources/beta";
776 
760777 const client = new Anthropic();
761778 
762779 const SYSTEM = "You are an AI assistant analyzing a large document. <document>...</document>";
from line 807
790807 ```
791808 
792809 ```csharp C#
810 using Anthropic.Models.Beta;
811 using Anthropic.Models.Beta.Messages;
812 using Messages = Anthropic.Models.Messages;
813 
793814 AnthropicClient client = new();
794815 
795816 var system = "You are an AI assistant analyzing a large document. <document>...</document>";
from line 890
869890 ```
870891 
871892 ```java Java
872 var client = AnthropicOkHttpClient.fromEnv();
893 import com.anthropic.models.beta.messages.BetaCacheControlEphemeral;
894 import com.anthropic.models.beta.messages.BetaDiagnosticsParam;
895 import com.anthropic.models.beta.messages.BetaMessageParam;
896 import com.anthropic.models.beta.messages.MessageCreateParams;
897 import com.anthropic.models.messages.Model;
873898 
874 var system = "You are an AI assistant analyzing a large document. <document>...</document>";
875 var prompts = List.of("Summarize section 1.", "Now section 2.", "Now section 3.");
899 void main() {
900 var client = AnthropicOkHttpClient.fromEnv();
876901 
877 var messages = new ArrayList<BetaMessageParam>();
878 String prevId = null;
902 var system = "You are an AI assistant analyzing a large document. <document>...</document>";
903 var prompts = List.of("Summarize section 1.", "Now section 2.", "Now section 3.");
879904 
880 for (var turn = 0; turn < prompts.size(); turn++) {
881 messages.add(BetaMessageParam.ofUser(prompts.get(turn)));
905 var messages = new ArrayList<BetaMessageParam>();
906 String prevId = null;
882907 
883 var response = client.beta().messages().create(
884 MessageCreateParams.builder()
885 .model(Model.CLAUDE_OPUS_5_5)
886 .maxTokens(1024)
887 .cacheControl(BetaCacheControlEphemeral.builder().build())
888 .system(system)
889 .messages(messages)
890 .diagnostics(BetaDiagnosticsParam.builder().previousMessageId(prevId).build())
891 .build()
892 );
908 for (var turn = 0; turn < prompts.size(); turn++) {
909 messages.add(BetaMessageParam.ofUser(prompts.get(turn)));
893910 
894 if (response.diagnostics().isPresent() && response.diagnostics().get().cacheMissReason().isPresent()) {
895 var reason = response.diagnostics().get().cacheMissReason().get();
896 IO.println("Turn " + (turn + 1) + " cache_miss_reason: " + reason.type().asString());
897 }
911 var response = client.beta().messages().create(
912 MessageCreateParams.builder()
913 .model(Model.CLAUDE_OPUS_5_5)
914 .maxTokens(1024)
915 .cacheControl(BetaCacheControlEphemeral.builder().build())
916 .system(system)
917 .messages(messages)
918 .diagnostics(BetaDiagnosticsParam.builder().previousMessageId(prevId).build())
919 .build()
920 );
898921 
899 messages.add(response.toParam());
900 prevId = response.id();
922 if (response.diagnostics().isPresent() && response.diagnostics().get().cacheMissReason().isPresent()) {
923 var reason = response.diagnostics().get().cacheMissReason().get();
924 IO.println("Turn " + (turn + 1) + " cache_miss_reason: " + reason.type().asString());
925 }
926 
927 messages.add(response.toParam());
928 prevId = response.id();
929 }
901930 }
902931 ```
903932 
904933 ```php PHP
934 use Anthropic\Beta\Messages\BetaCacheControlEphemeral;
935 use Anthropic\Beta\Messages\BetaDiagnosticsParam;
936 use Anthropic\Messages\Model;
937 
905938 $client = new Client();
906939 
907940 $system = 'You are an AI assistant analyzing a large document. <document>...</document>';
from line 1000
9671000 
9681001| Value | Meaning |
9691002| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
970| `null` | The request did not include the `diagnostics` object, `previous_message_id` was `null` (first turn, nothing to compare), or a comparison ran and found no divergence. |
1003| `null` | The request did not include the `diagnostics` object, `previous_message_id` was `null` (first turn, nothing to compare), or nothing diverged before the last breakpoint. |
9711004| `{"cache_miss_reason": null}` | The comparison was still running when the response was serialized. This can occur when the response starts very quickly. Treat it as inconclusive and check the next turn. |
9721005| `{"cache_miss_reason": {...}}` | A `cache_miss_reason` is attached. For `*_changed` types this identifies the first divergence point; `previous_message_not_found` and `unavailable` are cases where no comparison was produced. |
9731006 
from line 1050
10171050 
10181051This matrix applies to turns where you passed a real `previous_message_id`. On the first turn (`previous_message_id: null`), `diagnostics` is always `null` and `cache_read_input_tokens` is normally zero because the cache is being written, not read; no troubleshooting is needed. The matrix also does not apply when `cache_miss_reason` is `null` (the comparison is still pending; check the next turn) or when its `type` is `previous_message_not_found` or `unavailable` (no comparison was produced).
10191052 
1020| Diagnostics result | Cache read tokens | Interpretation |
1021| ----------------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1022| `null` | high | Working as expected. Your prefix is stable and the cache hit. |
1023| `null` | low or zero | Your requests match but the cache entry was no longer available. Consider shortening gaps between turns or using the [1-hour cache TTL](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#1-hour-cache-duration). |
1024| `cache_miss_reason` is a `*_changed` type | low or zero | The request changed; fix the cause indicated by `type`. |
1025| `cache_miss_reason` is a `*_changed` type | high | Rare. A change occurred late in the prompt but an earlier `cache_control` breakpoint still hit. Worth fixing, but low impact. |
1053| Diagnostics result | Cache read tokens | Interpretation |
1054| ----------------------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1055| `null` | high | The cache hit. |
1056| `null` | low or zero | Your requests match, but there was no cache entry to read: it had expired, or the prompt is shorter than the [minimum cacheable length](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#cache-limitations). |
1057| `cache_miss_reason` is a `*_changed` type | low or zero | The request changed; fix the cause indicated by `type`. |
1058| `cache_miss_reason` is a `*_changed` type | high | Rare. A change occurred late in the prompt but an earlier `cache_control` breakpoint still hit. Worth fixing, but low impact. |
10261059 
10271060## Limitations
10281061 

build-with-claude/compaction-on-demand Changed · +21 / -18 lines

from line 344
344344The API puts the summary where the block stands and passes every later message to Claude unchanged. Follow these rules:
345345 
346346* Put the block first in `messages`, either as an `assistant` message of its own or as the first content block of the first message, whether that is a `user` or `assistant` message.
347* Remove the summarized messages. If any remain in front of the block, the request returns a 400 error (`compaction_block_misplaced`).
348* Send exactly one `compaction` block in each request, on every later request.
347* Remove exactly the summarized messages. If any remain in front of the block, the request returns a 400 error (`compaction_block_misplaced`).
348* Send exactly one `compaction` block on every later request.
349349 
350350<Warning>
351351 Two mistakes in the swap can pass without an error:
from line 352
352352 
353353 * **The block is left out of a later request:** Claude gets no summary.
354354 * **Summarized messages stay after the block:** the API sends them to Claude again.
355 
356 On models with [preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking), either mistake can also make thinking blocks in the request fail the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check).
357355</Warning>
358356 
357On [models with preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes), each also [invalidates thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#mismatch-behavior):
358 
359* **Block left out:** thinking since the swap, and earlier thinking unless you resend the full history.
360* **Summarized messages left in:** thinking already in them and after them.
361 
359362Threshold compaction works the other way around: its block follows the messages it summarizes, and the API drops them for you. See [Passing compaction blocks back](https://platform.claude.com/docs/en/build-with-claude/compaction-threshold#passing-compaction-blocks-back).
360363 
361If you keep turns after the block and send their thinking blocks back, the conditions that keep that thinking valid are on [Compaction and preserved thinking](https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks).
364For kept turns, see [Conditions for kept thinking to stay valid](https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid).
362365 
363366### Compact again
364367 
from line 779
776779 
777780The SDK [tool runner](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-runner) can send the compaction request for you. When you decide to compact, call `compact_before_next_turn()` (ruby: `compact_before_next_turn`; typescript, java, php: `compactBeforeNextTurn()`; csharp, go: `CompactBeforeNextTurn()`) on the runner. Once the current turn and its tool calls complete, the runner sends the compaction request and replaces its history with the returned message. Create the runner with the `compact-2026-09-04` beta, because the runner doesn’t add it.
778781 
779The runner builds the compaction request from its own parameters and leaves `context_management` out. It also leaves out `stop_sequences`, a `tool_choice` of type `any` or `tool`, and a structured-output `output_config.format`, which the API rejects on a compaction request. [Request a summary](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#request-a-summary) explains why. The runner sends them again on its later requests. SDK versions before Python 1.8.0, TypeScript 0.128.0, C# 12.50.0, Go 1.75.0, and Java 2.65.0 send them on the compaction request too. On those versions, a runner that sets any of these parameters gets a 400 error. The runner sends a [task budget](https://platform.claude.com/docs/en/build-with-claude/task-budgets) unchanged. If `output_config.task_budget` sets `remaining`, the compaction request returns a 400 error, so leave `remaining` unset, as [Limits and interactions with other features](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#how-it-fits-with-the-rest-of-the-api) says. The runner refuses to compact while its `context_management` has a compaction edit, so use one kind of compaction on a runner.
782The runner builds the compaction request from its own parameters and leaves `context_management` out. It also leaves out `stop_sequences`, a `tool_choice` of type `any` or `tool`, and a structured-output `output_config.format`, which the API rejects on a compaction request. [Request a summary](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#request-a-summary) explains why. The runner sends them again on its later requests. SDK versions before Python 1.8.0, TypeScript 0.128.0, C# 12.50.0, Go 1.75.0, and Java 2.65.0 send them on the compaction request too. On those versions, a runner that sets any of these parameters gets a 400 error. The runner sends a [task budget](https://platform.claude.com/docs/en/build-with-claude/task-budgets) unchanged. If `output_config.task_budget` sets `remaining`, the compaction request returns a 400 error, so leave `remaining` unset (see [Limits and interactions with other features](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#how-it-fits-with-the-rest-of-the-api)). The runner can’t compact while its `context_management` has a compaction edit, so use one kind of compaction on a runner.
780783 
781784### When to compact
782785 
from line 822
819822 
820823A compaction request, or a request that carries a block, can also fail outright. Most 400 errors have a message that says what to remove or resend. Some also carry an `error.details.error_code` that starts with `compaction_`. Parameter errors, such as a field that can’t be combined with `compaction`, carry the message only.
821824 
822| Error | Cause | What to do |
823| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
824| 529 `overloaded_error`, `error.details.error_code` `compaction_unavailable` | A transient server problem while producing a block, or while reading one you sent back. | Retry the request. |
825| 400 `compaction_block_misplaced` | Summarized messages remain in front of the block. | Remove them, so the block comes first in `messages`. |
826| 400 `compaction_signature_invalid` or `compaction_content_mismatch` | The block’s `signature` or `content` was changed after the API returned it. | Send the block exactly as returned, including its `signature`. |
827| 400 | The request carries more than one `compaction` block. | Send exactly one, the newest. |
828| 400 | The last `assistant` turn ends in a tool call with no result yet. | Send that turn’s tool results, then compact. |
829| 400 `compaction_nothing_to_summarize` | `messages` has no `user` or `assistant` content, for example an empty list. | Send at least one `user` or `assistant` message. |
830| 400 with a message that a thinking block is `bound to a different conversation` | On a model with preserved thinking, a thinking block in the compaction request failed the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check). | [Handle the error](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#handle-the-error-in-code), then compact. |
831| 400 on the compaction request, with a message that says the `compaction` parameter `requires anthropic-beta: compact-2026-09-04` | The compaction request left out the beta header. | Add the beta header; see [Request a summary](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#request-a-summary). |
832| 400 on a later request that carries the block: a validation error that says `compaction` is not one of the expected content block types. The message doesn’t mention the header. | That request left out the beta header. | Add the beta header to every request that carries the block; see [Request a summary](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#request-a-summary). |
833| 400 validation error, such as `messages.0.content.0.compaction.citations: Extra inputs are not permitted` | A block was sent back with fields the API didn’t return, such as `citations: null`. | Send the block exactly as returned; see [Continue from the summary](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#continue-from-the-summary). |
825| Error | Cause | What to do |
826| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
827| 529 `overloaded_error`, `error.details.error_code` `compaction_unavailable` | A transient server problem while producing a block, or while reading one you sent back. | Retry the request. |
828| 400 `compaction_block_misplaced` | Summarized messages remain in front of the block. | Remove them, so the block comes first in `messages`. |
829| 400 `compaction_signature_invalid` or `compaction_content_mismatch` | The block’s `signature` or `content` was changed after the API returned it. | Send the block exactly as returned, including its `signature`. |
830| 400 | The request carries more than one `compaction` block. | Send exactly one, the newest. |
831| 400 | The last `assistant` turn ends in a tool call with no result yet. | Send that turn’s tool results, then compact. |
832| 400 `compaction_nothing_to_summarize` | `messages` has no `user` or `assistant` content, for example an empty list. | Send at least one `user` or `assistant` message. |
833| 400 with a message that a thinking block is `bound to a different conversation` | On a [model with preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes), a thinking block in the compaction request failed the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check). | [Handle the error in code](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#handle-the-error-in-code), then compact. |
834| 400 on the compaction request, with a message that says the `compaction` parameter `requires anthropic-beta: compact-2026-09-04` | The compaction request left out the beta header. | Add the beta header; see [Request a summary](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#request-a-summary). |
835| 400 on a later request that carries the block: a validation error that says `compaction` is not one of the expected content block types. The message doesn’t mention the header. | That request left out the beta header. | Add the beta header to every request that carries the block; see [Request a summary](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#request-a-summary). |
836| 400 validation error, such as `messages.0.content.0.compaction.citations: Extra inputs are not permitted` | A block was sent back with fields the API didn’t return, such as `citations: null`. | Send the block exactly as returned; see [Continue from the summary](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#continue-from-the-summary). |
834837 
835838## Count compaction usage
836839 

build-with-claude/compaction-thinking-blocks Changed · +43 / -41 lines

## When your code writes the summary

from line 1
11---
22title: Compaction and preserved thinking
33url: https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks
4description: When thinking blocks in turns kept after on-demand compaction stay valid on models with preserved thinking, and how to check.
4description: When thinking in turns kept after compaction, or after your own summary or cut, stays valid on models with preserved thinking, and how to check.
55featureMetadata:
66 status: beta
77 betaHeader: compact-2026-09-04
from line 29
2929 Microsoft Foundry: beta
3030---
3131 
32Skip this page unless you send thinking blocks back to a model with [preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking) and keep turns after the compaction block. Kept turns are the turns that follow the block. They’re either recent turns you left out of the compaction request, as in [Compaction that keeps recent turns](https://platform.claude.com/docs/en/build-with-claude/compaction-keep-recent-turns), or turns that arrived while the API was writing the summary, as in [Compaction in the background](https://platform.claude.com/docs/en/build-with-claude/compaction-background).
32Skip this page unless you send thinking blocks back to a model with [preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking) and keep turns after the compaction block, or after your own summary or cut. Kept turns are the turns that follow the block. They’re either recent turns you left out of the compaction request, as in [Compaction that keeps recent turns](https://platform.claude.com/docs/en/build-with-claude/compaction-keep-recent-turns), or turns that arrived while the API was writing the summary, as in [Compaction in the background](https://platform.claude.com/docs/en/build-with-claude/compaction-background).
3333 
34Models with preserved thinking check earlier thinking blocks against the conversation that produced them. A summary replaces part of that conversation, but the check accepts the swap when the API wrote the summary, so the thinking in kept turns can stay valid.
34Models with preserved thinking check earlier thinking blocks against the conversation that produced them. A summary replaces part of that conversation, but the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check) accepts the swap when the API wrote the summary, so the thinking in kept turns can stay valid.
3535 
3636## Conditions for kept thinking to stay valid
3737 
3838The thinking blocks in kept turns stay valid while all of these hold:
3939 
40* **The compaction request runs on a model with preserved thinking.** This condition covers every compaction request since a thinking block was produced, not only the most recent one. One way to meet it is to send every compaction request to the model the conversation uses.
41* **The kept turns directly follow the summarized messages, and you send them unchanged.** Send each kept message exactly as it is in your history. Don’t skip or add a message between the last summarized message and the first kept one. The first kept message must also have a different role from the last summarized message, and it can’t be a mid-conversation `role: "system"` message. Otherwise, the API merges it into the last summarized message. One way to get the first kept message right is to compact exactly the `messages` of a request you already sent. The kept turns then start with Claude’s reply to it.
42* **`system` and `tools` don’t change.** They are the same on the compaction request as on the requests that produced the kept thinking, and they stay the same on the requests that follow. The exception is a tool marked `defer_loading: true` that nothing in the conversation has referenced. [Change the system prompt or tools](https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks#change-the-system-prompt-or-tools) covers how to change them safely.
40* **The compaction request runs on a model with preserved thinking.** This condition covers every compaction request since a thinking block was produced, not only the latest. One way to meet it is to send every compaction request to the model the conversation uses.
41* **The kept turns directly follow the summarized messages, and you send them unchanged.** Send each kept message exactly as it is in your history, and don’t send summarized messages again. Don’t skip or add a message between the last summarized message and the first kept one. The first kept message must also have a different role from the last summarized message, and it can’t be a mid-conversation `role: "system"` message. Otherwise, the API merges it into the last summarized message. One way to get the first kept message right is to compact exactly the `messages` of a request you already sent. The kept turns then start with Claude’s reply to it.
42* **`system` and `tools` don’t change.** They are the same on the compaction request as on the requests that produced the kept thinking, and they stay the same on the requests that follow. The exception is a tool marked `defer_loading: true` that nothing has referenced. To change them safely, see [Change the system prompt or tools](https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks#change-the-system-prompt-or-tools).
4343 
44If a condition doesn’t hold, the API still accepts the compaction block on later requests. What fails is the kept thinking, on the first later request that sends it. The compaction request runs the same check on the thinking blocks it carries, so a changed `system` or `tools`, or an edited message, can fail that request too. [What the API does with an invalid block](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#mismatch-behavior) describes what happens then, and [When `prefix_mismatch_behavior` is unset](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement) covers requests that don’t set the field, including Message Batches items.
44If a condition doesn’t hold, the API still accepts the compaction block on later requests. What fails is the kept thinking, on the first later request that sends it. The compaction request runs the prefix check on the thinking blocks it carries, so a changed `system` or `tools`, or an edited message, can fail that request too. For what happens then, see [Set `prefix_mismatch_behavior`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#preserved-thinking-controls).
4545 
4646## Compact again without breaking older thinking
4747 
4848You can [compact again](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#compact-again) and keep turns: the new block covers the old summary and every message that follows it in the compaction request, and any turns you leave out of that request are kept turns of the new block.
4949 
50The first of the [conditions for kept thinking](https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) counts every compaction since a thinking block was produced, so a turn that you keep through two compactions needs both to have run on a model with preserved thinking.
50For a turn’s thinking to stay valid through two compactions, both must have run on a model with preserved thinking.
5151 
5252Compactions from before a thinking block was produced don’t count against it. Thinking produced after a block is in place is bound to that block, and it stays valid through later compactions that meet the conditions.
5353 
5454## Change the system prompt or tools
5555 
56A later request can use a different `system`, different `tools`, or a different model from the compaction request, and the API still accepts the block. Such a change can invalidate the thinking in the kept turns, but it has no other effect.
56A later request can use another `system`, `tools`, or model that supports on-demand compaction, and the API still accepts the block. The change can invalidate the kept thinking.
5757 
5858To change `system` or `tools` without invalidating any kept thinking, compact the whole conversation first, so no turns are kept. Then change them on the next request.
5959 
60To add an instruction or change the available tools without touching `system` or `tools`, append the change to `messages`, as described in [Make changes without editing the prefix](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#replace-prefix-edits).
60To add an instruction or change the available tools without touching `system` or `tools`, append the change to `messages`, as described in [Change tools or instructions without failing the prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions).
6161 
62The summarized turns can include mid-conversation system messages, which are `role: "system"` entries in `messages` (see [Mid-conversation system messages and tool changes](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages)). They’re summarized with the rest. What happens next depends on what a message carried:
62The summarized turns can include mid-conversation system messages, which are `role: "system"` entries in `messages`. They’re summarized with the rest, so their text instructions and [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) levels stop applying (see [Limits and interactions with other features](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#how-it-fits-with-the-rest-of-the-api)). Their tool changes can carry over:
6363 
64* **Text instructions** stop applying.
65* **A [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) level** stops applying too. Turns then run at the request’s top-level `output_config.effort`. If the request sets none, they run at the model’s default. A later message can set a level again.
66* **Tool changes** can carry over. See the steps that follow.
67 
68To carry tool changes over:
69 
70641. Send the `inline-tools-2026-09-15` beta header on the compaction request. The returned block then records the changes in a `tool_changes` field.
712. Send the block back unmodified. The API then applies the recorded changes on each request that includes the block. If the field is missing, the API accepts the block but applies nothing.
652. Send the block back unmodified. The API then applies the recorded changes on each request that includes the block. If the field is missing, the API accepts the block but applies nothing, so state the changes again.
72663. Send the same header on every request that includes the block.
7367 
74If the summarized turns changed your tools and the returned block has no `tool_changes` field, the changes weren’t recorded. State them again, as described next.
68You can state an instruction, an effort level, or a tool change again. Put it in a `role: "system"` message directly after the new `user` message of your next request. The request’s `messages` then run in this order:
7569 
76You can state an instruction, an effort level, or a tool change again. Put it in a `role: "system"` message at the end of your next request, directly after the `user` message. The request’s `messages` then run in this order:
77 
78701. The compaction block.
79712. The kept turns, if any.
80723. Your `user` message.
81734. The `role: "system"` message.
8274 
83On later requests, leave those entries as they are, and add new turns after the system message.
75On later requests, leave those entries as they are, and add new turns after the system message. Don’t put the system message before or between the kept turns, where it invalidates every kept thinking block after it.
8476 
85Don’t put the system message before or between the kept turns. There, it invalidates every kept thinking block that comes after it.
77## When your code writes the summary
8678 
79This section applies wherever the [prefix check runs](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#enforcement), with or without on-demand compaction.
80 
81If your code writes the summary, the thinking in turns you keep after it fails the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check), because your summary replaced the messages that thinking came after. To keep that thinking, have the API write the summary.
82 
83The same goes for turns you keep by [pausing after compaction](https://platform.claude.com/docs/en/build-with-claude/compaction-threshold#pausing-after-compaction) at a token threshold, turns Claude produced while your code summarized in the background, and turns after a cut.
84 
85Remove those turns’ `thinking` and [`redacted_thinking`](https://platform.claude.com/docs/en/build-with-claude/thinking#redacted-thinking-blocks) blocks and keep their other blocks, or send [`"drop_block"`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#preserved-thinking-controls) on every request that includes them. Either way, Claude reads those turns without that thinking, and [output tokens can increase](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#drop-block-cost).
86 
87If you send only your summary and the next instruction, as one user message, no earlier thinking is sent, and later thinking is valid.
88 
8789## Check that the kept thinking held
8890 
8991The compaction response doesn’t say whether the kept thinking holds. The first request after the swap does. To check in your tests:
9092 
911. Have a short conversation with thinking on. Use a model that runs the prefix check (see [Keeping the prefix unchanged](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check)), and use it for every step, because a model that can’t read a thinking block drops it with no error.
931. Have a short conversation with thinking on. Use a [model that runs the prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#enforcement), and use it for every step, because a model that can’t read a thinking block drops it with no error.
92942. Compact the older turns, and keep at least one turn that holds a thinking block.
93953. Send the next request, with the block first, then the kept turn, then a new `user` message, and with `thinking.block_binding.prefix_mismatch_behavior` set to `"error"`.
944. Read the result. A 200 response whose `input_transformations` array is empty means no thinking block failed the check or was dropped. A 400 error that says the block is bound to a different conversation means one did. The message starts with the path of the first block that failed, and [What the API does with an invalid block](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#mismatch-behavior) shows it in full.
964. Read the result. A 200 response whose `input_transformations` array is empty means no thinking block failed the prefix check or was dropped. A [400 error](https://platform.claude.com/docs/en/api/errors#thinking-block-conversation-mismatch) that says the block is bound to a different conversation means one did. The message starts with the path of the first block that failed, as [Error: The block is bound to a different conversation](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#prefix-mismatch-error) shows.
9597 
96The `prefix_mismatch_behavior` field needs the `thinking-binding-controls-2026-08-01` beta header in addition to the [`compact-2026-09-04` beta header](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#request-a-summary). The value a request sets applies on any account.
98The `prefix_mismatch_behavior` setting needs the `thinking-binding-controls-2026-08-01` beta header in addition to the [`compact-2026-09-04` beta header](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#request-a-summary).
9799 
98100The following program runs the four steps. It prints how many thinking blocks the kept turn holds and how many entries `input_transformations` has; no entries means the kept thinking held:
99101 
from line 117
115117 MODEL = "claude-fable-5-1"
116118 BETAS = ["compact-2026-09-04", "thinking-binding-controls-2026-08-01"]
117119 SYSTEM = "You help plan a recipe app's release. Keep answers short."
118 # With "error", a thinking block that fails the check makes the request fail with a 400.
120 # With "error", a thinking block that fails the prefix check makes the request fail with a 400.
119121 THINKING: BetaThinkingConfigParam = {
120122 "type": "adaptive",
121123 "block_binding": {"prefix_mismatch_behavior": "error"},
from line 196
194196 "thinking-binding-controls-2026-08-01"
195197 ];
196198 const systemPrompt = "You help plan a recipe app's release. Keep answers short.";
197 // With "error", a thinking block that fails the check makes the request fail with a 400.
199 // With "error", a thinking block that fails the prefix check makes the request fail with a 400.
198200 const thinking: Anthropic.Beta.Messages.BetaThinkingConfigParam = {
199201 type: "adaptive",
200202 block_binding: { prefix_mismatch_behavior: "error" }
from line 278
276278 const Model ModelId = Model.ClaudeFable5_1;
277279 AnthropicBeta[] betas = [AnthropicBeta.Compact2026_09_04, AnthropicBeta.ThinkingBindingControls2026_08_01];
278280 const string SystemPrompt = "You help plan a recipe app's release. Keep answers short.";
279 // With "error", a thinking block that fails the check makes the request fail with a 400.
281 // With "error", a thinking block that fails the prefix check makes the request fail with a 400.
280282 BetaThinkingConfigAdaptive thinking = new()
281283 {
282284 BlockBinding = new() { PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.Error },
from line 376
374376 anthropic.AnthropicBetaThinkingBindingControls2026_08_01,
375377 }
376378 system := []anthropic.BetaTextBlockParam{{Text: "You help plan a recipe app's release. Keep answers short."}}
377 // With "error", a thinking block that fails the check makes the request fail with a 400.
379 // With "error", a thinking block that fails the prefix check makes the request fail with a 400.
378380 thinking := anthropic.BetaThinkingConfigParamUnion{
379381 OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
380382 BlockBinding: anthropic.BetaThinkingBlockBindingParam{
from line 483
481483 AnthropicBeta.THINKING_BINDING_CONTROLS_2026_08_01
482484 );
483485 static final String SYSTEM = "You help plan a recipe app's release. Keep answers short.";
484 // With "error", a thinking block that fails the check makes the request fail with a 400.
486 // With "error", a thinking block that fails the prefix check makes the request fail with a 400.
485487 static final BetaThinkingConfigAdaptive THINKING = BetaThinkingConfigAdaptive.builder()
486488 .blockBinding(BetaThinkingBlockBinding.builder()
487489 .prefixMismatchBehavior(BetaThinkingPrefixMismatchBehavior.ERROR)
from line 573
571573 const MODEL = Model::CLAUDE_FABLE_5_1;
572574 const BETAS = [AnthropicBeta::COMPACT_2026_09_04, AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01];
573575 const SYSTEM = "You help plan a recipe app's release. Keep answers short.";
574 // With "error", a thinking block that fails the check makes the request fail with a 400.
576 // With "error", a thinking block that fails the prefix check makes the request fail with a 400.
575577 $thinking = BetaThinkingConfigAdaptive::with(
576578 blockBinding: BetaThinkingBlockBinding::with(
577579 prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::ERROR,
from line 639
637639 );
638640 
639641 // 4. A 200 with no dropped blocks means the kept thinking held.
640 printf("Dropped thinking blocks: %d\n", count($third->inputTransformations));
642 printf("Dropped thinking blocks: %d\n", count($third->inputTransformations ?? []));
641643 ```
642644 
643645 ```ruby Ruby
from line 652
650652 Anthropic::AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01
651653 ]
652654 SYSTEM = "You help plan a recipe app's release. Keep answers short."
653 # With "error", a thinking block that fails the check makes the request fail with a 400.
655 # With "error", a thinking block that fails the prefix check makes the request fail with a 400.
654656 THINKING = Anthropic::Beta::BetaThinkingConfigAdaptive.new(
655657 block_binding: Anthropic::Beta::BetaThinkingBlockBinding.new(
656658 prefix_mismatch_behavior: Anthropic::Beta::BetaThinkingPrefixMismatchBehavior::ERROR
from line 716
714716 )
715717 
716718 # 4. A 200 with no dropped blocks means the kept thinking held.
717 puts "Dropped thinking blocks: #{third.input_transformations.length}"
719 puts "Dropped thinking blocks: #{(third.input_transformations || []).length}"
718720 ```
719721</CodeGroup>
720722 
from line 725
723725Dropped thinking blocks: 0
724726```
725727 
726In production, `"drop_block"` keeps requests succeeding when a condition doesn’t hold. The response lists each dropped block in `input_transformations` with `reason: "prefix_binding_mismatch"`. An entry whose `path` falls in a kept turn means a condition didn’t hold for that turn’s thinking. [What the API does with an invalid block](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#mismatch-behavior) describes what is dropped and says how to alert on it. On Claude Sonnet 5.5 and Claude Haiku 5.5, `block_binding` works only with `thinking: {"type": "adaptive"}`. With any other thinking setting on those models, you can’t send `block_binding`, so make sure every condition holds or strip the `thinking` and `redacted_thinking` blocks from the kept turns.
728In production, `"drop_block"` keeps requests succeeding when a condition doesn’t hold, and the response lists each dropped block in `input_transformations` with `reason: "prefix_binding_mismatch"`. An entry whose `path` falls in a kept turn means a condition didn’t hold for that turn’s thinking. For how to alert on those entries, see [Watch production, and find reasoning lost with no error](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#monitor). On Claude Sonnet 5.5 and Claude Haiku 5.5, `block_binding` works only with `thinking: {"type": "adaptive"}`. With any other thinking setting on those models, make sure every condition holds, or remove the `thinking` and `redacted_thinking` blocks from the kept turns.
727729 
728730## Availability
729731 

build-with-claude/context-editing Changed · +5 / -3 lines

from line 91
9191 
9292Context editing is applied server-side before the prompt reaches Claude. Your client application maintains the full, unmodified conversation history. You do not need to sync your client state with the edited version. Continue managing your full conversation history locally as you normally would.
9393 
94On Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5, server-side context management never invalidates thinking blocks. Client-side edits to earlier turns can invalidate the thinking blocks in every later assistant turn. See [Keeping the prefix unchanged](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check).
94On [models with preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes), server-side context management never invalidates thinking blocks. Client-side edits to earlier turns can invalidate the thinking blocks in every later assistant turn. See [What must stay the same, and why](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check).
9595 
96The models with preserved thinking are Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5.
97 
9698### Context editing and prompt caching
9799 
98100Context editing’s interaction with [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) varies by strategy:
from line 109
107109 
108110## Tool result clearing usage
109111 
110The simplest way to enable tool result clearing is to specify only the strategy type. All other [configuration options](https://platform.claude.com/docs/en/build-with-claude/context-editing#configuration-options-for-tool-result-clearing) use their default values:
112One way to enable tool result clearing is to specify only the strategy type. All other [configuration options](https://platform.claude.com/docs/en/build-with-claude/context-editing#configuration-options-for-tool-result-clearing) use their default values:
111113 
112114<CodeGroup>
113115 ```bash cURL
from line 2853
28512853 
28522854#### Tool use edge cases
28532855 
2854When the SDK triggers compaction while a tool use response is pending, it removes the tool use block from the message history before generating the summary. Claude will re-issue the tool call after resuming from the summary if still needed.
2856When the SDK triggers compaction while a tool use response is pending, it removes the tool use block from the message history before generating the summary. After resuming from the summary, Claude reissues the tool call if it still needs it.
28552857 
28562858### Monitoring compaction
28572859 

build-with-claude/context-windows Changed · +14 / -4 lines

from line 49
4949 
5050Thinking tokens are a subset of your `max_tokens` parameter, are billed as output tokens, and count toward rate limits. With [adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/thinking), Claude determines its thinking allocation dynamically, so thinking token usage varies from request to request.
5151 
52Whether thinking blocks from previous assistant turns stay in the context window depends on the model. On Claude Opus 4.5 and later Opus models, Claude Sonnet 4.6 and later Sonnet models, Claude Haiku 5.5, Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, Claude Mythos 5.1, Claude Fable 5, Claude Mythos 5, and Claude Mythos Preview, the API keeps previous thinking blocks by default, and they count toward the context window like any other input tokens. On earlier Opus and Sonnet models and all Haiku models through Claude Haiku 4.5, the API automatically strips previous thinking blocks from the conversation history when you pass them back, which preserves token capacity for conversation content. For the per-model defaults, see [thinking block preservation by model](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-block-preservation-by-model). To override the default in either direction, use [thinking block clearing](https://platform.claude.com/docs/en/build-with-claude/context-editing#thinking-block-clearing).
52Whether thinking blocks from previous assistant turns stay in the context window depends on the model.
5353 
54The API keeps previous thinking blocks by default on these models, where those blocks count toward the context window like any other input tokens:
55 
56* Claude Opus 4.5 and later Opus models
57* Claude Sonnet 4.6 and later Sonnet models
58* Claude Haiku 5.5
59* Claude Fable 5.2, Claude Fable 5.1, and Claude Fable 5
60* Claude Mythos 5.2, Claude Mythos 5.1, Claude Mythos 5, and Claude Mythos Preview
61 
62On earlier Opus and Sonnet models and all Haiku models through Claude Haiku 4.5, the API automatically strips previous thinking blocks from the conversation history when you pass them back. This preserves token capacity for conversation content. For the per-model defaults, see [thinking block preservation by model](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-block-preservation-by-model). To override the default in either direction, use [thinking block clearing](https://platform.claude.com/docs/en/build-with-claude/context-editing#thinking-block-clearing).
63 
5464The following diagram shows how tokens are managed when thinking is enabled on a model that strips previous thinking blocks:
5565 
5666<Frame>
from line 90
8090 </Step>
8191 
8292 <Step title="Tool result handling (turn 2)">
83 * **Input components:** Every block in the first turn and the `tool_result`. You must return the thinking block with the corresponding tool results. This is the only case where you have to return thinking blocks.
93 * **Input components:** Every block in the first turn and the `tool_result`. Return the thinking block with the corresponding tool results.
8494 * **Output components:** After tool results have been passed back to Claude, Claude responds with only text (no additional thinking until the next `user` message, unless [interleaved thinking](https://platform.claude.com/docs/en/build-with-claude/thinking#interleaved-thinking) is enabled).
8595 * **Token calculation:** All input and output components count toward the context window, and all output components are billed as output tokens.
8696 </Step>
from line 104
94104 
95105* **Considerations for tool use with thinking:**
96106 
97 * When you post tool results, you must include the entire unmodified thinking block that accompanies that tool request, including its signature.
98 * The API uses cryptographic signatures to verify thinking block authenticity. If you modify a thinking block, the API returns an error.
107 * When you post tool results, include the entire unmodified thinking block that accompanies that tool request, including its signature.
108 * The API uses cryptographic signatures to verify thinking block authenticity.
99109 
100110<Note>
101111 Most current Claude models support [interleaved thinking](https://platform.claude.com/docs/en/build-with-claude/thinking#interleaved-thinking), which lets Claude think between tool calls, including after it receives tool results. It is automatic on models with adaptive thinking; Claude Opus 4.5, Claude Sonnet 4.5 (deprecated), and earlier Claude 4 models require the `interleaved-thinking-2025-05-14` beta header, and Claude Haiku 4.5 does not support it.

build-with-claude/effort Changed · +40 / -18 lines

from line 138
138138 };
139139 
140140 var message = await client.Messages.Create(parameters);
141 Console.WriteLine(message);
141 foreach (var block in message.Content)
142 {
143 if (block.TryPickText(out var textBlock))
144 {
145 Console.WriteLine(textBlock.Text);
146 }
147 }
142148 ```
143149 
144150 ```go Go
from line 276
270276 
271277**[Claude Fable 5.2](https://platform.claude.com/docs/en/models/fable-5-2/overview) & [Claude Mythos 5.2](https://platform.claude.com/docs/en/models/mythos-5-2/overview)** — *For demanding reasoning and long-horizon agentic work*
272278 
273Claude Fable 5.2 supports all five effort levels. The API default is `high`. Adaptive thinking is always on, so effort is your main control for thinking depth, latency, and cost. Start with `high`. Most of the gain in capability is already present at `high`, and above it, gains are uneven and depend on the task. Step up to `xhigh` for your hardest long-running coding and agentic work, where you’ve measured a gain. Step down to `medium` or `low` where your evals show quality holds. Reserve `max` for measuring the model’s ceiling and for the rare task where time and tokens don’t matter. At `max` the model optimizes for capability without regard to token cost. It runs slower and costs more than at `xhigh`, often for only a small gain. Run an effort sweep on your own evals rather than carrying settings over from Claude Fable 5.1. At `high` and above, set a large `max_tokens`. It’s a hard limit on total output (thinking plus response text). Effort barely changes how long the model’s replies are, so use your prompt to change reply length and tone. The same recommendations apply to Claude Mythos 5.2.
279Claude Fable 5.2 supports all five effort levels. The API default is `high`. Adaptive thinking is always on, so effort is your main control for thinking depth, latency, and cost.
274280 
275Where your platform supports it, Claude Fable 5.2 and Claude Mythos 5.2 also support [changing effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) with a per-message `output_config`, which preserves the prompt cache.
281Start with `high`. Most of the gain in capability is already present at `high`, and above it, gains are uneven and depend on the task. Step up to `xhigh` for your hardest long-running coding and agentic work, where you’ve measured a gain. Step down to `medium` or `low` where your evals show quality holds. Reserve `max` for measuring the model’s ceiling and for the rare task where time and tokens don’t matter. At `max` the model optimizes for capability without regard to token cost. It runs slower and costs more than at `xhigh`, often for only a small gain.
276282 
283Run an effort sweep on your own evals rather than carrying settings over from Claude Fable 5.1. At `high` and above, set a large `max_tokens`. It’s a hard limit on total output (thinking plus response text). Effort barely changes how long the model’s replies are, so use your prompt to change reply length and tone.
284 
285The same recommendations apply to Claude Mythos 5.2.
286 
287On [supported platforms](https://platform.claude.com/docs/en/build-with-claude/effort-per-message#feature-availability), Claude Fable 5.2 and Claude Mythos 5.2 also support [changing effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) with a per-message `output_config`, which preserves the prompt cache.
288 
277289See also: [Prompting Claude Fable 5.2](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#calibrate-effort)
278290 
279291**[Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/overview)** — *For long-running agentic coding and knowledge work*
280292 
281Claude Opus 5.5 supports all five effort levels, and `medium` is the default (Claude Opus 5 and earlier Opus models default to `high`, so a request that omits `effort` runs one level lower than it did on Claude Opus 5). Adaptive thinking is always on and can’t be turned off, so effort is the primary control for how much the model reasons and what a request costs. Run an effort sweep on your own evals rather than carrying settings over from an earlier model, and set a large `max_tokens` at the higher levels: it’s a hard limit on total output (thinking plus response text). Requests that set `thinking: {"type": "disabled"}` return a 400 error at every effort level. Claude Opus 5.5 also supports [changing effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) with a per-message `output_config`, which preserves the prompt cache.
293Claude Opus 5.5 supports all five effort levels, and `medium` is the default. Claude Opus 5 and earlier Opus models default to `high`, so a request that omits `effort` runs one level lower on Claude Opus 5.5.
282294 
295Adaptive thinking is always on and can’t be turned off, so effort is the primary control for how much the model reasons and what a request costs. Requests that set `thinking: {"type": "disabled"}` return a 400 error at every effort level.
296 
297Run an effort sweep on your own evals rather than carrying settings over from an earlier model. At `xhigh` or `max`, set a large `max_tokens`. It’s a hard limit on total output (thinking plus response text).
298 
299Claude Opus 5.5 also supports [changing effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) with a per-message `output_config`, which preserves the prompt cache.
300 
283301See also: [Prompting Claude Opus 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5)
284302 
285303**[Claude Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview)** — *The best combination of speed and intelligence*
286304 
287Claude Sonnet 5.5 supports all five effort levels, and `high` is the default on the Claude API. Its levels are recalibrated, so a level doesn’t produce the same amount of thinking as the same level on Claude Sonnet 5. Run a fresh effort sweep on your evals rather than carrying over the setting you used on Claude Sonnet 5. Start with `high` unless your workload is agentic or latency-sensitive. For agentic coding and multistep tool use, start with `medium` for well-specified tasks and move to `high` for harder or longer ones. For chat and other latency-sensitive work, start with `medium` or `low`. Use `xhigh` or `max` only where your evals show a quality gain. Set `max_tokens` with room for thinking and the reply. Thinking counts toward `max_tokens` even when the thinking content isn’t returned. For agentic coding, set `max_tokens` to 128,000, the model’s maximum, and [stream](https://platform.claude.com/docs/en/build-with-claude/streaming) the response.
305Claude Sonnet 5.5 supports all five effort levels, and `high` is the default on the Claude API. Its levels are calibrated differently, so a level doesn’t produce the same amount of thinking as on Claude Sonnet 5. Run a fresh effort sweep on your evals rather than carrying over the setting you used on Claude Sonnet 5.
288306 
289To turn off up-front thinking, send `thinking: {"type": "between_tools"}` instead of `"disabled"`. It’s the lowest thinking setting on Claude Sonnet 5.5, and it works at `low`, `medium`, and `high` effort. At `xhigh` or `max`, a request with it returns a 400 error, so use adaptive thinking at those levels: omit the `thinking` field or send `thinking: {"type": "adaptive"}`. See [Running without up-front thinking](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#running-without-up-front-thinking).
307Start with `high` unless your workload is agentic or latency-sensitive. For agentic coding and multistep tool use, start with `medium` for well-specified tasks and move to `high` for harder or longer ones. For chat and other latency-sensitive work, start with `medium` or `low`. Use `xhigh` or `max` only where your evals show a quality gain.
290308 
291Where your platform supports it, Claude Sonnet 5.5 also supports [changing effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) with a per-message `output_config`, which preserves the prompt cache. With `between_tools`, effort can’t change mid-conversation: a per-message `output_config.effort` that differs from the level in effect returns a 400 error. To vary effort for each turn, use adaptive thinking.
309Set `max_tokens` with room for thinking and the reply. Thinking counts toward `max_tokens` even when the thinking content isn’t returned. For agentic coding, set `max_tokens` to 128,000, the model’s maximum, and stream the response (see [Streaming messages](https://platform.claude.com/docs/en/build-with-claude/streaming)).
292310 
311To have the model respond without thinking first, send `thinking: {"type": "between_tools"}`, not `"disabled"`. It works at `low`, `medium`, and `high` effort. At `xhigh` or `max` it returns a 400 error, so use adaptive thinking, the default, at those levels. See [Running without up-front thinking](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#running-without-up-front-thinking).
312 
313On [supported platforms](https://platform.claude.com/docs/en/build-with-claude/effort-per-message#feature-availability), Claude Sonnet 5.5 also supports [changing effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) with a per-message `output_config`, which preserves the prompt cache. With `between_tools`, effort can’t change mid-conversation: a per-message `output_config.effort` at a different level returns a 400 error. To vary effort for each turn, use adaptive thinking.
314 
293315See also: [Prompting Claude Sonnet 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#calibrate-effort)
294316 
295317**[Claude Haiku 5.5](https://platform.claude.com/docs/en/models/haiku-5-5/overview)** — *For high-volume, latency-sensitive tasks such as classification, extraction, and routing*
from line 320
298320 
299321To get less thinking, lower the effort level. You can also send `thinking: {"type": "disabled"}` at `high` effort or below. At `xhigh` or `max`, it returns a 400 error, so use adaptive thinking there: omit the `thinking` field or send `thinking: {"type": "adaptive"}`.
300322 
301Where your platform supports it, Claude Haiku 5.5 also lets you [change effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) with a per-message `output_config`, which preserves the prompt cache. With `thinking: {"type": "disabled"}`, effort can’t change mid-conversation: a per-message `output_config.effort` that differs from the level in effect returns a 400 error. To vary effort for each turn, use adaptive thinking.
323On [supported platforms](https://platform.claude.com/docs/en/build-with-claude/effort-per-message#feature-availability), Claude Haiku 5.5 also lets you [change effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) with a per-message `output_config`, which preserves the prompt cache. With `thinking: {"type": "disabled"}`, effort can’t change mid-conversation: a per-message `output_config.effort` at a different level returns a 400 error. To vary effort for each turn, use adaptive thinking.
302324 
303325See also: [Prompting Claude Haiku 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#use-effort-to-control-thinking)
304326 
from line 352
330352 
331353When running Claude Opus 5 at `xhigh` or `max` effort, set a large `max_tokens` so the model has room to think and act across subagents and tool calls. Starting at 64k tokens and tuning from there is a reasonable default.
332354 
333Where your platform supports it, Claude Opus 5 also supports [changing effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) with a per-message `output_config`, which preserves the prompt cache.
355On [supported platforms](https://platform.claude.com/docs/en/build-with-claude/effort-per-message#feature-availability), Claude Opus 5 also supports [changing effort mid-conversation](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) with a per-message `output_config`, which preserves the prompt cache.
334356 
335357See also: [Prompting Claude Opus 5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5)
336358 
from line 398
376398 
377399**[Claude Sonnet 4.6](https://platform.claude.com/docs/en/models/sonnet-4-6/overview)**
378400 
379Sonnet 4.6 defaults to `high` effort. Explicitly set effort when using Sonnet 4.6 to avoid unexpected latency:
401Claude Sonnet 4.6 defaults to `high` effort. Set effort explicitly to avoid unexpected latency:
380402 
381* **Medium effort (recommended default):** Best balance of speed, cost, and performance for most applications. Suitable for agentic coding, tool-heavy workflows, and code generation.
403* **Medium effort (recommended):** Best balance of speed, cost, and performance for most applications. Suitable for agentic coding, tool-heavy workflows, and code generation.
382404* **Low effort:** For high-volume or latency-sensitive workloads. Suitable for chat and non-coding use cases where faster turnaround is prioritized.
383405* **High effort:** For complex reasoning and tasks where quality matters more than speed or cost.
384406* **Max effort:** For tasks requiring the absolute highest capability with no constraints on token spending.
from line 435
413435 
414436## Change effort mid-conversation
415437 
416You can run later turns of a conversation at a different effort level in two ways: a per-message effort change, which keeps the prompt cache, or a new top-level value on the next request, which starts the cache over.
438You can run later turns of a conversation at a different effort level in two ways. A per-message effort change keeps the prompt cache. A new top-level value on the next request can invalidate all or part of the prompt cache.
417439 
418440### Per-message effort
419441 
from line 443
421443 
422444### Top-level effort on the next request
423445 
424The top-level `output_config.effort` applies to the whole request. To run a later part of a conversation at a different level, set the new value on the next request. Because top-level effort shapes the rendered prompt, changing it between requests doesn’t preserve cached prefixes from earlier turns. If you rely on [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) across a long session and your model doesn’t support per-message effort, pick an effort level at the start and keep it constant.
446The top-level `output_config.effort` applies to the whole request. To run a later part of a conversation at a different level, set the new value on the next request. Because top-level effort shapes the rendered prompt, changing it between requests can invalidate cached prefixes from earlier turns. If you rely on [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) across a long session and your model doesn’t support per-message effort, pick an effort level at the start and keep it constant.
425447 
426448## Best practices
427449 
from line 451
4294512. **Use low for speed-sensitive or simple tasks:** When latency matters or tasks are straightforward, low effort can significantly reduce response times and costs.
4304523. **Test your use case:** The impact of effort levels varies by task type. Evaluate performance on your specific use cases before deploying.
4314534. **Consider dynamic effort:** Adjust effort based on task complexity. Simple queries might warrant low effort, whereas agentic coding and complex reasoning benefit from high effort. See the next item before varying it within one conversation.
4325. **Hold top-level effort constant within cached conversations:** Changing the top-level effort value between requests invalidates [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching), so vary it across workloads rather than within a conversation that relies on cache hits. On models that support it, use a [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) change instead, which preserves the cache. See [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching).
4545. **Hold top-level effort constant within cached conversations:** Changing the top-level effort value between requests can invalidate all or part of the [prompt cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching), so vary it across workloads rather than within a conversation that relies on cache hits. On models that support it, use a [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) change instead, which preserves the cache. See [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching).
433455 
434456## Next steps
435457 

build-with-claude/effort-per-message Changed · +19 / -20 lines

from line 47
4747 -H "anthropic-beta: mid-conversation-output-config-2026-07-01" \
4848 -H "content-type: application/json" \
4949 -d '{
50 "model": "claude-fable-5-1",
50 "model": "claude-opus-5-5",
5151 "max_tokens": 4096,
5252 "output_config": {"effort": "high"},
5353 "messages": [
from line 62
6262 ```bash CLI
6363 ant beta:messages create \
6464 --beta mid-conversation-output-config-2026-07-01 <<'YAML'
65 model: claude-fable-5-1
65 model: claude-opus-5-5
6666 max_tokens: 4096
6767 output_config:
6868 effort: high
from line 85
8585 client = anthropic.Anthropic()
8686 
8787 response = client.beta.messages.create(
88 model="claude-fable-5-1",
88 model="claude-opus-5-5",
8989 max_tokens=4096,
9090 output_config={"effort": "high"},
9191 messages=[
from line 113
113113 const client = new Anthropic();
114114 
115115 const response = await client.beta.messages.create({
116 model: "claude-fable-5-1",
116 model: "claude-opus-5-5",
117117 max_tokens: 4096,
118118 output_config: { effort: "high" },
119119 messages: [
from line 143
143143 ```csharp C#
144144 using Anthropic.Models.Beta;
145145 using Anthropic.Models.Beta.Messages;
146 using Model = Anthropic.Models.Messages.Model;
146 // ...
147147 
148148 AnthropicClient client = new();
149149 
150150 var response = await client.Beta.Messages.Create(new MessageCreateParams
151151 {
152 Model = Model.ClaudeFable5_1,
152 Model = Model.ClaudeOpus5_5,
153153 MaxTokens = 4096,
154154 OutputConfig = new() { Effort = Effort.High },
155155 Messages =
from line 180
180180 client := anthropic.NewClient()
181181 
182182 response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
183 Model: anthropic.ModelClaudeFable5_1,
183 Model: anthropic.ModelClaudeOpus5_5,
184184 MaxTokens: 4096,
185185 OutputConfig: anthropic.BetaOutputConfigParam{
186186 Effort: anthropic.BetaOutputConfigEffortHigh,
from line 216
216216 import com.anthropic.models.beta.messages.BetaSystemMessageOutputConfig;
217217 import com.anthropic.models.beta.messages.BetaSystemMessageParam;
218218 import com.anthropic.models.beta.messages.MessageCreateParams;
219 import com.anthropic.models.messages.Model;
219 // ...
220220 
221221 void main() {
222222 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
223223 
224224 MessageCreateParams params = MessageCreateParams.builder()
225 .model(Model.CLAUDE_FABLE_5_1)
225 .model(Model.CLAUDE_OPUS_5_5)
226226 .maxTokens(4096L)
227227 .addBeta(AnthropicBeta.MID_CONVERSATION_OUTPUT_CONFIG_2026_07_01)
228228 .outputConfig(BetaOutputConfig.builder()
from line 253
253253 use Anthropic\Beta\Messages\BetaOutputConfig;
254254 use Anthropic\Beta\Messages\BetaSystemMessageOutputConfig;
255255 use Anthropic\Beta\Messages\BetaTextBlock;
256 use Anthropic\Client;
257 use Anthropic\Messages\Model;
256 // ...
258257 
259258 $client = new Client();
260259 
261260 $response = $client->beta->messages->create(
262 model: Model::CLAUDE_FABLE_5_1,
261 model: Model::CLAUDE_OPUS_5_5,
263262 maxTokens: 4096,
264263 outputConfig: BetaOutputConfig::with(effort: 'high'),
265264 messages: [
from line 286
287286 client = Anthropic::Client.new
288287 
289288 response = client.beta.messages.create(
290 model: Anthropic::Model::CLAUDE_FABLE_5_1,
289 model: Anthropic::Model::CLAUDE_OPUS_5_5,
291290 max_tokens: 4096,
292 output_config: {effort: :high},
291 output_config: { effort: :high },
293292 messages: [
294 {role: "user", content: "Plan a migration from SQLite to PostgreSQL in three short steps."},
295 {role: "assistant", content: "1. Export the SQLite data. 2. Create the PostgreSQL schema. 3. Import the data and verify row counts."},
293 { role: "user", content: "Plan a migration from SQLite to PostgreSQL in three short steps." },
294 { role: "assistant", content: "1. Export the SQLite data. 2. Create the PostgreSQL schema. 3. Import the data and verify row counts." },
296295 # Effort-only system message: the new level takes effect from the next user turn.
297 {role: "system", content: [], output_config: {effort: :low}},
298 {role: "user", content: "Summarize the plan in one sentence."}
296 { role: "system", content: [], output_config: { effort: :low } },
297 { role: "user", content: "Summarize the plan in one sentence." }
299298 ],
300299 betas: [Anthropic::AnthropicBeta::MID_CONVERSATION_OUTPUT_CONFIG_2026_07_01]
301300 )
from line 317
318317 
319318The new level stays in effect until a later message changes it.
320319 
321Put the message after everything you’ve already sent, and keep it in place on later requests. Don’t insert it before turns you’ve already sent, and don’t move or remove it later. On models with [preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking), any of those changes invalidates the thinking blocks in the `assistant` turns after the message. [What the API does with an invalid block](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#mismatch-behavior) says what happens next.
320Put the message after everything you’ve already sent, and keep it in place on later requests. Don’t insert it before turns you’ve already sent, and don’t move or remove it later. On models with [preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking), any of those changes invalidates the thinking blocks in the `assistant` turns after the message. For what happens next, see [Set `prefix_mismatch_behavior`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#mismatch-behavior).
322321 
323322If it sits next to a `system` message that has content, both messages must follow the [placement rules for mid-conversation system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#limitations).
324323 
from line 331
332331 
333332## Per-message or top-level effort
334333 
335Prefer per-message effort over [changing the top-level value](https://platform.claude.com/docs/en/build-with-claude/effort#top-level-effort-on-the-next-request) between requests. A per-message change leaves everything before it unchanged, so the cached prefix still matches. A top-level change restarts the cache. On Claude Fable 5.1, a top-level change also steers the model less reliably. The model’s earlier replies were written at the previous level, and the model tends to stay consistent with them.
334Prefer per-message effort over [changing the top-level value](https://platform.claude.com/docs/en/build-with-claude/effort#top-level-effort-on-the-next-request) between requests. A per-message change leaves everything before it unchanged, so the cached prefix still matches. A top-level change can invalidate all or part of the cache. On Claude Fable 5.1, a top-level change also steers the model less reliably. The model’s earlier replies were written at the previous level, and the model tends to stay consistent with them.
336335 
337336## Availability
338337 

build-with-claude/extended-thinking Changed · +6 / -6 lines

from line 31
3131 
3232Extended thinking in manual mode gives you direct control over how much Claude thinks. You set a thinking token budget on each request with `thinking: {type: "enabled", budget_tokens: N}`, and Claude thinks against that budget before it starts its final answer. Manual mode remains useful when your workload requires predictable latency or precise control over thinking costs. This page covers how to set and tune the budget, how manual mode interacts with interleaved thinking and prompt caching, and how to migrate to adaptive thinking.
3333 
34To learn how thinking itself works, including thinking blocks and the response shape, the `display` parameter, streaming, thinking with tool use, and encryption, see the [thinking overview](https://platform.claude.com/docs/en/build-with-claude/thinking).
34To learn how thinking itself works, including thinking blocks and the response shape, the `display` parameter, streaming, thinking with tool use, and encryption, see [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking).
3535 
3636## Supported models
3737 
from line 317
317317 
318318How platforms treat the beta header differs. The Claude API, [Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws), and [Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed) accept `interleaved-thinking-2025-05-14` on any model and ignore it where unsupported. Acceptance is not the same as effect: on models that reject `type: "enabled"` (4.7 and later) or lack manual-mode interleaving (Claude Opus 4.6), the header has no manual-mode effect; adaptive thinking interleaves automatically there.
319319 
320Partner-operated platforms, [Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed) and [Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock), likewise accept the header on any model without returning an error, and ignore it on models that don’t support interleaved thinking.
320Partner-operated platforms, [Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed) and [Amazon Bedrock (`bedrock-mantle`)](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock), accept the header on any model without returning an error, and ignore it on models that don’t support interleaved thinking.
321321 
322322## Turn structure in manual mode
323323 
from line 346
346346 
347347## Shared mechanics
348348 
349Most thinking behavior is mode neutral and documented once on the [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking) page. Everything there applies in manual mode too:
349Most thinking behavior is mode neutral and documented once on the [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking) page. These sections apply in manual mode too:
350350 
351351* [Controlling thinking display](https://platform.claude.com/docs/en/build-with-claude/thinking#controlling-thinking-display)
352352* [Streaming thinking](https://platform.claude.com/docs/en/build-with-claude/thinking#streaming-thinking)
from line 358
358358 
359359## Migrating to adaptive thinking
360360 
361If your model supports only extended thinking (Claude Sonnet 4.5 (deprecated), Claude Opus 4.5, Claude Haiku 4.5, and earlier Claude 4 models), no action is needed now: adaptive thinking is not available there, and `type: "adaptive"` [returns a 400 error](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting#error-thinking-type-adaptive). Keep `budget_tokens` until you move to a model that supports adaptive thinking, then apply the mapping that follows.
361If your model supports only extended thinking, no action is needed. These models are Claude Sonnet 4.5 (deprecated), Claude Opus 4.5, Claude Haiku 4.5, and earlier Claude 4 models. Adaptive thinking is not available on them, and `type: "adaptive"` [returns a 400 error](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting#error-thinking-type-adaptive). Keep `budget_tokens` until you move to a model that supports adaptive thinking, then apply the mapping that follows.
362362 
363363You need to migrate off `type: "enabled"` if:
364364 
from line 395
395395 
396396`effort: "high"` is the default on Claude Sonnet 4.6, so omitting it here produces identical behavior; it appears only to show where the depth control lives in adaptive mode. Claude Opus 5.5 and Claude Haiku 5.5 default to `"medium"`, and other models that support effort default to `"high"` (see [Effort levels](https://platform.claude.com/docs/en/build-with-claude/effort#effort-levels)).
397397 
398Expect a behavioral difference, not just a syntax change. With a fixed budget, Claude thinks on every request. With adaptive thinking, Claude determines whether and how much to think on each request, and at lower [effort](https://platform.claude.com/docs/en/build-with-claude/effort) settings it might skip thinking entirely on easy inputs. You can also remove the `interleaved-thinking-2025-05-14` beta header after migrating: adaptive thinking interleaves automatically, and the Claude API ignores the header on these models. Thinking block preservation changes too: Claude Opus 4.5 and models numbered 4.6 and higher keep prior turns’ thinking blocks in context and bill them as input, where Claude Sonnet 4.5 (deprecated), Claude Haiku 4.5, and earlier models strip them; see [thinking block preservation by model](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-block-preservation-by-model).
398Expect a behavioral difference, not only a syntax change. With a fixed budget, Claude thinks on every request. With adaptive thinking, Claude determines whether and how much to think on each request, and at lower [effort](https://platform.claude.com/docs/en/build-with-claude/effort) settings it might skip thinking entirely on easy inputs. You can also remove the `interleaved-thinking-2025-05-14` beta header after migrating: adaptive thinking interleaves automatically, and the Claude API ignores the header on these models. Thinking block preservation changes too. Claude Opus 4.5 and models numbered 4.6 and higher keep prior turns’ thinking blocks in context and bill them as input. Claude Sonnet 4.5 (deprecated), Claude Haiku 4.5, and earlier models strip them. See [thinking block preservation by model](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-block-preservation-by-model).
399399 
400400Switching modes is a thinking-configuration change, so the first request after the switch invalidates cache breakpoints, as described in [Prompt caching in manual mode](https://platform.claude.com/docs/en/build-with-claude/extended-thinking#extended-thinking-with-prompt-caching).
401401 
402For full guidance, see [adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/thinking), [effort](https://platform.claude.com/docs/en/build-with-claude/effort), and the [model migration guide](https://platform.claude.com/docs/en/about-claude/models/migration-guide).
402For full guidance, see [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking), [Effort](https://platform.claude.com/docs/en/build-with-claude/effort), and [Migration guides](https://platform.claude.com/docs/en/about-claude/models/migration-guide).
403403 
404404## Next steps
405405 

build-with-claude/message-threads Changed · +3 / -3 lines

from line 604
604604 
605605**If you change `system` or `tools`:** On the following models, leave every `thinking` and `redacted_thinking` block out of the conversation that you send in the new create request: Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5. The model then answers without that earlier reasoning.
606606 
607* **Why:** Changing `system` or `tools` makes the `thinking` and `redacted_thinking` blocks already in the conversation invalid. See [What counts as an edit](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#what-counts-as-an-edit).
608* **If you send the blocks anyway:** The create request can return a 400 error. Whether it does depends on the model and your account. See [When `prefix_mismatch_behavior` is unset](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement) and [What the API does with an invalid block](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#mismatch-behavior).
607* **Why:** Changing `system` or `tools` makes the `thinking` and `redacted_thinking` blocks already in the conversation invalid. See [What counts as a change](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#what-counts-as-an-edit).
608* **If you send the blocks anyway:** The create request can get a 400 error (see [Thinking block bound to a different conversation](https://platform.claude.com/docs/en/api/errors#thinking-block-conversation-mismatch)). See [Which models run the prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#enforcement).
609609 
610610Send only the new messages on a continue request. The API doesn’t check them against the messages it already has. A message you send again can appear twice in the conversation, or the request can return an error. For example, a continue request that starts with the previous response returns an error.
611611 
from line 632
632632 
633633If the stream of a continue request drops before `message_stop`, send the same continue request again. If that request returns a `thread_already_continued` or `thread_continue_in_flight` error, replay the full conversation in a new create request.
634634 
635Your connection might have dropped while the server was still generating the response, or after the server saved it. That is why the API can reject the retry. Replaying is always safe.
635Your connection might have dropped while the server was still generating the response, or after the server saved it. That is why the API can reject the retry. Replaying your exact copy is safe.
636636 
637637The SDK thread helper doesn’t retry the continue request after a dropped stream. See [How the SDK helper behaves](https://platform.claude.com/docs/en/build-with-claude/message-threads#sdk-helper-handles).
638638 

build-with-claude/mid-conversation-system-messages Changed · +96 / -63 lines

from line 14
1414 - claude-mythos-5-1
1515 - claude-fable-5
1616 - claude-mythos-5
17 - claude-mythos-preview
1817 - claude-opus-5-5
1918 - claude-opus-5
2019 - claude-sonnet-5-5
from line 28
2928 Claude Platform on AWS: stable
3029 Claude Models on Google Cloud (Anthropic managed): stable
3130 Claude Models on Google Cloud (Google managed): stable
31 Microsoft Foundry: stable
3232---
3333 
3434**API support**: Usage differs by product.
from line 43
4343<Note>
4444 Mid-conversation system messages are available on Claude Fable 5.2, [Claude Mythos 5.2](https://platform.claude.com/docs/en/models/mythos-5-2/overview), Claude Fable 5.1, [Claude Mythos 5.1](https://platform.claude.com/docs/en/models/mythos-5-1/overview), Claude Fable 5, [Claude Mythos 5](https://platform.claude.com/docs/en/models/mythos-5/overview), Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Sonnet 5.5, and Claude Haiku 5.5. This feature is not available on Claude Sonnet 5. Use the top-level `system` field there instead.
4545 
46 [Mid-conversation tool changes](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes) are in beta on the same models. On the Claude API, Claude Platform on AWS, and Claude Models on Google Cloud (Anthropic managed), send the `inline-tools-2026-09-15` beta header, which also covers [defining a tool inside a `tool_addition` block](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta). [Adding an MCP server that way](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#add-an-mcp-server-mid-conversation-beta) needs a second beta header, `mcp-client-2026-09-15`, which is available on the Claude API. The `mid-conversation-tool-changes-2026-07-01` header works for changes that name a tool by reference, on the Claude API, Amazon Bedrock, Claude Platform on AWS, Claude Models on Google Cloud (Anthropic managed), and Claude Models on Google Cloud (Google managed).
46 [Mid-conversation tool changes](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes) are in beta on the same models. Two beta headers enable these changes. Where both work on your platform, send `inline-tools-2026-09-15`:
4747 
48 [Turn-scoped system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) (`clear_at`) are in beta and require the `mid-conversation-system-clear-at-2026-08-21` beta header, on the same models and platforms as mid-conversation system messages.
48 * `inline-tools-2026-09-15` works on the Claude API, Claude Platform on AWS, Claude Models on Google Cloud (Anthropic managed), and Microsoft Foundry. It also covers [defining a tool inside a `tool_addition` block](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta). [Adding an MCP server that way](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#add-an-mcp-server-mid-conversation-beta) also needs the `mcp-client-2026-09-15` beta header, which is available on the Claude API.
49 * `mid-conversation-tool-changes-2026-07-01` works on Claude Models on Google Cloud (Google managed) and Amazon Bedrock, and on the four platforms listed for `inline-tools-2026-09-15`. It doesn’t cover defining a tool inside a `tool_addition` block.
50 
51 [Turn-scoped system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) (`clear_at`) are in beta and require the `mid-conversation-system-clear-at-2026-08-21` beta header, on the [same models and platforms](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#feature-availability) as mid-conversation system messages.
4952</Note>
5053 
5154## Mid-conversation tool changes
5255 
53The `tools` array sits even earlier in the hashed request prefix than the top-level `system` field, so editing it invalidates the [prompt cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) for the entire conversation. Mid-conversation tool changes are the tools counterpart to mid-conversation system messages. Instead of fixing the tool list for the lifetime of the conversation, you change which tools are offered to the model between turns: declare the full tool set in `tools` up front, then use `tool_addition` and `tool_removal` blocks to offer a tool to the model, or withdraw it, from a specific point in the conversation onward. The `tools` array itself never changes, so the cached prefix stays intact. Mid-conversation tool changes are in beta and use the `inline-tools-2026-09-15` beta header on the Claude API, Claude Platform on AWS, and Claude Models on Google Cloud (Anthropic managed).
56The `tools` array sits even earlier in the hashed request prefix than the top-level `system` field, so editing it invalidates the [prompt cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) for the entire conversation. Mid-conversation tool changes are the tools counterpart to mid-conversation system messages. Instead of fixing the tool list for the lifetime of the conversation, you change which tools are offered to the model between turns. Declare the full tool set in `tools` up front, then use `tool_addition` and `tool_removal` blocks to offer a tool to the model, or withdraw it, from a specific point in the conversation onward. The `tools` array itself never changes, so the cached prefix stays intact. Mid-conversation tool changes are in beta and use the beta headers named earlier on this page.
5457 
5558`tool_addition` and `tool_removal` are content blocks in the `content` array of a `role: "system"` message, and they can be mixed with `text` blocks in the same message. The message follows the placement rules for any mid-conversation system message, with one extra restriction after a paused turn (see [Limitations](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#limitations)), and the change applies from that point in the conversation onward. Each block’s `tool` field references a tool rather than defining one: `{"type": "tool_reference", "name": "..."}` names a tool declared in the request’s `tools` array, and [MCP connector](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector) tools can be referenced individually with `mcp_tool_reference` (`server_name` and `name`) or as a whole toolset with `mcp_toolset_reference` (`server_name`). Referencing a name that is not declared in `tools` returns a 400 error (on the Claude API, with `error.details.error_code` set to `tool_reference_unresolved`). A `tool_addition` block can instead [carry the tool’s full definition](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta), which the `mid-conversation-tool-changes-2026-07-01` header doesn’t support.
5659 
from line 342
339342 import com.anthropic.models.beta.messages.BetaTool;
340343 import com.anthropic.models.beta.messages.MessageCreateParams;
341344 // ...
345 
346 void main() {
342347 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
343348 
344349 // The full tool set is declared up front and never changes, so the
from line 380
375380 response.content().stream()
376381 .flatMap(block -> block.text().stream())
377382 .forEach(textBlock -> IO.println(textBlock.text()));
383 }
378384 ```
379385 
380386 ```php PHP
from line 429
423429 );
424430 
425431 foreach ($response->content as $block) {
426 if ($block->type === 'text') {
432 if ($block instanceof \Anthropic\Beta\Messages\BetaTextBlock) {
427433 echo $block->text, PHP_EOL;
428434 }
429435 }
from line 1041
10351041A few rules follow from where the definition renders:
10361042 
10371043* **Declare what you know up front.** A tool you know about at the first request belongs in `tools`, with `defer_loading: true` and a later `tool_addition` reference if you don’t want to offer it to the model yet. Define by value only what is unknown at the first request or changes later.
1038* **Keep at least one non-deferred tool in `tools`.** A conversation whose `tools` array has no non-deferred tool is accepted, but the first tool it defines by value changes the start of the rendered prompt, which costs one full cache miss on that request. A [tool search tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool) counts as non-deferred.
1044* **Keep at least one non-deferred tool in `tools`.** If every tool is deferred, the request gets a 400 error, unless it sends the `inline-tools-2026-09-15` header and `messages` holds a `tool_addition` block. Then the first tool defined by value costs one full cache miss. A [tool search tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool) counts as non-deferred.
10391045* **Dated tool types keep their own beta headers.** If a server tool you define by value requires its own beta header, send that header on every later request in the conversation.
10401046* **`cache_control` goes on the block or in the definition, not both,** and counts toward the request’s breakpoint limit. A deferred definition can’t carry `cache_control`.
10411047 
from line 1109
11031109 "messages": [
11041110 {
11051111 "role": "user",
1106 "content": "What'\''s on my calendar tomorrow?"
1112 "content": "What is on my calendar tomorrow?"
11071113 },
11081114 {
11091115 "role": "system",
from line 1153
11471153 - location
11481154 messages:
11491155 - role: user
1150 content: What's on my calendar tomorrow?
1156 content: What is on my calendar tomorrow?
11511157 # Make the calendar server's tools available from this point onward.
11521158 # The block names the server; it never holds a URL or token.
11531159 - role: system
from line 1196
11901196 },
11911197 ],
11921198 messages=[
1193 {"role": "user", "content": "What's on my calendar tomorrow?"},
1199 {"role": "user", "content": "What is on my calendar tomorrow?"},
11941200 # Make the calendar server's tools available from this point onward.
11951201 # The block names the server; it never holds a URL or token.
11961202 {
from line 1256
12501256 }
12511257 ],
12521258 messages: [
1253 { role: "user", content: "What's on my calendar tomorrow?" },
1259 { role: "user", content: "What is on my calendar tomorrow?" },
12541260 // Make the calendar server's tools available from this point onward.
12551261 // The block names the server; it never holds a URL or token.
12561262 {
from line 1330
13241330 ],
13251331 Messages =
13261332 [
1327 new BetaUserMessageParam { Content = "What's on my calendar tomorrow?" },
1333 new BetaUserMessageParam { Content = "What is on my calendar tomorrow?" },
13281334 // Make the calendar server's tools available from this point onward.
13291335 // The block names the server; it never holds a URL or token.
13301336 new BetaSystemMessageParam
from line 1397
13911397 }},
13921398 },
13931399 Messages: []anthropic.BetaMessageParam{
1394 anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What's on my calendar tomorrow?")),
1400 anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What is on my calendar tomorrow?")),
13951401 // Make the calendar server's tools available from this point onward.
13961402 // The block names the server; it never holds a URL or token.
13971403 anthropic.NewBetaSystemMessage(anthropic.BetaSystemMessageOutputConfigParam{}, anthropic.BetaSystemMessageParamContentUnion{
from line 1472
14661472 .authorizationToken("YOUR_TOKEN")
14671473 .build())
14681474 .addTool(weatherTool)
1469 .addUserMessage("What's on my calendar tomorrow?")
1475 .addUserMessage("What is on my calendar tomorrow?")
14701476 // Make the calendar server's tools available from this point onward.
14711477 // The block names the server; it never holds a URL or token.
14721478 .addSystemMessageOfBlocks(List.of(
from line 1541
15351541 ],
15361542 ],
15371543 messages: [
1538 ['role' => 'user', 'content' => "What's on my calendar tomorrow?"],
1544 ['role' => 'user', 'content' => 'What is on my calendar tomorrow?'],
15391545 // Make the calendar server's tools available from this point onward.
15401546 // The block names the server; it never holds a URL or token.
15411547 [
from line 1609
16031609 }
16041610 ],
16051611 messages: [
1606 { role: "user", content: "What's on my calendar tomorrow?" },
1612 { role: "user", content: "What is on my calendar tomorrow?" },
16071613 # Make the calendar server's tools available from this point onward.
16081614 # The block names the server; it never holds a URL or token.
16091615 {
from line 1654
16481654 
16491655A few situations where this matters:
16501656 
1651* **Mid-session policy or persona changes.** A long agentic session needs a new constraint (“from now on, write all SQL as parameterized queries”) after dozens of cached turns. Adding it to the top-level `system` field would re-process the entire history.
1657* **Mid-session policy or persona changes.** A long agentic session needs a new constraint (“from now on, write all SQL as parameterized queries”) after dozens of cached turns. Adding it to the top-level `system` field would reprocess the entire history.
16521658* **Per-turn context that must be authoritative.** You want to inject a freshness note, a session deadline, or a tool-availability change with system-level weight, and it changes too often to live in the cached prefix.
16531659* **Per-turn reminders that shouldn’t pile up.** A harness nudges the model after each batch of tool results (“request independent reads together,” “the user hasn’t heard from you in a while”) and needs the model to receive only the newest copy. A [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) renders for one turn and then costs nothing, without deleting anything from the history.
16541660* **State changes your application observes.** Your application detects something Claude should treat as an operator-level fact: files changed on disk, the user toggled an auto-approve setting, available tools changed, or the remaining token budget dropped below a threshold.
from line 1833
18271833 };
18281834 
18291835 var response = await client.Messages.Create(parameters);
1830 Console.WriteLine(response);
1836 foreach (var block in response.Content)
1837 {
1838 if (block.TryPickText(out var textBlock))
1839 {
1840 Console.WriteLine(textBlock.Text);
1841 }
1842 }
18311843 ```
18321844 
18331845 ```go Go
from line 1882
18701882 ```java Java
18711883 import com.anthropic.models.messages.CacheControlEphemeral;
18721884 // ...
1885 
1886 void main() {
18731887 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
18741888 
18751889 MessageCreateParams params = MessageCreateParams.builder()
from line 1907
18931907 response.content().stream()
18941908 .flatMap(block -> block.text().stream())
18951909 .forEach(textBlock -> IO.println(textBlock.text()));
1910 }
18961911 ```
18971912 
18981913 ```php PHP
from line 1927
19121927 // request is still read from cache.
19131928 ['role' => 'system', 'content' => 'From now on, every suggestion must include explicit type annotations.']
19141929 ],
1915 model: 'claude-opus-5-5',
1930 model: Model::CLAUDE_OPUS_5_5,
19161931 // Automatic prompt caching: each request caches the conversation so far,
19171932 // and the next request reads the unchanged prefix from cache.
19181933 cacheControl: CacheControlEphemeral::with(),
from line 1935
19201935 );
19211936 
19221937 foreach ($response->content as $block) {
1923 if ($block->type === 'text') {
1938 if ($block instanceof \Anthropic\Messages\TextBlock) {
19241939 echo $block->text, PHP_EOL;
19251940 }
19261941 }
from line 1971
19561971 
19571972This example enables [automatic caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching) with the top-level `cache_control` field. Prompt caching is opt-in: if a request has no `cache_control` field (automatic or an [explicit breakpoint](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints)), nothing is cached and every request pays the regular input token price for the full conversation. With caching enabled, appending the system message leaves the already-cached turns unchanged, so the request that carries the new instruction still reads them from cache instead of processing them again. Caching also requires the conversation to meet the [minimum cacheable prompt length](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#cache-limitations); an example as short as this one falls below it, so `cache_creation_input_tokens` and `cache_read_input_tokens` stay at 0 until the conversation grows.
19581973 
1959A mid-conversation system message that carries content (`text`, `tool_addition`, or `tool_removal` blocks) must immediately follow a `user` turn (or an `assistant` turn ending in a server tool result), and must either be the last entry in `messages` or be immediately followed by an `assistant` turn. A `user` message that carries `tool_result` blocks counts: in an agentic loop you can place the system message right after the tool results, before Claude’s next turn. Any other position for a message that carries content, including between an `assistant` `tool_use` block and the `tool_result` that answers it, returns a 400 error. A message with empty `content` that only sets [`output_config.effort`](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) is accepted anywhere in `messages`. Consecutive `system` messages are judged together, so an effort-only message next to one that carries content follows the rule for content.
1974A mid-conversation system message that carries content (`text`, `tool_addition`, or `tool_removal` blocks) must immediately follow a `user` turn (or an `assistant` turn ending in a server tool result). It must then end `messages` or be immediately followed by an `assistant` turn. A `user` message that carries `tool_result` blocks counts: in an agentic loop you can place the system message right after the tool results, before Claude’s next turn.
19601975 
1976Any other position for a message that carries content, including between an `assistant` `tool_use` block and the `tool_result` that answers it, returns a 400 error. A message with empty `content` that only sets [`output_config.effort`](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) can follow any turn, but goes after everything already sent. Consecutive `system` messages are judged together, so an effort-only message next to one that carries content follows the rule for content.
1977 
19611978### Placement after tool results
19621979 
19631980In an [agentic loop](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview), the system message goes after the `user` message that delivers the tool results. On most models, this is also where your application can relay input that the user typed while Claude was working, so the new context is absorbed without restarting the turn (for Claude Sonnet 5.5 and Claude Haiku 5.5, see the end of this section):
from line 2028
20112028 
20122029To scope a `role: "system"` message to the current turn, set its `clear_at` field. It takes one of two values:
20132030 
2014* `"never"` (the default): the message renders at its position on every request that includes it. Omitting the field is identical.
2031* `"never"` (the default): the message renders at its position on every request that includes it. Omitting the field has the same effect.
20152032* `"next_user_message"`: the message is **turn-scoped**. Its text renders only while no `role: "user"` message comes after it in `messages`. A user message that carries only `tool_result` blocks counts as a user message here. Once a later user message exists, the message is **cleared**: it stays in the array but renders nothing and costs no input tokens, on that request and every later one.
20162033 
20172034Turn-scoped system messages are in beta. Include the [beta header](https://platform.claude.com/docs/en/api/beta-headers) `mid-conversation-system-clear-at-2026-08-21`. Without it, `clear_at` is rejected as an unknown field.
from line 2043
20262043 
20272044The main use is a per-turn reminder in a tool loop. Each time you want the model to see the reminder, append it after the `tool_result` message. Leave every earlier copy where it is. The model sees only the copies that come after the last user message, so the reminder never piles up. Nothing earlier in `messages` changes, so the [prompt cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) keeps matching. On Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5, this also keeps later [thinking blocks valid](https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation). Deleting an earlier reminder would change the conversation before those blocks, so they would fail the prefix check. A cleared message stays in the array and leaves the conversation before those blocks unchanged.
20282045 
2029The following request is a later step of an agent loop. `messages[3]` rendered on the earlier request, when it was the last message in the array. Once `messages[5]` (a later user message) exists, `messages[3]` is cleared: the cleared message stays in the array, so the conversation before the thinking block in `messages[4]` is unchanged, but the model no longer receives its text. `messages[6]` and `messages[7]` both render, in order.
2046The following request is a later step of an agent loop:
20302047 
2048* `messages[3]` rendered on the earlier request, as the last message in the array.
2049* `messages[5]` is a later user message, so `messages[3]` is cleared. The cleared message stays in the array, so the conversation before the thinking block in `messages[4]` is unchanged, but the model no longer receives its text.
2050* `messages[6]` and `messages[7]` both render, in order.
2051 
20312052```json
20322053{
2033 "model": "claude-fable-5-1",
2054 "model": "claude-opus-5-5",
20342055 "max_tokens": 16000,
20352056 "messages": [
20362057 { "role": "user", "content": "Fix the failing test." },
from line 2123
21022123Rules for turn-scoped messages:
21032124 
21042125* **Resend cleared messages verbatim.** A cleared message is still part of the conversation history. Rebuilding it from current state (a fresh token count, a timestamp), dropping it as redundant, or changing its `clear_at` value is an edit to an earlier message. On Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5, every thinking block produced after it fails the [prefix check](https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation).
2126 
21052127* **Text only.** `content` is one or more `text` blocks (or a string). `tool_addition` and `tool_removal` blocks return a 400 error on a turn-scoped message, and so does `output_config`. Use a separate `role: "system"` message without `clear_at` for those.
2106* **No `cache_control` on its blocks.** A cleared message is never part of a cache key, so a breakpoint on it could never match. Put the breakpoint on the last block of the preceding user turn instead, as the example does. The top-level [automatic caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching) field skips turn-scoped messages when it picks a breakpoint. On the request that clears a message, the reusable cached prefix ends at the user turn before it, so only the one assistant turn between that message and the new user message is reprocessed.
2107* **Placement rules still apply**, cleared or not. A turn-scoped message must follow a `user` turn (or an `assistant` turn ending in a server tool result) and precede an `assistant` turn or end the array, like any mid-conversation system message. One that ends the array always renders. One followed directly by another `user` message is a 400 error, not a cleared message: put all of a tool round’s results in one user message and the reminders after it.
2108* **Assistant turns don’t clear it.** A prefilled or [paused](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#pause-turn) assistant turn after the message, or a server-side tool loop, adds no user message, so the message still renders on that continuation. To keep a reminder in view through a client-side tool loop, append it again after each `tool_result` message.
2128 
2129* **No `cache_control` on its blocks.** A cleared message is never part of a cache key, so a breakpoint on it could never match. Put the breakpoint on the last block of the preceding user turn instead, as the example does. The top-level [automatic caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching) field skips turn-scoped messages when it picks a breakpoint. On the request that appends the next user message, a cache breakpoint on the turn that the cleared message followed, or anywhere earlier, still matches. With the breakpoint on that turn, only the one assistant turn between the cleared message and the new user message is reprocessed.
2130 
2131* **Placement rules still apply**, cleared or not. As with any mid-conversation system message that carries content, a turn-scoped message:
2132 
2133 * Must follow a `user` turn, or an `assistant` turn ending in a server tool result.
2134 * Must precede an `assistant` turn or end the array. If it ends the array, it always renders.
2135 * Can’t have a `user` message directly after it: the request returns a 400 error. A later user message clears it only when an `assistant` turn comes between them. In a tool loop, put all of a round’s tool results in one user message, with the reminders after that message.
2136 * Is judged together with any `system` message directly before or after it. These placement rules apply to the group as a whole.
2137 
2138* **Assistant turns don’t clear it.** An assistant turn [paused with `pause_turn`](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#pause-turn) after the message, or a server-side tool loop, adds no user message, so the message still renders on that continuation. To keep a reminder in view through a client-side tool loop, append it again after each `tool_result` message.
2139 
21092140* **Token counting follows what renders.** A cleared message adds nothing to `usage.input_tokens` or to a [token count](https://platform.claude.com/docs/en/build-with-claude/token-counting).
2110* **Imported history.** In a transcript you construct in one step (few-shot examples, a migrated conversation), a turn-scoped message that already has an assistant turn and a user message after it is cleared from the first request and never renders. That is the right state for a per-turn reminder you are carrying over. Leave `clear_at` unset only on a message that should render on every request.
21112141 
2142* **History you write yourself.** In few-shot examples or a transcript from another system, a turn-scoped message with an assistant turn and a user message after it never renders. If the model should see that text, leave `clear_at` unset, and the message renders on every request. If not, leave the message out. This applies only to history you write yourself: when you resend a conversation with the thinking blocks Claude returned, keep each message exactly as it was, `clear_at` included. See **Resend cleared messages verbatim**.
2143 
21122144The validation errors are:
21132145 
21142146```text wrap
from line 2152
21202152messages.3.content.0: cache_control is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
21212153```
21222154 
2123The first is the error returned without the beta header. On [Claude in Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock), Claude Platform on AWS, Claude Models on Google Cloud (Anthropic managed), and Claude Models on Google Cloud (Google managed), send the beta value in the `anthropic-beta` header, as on the Claude API (see [Beta headers](https://platform.claude.com/docs/en/api/beta-headers)). With the Amazon Bedrock [InvokeModel API](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy), put it in the `anthropic_beta` array of the request body instead.
2155The first is the error returned without the beta header. Send `mid-conversation-system-clear-at-2026-08-21` in the `anthropic-beta` header (see [Beta headers](https://platform.claude.com/docs/en/api/beta-headers)). With the InvokeModel API on [Amazon Bedrock (`bedrock-runtime`)](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy), put it in the `anthropic_beta` array of the request body instead.
21242156 
2125Through the SDK, set `clear_at` (csharp, go: `ClearAt`; java: `.clearAt()`; php: `clearAt`) on the `role: "system"` entry in `messages` and send the beta header. The following example appends a turn-scoped reminder after the user turn; on the next request, once a later user message exists, the reminder stays in the array but no longer renders:
2157Set `clear_at` on the `role: "system"` entry in `messages` and send the beta header. The following example appends a turn-scoped reminder after the user turn. On the next request, once a later user message exists, the reminder stays in the array but no longer renders:
21262158 
21272159<CodeGroup>
21282160 ```bash cURL
from line 2164
21322164 -H "anthropic-beta: mid-conversation-system-clear-at-2026-08-21" \
21332165 -H "content-type: application/json" \
21342166 -d '{
2135 "model": "claude-fable-5-1",
2167 "model": "claude-opus-5-5",
21362168 "max_tokens": 4096,
21372169 "messages": [
21382170 {"role": "user", "content": "Draft a short status update on the database migration for the team channel."},
from line 2176
21442176 ```bash CLI
21452177 ant beta:messages create \
21462178 --beta mid-conversation-system-clear-at-2026-08-21 <<'YAML'
2147 model: claude-fable-5-1
2179 model: claude-opus-5-5
21482180 max_tokens: 4096
21492181 messages:
21502182 - role: user
21512183 content: Draft a short status update on the database migration for the team channel.
2152 # Turn-scoped reminder: renders for this turn, then clears once a later user message exists.
2184 # Turn-scoped reminder: renders for this turn, then stops rendering once a later user message exists.
21532185 - role: system
21542186 clear_at: next_user_message
21552187 content: "The reader is on call: keep this reply under 50 words."
from line 2192
21602192 client = anthropic.Anthropic()
21612193 
21622194 response = client.beta.messages.create(
2163 model="claude-fable-5-1",
2195 model="claude-opus-5-5",
21642196 max_tokens=4096,
21652197 messages=[
21662198 {
from line 2199
21672199 "role": "user",
21682200 "content": "Draft a short status update on the database migration for the team channel.",
21692201 },
2170 # Turn-scoped reminder: renders for this turn, then clears once a later user message exists.
2202 # Turn-scoped reminder: renders for this turn, then stops rendering once a later user message exists.
21712203 {
21722204 "role": "system",
21732205 "clear_at": "next_user_message",
from line 2218
21862218 const client = new Anthropic();
21872219 
21882220 const response = await client.beta.messages.create({
2189 model: "claude-fable-5-1",
2221 model: "claude-opus-5-5",
21902222 max_tokens: 4096,
21912223 messages: [
21922224 {
from line 2225
21932225 role: "user",
21942226 content: "Draft a short status update on the database migration for the team channel."
21952227 },
2196 // Turn-scoped reminder: renders for this turn, then clears once a later user message exists.
2228 // Turn-scoped reminder: renders for this turn, then stops rendering once a later user message exists.
21972229 {
21982230 role: "system",
21992231 clear_at: "next_user_message",
from line 2251
22192251 
22202252 var response = await client.Beta.Messages.Create(new MessageCreateParams
22212253 {
2222 Model = Messages::Model.ClaudeFable5_1,
2254 Model = Messages::Model.ClaudeOpus5_5,
22232255 MaxTokens = 4096,
22242256 Messages =
22252257 [
22262258 new BetaUserMessageParam { Content = "Draft a short status update on the database migration for the team channel." },
2227 // Turn-scoped reminder: renders for this turn, then clears once a later user message exists.
2259 // Turn-scoped reminder: renders for this turn, then stops rendering once a later user message exists.
22282260 new BetaSystemMessageParam
22292261 {
22302262 ClearAt = ClearAt.NextUserMessage,
from line 2279
22472279 client := anthropic.NewClient()
22482280 
22492281 response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
2250 Model: anthropic.ModelClaudeFable5_1,
2282 Model: anthropic.ModelClaudeOpus5_5,
22512283 MaxTokens: 4096,
22522284 Messages: []anthropic.BetaMessageParam{
22532285 anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Draft a short status update on the database migration for the team channel.")),
2254 // Turn-scoped reminder: renders for this turn, then clears once a later user message exists.
2286 // Turn-scoped reminder: renders for this turn, then stops rendering once a later user message exists.
22552287 {OfSystem: &anthropic.BetaSystemMessageParam{
22562288 ClearAt: anthropic.BetaSystemMessageParamClearAtNextUserMessage,
22572289 Content: []anthropic.BetaSystemMessageParamContentUnion{{OfText: &anthropic.BetaTextBlockParam{Text: "The reader is on call: keep this reply under 50 words."}}},
from line 2307
22752307 import com.anthropic.models.beta.messages.BetaMessage;
22762308 import com.anthropic.models.beta.messages.BetaSystemMessageParam;
22772309 import com.anthropic.models.beta.messages.MessageCreateParams;
2278 import com.anthropic.models.messages.Model;
2310 // ...
22792311 
22802312 void main() {
22812313 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
22822314 
22832315 MessageCreateParams params = MessageCreateParams.builder()
2284 .model(Model.CLAUDE_FABLE_5_1)
2316 .model(Model.CLAUDE_OPUS_5_5)
22852317 .maxTokens(4096L)
22862318 .addBeta(AnthropicBeta.MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21)
22872319 .addUserMessage("Draft a short status update on the database migration for the team channel.")
2288 // Turn-scoped reminder: renders for this turn, then clears once a later user message exists.
2320 // Turn-scoped reminder: renders for this turn, then stops rendering once a later user message exists.
22892321 .addMessage(BetaSystemMessageParam.builder()
22902322 .clearAt(BetaSystemMessageParam.ClearAt.NEXT_USER_MESSAGE)
22912323 .content("The reader is on call: keep this reply under 50 words.")
from line 2334
23022334 ```php PHP
23032335 use Anthropic\Beta\AnthropicBeta;
23042336 use Anthropic\Beta\Messages\BetaMessageParam;
2305 use Anthropic\Client;
2337 use Anthropic\Beta\Messages\BetaTextBlock;
2338 // ...
23062339 
23072340 $client = new Client();
23082341 
23092342 $response = $client->beta->messages->create(
2310 model: 'claude-fable-5-1',
2343 model: Model::CLAUDE_OPUS_5_5,
23112344 maxTokens: 4096,
23122345 messages: [
23132346 BetaMessageParam::with(role: 'user', content: 'Draft a short status update on the database migration for the team channel.'),
2314 // Turn-scoped reminder: renders for this turn, then clears once a later user message exists.
2347 // Turn-scoped reminder: renders for this turn, then stops rendering once a later user message exists.
23152348 BetaMessageParam::with(
23162349 role: 'system',
23172350 clearAt: 'next_user_message',
from line 2355
23222355 );
23232356 
23242357 foreach ($response->content as $block) {
2325 if ($block->type === 'text') {
2358 if ($block instanceof BetaTextBlock) {
23262359 echo $block->text, PHP_EOL;
23272360 }
23282361 }
from line 2365
23322365 client = Anthropic::Client.new
23332366 
23342367 response = client.beta.messages.create(
2335 model: Anthropic::Model::CLAUDE_FABLE_5_1,
2368 model: Anthropic::Model::CLAUDE_OPUS_5_5,
23362369 max_tokens: 4096,
23372370 messages: [
2338 {role: "user", content: "Draft a short status update on the database migration for the team channel."},
2339 # Turn-scoped reminder: renders for this turn, then clears once a later user message exists.
2340 {role: "system", clear_at: :next_user_message, content: "The reader is on call: keep this reply under 50 words."}
2371 { role: "user", content: "Draft a short status update on the database migration for the team channel." },
2372 # Turn-scoped reminder: renders for this turn, then stops rendering once a later user message exists.
2373 { role: "system", clear_at: :next_user_message, content: "The reader is on call: keep this reply under 50 words." }
23412374 ],
23422375 betas: [Anthropic::AnthropicBeta::MID_CONVERSATION_SYSTEM_CLEAR_AT_2026_08_21]
23432376 )
from line 2395
23622395## Limitations
23632396 
23642397* **Not for the first message.** A `system` message that carries content cannot be the first entry in `messages`. Use the top-level `system` field for instructions that apply from the very start.
2365* **Placement is constrained.** A `system` message that carries content (`text`, `tool_addition`, or `tool_removal` blocks) must immediately follow a `user` turn (including a `user` turn that carries `tool_result` blocks) or an `assistant` turn ending in a server tool result, and must precede an `assistant` turn or end the array. It cannot sit between a `tool_use` block and its `tool_result`. Placing it elsewhere returns a 400 error. One exception: `tool_addition` and `tool_removal` blocks are not accepted immediately after a [paused](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#pause-turn) `assistant` turn (one ending in a server tool result), though `text` blocks are; resume the paused turn first, then send the tool change in the next `system` message. A message with empty `content` that only sets [`output_config.effort`](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) renders nothing at its position and is accepted anywhere in `messages`, including first or between an `assistant` turn and a `user` turn. Consecutive `system` messages are judged together, so adding a text-carrying message next to an effort-only one makes the whole group follow the content rule.
2398* **Placement is constrained.** A `system` message that carries content (`text`, `tool_addition`, or `tool_removal` blocks) must immediately follow a `user` turn or an `assistant` turn ending in a server tool result. A `user` turn that carries `tool_result` blocks counts. The message must precede an `assistant` turn or end the array. It cannot sit between a `tool_use` block and its `tool_result`. Placing it elsewhere returns a 400 error. One exception: `tool_addition` and `tool_removal` blocks are not accepted immediately after a [paused](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#pause-turn) `assistant` turn (one ending in a server tool result), though `text` blocks are. Resume the paused turn first, then send the tool change in the next `system` message. A message with empty `content` that only sets [`output_config.effort`](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) renders nothing at its position. It can follow any turn, or come first, but goes after everything already sent. Consecutive `system` messages are judged together, so adding a text-carrying message next to an effort-only one makes the whole group follow the content rule.
23662399* **Turn-scoped messages are text-only and re-sent verbatim.** A `clear_at: "next_user_message"` message carries no `tool_addition`, `tool_removal`, `output_config`, or `cache_control`, and once cleared it must stay in `messages` byte-for-byte on later requests. See [Turn-scoped system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages).
23672400* **Not a place for untrusted content.** Claude treats system content as operator instructions and follows it. Do not place text from outside the conversation, such as raw tool output, retrieved documents, or web content, directly in a system message; doing so gives that text operator-level authority. Keep that data in `tool_result` blocks and continue to follow [Mitigate jailbreaks and prompt injections](https://platform.claude.com/docs/en/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks).
23682401 
from line 2407
23742407 </Card>
23752408 
23762409 <Card title="Cache diagnostics" icon="magnifying-glass" href="https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics">
2377 Find out exactly where two requests diverged when a cache hit you expected does not occur.
2410 Find out what changed between two requests when a cache hit you expected does not occur.
23782411 </Card>
23792412 
23802413 <Card title="Using the Messages API" icon="message" href="https://platform.claude.com/docs/en/build-with-claude/working-with-messages">
from line 2434
24012434* Availability: Available
24022435* Usage: Append a message with `role` `"system"` to `messages` at the point where the instruction starts to apply.
24032436 
2404| Status | Cloud platforms | Models |
2405| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
2406| Available | Claude API, [Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws), [Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed), [Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed) | [Claude Fable 5.2](https://platform.claude.com/docs/en/models/fable-5-2/overview), [Claude Mythos 5.2](https://platform.claude.com/docs/en/models/mythos-5-2/overview), [Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/overview), [Claude Mythos 5.1](https://platform.claude.com/docs/en/models/mythos-5-1/overview), [Claude Fable 5](https://platform.claude.com/docs/en/models/fable-5/overview), [Claude Mythos 5](https://platform.claude.com/docs/en/models/mythos-5/overview), Claude Mythos Preview, [Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/overview), [Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/overview), [Claude Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview), [Claude Haiku 5.5](https://platform.claude.com/docs/en/models/haiku-5-5/overview), [Claude Opus 4.8](https://platform.claude.com/docs/en/models/opus-4-8/overview) |
2407| Available<sup>1</sup> | [Amazon Bedrock (bedrock-runtime)](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy) | [Claude Fable 5.2](https://platform.claude.com/docs/en/models/fable-5-2/overview), [Claude Mythos 5.2](https://platform.claude.com/docs/en/models/mythos-5-2/overview), [Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/overview), [Claude Fable 5](https://platform.claude.com/docs/en/models/fable-5/overview), [Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/overview), [Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/overview), [Claude Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview), [Claude Haiku 5.5](https://platform.claude.com/docs/en/models/haiku-5-5/overview), [Claude Opus 4.8](https://platform.claude.com/docs/en/models/opus-4-8/overview) |
2408| Available | [Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock) | [Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/overview), [Claude Mythos 5.1](https://platform.claude.com/docs/en/models/mythos-5-1/overview), [Claude Fable 5](https://platform.claude.com/docs/en/models/fable-5/overview), [Claude Mythos 5](https://platform.claude.com/docs/en/models/mythos-5/overview), [Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/overview), [Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/overview), [Claude Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview), [Claude Haiku 5.5](https://platform.claude.com/docs/en/models/haiku-5-5/overview), [Claude Opus 4.8](https://platform.claude.com/docs/en/models/opus-4-8/overview) |
2437| Status | Cloud platforms | Models |
2438| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2439| Available | Claude API, [Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws), [Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed), [Claude Models on Google Cloud (Google managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/google-managed), [Microsoft Foundry](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry) | [Claude Fable 5.2](https://platform.claude.com/docs/en/models/fable-5-2/overview), [Claude Mythos 5.2](https://platform.claude.com/docs/en/models/mythos-5-2/overview), [Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/overview), [Claude Mythos 5.1](https://platform.claude.com/docs/en/models/mythos-5-1/overview), [Claude Fable 5](https://platform.claude.com/docs/en/models/fable-5/overview), [Claude Mythos 5](https://platform.claude.com/docs/en/models/mythos-5/overview), [Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/overview), [Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/overview), [Claude Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview), [Claude Haiku 5.5](https://platform.claude.com/docs/en/models/haiku-5-5/overview), [Claude Opus 4.8](https://platform.claude.com/docs/en/models/opus-4-8/overview) |
2440| Available<sup>1</sup> | [Amazon Bedrock (bedrock-runtime)](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy) | [Claude Fable 5.2](https://platform.claude.com/docs/en/models/fable-5-2/overview), [Claude Mythos 5.2](https://platform.claude.com/docs/en/models/mythos-5-2/overview), [Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/overview), [Claude Fable 5](https://platform.claude.com/docs/en/models/fable-5/overview), [Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/overview), [Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/overview), [Claude Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview), [Claude Haiku 5.5](https://platform.claude.com/docs/en/models/haiku-5-5/overview), [Claude Opus 4.8](https://platform.claude.com/docs/en/models/opus-4-8/overview) |
2441| Available | [Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock) | [Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/overview), [Claude Mythos 5.1](https://platform.claude.com/docs/en/models/mythos-5-1/overview), [Claude Fable 5](https://platform.claude.com/docs/en/models/fable-5/overview), [Claude Mythos 5](https://platform.claude.com/docs/en/models/mythos-5/overview), [Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/overview), [Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/overview), [Claude Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview), [Claude Haiku 5.5](https://platform.claude.com/docs/en/models/haiku-5-5/overview), [Claude Opus 4.8](https://platform.claude.com/docs/en/models/opus-4-8/overview) |
24092442 
241024431. Through InvokeModel only (not Converse).
24112444 
from line 2447
24142447* Availability: Available
24152448* Usage: Send a `system.message` event. It applies to that turn and all later turns; the agent’s own `system` field cannot change during a session.
24162449 
2417| Status | Cloud platforms | Models |
2418| --------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
2419| Available | All supported platforms | [Claude Fable 5.2](https://platform.claude.com/docs/en/models/fable-5-2/overview), [Claude Mythos 5.2](https://platform.claude.com/docs/en/models/mythos-5-2/overview), [Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/overview), [Claude Mythos 5.1](https://platform.claude.com/docs/en/models/mythos-5-1/overview), [Claude Fable 5](https://platform.claude.com/docs/en/models/fable-5/overview), [Claude Mythos 5](https://platform.claude.com/docs/en/models/mythos-5/overview), Claude Mythos Preview, [Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/overview), [Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/overview), [Claude Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview), [Claude Haiku 5.5](https://platform.claude.com/docs/en/models/haiku-5-5/overview), [Claude Opus 4.8](https://platform.claude.com/docs/en/models/opus-4-8/overview) |
2450| Status | Cloud platforms | Models |
2451| --------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2452| Available | All supported platforms | [Claude Fable 5.2](https://platform.claude.com/docs/en/models/fable-5-2/overview), [Claude Mythos 5.2](https://platform.claude.com/docs/en/models/mythos-5-2/overview), [Claude Fable 5.1](https://platform.claude.com/docs/en/models/fable-5-1/overview), [Claude Mythos 5.1](https://platform.claude.com/docs/en/models/mythos-5-1/overview), [Claude Fable 5](https://platform.claude.com/docs/en/models/fable-5/overview), [Claude Mythos 5](https://platform.claude.com/docs/en/models/mythos-5/overview), [Claude Opus 5.5](https://platform.claude.com/docs/en/models/opus-5-5/overview), [Claude Opus 5](https://platform.claude.com/docs/en/models/opus-5/overview), [Claude Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview), [Claude Haiku 5.5](https://platform.claude.com/docs/en/models/haiku-5-5/overview), [Claude Opus 4.8](https://platform.claude.com/docs/en/models/opus-4-8/overview) |
24202453 
24212454### Data handling
24222455 

build-with-claude/preserved-thinking/change-tools-or-instructions New page · 295 lines, new page

## Send assistant turns back exactly ## Change instructions ## Text that other people can edit ## Update the date, files, or other context ## Add, remove, or turn off tools ## Trim or summarize older turns ## Save, resume, or fork a conversation ## Remove secrets, personal data, or injected text ## Technical details ### Ways code changes assistant turns ### Leave out thinking ### Your instructions in a tool loop ### Write the tool call yourself ### Your user’s words, and updated values, in a tool loop ### Models that don’t accept system messages ### Send a reminder for one turn ### Which block and beta header a tool change needs ### Tools with `defer_loading`, and the 400 error that names it ### Shorten or clear old results and images ### Files you send by URL ### If your own code summarizes or cuts older turns ### Libraries, proxies, and gateways ## Next steps

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Change tools or instructions without failing the prefix check
url: https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions
description: Send an instruction, tool, reminder, or summary, resume a saved conversation, or pass on other people's requests, so that Claude keeps its earlier thinking.
featureMetadata:
  status: stable
  supportedModels:
    - claude-fable-5-2
    - claude-mythos-5-2
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-opus-5-5
    - claude-sonnet-5-5
    - claude-haiku-5-5
  supportedPlatforms:
    Claude API: stable
    Amazon Bedrock: stable
    Amazon Bedrock (bedrock-runtime): stable
    Claude Platform on AWS: stable
    Claude Models on Google Cloud (Anthropic managed): stable
    Claude Models on Google Cloud (Google managed): stable
    Microsoft Foundry: stable
---

To update tools, instructions, or other context, leave everything you sent as it was, and add the update at the end, where it stays. On models with preserved thinking, changing what you sent can make the thinking after it invalid, and [the request can fail](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes).

The models with preserved thinking are Claude Fable 5.2, Claude Mythos 5.2, Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5.

## Send assistant turns back exactly

Send back the whole `content` array of each response, in order, including thinking blocks whose text is empty. A block with empty text is complete, because its `signature` holds the reasoning, encrypted. A turn that holds a [`fallback` block](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#continuing-the-conversation) has its own rule.

[Serializers, filters, and stream parsers](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#append-assistant-turns-exactly-as-returned-details) can break this.

## Change instructions

Keep `system` the same on every request. Put your own instructions in a `role: "system"` message at the end, and send one only when something has changed. Claude treats it as an instruction from you, the operator. Leave it for the rest of the conversation, because deleting or rewording it later makes the thinking after it invalid. [Your user’s words](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#user-words) have their own rule.

A reminder that must come with every turn is different: [send one that clears itself](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#per-turn-reminders).

The system message goes after the newest user message, even one with [tool results](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#new-instructions-details). A system message with text or tool blocks gets a 400 error right after Claude’s turn or right before a user message. So when Claude’s turn is last, wait until the next user message is in place.

A system message doesn’t guarantee that Claude follows an instruction, so apply limits such as read-only mode in the code that runs your tools. Some models [don’t accept system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages).

## Text that other people can edit

Ask whether your user would expect Claude to trust a file, such as an `AGENTS.md` or `CLAUDE.md` that other people can edit, or stored memory. If not, send its text only in a `tool_result` block, the first version included. For why, see [Indirect prompt injection](https://platform.claude.com/docs/en/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks#indirect-prompt-injection).

Don’t put such text in a system message or in the text of a user message, and in new conversations, don’t put it in `system`.

When you load such a file or it changes, tell Claude to read it with a tool, and don’t include its text. Or, after the next user message, append the tool call and its result yourself: an `assistant` message with a `tool_use` block, then a `user` message whose `tool_result` block holds the text. For the steps, see [Write the tool call yourself](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#write-the-tool-call).

A file that your user expects Claude to follow can go in a user message. An instruction file that only you control can go in a system message: load it once, and append each updated version.

## Update the date, files, or other context

Build `system` and the first message once, and send them unchanged on every request.

Put an updated value in its own text block of the user message you’re about to send, [after any tool results](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#user-words):

```json
{
  "role": "user",
  "content": [
    { "type": "text", "text": "Environment update: the current branch is now release-2." },
    { "type": "text", "text": "Run the tests again." }
  ]
}
```

State it only when it changes, and leave it there.

Store any context that your code adds to a message with that message. Otherwise the next request sends something different before the same thinking.

## Add, remove, or turn off tools

Keep `tools` the same on every request. Adding, changing, or removing a tool there, other than [a deferred one](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#deferred-tools), makes the thinking already in the conversation invalid, because `tools` comes before all of it. One reworded sentence in a description is enough.

To add or remove a tool, append a system message with a `tool_addition` or `tool_removal` block and [the beta header for your case](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#tool-changes-details). Do the same when an MCP server or plugin connects.

To turn tools off for one request, set `tool_choice: {"type": "none"}`, and keep `tools` as it was.

## Trim or summarize older turns

To keep recent turns with their thinking, let the API write the summary with [on-demand compaction](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#request-a-summary), under the [conditions for kept thinking](https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid). Start `messages` with the compaction block it returns, and remove the messages it summarizes.

If your own code writes the summary, or cuts older turns without one, [remove the kept turns’ thinking or send `"drop_block"`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#server-side-trimming-details). Each new cut makes the kept turns’ thinking invalid again, so cut rarely, in large steps. To clear old tool results instead, [use context editing](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#clear-old-content).

## Save, resume, or fork a conversation

Store what you sent and what you received, and send exactly that. A resumed conversation is an ordinary next request: `system`, `tools`, and earlier `messages` must have the values they had. For a fork, put the branch’s instruction in its first new user message, or in a system message after that. Thinking can’t move to a conversation with a different history: start that conversation from a summary instead.

A release that changes your system prompt or tools is a change in conversations already running. The fix that makes your code append-only can be one too. Keep sending each running conversation the `system` and `tools` of its last successful request, because its newest thinking was produced after that version. Going back to an earlier version would make that thinking invalid.

Use the updated `system` and `tools` in new conversations. If the release removes a tool or changes an instruction for safety, apply it to running conversations too. Append [a `tool_removal` block](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#tool-changes) or [a system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#new-instructions).

## Remove secrets, personal data, or injected text

Safety and privacy come before keeping thinking valid. If a message holds a secret or personal data you must delete, remove that text. Remove it from every message and summary that repeats it, too.

For a tool result with injected instructions, replace its content with a short note such as “Removed.” Keep the `tool_result` block itself, because its `tool_use` needs one. If a [compaction block](https://platform.claude.com/docs/en/build-with-claude/compaction) holds the text, delete the block, and start from your own summary.

Then delete every `thinking` and `redacted_thinking` block after the first place the text appeared. If it was in `system` or `tools`, that’s all of them. Each block can repeat the text, and you can’t read or edit what’s inside. Sending `"drop_block"` isn’t enough here, because it leaves those blocks in your stored history. The conversation carries on without that reasoning.

After an injected result, later turns might already have acted on it. Check the tool calls made since, and undo what you need to.

## Technical details

### Ways code changes assistant turns

* A serializer drops block types it doesn’t know, or reorders, merges, or splits blocks. That changes what came before every later block.
* Code skips thinking blocks that look empty. If it skips all of them, Claude loses that reasoning. If it skips only some, the gap makes the thinking after it invalid.
* A stream parser of your own drops a thinking block that got no text. The SDK’s stream helpers keep it.

### Leave out thinking

Claude loses the reasoning you leave out. Leave out the oldest blocks, the newest, or all of them, but none in between. Each block records the one it was produced after, so a gap makes the blocks after it invalid. Thinking blocks with no other block between them in a turn are checked together, so leave out all of them or none. Once a block is out, keep it out.

While a tool call is open, [send that turn’s thinking back](https://platform.claude.com/docs/en/build-with-claude/thinking#preserving-thinking-blocks), so that Claude finishes the round with its reasoning.

### Your instructions in a tool loop

The messages go in this order:

```json
[
  {
    "role": "assistant",
    "content": [
      { "type": "thinking", "thinking": "", "signature": "..." },
      {
        "type": "tool_use",
        "id": "toolu_01",
        "name": "run_tests",
        "input": { "path": "tests/" }
      }
    ]
  },
  {
    "role": "user",
    "content": [
      { "type": "tool_result", "tool_use_id": "toolu_01", "content": "2 failed, 48 passed" }
    ]
  },
  {
    "role": "system",
    "content": "Plan mode is off. You can edit files."
  }
]
```

### Write the tool call yourself

Declare a tool that reads files on the first request, or [add it later in a system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#tool-changes), and have your code answer Claude’s calls to it. After the next user message, append an `assistant` message with a `tool_use` block for that tool. Directly after it, append a `user` message whose `tool_result` block has the matching `tool_use_id` and holds the file’s text. Claude answers after that:

```json
[
  { "role": "user", "content": "Run the tests again." },
  {
    "role": "assistant",
    "content": [
      {
        "type": "tool_use",
        "id": "toolu_app_agents_md_1",
        "name": "read_file",
        "input": { "path": "AGENTS.md" }
      }
    ]
  },
  {
    "role": "user",
    "content": [
      {
        "type": "tool_result",
        "tool_use_id": "toolu_app_agents_md_1",
        "content": "The file's text"
      }
    ]
  }
]
```

Leave both in place, and append a new pair, with a new `id`, for each new version.

### Your user’s words, and updated values, in a tool loop

If you pass on what your user typed while Claude was working, add it before you send the user message that carries the `tool_result` blocks. Make it a text block after the last `tool_result`.

A value that comes from you can go in a system message instead. After tool results, Claude Sonnet 5.5 and Claude Haiku 5.5 can ignore a user’s words in a system message as a prompt injection. Claude Sonnet 5.5 can do the same with your own instructions and reminders if they come after every tool result.

The user message with the tool results must hold only `tool_result` blocks when the turn also called a [server tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls) that has no result yet, or used programmatic tool calling. Then add the text to the next user message.

### Models that don’t accept system messages

On the Claude API, every model with preserved thinking accepts system messages. For a model that doesn’t, see [When a model doesn’t accept system messages](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#unchosen-switches-details).

### Send a reminder for one turn

Send a reminder as a [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages): set `clear_at: "next_user_message"`, and send the beta header `mid-conversation-system-clear-at-2026-08-21`. It goes after the user message that carries the `tool_result` blocks:

```json
{
  "role": "system",
  "clear_at": "next_user_message",
  "content": "Run the linter before you report that a task is done."
}
```

At the next user message, even one with only `tool_result` blocks, the API clears it, so Claude stops reading it. On Claude Sonnet 5.5, [don’t send one after every tool result](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#user-words). Keep every reminder in your `messages`, cleared or not, unless it [holds something you must remove](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#remove-sensitive-content). Removing or rewording one makes the thinking after it invalid.

Without the header, send a plain system message and leave it in place. It never clears, so reminders pile up. On a model that takes no system messages, use a text block in the user message.

### Which block and beta header a tool change needs

For the platforms that take each header, see [Mid-conversation system messages and tool changes](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages).

* **If you know every tool at the start:** Declare them all on the first request, with `defer_loading: true` on those you offer later. Then name the tool in a `tool_addition` or `tool_removal` block of a system message. Beta header: `inline-tools-2026-09-15` or `mid-conversation-tool-changes-2026-07-01`.
* **If you learn of a tool later, or have one whose schema changes:** Define the tool in a `tool_addition` block of a system message. Beta header: `inline-tools-2026-09-15`.
* **If you learn of a tool later, on a platform without the `inline-tools-2026-09-15` header:** Add the tool to the end of `tools` with `defer_loading: true`, which isn’t a change, then offer it by name. Beta header: `mid-conversation-tool-changes-2026-07-01`.
* **If you connect an MCP server through the MCP connector late, on the Claude API:** Define its `mcp_toolset` in a `tool_addition` block. Beta headers: `inline-tools-2026-09-15` and `mcp-client-2026-09-15`.

If an MCP server’s tool list can change, see [Pin an MCP server’s tool list](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector#pin-mcp-tool-list).

This system message offers a declared tool by name and defines another, which needs `inline-tools-2026-09-15`:

```json
{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": { "type": "tool_reference", "name": "search_tickets" }
    },
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": {
          "name": "get_weather",
          "description": "Get the current weather in a city.",
          "input_schema": {
            "type": "object",
            "properties": { "city": { "type": "string" } },
            "required": ["city"]
          }
        }
      }
    }
  ]
}
```

### Tools with `defer_loading`, and the 400 error that names it

A tool with `defer_loading: true` stays out of Claude’s context and the prefix check until a message or tool search result refers to it. Until then, adding, updating, or removing it isn’t a change. Afterward it is. Turning `defer_loading` on or off counts as changing `tools`, too.

Declare at least one tool that isn’t deferred, or the request can get a 400 error that names `defer_loading`.

### Shorten or clear old results and images

Shorten or downscale a tool result or image before you first send it. If your code clears, shortens, or re-encodes something it already sent, the thinking after it becomes invalid. To clear old tool results later, including any images inside them, use context editing. Send `context_management` with an edit of type `clear_tool_uses_20250919`, and the beta header `context-management-2025-06-27`. For the full request and its options, see [Context editing](https://platform.claude.com/docs/en/build-with-claude/context-editing#tool-result-clearing).

### Files you send by URL

For a file by URL, the API compares the bytes it fetched. So when a signed URL expires, a fresh one for the same file is fine. If the content behind a URL can change, send a `file_id` or base64 from the first request.

### If your own code summarizes or cuts older turns

After your own summary or cut, a kept turn’s thinking fails the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check), because the messages it followed are gone. Remove that thinking, or [send `"drop_block"`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#preserved-thinking-controls). Claude still reads the turn without it.

### Libraries, proxies, and gateways

If other people’s requests pass through your code, your rewrites change their history, and they might not be able to see or fix those changes. Don’t hide the 400 error. If you recover for the caller, say so, because their history still holds the change.

* Pass `anthropic-beta` values and `thinking.block_binding` through as sent. If your gateway allows only known fields, add `thinking.block_binding` and the header value `thinking-binding-controls-2026-08-01`, or your users can’t choose `"drop_block"`.
* Don’t remove the beta header and forward the setting. That request gets a 400 error.
* Return thinking blocks whose text is empty, and the `input_transformations` array, to the caller.
* Leave a `role: "system"` message where it is. Moving it into `system` makes the thinking already in the conversation invalid.
* Test with [`prefix_mismatch_behavior`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#preserved-thinking-controls) set to `"error"`, which gives the error on every model with preserved thinking.

## Next steps

<CardGroup cols={2}>
  <Card title="Preserved thinking" icon="book" href="https://platform.claude.com/docs/en/build-with-claude/preserved-thinking">
    What preserved thinking is, what a thinking block is tied to, and switching models or accounts.
  </Card>

  <Card title="Fix a thinking block bound to a different conversation" icon="wrench" href="https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation">
    Recover a failing conversation, and see what dropping thinking costs.
  </Card>

  <Card title="Mid-conversation system messages and tool changes" icon="message" href="https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages">
    Where system messages and tool changes go, and which models and platforms take them.
  </Card>
</CardGroup>

build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation New page · 543 lines, new page

## Error: The block is bound to a different conversation ## What dropping thinking costs ## Find what your code changed ## Test your code for prefix check failures ## Watch production, and find reasoning lost with no error ## Technical details ### What else the error message can say ### The error still asks for the header, or says `Extra inputs are not permitted` ### Remove the invalid thinking by hand ### Errors that look like this one ### When you can stop sending `"drop_block"` ### Handle the error in code ### You have no error, or one that doesn’t say what changed ### Five steps for a test that can fail, and a program that runs them ### What each `input_transformations` entry means, and which are yours to fix ### Batches and token counting ## Next steps

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Fix a thinking block bound to a different conversation
url: https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation
description: Get a conversation going again after the 400 error that says a thinking block is bound to a different conversation, find what your code changed, and test that the change is gone.
featureMetadata:
  status: stable
  supportedModels:
    - claude-fable-5-2
    - claude-mythos-5-2
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-opus-5-5
    - claude-sonnet-5-5
    - claude-haiku-5-5
  supportedPlatforms:
    Claude API: stable
    Amazon Bedrock: stable
    Amazon Bedrock (bedrock-runtime): stable
    Claude Platform on AWS: stable
    Claude Models on Google Cloud (Anthropic managed): stable
    Claude Models on Google Cloud (Google managed): stable
    Microsoft Foundry: stable
---

Sending the same request again can’t work, because your history still holds what your code changed. Send `"drop_block"` to [stop the errors now](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#prefix-mismatch-error). The long-term fix is to make your code [append-only](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check).

## Error: The block is bound to a different conversation

The thinking block failed the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check): something before it changed after Claude produced it (see [What counts as a change](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#what-counts-as-an-edit)), or a thinking block between others was left out or moved. The error looks like this, and can go on to [name what changed](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#prefix-mismatch-error-details):

```text wrap
messages.1.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".
```

“A different conversation” means different content before the block: the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check) doesn’t compare sessions or users. The error message says to remove the block, but [removing only that block isn’t enough](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#remove-by-hand). [Other errors](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#similar-errors) can look similar.

If the app isn’t yours, start a new conversation and tell its maintainer. If you [removed a secret, personal data, or injected text](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#remove-sensitive-content), or your requests [turn thinking off](https://platform.claude.com/docs/en/build-with-claude/thinking#turning-thinking-off), [remove the thinking by hand](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#remove-by-hand) instead of step 1.

<Steps>
  <Step title="Stop the errors now">
    Set `thinking.block_binding.prefix_mismatch_behavior` to `"drop_block"`, and send the [beta header](https://platform.claude.com/docs/en/api/beta-headers#beta-features-on-other-platforms) `anthropic-beta: thinking-binding-controls-2026-08-01`. Do this on every later request in the conversation, because the API doesn’t store the setting between requests. A saved conversation still holds the change, even after you fix your code, so store the setting with it. Set `type` to `"adaptive"`, as shown:

    ```json
    {
      "thinking": {
        "type": "adaptive",
        "block_binding": {
          "prefix_mismatch_behavior": "drop_block"
        }
      }
    }
    ```

    In the SDK, call the beta Messages method and pass the header value, as [the test program](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#how-to-tell-whether-your-integration-is-impacted-details) does. If the error [still asks for the header](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#setting-not-received), the header didn’t arrive.

    That stops the errors by dropping the invalid thinking, but it [can cost more](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#drop-block-cost) and can affect output quality and latency. The next request succeeds, and its `input_transformations` array lists each block the API dropped.

    If your requests don’t set the `thinking` parameter, adding it changes nothing else, because [models with preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes) think adaptively by default.
  </Step>

  <Step title="Long-term fix">
    Make your integration append-only:

    1. Find the change. The error can name it. To find where your code makes it, run `claude update`, then run `/claude-api preserved-thinking-migration` in Claude Code in your code’s repository. Or [look by hand](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#find-the-change-details).
    2. Stop making the change, or new conversations can get the error too. [Send an update at the end instead](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions).
    3. Keep sending each running conversation the `system` and `tools` of [its last successful request](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#saved-sessions).
  </Step>
</Steps>

If the change was recent, you can undo it instead: put back what your code changed. The thinking from before the change is valid again. Thinking produced since then fails, so remove it or keep sending `"drop_block"`.

## What dropping thinking costs

Claude can spend more output tokens working out reasoning it can no longer read. Dropping the blocks also invalidates the prompt cache from the first dropped block onward.

When something changes on every turn, every turn loses the thinking from earlier turns, so the increase repeats. Run evals on your own workload before you rely on `"drop_block"`.

<Frame>
  ![Four requests after a change: the first is rejected; the next three drop the old thinking and keep each new block](https://platform.claude.com/docs/images/preserved-thinking-drop-block-loss.svg)
</Frame>

Use `"drop_block"` to keep existing conversations going while they hold a change you’re fixing, and for a planned drop, such as [after your own summary](https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks#own-summary). Don’t leave it on to hide a change your code keeps making. You can [stop sending it](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#drop-block-cost-details) once the invalid blocks are out of the history.

## Find what your code changed

The change is before the first block that the API names. The 400 error can say what changed, such as `system`, `tools`, a missing thinking block, or the first message that differs. With no error, or one that doesn’t say, [start from what you have](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#find-the-change-details), such as a `prefix_binding_mismatch` entry or more output tokens.

## Test your code for prefix check failures

You can trust a test once you’ve seen it fail. First, through your own code, run a session that makes Claude think, and change something on purpose. Send `"drop_block"` for this step, so the response lists every invalid block instead of stopping at the first, as [five steps and a program](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#how-to-tell-whether-your-integration-is-impacted-details) show.

Then take that change out, and run your real sessions. On every request, send the beta header `thinking-binding-controls-2026-08-01`, and set [`prefix_mismatch_behavior`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#preserved-thinking-controls) to `"error"`, so a change your code makes in those sessions fails the build with the 400 error.

Test sessions that compact, add tools late, change instructions, [switch models](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#switching-models), or resume: plain turns don’t reach that code.

A clean run has no `prefix_binding_mismatch` entry and no error. It shows only that the blocks it checked are valid, in the sessions you ran. It proves nothing if:

* the session had no thinking blocks
* your code removes all thinking, or the model doesn’t have preserved thinking
* you didn’t send the beta header, and [the model might let failing blocks through](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes) without an error

## Watch production, and find reasoning lost with no error

Log each 400 error, and [handle it in code](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#handle-the-error-in-code) so the conversation carries on. If you leave `prefix_mismatch_behavior` unset instead, [watch production traffic](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#watch-production-traffic) for failing thinking that reached Claude.

Reasoning can be lost with no error through `"drop_block"`, a batch item, a model switch, a move to [another account](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#account-bound-thinking), or code that sends no thinking back. With the beta header, each leaves an entry except the last. For that one, check that your requests hold `thinking` blocks.

## Technical details

### What else the error message can say

The error message goes on to name what changed, where the API can tell, such as `system`, `tools`, the first message or block that differs, content that is missing or new, or an earlier thinking block that is missing or out of order. That sentence’s wording can change, so don’t match on it. If the request had no beta header, the error message adds this sentence:

```text wrap
That setting requires the `thinking-binding-controls-2026-08-01` value in the `anthropic-beta` header.
```

### The error still asks for the header, or says `Extra inputs are not permitted`

If the error still asks for the header, the header didn’t reach the API: a proxy or library might have removed it. A different error, ending `block_binding: Extra inputs are not permitted`, means the same, or that thinking is off.

### Remove the invalid thinking by hand

Use this where you can’t send the setting, or in one of these cases:

* After you removed a secret, personal data, or injected text, because `"drop_block"` leaves the thinking in your stored history.
* When thinking is off (`"disabled"` or `"between_tools"`), because `"drop_block"` needs `"adaptive"`, which would turn thinking on and add output tokens.

1. Remove the block the error names, and every `thinking` and [`redacted_thinking`](https://platform.claude.com/docs/en/build-with-claude/thinking#redacted-thinking-blocks) block after it, or the same error then names the next invalid one. But if your history holds `role: "system"` messages, or two messages of the same role in a row, remove every `thinking` and `redacted_thinking` block. The error counts such a message as part of the message before it, so the position it names can be lower than the index in your array. The `path` of an `input_transformations` entry counts every message separately.
2. Keep every other block, and send the request again. Don’t put the removed blocks back.

### Errors that look like this one

These errors don’t say that the block is bound to a different conversation, and setting `prefix_mismatch_behavior` might not clear them:

* A message that stops after “Invalid `signature` in `thinking` block”, says “cannot be modified”, or is about `budget_tokens`: [Troubleshooting thinking](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting)
* A message about `temperature` or a prefilled reply: [Limits and feature compatibility](https://platform.claude.com/docs/en/build-with-claude/thinking#limits-and-feature-compatibility)

### When you can stop sending `"drop_block"`

To stop sending `"drop_block"`, remove the blocks it drops and keep the thinking produced since. If nothing else has changed, the conversation then passes with `"error"`.

### Handle the error in code

To handle the error in code, send the beta header and `"error"` on every request, so a failure is a 400 error on every model. When it comes, switch that conversation alone to `"drop_block"` for every later request, store that choice with it, send again once, and log the error. If the same error comes back, the setting didn’t reach the API: see [The error still asks for the header, or says `Extra inputs are not permitted`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#setting-not-received).

Your code has to recognize this error by its `message` field, the exception to the general advice not to match an error’s text. Every 400 error has the type `invalid_request_error`, and this one has no `error.details.error_code`. Match only on “The block is bound to a different conversation”, because the rest of the message can change.

### You have no error, or one that doesn’t say what changed

* **The 400 error, and it names no change:** Compare the requests yourself. One cause is a compaction block sent without removing the messages it summarizes.

* **A `prefix_binding_mismatch` entry:** Compare `system`, `tools`, and `messages` up to the first entry’s `path` with the conversation as it was when that block was produced. If every block is listed, start with `system` and `tools`.

  If nothing differs, look for [an image or document URL whose content changed](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#files-by-id), an MCP server’s changed tool list (see [Pin an MCP server’s tool list](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector#pin-mcp-tool-list)), or a thinking block left out, moved, or put back. Without request logs, send the request again with `"error"`, and read the sentence that says what differs, if there is one.

* **A proxy or library that isn’t yours, in between:** Compare what it sends with what you sent, and point its maintainer to [Libraries, proxies, and gateways](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#libraries-proxies-gateways).

* **Only a suspicion, and no Claude Code:** Capture a conversation’s request bodies, one with a compaction or a tool change. Compare each with the one before, leaving out its new turns.

### Five steps for a test that can fail, and a program that runs them

1. In your own code, send the beta header and `"drop_block"` on each request of a session, to a [model with preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes).
2. Use prompts that make Claude think, and check that the first response has a `thinking` block. With adaptive thinking, Claude can skip thinking on an easy prompt.
3. Fail only on an `input_transformations` entry whose reason is `prefix_binding_mismatch`. A test that wants an empty array also fails after a model switch, because entries with `model_binding_mismatch` or `organization_binding_mismatch` are expected then.
4. Change something on purpose, such as adding a `system` prompt on the third request only.
5. Check that `input_transformations` lists the thinking blocks that sit after the change. If it lists none, check that the history holds a thinking block.

This program does steps 1, 2, 4, and 5. It prints how many thinking blocks and `input_transformations` entries each response has, then each entry, which is what step 3 checks:

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    This workflow needs more logic than a single shell command. Use the [Anthropic SDK](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) to run it.
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    This workflow needs more logic than a single shell command. Use the [Anthropic SDK](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) to run it.
  </CodeGroupItem>

  ```python Python
  client = anthropic.Anthropic()

  user_turns = [
      "How many positive integers below 500 have exactly 6 positive divisors?",
      "How many have exactly 8?",
      "How many have exactly 10?",
  ]

  messages = []
  for turn, user_turn in enumerate(user_turns, start=1):
      messages.append({"role": "user", "content": user_turn})
      response = client.beta.messages.create(
          model="claude-opus-5-5",
          max_tokens=16000,
          thinking={
              "type": "adaptive",
              "block_binding": {"prefix_mismatch_behavior": "drop_block"},
          },
          # Only the last request adds a system prompt, which changes the prefix on purpose
          system="Answer briefly." if turn == len(user_turns) else anthropic.omit,
          messages=messages,
          betas=["thinking-binding-controls-2026-08-01"],
      )
      messages.append({"role": "assistant", "content": response.content})
      thinking_blocks = sum(block.type == "thinking" for block in response.content)
      entries = response.input_transformations or []
      print(f"thinking blocks: {thinking_blocks}, entries: {len(entries)}")
      for entry in entries:
          if entry.type == "thinking_dropped":
              print(entry.type, entry.path, entry.reason)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const userTurns = [
    "How many positive integers below 500 have exactly 6 positive divisors?",
    "How many have exactly 8?",
    "How many have exactly 10?"
  ];

  const messages: Anthropic.Beta.BetaMessageParam[] = [];
  for (const [turnIndex, userTurn] of userTurns.entries()) {
    messages.push({ role: "user", content: userTurn });
    const response = await client.beta.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 16000,
      thinking: {
        type: "adaptive",
        block_binding: { prefix_mismatch_behavior: "drop_block" }
      },
      // Only the last request adds a system prompt, which changes the prefix on purpose
      system: turnIndex === userTurns.length - 1 ? "Answer briefly." : undefined,
      messages,
      betas: ["thinking-binding-controls-2026-08-01"]
    });
    messages.push({ role: "assistant", content: response.content });
    const thinkingBlocks = response.content.filter((block) => block.type === "thinking");
    const entries = response.input_transformations ?? [];
    console.log(`thinking blocks: ${thinkingBlocks.length}, entries: ${entries.length}`);
    for (const entry of entries) {
      if (entry.type === "thinking_dropped") {
        console.log(entry.type, entry.path, entry.reason);
      }
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Model = Anthropic.Models.Messages.Model;

  AnthropicClient client = new();

  string[] userTurns =
  [
      "How many positive integers below 500 have exactly 6 positive divisors?",
      "How many have exactly 8?",
      "How many have exactly 10?",
  ];

  List<BetaMessageParam> messages = [];
  foreach (var (turnIndex, userTurn) in userTurns.Index())
  {
      messages.Add(new BetaUserMessageParam { Content = userTurn });
      var response = await client.Beta.Messages.Create(
          new()
          {
              Model = Model.ClaudeOpus5_5,
              MaxTokens = 16000,
              Thinking = new BetaThinkingConfigAdaptive
              {
                  BlockBinding = new()
                  {
                      PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.DropBlock,
                  },
              },
              // Only the last request adds a system prompt, which changes the prefix on purpose
              System = turnIndex == userTurns.Length - 1 ? new("Answer briefly.") : null,
              Messages = messages,
              Betas = [AnthropicBeta.ThinkingBindingControls2026_08_01],
          }
      );
      messages.Add(new BetaAssistantMessageParam
      {
          Content = response.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
      });
      var thinkingBlocks = response.Content.Count(block => block.TryPickThinking(out _));
      var entries = response.InputTransformations ?? [];
      Console.WriteLine($"thinking blocks: {thinkingBlocks}, entries: {entries.Count}");
      foreach (var entry in entries)
      {
          if (entry.TryPickThinkingDropped(out var dropped))
          {
              Console.WriteLine($"{dropped.Type} {dropped.Path} {dropped.Reason.Raw()}");
          }
      }
  }
  ```

Cut at 300 lines. The page has the rest.

build-with-claude/preserved-thinking/prefix-checks New page · 446 lines, new page

## Who the prefix check affects ## What must stay the same, and why ## If your code changes the system prompt, tools, or history ## What each model does when the prefix check fails ## Handle both cases ## Technical details ### How the prefix check works ### Which models run the prefix check ### What counts as a change ### What doesn’t count ### Set `prefix_mismatch_behavior` ### Watch production traffic ### Check which case you get ## Next steps

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Prefix checks on thinking blocks
url: https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks
description: What the prefix check compares, which models run it, what happens when a request fails it, and how to handle the 400 error and the case with no error.
featureMetadata:
  status: stable
  supportedModels:
    - claude-fable-5-2
    - claude-mythos-5-2
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-opus-5-5
    - claude-sonnet-5-5
    - claude-haiku-5-5
  supportedPlatforms:
    Claude API: stable
    Amazon Bedrock: stable
    Amazon Bedrock (bedrock-runtime): stable
    Claude Platform on AWS: stable
    Claude Models on Google Cloud (Anthropic managed): stable
    Claude Models on Google Cloud (Google managed): stable
    Microsoft Foundry: stable
---

Each request that sends thinking blocks back to a [model with preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes) gets a prefix check. A prefix check fails if `system`, `tools`, or an earlier message changed after Claude produced a block. It also fails if a thinking block between others was left out or moved.

Failing the prefix check might or might not result in a 400 error, [depending on the model](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes), so [handle both cases](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#handle-either-outcome).

## Who the prefix check affects

You have nothing to change if one of these is true:

* Claude Code, claude.ai, or Claude Managed Agents manages your conversation history.
* The Claude Agent SDK manages the history, and the system prompt you give the SDK stays the same.
* Your code follows [the three habits of an append-only integration](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check), and nothing rewrites its requests on the way.
* You call no [model with preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes).

If your requests pass through a library, proxy, or gateway, [compare what it sends with what you sent](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#find-the-change-details). If you run one, see [Libraries, proxies, and gateways](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#libraries-proxies-gateways) for what to pass through.

## What must stay the same, and why

Make your integration append-only. Three habits do it:

1. Send each assistant turn back exactly as the API returned it, including thinking blocks whose text is empty.
2. Build `system` and `tools` once for each conversation, and send that copy every time.
3. Put every update in a new message at the end, and leave it there.

Each thinking block’s reasoning is about exactly what came before it: `system`, `tools`, and every earlier message. That content is the block’s *prefix*, and it’s what the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check-details) compares.

The prefix check is similar to prompt caching, except that a change makes the thinking after it invalid instead of only missing the cache.

Take an app that puts today’s date in its system prompt. At midnight the date changes, and so does the prefix of the thinking already in the conversation. That thinking becomes invalid, and the next request can fail. An append-only app keeps the system prompt as it was, and states the new date in [a message at the end](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#changing-context).

<Frame>
  ![An update at the end keeps all thinking valid; a change to turn 2, or to system, invalidates the thinking after it](https://platform.claude.com/docs/images/preserved-thinking-add-or-change.svg)
</Frame>

A change makes only the thinking that already follows it invalid. The thinking before it and the thinking Claude produces afterward stay valid.

## If your code changes the system prompt, tools, or history

| If your code…                                                                    | What to do                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Rebuilds the system prompt with the date, a mode, or instruction files           | Stop changing `system`. [Append your own instructions as a system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#new-instructions), a `role: "system"` entry in `messages`, and [state new values in the newest turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#changing-context). For text that other people can edit, see [Text that other people can edit](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#untrusted-text) instead. |
| Adds, removes, or rewords a tool, or gains tools when an MCP server connects     | Stop changing `tools`, and [add or remove tools in a system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#tool-changes).                                                                                                                                                                                                                                                                                                                                                                                                                                |
| Trims, collapses, or summarizes older turns, and keeps the latest ones unchanged | [Let the API write the summary, or remove the kept turns’ thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#server-side-trimming).                                                                                                                                                                                                                                                                                                                                                                                                                         |

Other causes, such as skipping thinking blocks whose text is empty or rebuilding a saved conversation, have fixes of their own: see [Change tools or instructions without failing the prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions). To find yours, [have an agent check your code](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#hand-to-an-agent).

## What each model does when the prefix check fails

On the Claude API and [some cloud platforms](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#feature-availability), the result of failing the prefix check with [`prefix_mismatch_behavior`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#preserved-thinking-controls) unset depends on the model:

| Model with preserved thinking | Result                                                                                                                          |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Claude Fable 5.2              | 400 error                                                                                                                       |
| Claude Mythos 5.2             | 400 error                                                                                                                       |
| Claude Mythos 5.1             | 400 error                                                                                                                       |
| Claude Fable 5.1              | [Possible 400 error](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#possible-400-error) |
| Claude Opus 5.5               | [Possible 400 error](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#possible-400-error) |
| Claude Sonnet 5.5             | [Possible 400 error](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#possible-400-error) |
| Claude Haiku 5.5              | [Possible 400 error](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#possible-400-error) |

Where the table says “Possible 400 error,” there are two cases: a request that fails the prefix check might get a 400 error or no error. When no error is returned, the failing blocks reach the model. Claude reads them like any other input, you’re billed for them, and Claude works from reasoning about content that has since changed.

On those models, you can [check which case a request gets](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#check-which-case), but [handle both cases](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#handle-either-outcome).

<Tip>
  Code that follows [the three habits of an append-only integration](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check) doesn’t cause prefix check failures.
</Tip>

[Message Batches items](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#batches) that leave `prefix_mismatch_behavior` unset get no error, and the API can drop the failing blocks.

## Handle both cases

For one result on every request, make your integration append-only or set `prefix_mismatch_behavior`. Otherwise, your code must handle both behaviors.

* **Append-only:** with [the three habits](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check), your code doesn’t make a request fail the prefix check.
* **The setting:** with `"error"` on every request, each failure is a 400 error, and you [catch it in code](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#handle-the-error-in-code).
* **Both behaviors:** if you leave the setting unset, catch the 400 error, and [watch for failing thinking that reached Claude](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#watch-production-traffic).

After a 400 error, send `"drop_block"` on that conversation’s later requests to recover. It has a cost: see [What dropping thinking costs](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#drop-block-cost). Don’t send it on all your conversations to hide errors.

## Technical details

### How the prefix check works

The models with preserved thinking record a fingerprint of each thinking block’s prefix in its `signature`. The API reference calls the prefix check the conversation check, and the 400 error says that a failing block `is bound to a different conversation`.

### Which models run the prefix check

The prefix check runs on the Claude API and on [some cloud platforms](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#feature-availability). It checks thinking blocks that a [model with preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes) produced, on requests to one of those models. On the Claude API, other models, such as Claude Opus 5, don’t run it, and it doesn’t cover their blocks.

### What counts as a change

* **Each block is checked against its own record.** The API compares what’s before a block in this request with what its signature recorded when Claude produced it. Your last request plays no part. The prefix check looks only at content, not at sessions, IDs, or users. The same content in a new request or a fork passes it.
* **The prefix check compares what you sent, not what Claude read.** [Compaction at a token threshold](https://platform.claude.com/docs/en/build-with-claude/compaction-threshold) and context editing change only what Claude reads, so they never count. After a threshold compaction block, the API compares only the messages from that block on, plus `system` and `tools`. On-demand compaction has its own conditions: see [Conditions for kept thinking to stay valid](https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid). For a file sent by URL and, on the Claude API, [an MCP tool list](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector#pin-mcp-tool-list), the API compares what it fetched instead.
* **The thinking you send must be an unbroken run.** Thinking blocks aren’t compared as content. But each one you send, apart from the first, must have the same previous thinking block as when Claude produced it. So you can [leave out the oldest, the newest, or all of them](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#leave-out-thinking), but not one in between.

A change can be as small as one word of a tool description. Changing, inserting, moving, or deleting an earlier message counts, whatever its role. So does changing text before a thinking block in its own message.

### What doesn’t count

| This doesn’t count                                                                                   | Because                                                       |
| ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `model`, `effort`, `max_tokens`, `tool_choice`, `metadata`, `thinking.display`, and other parameters | Only `system`, `tools`, and messages are compared             |
| JSON formatting or key order                                                                         | The API compares parsed JSON, not its text                    |
| `cache_control` markers                                                                              | They say where to cache, and aren’t content that Claude reads |
| A tool with `defer_loading: true` that nothing has referred to                                       | It isn’t in Claude’s context until something refers to it     |

### Set `prefix_mismatch_behavior`

The [beta header](https://platform.claude.com/docs/en/api/beta-headers#beta-features-on-other-platforms) `thinking-binding-controls-2026-08-01` adds the setting `thinking.block_binding.prefix_mismatch_behavior` and the response’s `input_transformations` array.

| Value              | If a block fails the prefix check                                                                                                                                                                                                                                 |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `"error"`          | The API rejects the request with a 400 error that names the first invalid block                                                                                                                                                                                   |
| `"drop_block"`     | The API drops the invalid blocks, and the request succeeds. You aren’t billed for those blocks, but [dropping them can cost more](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#drop-block-cost) |
| Not set, or `null` | [Depends on the model](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#outcomes)                                                                                                                                           |

Blocks that fail the prefix check stay invalid on every later request that sends them, while the change is in place. The setting acts on the one request that carries it. With thinking off (`"disabled"` or `"between_tools"`), sending it is a 400 error on every model.

The following request sets `prefix_mismatch_behavior` to `"drop_block"`. On a first turn there’s no thinking to send back, so `input_transformations` comes back empty:

<CodeGroup>
  ```bash cURL
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2026-10-21" \
    -H "anthropic-beta: thinking-binding-controls-2026-08-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-opus-5-5",
      "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?"
        }
      ]
    }'
  ```

  ```bash CLI
  ant beta:messages create --beta thinking-binding-controls-2026-08-01 <<'YAML'
  model: claude-opus-5-5
  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?
  YAML
  ```

  ```python Python
  client = anthropic.Anthropic()

  response = client.beta.messages.create(
      model="claude-opus-5-5",
      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 [])}")
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await client.beta.messages.create({
    model: "claude-opus-5-5",
    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 (const block of response.content) {
    if (block.type === "text") {
      console.log(block.text);
    }
  }
  console.log(`Input transformations: ${response.input_transformations?.length ?? 0}`);
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Model = Anthropic.Models.Messages.Model;

  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(
      new()
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 16000,
          Thinking = new BetaThinkingConfigAdaptive
          {
              BlockBinding = new()
              {
                  PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.DropBlock,
              },
          },
          Messages =
          [
              new BetaUserMessageParam
              {
                  Content = "What is the greatest common divisor of 1071 and 462?",
              },
          ],
          Betas = [AnthropicBeta.ThinkingBindingControls2026_08_01],
      }
  );

  foreach (var block in response.Content)
  {
      if (block.TryPickText(out var textBlock))
      {
          Console.WriteLine(textBlock.Text);
      }
  }

  Console.WriteLine($"Input transformations: {response.InputTransformations?.Count ?? 0}");
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeOpus5_5,
  	MaxTokens: 16000,
  	Thinking: anthropic.BetaThinkingConfigParamUnion{
  		OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
  			BlockBinding: anthropic.BetaThinkingBlockBindingParam{
  				PrefixMismatchBehavior: anthropic.BetaThinkingPrefixMismatchBehaviorDropBlock,
  			},
  		},
  	},
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What is the greatest common divisor of 1071 and 462?")),
  	},
  	Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaThinkingBindingControls2026_08_01},
  })
  if err != nil {
  	log.Fatal(err)
  }

  for _, block := range response.Content {
  	if textBlock, ok := block.AsAny().(anthropic.BetaTextBlock); ok {
  		fmt.Println(textBlock.Text)
  	}

Cut at 300 lines. The page has the rest.

build-with-claude/prompt-caching Changed · +21 / -29 lines

from line 48
4848* **[Automatic caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#automatic-caching):** Add a single `cache_control` field at the top level of your request. The system automatically applies the cache breakpoint to the last cacheable block and moves it forward as conversations grow. Best for multi-turn conversations where the growing message history should be cached automatically.
4949* **[Explicit cache breakpoints](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints):** Place `cache_control` directly on individual content blocks for fine-grained control over exactly what gets cached.
5050 
51The simplest way to start is with automatic caching:
51One way to start is with automatic caching:
5252 
5353<CodeGroup>
5454 ```bash cURL
from line 240
240240 
241241The lifetime is measured from the start of the request that writes or reads the cache entry, not from the end of its response. Time spent generating a response counts against the lifetime: if a response takes 4 minutes to stream, a follow-up request that reuses the same cached prefix must start within about 1 minute of that response completing.
242242 
243<Note>
244 If you find that 5 minutes is too short, Anthropic also offers a 1-hour cache duration at additional cost (see [Pricing](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#pricing)).
243If 5 minutes is too short, you can use a [1-hour cache duration](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#1-hour-cache-duration) at additional cost (see [Pricing](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#pricing)).
245244 
246 For more information, see [1-hour cache duration](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#1-hour-cache-duration).
247</Note>
245Prompt caching covers the full prefix: `tools`, `system`, and `messages` (in that order), up to and including the block designated with `cache_control`.
248246 
249<Tip>
250 **Prompt caching caches the full prefix**
251 
252 Prompt caching references the entire prompt: `tools`, `system`, and `messages` (in that order), up to and including the block designated with `cache_control`.
253</Tip>
254 
255247***
256248 
257249## Pricing
from line 301
309301 
310302## Automatic caching
311303 
312Automatic caching is the simplest way to enable prompt caching. Instead of placing `cache_control` on individual content blocks, add a single `cache_control` field at the top level of your request body. The system automatically applies the cache breakpoint to the last cacheable block.
304Automatic caching enables prompt caching with one field. Instead of placing `cache_control` on individual content blocks, add a single `cache_control` field at the top level of your request body. The system automatically applies the cache breakpoint to the last cacheable block.
313305 
314306<CodeGroup>
315307 ```bash cURL
from line 666
674666 
675667The following table shows which parts of the cache are invalidated by different types of changes. ✘ indicates that the cache is invalidated, whereas ✓ indicates that the cache remains valid.
676668 
677| What changes | Tools cache | System cache | Messages cache | Impact |
678| ----------------------------------------------------- | -------------- | -------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
679| **Tool definitions** | ✘ | ✘ | ✘ | Modifying tool definitions (names, descriptions, parameters) invalidates the entire cache |
680| **Web search toggle** | ✓ | ✘ | ✘ | Enabling/disabling web search modifies the system prompt |
681| **Citations toggle** | ✓ | ✘ | ✘ | Enabling/disabling citations modifies the system prompt |
682| **Speed setting** | ✓ | ✘ | ✘ | Switching between [`speed: "fast"` and standard speed](https://platform.claude.com/docs/en/build-with-claude/fast-mode) invalidates system and message caches |
683| **Tool choice** | ✓ | ✓ | ✘ | Changes to the `tool_choice` parameter only affect message blocks |
684| **Images** | ✓ | ✓ | ✘ | Adding/removing images anywhere in the prompt affects message blocks |
685| **Thinking parameters** | Model-specific | Model-specific | ✘ | The thinking configuration (mode, and `budget_tokens` in extended mode) is rendered into the prompt, so changing it always invalidates message blocks; tool and system caches are also invalidated on models that render the configuration ahead of them. See [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching). |
686| **Effort setting** | Model-specific | Model-specific | ✘ | Changing the [`output_config.effort`](https://platform.claude.com/docs/en/build-with-claude/effort) value always invalidates message blocks, with the same model-specific effect on tool and system caches as thinking parameters. Setting effort explicitly to the model’s default is equivalent to omitting it and does not invalidate. On models that support [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message), an effort change carried in a `role: "system"` message inside `messages` leaves the cached prefix intact. |
687| **Non-tool results passed to requests with thinking** | ✓ | ✓ | Model-specific | On Opus 4.5+, Sonnet 4.6+, and Haiku 5.5, thinking blocks are preserved by default, so the cache remains valid (✓). On earlier Opus/Sonnet models and Haiku models through Claude Haiku 4.5, all previously-cached thinking blocks are stripped from context, and any messages that follow those thinking blocks are removed from the cache (✘). For more details, see [Caching with thinking blocks](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#caching-with-thinking-blocks). |
688| **Dropped thinking blocks** | ✓ | ✓ | ✘ | When the API drops a thinking block that isn’t [preserved](https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-thinking) on that request, the cached prefix changes from that block’s position onward on that request. Blocks the receiving model can read, passed back unchanged, keep the cache intact. |
669| What changes | Tools cache | System cache | Messages cache | Impact |
670| ----------------------------------------------------- | -------------- | -------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
671| **Tool definitions** | ✘ | ✘ | ✘ | Modifying tool definitions (names, descriptions, parameters) invalidates the entire cache |
672| **Web search toggle** | ✓ | ✘ | ✘ | Enabling/disabling web search modifies the system prompt |
673| **Citations toggle** | ✓ | ✘ | ✘ | Enabling/disabling citations modifies the system prompt |
674| **Speed setting** | ✓ | ✘ | ✘ | Switching between [`speed: "fast"` and standard speed](https://platform.claude.com/docs/en/build-with-claude/fast-mode) invalidates system and message caches |
675| **Tool choice** | ✓ | ✓ | ✘ | Changes to the `tool_choice` parameter only affect message blocks |
676| **Images** | ✓ | ✓ | ✘ | Adding/removing images anywhere in the prompt affects message blocks |
677| **Thinking parameters** | Model-specific | Model-specific | ✘ | The thinking configuration (mode, and `budget_tokens` in extended mode) is rendered into the prompt, so changing it always invalidates message blocks; tool and system caches are also invalidated on models that render the configuration ahead of them. See [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching). |
678| **Effort setting** | Model-specific | Model-specific | ✘ | Changing the [`output_config.effort`](https://platform.claude.com/docs/en/build-with-claude/effort) value can invalidate message blocks, and on some models tool and system caches too (see [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching)). Setting effort explicitly to the model’s default is equivalent to omitting it and does not invalidate. On models that support [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message), an effort change carried in a `role: "system"` message inside `messages` leaves the cached prefix intact. |
679| **Non-tool results passed to requests with thinking** | ✓ | ✓ | Model-specific | On Claude Opus 4.5 and later Opus models, Claude Sonnet 4.6 and later Sonnet models, Claude Haiku 5.5, and every Claude Fable and Claude Mythos model, thinking blocks are preserved by default, so the cache remains valid (✓). On other models, all previously cached thinking blocks are stripped from context, and any messages that follow those thinking blocks are removed from the cache (✘). For more details, see [Caching with thinking blocks](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#caching-with-thinking-blocks). |
680| **Dropped thinking blocks** | ✓ | ✓ | ✘ | When the API drops a thinking block that isn’t [preserved](https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-thinking) on that request, the cached prefix changes from that block’s position onward on that request. Blocks the receiving model can read, passed back unchanged, keep the cache intact. |
689681 
690682On models that support [mid-conversation tool changes](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#mid-conversation-tool-changes), the `inline-tools-2026-09-15` beta header lets you add a tool, or change a tool’s definition, partway through a conversation without editing `tools`. Send the definition in a `tool_addition` block in a mid-conversation system message and leave `tools` exactly as you first sent it. The cached prefix still matches, so only the appended message is processed as new input. The one exception is a `tools` array with no non-deferred tool, where the first tool defined this way costs one full cache miss on that request. See [Define tools in a message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta).
691683 
from line 731
739731**Cache invalidation patterns:**
740732 
741733* Cache remains valid when only tool results are provided as user messages.
742* On Opus 4.5+, Sonnet 4.6+, and Haiku 5.5, thinking blocks are preserved by default even when non-tool-result user content is added, so the cache remains valid.
743* On earlier Opus/Sonnet models and Haiku models through Claude Haiku 4.5, cache gets invalidated when non-tool-result user content is added, causing all previous thinking blocks to be stripped from context.
734* On Claude Opus 4.5 and later Opus models, Claude Sonnet 4.6 and later Sonnet models, Claude Haiku 5.5, and every Claude Fable and Claude Mythos model, thinking blocks are preserved by default even when non-tool-result user content is added, so the cache remains valid.
735* On other models, adding non-tool-result user content invalidates the cache and strips all previous thinking blocks from context.
744736* This caching behavior occurs even without explicit `cache_control` markers.
745737 
746738For more details on cache invalidation, see [What invalidates the cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#what-invalidates-the-cache).
from line 760
768760# Depending on the model, this non-tool-result user block either keeps prior thinking blocks or strips them (see the next paragraph)
769761```
770762 
771On earlier Opus/Sonnet models and Haiku models through Claude Haiku 4.5, all previous thinking blocks are removed from context at this point. On Opus 4.5+, Sonnet 4.6+, and Haiku 5.5, prior thinking blocks are kept by default and remain part of the cached prefix.
763On the [models that keep earlier thinking](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#caching-with-thinking-blocks), prior thinking blocks stay in context by default and remain part of the cached prefix. On other models, all previous thinking blocks are removed from context at this point.
772764 
773765For more detailed information, see [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching).
774766 
from line 3402
34103402 </Accordion>
34113403 
34123404 <Accordion title="How does prompt caching work with thinking?">
3413 Changing thinking parameters (switching modes, or changing the budget in extended mode) invalidates cached message prefixes, and can invalidate cached system prompts and tools as well, because the thinking configuration is rendered into the prompt. The [`output_config.effort`](https://platform.claude.com/docs/en/build-with-claude/effort) value behaves the same way.
3405 Changing thinking parameters (switching modes, or changing the budget in extended mode) invalidates cached message prefixes, and can invalidate cached system prompts and tools as well, because the thinking configuration is rendered into the prompt. Changing the [`output_config.effort`](https://platform.claude.com/docs/en/build-with-claude/effort) value can do the same.
34143406 
34153407 For more details on cache invalidation, see [What invalidates the cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#what-invalidates-the-cache).
34163408 

build-with-claude/prompt-engineering/prompting-claude-fable-5-1 Changed · +24 / -8 lines

from line 69
6969 
7070Each time you send tool results back, append it after that user message as a [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages): a `role: "system"` entry in `messages` with `clear_at: "next_user_message"`. Once a later user message exists, the API clears the earlier copies, so the model reads only the newest one. Turn-scoped system messages are in beta and require the [beta header](https://platform.claude.com/docs/en/api/beta-headers) `mid-conversation-system-clear-at-2026-08-21`. Without the beta, place the sentence in a text block after the `tool_result` blocks in the same user message instead.
7171 
72Append a fresh copy each turn and leave the earlier copies where they are, byte-for-byte. They stay in the array, but once cleared the model doesn’t see them and they cost no input tokens. Deleting or rewriting them is an edit to earlier turns: it invalidates the thinking blocks that came after them (see [Keep the conversation history append-only](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#keep-the-conversation-history-append-only)).
72Append a fresh copy each turn and leave the earlier copies where they are, unchanged. They stay in the array, but once cleared the model doesn’t see them and they cost no input tokens. Deleting or rewriting them is an edit to earlier turns: it invalidates the thinking blocks that came after them (see [Keep the conversation history append-only](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#keep-the-conversation-history-append-only)).
7373 
7474The following loop shows this placement. Each assistant turn goes back exactly as returned, each user turn carries only the tool results, and a fresh turn-scoped copy of the nudge follows it.
7575 
76<CodeGroup exclude="shell">
76<CodeGroup exclude="shell:cURL, shell:CLI">
77 <CodeGroupItem language="cURL">
78 This workflow needs more logic than a single shell command. Use the [Anthropic SDK](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) to run it.
79 </CodeGroupItem>
80 
81 <CodeGroupItem language="CLI">
82 This workflow needs more logic than a single shell command. Use the [Anthropic SDK](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) to run it.
83 </CodeGroupItem>
84 
7785 ```python Python
7886 import anthropic
7987 from anthropic.types.beta import (
from line 756
748756 
749757## Keep the conversation history append-only
750758 
751Append each assistant turn to the history exactly as the API returned it, thinking blocks included, and don’t edit earlier turns between requests. A thinking block is valid [only while everything before it is unchanged](https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation): the system prompt, the tool list, and every earlier message. To choose what happens to a block that fails the prefix check, set `thinking.block_binding.prefix_mismatch_behavior`, which requires the `thinking-binding-controls-2026-08-01` beta header. With `"error"`, the API rejects the request with a 400 error; with `"drop_block"`, it drops the invalid blocks. [When `prefix_mismatch_behavior` is unset](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement) covers requests that don’t set it. On Claude Fable 5.2 and Claude Mythos 5.2, a request that leaves it unset and sends back a block that fails the check gets the 400 error on every account (see [Editing earlier turns invalidates thinking blocks on every account](https://platform.claude.com/docs/en/models/fable-5-2/whats-new-fable-5-2#editing-earlier-turns-invalidates-thinking-blocks) in What’s new in Claude Fable 5.2).
759Append each assistant turn to the history exactly as the API returned it, thinking blocks included, and don’t edit earlier turns between requests. The API’s [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check) passes a thinking block [only while everything before it is unchanged](https://platform.claude.com/docs/en/build-with-claude/thinking#preserved-in-conversation): the system prompt, the tool list, and every earlier message.
752760 
753Most history edits that trip the prefix check also restart the [prompt cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching): injecting and removing per-turn reminders, summarizing older turns in place, or changing the system prompt mid-session. Send per-turn reminders as [turn-scoped system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages). To change instructions or tools, send a [mid-conversation system message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages) instead of rewriting `system` or `tools`. Let server-side [compaction](https://platform.claude.com/docs/en/build-with-claude/compaction) or [context editing](https://platform.claude.com/docs/en/build-with-claude/context-editing) do any trimming. If you compact on the client, the simplest approach is to replace the whole history with one summary message plus the new user turn, and nothing else. No thinking blocks carry over, so nothing fails, and the model thinks afresh on the compacted conversation (see [Compact on the client](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#custom-compaction-on-the-client)). Cache reads on Claude Fable 5.1 cost $0.25 USD per million tokens, 2.5 percent of the input price (see [Prompt caching pricing](https://platform.claude.com/docs/en/about-claude/pricing#prompt-caching)). Compacting early to save cost can be the wrong trade-off between cost and intelligence, so experiment with later compaction points.
761Failing the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check) might or might not result in a [400 error](https://platform.claude.com/docs/en/api/errors#thinking-block-conversation-mismatch). To identify and handle both cases, see [Prefix checks on thinking blocks](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks).
754762 
755To find edits your harness makes, run a session with `prefix_mismatch_behavior: "drop_block"` and log `input_transformations`, as described in [Check whether your code edits the prefix](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#how-to-tell-whether-your-integration-is-impacted). You can also capture the exact requests it sends over a few normal turns and confirm that consecutive requests are byte-identical up to the appended turns.
763To choose what happens to a block that fails the prefix check, set `thinking.block_binding.prefix_mismatch_behavior`. This setting requires the `thinking-binding-controls-2026-08-01` beta header. With `"error"`, the API rejects the request with a 400 error. With `"drop_block"`, the API drops the invalid blocks.
756764 
765These history changes fail the prefix check and also invalidate the [prompt cache](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) from the changed point onward: injecting and removing per-turn reminders, summarizing older turns in place, and changing the system prompt mid-session. Send per-turn reminders as [turn-scoped system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages). To change instructions or tools, send a [mid-conversation system message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages) instead of rewriting `system` or `tools`. Let server-side [compaction](https://platform.claude.com/docs/en/build-with-claude/compaction) or [context editing](https://platform.claude.com/docs/en/build-with-claude/context-editing) do any trimming.
766 
767If you compact on the client, one approach is to replace the whole history with one summary message plus the new user turn, and nothing else. No thinking blocks carry over, so nothing fails, and the model thinks afresh on the compacted conversation (see [When your code writes the summary](https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks#own-summary)).
768 
769Cache reads on Claude Fable 5.1 cost $0.25 USD per million tokens, 2.5 percent of the input price (see [Prompt caching pricing](https://platform.claude.com/docs/en/about-claude/pricing#prompt-caching)). Compacting early to save cost can be the wrong trade-off between cost and intelligence, so experiment with later compaction points.
770 
771To find edits your harness makes, run a session with `prefix_mismatch_behavior: "drop_block"` and log `input_transformations`, as described in [Test your code for prefix check failures](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#how-to-tell-whether-your-integration-is-impacted). You can also capture the exact requests it sends over a few normal turns and confirm that consecutive requests are the same up to the appended turns.
772 
757773## Writing density
758774 
759775Claude Fable 5.1’s writing has few stock phrases and little unexplained jargon. In some cases, though, its prose is denser than Claude Fable 5’s: sentences run longer and there are fewer paragraph breaks. An instruction that defines the anti-pattern, mannered prose, helps. Add it to a user message (preferred) or the system prompt:
from line 906
890906 
891907## Give vision work tools to crop and zoom
892908 
893Claude Fable 5.1 has better vision capabilities out of the box, and on complex visual inputs such as dense charts it does its best work when it can iteratively analyze, crop, and visually verify what it sees. To get the full benefit, run the model as an agent with access to a container that holds the raw images or videos and has basic image-processing libraries (such as PIL and OpenCV) pre-installed. If running a container is too much overhead, an image-cropping tool alone delivers most of the uplift: a tool that returns a chosen region of the image, cropped and enlarged, lets the model examine specific details in more depth and scales test-time compute with image tokens. The [crop tool recipe](https://platform.claude.com/cookbook/multimodal-crop-tool) has a working definition.
909On complex visual inputs such as dense charts, Claude Fable 5.1 does its best work when it can iteratively analyze, crop, and visually verify what it sees. To get the full benefit, run the model as an agent with access to a container that holds the raw images or videos. Give the container basic image-processing libraries, such as PIL and OpenCV. If running a container is too much overhead, an image-cropping tool alone also helps. A tool that returns a chosen region of the image, cropped and enlarged, lets the model examine specific details in more depth, and it scales test-time compute with image tokens. The [crop tool recipe](https://platform.claude.com/cookbook/multimodal-crop-tool) has a working definition.
894910 

build-with-claude/prompt-engineering/prompting-claude-fable-5-2 Changed · +6 / -6 lines

from line 6
66 
77This guide covers the prompting patterns specific to Claude Fable 5.2. For the model’s capabilities and API changes, see [What’s new in Claude Fable 5.2](https://platform.claude.com/docs/en/models/fable-5-2/whats-new-fable-5-2) and the [Claude Fable 5.2 and Claude Mythos 5.2 migration guide](https://platform.claude.com/docs/en/models/fable-5-2/migration-guide). For techniques that apply across all current Claude models, see [Prompting best practices](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices).
88 
9Claude Fable 5.2 has a handful of behavioral differences from earlier models that are worth knowing about. Start by exploring the section that matches what you observe:
9Claude Fable 5.2 behaves differently from earlier models in several ways. Start with the section that matches what you observe:
1010 
1111* Unsure which effort level to run, or easy requests start slowly: [Calibrate effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#calibrate-effort)
1212* A turn ends before the work is done: [Finish the whole task](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#finish-the-whole-task)
from line 21
2121<Note>
2222 For the order in which to apply this guidance when you migrate, see [Where to start](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#where-to-start).
2323 
24 Several sections on this page suggest text to add to your system prompt, lines to remove from it or from the notes and rules your agents carry, or changes to a tool description. Make these changes in new conversations only. On Claude Fable 5.2, the API enforces the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#prefix-check) for every account. A request that sends thinking blocks back after `system`, `tools`, or an earlier message changed can return a 400 error, so a stored conversation resumed with the new text can fail. To change instructions partway through a conversation, [put them in the newest turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#changing-context). Where [mid-conversation system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages) are available, you can instead [append a system message to the conversation](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#new-instructions).
24 Several sections on this page suggest text to add to your system prompt or changes to a tool description. Some also suggest lines to remove from the system prompt or from the notes and rules your agents carry. Make these changes in new conversations only. On Claude Fable 5.2, a request that fails the [prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#prefix-check) gets a [400 error](https://platform.claude.com/docs/en/api/errors#thinking-block-conversation-mismatch). If you resume a stored conversation after you change `system`, `tools`, or an earlier message, the request can fail the prefix check. To change instructions partway through a conversation, [put them in the newest turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#changing-context). Where [mid-conversation system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages) are available, you can instead [append a system message to the conversation](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#new-instructions).
2525</Note>
2626 
2727## Calibrate effort
from line 44
4444 
4545Effort has little effect on the length of assistant turn responses. Use prompting to change the length and tone of replies.
4646 
47You can also mix levels in one workflow. For example, you might plan and iterate with the model at `medium`, then raise effort for the long, unattended part. To change levels within a conversation and keep the prompt cache, use [Per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) (beta, `mid-conversation-output-config-2026-07-01` header). That page lists the platforms where it’s available. A change holds until another one replaces it. Where per-message effort isn’t available, set a new top-level `effort` value on the next request, which starts the cache over.
47You can also mix levels in one workflow. For example, you might plan and iterate with the model at `medium`, then raise effort for the long, unattended part. To change levels within a conversation and keep the prompt cache, use [Per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) (beta, `mid-conversation-output-config-2026-07-01` header). That page lists the platforms where it’s available. A change holds until another one replaces it. Where per-message effort isn’t available, set a new top-level `effort` value on the next request, which can invalidate the cached messages.
4848 
4949## Finish the whole task
5050 
from line 87
8787 
8888The ownership sentence makes the model much more likely to consolidate duplicated code into one shared function. In Anthropic’s testing on small coding tasks, the model consolidated duplicated code in under 10 percent of runs without the sentence and in about 75 percent of runs with it.
8989 
90When using this prompt, output tokens rose by about 70 to 80 percent and the model made changes nobody had asked for, many of them new tests and documentation. In some runs, it also changed how an existing feature behaves. A closing PR summary from Claude Fable 5.2 often left out small changes, so review the reported diff and the summary.
90With this prompt, output tokens rose by about 70 to 80 percent and the model made changes nobody had asked for, many of them new tests and documentation. In some runs, it also changed how an existing feature behaves. A closing PR summary from Claude Fable 5.2 often left out small changes, so review the reported diff and the summary.
9191 
9292Leave the ownership sentence out where the user owns the code and wants it changed as little as possible. A rule that limits scope doesn’t cancel it. In Anthropic’s testing, the model still consolidated duplicated code in more than half of runs when “No drive-by refactors, renames or cleanups” appeared earlier in the same prompt.
9393 
from line 109
109109 
110110In Anthropic’s testing on multi-turn coding tasks, the reminder roughly halved the longest silent stretch without a noticeable increase in tokens or time.
111111 
112Leave each reminder in `messages` on later requests. Removing or rewording one edits an earlier turn, which invalidates the thinking blocks after it. See [Send per-turn reminders as turn-scoped system messages](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#per-turn-reminders).
112Leave each reminder in `messages` on later requests. Removing or rewording one edits an earlier turn, which invalidates the thinking blocks after it. See [Send a reminder for one turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#per-turn-reminders).
113113 
114114### Signal intent
115115 
from line 168
168168 
169169* **Standing instructions to delegate:** Lines that tell the model to delegate can sit in system prompts, skills, and agent files. Read those files before you migrate and remove the lines you no longer need if the model delegates too much in testing. See [Set expectations for subagents](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#set-expectations-for-subagents).
170170* **A token budget shown to the model:** Some harnesses show the model a token budget for the task and how much of it is left. The size of that budget changes how much Claude Fable 5.2 spends. In Anthropic’s testing on coding tasks at `high` and `xhigh` effort, removing a large budget lowered cost, with equivalent performance. Test your tasks without it. This finding is about text in the prompt, not the API’s [task budgets](https://platform.claude.com/docs/en/build-with-claude/task-budgets), a beta feature that the testing didn’t cover.
171* **Harness code that edits earlier turns:** Claude Fable 5.2 uses [preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking). If your harness changes the system prompt, the tools, or an earlier message between requests, the thinking blocks that follow the changed point in the history become invalid. By default, the Messages API then rejects the request, and the Message Batches API drops those blocks. To shorten the history without this error, use [context editing](https://platform.claude.com/docs/en/build-with-claude/context-editing), or [compaction](https://platform.claude.com/docs/en/build-with-claude/compaction) that keeps no earlier turns after the summary. To have the Messages API drop the blocks too, set `thinking.block_binding.prefix_mismatch_behavior` to `"drop_block"` (beta, `thinking-binding-controls-2026-08-01` header). In Anthropic’s testing, when earlier thinking was dropped on every turn, the model thought again and used more output tokens. That is the worst case, and the increase depends on how often your harness edits earlier turns. Apart from compaction and context editing, keep the history append-only. That keeps the cache hit rate high, and no thinking is dropped. Measure output tokens on your own tasks before you rely on `"drop_block"`. See [What the API does with an invalid block](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#mismatch-behavior) and [Make changes without editing the prefix](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#replace-prefix-edits).
171* **Harness code that edits earlier turns:** Claude Fable 5.2 uses [preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking). If your harness changes the system prompt, the tools, or an earlier message between requests, the thinking blocks that follow the changed point in the history become invalid. By default, the Messages API then rejects the request, and the Message Batches API drops those blocks. To shorten the history without this error, use [context editing](https://platform.claude.com/docs/en/build-with-claude/context-editing), or [compaction](https://platform.claude.com/docs/en/build-with-claude/compaction) that keeps no earlier turns after the summary. To have the Messages API drop the blocks too, set `thinking.block_binding.prefix_mismatch_behavior` to `"drop_block"` (beta, `thinking-binding-controls-2026-08-01` header). In Anthropic’s testing, when earlier thinking was dropped on every turn, the model thought again and used more output tokens. That is the worst case, and the increase depends on how often your harness edits earlier turns. Apart from compaction and context editing, keep the history append-only. That keeps the cache hit rate high, and no thinking is dropped. Measure output tokens on your own tasks before you rely on `"drop_block"`. See [Set `prefix_mismatch_behavior`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/prefix-checks#mismatch-behavior) and [Change tools or instructions without failing the prefix check](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions).
172172* **The “treat that answer as done” lines:** [Prompting Claude Opus 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5#thinking-instructions-in-chat-system-prompts) offers two sentences for chat system prompts. They tell the model to treat an earlier answer as done and to focus its thinking on the new message. In Anthropic’s testing at `high` effort, these instructions reduced Claude Fable 5.2’s thinking on follow-up questions. The model also became far less likely to point out mistakes in its earlier answers. Leave these lines out where you want the model to keep re-examining its earlier answers. Elsewhere, test whether the model still points out its own mistakes before you adopt the lines.
173173* **Instructions to think less:** Claude Fable 5.1 usually followed a line such as “answer directly without deliberating.” On Claude Fable 5.2, this addition doesn’t stop the model from thinking at `medium` and above. Remove such lines and lower the effort level, as described in [Calibrate effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#calibrate-effort).
174174* **Style rules for writing:** Claude Fable 5.2 follows them closely, so a hard limit such as “one instruction per sentence, in 20 words or fewer” can make its prose choppy. Remove the rules you no longer need before you add the text in [Make reports easy to follow](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#make-reports-easy-to-follow).

build-with-claude/prompt-engineering/prompting-claude-haiku-5-5 Changed · +6 / -6 lines

from line 21
2121<Note>
2222 For the breaking API changes when migrating from Claude Haiku 4.5, see the [Claude Haiku 5.5 migration guide](https://platform.claude.com/docs/en/models/haiku-5-5/migration-guide).
2323 
24 Several sections on this page suggest text to add to your system prompt. Add it to new conversations only. A request that sends thinking blocks back after `system` changed can return a 400 error, so a stored conversation resumed with the new system prompt can fail. To change instructions partway through a conversation, [put them in the newest turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#changing-context). On the Claude API, Amazon Bedrock, Claude Platform on AWS, Claude Models on Google Cloud (Anthropic managed), and Claude Models on Google Cloud (Google managed), you can instead [append a system message to the conversation](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#new-instructions).
24 Several sections on this page suggest text to add to your system prompt. Add it to new conversations only. If you resume a stored conversation with a new system prompt and send its thinking blocks back, the request can return a 400 error. To change instructions partway through a conversation, [put them in the newest turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#changing-context). On [platforms that support mid-conversation system messages](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#feature-availability), you can instead [append a system message to the conversation](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#new-instructions).
2525</Note>
2626 
2727## Use effort to control thinking
2828 
29[Effort](https://platform.claude.com/docs/en/build-with-claude/effort) is the main control for how much Claude Haiku 5.5 thinks. It replaces the thinking budget (`budget_tokens`) that Claude Haiku 4.5 used, so there’s no old setting to carry over. Compare two or three of these levels on your own evals:
29[Effort](https://platform.claude.com/docs/en/build-with-claude/effort) is the main control for how much Claude Haiku 5.5 thinks. Claude Haiku 4.5 uses a thinking budget (`budget_tokens`) instead, so there’s no effort setting to carry over. On Claude Haiku 5.5, a request that sets `budget_tokens` returns a 400 error. Compare two or three of these levels on your own evals:
3030 
3131* `low` is the cheapest and fastest level. Use it for chat, short tool tasks, and simple, high-volume requests. In long agent prompts, the model is more likely to skip a search, stop early, or skip a check at this level.
3232* `medium` is the default. Start here for most work, including agentic coding.
from line 33
3333* `high` suits knowledge work, longer agent tasks, and strict instruction following.
3434* `xhigh` and `max` are for work where a quality gain on your evals justifies the cost. Thinking and replies get much longer at these levels, so also run your evals on Claude Sonnet 5.5 and compare performance, cost, and speed.
3535 
36Claude Haiku 5.5 is the first Haiku model with effort levels. Thinking works as follows:
36Thinking works as follows:
3737 
3838* Thinking is on by default and counts toward `max_tokens`, which can go up to 128,000. A `max_tokens` value sized for Claude Haiku 4.5 requests that ran without thinking can cut the reply off, so leave room for thinking.
3939* To get less thinking, lower the effort level. In Anthropic’s testing, telling the model in the prompt to answer directly didn’t stop it from thinking. You can also turn thinking off with `thinking: {"type": "disabled"}`. This works at `low`, `medium`, and `high` only. At `xhigh` and `max`, the request returns a 400 error.
4040* At `xhigh` effort in multi-turn chats, the model sometimes writes its whole answer in its thinking and ends the turn with no visible text. If you see this behavior, check each response for an empty reply.
41* Changing the top-level `effort` value between requests invalidates the prompt cache for the conversation’s messages. Where your platform supports it, you can change the level partway through a conversation with a [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) change, which keeps the cache. A change holds for every later turn until another one replaces it. It needs the `mid-conversation-output-config-2026-07-01` beta header and adaptive thinking, which is the default. With thinking off, a per-message effort change returns a 400 error.
41* Changing the top-level `output_config.effort` value between requests invalidates the prompt cache for the conversation’s messages. On [supported platforms](https://platform.claude.com/docs/en/build-with-claude/effort-per-message#feature-availability), you can change the level partway through a conversation with a [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) change, which keeps the cache. A change holds for every later turn until another one replaces it. It needs the `mid-conversation-output-config-2026-07-01` beta header and adaptive thinking, the default thinking mode. With thinking off, a per-message effort change returns a 400 error.
4242 
4343## Accurate search results
4444 
from line 48
4848The current date is {{current_date}}.
4949```
5050 
51Render the date once, when the conversation starts, and send the same `system` and `tools` on every later request in that conversation (see [Keep earlier turns unchanged](https://platform.claude.com/docs/en/models/haiku-5-5/migration-guide#keep-earlier-turns-unchanged)). When a conversation continues on a later day, [give the new date in the newest turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#changing-context) instead.
51Render the date once, when the conversation starts, and send the same `system` and `tools` on every later request in that conversation (see [Keep earlier turns unchanged](https://platform.claude.com/docs/en/models/haiku-5-5/migration-guide#keep-earlier-turns-unchanged)). When a conversation continues on a later day, [give the new date in the newest turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#changing-context) instead.
5252 
5353The model also sometimes needs an extra nudge to search. This occurs most at `low` effort and with long system prompts. To fix it, add this text directly after the date:
5454 
from line 132
132132* `bio`: the request could enable biological harm, such as dangerous lab methods. Everyday health and educational questions aren’t affected. If the `bio` classifier blocks your organization’s life sciences work, you can apply to the [Life Sciences Verification Program](https://www.anthropic.com/news/life-sciences-verification-program).
133133* `general_harms`: the request falls under a usage-policy area other than the previous three. Benign work can also trigger this category.
134134 
135If you’re moving from Claude Haiku 4.5, these refusals are new.
135Claude Haiku 4.5 doesn’t return these refusals.
136136 
137137Claude Haiku 5.5 has no [server-side fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#server-side-fallback). If a request is declined, handle `stop_reason: "refusal"` in your client. Sending the same request to Claude Haiku 5.5 again usually returns another refusal.
138138 

build-with-claude/prompt-engineering/prompting-claude-opus-5-5 Changed · +10 / -6 lines

from line 43
4343* Reserve `xhigh` and `max` for work where you’ve measured a quality gain.
4444* To get less thinking, lower the effort level first. Lowering effort reduces thinking, and with it cost and latency, more reliably than prompt instructions do.
4545 
46Changing the top-level `effort` value between requests invalidates the prompt cache. To change the level partway through a conversation, use a [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) change instead, which keeps the cache. Per-message effort is in beta. A change holds for every later turn until another one replaces it.
46Changing the top-level `effort` value between requests invalidates the cached messages. To change the level partway through a conversation, use a [per-message effort](https://platform.claude.com/docs/en/build-with-claude/effort-per-message) change instead, which keeps the cache. Per-message effort is in beta. A change holds for every later turn until another one replaces it.
4747 
4848## Prompts written for thinking disabled
4949 
from line 68
6868 
6969A system prompt addition can also make these early stops less frequent. Claude Opus 5.5 is responsive to instructions that name the specific kinds of early stop you want it to avoid, such as ending the turn with a summary that announces the next step instead of taking it. It also helps to name the stops you do want, for example when no work can advance without the user’s input.
7070 
71The following paragraph is one example of such an addition, written for agents that run fully unattended, where you want the model to keep working rather than stop to report. Treat it as a starting point: you might need to adapt it for your own application. Add it at the end of your system prompt from the first request of the session: adding it partway through changes the `system` prompt and invalidates the conversation’s earlier thinking blocks (see [Add instructions with a mid-conversation system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#new-instructions)). Because it tells the model to put status notes in the same message as its next tool call, those notes arrive between tool calls as progress updates. The text of these updates comes back empty at the default `thinking.display`. Set `display: "updates"` to receive a summary of each (see [User-facing progress updates](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5#user-facing-progress-updates)). With this addition the model carries on where it would otherwise have stopped to check in, so keep your own confirmation step for risky or irreversible actions, and leave the addition out of human-in-the-loop applications, where someone is there to answer. Expect somewhat more tool calls and output tokens per task.
71The following paragraph is one example of such an addition, written for agents that run fully unattended, where you want the model to keep working rather than stop to report. Treat it as a starting point: you might need to adapt it for your own application. Add it at the end of your system prompt from the first request of the session: adding it partway through changes the `system` prompt and invalidates the conversation’s earlier thinking blocks (see [Change instructions](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#new-instructions)). Because it tells the model to put status notes in the same message as its next tool call, those notes arrive between tool calls as progress updates. The text of these updates comes back empty at the default `thinking.display`. Set `display: "updates"` to receive a summary of each (see [User-facing progress updates](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5#user-facing-progress-updates)). With this addition the model carries on where it would otherwise have stopped to check in, so keep your own confirmation step for risky or irreversible actions, and leave the addition out of human-in-the-loop applications, where someone is there to answer. Expect somewhat more tool calls and output tokens per task.
7272 
7373```text wrap
7474A standing instruction from the user, the person you are working for. It is about how your turns end. A message with no tool call in it ends your turn, and the work stops there until you are asked to continue. The user has seen you end turns in four ways while work they asked for was still owed, and does not want any of them. One: a long summary of what was done that closes by announcing the next step and has no tool call, so the next thing never starts. Two: an offer to carry on with something unless the user would prefer otherwise, which stops to wait for an answer the user was not going to give. Three: a list of decisions for the user when, by your own account, none of them blocks the rest of the work. Four: deciding that this is a good place to report, because the turn has been long or a milestone is done. Status notes are welcome, and so are your recommendations on open decisions, but put them in the same message as your next tool call and carry on with whatever does not depend on the user's answer. If you notice yourself inviting the user to redirect you or offering to wait, delete it and do the next thing. The stops the user does want are the ones where nothing can move without them, or where the thing blocking you is deliberately protected from you. This does not override the need for confirmation on risky or destructive actions.
from line 78
7878 
7979Claude Opus 5.5 runs safety classifiers, including for biology, cybersecurity, and reasoning extraction.
8080 
81* **Biology:** The biology safeguards are the same as Claude Fable 5.1’s and are new if you’re coming from Claude Opus 5. Everyday health and educational questions are unaffected. If the biology classifier blocks your organization’s life sciences work, apply to the [Life Sciences Verification Program](https://www.anthropic.com/news/life-sciences-verification-program).
81* **Biology:** The biology safeguards are the same as Claude Fable 5.1’s, and Claude Opus 5 doesn’t have them. Everyday health and educational questions are unaffected. If the biology classifier blocks your organization’s life sciences work, apply to the [Life Sciences Verification Program](https://www.anthropic.com/news/life-sciences-verification-program).
8282* **Cybersecurity:** Finding vulnerabilities in source code is allowed. High-risk dual-use cybersecurity activities are not. If the cybersecurity classifier blocks your organization’s legitimate security work, apply to the [Cyber Verification Program](https://support.claude.com/en/articles/14604842).
8383* **Reasoning extraction:** Requests that push the model to reproduce its internal reasoning in the response text might be declined with the `reasoning_extraction` category. If your prompts ask the model to write its reasoning in the response, remove those instructions, set `display: "summarized"`, and read the summarized reasoning from the thinking blocks instead; see [Prompts written for thinking disabled](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5#prompts-written-for-thinking-disabled). You can still ask for a short explanation of the answer or a summary of the actions taken; see [Keep reasoning in thinking blocks](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks).
8484 
from line 90
9090 
9191First, check that your client receives them. On Claude Opus 5.5 these notes come back as [progress-update `thinking` blocks](https://platform.claude.com/docs/en/build-with-claude/thinking#progress-updates) rather than `text` blocks, and their text is empty at the default `thinking.display`. As a result, a client that renders only `text` blocks can look silent during a long agentic turn. Set `display: "updates"` (beta, `thinking-display-updates-2026-08-18` header) to receive a short summary of each note; see [Progress updates between tool calls](https://platform.claude.com/docs/en/build-with-claude/thinking#progress-updates) for how to render them.
9292 
93Second, if the model might need to hand the user something verbatim partway through a long turn, such as a code snippet, give it a simple tool for sending the user a message and tell it to reserve the tool for that content. Declare the tool in `tools` from the first request of the session: adding it to `tools` later edits the conversation’s prefix and invalidates earlier thinking blocks (see [tool changes in Preserved thinking](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#tool-changes)).
93Second, if the model might need to hand the user something verbatim partway through a long turn, such as a code snippet, give it a tool for sending the user a message and tell it to reserve the tool for that content. Declare the tool in `tools` from the first request of the session: adding it to `tools` later edits the conversation’s prefix and invalidates earlier thinking blocks (see [Add, remove, or turn off tools](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#tool-changes)).
9494 
9595Third, if you want more frequent or predictable updates, such as a one-line statement of intent before the first tool call and a short recap at the end, say so in the system prompt; the model is responsive to such instructions. This helps most in human-in-the-loop work.
9696 
97Fourth, if long tool-calling turns still go quiet for longer than you want, have your harness ask for an update. With `display: "updates"` set (the first lever), count consecutive tool-calling steps that give the user nothing to read: no `text` block and no progress-update text. After several in a row (five, for example), append a reminder such as the following one after the latest tool results, as a [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) (`clear_at: "next_user_message"`, in beta with the `mid-conversation-system-clear-at-2026-08-21` header). If the turn stays quiet, stop after two or three reminders rather than sending more. Because each reminder is appended and left in place, rather than inserted for one request and deleted on the next, the prompt cache keeps matching and the thinking blocks that follow it stay valid (see [Send per-turn reminders as turn-scoped system messages](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#per-turn-reminders)). In Anthropic’s testing on agentic coding tasks, this roughly halved the share of tasks with a long silent stretch, with no measurable change in cost.
97Fourth, if long tool-calling turns still go quiet for longer than you want, have your harness ask for an update. With `display: "updates"` set (the first lever), count consecutive tool-calling steps that give the user nothing to read: no `text` block and no progress-update text. After several in a row (five, for example), append a reminder such as the following one after the latest tool results, as a [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#turn-scoped-system-messages) (`clear_at: "next_user_message"`, in beta with the `mid-conversation-system-clear-at-2026-08-21` header). If the turn stays quiet, stop after two or three reminders rather than sending more. Because each reminder is appended and left in place, rather than inserted for one request and deleted on the next, the prompt cache keeps matching and the thinking blocks that follow it stay valid (see [Send a reminder for one turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking/change-tools-or-instructions#per-turn-reminders)). In Anthropic’s testing on agentic coding tasks, this roughly halved the share of tasks with a long silent stretch, with no measurable change in cost.
9898 
9999```text wrap
100100The user hasn't heard from you in a while: say in a few words what you're doing, then continue.
from line 112
112112 
113113## Time signals for multiagent harnesses
114114 
115Claude Opus 5.5 is highly responsive to information about elapsed time, and in a multiagent setup, for example a lead agent that delegates to subagents, you can use that to speed up the work through better parallelization. If you can estimate how long the task should take, give the model a time budget: have your harness add a short line at the end of each message it sends back to the model giving the elapsed time against that budget, in seconds, for example `elapsed 340s / 1200s`. The model paces its work to finish inside the budget and usually finishes well before it, so set the budget somewhat above the time you actually want spent and tune it on a sample of your own tasks. If you can’t predict a sensible budget, show the elapsed time alone and add one sentence to the system prompt:
115Claude Opus 5.5 is highly responsive to information about elapsed time. In a multiagent setup, for example a lead agent that delegates to subagents, you can use that to speed up the work through better parallelization.
116 
117If you can estimate how long the task should take, give the model a time budget. Have your harness add a short line at the end of each message it sends back to the model, giving the elapsed time against that budget in seconds, for example `elapsed 340s / 1200s`.
118 
119The model paces its work to finish inside the budget and can finish well before it. So set the budget somewhat above the time you actually want spent, and tune it on a sample of your own tasks. If you can’t predict a sensible budget, show the elapsed time alone and add one sentence to the system prompt:
116120 
117121```text wrap
118122Time matters here: do not spend time that can be avoided, and the earlier a correct result is obtained, the better.
Feedback