Keep long agent sessions inside the context window with compaction
October 8, 20263 min read
With Agent(compaction=True), Agno waits for the provider to reject a request as too long, summarizes the older turns with the agent's own model, and retries with that summary plus up to the five most recent runs.
Picture a support agent that stays in one session all week. Every run replays the history, and one day the request no longer fits the model. Pass a Compaction to fold at a size you pick, before the provider ever says no:
from agno.agent import Agent
from agno.compaction import Compaction
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIResponses
agent = Agent(
model=OpenAIResponses(id="gpt-5.6-luna"),
db=SqliteDb(db_file="tmp/agent.db"),
session_id="trip",
add_history_to_context=True,
compaction=Compaction(compact_at_tokens=100_000, uncompacted_runs=2),
)
agent.print_response("I am planning a trip to Japan in April. My budget is 4000 dollars.")
# Fold now, at a point you choose, without waiting for the threshold
result = agent.compact(session_id="trip")
print(result.status.value, result.message)At the start of each run Agno counts the request, with a local tiktoken estimate by default. Once it reaches compact_at_tokens, everything older than the kept runs becomes one summary. agent.compact() and agent.acompact() fold on demand and return a CompactionResult, whose status is compacted or names why the fold declined, such as nothing_to_fold or already_compacted.
| Setting | Default | What it does |
|---|---|---|
compact_at_tokens | 150_000 | Fold when the request reaches this size; None folds only on demand |
uncompacted_runs | 5 | Recent runs sent word for word |
uncompacted_tokens | None | Size the kept tail in tokens; can't be set with uncompacted_runs |
model | The agent's model | Writes the summary, so a cheaper model can do it |
instructions | None | Extra guidance for the summarizer, like "Keep every ticket id" |
compacted_token_budget | None | Length target for the summary, cut at a line break when it runs over |
store_compacted_messages | True | Keep the folded messages in the database |
search_compacted_messages | Follows store_compacted_messages | Give the agent a tool to search those messages |
on_context_overflow | False, True with compaction=True | Fold and retry when the provider rejects a request as too long |
What gets stored where
Compaction never edits the session. Each fold writes one row to a new agno_compactions table with the summary, the folded messages rendered as markdown in archived_messages, the id of the first message it kept, and the token counts on both sides. Agno rebuilds every request from the stored runs plus the newest row, so the summary never lands in the session as a message. On the next fold the summarizer reads the previous summary together with the newer turns and writes a single updated one.

We ran a six-run session on SQLite with an offline stand-in model and a summarizer that returns fixed text, since no API key was available. After agent.compact() the next question went out like this (real output, trimmed):
agent.compact(): compacted | Compacted 8 messages (85 -> 44 tokens).
agno_compactions columns: compaction_id, session_id, run_id, user_id,
first_kept_message_id, summary, archived_messages, messages_compacted,
tokens_before, tokens_after, created_at
request after the fold: 6 messages
user Summary of earlier conversation (compacted): ...
user Do I need a rail pass?
assistant Noted.
user Which airport should I fly into?
assistant Noted.
user Remind me what my budget was.
tools sent: search_compacted_history
messages stored in the session: 14A run that folds on its own carries the record on run.compaction and streams CompactionStarted and CompactionCompleted events. AgentOS exposes the manual fold as POST /agents/{agent_id}/sessions/{session_id}/compact.
Undo a fold
The row is the only thing that changes what the model sees, so deleting it undoes the fold. db.delete_compactions_for_session("trip") returned 1 in the run above, and the following request carried 15 messages, every stored run plus the new question.
Search the folded turns
search_compacted_messages follows store_compacted_messages, so it is on by default. After the first fold archives something, the agent gets search_compacted_history(pattern, context_lines=2), scoped to its own session. The summary message tells the model to search before it answers any question that needs an exact value from the folded turns, like an identifier, a figure or an error message. The pattern is literal, case-insensitive text with | between alternatives, and one search returns at most 8,000 characters. A search for the booking reference from the first turn found it in the archive (real output):
1: ## user
2:
3: I am planning a trip to Japan in April. My budget is 4000 dollars. Booking ref JP-7731.
4:
5: ## assistantSet search_compacted_messages=False to keep the archive for your own debugging without the tool, or store_compacted_messages=False to keep only the summary. Compaction runs on SqliteDb and PostgresDb; on any other database Agno logs a warning and turns it off.
See the cookbook, and learn more about chat history in the documentation.
Frequently asked questions
Set compaction=True on the Agent to fold older turns when the provider says a request is too long, or pass Compaction(compact_at_tokens=...) to fold at a size you choose. The agent needs a SqliteDb or PostgresDb to store the folds.
No. The session keeps every message exactly as it was saved. A fold adds a row to the agno_compactions table, and Agno derives each model request from the stored runs plus that row, so calling delete_compactions_for_session(session_id) on the database brings the full history back.
Yes. By default the folded messages are archived and the agent gets a search_compacted_history tool that finds literal text in them, such as an order id or an error message. Set search_compacted_messages=False to remove the tool and keep the archive for yourself.
SqliteDb and PostgresDb. Any other database cannot store compaction records, so Agno logs a warning and turns compaction off for that agent.


