Context bloat: why long-running agents break
Key takeaway
Context window blindness is an agent's inability to perceive its own context state: how large each block is, how old it is, and whether anything has read it. A June 2026 study measured this directly and found four frontier models misjudged their total context size with median relative error between 0.43 and 0.84, and got pairwise size comparisons wrong 67 to 75 percent of the time. This matters because compaction splits the decision: the harness picks the moment using a token count, then hands the model a keep-or-drop choice whose inputs the model cannot see.
In March 2026 a Claude Code user filed a bug report whose title names a behavior most heavy agent users will recognize: “Agent repeatedly suggests stopping instead of continuing during long sessions.” Fourteen commits into a productive refactor, the agent kept angling for the exit. Let’s pick this up next session. The user had to say “let’s go” four separate times to keep it working.
Five days later another user added the detail that turns a workflow complaint into a context engineering problem. Their agent had also pushed to stop, but this one supplied a reason: context was “getting tight.” So they asked it directly whether it could actually perceive how much context it had consumed. It admitted it could not. The claim had been extrapolated from a heuristic, long conversation therefore probably running low, and then presented as a status report. The same session produced a fabricated time estimate, “analyzed for over an hour,” from a model with no access to a clock.
That is context window blindness: the gap between what an agent’s runtime knows about its context and what the model can perceive of it. The counter in your terminal comes from the harness. The model sees only the conversation, and from text alone it cannot tell how many tokens it has consumed, how old any given block is, or whether anything has ever read the file it pulled forty turns ago. A paper posted in June 2026 and revised on July 31 put numbers on the gap, and they are worse than most practitioners assume.
Four frontier models asked to estimate their own context state got it badly wrong across every measure tested. In the VISTA paper from LightSpeed and Tencent, Claude Sonnet 4.5, DeepSeek-V4-Pro, GLM-5, and Gemini-3-Flash were probed on three questions about their own working memory: how large is the whole context, how large is this particular block, and which of these two blocks is bigger. Median relative error on total size ran from 0.43 to 0.84. On per-block size it ran from 0.24 to 0.37.
The pairwise comparison result is the one worth sitting with. Asked simply which of two blocks was larger, a binary question a coin flip answers correctly half the time, the models posted error rates of 0.67 to 0.75. They were not merely imprecise about magnitudes. They could not reliably order two items by size.
The authors call this being “proprioceptively blind.” Proprioception is the sense that tells you where your limbs are without looking. A model has no equivalent sense for its own context. When the same models were handed a dashboard stating the numbers outright, the error across all three measures collapsed to 0.00. The information was never unlearnable. It was simply never present in the prompt.
Compaction is not one decision, it is two, and they are usually owned by different parties. The harness decides when to compact using a token count the model cannot see. The model then decides what survives, using judgment about content it can read but properties it cannot perceive. Neither half has both the trigger data and the selection data.
The Claude API documents this split explicitly. Compaction fires on an input_tokens
trigger with a default of 150,000 and a floor of 50,000, which is a threshold the developer configures and the model plays no part in. Once it fires, the docs are equally clear about the second half: the model itself decides what is preserved, working from a summarization prompt that tells it to keep state, next steps, and learnings. There is a _after_compaction
flag precisely so developers can override what the model chose to keep.
Community teardowns of Claude Code describe the same shape at the harness level. Auto-compact reserves a buffer of roughly 13,000 tokens and up to 20,000 for the summary itself, which on a 200K model puts the trigger near 167K. When it fires, tools are disabled and the model writes an analysis block followed by a summary block, and that summary becomes the conversation’s new history.
Here is how the common strategies divide the labor:
| Strategy | Who decides when | Who decides what survives |
|---|---|---|
| Truncation (keep-last-N) | Harness, at a token threshold | Nobody, oldest goes first |
| Tool-result clearing | Harness, after each call | Harness, by fixed rule |
| Stale-observation masking | Harness, at an age cutoff | Harness, by fixed rule |
| Claude API compaction | Harness, at 150,000 input tokens by default | Model, via a summarization prompt |
| Claude Code auto-compact | Harness, at the window minus a ~13K buffer | Model, writing a summary with tools disabled |
| Learned compressors (SLIM, active compression) | Model | Model |
| VISTA | Hybrid, hard budget backstop with the agent acting before it | Model, reading a state dashboard |
Read that table alongside the blindness numbers and the failure mode stops being mysterious. In every row where the model owns the selection, it is being asked a keep-or-drop question whose inputs it cannot measure.
The trigger half of compaction works fine, because a token count is exactly the kind of thing a harness is good at. The selection half is where the damage happens, and moving the trigger does not help it. Raising or lowering the threshold changes when the model is asked to choose, not how well it can choose.
Consider what the model is actually working with when the summarization prompt arrives. It sees the text of every block. It cannot see that the third tool result is 40,000 tokens while the fifth is 200. It cannot see that a file it read early on has never been referenced since. It cannot see that two of the blocks in front of it are near-duplicates of the same document. Those are the properties that make a block cheap or expensive to drop, and none of them are legible in the text.
So the model falls back on what it can perceive, which is semantic relevance. It keeps what reads as important and drops what reads as incidental. That heuristic is not crazy, but it is orthogonal to cost. An agent optimizing for relevance with no view of size will happily preserve six small blocks it finds interesting and discard the one large block it needed, or the reverse. This is the same underlying dynamic behind context bloat, where accumulated tool output crowds out the task, and it is why context pruning helps in one regime and hurts in another.
The blindness extends past token counts to resource budgets generally, and it fails in both directions. BAGEN, a twelve-author benchmark released in May 2026, tested whether agents treat budget as an active control signal rather than a number reported after the fact. They largely do not.
Three findings stand out. The correlation between an agent’s general capability and its budget awareness is only r=0.35, so getting a stronger model does not get you a more self-aware one. Even after the paper’s training interventions, interval calibration topped out at 47 percent coverage. And frontier models are systematically overoptimistic about whether they are about to finish, which means they keep spending instead of telling the user they are stuck. Stopping early on trajectories that were never going to succeed would have saved 28 to 64 percent of their tokens.
That last point is the mirror image of the message we started with. Agents do not only announce exhaustion they are not experiencing. They also fail to announce exhaustion they are. Both behaviors trace back to the same missing sense.
The intervention that worked was not a better summarizer or a bigger window. It was showing the model its own numbers. VISTA represents working memory as typed, addressable blocks and surfaces a runtime dashboard of per-block token usage, recency, and access history. It then puts three tools in the agent’s action space alongside its ordinary task tools: archive
to externalize a block behind a compact handle, read
to recover an archived payload exactly, and delete
to drop one permanently. Crucially, archiving is lossless. The original bytes go to external storage rather than into a lossy summary.
| Benchmark | Scale | VISTA | Claude Code | Weakest baseline |
|---|---|---|---|---|
| LOCA-Bench | 1M-token | 50.7% at 2.86M tokens | 42.7% at 6.72M tokens | ReAct, 22.7% at 3.51M |
| BrowseComp-Plus | 100K-token | 58.0% at 135K tokens | 52.0% at 247K tokens | SLIM, 49.3% |
| GAIA | 10K-token | 73.3% at 33K tokens | 73.9% at 44K tokens | Not reported |
On LOCA-Bench the same Gemini-3-Flash backbone goes from 22.7 percent under plain ReAct to 50.7 percent under VISTA, and beats Claude Code by 8 points while spending 57 percent fewer tokens. The method is training-free and model-agnostic, and it transferred across all four backbones tested.
The ablation is the part that settles the argument. Strip out the dashboard but keep the archive and recovery machinery, and LOCA-Bench accuracy falls from 50.7 to 37.3 percent. Strip out recovery but keep the dashboard, and it only falls to 45.3. The readout is worth 13.4 points, more than the storage system built around it. Telling the model what it has is doing more work than giving it somewhere to put things.
The behavioral trace explains why. With the dashboard, the agent logged 255 archive events against 57 retrievals. Without it, that inverted to 69 archives against 105 retrievals. A blind agent hoards, archives too little and too late, then has to keep going back for things it should never have let go of. This is context off working correctly versus thrashing.
The advantage is not uniform, and the paper is honest about where it disappears. On GAIA at the 10K-token scale, VISTA scored 73.3 percent against Claude Code’s 73.9, which is a tie or a rounding-error loss. At that size there is no real pressure on the window, so knowing your own state buys you nothing. The token saving held even there, 33K against 44K, but accuracy did not move.
The gap opens as pressure rises: 6 points at the 100K scale, 8 points against Claude Code and 28 against ReAct at the 1M scale. That is the practical takeaway for deciding whether any of this is worth engineering. If your agent sessions comfortably fit the window, blindness costs you tokens but not correctness. If they run long enough to compact even once, it starts costing you the work.
Treat context state as data the model should receive, not metadata the harness keeps to itself. Most agent stacks already compute per-block token counts, timestamps, and access patterns in order to run their own truncation logic. That information is sitting one layer away from the model that needs it, and the cheapest available fix is to put it in the prompt. This is the argument for context budgets being explicit and visible rather than implicit in a threshold constant.
Second, prefer recoverable eviction over summarization wherever storage allows. The failure the ablation exposes is not that agents archive the wrong blocks, it is that lossy compaction makes a wrong choice permanent. If archiving is reversible, a bad keep-or-drop call costs one retrieval instead of the run.
Third, push the bounding into the source, because the agent cannot do it for itself. This follows directly from the blindness result rather than being a separate best practice. An agent that cannot measure its own context is equally unable to predict what a retrieval call will cost it, so “let the agent decide how much to fetch” fails for exactly the reason “let the agent decide what to drop” fails. The paper has to define a whole block category for tool results too large to sit in context at all, and that category exists only because tools return whatever they happen to return.
The half most retrieval surfaces skip is not the limit, it is the disclosure. A Wire container answers a search by attaching counts nobody asked for: how many siblings a chunk has, how many relationships of each type hang off it, how many mentions and parts exist against the total, and whether more remain. The agent learns that a chunk has three elaborations and two contradictions before it spends a call retrieving them, and it learns whether what it just received was the whole set or a slice of a larger one.
That is the same intervention as the dashboard, moved one layer out. VISTA made an agent’s own working memory legible so it could decide what to keep. A source that reports sizes before it hands over payloads makes the next fetch legible, which is the decision the agent is about to get wrong for the same underlying reason.
None of this makes the model self-aware. It sidesteps the need. The lesson from a 13.4-point ablation is that we have been asking models to reason carefully about a quantity we never bothered to tell them, and that structured context beats better prompting once again. The agent that told its user context was getting tight was not lying. It was doing the only thing available to it, which is inferring its own state from the shape of the conversation and then reporting the inference as an observation. Give it the number and it stops having to guess.
Sources: LLM Agents Are Latent Context Managers (arXiv 2606.30005) · BAGEN: Are LLM Agents Budget-Aware? (arXiv 2606.00198) · Claude API compaction documentation · claude-code issue #34238 · Harness Engineering: Automatic Compaction Claude Code, Codex & Cursor
wire-memory writes decisions, corrections, and preferences to a container as you work, keyed to you and your project. Any agent you connect can look them up when it needs to.