Auto-Compaction vs a Handoff File in a Long AI Agent Session

Two 200-token files carry one session forward. Next session they are 5,000 tokens apart. The gap is one verdict line.

Auto-Compaction vs a Handoff File in a Long AI Agent Session

There’s a tell, late in a long session, when the agent stops writing the careful version. It collapses three steps into one. It skips the test it said it would write. It calls the task “essentially complete” and offers a commit that papers over a TODO. Nothing failed. The agent just downshifted, because it can see its own context window filling, and it is now optimizing for finishing over finishing well.

Two earlier pieces on this site handle the front of the window. Deterministic context primes the files you already know matter, and cache the explore writes down where things are so the next run doesn’t pay for the search twice. Neither helps at the moment the tell appears. The window is two-thirds full, the work is half done, and something has to be thrown overboard right now. What happens at that seam is this piece’s whole subject.

The default answer is auto-compaction: the tool summarizes the conversation, drops the raw history, and carries on. The alternative is a handoff file: a short file you write yourself, read once before it carries forward, and hand to a fresh session. Here is the claim up front, and the rest of the piece re-derives it: those two artifacts can be exactly the same size, 200 tokens each, and still differ by 5,000 tokens of pure rework in the very next session. Size was never the variable that mattered. The presence of one explicit “do not reinvestigate” verdict was.

That is the tension in one line. The context that made the agent good at your problem - the hypotheses it ruled out, the approach it abandoned, the full record of what was tried - is the exact same material that will sink the next session if nobody edits it before it carries forward. A summarizer optimizing for faithfulness cannot tell the difference between the two. Everything below is aimed at one villain: carry-forward that nobody edited.

Check your own last compacted session first

Section titled “Check your own last compacted session first”

Before any arithmetic, thirty seconds on your own history settles whether this piece is for you.

Open the transcript of your last session that ran long enough to auto-compact. Find the summary the tool wrote when it cut; most agents print it at the compact boundary. Read it with one question in mind: for every dead end it mentions - the abandoned approach, the hypothesis that didn’t pan out - does the summary say what happened to it?

“We looked at the connection pool and the retry logic” is a mention. “Ruled out the retry logic: the storm only starts after the first 500, so it can’t be the cause” is a verdict. Scan the summary and count each kind.

If every dead end carries its verdict, you are already editing what carries forward, and the rest of this piece just names what you do by feel. Close the tab. If the dead ends read as neutral mentions, or quietly dropped out of the summary entirely, the next section is about your sessions, exactly.

The test is whether your carried-forward context says what was ruled out, or only what was touched.

The tell has a cause that has nothing to do with the agent’s mood. It’s called context rot: accuracy degrades as input length grows, well before the documented limit is reached. Chroma Research’s “Context Rot” study (July 2025) ran eighteen frontier models across multiple long-context tasks, and all eighteen degraded as the input grew. An agent at 65% of its window is measurably not the agent at 15%.

You have seen the artifact of this. A commit at the end of a marathon session that looks finished and isn’t. A function stubbed where the plan said implement. An error swallowed because handling it properly would cost tokens the agent didn’t think it had. The degradation is invisible in the moment because the agent narrates confidence the whole way down.

Then the tool intervenes, on its own clock. Claude Code’s auto-compact fires at a default threshold of 95% of the window; community reporting puts the effective ceiling nearer 83% once the reserved response buffer is counted, and the CLAUDE_AUTOCOMPACT_PCT_OVERRIDE setting can lower the trigger but never raise it. The trigger knows the token count. It has no idea whether you are mid-refactor or between clean tasks.

The cut lands where the budget runs out, which is almost never where the work has a seam.

When auto-compact fires, the tool summarizes the conversation so far, drops the raw history, and the session continues on top of the summary. Steel-manned, this is a real feature: it keeps a long session alive without you babysitting the token count, and current summarizers are genuinely good at it. A good summary preserves the goal, the decisions, the open threads. A faithful summary also preserves everything else, dead ends included.

Fix one example and stay with it, because the whole argument turns on what this session looks like at the moment of the cut.

The task: intermittent 500s on POST /sync. The session investigates six hypotheses in order, each chased to a verdict. Connection-pool exhaustion: wrong. Retry-storm amplification: wrong. A serializer race: wrong. A stale cache TTL: wrong. A bad DNS cache: wrong. And finally clock skew between workers breaking JWT exp validation - the actual cause, confirmed by skewing the node clocks and watching the errors move. Call it 1,000 tokens to chase each hypothesis and 500 to implement and verify the fix. Session one costs 6,500 tokens. Sunk either way; both carry-forward paths happen after it.

Five of those six investigations produced a negative result, and that negative result is the most valuable thing the session owns. Knowing the connection pool is innocent is exactly what stops the next session from re-trying it. To a summarizer, though, an acquitted suspect and an open lead look nearly the same. The transcript says “we examined the connection pool.” A faithful summary records the examination. Whether the examination ended in an acquittal is a fact about the author’s conclusion, and the transcript is where conclusions are least likely to be stated outright.

The session’s most valuable output is a set of negative results, and a faithful summary files them as topics.

Now run the seam itself, with numbers small enough to check with a pencil. Every number in this section is a toy: invented for traceability, not measured off a real session. The sizes are faithful to the real shape - a six-hypothesis debug session and a 200-token carry-forward file are both ordinary.

Session one ends. Two candidate artifacts could carry it into a fresh session, and they are declared the same size on purpose: 200 tokens each. The first is the auto-compact summary, a faithful 200 tokens naming the goal, the confirmed cause, and the six areas that were examined, with no verdict on the five wrong ones - because the transcript never states one. The second is a handoff file: the same 200 tokens, the same goal and cause, plus the five wrong hypotheses listed under a single clause - ruled out with evidence, do not reinvestigate.

Same size. Same subject. Hold onto that, because it is the whole experiment: if the next session diverges, size cannot be the cause of the divergence.

Session two opens with a look-alike bug: intermittent 500s on a neighboring endpoint. The fresh agent reads whichever artifact it was handed, then decides what to do about five hypotheses it has never tested itself.

On the summary path, it reads 200 tokens and faces five mentions with no verdicts. It cannot tell “ruled out” from “still open,” so it re-verifies them before it will trust its own new investigation: five checks at 1,000 tokens each is 5,000 tokens, spent before any new work starts. Total: 200 + 5,000 = 5,200 tokens.

On the handoff path, it reads 200 tokens, trusts the explicit verdicts, re-checks nothing that was ruled out, and starts on the actual bug. Total: 200 + 0 = 200 tokens.

The difference is 5,000 tokens, and it is the claim from the top of the piece, paid off exactly. Check what the 5,000 is made of: five hypotheses times 1,000 tokens each. The whole gap is the re-verification that missing verdicts forced. None of it is storage, prose quality, or summary accuracy.

ArtifactTokens storedWhat it says about the 5 wrong hypothesesTokens spent re-verifying themSession-2 total
Auto-compact summary200Mentions them, no verdict5,0005,200
Handoff file200”Do not reinvestigate,” explicit0200

Every cell comes from the four constants above: six hypotheses at 1,000 tokens, a 500-token fix, two 200-token artifacts. Nothing is rounded, nothing is estimated, and you can re-derive both totals on paper in under a minute.

Reading costs 200 either way. What differed was the 5,000 the summary made the next session spend.

”But the models are getting good at compaction”

Section titled “”But the models are getting good at compaction””

The strongest objection to this piece deserves its exact dates.

Amp, the coding agent from Sourcegraph, shipped this piece’s argument as a product on October 23, 2025: it retired compaction in favor of a handoff command that analyzed the thread, drafted a prompt and file list for a fresh session, and let you review what carried forward before committing to it. Then on May 6, 2026, its “Neo” rebuild deleted Handoff entirely and restored automatic compaction, triggering at 90% capacity, on an explicit bet: “Some features made sense when models needed more babysitting…They don’t anymore.” The team that shipped both designs landed on the automatic one. That is the best evidence against this piece, stated fairly.

Notice what “good at compaction” improves, though: fidelity. A better model writes a summary that reflects the conversation more accurately. A perfectly accurate summary of a session full of dead ends carries the dead ends, faithfully, into the next window. The 5,000-token gap above does not shrink as the summarizer improves, because no summary error caused it. A missing editorial decision did.

So name the thing the handoff file has that no faithful summary can originate. Call it the verdict line: the one clause that says what happened to a hypothesis - ruled out, with evidence, do not reopen. A summarizer cannot write it, because the information lives in the wrong place. The verdict is a conclusion the author reached about the work; the transcript contains the investigation, the hedging, and the move to the next lead, and a faithful rendering of that material is a mention. Writing the verdict requires deciding, line by line, which true things the next session should be allowed to believe. That decision is an editorial act, and the edit is the product.

Amp’s bet, taken seriously, is that this editing burden is friction the model should absorb for you. For routine work it is right, and a later section says so out loud. For the session above - five wrong hypotheses and a look-alike bug inbound - the model absorbing the editing for you costs exactly the 5,000 tokens.

“Good at compaction” improves fidelity, and the verdict line was never an act of fidelity.

The mechanism is small enough to build in an afternoon. Make it a slash command so it is one keystroke at the moment of the tell:

---
description: Write a clean handoff file for a fresh session
---
Write `HANDOFF.md` capturing ONLY what the next session needs:
1. **Goal** - the one task, in one sentence.
2. **Done** - what is finished and verified, not "started."
3. **Next** - the precise next step, with file paths.
4. **Constraints** - decisions already locked in.
5. **Dead ends** - hypotheses we ruled out, WITH the evidence,
each marked do-not-reinvestigate.
Do NOT summarize the whole conversation. Do NOT include
reasoning we've already discharged. Be ruthless. If it
won't change what the next session does, cut it.

Run against the /sync session, it produces something like this. Five dead ends, five verdicts, each with its evidence in a clause - and the count in the file has to match the count in the session, because any dead end you leave out goes back to being an open question:

# Handoff - intermittent 500s on POST /sync
## Confirmed cause
Clock skew between workers: tokens minted on one node fail
`exp` validation on another. Reproduced by skewing node clocks.
## Next
- In `src/auth/verify.ts`, widen the `exp` leeway to 30s and
pin all workers to NTP. Add a test that skews the clock.
## Dead ends - do NOT reinvestigate
- Connection pool: exhausted at peak, but the 500s predate it.
- Retry storm: amplification only starts after the first 500.
- Serializer race: ruled out under a single-threaded load test.
- Cache TTL: purged, errors unchanged.
- DNS cache: forced misses, errors unchanged.
All five ruled out with evidence. Reopening any is wasted budget.

Then you restart. Fresh session, point it at HANDOFF.md, and delete the file once the seam is behind you. The new agent begins near empty, on the clean end of the context-rot curve, holding every verdict and none of the maze. You decide what the next session is allowed to know.

The reason people skip this is friction: at the exact moment the agent is rushing, you are tired and just want it done. So take the willpower out of the loop. Keep /handoff in the project so it is shared and versioned, and add one line to your configuration so the agent raises its hand at a budget you set instead of quietly downshifting (a sensible trigger is around 60%, well under the 95% default):

## Context discipline
When your context usage passes ~60% mid-task, stop and propose
a handoff: draft HANDOFF.md per the /handoff format and
recommend a fresh session. Do not quietly compress the
remaining work to fit.

The file is a few hundred tokens you actually read before it carries forward. That review is not ceremony. It is the only moment anyone checks that the five verdicts are true.

You write 200 tokens on purpose so the next session never re-earns the 5,000.

One look-alike bug is the small case. The dead-ends ledger pays out again every time a similar bug lands on the same ground, because every new session re-faces the same question: trust the carried-forward verdicts, or re-verify? Run the same two paths across a run of look-alike bugs, where each bug means a fresh session that reads the artifact again:

Look-alike bugs hitAuto-compact pathHandoff pathGap
15,200200+5,000
210,400400+10,000
315,600600+15,000
526,0001,000+25,000

Each row multiplies the toy’s two session-2 totals by the bug count, and the gap grows by 5,000 per bug - in lockstep with the number of verdicts available to trust. The stored size never moved off 200.

The 5,000 behaves like a subscription: every session that inherits the unedited summary pays it again.

For routine, linear work - a small feature, a rename, a dependency bump - the dead-ends ledger is close to empty, and the manual ritual is pure ceremony. Let auto-compaction run. Amp’s 2026 reversal is the right call for exactly that class of work, and this piece would oversell itself by pretending otherwise. The handoff earns its keep only where a wrong carry-forward is expensive: the long debug, the architecture spike, the refactor with three abandoned approaches behind it.

The handoff fails in the other direction too. It is only as good as your editing, and an over-aggressive cut is its own failure mode: delete a constraint that mattered and the fresh session cheerfully rediscovers the bug you had already fixed around. A verdict line is powerful exactly because the next session trusts it more than anything else in the file, which is also why a wrong one costs more than a neutral mention would have.

And some of what you are tempted to put in the file does not belong there at all. Locked-in conventions, hard project rules, anything still true next month: that is persistent context, and it belongs in your rules file, which loads every session regardless. Hierarchical context draws that split - static rules at the top, forever, disposable files scoped to one seam - and if what you are accumulating is corrections meant to outlive the project, your AGENTS.md is write-once agent memory and has that whole lifecycle. The handoff file is the opposite: single use, single seam, deleted when the seam closes.

Reach for the handoff when the session is full of verdicts worth protecting; leave auto-compaction on when it isn’t.

This piece argues a binary - an opaque compactor or an authored file - and the real landscape already has third options. Naming them honestly is cheaper than pretending the binary is exhaustive.

Anthropic shipped its own answer at the API layer on September 29, 2025: a memory tool (memory_20250818) and a Context Editing API that let the model read and write its own memory files and clear stale tool results server-side, with Anthropic reporting a 39% improvement on a 100-turn benchmark when the two are combined. That is closer in spirit to the handoff - the model deciding what carries forward - but it operates without the human editorial gate this piece argues the verdict line needs. A related bet, named here, not evaluated; it deserves its own piece.

Session resume and fork are a second alternative: rewind the transcript to an earlier point and branch from there. It is no substitute, because rewinding restores an earlier low-context state by throwing away everything gained since, good and bad together, where a handoff keeps the earned signal and cuts only the dead ends.

A scope note, finally: the mechanics here are checked against Claude Code and Amp, the two tools that have shipped opposite designs on this exact seam. Codex, OpenCode, Cursor, and Copilot all compact long sessions too, but nothing in this piece is verified against their internals. Treat the mechanism as portable and the specifics as untested.

The binary this piece argues is real, and it is already being outflanked from both sides.

Four other pieces on this blog work adjacent ground, and the differences matter more than the overlap. The relay, not the window runs a multi-session relay across an entire build, with auto-compact disabled outright and a plan file as the baton; this piece is the single seam inside one session, argued while auto-compact is still on as the default. Treat the plan file as external memory builds an exhaustive checklist audited by a second model across a 340-file migration, where completeness is the goal; the handoff is a dead-ends ledger, where deliberate incompleteness is the goal. Destination and journey fixes scope before work starts, preventing the drift; this piece is triage after a session has already filled. The loop that rereads its diary runs unattended with git commits as its memory between passes; the handoff is a human-triggered decision inside one interactive session.

Same villain, different seam: this piece owns the moment a full session hands its verdicts forward.

Put the whole argument back on the two-row table. Two artifacts, 200 tokens stored each; 5,200 against 200 in the very next session. Replay it across the run of look-alike bugs and the gap reads +5,000, +10,000, +15,000, +25,000 - growing by exactly five verdicts’ worth per returning session. At every scale, the stored size was identical. The only thing that ever moved the number was whether someone had written, and taken responsibility for, the line that says ruled out.

When the seam arrives, one of two editors chooses what survives it. A black box decided what to forget, or you did. Only one of those is context engineering.

And this piece cannot close its own last loop: nothing enforces that a verdict line is honest. A tired human writes “ruled out with evidence” about a hypothesis they abandoned without actually ruling it out, and the next session trusts the most confident line in the file. The arithmetic above catches an oversized artifact - you can see bloat in the table. It cannot catch a false verdict, because a false verdict occupies the same 200 tokens as a true one. How a carried-forward verdict earns trust is an open question, and it is the one this piece hands forward.

The handoff file solves who edits the carry-forward. Whether the editor told the truth is still unchecked.


About the numbers. The toy constants - 1,000 tokens per hypothesis, 500 for the fix, six hypotheses of which five were wrong, and two 200-token artifacts - are invented for traceability, sized so every total can be re-derived with a pencil. The 6,500, 5,200, 200, the 5,000 gap, and every figure in both tables follow from those constants by arithmetic and were re-checked against a script before publishing; nothing is measured off a real session. The ~60% proposal threshold is this piece’s recommendation, not a measured optimum. The dated facts are separate and sourced: Chroma Research’s “Context Rot” (July 2025, eighteen models, all degraded; research.trychroma.com/context-rot); Claude Code’s 95% auto-compact default and the community-reported ~83% effective ceiling (checked August 2026; github.com/anthropics/claude-code/issues/31806); Amp’s Handoff launch (October 23, 2025; ampcode.com/news/handoff) and its Neo rebuild’s reversal (May 6, 2026; ampcode.com/news/neo); and Anthropic’s memory tool and Context Editing API (September 29, 2025, 39% on a 100-turn benchmark; platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool).

For the per-tool mechanics, see Context window management for when to reach for a handoff versus compaction, Slash commands for wiring /handoff as a one-keystroke trigger, and Configuration & profiles for making the agent propose a handoff at your threshold.