Agent context compaction: keep what the 150K cutoff drops
Agent context compaction drops every block before the summary at 150K tokens. What survives, what instructions silently replaces, and the usage field that lies.

TL;DR
Agent context compaction replaces a long transcript with a model-written summary, and once that summary exists the API permanently drops every content block that came before it. The default trigger is 150,000 input tokens, and the transformation is lossy by construction — there is no summarizer that preserves everything, so the engineering question is not whether the agent forgets but what you make sure survives. Anything load-bearing belongs on a durable surface the summary does not gate.
What agent context compaction actually does
Agent context compaction is a server-side context-management strategy that summarizes a conversation once its input tokens cross a threshold, then serves that summary in place of the transcript. The model writes the summary itself, the API stores it as a content block, and the conversation continues past the context window without you writing any summarization code.
Long-running agents hit that window eventually. The old answer was to write your own summarizer: truncate the history, ask a model to condense it, splice the result back in. Anthropic’s compaction moves that loop server-side.
You enable it by adding one edit to the request:
{
"context_management": {
"edits": [
{
"type": "compact_20260112",
"trigger": { "type": "input_tokens", "value": 150000 },
"pause_after_compaction": false,
"instructions": null
}
]
}
}With the compact-2026-01-12 beta header set, the API watches the request’s input token count. When it reaches the trigger, the model writes a summary of the conversation so far and returns it as a compaction content block ahead of its normal response:
{
"content": [
{ "type": "compaction", "content": "Summary of the conversation..." },
{ "type": "text", "text": "Continued response based on compacted context..." }
]
}Here is the part that matters, and it is easy to skim past: all content blocks prior to the compaction block are dropped by the API on subsequent requests. The compaction block itself is kept, along with everything after it. The transcript that produced the summary is gone from the model’s view — not truncated, not archived somewhere the model can reach, just no longer part of the prompt.
That single rule is the whole design. Everything else is a consequence of it.
The transformation is lossy, and that is not a bug
Sophie Alpert put the underlying principle better than any API doc will: there are no lossless transformations of natural-language text. Her argument is about AI writing assistance — that “every rewrite and rephrase changes the meaning of your writing,” because whoever is rewriting lacks “the most detailed mental representation” of the original intent.
Compaction is exactly that transformation, applied automatically, to the record your agent is reasoning from.
The default summarization prompt is instructive about what it is optimizing for. It tells the model the summary exists “to provide continuity so you can continue to make progress towards solving the task in a future context, where the raw history above may not be accessible,” and to “write down anything that would be helpful, including the state, next steps, learnings etc.”
That is a good prompt for continuity. It is not a prompt for fidelity, and it cannot be — 180,000 tokens do not fit in a summary. The summarizer is making judgment calls about what mattered, using its own read of the task, and it makes those calls without knowing which detail you will need in forty turns.
So the failure mode is not dramatic. The agent does not announce that it forgot something. It carries on confidently from a summary that omitted the constraint you established in turn nine, and the first sign of trouble is work that quietly contradicts a decision you already made.
The billing field that lies to you
Before the design advice, one operational trap worth its own section, because it silently breaks cost dashboards.
When compaction fires, the request runs more than one sampling iteration: one to generate the summary, one to answer. The response reports them separately:
{
"usage": {
"input_tokens": 23000,
"output_tokens": 1000,
"iterations": [
{ "type": "compaction", "input_tokens": 180000, "output_tokens": 3500 },
{ "type": "message", "input_tokens": 23000, "output_tokens": 1000 }
]
}
}The top-level input_tokens and output_tokens reflect non-compaction iterations only. In that response, the top level reports 23,000 input tokens for a request that actually processed 203,000 across both iterations. The docs are explicit about the consequence: if you previously relied on usage.input_tokens and usage.output_tokens for cost tracking or auditing, you need to update that logic to aggregate across usage.iterations.
Two related details save money rather than cost it. A compaction entry appears only when a new compaction is triggered — re-applying a compaction block you already hold incurs no additional compaction cost. And count_tokens applies existing compaction blocks without triggering new ones, returning context_management.original_input_tokens so you can see the pre-compaction size.
Three mechanisms, three different losses
Compaction is one of three context-management tools, and they are frequently conflated. They are not interchangeable, and picking by name rather than by loss profile is how agents end up with the wrong thing missing.
| Mechanism | Beta header | What it removes | What survives |
|---|---|---|---|
| Context editing | context-management-2025-06-27 | Old tool results (clear_tool_uses_20250919), thinking blocks (clear_thinking_20251015) | The conversation’s turn structure — you still see that a tool ran |
| Compaction | compact-2026-01-12 | Every block before the summary | One prose narrative of the whole span |
| Memory tool | none (memory_20250818) | Nothing | Files under /memories, across sessions |
Context editing clears; it does not summarize. It prunes stale tool output while leaving the shape of the conversation intact, which is the right tool when the raw payloads are large but the sequence of actions is what matters. Compaction summarizes; it keeps a story and discards the sequence. The memory tool is the only one of the three that is additive — the agent writes to a directory that outlives the request entirely.
The practical read: compaction is not a memory system. It is a survival mechanism for the context window. If you treat it as memory, you have built an agent whose long-term recall is a paraphrase written under a token budget.
Designing for the cutoff
Four things follow from the mechanism.
1. Put load-bearing state somewhere the summary does not gate. If a constraint, an identifier, or a decision must survive turn 400, it should not exist only in the transcript. Write it to a file the agent re-reads, a memory store, or a record your harness re-injects after each compaction. This is the same discipline that makes agent tool instructions work — state the thing durably rather than hoping context carries it.
2. Understand what instructions replaces. The field lets you supply a custom summarization prompt, and it completely replaces the default prompt when provided. That is easy to misread as “adds emphasis.” A narrow instruction like “summarize the code changes” silently discards the default’s guidance about state, next steps, and learnings. If you customize, restate what the default was doing before you add your own priorities.
3. Append the full content, not the text. Every SDK guide flags this and it is still the most common integration bug: append response.content to your messages on every turn, not the extracted text string. Compaction blocks live in content, and the API uses them to replace the compacted history on the next request. Pull out just the text and you silently lose the compaction state — the conversation reverts to sending the whole transcript, and you are back to hitting the window.
4. Keep the cache breakpoint on the system prompt. Compaction blocks accept cache_control, and a breakpoint on the system prompt stays valid across a compaction event — only the summary is written as a new cache entry. That is the design working with you. Rebuilding the prefix around the summary invalidates everything after it, which is the expensive mistake.
For agents that need a checkpoint rather than a seamless continuation, pause_after_compaction: true returns stop_reason: "compaction" with only the compaction block, letting you inspect the summary, append preserved messages, or inject additional context before calling again. That hook is where a well-designed harness earns its keep — it is the one moment you can see exactly what the agent is about to carry forward.
Common mistakes
- Treating compaction as free. The summarization iteration is a real model call over the full pre-compaction context, and it lands in
usage.iterations, not the top-level fields. - Lowering the trigger to “lose less.” A lower trigger compacts more often on smaller spans. Each summary is less lossy, but you pay for more of them, and compounding summaries-of-summaries has its own drift.
- Assuming the streaming shape matches text. Compaction blocks stream non-streaming: one
content_block_start, a singlecontent_block_deltacarrying the whole summary as acompaction_delta, thencontent_block_stop. A UI written for token-by-token text sits still, then jumps. - Expecting it on every model. Compaction is supported on Claude Opus 5, Opus 4.8/4.7/4.6, Sonnet 5, Sonnet 4.6, and the Fable/Mythos 5 models — not universally.
- Debugging “the agent got dumber” as a model problem. When quality drops sharply after a long run rather than gradually, check whether a compaction landed between the good behavior and the bad. That is a context problem, not a capability one — the class of failure that separates a demo from a production-grade agent.
The takeaway
Compaction is a good feature solving a real problem, and the alternative — writing your own summarizer — is worse in every dimension except one: you knew where the loss was. Server-side compaction hides that boundary, and hidden boundaries are where agents fail confidently.
So build as if the summary will drop the thing you care about, because eventually it will. The mechanism guarantees only that the conversation continues, not that it remembers. Everything you cannot afford to lose goes somewhere the 150K cutoff cannot reach.
FAQ
What is agent context compaction?
Compaction is a server-side context-management strategy that summarizes a conversation when its input tokens cross a threshold, then serves the summary in place of the transcript. On the Claude API it is the compact_20260112 edit type behind the compact-2026-01-12 beta header. The model writes a summary into a compaction content block, and on every subsequent request the API drops all content blocks that came before it.
What is the difference between context editing and compaction?
They remove different things in different ways. Context editing clears — clear_tool_uses_20250919 deletes old tool results and clear_thinking_20251015 deletes thinking blocks, leaving the turn structure intact. Compaction summarizes — it collapses everything before a point into one prose block and discards the underlying turns. Editing loses raw detail but keeps the shape of what happened; compaction keeps a narrative and loses the shape.
When does compaction trigger, and can I change it?
It fires when input tokens reach trigger.value, which defaults to 150,000 and has a documented minimum of 50,000. input_tokens is the only supported trigger type. Lowering it compacts more often on smaller transcripts; raising it produces fewer, larger, lossier summaries. Neither setting makes compaction lossless.
Why does my token usage look wrong after enabling compaction?
Because the top-level usage.input_tokens and usage.output_tokens reflect non-compaction iterations only. A compaction’s cost appears as a separate entry in the usage.iterations array. Cost tracking that reads only the top-level fields under-reports the request — sum across usage.iterations instead.
Does compaction break prompt caching?
No. Compaction blocks accept cache_control, and a cache breakpoint on the system prompt stays valid across a compaction event — only the new summary is written as a fresh cache entry. Re-applying a compaction block you already have costs nothing extra, because no new compaction is triggered.
How do I stop the agent from losing the one fact that mattered?
Do not rely on the summary to carry it. Write load-bearing state to a durable surface the summary does not gate — a file, a memory store, or a structured record your harness re-injects after each compaction. The instructions field can bias the summarizer, but it completely replaces the default prompt rather than adding to it.
Sources
Related Articles

AI Engineering
Agent Harness Design: Why an ARC-AGI-3 Score Tripled
Agent harness design decided a benchmark: OpenAI's ARC-AGI-3 score went 13.3% → 38.3% with zero model changes. What that means for your agent loop.

AI Engineering
Why 77% of Autonomous AI Agents Never Reach Production (2026)
Only 23% of autonomous AI agents reach production in 2026. The demo-to-production gap, why agents fail, and the playbook the winners actually use.

AI Engineering
How to Build an MCP Server: A Step-by-Step Guide (2026)
How to build an MCP server, step by step: JSON-RPC 2.0, the Streamable HTTP transport, typed tools, and agent discovery — from a real one I shipped.
Keep reading
Get new posts on AI, Claude Code & LLMs
New deep-dives on AI engineering, Claude Code, and developer tooling — follow along however you prefer.
About the Author
Software engineer writing about AI, Claude Code, LLMs, OpenAI, Anthropic, and developer tooling. 5+ years building production systems at Expedia Group, Tekion, and BYJU'S.