Skip to main content

How it works

A compaction is one summary request. The model reads the conversation as it stands and writes a summary that lets it carry on from the same point. From then on, the summary stands in for the turns it covers. The summary request is billed like any other request, on the model you asked for. It reuses the conversation’s system prompt and tools, so on models that cache input most of it is read from cache. Pick the shape that matches the API you call:

OpenAI Responses

Compact on demand

Send the conversation to POST /v1/responses/compact, either as input items or as a stored chain with previous_response_id. Pass the same instructions and tools you use for the rest of the conversation.
The reply has one compaction item:
Put the item in your next input, followed by the next turn. You can keep the older items or drop them: the newest compaction item stands in for everything before it, so they are not sent again. encrypted_content opens only for the API key that made it.

Compact at a threshold

Add context_management to an ordinary /v1/responses request:
When the input reaches compact_threshold tokens (default 200,000, and never later than 90% of the model’s window), we summarize the conversation first and the model answers from the summary. The reply’s output then starts with the compaction item; when streaming, it arrives as output item 0 before the answer. Append the output to your next request as usual. With previous_response_id, send only the new turn.

Anthropic Messages

Compact on demand

Send the conversation with compaction:
The reply is one compaction block with stop_reason: "compaction". Its usage is reported in usage.iterations; the top-level input_tokens and output_tokens are zero. Streamed, the whole block arrives in one content_block_start. Add instructions to replace the summary prompt. Send the block back exactly as it came, first in messages, in place of the turns it summarizes.

Compact at a threshold

Add the compaction edit to context_management:
The trigger counts input tokens: 150K by default, and at least 50K. When it fires, the reply’s content starts with a compaction block and then the answer, and usage.iterations lists the summary (compaction) and the answer (message). With "pause_after_compaction": true the reply is the block alone, with stop_reason: "compaction". Append the reply’s full content to your messages, as you would any reply. A compaction block stands in for everything before it, wherever it sits. clear_tool_uses_20250919 and clear_thinking_20251015 work as documented by Anthropic: cleared tool results become a short placeholder, the calls stay, and context_management.applied_edits reports what was cleared.

Chat Completions

Chat Completions has no compaction standard. Add one header to let us manage it:
Past the line, we summarize the older part of the chat and keep the newest turns word for word. Keep sending your full history every turn. We remember the summary for the conversation, so later turns reuse it and keep the prompt cache warm, and we write a new one only when the chat grows past the line again. The reply header x-sideren-compacted says how many of your messages the summary stood in for, and usage counts what was actually sent.
Without the header we change nothing. x-sideren-context: full keeps the full context.

Coding agents

Codex, Claude Code, OpenCode, Kilo Code, the Sideren CLI and others compact on their own, with their own summary request. We recognize those requests and give them priority: a compaction stays on its model and on the route that already holds the conversation’s cache, and it is never pushed aside when that route is busy. If an agent’s summary request is bigger than the model’s window, or bigger than your plan’s input cap, we shrink it to fit (the oldest tool output goes first) instead of refusing it, so the session can always compact its way out. On a plan with an input cap, GET /v1/models with your key shows that cap as each model’s context_window, so agents that size themselves from it compact before the cap. The model’s full window stays in sideren.max_context_window.