The whole hunk
from line 383, old and new numbered
/
lines
from line 383
383383
384384Each row compares two consecutive requests:
385385
386| Change between requests | Later thinking blocks |
387| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
388| Append messages at the end | Valid |
389| Add a tool with `defer_loading: true` that nothing has referenced yet | Valid |
390| Remove `thinking` blocks from the start of the history, from the end, or all of them | Valid (the model loses that reasoning) |
391| Change any request parameter outside `system`, `tools`, and `messages` (`effort`, `max_tokens`, `output_config`, `tool_choice`, `metadata`, `thinking.display`, and so on) | Valid |
392| Add, move, or remove `cache_control` markers | Valid |
393| A rotating signed URL that returns the same bytes | Valid |
394| Server-side compaction or context editing removes or replaces content | Valid (the check compares what you sent, not the server's edited copy) |
395| A cleared [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#per-turn-reminders) left in place | Valid |
396| Edit, reorder, or delete any earlier `user`, `assistant`, or `system` message | Invalid, except when the signed block from [on-demand compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#server-side-trimming) replaces the messages it summarizes, under the conditions in [Keep-tail compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#keep-tail-compaction) |
397| Re-render the context you put in the first user message with a changed value | Invalid for every thinking block |
398| Clear or shorten an earlier `tool_result`, re-encode an earlier image, or change an earlier `tool_use` input | Invalid for every later thinking block |
399| Add a text block to an earlier user turn, or remove one you added last time | Invalid |
400| Change the top-level `system` string or blocks | Invalid |
401| Add, remove, rename, or edit a tool in `tools` | Invalid |
402| Remove a `thinking` block from the middle of the history and keep later ones | Invalid for every later thinking block |
403| Put back a `thinking` block you removed on an earlier request | Invalid for thinking blocks produced while it was gone |
404| An image or document URL that returns different bytes on the next request | Invalid |
405| The same turn-scoped message deleted or reworded on a later request | Invalid |
386| Change between requests | Later thinking blocks |
387| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
388| Append messages at the end | Valid |
389| Add a tool with `defer_loading: true` that nothing has referenced yet | Valid |
390| Remove `thinking` blocks from the start of the history, from the end, or all of them | Valid (the model loses that reasoning) |
391| Change any request parameter outside `system`, `tools`, and `messages` (`effort`, `max_tokens`, `output_config`, `tool_choice`, `metadata`, `thinking.display`, and so on) | Valid |
392| Add, move, or remove `cache_control` markers | Valid |
393| A rotating signed URL that returns the same bytes | Valid |
394| Server-side compaction or context editing removes or replaces content | Valid (the check compares what you sent, not the server's edited copy) |
395| A cleared [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#per-turn-reminders) left in place | Valid |
396| Edit, reorder, or delete any earlier `user`, `assistant`, or `system` message | Invalid, except when the signed block from [on-demand compaction](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand) replaces the messages it summarizes, 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) |
397| Re-render the context you put in the first user message with a changed value | Invalid for every thinking block |
398| Clear or shorten an earlier `tool_result`, re-encode an earlier image, or change an earlier `tool_use` input | Invalid for every later thinking block |
399| Add a text block to an earlier user turn, or remove one you added last time | Invalid |
400| Change the top-level `system` string or blocks | Invalid |
401| Add, remove, rename, or edit a tool in `tools` | Invalid |
402| Remove a `thinking` block from the middle of the history and keep later ones | Invalid for every later thinking block |
403| Put back a `thinking` block you removed on an earlier request | Invalid for thinking blocks produced while it was gone |
404| An image or document URL that returns different bytes on the next request | Invalid |
405| The same turn-scoped message deleted or reworded on a later request | Invalid |
406406
407407### Check whether your code edits the prefix
408408
from line 785
785785
786786Each common prefix edit has a replacement that gives the model the same information and leaves earlier bytes unchanged, so later thinking stays valid. Find the edit your code makes today in the first column:
787787
788| Instead of | Use | Beta header |
789| --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
790| Rebuilding the top-level `system` prompt | A [mid-conversation system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#new-instructions) | None |
791| Re-rendering the context in your first user message (environment, date, memory, project instructions) on each request | Render it once and resend it unchanged. When something changes, [put the new version in the newest turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#changing-context) | None |
792| Clearing or shortening old `tool_result` content, or re-encoding old images, in place | Shorten a tool result or downscale an image before the first time you send it, not after. To clear old results later, [trim context on the server](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#server-side-trimming) with `clear_tool_uses_20250919` | `context-management-2025-06-27` |
793| Injecting a reminder and deleting it on the next request | A [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#per-turn-reminders) (`clear_at: "next_user_message"`) | `mid-conversation-system-clear-at-2026-08-21` |
794| Adding or removing entries in `tools` | [`tool_addition` and `tool_removal` blocks](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#tool-changes) | `mid-conversation-tool-changes-2026-07-01` |
795| Changing top-level `output_config.effort` (restarts the cache, doesn't affect thinking) | A [per-message `output_config`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#effort-changes) | `mid-conversation-output-config-2026-07-01` |
796| Dropping or summarizing old turns on the client | [On-demand compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#server-side-trimming) to keep the recent turns with their thinking, other server-side [compaction or context editing](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#server-side-trimming), or [client-side compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#custom-compaction-on-the-client) that keeps no stale thinking | `compact-2026-09-04` (not on Amazon Bedrock or Google Cloud) |
797| An image or document URL whose bytes change between requests | A [`file_id` from the Files API](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#files-by-id), or base64 | None |
788| Instead of | Use | Beta header |
789| --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
790| Rebuilding the top-level `system` prompt | A [mid-conversation system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#new-instructions) | None |
791| Re-rendering the context in your first user message (environment, date, memory, project instructions) on each request | Render it once and resend it unchanged. When something changes, [put the new version in the newest turn](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#changing-context) | None |
792| Clearing or shortening old `tool_result` content, or re-encoding old images, in place | Shorten a tool result or downscale an image before the first time you send it, not after. To clear old results later, [trim context on the server](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#server-side-trimming) with `clear_tool_uses_20250919` | `context-management-2025-06-27` |
793| Injecting a reminder and deleting it on the next request | A [turn-scoped system message](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#per-turn-reminders) (`clear_at: "next_user_message"`) | `mid-conversation-system-clear-at-2026-08-21` |
794| Adding or removing entries in `tools` | [`tool_addition` and `tool_removal` blocks](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#tool-changes) | `mid-conversation-tool-changes-2026-07-01` |
795| Changing top-level `output_config.effort` (restarts the cache, doesn't affect thinking) | A [per-message `output_config`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#effort-changes) | `mid-conversation-output-config-2026-07-01` |
796| Dropping or summarizing old turns on the client | [On-demand compaction](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand) to keep the recent turns with their thinking, other server-side [compaction or context editing](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#server-side-trimming), or [client-side compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#custom-compaction-on-the-client) that keeps no stale thinking | `compact-2026-09-04` |
797| An image or document URL whose bytes change between requests | A [`file_id` from the Files API](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#files-by-id), or base64 | None |
798798
799799All of these assume you [send assistant turns back exactly as returned](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#append-assistant-turns-exactly-as-returned). Mid-conversation system messages, turn-scoped system messages, and tool changes aren't available on every model: [Mid-conversation system messages and tool changes](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages) lists the models that accept them. If your code serves several models, keep editing the top-level `system` prompt for the models that don't accept them.
800800
from line 940
940940
941941Another common prefix edit is client-side trimming: dropping or summarizing the oldest turns and keeping the recent ones verbatim. The kept turns' thinking blocks were produced while the removed history was still in place, so they fail the check. The server-side equivalents don't count as edits, because the check compares the conversation as you sent it:
942942
943* [Compaction](https://platform.claude.com/docs/en/build-with-claude/compaction) summarizes older turns into a compaction block when the context approaches a threshold you set, and the checked prefix restarts from that block. Its [`instructions` parameter](https://platform.claude.com/docs/en/build-with-claude/compaction#custom-summarization-instructions) takes your own summarization prompt, such as "preserve every ticker, position size, and stated assumption". [On-demand compaction](https://platform.claude.com/docs/en/build-with-claude/compaction#compact-on-demand-with-the-compaction-parameter) (beta) returns the summary from a separate request, which can [run in the background](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#background-compaction). Send `"compaction": {"type": "summarize"}` in the request body, and the response carries a single `compaction` block, holding the summary and a signature, instead of a reply. On-demand compaction is available on the Claude API but not on Amazon Bedrock or Google Cloud, and it needs the `compact-2026-09-04` beta header on the summary request and on every later request that carries the block. You send the block in place of the messages it summarizes. The check accepts that swap, so the turns you keep can stay valid with their thinking, under the conditions in [Keep-tail compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#keep-tail-compaction).
943* [On-demand compaction](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand) (beta) returns the summary from a separate request, which can [run in the background](https://platform.claude.com/docs/en/build-with-claude/compaction-background), and you send the returned block in place of the messages it summarizes. The check accepts that swap, so the turns you keep can stay valid with their thinking, 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). [Request a summary](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand#request-a-summary) shows the request and names the beta header it needs.
944* [Compaction at a token threshold](https://platform.claude.com/docs/en/build-with-claude/compaction-threshold) summarizes older turns into a compaction block when the context approaches a threshold you set, and the checked prefix restarts from that block. Its [`instructions` parameter](https://platform.claude.com/docs/en/build-with-claude/compaction-threshold#custom-summarization-instructions) takes your own summarization prompt, such as "preserve every ticker, position size, and stated assumption".
944945* [Context editing](https://platform.claude.com/docs/en/build-with-claude/context-editing) clears old tool results or old thinking blocks by rule, oldest first. The strategies are `clear_tool_uses_20250919` and `clear_thinking_20251015`.
945946
946947### Compact on the client
947948
948You can still compact on the client. If you write the summary yourself, don't send back a thinking block that was produced before the rewrite. If the API writes it with on-demand compaction, [Keep-tail compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#keep-tail-compaction) lists when kept thinking stays valid.
949You can still compact on the client. If you write the summary yourself, don't send back a thinking block that was produced before the rewrite. If the API writes it with on-demand compaction, [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) lists when kept thinking stays valid.
949950
950951#### Simple compaction (recommended)
951952
from line 969
968969
969970Keep-tail compaction summarizes the older turns and keeps the most recent turns verbatim, so the model still sees the last few exchanges word for word. If you write the summary yourself, it breaks the rule: the kept assistant turns still carry thinking blocks that were produced when the original turns, not the summary, came before them. Those blocks fail.
970971
971To keep that thinking, have the API write the summary with [on-demand compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#server-side-trimming). Send only the older turns in a request with the `compaction` parameter and the `compact-2026-09-04` beta header. Then send the signed block it returns in place of those turns, followed by the kept turns exactly as returned. The kept thinking stays valid while all of these hold:
972To keep that thinking, have the API write the summary with on-demand compaction. [Compaction that keeps recent turns](https://platform.claude.com/docs/en/build-with-claude/compaction-keep-recent-turns) shows how, and [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) lists when the kept thinking stays valid.
972973
973* The compaction request runs on a model with preserved thinking. The conversation's own model is the simple choice.
974* The kept turns directly follow the summarized messages, and the first kept message isn't one the API would merge into the last summarized one: a message with the same role, or a `role: "system"` message.
975* `system` and your non-deferred `tools` match the compaction request.
976
977The simplest way to meet the second is to compact exactly the `messages` of a request you already made. Mid-conversation system messages inside the summarized turns are summarized too, so their instructions and tool changes stop applying after the swap. To keep one in force, state it again in a `role: "system"` message directly after the first new `user` turn that follows the kept turns. A system message placed between the block and the kept turns breaks their thinking.
978
979974The rest of this section covers a summary you write yourself.
980975
981976
from line 1190
11951190
11961191#### Background (async) compaction
11971192
1198Background compaction builds the summary off the critical path while the conversation continues, then swaps it in a few requests later. Have the API write the summary with [on-demand compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#server-side-trimming):
1193Background compaction builds the summary off the critical path while the conversation continues, then swaps it in a few requests later. To keep the thinking produced in the meantime, have the API write the summary with on-demand compaction: [Compaction in the background](https://platform.claude.com/docs/en/build-with-claude/compaction-background) has the steps, and that thinking stays valid under the same [conditions for kept thinking](https://platform.claude.com/docs/en/build-with-claude/compaction-thinking-blocks#conditions-for-kept-thinking-to-stay-valid) as kept recent turns.
11991194
12001. Send the conversation so far in a separate request with the `compaction` parameter and the `compact-2026-09-04` beta header.
12012. Keep working on the full history while that request runs.
12023. On the first request after the block arrives, send it in place of the messages the compaction request held, followed by every turn appended since.
1203
1204The thinking produced while the summary was being built stays valid under the same conditions as in [Keep-tail compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#keep-tail-compaction).
1205
12061195A summary you build yourself breaks the rule the same way keep-tail does, with a delay: every assistant turn produced while the summary was being built carries thinking that predates the swap, and it all fails the moment the summary lands. If you use one, treat the swap like keep-tail and send `"drop_block"` from the swap onward, or compact synchronously.
12071196
12081197#### Patterns that don't work with preserved thinking
from line 1232
12431232 </Accordion>
12441233
12451234 <Accordion title="I compact by summarizing older turns and keeping recent turns verbatim. Does that still work?">
1246 Yes, if the API writes the summary. [On-demand compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#server-side-trimming) (beta header `compact-2026-09-04`) summarizes the older turns into a signed block that you send in place of them. The recent turns keep their thinking under the conditions in [Keep-tail compaction](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#keep-tail-compaction).
1235 Yes, if the API writes the summary. [On-demand compaction](https://platform.claude.com/docs/en/build-with-claude/compaction-on-demand) (beta header `compact-2026-09-04`) summarizes the older turns into a signed block that you send in place of them. The recent turns keep their thinking 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).
12471236
12481237 If you write the summary yourself, the kept turns' thinking fails the check, because those blocks were produced against the history you replaced. Strip `thinking` and `redacted_thinking` blocks from the turns you carry across and keep their `text` and `tool_use` blocks, or send `prefix_mismatch_behavior: "drop_block"` and let the API drop them. Simple compaction leaves no thinking behind to fail and is the recommended approach: one summary message plus the next user turn, with no earlier turns replayed. Server-side [compaction](https://platform.claude.com/docs/en/build-with-claude/compaction) and [context editing](https://platform.claude.com/docs/en/build-with-claude/context-editing) don't count as edits. See [Compact on the client](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#custom-compaction-on-the-client).
12491238 </Accordion>