CliffCompaction: Cost-Efficient Compaction for Long-Horizon Coding Agents
ProblemLong-horizon coding agents accumulate millions of tokens of context; how to compact it without losing what matters and without re-prefilling (and paying) on every step.
VerdictThe mechanism is sound and worth borrowing, but headline numbers are oversold: cost savings are solid, 'quality improves' sits within seed noise, and 'matches Opus 4.7' / '25% over specialized methods' are cross-harness / cross-model comparisons.
1. Verdict
The mechanism is sound and worth borrowing, but headline numbers are oversold. The core contribution is a very simple rule: let the context grow until a threshold, compact only by truncating/dropping (never rewriting), and discard the previous compaction block every time. The cost reduction (cache reads −80%) is solid; "quality maintained or improved" on Terminal-Bench is within seed noise; "matches Opus 4.7" and "25% over specialized methods" are cross-harness / cross-model comparisons. Trust: mechanism high / cost medium-high / quality gains low-medium.
2. Mechanism + mental model
Trigger: only when LLM() raises ContextWindowExceeded (Alg. 1). On compaction, older turns are processed message by message:
- System prompt + first user message (task description) kept verbatim
- Most recent K turns kept verbatim
- Older turns:
- assistant thinking truncated to 300 chars
- tool calls reduced to a signature (tool name + path and key arguments, ≤150 chars; inline file contents in write calls removed)
- tool results ≤500 chars kept, >500 chars dropped entirely
- the previous compaction block is discarded, never nested into the new one
- New context = [system, task, this compaction block] + last K turns
Mental model (paper evidence + my inference):
- Cost side: most of an agent's bill is cache reads (78% uncompacted, Terminal-Bench / GLM 5.1), because every step re-reads the whole prefix. Changing the prefix only at the "cliff" keeps the prefix cache valid for the whole segment in between; sliding windows and microcompaction change the prefix almost every step and keep invalidating the cache. So when you compact matters more for cost than what you compact into.
- Quality side: dropping content leaves an obvious hole (signature present, result gone) — the agent knows what it doesn't know and re-reads the file to get ground truth. An LLM summary leaves a plausible-looking paraphrase — the agent believes it already knows, stops going back to the source, and drifts. The authors call this "high compaction precision, low recall".
3. Key numbers, verified
| Claim | Where | Actual condition | Holds? | Note |
|---|---|---|---|---|
| Cost down up to 50% | Tab. terminal-bench; Tab. real-cost | Kimi K2.6, Terminus-2, 16K: $0.40→$0.19 (metered −53%); GLM 5.1 8K metered −72% | ✅ | But on SWE-bench Kimi K2.6 32K is 0%, 16K −8%, 8K +1% (Tab. real-cost). Savings depend heavily on the model's cache hit rate and the scaffold |
| Terminal-Bench quality "maintained or improved" | Tab. terminal-bench | Kimi 59.16±3.41 → 61.42±4.25 (32K/16K) | ⚠️ within noise | 89 tasks; 2.26 pts ≈ 2 tasks; std 3–4 pts on both sides. Number of seeds not reported. The more meaningful comparison is vs. Terminus-2's native summarizer at the same 16K: 55.45→61.42 |
| Cache reads −90% | Intro | Efficiency section reports 80% ($0.427→$0.087/task, GLM 5.1 TB) | ⚠️ | The intro's 90% has no matching number in the body |
| +10.5 pts with 3 rollouts at 1.9× cost | Tab. terminalbench-scaling | Kimi 16K + SGV selector, k=3: 69.7 vs. single full-context 59.2 | ✅ numbers check out | ~5.7 of the 10.5 pts come from Cliff vs. "no compaction + SGV" (64.0); same 89 tasks, single selector run, no confidence interval |
| Matches Opus 4.7, beats GPT-5.3 Codex / Opus 4.6 | same | Opus 4.7's 69.4 is from the system card, not the Terminus-2 harness; GPT-5.3 / Opus 4.6 are Terminus-2 leaderboard numbers, k=1 | ⚠️ | Caption claims "surpassing every proprietary baseline on the same Terminus-2 harness" — Opus 4.7 isn't on that harness. Also k=3 + selector vs. k=1; and k=3 costs $58.01, more than Opus 4.6's $44.53 — "at lower cost" holds for k=3 only vs. GPT-5.3 Codex ($64.63); only k=2 (65.9% / $38.67) beats Opus 4.6 while being cheaper |
| KernelBench 2.23× @200 steps, 3.58× @400 | Tab. kernel-bench | Kimi K2.7 (not the K2.6 used for TB/SWE), L40S, CUDA, atol=rtol=1e-2 | ✅ | The same setup with Kimi K2.6 on RTX Pro 6000 gets only 1.87× / 2.48× |
| "Under matched settings" beats specialized methods by 25% | Intro | 25% = 2.23/1.78, i.e. Kimi K2.7 + Cliff vs. GPT-5-mini + AdaExplore | ❌ not matched | Same-model (GPT-5-mini) is 2.09 vs 1.78 = +17%; all baselines are "as reported" numbers; CUDA-Agent's 1.80× is a geomean over correct solutions only, on H20 |
| Beats other compaction methods, only one both good and cheap | Tab. compaction-cost | KernelBench: Cliff 3.58× / $8.32 vs. summarization 3.47× / $8.10; SWE-bench: all four within 2.6 pts, sliding window highest | ⚠️ | Summarization essentially ties on KernelBench and is cheaper; this table switches models (Kimi K2.7, GLM 5.2) and is a single run |
4. Checklist findings (agent checklist)
- Evaluation validity: SWE-bench Verified / Terminal-Bench 2.0 (89 tasks) / KernelBench L3 (50 tasks) are all execution-judged. Fine.
- Reliability: ± std reported but number of seeds not reported; the TB "improvement" is within std. In the Claude Code experiment Cliff's std is 1.41 vs. 3.72 for native compaction — a notable positive signal (lower variance).
- Controlled comparison: main tables compare same model, same scaffold — clean. But model versions drift across experiments: TB/SWE main tables use Kimi K2.6 / GLM 5.1, the compaction comparison uses Kimi K2.7 / GLM 5.2, KernelBench uses Kimi K2.7. The Claude Code comparison is matched on mean peak context (~45K), which is reasonable.
- Serving confounds: cost depends heavily on the provider's prefix-cache behavior (Kimi hit rate 96–98%, GLM 58–91%). The main-table Cost column is an idealized perfect-cache estimate; metered costs are in a separate appendix table and don't match (e.g. GLM 5.1 TB full context: $0.54 main table vs. $0.89 metered).
- Cost reporting: thorough (metered cost, cache hit rate, wall-clock −23% / −34%). The most solid part of the paper.
- Generalization: the SGV selector is trained on another model's rollouts on the same 89 tasks; main results use the 100%-of-tasks version. The appendix "25% of tasks works just as well" only partly mitigates this (evaluation still includes training tasks). SWE-bench features include
repo_code(repository identity), a prior-type feature. - Failure analysis: a good behavioral analysis — re-read counts (appendix Fig. extra-steps) support the precision argument. The 8K threshold clearly degrades; authors acknowledge it.
5. What the abstract doesn't say
- On SWE-bench, test-time scaling doesn't benefit from Cliff: uncompacted Kimi + SGV k=3 = 78.0% @ $284 vs. Cliff 16K k=3 = 76.4% @ $264 (appendix Tab. swebench-scaling). The abstract only cites Terminal-Bench.
- Kimi barely saves money on SWE-bench (cache already 96% hit, short trajectories). Gains concentrate in long trajectories with imperfect cache hit rates.
- Only meaningful for medium-to-long horizon tasks (stated in Limitations).
- Self-hosted vLLM measurement (appendix Tab. glm-flash-time; GLM-4.7-Flash, vLLM, RTX PRO 6000 Blackwell, SWE-bench Verified): total LLM-call time 234.2h → 146.0 / 111.6 / 88.9h, i.e. 1.60× / 2.10× / 2.62× at 32K/16K/8K. But the same model's accuracy (Tab. swe-bench) is 43.20 → 43.60 / 41.20 / 30.70 — the 2.62× costs 12.5 points; 16K is the sensible setting. The appendix reports only the speedup.
- Main-table costs use a "perfect-caching model" (§A.1): any prompt longer than the previous one counts as a full prefix hit; any shorter prompt counts as a full invalidation. This is optimistic for the full-context baseline (real provider hit rates are 58–98%) and conservative for Cliff's re-prefills (the system+task prefix would still hit). Metered costs are in a separate table.
- Cost breakdown (Tab. cost-attribution, GLM 5.1 TB): savings come almost entirely from tool results (−61%) and tool calls (−58%); thoughts save only 11%, system+task actually rise +22% (re-prefill). OpenHands signature rules are in Tab. openhands-signatures (command ≤120 chars, old_str ≤60 chars, task_tracker dropped entirely).
- Commented-out text in the LaTeX source (not part of the paper; my observation):
- A removed limitation: proprietary models have much shorter trajectories — Opus 4.8 uses ~0.5M tokens / 22 turns on TB 2.1 vs. ~1.7M / 35 for Kimi K2.7 — i.e. the benefit falls mainly on open-weight models. This sentence is gone from the final version.
- An older compaction comparison had weaker baselines (sliding 2.76×, Anthropic-style 2.71×) and claimed both "underperform no compaction per dollar"; in the final version baseline numbers are higher (2.86× / 3.33× / 3.47×) and that claim was removed.
6. Takeaways (my inference)
- Compaction timing is an inference-cost problem, not just an agent-design problem: cache hit rate drives the bill. Any context management that edits the prefix (including Claude Code's microcompaction) fights the prefix cache. This directly links the agent and serving tracks — read alongside Hot-Cold KV tiering (2609.25782) and PatchKV (2609.26219, KV repair after editing mid-context).
- Leave a hole rather than fill it with a paraphrase: letting the agent clearly see what it lost — with a signature to fetch it back — is more reliable than a plausible summary. A transferable harness design principle; same idea as DTOC (placeholder + on-demand restore).
- For your own Claude Code use: the proxy can sit directly in front of Claude Code. But Claude trajectories are short and cache hit rates high, so per the paper's own deleted paragraph the benefit may be small — better suited to long-running open-weight-model agents.
7. Next steps
- Worth reading the code (the proxy is small) to see how tool-call signatures are built for Claude Code's schema.
- Open question: how many seeds? Is Cliff vs. full context on TB significant across seeds?
- Read next: Anthropic context editing (
clear_tool_uses), DTOC (2609.26121), PatchKV (2609.26219).
8. Cross-check: independent full read by Gemini 3.1 Pro
All 22 source files (commented-out drafts removed) were given to Gemini 3.1 Pro (via agy, no tools) for an independent read, without this note. Every point below was re-checked against the source:
- It caught, I had missed: k=3 costs more than Opus 4.6 (now in the verification table); appendix parts I had not read end to end (wall-clock, signature rules, price table).
- I had, it missed: the "matched settings +25%" is a cross-model comparison (it marked it as holding); Opus 4.7's score is from the system card, not the same harness; test-time scaling doesn't help on SWE-bench; summarization ties Cliff on KernelBench; the 8K accuracy drop behind the self-hosted speedup.
- It overstated: that the selector is "evaluated on its own training data". The selector is trained on another model's trajectories; the overlap is in tasks, not trajectories — task-level overlap, not direct label leakage.
- Both agree: "cache reads −90%" has no support in the body (it's 80%); seeds not reported and the TB gain is within std; model versions drift across experiments; at 8K cost can go up rather than down.