Skip to content

Context Compression (Rolling Summary)

The Rolling Summary automatically compresses older chat history once the context exceeds a configurable token threshold. This keeps conversations running smoothly even over very long sessions without any manual intervention.


Every new user input goes through the following check:

Total tokens > threshold?
└─ No → no action, original context is passed through
└─ Yes →
Existing summary + gap ≤ minRecent AND tokens(summary + gap + plaintext) ≤ threshold?
└─ Yes → REUSE — existing summary is reused, no LLM call
└─ No → COMPRESS — new LLM call, summary is created and stored in DB

Terminology:

TermMeaning
thresholdTokensTotal-token ceiling; compression only triggers above this value
minRecentNumber of most recent messages always kept as plaintext
GapMessages between the covers_until counter and the plaintext window
covers_untilCounter (not an ID): how many messages the current summary covers
ReuseExisting summary still fits — no new LLM call
CompressNew summary is generated and stored in the DB

The compressed summary is prepended to the LLM request as a synthetic user/assistant pair:

[User]: [Context Summary — compressed history of this conversation]
## Chat Summary … (structured text)
[Assistant]: [Context loaded]
[User]: <last minRecent messages as plaintext>

System messages and the actual agent prompts are not affected.

The summarizer produces a fixed outline. Empty sections are dropped.

SectionContent
### GuideTopic horizon, last completed, current task, next steps
### Main TopicsTopics of the compressed range
### Decisions & ResultsDurable decisions, each with a message number as source locator
### Open CommitmentsOutstanding promises, blockers, approvals granted or refused
### UncertaintiesOpen questions, unverified assumptions and rejected hypotheses
### Tool CallsOne line per call: [Tool: name(args) → result]
### OmittedDropped topic strands — as pointers, so they stay findable in the full history
### Current StateFree text on where things stand

Messages reach the summarizer numbered ([#12 User]) so decisions can cite their source.

Three sections are never overwritten: Decisions & Results, Open Commitments and Uncertainties are carried over unchanged from the previous summary and only added to. Everything else is weighted towards newer messages. Without that exception, precisely the content a summary exists for fades across repeated compressions.

The original messages remain intact. The summary replaces them only in the LLM’s context window, not in the database — every entry under ### Omitted therefore stays readable in the chat history.


Path: Administration → General → Summarizer

FieldDefaultDescription
Providerinstall defaultAI provider for the summarizer LLM call. Preset by the installer (same provider as the example agents); changeable in the AI Provider tab.
Modelinstall defaultModel within the chosen provider. Preset by the installer.
Token Threshold8,000Total tokens (chars ÷ 4) of all chat messages above which compression triggers.
Minimum Plaintext Window20Number of most recent messages always passed to the LLM as full text.

Important: Without a provider and model configured, compression remains inactive — a fresh install comes with both preset. Settings are stored globally for all users.


Model classContext windowRecommended thresholdRecommended plaintext window
Small cloud models (e.g. Haiku 4.5)200k tokens32,00020
Medium cloud models (e.g. Sonnet 4.6, GPT-5 mini)400k tokens64,00020
Large cloud models (e.g. GPT-5, Claude Opus)≥ 1M tokens128,00030
Local models (Ollama, llama.cpp)8k – 128k tokens4,000 – 16,00010

Token estimation uses chars ÷ 4. For more conservative behaviour, set the threshold slightly below the actual context limit.


When a real compression occurs (not a reuse), a line appears in the chain console:

rolling_summary: 56 compressed → summary, 5 plaintext
  • compressed: number of messages folded into the summary
  • plaintext: number of messages kept as full text

No entry is shown on reuse.


  • Provider compatibility: The summarizer call uses the same provider infrastructure as regular agent runs. All providers are supported (OpenAI, Anthropic, Google Gemini, xAI, local CLI providers).
  • Fault tolerance: If the summarizer call fails, the original context is passed through unchanged. The run is not blocked.
  • Data privacy: The summary is stored in the rolling_summary column of app.chats. When an account is deleted (DELETE /auth/me), chat data including the summary is removed completely.
  • Sub-agents: With agent-to-agent delegation, compression only applies in RunService.run(), not in the internal ChainRunner. This has no effect in normal operation.
  • Hard cap: Summaries are capped at 8,000 characters to keep overhead under control.