Part II · The methodsChapter 3

Ten methods that survive scrutiny

The question Which context-management methods survive scrutiny, why does each work, and what does each cost?

23 min read Core Step 3 of 20 1/6 in this part

In 30 seconds

  • Only ten methods passed four tests: a mechanism, evidence, independence from the others, and a test you can run today.
  • Each method loses something. The loss mode matters as much as the gain.
  • The biggest wins are unglamorous: stable prefixes, fewer tools, and quieter tool output.

You will be able to

  • Describe each of the ten methods in one sentence and name the force it acts on
  • State what each method costs and what it can lose
  • Run the decision test for any method on your own workload
  • Explain why popular advice such as bigger windows or default multi-agent was benched

The ten on one page#

These ten passed the four tests described below; the benched list records what failed and why.

Where each method acts, in the order it acts

The ten methods arranged from prevention before context exists, through prefix, selection, state, compression and topology, to the session lifecycle. PREVENTION M-5 Output shaping before context exists PREFIX M-2 Tool minimisation · M-1 Prefix stability per session, static SELECTION M-4 Structural retrieval · M-3 Just-in-time what unit, and when STATE M-7 Living plan · M-6 Reversible offload survives every boundary COMPRESSION M-8 Semantic-boundary compaction only after offload TOPOLOGY M-9 Sub-agent isolation only for composable work LIFECYCLE M-10 Session discipline the outer loop
Figure 1. The methods layer rather than compete. Three orderings are mandatory: offload (M-6) before compaction (M-8), externalised state (M-7) before resets (M-10), and every method checked against the cache (M-1).
Method Core move Acts on Main loss
M-1 Prefix stability Keep the start of the prompt byte-identical; never edit it mid-session Cache Freshness
M-2 Tool surface minimisation Delete unused tools; load short descriptions, fetch schemas on demand Dilution, confusion A rarely used tool
M-3 Just-in-time retrieval Carry pointers; fetch content at the moment of need Dilution Starvation
M-4 Structural retrieval Follow the reference graph the compiler already knows Dilution Config blind spots
M-5 Output shaping The cheapest token is the one never generated Dilution Hiding a line you needed
M-6 Reversible offload Move it out, leave a self-describing stub Information loss Pointers never followed
M-7 Externalised state A short plan file with a ruled-out section Clash, distraction Drift
M-8 Semantic-boundary compaction Compact when a sub-goal closes, never on a timer or mid-debug Information loss Anything not in the schema
M-9 Sub-agent isolation Delegate only composable work, only with a written contract Dilution Contract loss; total spend
M-10 Session lifecycle Scope sessions, hand off deliberately, never compact twice Position, poisoning Tacit understanding

How the ten were chosen#

Most "context engineering best practices" are restated blog posts. A method made this list only by passing four tests; candidates that failed any one were benched, and the benched list is part of the result.

Test Question
T1 Mechanism Is there a stated reason, in terms of attention, position, cache or information loss, why it changes agent behaviour? "It works for me" is not a mechanism.
T2 Evidence Is there at least one measured result: a paper, a controlled comparison, or a credible account with numbers? Testimonials alone are benched.
T3 Independence Is it more than a special case of a method already on the list? Two variants of one idea count once.
T4 Decidability Can a reader run a test today, on their own workload, to decide whether to use it — and remove it later if it fails?

Every method below follows the same spine — how to do it, why it works, what it costs and loses, and a decision test — plus trouble signs and a worked example where one adds proof. The table above carries each method's claim.

Before any method: measure#

Measure your distribution first. In the composite budget used here, the segment being optimised was not the large one: the instruction file is 4% of the window, while 25% is definitions for tools never called C.

The minimum measurement takes about an hour:

  1. Fresh session, send ., record input tokens — your prefix tax.
  2. Dump tool schemas; count their tokens.
  3. Bucket your three longest recent sessions by segment, with the budget audit template.
  4. List every tool defined and every tool actually called in those sessions.

You are looking for one thing: the largest segment you control. Choose methods against it. A team whose largest segment is tool definitions should read M-2 and stop; adopting all ten is itself an antipattern.

M-1: Prefix stability#

How to do it.

  1. Split context into a stable prefix (system prompt, tool definitions, instruction files, skill descriptions) and a growing body (retrieval, tool results, messages).
  2. Make the prefix deterministic: fixed tool order; no timestamps, session IDs or dynamically assembled rules.
  3. Make context changes append-only wherever possible.
  4. Batch all prefix edits (instruction files, tool configuration) to session boundaries.
  5. Track cache hit rate, and treat a drop like a production incident.

Why it works. The cache reuses the computed state of an unchanged prefix, up to the first changed byte, turning the largest repeated part of the prompt from a per-call cost into a one-time cost. Reported: 85.2% hit rate with about 46,059 tokens reused per request P; at 90%, time to first token typically drops from seconds to under 200 ms and compute cost falls 80–90% P.

The less obvious half: this inverts the cost ranking of context operations. Deleting tokens from the prefix costs money, because it invalidates everything after it for the rest of the session.

Costs and losses. Almost no tokens, but real discipline: dynamic tool selection, per-turn memory rewriting and injected timestamps all break the prefix, which is why this method is usually broken by accident. The loss is freshness — a stable prefix is stale by construction — so put volatile facts in the body (a user turn or tool result), where recency weights them more anyway.

Trouble signs. Hit rate under about 50% on multi-turn sessions — that is an incident. The decision test below fires earlier, at 60%. Cost per turn rising faster than token count. Latency that never improves as a conversation "warms up".

Cost per turn: fewer tokens, far higher bill

Static: 14.9 units per turn. Dynamic: 102.3 units per turn.0306090120Static 38K tool block (120K context)14.9Dynamic 9K tool block (91K context)102.3
Figure 2. Static pruning beats dynamic selection, mostly for cache reasons; the numbers are in the worked example and the data table C.
View data
ConfigurationRelative cost per turn
Static 38K tool block (120K context)14.9
Dynamic 9K tool block (91K context)102.3

M-2: Tool surface minimisation#

How to do it.

  1. List every tool in scope and count its schema tokens.
  2. Count how often each tool was called in your last 20 sessions.
  3. Treat zero-call tools as deletion candidates after a representative sample; verify task coverage and keep rollback.
  4. For what remains, prefer, in order: built-in tools over MCP equivalents (the shell already has grep, find, curl); one general tool over five narrow ones; deferred definitions (short descriptions upfront, schemas on demand); and code execution against an API instead of tool schemas at all.
  5. Scope tools per sub-agent or per task type where the harness allows.
  6. Set a hard budget, for example 20 active tools and 15K definition tokens, and enforce it in review.

Why it works. Tools hurt through two separate channels, and mixing them up leads to the wrong fix.

  • Displacement. Definition tokens are prefix tokens and crowd out work. One popular MCP server measures about 42,000 tokens of definitions P.
  • Selection confusion. More candidates means worse choices, independent of tokens. Accuracy fell from 43% to under 14% as tool count grew S; 19 of 20 at 20 tools became complete failure at 107 S.

Progressive disclosure fixes displacement; code execution fixes both, with the agent writing code against a documented API instead of choosing among schemas. Reported, and vendor-reported means best case: 25,000 tokens of definitions became about 2,500 tokens of descriptions P, and 150,000 → about 2,000 tokens, a 98.7% reduction P.

Costs and losses. A one-time effort, then governance: surfaces grow back because adding an MCP server is one click and its cost invisible; without a recurring audit this regresses within a quarter P. The risk is dropping a tool the agent needed rarely but decisively — a representative zero-call sample plus task-coverage verification guards against it, and removal is reversible. Over-deferral also adds a round trip before each tool's first use.

Trouble signs. Definitions over 20% of the prefix. More than three tools defined for each tool used. The agent choosing an applicable but wrong tool. The agent talking about a capability it never calls.

Details, including the audit procedure, are in chapter 8.

M-3: Just-in-time retrieval#

How to do it.

  1. Pre-load nothing by default. The session opens with the task and the repository, not a briefing document.
  2. Give the agent tools that return locations, not content: ls, glob, grep -l, a symbol index.
  3. Give it tools that fetch one location at a time: read a range, read a symbol.
  4. Encourage narrowing: locate, then inspect, then read. Three cheap steps beat one expensive one.
  5. When information stops being needed, let it fall out or offload it (M-6).

Why it works. Just-in-time retrieval keeps relevance density high: pre-loading maximises recall and pays for it in precision; carrying pointers until the moment of need keeps density high at the cost of a few small round trips. It is especially strong for code:

Property of code Consequence for retrieval
The filesystem is always current An index can be stale; cat cannot
Paths and names carry relevance for free src/auth/session.ts says a lot in five tokens
Needs are discovered by looking The agent often cannot say what to pre-load

The evidence: focused ~300-token prompts beat ~113K-token prompts holding the same answer-bearing material, on LongMemEval S; 5K of targeted retrieval beat a 100K codebase summary P; full-context approaches used 2.68× the tokens of the best managed method and completed fewer tasks S.

Costs and losses. More turns and latency; on a small repository pre-loading may genuinely be cheaper. Just-in-time wins once the repository exceeds a few windows' worth D. The loss is starvation, the most dangerous failure in this research because it is silent: the agent never looks at the file that governs the behaviour and produces a confidently wrong change from a clean-looking transcript. That is why read-coverage audits are mandatory alongside this method.

M-4: Structural retrieval#

How to do it.

  1. Expose structure-aware operations: find a symbol, find its references, outline a file, list imports.
  2. Read symbol bodies by default, not files.
  3. Expand along the reference graph: found the function, now read its callers, not its neighbours in the file.
  4. Optionally keep a compact repository map, a per-file outline of top-level symbols. A 10,000-file repository maps to a few thousand tokens.
  5. Keep grep as the complement, not the competitor.

Why it works. Structural retrieval — by symbols, references, imports and the call graph, not whole files or embedding similarity — works because a file is a storage unit while a symbol is a meaning unit. Reading files to answer symbol questions wastes, by construction, the part of the file you did not need, typically over 90% D.

More importantly, code has exact relevance edges that prose lacks — A calls B, C implements I, test_T tests T — and a language server computes them precisely and keeps them current. Using embeddings to guess at "related code" pays for a worse version of something you already own.

The evidence, stated carefully because it is often misreported: a 2026 study compared grep with vector retrieval across four harnesses on 116 LongMemEval-derived questions. Grep generally won, and the harness mattered more than the retrieval strategy, on identical data S. The discount: the questions are conversational-memory shaped, not repository shaped — the harness finding transfers more confidently than the ranking. A hybrid of semantic search and grep has been reported 12.5% more accurate than either alone P. The synthesis: exact beats approximate when exact is available; approximate helps when you do not know the name of what you are looking for.

Costs and losses. Minutes to hours of setup for a language-server toolkit, and a running process. Token cost is negative. It adds five to eight tools to your budget, which is usually a good trade. The loss is structural blindness: configuration values, environment variables, string-keyed dispatch, database schemas, CI files and feature flags are not in the symbol graph. Always keep grep.

The retrieval architecture this fits into, including when embeddings still earn their place, is chapter 5's subject.

M-5: Output shaping#

How to do it.

  1. Rank commands by token volume across recent sessions. Usually three to five commands make up over 70% of tool output D.
  2. For each, apply in order: quieter flags (npm ci --silent, pytest -q, git diff --stat); filtering (tail, grep -v, jq); redirection (full output to a file, path plus a short preview into context); wrapping (a small script that returns a structured digest).
  3. Cap output with head-and-tail truncation, never middle truncation. The ends carry the command and the error.
  4. Add ignore files so lockfiles, dist/, node_modules/, snapshots and fixtures never enter through globs or diffs.
  5. Make the digest task-aware: a failing test run keeps the trace; a passing one needs one line.

Why it works. Pure density gain with no information loss when done right, because the discarded text contained nothing: "200 passed in 14.2s" is complete; the 4,000 tokens of dots were noise. Reported: 60–90% reduction on common dev commands P and 98% by isolating large outputs in an indexed sandbox P. Since input is 99.75–99.87% of agent token usage S and tool results are the largest input, this is where the money is.

Costs and losses. An afternoon of scripting for the top five commands; near zero afterwards. The real cost is over-filtering — hiding the warning that mattered, like the peer-dependency warning that explains a bug three hours later. The mitigation that works: never delete, always redirect. Full output to a file, digest to context, path included: an irreversible loss becomes a reversible one for about 15 tokens.

Trouble signs. The agent re-running a command with different verbosity flags to see more. That signal is clean and worth counting: a rise means you cut too deep.

M-6: Reversible offload#

How to do it.

  1. Send large tool outputs to files. Return the path, the size and a short head-and-tail preview.
  2. Give every offloaded item a stable identifier: a path, a content hash, or an ID in a manifest.
  3. Expose a recall operation: read by ID, read a range, search inside the store.
  4. At compaction, replace old observations with citation stubs (ID, one-line description, preview) instead of a paraphrase.
  5. Keep a small manifest of what exists and where.

Why it works. Never discard what you can relocate: offload converts irreversible loss into reversible loss, decoupling what is in the window from what is available. The measured result is unusually clean: addressable recall compaction — deterministic, no model call, content-addressed, with recall <id> — against five baselines including sliding window, LLM summary, structured state and RAG S.

Addressable recall versus the best lossy baseline

Needle 8B: 99.0% vs 79.57%. Needle 32B: 99.8% vs 96.67%. LongBench-v2 Hard 8B: 27.47% vs 25.83%. 32B: 32.47% vs 30.87%.0%25%50%75%100%Needle tasks, 8B99%79.57%Needle tasks, 32B99.8%96.67%LongBench-v2 Hard, 8B27.47%25.83%LongBench-v2 Hard, 32B32.47%30.87%
Figure 3. A huge gain on retrieval (+19.43 points on 8B) and a modest one on hard reasoning (+1.6). Offload fixes access to information, not thinking. Claiming more would overstate it S.
View data
BenchmarkAddressable recallBest baseline
Needle tasks, 8B99%79.57%
Needle tasks, 32B99.8%96.67%
LongBench-v2 Hard, 8B27.47%25.83%
LongBench-v2 Hard, 32B32.47%30.87%

It also saved 38.8–80.3% of memory bandwidth versus a sliding window S. The mechanism is not sophistication: nothing was thrown away.

Costs and losses. Stubs are 20–60 tokens each, plus one round trip when recall is needed. Two failure modes: the manifest can grow until it becomes the problem, one level down; and the agent may never recall something it cannot recognise as relevant — a pointer the agent will not follow is equivalent to deletion. A stub must carry enough to make the recall decision, and nothing more:

Stub Can the agent decide?
log_a3f9.txt (14KB) No — nearly useless
log_a3f9.txt (14KB) — npm ci output, 2 peer-dep warnings, exit 0 Yes — actionable

The full offload architecture, including where offloaded files should live, is chapter 6's subject.

M-7: Externalised state, the living plan#

How to do it.

  1. At the start of a task, have the agent write a plan file: goal, constraints, approach, open questions, done and not done.
  2. Rewrite it in place at each meaningful checkpoint. It is a state document, not a log.
  3. Include a ruled-out section: the most valuable and most often omitted part.
  4. Re-read it after every compaction, reset or sub-agent return.
  5. Keep it to 30–80 lines. Longer means the task needed splitting.

Why it works. It attacks clash and distraction at once by treating the plan file, not the transcript, as the state. The transcript is an append-only log of everything that happened, including everything wrong, and the model resolves its contradictions by recency. A plan file is a mutable statement of what is currently true: the wrong thing is gone, not outvoted. It lives on disk, so it survives compaction and resets intact — the only structure in this research that gives deliberate control over what crosses a context boundary. And the ruled-out section counters the most expensive repeated behaviour in agent sessions: trying a failed approach again.

Costs and losses. 300–800 tokens resident, plus a few hundred per rewrite. Read it as a body message, not injected into the prefix, so it stays cache-safe. The loss is drift: a document that stops matching reality is a confidently wrong source, worse than having none. Update at state changes, not on a timer, and include a "last updated at turn N" line so staleness is visible.

The plan-file template is ready to copy.

M-8: Semantic-boundary compaction#

How to do it.

  1. Define close boundaries for your work, and the conditions that suppress compaction:
Compact when a boundary closes Suppress when
A test passes Mid-derivation
A plan item completes Mid-edit
A hypothesis is confirmed or ruled out Stuck
An edit is verified Just after an error
  1. Compact only at boundaries, unless a hard ceiling forces it.
  2. Compact with an explicit schema, not "summarise the above": goal and state; decisions with reasons; ruled-out approaches with reasons; exact strings (errors, versions, paths, line numbers); open questions; and what was verified and how.
  3. Offload first (M-6), so anything dropped is recoverable.
  4. Re-read the plan file (M-7) immediately afterwards.

Why it works. Threshold compaction waits until the context is already full of stale and wrong tokens that have been degrading output for many steps; periodic compaction discards indiscriminately and often fires mid-task. Both naive triggers fail, in opposite directions S. Semantic triggering fires when information is genuinely finished: the 2026 self-compaction work gates on closed reasoning units and preserves verified facts that fixed-interval compaction destroys S.

Why the quality of compaction deserves this attention. Holding the agent fixed and changing only the summariser moved SWE-bench from 49.0% to 55.5% S. Compaction-aware training added +5.5 and +7.0 on SWE-bench Verified and +6.8 and +3.1 on Terminal-Bench 2.0 S. And the damage is mostly variance: on AppWorld, no compression scored 85.7% / 77.4% Pass², prompt-based compaction 71.4% / 59.5%, FIFO 63.7% / 53.0% S.

Costs and losses. A blocking model call per compaction, sometimes tens of seconds S, plus a full cache invalidation — often the bigger cost, and almost never counted. See chapter 10. The loss is anything not in the schema. Compaction is the most lossy operation here and the only one that can invent: a paraphrase can assert what the transcript only hypothesised. That is laundering. Mitigate it with a "verified how" field, verbatim exact strings, and offload.

The full compaction schema, field by field, is chapter 6's subject.

M-9: Sub-agent isolation with a contract#

How to do it.

  1. Identify isolatable work and delegate it to a sub-agent with a fresh context, a narrow tool set and a written contract. Keep the rest in the main thread:
Delegate: bounded, verifiable, small result from a large amount of reading Keep in the main thread
Search, surveys, log analysis, test triage, dependency audits Work that needs shared judgment or interlocking decisions
  1. Write the contract before delegating: inputs, scope, tools, output schema, size cap.
  2. Give the sub-agent only the tools it needs, and take back a structured result, not a transcript: a ranked list of file:line entries with one-line reasons.

Why it works. Isolation converts a large intermediate context into a small result. A search that reads 40 files (60K tokens) to conclude "the retry logic is in client/retry.ts:88" returns 20 tokens to the parent. Reported: about 9K total tokens for a multi-domain query with isolated sub-agents versus 15K with an accumulating pattern P. A parallel research system beat a single agent by 90.2% on an internal research eval P.

The other half, which most write-ups omit. That same system used about 15× the tokens of a chat interaction, and token usage alone explained about 80% of the performance difference P. The gain is real, and it is bought.

Costs and losses. The most of any method here. Each sub-agent pays its own prefix tax. Sub-agents shrink the parent's context at the expense of total spend. If your constraint is cost, this is often wrong. If it is the parent's attention, it is often right. The loss is contract loss: the sub-agent saw something decisive and did not report it because the contract did not ask. Add a "notable observations outside scope" field; it is cheap and recovers a surprising amount.

The full treatment, including the public disagreement between two well-known teams, is in chapter 7.

M-10: Session lifecycle#

How to do it.

  1. One session, one coherent task. New task, new session.
  2. Open well. The first message is the highest-leverage 200 tokens you will write: goal, constraints, relevant paths, definition of done, and what not to do.
  3. Checkpoint at boundaries. Commit, and update the plan file.
  4. Reset instead of arguing. When the context is poisoned or the agent loops, start fresh from the plan file.
  5. Hand off explicitly. End long sessions with a handoff note.
  6. Decide your reset triggers in advance: a second compaction is needed; the agent repeats the same action three times; you find a poisoned fact; the task pivots; the window is over 70% full with a lot left to do.

Why it works. A reset restores the premium position of the prefix, removes every accumulated distractor at once, and is the only way to remove poisoned content from an append-only transcript. A good opener replaces exploratory retrieval — the most expensive thing an agent does — with directed retrieval.

The economics are stark: a reset costs one plan-file read (about 500 tokens) and buys back everything. Continuing a degraded session pays full context on every turn and succeeds less often. The instinct to keep a long session alive is a sunk-cost error.

Costs and losses. Tacit understanding: which approaches feel promising, the codebase's idioms, what the user really meant. Not all of it fits in a plan file. That is the honest argument against resetting aggressively. A better handoff note reduces the loss; the rest is the price.

What was benched, and why#

The popular advice that did not make the list. This table is a result, not an omission.

Candidate Why it is popular Test failed Verdict
"Use a bigger context window" Trivially available T1: no mechanism by which more capacity improves attention; the evidence runs the other way Not a method. Capacity relieves fitting pressure only
Embedding-based code search as the primary retriever Familiar from document search T2: grep generally beat vector retrieval head-to-head S; index staleness is a running cost A complement (hybrid +12.5% P), not the primary. Folded into M-4
Automatic memory extraction ("remember everything") Compelling demos T4: no test tells you whether a memory helped Bench until you can measure recall value
"Be concise" instructions One line, feels free T2: no measured effect on total context Marginal. The real fix is M-5
Per-turn dynamic tool selection Obviously right T1/T2: cache-hostile, often net-negative Bench unless you can prove the cache economics
Multi-agent by default Impressive architecture T4: no test separates decomposable from non-decomposable work without M-9's contract Folded into M-9 with a decision rule
Knowledge-graph project memory Intellectually attractive T2: no coding-specific measured result; high upkeep Watch. Promising across repositories, unproven here
Middle truncation of long output Simple to build T1: removes the region where errors usually are Strictly dominated by head-and-tail
Priming with a codebase overview Feels like onboarding T2: the 5K-versus-100K result and the coherent-text finding (chapter 1) both point against it A small pointer seed survives as an M-3 setting
"Focus" reminders sprinkled through a session Cheap, feels responsive T3: a weaker version of M-7 Use M-7

Two of these, bigger windows and default multi-agent, absorb a disproportionate share of the field's attention and money.

Key takeaways

  1. Measure your distribution before choosing any method.
  2. Static pruning beats dynamic selection, mostly for cache reasons.
  3. Never delete what you can relocate: redirect, offload, stub.
  4. A plan file with a ruled-out section is the only deliberate control over what survives a boundary.
  5. Compact at sub-goal boundaries, at most once, and only after offloading.

Go deeper

Terms used in this chapter

  • Prefix tax — The tokens present in segments 1–4 on each call before any work. Measure them by sending a one-token message in a fresh session; billing depends on cache hits.
  • Prefix caching — Reusing the computed state of an unchanged prompt prefix. Prefix-exact: valid up to the first changed byte.
  • Progressive disclosure — Loading short descriptions first and full content only on demand. Applied to tool schemas, skills and file reads.
  • Just-in-time retrieval — Carrying lightweight identifiers such as paths and symbol names, and fetching content only at the moment it is needed.
  • Relevance density — Tokens that could plausibly be cited in a correct answer, divided by all tokens in context. The working measure of dilution.
  • Starvation — The agent lacks a fact, does not know it is missing, and proceeds on an assumption. A clean trajectory and a wrong answer.
  • Structural retrieval — Retrieving code by symbol, reference and import graph instead of by whole file or embedding similarity.
  • Addressable recall — Compaction that replaces old content with content-addressed stubs the agent can fetch on demand, instead of a paraphrase. Lossless by construction.
  • Clash — A failure mode where the context contains contradictions from different phases and the model resolves them by recency or by blending.
  • Distraction — A failure mode where the agent imitates its own transcript instead of reasoning: re-running, re-reading, re-proposing.
  • Semantic triggering — Compacting on task events such as a sub-goal closing or a test passing, instead of at a token threshold or on a timer.
  • Laundering — Compaction turning a hedged hypothesis into an asserted fact by stripping the uncertainty around it.
  • Sub-agent — A separate agent with its own fresh context, given a bounded task and returning a result to a parent agent.
  • Contract loss — A sub-agent knew something relevant but did not report it because its output contract did not ask.