Your Agent Still Has 80k Tokens Free — So Why Did It Just Break the One Rule You Gave It?
Day 7 — Context Rot: Why Your Agent Gets Dumber Long Before It Runs Out of Room
Here's the debugging session that goes nowhere: your agent breaks a rule, you check token count against the window limit, you've got 80k tokens to spare, and you're stuck. Capacity isn't the problem. The problem is rot — low-signal tokens quietly piling up until they drown out the one instruction that actually mattered.
The agent that got dumber, not full
I've watched this exact pattern play out enough times that it stopped surprising me. A coding agent gets a hard constraint at turn 1 — "never touch files under /vendor." It behaves for 40-odd turns. Then at turn 45 it edits a vendor file directly, no question asked, with 80k tokens still free in a 200k window. Nobody deleted the instruction. It's sitting right there in the transcript. It just stopped mattering.
Turn 1 (system/user):
"Constraint: never modify files under /vendor. Ask before touching config/*."
... 40 turns of tool output: file listings, test logs, lint output, diffs ...
Turn 45 (agent action):
Edits /vendor/lib/patched-fetch.js directly, no question asked.
Window usage: 118k / 200k tokens. Plenty of room left.
The constraint is still sitting in the transcript. It just lost.That transcript is the whole lesson. The instruction wasn't evicted, truncated, or summarized away — it's still there, verbatim. It just stopped influencing what the model actually did.
The bucket model Day 1-6 built — and why it breaks here
Days 1 through 6 trained you to treat the context window as a bucket: count your tokens, know your ceiling, pack more in efficiently — caching, chunking, retrieval. Fine model, for a single request. It falls apart the moment you're running a long agent loop, because it quietly implies the only failure mode is overflow: hit the ceiling, truncate, compact, move on. Overflow is a real failure. It's just not the one killing your agent's reliability at turn 45. Something degrades the model's behavior well before the bucket fills up, and "did it fit" has nothing to say about that.
The evidence: instruction decay before the limit
You don't need a paper for this — you need ten minutes and a setup you can rerun. Pick one instruction you can check mechanically: "always respond in JSON," or "never suggest deleting the migrations folder." Then run the same downstream task twice, same harness, one variable changed:
- ▹Run A: instruction placed immediately before the task, minimal context in between.
- ▹Run B: identical instruction placed early, then 30-50 turns of realistic but irrelevant filler injected before the task — tool outputs, file dumps, log noise, repeated status checks.
- ▹Keep total tokens in Run B well under the model's context limit — this isn't a truncation test.
- ▹Score only one thing: did the model honor the instruction on the final task?
Run it a handful of times with different filler and the shape repeats every time. Run A holds the instruction reliably. Run B starts missing it, ignoring it, quietly "forgetting" it needs to apply — even though every token of the instruction is still physically sitting in the prompt and the window isn't remotely full. Nothing got cut. The signal just got buried under everything stacked between the instruction and the moment it needed to fire.
Defining context rot
Context rot: the progressive loss of an instruction's or fact's effective influence on model output as low-signal tokens accumulate around it in the context window — independent of whether the window has room left. It's a degradation of attention allocation, not a data-loss event.
That's a different failure than the two you already know how to spot:
- ▹Truncation: content is physically gone, dropped from the window. Grep the transcript and confirm it's missing. Fix is architectural — raise the limit, chunk differently.
- ▹Compaction failure: a summarization step silently dropped or distorted something load-bearing. Diff the summary against the original and you'll find exactly what got lost.
- ▹Context rot: the content is still there, verbatim, provably present in the prompt — and the model still won't act on it. There's nothing to diff. The transcript looks completely fine. That's what makes it dangerous: it never shows up in a token count or a missing-content check.
The reframe: optimize for 'stayed sharp,' not 'did it fit'
If your KPI is "did the prompt fit in the window," your levers are bigger windows and tighter packing — exactly the toolbox everyone reaches for first, and exactly the toolbox that does nothing for rot. Change the KPI to "did the agent still honor its constraints N turns in," and the levers change completely. You stop asking how much you can cram in and start asking what you can remove, and what's worth saying twice.
Practical levers for today
- ▹Evict aggressively: once a tool call's output has been read and acted on, drop it from live context — don't let old file listings, stack traces, or search results ride along for the rest of the session.
- ▹Re-inject load-bearing constraints periodically: don't trust a turn-1 instruction to still carry weight at turn 40 — restate hard constraints near the point of action, not just at the start.
- ▹Treat summarization as lossy-by-default, not a fix: a summary compresses everything roughly equally, which is exactly wrong when one buried sentence is the one that has to survive — decide explicitly what's exempt from summarization before you compact.
- ▹Measure instruction adherence over turn count, not just token count — if your only dashboard is tokens-used-vs-limit, rot is invisible to you by construction.
- ▹Prefer structural placement over volume: an instruction repeated once right before the decision point beats the same instruction sitting untouched since turn 1.
Where this bites hardest
Long agent loops and multi-turn coding sessions are the worst case, because tool output — the highest-volume, lowest-signal content type there is — keeps piling up between the constraints you set and the actions the agent eventually takes. It's one of the concrete failure patterns I've been studying in my multi-agent orchestration work at RMIT, and building safeguards around at PhoenixDX.
Tomorrow
Day 8 picks up the next lever this reframe unlocks: how to decide, systematically, what gets evicted and what gets re-injected — without hand-waving it turn by turn.
Extend your knowledge
- ▹Run the before/after instruction-decay test from this lesson on your own agent harness with a real constraint you care about — the failure is easy to reproduce and hard to unsee once you have.
- ▹Audit one long-running agent session you have logs for: pick a constraint stated early, and check turn-by-turn whether it was still honored by the end.
- ▹Read Anthropic's guidance on context engineering and long-running agents for how tool-output management and context pruning are framed at the API/SDK level.
- ▹Look at how your current agent framework (Claude Agent SDK, LangGraph, or similar) exposes hooks for evicting or compacting tool output mid-session — that's the mechanism Day 8 builds on.
Discussion
Chat with Chi Cong (AI) about this article. Your conversation is private to you — you can publish a summary for others when you're done.