Skip to content
Agent Month

Context engineering for coding agents

Last verified: September 2026· Agentic coding

Ask an engineer why their coding agent produced a confidently wrong change and you will usually hear that the model is not smart enough for the task. Look at the transcript and you will usually find something duller: the agent never saw the file that mattered, or it saw it on step three and by step eleven it had been pushed behind forty thousand tokens of test output. Larger context windows have not made this go away, because the constraint that bites is not capacity but attention and cost. This guide covers how to budget a window, what genuinely earns a place in it, why retrieval beats stuffing once a repo passes a certain size, what to do about long sessions, and how to tell when your context is the thing that is broken.

Context engineering for coding agents
PhotoOrkney Library and Archive shelvesbyVictuallersCC BY 4.0tinted
3
questions per turn
what goes in · in what order · what is dropped
O(n²)
naive agent context
every step re-reads the last
1
job per subagent
narrow brief, short report
Task
what the user asked
Curated context
rules · retrieved files · state
Act · verify
edit, then run the tests
Compact
keep decisions, drop transcripts
The loop that stays cheap: curate before acting, verify with a real signal, and compact by keeping conclusions rather than the raw output that produced them.

The window is a budget, not a bucket

A context window is quoted as a capacity, which invites teams to treat filling it as free until it overflows. It is not free in either of the two ways that matter. It costs money, because input tokens are billed on every single turn and an agent loop re-sends its accumulated context each step, which is why naive agent cost grows with the square of the number of steps rather than linearly. And it costs accuracy, because a model's ability to use a specific fact degrades as the amount of competing material around it grows. Two hundred thousand tokens of capacity does not mean two hundred thousand tokens of equally usable attention.

The practical consequence is that adding context is a trade, not an improvement. Every file you include makes every other file slightly less likely to drive the model's behaviour. Teams discover this backwards: an agent misses something, so they add more to the prompt, which makes the next miss more likely, so they add more again. We have seen rules files grow to several thousand words through exactly this ratchet, at which point the model is reliably following about four of the instructions and quietly ignoring the rest.

So the useful mental model is a budget with a fixed size that you allocate deliberately. Some of it goes to standing instructions, some to the current task description, some to the files the task actually touches, some to the state accumulated so far, and some must be held in reserve for the output. Writing those allocations down, even roughly, changes the conversation from "can we fit this" to "what is this displacing" — which is the question that produces good decisions.

What actually earns a place in the window

Work backwards from the failure you are trying to prevent. Context earns its place when its absence would cause a specific, foreseeable mistake, and not otherwise. The things that clear that bar consistently are: how to run the build and the tests, because without it the agent invents a command and fails in a way it cannot diagnose; the conventions that are not inferable from the code it is about to read; the architectural facts it would otherwise reverse-engineer wrongly; and the explicit list of things not to touch, which is the single most under-supplied category in most repos.

The things that do not clear the bar are equally consistent. A restatement of what the code already says is pure cost, since the agent can read the code. Aspirational descriptions of how the system ought to work mislead an agent that has no way to detect the gap between the document and reality. General programming advice — write clean code, handle errors, add tests — occupies budget to tell a model something it already does by default. And long lists of every module in the repository, common in generated context files, are a retrieval index pretending to be instructions.

There is a sharp asymmetry worth naming: a stale instruction is much worse than a missing one. If the context omits a fact, the agent reads the code and finds out. If the context asserts something false — a command that no longer exists, a pattern the team abandoned last quarter — the agent trusts it and builds on it, and the resulting failure is confusing because the transcript looks reasonable throughout. This is the argument for keeping context files short: not elegance, but the fact that you can only keep a short document true.

Context files: writing one that stays true

The file your tooling reads on every session — CLAUDE.md, AGENTS.md, a rules file, whatever the tool calls it — is standing context, paid for on every turn of every session forever. That pricing should shape what goes in it. Reserve it for things that are true across all tasks and that the agent cannot cheaply discover: the commands, the conventions that surprise people, the invariants, the prohibitions. Anything task-specific belongs in the task description, and anything discoverable belongs in the code.

Keep it maintained by treating it as a debugging artefact rather than documentation. The healthy loop is: the agent makes a mistake, you correct it once, and if you expect that mistake to recur you add one line to the file. The unhealthy loop is writing the file once at the start of the quarter and letting it rot. A good test is to read the file cold and ask whether every line is still true today; in most repos that have had one for a few months, several lines are not.

Structure matters more than length within the length you have chosen. Put the commands near the top, because they are consulted most. Make prohibitions unmistakable and specific — "do not edit anything under generated/, it is rebuilt from the schema" beats "be careful with generated files", because the second requires the agent to guess which files qualify. Where your team exposes internal systems over MCP, say which server answers which kind of question, so the agent reaches for the tool instead of guessing around the gap. And if your repo is a monorepo with genuinely different conventions per area, prefer several small scoped files near the code over one large file at the root that is mostly irrelevant to any given task.

Retrieval beats stuffing, past a certain size

Below some repository size, the cheapest strategy is to let the agent read what it wants: grep, open a few files, proceed. Above it, that strategy degrades badly, because the agent spends its budget discovering where things are rather than changing them, and the exploration transcript itself becomes the bulk of the context. The transition point is not a file count so much as a property of the codebase — it arrives when a competent engineer could no longer guess which file to open from the name of the task.

The fix is the same one that makes repositories pleasant for humans: make location inferable. Predictable directory structure, names that describe responsibility rather than history, and module boundaries that mean something turn retrieval into a single confident lookup rather than a search. This is why context engineering and codebase readiness are the same subject approached from two directions; a legible repository is one where the right context is cheap to assemble.

Where that is not yet true, lean on tooling that narrows before it reads. A symbol index or a language server gives an exact answer to "where is this defined and who calls it" for a fraction of the tokens a text search costs. Retrieval over documentation and tickets helps when intent lives outside the code. The principle in both cases is to spend a small, bounded number of tokens on a precise lookup rather than an unbounded number on exploration — and to put the result in context, not the search that found it.

Long sessions, compaction, and what to keep

Every long-running agent session eventually hits the same wall: the accumulated transcript of everything it has done crowds out the task it is doing. Tool output is the usual culprit, and test output is the worst offender, because a failing suite can emit more tokens in one call than the entire source file under repair. The naive remedies — truncate the oldest turns, or summarise everything — both fail, the first by dropping the original task statement and the second by blurring precisely the specifics that mattered.

The better frame is that compaction should keep decisions and discard evidence. What the agent needs to carry forward is the task, the constraints it has learned, the changes it has already made, and the conclusions it drew — "the failure is in the date parser, not the API client" — not the fifteen thousand tokens of stack traces that led there. Written that way, a compacted state is often a few hundred tokens and loses almost nothing operationally. It is also worth trimming tool output at the source: return the first and last portion of a long test run rather than all of it, and the compaction problem gets much smaller before it starts.

There is a structural alternative that is usually better than doing this well, which is not letting sessions get long. Break the work into tasks that each fit comfortably in a fresh window, with the repository itself as the shared state between them. A task that ends with a commit and a clear description leaves behind context that the next session can pick up for almost nothing, because it is written in the form the agent is best at reading. Long sessions are often a sign that the work was not decomposed, not that the window was too small.

Subagents as a context isolation device

The most reliable way to keep a context clean is to do the messy work somewhere else. A subagent given a narrow brief — find where this behaviour is implemented, run the suite and report which tests fail and why, check whether this pattern appears elsewhere — can burn as much context as it needs inside its own window and return a short answer to the parent. The parent pays for the answer, not the search. This is why isolation generally beats compression: you never accumulate the material you would later have to compact.

It works when the brief is genuinely narrow and the return value is genuinely small. It fails when teams use subagents as a general parallelism device, spawning several to write code in different parts of the system at once. Then each holds a partial view, none can see the others' changes, and the parent gets three plausible reports that are mutually inconsistent. The distinction that holds up in practice is that investigation parallelises well and modification does not — reads are independent, writes are not.

Specify the return format explicitly, because an unconstrained subagent tends to return a narrative of what it did rather than the answer, and a narrative is exactly the bulk you were trying to avoid. "Report the file and line, the failing assertion, and one sentence on the cause" produces something a parent can act on in fifty tokens. It is worth being this prescriptive; the value of the whole pattern lives in the size of the report.

How to tell your context is the problem

There are a few signatures worth learning to recognise, because they point at context rather than capability. The agent re-reads files it has already read, which means earlier content has been evicted or buried. It asks a question the rules file answers, which means the file is too long to be attended to or the answer is phrased ambiguously. It invents a command or a helper that does not exist, which usually means the real one was never in the window. It contradicts a decision it made ten steps earlier, which means the decision was in the evidence that got compacted away.

Two more are specifically about cost. Steadily rising tokens per step across a session means the loop is accumulating rather than curating, and is the fingerprint of the quadratic pattern. A sudden collapse in prompt cache hit rate means something dynamic got into the stable prefix — a timestamp, a session identifier, a file list that reorders — and the fix is usually to move that one item further down the prompt rather than to change anything about the content.

The diagnostic that settles it is cheap: take a failing task, hand-assemble the context you believe the agent needed, and run it once in a fresh window. If it succeeds, the model was never the constraint and your effort belongs in curation. If it fails with perfect context, you have a genuinely hard task and should decompose it or keep a human in the loop. We run this before any deeper work on an agent setup, because it separates the two failure modes in about ten minutes and they have completely different remedies.

Where context engineering stops helping

Curation cannot supply information the repository does not contain. If the reason a change is hard is that the intent was never written down and the last person who knew has left, no arrangement of tokens recovers it. The honest move there is to write the missing thing down once — a short design note, a decision record — and treat that as the work, rather than iterating on prompts around a gap.

It also cannot fix a task that is genuinely underspecified. A significant share of agent failures we look at turn out to be requests that two competent engineers would have implemented differently, where the agent picked one reading and committed to it. More context does not resolve an ambiguity; a decision does. The tell is that the output is defensible but not what was wanted, rather than wrong.

And there is a floor set by the structure of the codebase itself. In a repository where a change to one module routinely breaks two others with no type or test to catch it, the context required to be safe is the whole system, which does not fit and would not be attended to if it did. At that point the leverage has moved out of the prompt and into the code: boundaries, tests, types. Context engineering makes a legible repository much cheaper to work in; it does not substitute for making one legible.

How to audit your agent's context

  1. 1
    Step 1

    Capture what the agent actually saw

    Take one failing task and dump the resolved context for each turn, not the template. Count tokens by category: standing instructions, task description, file contents, tool output, accumulated transcript. Most teams are surprised by the split, and the surprise is usually tool output.

  2. 2
    Step 2

    Run the perfect-context test

    Hand-assemble the context you believe the task needed and run it once in a fresh window. Success means curation is your problem and the model is not. Failure with ideal context means the task needs decomposing or a human in the loop. Ten minutes, and it settles which remedy applies.

  3. 3
    Step 3

    Read your context file cold and delete

    Go line by line and ask whether each is still true and whether its absence would cause a specific mistake. Cut restatements of the code, aspirational architecture, and general programming advice. Fix anything stale first — a false instruction does more damage than a missing one.

  4. 4
    Step 4

    Trim tool output at the source

    Cap what long-running commands return: the head and tail of a test run rather than every line, a summary of a large diff, counts rather than full listings. This shrinks the compaction problem before it starts and is usually the single biggest reduction available.

  5. 5
    Step 5

    Move investigation into subagents

    Identify the searching and reporting steps and give each to a subagent with a narrow brief and an explicitly specified, short return format. Keep modification in one place. The parent then pays for answers rather than for the exploration that produced them.

  6. 6
    Step 6

    Watch tokens per step and cache hit rate

    Instrument both and treat them as the standing signals. Steadily rising tokens per step means the loop accumulates instead of curating. A collapsed cache hit rate means something dynamic entered the stable prefix — find it and move it later in the prompt.

Frequently asked questions

What is context engineering?

It is the practice of deciding what information goes into a model's context window on each turn, in what order, and what is deliberately left out. For coding agents it covers standing instructions, the task description, which files are retrieved, how tool output is trimmed, and how accumulated state is compacted. It replaced prompt engineering as the main lever once models got good enough that the phrasing of an instruction mattered less than whether the relevant material was present at all.

Do bigger context windows make this unnecessary?

No, for two reasons. Input tokens are billed on every turn and an agent loop re-sends its accumulated context each step, so a filled window is a recurring cost that grows with the square of the step count. And a model's ability to act on a specific fact degrades as competing material accumulates around it, so quoted capacity is not the same as usable attention. Bigger windows raise the ceiling; they do not change the economics of filling one.

How long should a CLAUDE.md or AGENTS.md file be?

Short enough that you can keep every line true. That is the binding constraint, not a token count. The content that earns its place is the build and test commands, conventions that are not inferable from the code, architectural facts the agent would otherwise reverse-engineer wrongly, and an explicit list of what not to touch. Restating the code, describing how the system ought to work, and general programming advice all cost budget and return nothing.

Why does my agent keep re-reading the same files?

Because the earlier read has been evicted or buried under later tool output, most often test or build output that returned far more text than the source file it was checking. Cap what long-running commands return — head and tail rather than everything — and compact by keeping conclusions rather than the evidence that produced them. Re-reading is the clearest single signal that the loop is accumulating instead of curating.

When should I use subagents?

For investigation, not modification. A subagent with a narrow brief can burn as much context as it needs inside its own window and return a short answer, so the parent pays for the answer rather than the search — which is why isolation generally beats compression. Parallel subagents writing code in different parts of the system tends to fail instead: each holds a partial view, none sees the others' changes, and you get plausible but mutually inconsistent results.

How do I know whether the problem is context or the model?

Run the perfect-context test. Take a task the agent failed, hand-assemble the context you believe it needed, and run it once in a fresh window. If it now succeeds, the model was never the constraint and the work belongs in curation. If it still fails with ideal context, the task is genuinely hard or underspecified and needs decomposing or a human decision. The two failure modes look identical in a transcript and have completely different remedies.

What is the relationship between context engineering and codebase readiness?

They are the same problem from two directions. Context engineering is cheap in a repository where module boundaries are clear, names describe responsibility, and tests give a fast verification signal — because the right context is then a small, confident lookup. In a repository where a change to one module silently breaks two others, being safe requires the whole system in context, which neither fits nor would be attended to. Past that point the leverage moves out of the prompt and into the code.