A tightly compressed hay bale bound with steel strapping and a small red tamper-evident seal clipped to the strap, standing on a barn floor beside loose hay that was left behind, photoreal

Anthropic Now Compacts Claude Conversations When You Ask. The Summary Comes Back Signed, and You Can't Edit It.

On 14 September Anthropic added on-demand compaction to the Messages API, in beta behind the compact-2026-09-04 header. You send a compaction parameter, get back one signed summary block, and send that block in place of the messages it covers. The summary can be written in the background while the agent keeps working, and you can keep recent turns word for word.

The block is plain text plus a signature, and the API rejects an altered block. When the summary drops a constraint, a file path or a decision, you can't correct it in place. You restate it after the block, or compact again with better instructions, which only works if you kept the original messages.

Several things fail without an error. A summary that never arrives is still a 200. A request that forgets the block runs without the summary. System messages inside the summarized range stop applying, and images, documents and fetched URLs are gone. The compaction call also reports zero top-level tokens, so cost tracking has to read usage.iterations.

If you run long agent sessions on Claude, you have probably written a summarizer of your own, or you turned on threshold compaction and let the API summarize once input passed 150,000 tokens. With your own summarizer, a bad summary was a string in your database, and you could fix it.

The new mode gives you control over when compaction happens, and takes away the ability to fix the result by hand.

What shipped

You send the conversation as it stands with "compaction": {"type": "summarize"}. The response has no reply in it. It holds one compaction block with a content field and a signature, and stop_reason is "compaction". From then on you send that block first in messages, in place of the messages it summarized, followed by whatever came after.

Three things come with it. You choose the moment. The summarization request can run in the background while the conversation continues on its full history, and you swap the block in when it lands. And you can keep a tail of recent turns verbatim by leaving them out of the compaction request. On models with preserved thinking, the thinking in those kept turns stays valid, provided they directly followed the summarized messages and the system prompt and tools haven't changed.

Availability is narrower than threshold compaction. The docs list threshold compaction on the Claude API, Claude Platform on AWS, Bedrock, Google Cloud and Microsoft Foundry. On-demand compaction is on the Claude API and explicitly not on Bedrock or Google Cloud. It works on eleven models, from Claude Fable 5.1 and Mythos 5.1 down to Opus 4.6 and Sonnet 4.6, and you can't send compaction and context_management on the same request.

A summary you can read but not change

The summary is readable. Anthropic's own example is a short recap of a recipe app data model. The docs tell you to keep the block "exactly as the API returned it", and the beta has specific 400 errors for an altered, misplaced or duplicated block.

Summaries lose things, and Anthropic says so. The Claude Fable 5.1 prompting guide lists summaries that drop constraints, decisions or exact details as a known symptom of client-side compaction, and ships a six-point summarization instruction to counter it. The default server-side prompt already accounts for this, but any summary shrinks a long session to a few paragraphs, and something has to go.

When that happens with a signed block, you have two fixes. Add a message after the block that restates what went missing. Or compact again with better instructions, which can run up to 16,384 characters. Compacting a conversation that already starts with a block summarizes the old summary plus everything after it, so a detail lost in the first round stays lost. To get it back you need the original messages, and the conversation you send has to fit the model's context window.

The block is a compressed stand-in for the history. Keep the history itself somewhere you control.

What stops existing after the swap

Mid-conversation role: "system" messages inside the summarized range get summarized like any other message. The docs say: "What they declared stops applying once the block replaces them." The same goes for tool changes declared mid-conversation.

Take a coding agent where an operator added a system message at turn 40: do not write to the migrations/ directory. A background compaction covers turns 1 to 60. After the swap, that rule exists only as whatever sentence the summary wrote about it, and the model reads it as part of a recap. The fix is to state it again in a new system message sent right after your next user turn. The docs say not to put it between the block and the kept turns, because that breaks the thinking in those turns.

Images, documents, container_upload blocks and fetched URLs inside the summarized range are dropped too. If the agent was working from a screenshot of a failing build or a PDF of a contract, it now has a description of that file at best. Re-upload anything later turns still depend on.

Failures that are easy to misread

No summary. A summary is produced only when the call ends with text and no tool call. Otherwise you get a 200 with empty content and a stop_reason of max_tokens, model_context_window_exceeded, refusal, tool_use or end_turn, and the call is still billed. max_tokens covers any thinking before the summary as well, so the docs advise allowing several thousand tokens.

No block. A later request that leaves out the block, in the docs' own words, "reaches Claude without the summary." The API accepts it. The agent just forgets.

Leftovers. Summarized messages left in front of the block return a 400. Left behind it, they are accepted and sent to the model again, so you pay for the summary and the originals.

No header. Forget the beta header and the error is a generic compaction: Extra inputs are not permitted, with no mention of the header.

The bill sits in iterations

On the compaction call, top-level input_tokens and output_tokens are zero, because no reply was generated. The real usage is in usage.iterations as a compaction entry. A dashboard that sums the top-level fields records every compaction as free.

Summarization uses the model of the request, and the docs list no option to route it to a cheaper model. On Fable 5.1 at $10 per million input tokens, compacting a 600,000-token session costs about $6 of input at list price before the summary is written. The docs don't say whether that call reads from the prompt cache, so measure it on your own traffic before you schedule compaction every few turns.

What to change before you adopt it

Keep the raw transcript. Store every original message outside the conversation you send. It is the only way to rebuild a summary that lost something.

Write the instructions. Start from Anthropic's six-point instruction in the Fable 5.1 guide and add what your domain can't lose: ticket IDs, file paths, the user's exact constraints. Tell the model not to call tools.

Re-issue standing rules after each swap. Keep a list of system messages, tool changes and uploads that must outlive compaction, and resend them right after the next user turn.

Gate the swap on the stop reason. Swap only when stop_reason is "compaction", drop exactly the messages you sent, and add a test that fails if any request after a swap goes out without the block.

Fix cost tracking now. Sum usage.iterations, and tag compaction calls separately so you can see what they cost.

Plan for two code paths. If part of your traffic runs through Bedrock or Google Cloud, on-demand compaction isn't there. Keep threshold compaction or your own summarizer for those routes.

This fits a direction the API was already taking. Since 1 September, Fable 5.1 checks that nothing before a replayed thinking block has changed, and for accounts created on or after 31 August a changed history returns a 400. Signed summaries apply the same idea to compacted history. For the stretch a signed block covers, your code controls what goes into the summary and what gets restated after it, and the text of the summary is fixed once the API returns it.