Harnesses, Part Three: How Agents Run Forever
What happens when an agent outlives its context window — and how it decides what history survives.
Read the article for free, here.
Alpinists don’t carry the expedition. They cache it.
A long climb is staged into camps each stocked with what the next leg needs. Whatever isn’t required stays behind, retrievable if you have to come back, but not dragged any higher. The load that reaches the summit is whatever survived every camp’s decision about what to leave behind.
A context window works the same way. Capacity is fixed, the route isn’t, and eventually something has to be left behind.
Part Two argued for the rule underneath all of this, never invalidate the cache. Keep the stable part warm and push change to the tail. But Part Two treated a session like a still photograph. It didn’t account for time.
Every session ages. The conversation grows. Eventually the window fills and you have to fold.
The mechanical outcome is simple a smaller window. The cost is less simple, folding requires an invalidation event. You pay that cost once, rewrite what survives, and continue.
But the invalidation isn’t the interesting part.
The interesting part is what survives the fold.
A good compaction doesn’t merely remove tokens. It compresses a history into something the agent can continue from. And long-running sessions don’t fold once. They fold, work, fold again, and eventually fold the previous fold.
The real question is therefore not when should we compact?
It’s, what survives a fold of a fold of a fold, and eventually, what disappears?
This changes how we should think about compaction. The schedule matters because invalidation costs money. But the compression matters because it determines whether the session is still the same session afterward.
And compaction should be the last rung you reach for, not the first.
The tail is the bill
A request has two economic regions: the prefix that survives, and the tail that grows.
The prefix is the system prompt, tool definitions, repo-stable context, rules files. Written once, cached, read back at a fraction of cost on every later turn. It doesn’t grow. It’s the thing we were protecting in Part Two.
The tail is everything after. The conversation, tool calls, tool results, thinking blocks, diffs. It grows monotonically.
But growth isn’t the tail’s expensive property. Rent is.
Every time you type a message and hit enter, the harness doesn’t send the new text alone. It resends the matched prefix, reads it back at the cached rate, and writes whatever’s new at the write premium. The tail rides along on every one of those reads.
A hundred and fifty thousand tokens of tail isn’t a static liability sitting in the window. It’s a bill that comes due on every turn, whether the model needs any of it to answer your next question or not.
You’re paying rent on your own history every time you press enter, for as long as the session lives.
The cache has another clock. Its TTL is refreshed by activity, so idle time can turn the next turn into a cold write.
Human think time is a non-advertised cache expense.
Compaction is therefore an operation on the tail that is also an operation on the cache. You’re choosing to pay an invalidation cost today to stop paying rent tomorrow.
That’s the trade.
And before paying it, there are cheaper places to intervene.
The ladder
There are five moves against tail growth. They aren’t alternatives so much as rungs. The higher you climb, the more existing history you are willing to disturb.
One: don’t generate it. Cap the output at the tool. Anthropic’s text editor tool supports max_characters , web search supports max_uses. Codex caps individual tool outputs betwen 10,000 — 16,000 tokens by default, before they reach the compaction calculation. The more disciplined version is snipping. Keep a head and a tail, trim the middle, on the assumption that what a command started with and where it ended matter more than the scroll back between them.
The weakness is that you’re truncating before you know what mattered. A stack trace with the relevant frame removed is worse than no stack trace.
Two, spill it. Don’t carry the whole observation if you don’t need the whole observation. When a tool result crosses a size threshold, the harness can write it to disk and leave a reference behind. The full artifact survives, the live context doesn’t.
This is different from truncation. Nothing was thrown away. A 500k-line build log or terminal result can live on disk while the context contains only its path, metadata, or a searchable index. When the agent needs something from it later, a native search or read tool pulls back only the relevant slice.
Keep the artifact. Remove the observation.
This is one of the cleanest ways to separate storage from context. The information remains durable without collecting rent on every subsequent turn.
The catch is that the harness needs the tools to find it again. Spill-to-disk only works if the agent can search, read, and reason about what it stored. Otherwise you’ve traded context overflow for a filesystem full of things that can’t be retrieve.
The convergence here is striking. Several harnesses land on nearly the same threshold. Claude Code spills any tool result over roughly a 100k to disk and hands back a preview plus a path. Hermes uses the same 100k per-result cap. And both make the same pointed exception, the read tool is exempt from spilling, because a spilled read is a path that the agent would only read again. Literally, a read to spill to read, forever. I honestly have gone into infinite loops here. Be careful. The one tool whose whole job is to pull content back is the one tool you must never spill.
Three, don’t admit it. Delegate the work. A subagent with the harnesses native tools can read the files, scan the logs, explore the repository, and accumulate a large working context without any of that history entering the parent’s tail. When the task ends, the child’s window disappears and only its return value crosses the boundary.
This is genuinely one of the most popular features harnesses shipped this year. However, exploration is not as dangerous as modification. A worker that reads the wrong files costs you a re-run. A worker that edits the wrong files leaves damage behind after its context is gone. Be careful about which model you allow to do a modification. Back in the day, a scout wasn’t typically a high-ranked officer of your kingdom. You sent someone fast and expendable to go look. Looking is cheap and the report is easy to check. An emperor looking to overtake would always send their best to do the taking, the act itself is the thing that can’t be undone.
Delegate the scouting to a cheap, disposable context. Reserve your strongest for the move that actually changes the world. And, keep the parent in the loop to verify it.
The parent pays for the answer, not the investigation.
Four, replace it with a pointer. If the content already exists durably — a file, artifact, generated report, or spilled tool result — the pointer is all the conversation needs. A re-read goes back to where the content lives without carrying the content permanently in the conversation.
Anthropic’s memory tool is exactly this, built for you. OpenAI provides similar behavior with their Tools API (Function Calling).
Turn expensive conversational state into a cheap reference to durable state.
The catch is that the pointer only saves money while the underlying content stays out of the window. Re-read it and it becomes tail content again, renting from the moment it lands.
Five, delete it after the fact. Clear it. Compact it. Fold it. This is the only rung that invalidates existing cache.
You spend a turn to replace accumulated history with a smaller representation and hope the next turn can continue from it. The transcript may still exist on disk, but the live context has changed.
Now the economics become a bet… will the rent you stop paying over the rest of the session exceed the cost of rewriting the history today? Compact too early and you destroy a warm cache you could have used for hundreds of cheap turns. Compact too late and you’ve already paid rent on a mountain of history — while the model may already be getting worse at using it.
Almost every conversation about long-running sessions starts here.
It shouldn’t.
The distinction becomes
- Don’t generate it. Prevent tail growth.
- Spill it. Remove the bloated observation, preserve the artifact.
- Don’t admit it. Delegate the investigation to another context.
- Replace it with a pointer. Keep only a cheap reference in the conversation.
- Delete it after the fact — compact/fold and accept information loss.
The cheapest context is not compressed context. It’s context that never had to be there.
Native tools are a bet about which region pays
A tool definition lives in the prefix. Fixed cost, written once, cached.
A tool result lives in the tail. Variable cost, paid, and then rented forever.
That makes the shape of a harness’s toolset a bet about where to pay for information. A minimal tool surface keeps the prefix small but pushes more raw observation into the tail. A richer tool surface spends prefix tokens to make observations smaller and more structured.
At the minimal end, Terminus 2 keeps the prefix genuinely small. A single headless terminal, on the Unix bet that one general tool composes infinitely. Codex is often grouped here, but that’s only half correct. Its native prefix isn’t small at all, it ships around 20 always-present tools plus a multi-agent suite, they also have a v1/v2 suite. It uses deferral, not omission, to stay lean, indexing MCP and connector tools in a search engine and pulling them in on demand rather than carrying them upfront. Where Codex really makes the minimal bet is the tail, not the prefix. Codex’s apply_patch shows the trade directly. A compact diff can replace thousands of tokens of rewritten file content, and per-tool output caps keep raw observation from piling up. So the two harnesses land relatively close each other for different reasons, Terminus 2 by holding the prefix down, Codex by holding the tail down.
Claude Code and Hermes spend more prefix on specialized tools that produce structured observations instead of raw ones. Claude Code’s catalogue runs to roughly 40+ once you count LSP, plan mode, worktrees, and cron. Hermes’ to about 55, grouped into toolsets for terminal, file, memory, skills, delegation, and more. Grep returning matches instead of an entire file, essentially, the harness pays a little more permanent prefix to avoid paying thousands of tokens of permanent tail.
Different harnesses make different bets. The interesting question isn’t which one has more tools. It’s whether the prefix investment reduces enough tail accumulation to delay the fold.
This is the same eager-versus-JIT axis from Part One, one layer higher. Anthropic’s deferred tool loading makes the trade explicit, tool definitions themselves can be discovered just in time instead of being carried eagerly in every request. Claude Code implements a ToolSearch mechanism that keeps deferred tools’ names visible but withholds their full schemas until the model asks for them, auto-enabling once MCP tool definitions cross roughly 10% of the context window. Even the ordering is chosen for the prefix. Tools are sorted alphabetically so the tool definition block stays byte-stable and cacheable across turns. The prefix isn’t just small or large. It’s arranged to stay warm.
The axis is still useful though, but its role changes here. It doesn’t determine whether you compact. It determines how much history you accumulate before you have to.
And that distinction matters because this history that you accumulate isn’t homogeneous. Search results are often re-derivable. Decisions aren’t. A file path can be reconstructed. The reason you rejected an approach may not be.
The longer the session runs, the more expensive it becomes to confuse those two kinds of memory.
Delegation is a memory boundary
Delegation is the one rung that sheds history without invalidating the parent’s cache. That makes it more interesting than simply being a cheaper way to run work.
A subagent creates a separate context window. It can accumulate a huge tail, fill its own window, compact internally, and eventually disappear. None of that rewrites the parent’s history.
This corrects an assumption from an earlier version of this argument. I had framed same-model forking, aka, a child inheriting the parent’s accumulated tail while sharing its warm prefix, as a production pattern. Looking across current harnesses, the implementations I could verify don’t generally do that. Claude Code, OpenCode, Codex, and Hermes all establish separate worker contexts rather than handing a child the parent’s entire accumulated tail. Some can also run the worker on a different model. Codex takes a model override on the spawn call, Claude Code lets you pick sonnet, opus, or haiku per subagent. Though it isn’t universal. Hermes’ delegate has no direct model switch and reaches a different model only indirectly. The point that generalizes here isn’t the model knob. It’s the separate context.
That turns out to reveal something more important than the fork mechanism.
The child’s tail is disposable. It reads forty files, scans the logs, maps the naming convention, and its entire context can disappear while a paragraph comes back.
Get Jordan Carson’s stories in your inbox
Join Medium for free to get updates from this writer.
Delegation is therefore a memory boundary. The parent says, “here is the task, figure it out, give me what I need.” That’s a form of compression performed prospectively. The worker knows who will read the result and what decision the result needs to support. If you notice what happens when a subagent completes, the parent usually verifies or validates. Although this spends a few turns, its a good idea.
Compaction works retrospectively. It has to summarize toward an unknown future reader and hedge against every possible next question. Prospective compression has an advantage, the reader is known.
Which leads to the more important budgeting rule.
Budget the return, not the run.
The worker may burn hundreds of thousands of tokens and none of them become permanent parent memory. The return does. A four-hundred-token answer enters the parent’s tail and starts collecting rent on every remaining turn. A raw diff may therefore be more expensive over a long session than a much more expensive worker that returns one useful sentence.
The worker’s investigation is ephemeral. Its answer is history. And that answer will eventually have to survive a fold.
What the platforms give you
The model platform determines how much of this machinery the harness has to build itself.
Anthropic (compaction docs) provides two distinct forms of help, and they solve different problems. clear_tool_uses_20250919 is surgical once the prompt crosses a threshold — 100k input tokens by default, keeping the three most recent tool uses — it clears stale tool results server-side and replaces each with a placeholder. clear_at_least is the amortization knob, forcing you to specify a floor worth the invalidation. compact_20260112 is the heavier primitive, full server-side summarization, a new representation of the conversation rather than a removal from the old one.
Claude Code is particularly instructive because even the harness built by the company providing those primitives still appears to orchestrate its heavier /compact behavior itself — based on community reverse-engineering (barazany.dev and karanprasad.com, both tracing to the same Github sourced exposure) rather than Anthropic’s public documentation. The light clearing rides server-side. The actual /compact, the operation that decides what conversational state survives, is a client-orchestrated call.
OpenAI’s server-side offering is centered on compaction. /v1/responses/compact returns an opaque, encrypted blob the client passes back without inspecting — encrypted in part to close off a prompt-injection surface, a tampered summary steering later turns. There’s no OpenAI equivalent of surgical clearing, so Codex still has to manage tool-output size itself, and underneath both paths sits a crude fallback exceed the window anyway and Codex just drops the oldest history item and retries.
DeepSeek provides much less context-management machinery. Its server-side prefix caching is a cost optimization, not a solution to the fixed-window problem — a harness operating there has to own the entire compression pipeline itself. The official DeepSeek Harness builds one, and does it non-destructively shadowed events stay in the log and stay reachable. A third-party DeepSeek TUI I looked at doesn’t bother, and simply doesn’t proactively compact at all.
The interesting point isn’t which API has the best compaction endpoint. It’s where the responsibility for deciding what survives lives.
Hermes is useful as the limiting example because it operates across multiple providers. It can’t assume any one platform will provide the necessary primitives, so it runs its own client-side compressor as the floor — a dual-threshold design, 50% from its own token accounting, 85% from a rougher gateway-level check that catches sessions accumulating between turns while nobody’s watching and reaches past that compressor whenever the active provider offers something better.
That’s the right general architecture. The harness should own the compression by default, they have information a server may never see. Then, defer to the platform when the platform earns it.
Because regardless of who performs the fold, the same question remains.
What are you willing to forget?
Coming back to camp
Everything above assumed the session never stops.
But sessions stop. The laptop closes. The process dies. The CI job exits. Someone types /resume and expects to pick up where they left off.
It’s the easiest thing you’ll type all day for the most expensive turn in the session. /resume is seven characters, counting the slash, same shape as /help or /clear — no arguments, no confirmation, no friction. Nothing about it says what it costs, and the interface has one job here, which is pure convenience, so it’s tuned to make coming back feel free.
The conversation can come back. The cache cannot.
A resumed session is not a paused process. The harness replays the transcript from disk and reconstructs the message history. The conversation returns from durable storage, but the warm prefix does not.
That creates two different kinds of recovery.
The first is economic. As discussed in Part 2, Anthropic’s prefix cache has a TTL — five minutes by default, an hour if you paid the heavier write for it — refreshed only by activity. A resume is idle time taken to its limit, a gap with no process on the other end at all. So the prefix that had been cheap to reuse comes back stone cold, and the next turn pays full price to re-establish it. The most expensive cost is resuming a multiple day long-session, so be aware and smart with how you manage your sessions.
The second is informational. If the transcript is larger than the available window, the harness may have to fold it before the first new action happens. And that’s a particularly dangerous fold — the session is being compressed before you’ve had a chance to re-establish what matters. A constraint that explained a decision nine turns ago may be present in the transcript but absent from the compressed representation. The agent resumes with a smaller window and a plausible history, but not necessarily the history that made the previous decisions make sense.
What survives a fold is what survives a resume. That’s the deeper reason durable state matters. Project-root rules can be re-injected from disk. Files can be read again. A todo list can be reconstructed. A generated build log can be stored and referenced. But a conversation-only decision has no external source. If it survives only because the transcript carried it, it must be paid for again when the session comes back. If it was folded away, it may simply be gone.
The hierarchy is therefore not just about cost. It’s about durability.
The closer something is to the bottom, the more vulnerable it is to a fold.
Where folding breaks
There are two ways folding fails.
The acute failure is obvious. Compaction succeeds. A huge tool output immediately refills the window. The harness compacts again. The same output arrives. The harness compacts again, like a machine bailing the boat while drilling the hole.
Claude Code stops retrying rather than burning calls in a loop, baked in logic to identify when its in a loop and agent isn’t progressing. That’s the right behavior. But the loop itself is the signal. You’re operating on the wrong rung. Ideally, it should self-reflect to identify a different approach rather than retrying a native tool. If the same oversized file keeps forcing compaction, the answer isn’t a lower threshold. It’s a line-range read, a scoped grep, a pointer to durable output, or a subagent whose window you don’t need to preserve. (Note to readers, Claude Code has multiple Stop Iterations called at different sites, I am not referring to /goal or /loop here).
Every time you find yourself tuning compaction, ask whether the answer is three rungs up or a different approach entirely.
The chronic failure is more interesting. Compaction is lossy, and long sessions don’t compact once. They compact. Work. Compact again. Work. Compact again. Summaries of summaries of summaries.
Folds of folds
The first fold can be excellent and still create a bad third fold. Because the second summarizer isn’t looking at the original history. It’s looking at a representation chosen by the first summarizer. The third isn’t looking at either of those, it’s looking at the second summarizer’s judgment about the first summarizer’s judgment.
That changes what information is at risk. The original conversation contains both facts and reasons. The first fold may preserve, “we chose approach B.” The second may preserve, “approach B is the current implementation.” The third may preserve, “current implementation uses approach B.”
All three statements are true. But the reason approach A was rejected has disappeared. The system hasn’t forgotten the decision. It has forgotten the information that made the decision intelligible. That’s the distinctive failure of folds of folds.
What should survive?
Across different harnesses, structured summaries keep converging on roughly the same categories:
- Intention, what are we trying to accomplish?
- State, what have we learned or changed?
- Work/ To-dos, what has been completed and what remains?
- Open items, what is unresolved, constrained, or still under consideration?
Different harnesses give these fields different names, but the shape keeps recurring. Maybe that’s the smallest practical state a session needs to preserve. Several harnesses also have file restoration techniques to minify stale / cached file reads post-compaction. Claude Code, Hermes, and DeepSeek Harness all keep a small record of what was read, keyed on path + range + modification time (mtime), and return a lightweight stub instead of re-sending a file whose contents haven’t changed. The read already happened, its just, the tokens don’t have to happen again.
But even that isn’t enough if those fields themselves are repeatedly summarized without a durable source of truth. A summary can say “we decided to use approach B.” A durable artifact can say “we decided to use approach B because constraint X makes approach A invalid.” The second survives compression better because the reason exists somewhere outside the compression process.
That’s the bridge from compaction to memory.
Memory is what survives the fold
The obvious response to lossy compression is to compress better. The more durable response is to move important information somewhere that doesn’t need to be compressed with the conversation at all. I will write more on this later, but let’s leave it here for now.
This is why memory tooling matters. This is why companies have all defined their own paths forward towards memory architectures, and have previously wrote about Memory Engineering.
Anthropic’s context-editing and memory mechanisms make the boundary explicit. As the conversation approaches a clearing threshold, the agent can be given an opportunity to write important state to durable memory before volatile context is removed. The techniques we mentioned above, can be repurposed.
The system is effectively saying, “you’re about to forget this, write down what matters.”
That’s a fundamentally different operation from asking the model to summarize everything. A summary tries to make the live window smaller. Memory tries to make some information independent of the live window. And that distinction becomes more important with every fold.
The ideal long-running harness therefore isn’t one that never compacts. It’s one that understands the difference between information that can be regenerated, information that can be referenced, information that should be compressed, and information that must survive unchanged.
The last category shouldn’t depend on a summary of a summary. It should have somewhere else to live.
The long climb
Never invalidating the cache is a fairytale. A fixed context window eventually forces a fold. The invalidation cost is unavoidable. The smaller window is the mechanical outcome.
But that isn’t the hard problem. The hard problem is deciding what gets carried to the next camp. And then the camp after that. And the camp after that.
A long-running agent isn’t maintaining one context window. It’s maintaining a sequence of compressed representations of its own history. History becomes summary. Summary becomes memory. Memory becomes the input to the next summary. Every fold is therefore a judgment about what the agent is allowed to forget.
The engineering challenge isn’t to make the pack infinitely large. It’s to make sure the things that matter aren’t the things left at camp.
The list
- Context Rot: How Increasing Input Tokens Impacts LLM Performance. Chroma. https://research.trychroma.com/context-rot
- Lost in the Middle: How Language Models Use Long Contexts. Transactions of the Association for Computational Linguistics. https://aclanthology.org/2024.tacl-1.9/
- Context editing — https://platform.claude.com/docs/en/build-with-claude/context-editing
- Prompt caching (TTL, 5-min/1-hour): https://platform.claude.com/docs/en/build-with-claude/prompt-caching
- Memory toolm https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool
- Tool reference (tool search / defer_loading): https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference
- OpenAI Compaction guide, https://developers.openai.com/api/docs/guides/compaction
- Compact a response (API reference) https://developers.openai.com/api/reference/resources/responses/methods/compact
- OpenAI Subagents, https://developers.openai.com/codex/subagents
- https://api-docs.deepseek.com/guides/kv_cache/ (DeepSeek Context Caching on Disk)
- Claude Code reverse-engineering: https://barazany.dev/blog/claude-codes-compaction-engine and https://karanprasad.com/blog/how-claude-code-actually-works-reverse-engineering-512k-lines — both trace to the same source
- Codex CLI compaction architecture: https://codex.danielvaughan.com/2026/03/31/codex-cli-context-compaction-architecture/
- OpenCode context management: https://deepwiki.com/sst/opencode/2.4-context-management-and-compaction
- Hermes Agent — context compression: https://hermes-agent.nousresearch.com/docs/developer-guide/context-compression-and-caching
- DeepSeek Harness (GitHub): https://github.com/deepseek-ai/deepseek-harness
Harnesses, Part One: Eager vs. Just-in-Time and Part Two, Cache Economics are on Medium, Towards Data Science.
Written by Jordan Carson, Applied AI Engineer JP Morgan Chase, Asset & Wealth Management.











