Context Engineering: The Discipline After Prompting
4 min read · updated August 3, 2026
“Context engineering” sounds like a rename of prompt engineering by people who wanted a newer word. It is not. There is a clean boundary between them, and it is the boundary between writing a string and writing the function that decides which strings exist.
A definition with a function signature
Context engineering is the design of the code that assembles a model’s input on each request. Not the wording of any one part of that input — the selection, sizing, ordering and eviction of all of the parts, under a fixed capacity and a non-zero price per token.
The definition is easiest to hold as a signature. Somewhere in every non-trivial LLM application there is a function shaped like this, whether it was designed or grew:
assembleContext( sessionState, // everything the app knows about this run request, // what the user or the loop just asked for limits // window size, reserved output, price per token ) -> Message[]
If that function is three lines that concatenate a system prompt and an ever-growing message array, you have not avoided context engineering. You have shipped one particular policy — keep everything, ordered by time, evict nothing — and you will meet its failure modes on schedule. Context engineering is the practice of making that function a deliberate object with a stated policy, rather than the residue of whatever the framework’s default was.
Where prompt engineering stops
The line is worth drawing sharply because the two disciplines fail differently and are fixed by different people.
| Question | Description |
|---|---|
| prompt engineering | Given that this text will be in the window, how should it be worded? Instruction phrasing, examples, output format, role framing, delimiters. The artefact is a string, usually in version control, ideally with evals attached. |
| context engineering | Given a window that fits N tokens and this session's accumulated state, which texts get to be in the window at all, at what size, in what order, and what leaves when something new arrives? The artefact is a function plus a policy. |
A concrete test: if you can fix the bug by editing a string in a file, it was a prompt problem. If the string is already correct and the model never saw it — because a retrieval step returned nine documents and the ninth got truncated away, or because forty turns of history pushed it out, or because a tool returned 40,000 tokens of JSON and the truncation ran from the top — it was a context problem. The two look identical from the outside. Both present as “the model ignored my instruction.”
This is also why the disciplines do not compete. A perfectly worded system prompt that is evicted at turn thirty is worth nothing, and a flawless allocator feeding a badly worded instruction is worth nothing either. For the wording half, the system prompt placement rules and long-prompt structuring conventions are the neighbouring cluster’s subject and are not repeated here.
The four questions an assembler answers
Every assembler answers all four, explicitly or by accident. Writing them down is most of the discipline.
- Eligibility — what is even a candidate? The session may hold a hundred past turns, twelve tool schemas, four retrieved documents and a 200-file repository. Almost none of it is relevant to this request. Eligibility is a filter, and it runs before any sizing decision, because filtering a candidate out is free and shrinking it is not.
- Allocation — how much room does each part get? The window is a fixed budget with a mandatory reservation for output. Splitting the remainder between system, tools, history and retrieved material is an allocation problem with floors and priorities, and it is solvable in about forty lines.
- Ordering — where does each part sit? Identical content in a different order is a different request. Position affects what the model attends to, and it also decides whether a prompt cache can be reused at all, which are two pressures that pull in opposite directions.
- Eviction — what leaves when the next thing arrives? This is the one that is almost always implicit. “Drop the oldest messages” is a policy; it is just rarely a considered one, and it is the policy most likely to delete the turn where the user stated the requirement everything else depends on.
Why this became a job
Three things happened at once. Applications stopped being single-turn. A one-shot classifier has no context problem at all — the input is whatever you were given, every time. A forty-turn assistant or a multi-step agent accumulates, and accumulation under a fixed ceiling is by definition an allocation problem.
Second, tools started returning bulk. A model that can call a search API, read a file and query a database now has three sources that can each produce more tokens than the entire conversation preceding them. Nobody writes those payloads by hand, so nobody was reviewing their size until the window filled.
Third, the economics stopped being negligible. Every turn re-sends the whole history, which makes the cost of a long conversation grow with the square of its length rather than linearly — the arithmetic is worth doing once. At that point what is in the window is a budget line, and budget lines get owners.
What the code looks like
A designed assembler tends to converge on the same skeleton, which is a useful thing to recognise because it means the pieces are separable and individually testable:
const blocks = [ ...gather(sessionState, request), // eligibility ]; const budget = allocate(blocks, limits); // allocation const sized = blocks.map(b => b.fit(budget[b.id])); // shrink or drop const ordered = order(sized); // ordering return render(ordered); // to Message[]
Four pure functions and a renderer. gather is business logic. allocate is arithmetic. fit is per-block and is where compaction, truncation and summarisation live. order is a policy with two competing objectives. None of them needs a model to test, which matters more than it sounds: it means the part of your application most likely to cause an inexplicable failure is the part you can unit-test deterministically.
The rest of this cluster is those functions, one at a time — the allocator, compaction that keeps decisions, ordering and an eviction policy with a priority order.