toolcall() ← all concepts

// concept · agentic

Your agent summarised itself and lost the detail

A long agent session reaches the context limit and keeps going, which feels like a free upgrade. What actually happened is that the conversation was replaced by a paragraph about the conversation.

// not a trim

The instinct is that something drops the oldest few messages and slides the window forward. That is not what happens. From the docs:

On subsequent requests, the API automatically drops all content blocks prior to the compaction block, continuing the conversation from the summary forward.

All of them. What the model has after that point is one compaction block containing a summary, and whatever came after it.

# before [ 240 messages · tool calls · results · decisions ] # after [ compaction: "Summary of the conversation: the user requested…" ] everything above is gone, not archived

So a small detail is either in the paragraph or nowhere

A summariser keeps what looks important. The trouble is that importance is judged without knowing what you are about to ask next.

survives the goal · the current task · recent decisions may not a file path mentioned once, forty turns ago may not why you rejected the first approach may not the exact wording of a constraint

This is the whole failure mode. The agent is not confused and has not malfunctioned — it is working from an accurate, lossy description of a conversation it can no longer see.

When it fires

Compaction is opt-in and configurable, which means the defaults are worth knowing before a long run rather than after one.

beta header compact-2026-01-12 default trigger at 150,000 input tokens minimum 50,000 — you cannot set it arbitrarily low models Opus 5 · 4.8 · 4.7 · 4.6 · Sonnet 5 · 4.6 · Fable 5 / 5.1 · Mythos 5 / 5.1

That is a broad model list, so this is not an exotic edge case — but it is one provider's parameter rather than an industry-wide behaviour, and it is beta.

Two levers, and a trap in the first

Tell it what to keep. Custom instructions steer the summariser — for example, "Focus on preserving code snippets, variable names, and technical decisions."

The trap: custom instructions completely replace the default prompt — they do not supplement it. A helpful one-line instruction silently discards everything the default summariser was doing, which is a strictly worse summary than the one you were trying to improve.

Pin the recent messages. pause_after_compaction: true hands control back to you, so you can rebuild the message list as the compaction block plus whichever recent turns you want preserved word for word.

# summary + the last three turns, verbatim messages = [{"role": "assistant", "content": [compaction_block]}] + messages[-3:]

Two things that will surprise you later

Your token count is not your bill. Compaction runs an extra sampling pass, and the top-level input_tokens and output_tokens do not include it. To get what you were actually charged you have to sum across usage.iterations.

# the compaction pass is its own iteration iterations: [ { type: "compaction", input_tokens: 180000, output_tokens: 3500 }, { type: "message", input_tokens: 23000, output_tokens: 1000 }, ] top-level input_tokens says 23000

Thinking blocks do not cross the boundary. On Fable 5.1 and Mythos 5.1, thinking blocks from before a compaction block are not carried forward; re-inserting earlier turns afterwards means stripping thinking and redacted_thinking blocks, or setting the prefix-mismatch behaviour to drop them.

Related: the durable answer to all of this is not to depend on the window at all — give the agent a scratchpad it writes to and reads back, so the important things live somewhere a summariser cannot edit. What a context window really limits is the fact underneath this, and why 20 tool calls cost you 200 is the other thing a long conversation does to you.

Source: Claude Platform docs — Compaction (beta). Verified 2026-09-07.

One concept a week. Free.

The deeper, copy-paste version of each ToolCall short — in your inbox.

// total: 0.00 · spam: void · unsubscribe: one click