Skip to content
Malik Hamza Shabbir
Agents in Productionagentscontext engineeringcompactionreliability

Context Rot Is Killing Your Long-Running Agent: A Compaction Playbook That Survives 100k+ Tokens

HSMalik Hamza ShabbirUpdated 9 min read

In short

Context rot means your agent gets less accurate as its context grows, long before it hits the window limit. The fix is context engineering, not a bigger model: compact on triggers rather than reactively, summarize iteratively against a fixed anchor, give the model awareness of its own context budget, and push durable state into external memory. This playbook is what keeps my production agents reliable past 100k tokens.

Context Rot Is Killing Your Long-Running Agent: A Compaction Playbook That Survives 100k+ Tokens
On this page

Your long-running agent is not failing because it ran out of tokens. It is failing because its accuracy quietly degrades as the context grows, an effect now widely called context rot. The 2026 Chroma study across 18 models showed the same pattern everywhere: as you pack more into the context, the model gets worse at using any single part of it, even when the window is nowhere near full. The fix is not a bigger model or a longer window. It is context engineering: deciding what stays in the live context, when to compact it, and what to push out to external memory. This is the playbook I use to keep agents reliable past 100k tokens.

What is context rot, and why does it kill long-running agents?

Context rot is the measurable drop in a model's accuracy as the amount of context you give it grows, independent of how much room is left in the window. The longer your agent runs, the more tool outputs, intermediate reasoning, and conversation history it accumulates, and the worse it gets at attending to the parts that matter.

Two failure modes stack on top of each other in a long-running agent:

  • Lost-in-the-middle. Models attend strongly to the beginning and end of their context and weakly to the middle. A critical instruction buried at turn 30 of an 80-turn trajectory effectively disappears.

  • Distractor accumulation. Every tool call dumps more text in. Old, stale, or near-duplicate content competes for attention with the few tokens that actually drive the next decision.


The dangerous part is that none of this throws an error. The agent keeps running. It just starts ignoring constraints, re-doing work it already did, or confidently citing a stale tool result. By the time you notice, the trajectory is 60k tokens deep and unrecoverable. If you are scoring agents in CI, this is exactly the kind of slow drift that only shows up when you grade the whole trajectory and not just the final answer .

Does a bigger context window fix context rot?

No. A bigger window buys you more turns before collapse, but it does not change the curve. The accuracy drop scales with how much you actually put in the context, not with how much capacity remains.

I have watched teams treat a 200k or 1M token window as a license to never prune anything. That is the trap. You hit the same degradation at 120k that you would have hit at 60k with a smaller model, just later and with a larger bill. The window size sets your ceiling. Context engineering sets how close to the ceiling you can run before quality falls apart.

The mental model I keep: treat the context window like working memory, not a hard drive. Working memory is for what you need right now. Everything durable belongs somewhere else and gets pulled back in on demand.

Trigger-based vs reactive compaction: which should I use?

Use trigger-based compaction. Reactive compaction, where you only summarize once you are about to overflow the window, means the model spends its final and most important turns operating inside an already-degraded context. That is the worst possible moment to compact.

Trigger-based compaction fires on an explicit condition before quality degrades, so the agent never works in a rotted window. Here is the difference laid out:







The triggers I actually use, in order of preference:

  1. Token budget threshold. Compact when live context crosses, say, 50% of the window. Cheap to compute, easy to reason about.

  2. Task-boundary trigger. Compact when a sub-task completes. A finished sub-task is a natural seam: collapse its scratch work into one or two lines of outcome and keep going.

  3. Tool-output size trigger. When a single tool returns something huge (a full file, a long API payload), summarize or store it immediately rather than letting it sit raw in context.


PYTHON
def should_compact(state) -> bool:
    over_budget = state.live_tokens > 0.5 * state.window_size
    subtask_done = state.last_event == "subtask_complete"
    huge_tool_output = state.last_tool_tokens > 8_000
    return over_budget or subtask_done or huge_tool_output

The provider-native compaction APIs that shipped in Q1 2026 make the budget trigger easier, because the runtime can collapse older turns for you. I still keep my own task-boundary trigger on top of them, because the provider does not know where my sub-tasks begin and end. The provider optimizes for the window. I optimize for the task.

How do I compact without losing the original goal?

Use anchored iterative summarization. You keep a small, fixed anchor block that never gets summarized, holding the original goal and the hard constraints, and you summarize everything else in rolling passes. This is the single highest-leverage technique in this playbook.

The problem with naive summarization is drift. Summarize a summary three times and the model slowly forgets why it started. Each pass compresses away a little intent until the agent is solving a subtly different problem. Anchoring fixes this by separating the immutable parts of the context from the compressible parts.

I structure the live context in three zones:

TEXT
[ ANCHOR ]   immutable: goal, hard constraints, output contract, key IDs
[ SUMMARY ]  rolling: compressed history of completed work + decisions
[ ACTIVE ]   recent: last N turns + most recent tool outputs, verbatim

The anchor is written once, ideally by the orchestrator, not regenerated by the model. The summary zone is the only thing compaction rewrites. The active zone is always raw and recent so the model has full fidelity on what it is doing right now.

A compaction prompt that holds up in production looks roughly like this:

TEXT
You are compacting an agent's working context. 
Do NOT touch or restate the ANCHOR; it is preserved separately.

Rewrite the SUMMARY so it captures, in under 400 tokens:
- Decisions made and WHY (not just what)
- Facts discovered that future steps depend on (IDs, paths, values)
- Dead ends already tried, so they are not repeated
- Open questions still unresolved

Drop: raw tool dumps, exploratory reasoning, anything superseded.
Preserve exact identifiers verbatim. Never invent state.

Two rules I never break. First, preserve identifiers verbatim. Summaries love to paraphrase a file path or an order ID into uselessness. Second, summarize decisions and reasons, not just outcomes, because the next step often needs to know why a path was rejected so it does not wander back into it.

How does context-awareness feedback after each tool call help?

Give the model a short status line after each tool call telling it how much context budget it has left and what to do as it gets tight. An agent that knows it is running low on healthy context will naturally start wrapping up, delegating, or writing state out, instead of blindly accumulating.

The model has no innate sense of its own context pressure. It does not feel the window filling. So I feed it that signal explicitly as a small system note appended after each tool result:

TEXT
[context status] live: 41k / 200k tokens (~20%). Budget healthy.
You may continue exploring.

And when it crosses a threshold:

TEXT
[context status] live: 108k / 200k tokens (~54%). Budget tight.
Wrap up the current sub-task, persist any durable findings to memory,
and prepare for compaction. Avoid starting new wide searches.

This nudge changes behavior. The agent stops launching broad three-tool fan-outs late in a trajectory and starts consolidating. It is the same instinct a senior engineer has near the end of a long debugging session: stop opening new threads, write down what you know, narrow the scope. Pairing this with a hard trigger means the model cooperates with compaction instead of being surprised by it.

When should I delegate to external memory instead of compacting?

Delegate to external memory whenever a fact needs to survive longer than the current sub-task or be shared across agents. Compaction shrinks the live context; external memory removes the obligation to carry that state inline at all. They solve different problems and you want both.

The division of labor I use:






DimensionReactive (overflow-driven)Trigger-based (proactive)
When it firesAt ~95% window fillAt a budget threshold or task boundary
Context quality at compactionAlready degradedStill healthy
PredictabilityErratic, depends on tool verbosityDeterministic, you control it
Risk of losing key factsHigh, summarizing under pressureLow, summarizing with headroom
Cost behaviorSpiky, large one-shot summariesSmooth, smaller rolling summaries
Keep in live contextPush to external memory
Current goal and constraintsDurable facts and user preferences
Last few turns, verbatimLarge documents and full tool payloads
The active rolling summaryHistory older than the current sub-task
Identifiers needed right nowAnything another agent might need later

Concretely: when a tool returns a 12k-token document, I do not keep it in context. I write it to a store, keep a one-line pointer plus the few extracted facts I need, and retrieve the full text again only if a later step requires it. The agent operates on a compact index of what it knows and pulls detail on demand. That is retrieval, applied to the agent's own working state rather than to a static corpus.

This is also where memory framework choice matters, because retrieval latency and recall accuracy become part of your agent loop. I went deep on the tradeoffs in my benchmark of Mem0, Letta, Zep, and LangMem , and the headline is that the store you pick directly affects how aggressively you can compact without losing fidelity. A good external memory layer lets you run the live context lean, which is the whole point.

One caution that ties back to security: anything you write to external memory and later retrieve is untrusted input the next time it enters context. If an agent can read external content and also act, you have to treat retrieved memory as a possible injection vector, which is the lethal trifecta problem in a different outfit. Compaction and memory are reliability tools, but they widen the surface you have to defend.

What does the full compaction loop look like end to end?

The complete loop is: run the step, check triggers, compact the summary zone against the fixed anchor if a trigger fires, persist durable state to external memory, feed back the context status, and continue. Wired together it looks like this:

PYTHON
def agent_step(state):
    result = run_next_action(state)          # model + tool call
    state.record(result)

    if should_compact(state):
        durable = extract_durable_facts(result, state)
        memory.upsert(durable)               # push state out
        state.summary = compact_summary(     # anchored, iterative
            anchor=state.anchor,             # never rewritten
            prior_summary=state.summary,
            active=state.active_turns,
        )
        state.active_turns = state.active_turns[-RECENT_N:]

    state.append_status_note(context_budget(state))  # feedback
    return state

A few hard-won notes on running this in production. Keep RECENT_N generous; cutting the active zone too aggressively starves the model of the fidelity it needs for the immediate next move. Log every compaction with before-and-after token counts and a hash of the anchor, so when an agent goes off the rails you can replay exactly what it could see. And test compaction explicitly in your evals by running trajectories long enough to trigger it, because a compaction step that silently drops a key identifier is the kind of bug that only surfaces at turn 40.

If you are designing or rescuing a long-running agent and this is the layer that keeps biting you, this is exactly the work I do under AI agents and automation . Most reliability problems I get called in for are not model problems. They are context problems wearing a model problem's clothes.

The short version

Context rot is real, it is measured across every major model, and it gets your agent long before the window does. You beat it by treating context as working memory: anchor the goal so summarization cannot drift, compact on triggers instead of waiting for overflow, tell the model how much budget it has so it cooperates, and offload durable state to external memory so the live context stays lean. Do those four things and an agent that used to collapse at turn 30 will run clean past 100k tokens.

If you are wrestling with an agent that degrades the longer it runs and want a second set of eyes, my contact page is the fastest way to reach me. I would rather help you fix the context layer than watch another agent quietly rot.

FAQ

What is context rot in an AI agent?

Context rot is the measurable drop in model accuracy as the input context grows, so a long-running agent gets less reliable well before it ever fills the context window.

Is a bigger context window the fix for context rot?

No, a larger window only delays the problem, because the lost-in-the-middle accuracy drop scales with how much you put in the context, not with how much room is left.

When should an agent compact its context?

Compact on explicit triggers like a token-budget threshold or a completed sub-task, not reactively at the last moment, so the model never operates inside a degraded window.

What is anchored iterative summarization?

It is summarizing the conversation in rolling passes while keeping a fixed anchor of the original goal and hard constraints, so repeated compaction never drifts away from the task.

How does external memory help fight context rot?

External memory lets the agent store durable facts and retrieve only what each step needs, keeping the live context small instead of carrying the entire history inline.

Working on something like this?

I build web apps, AI features, and mobile products for clients. If this article matches a problem you have, tell me about it.

Start a conversation
HS

Malik Hamza Shabbir · Full-Stack & AI Engineer

I build full-stack and AI products solo: a reputation SaaS in production, RAG pipelines, and React Native apps. I write from what I ship, not from documentation summaries.

Related articles