Prompt and context engineering
Prompt engineering is wording the request well, and context engineering is the larger discipline of deciding what information the model gets to see at all.
Prompt engineering is the craft of wording a request so a model understands what you want. Context engineering is the larger discipline of deciding what information the model gets to see in the first place. Wording matters, but what you put in front of the model matters more, and for real work the second question is where the results are won.
Prompting basics
Start with the smaller idea, because it is the one most people meet first. A prompt is the text you send to a model, and prompt engineering is the practice of shaping that text to get a better answer. Since a model responds only to what it reads, small changes in how you ask can produce large changes in what you get. A vague request yields a vague answer. A precise one yields a precise answer. None of this is magic. It is just that the model takes your words literally as the whole of your intent.
A few reliable techniques do most of the work. The first is clear instructions. Tell the model exactly what you want, in what form, with what constraints. Compare fix this code with fix the off-by-one error in this loop and return only the corrected function. The second is fluent and adds nothing to guess at.
The second technique is examples. Instead of describing the output you want, show one or two. If you want data pulled into a particular shape, include a small sample of input paired with the exact output you expect, then give the real input. The model is a pattern matcher, so a concrete example of the pattern is often worth more than a paragraph describing it. This is sometimes called giving the model a shot or two at seeing the pattern before it tries.
The third is roles and framing. Telling the model to answer as a careful code reviewer who flags edge cases nudges it toward a certain manner and level of care, because it steers which patterns from training the response draws on. A role is not a personality trick. It is a compact way to set expectations about tone, depth, and what to pay attention to.
These techniques are genuinely useful and worth learning. On a self-contained task, where the model already has everything it needs and you are mainly steering how it responds, good wording can be the whole difference between a poor answer and a good one.
The shift from wording to information
Prompt engineering has a ceiling, and you hit it the moment the task depends on facts the model does not have. No amount of careful phrasing can make a model tell you about code it has never seen. You can ask, in the clearest, most expertly worded prompt imaginable, how does our payment retry logic handle a timeout, and if the code for that logic is not in front of the model, the clarity of the question changes nothing. The model will either say it does not know or, worse, invent a plausible answer. The bottleneck was never the wording. It was the missing information.
This is the shift that separates a beginner from someone who gets consistent results. The beginner, faced with a bad answer, reaches for better words: rephrase, add emphasis, try again. Sometimes that helps. Often it does not, because the real gap is not in how the question was asked but in what the model could see when it answered. The experienced move is to stop editing the question and start editing the information: what facts does this task actually require, and are they in front of the model.
Recall why this must be so. A model is frozen at training time and knows nothing specific to you, and it works only from what sits in its context window for the current request. So the specific facts a task needs have to be delivered through the window. Wording arranges the furniture in the room. But if the thing you need is not in the room at all, no arrangement helps. First you have to bring it in.
When the answer is wrong, the beginner rewrites the question. The expert asks what the model could see when it answered, and fixes that instead.
What you put in matters more than how you phrase it
Put the two levers side by side and weigh them honestly. Clever phrasing over the wrong information gives you a well-worded wrong answer. Plain phrasing over the right information gives you a correct answer. Between a beautifully engineered prompt with the wrong facts and a blunt prompt with the right facts, the blunt one wins almost every time. The information is the larger lever by a wide margin.
This is not an argument to write careless prompts. It is an argument about where to spend your attention. Getting the wording roughly right is quick and has a modest payoff. Getting the right information into the window is harder and has a much bigger payoff, especially as tasks grow. The reason it is harder is the same reason it matters. On a large problem you cannot just paste everything. The context window is a limited budget, and reliability fades as it fills, so you have to choose a small, precise set of facts out of a very large pool. Choosing well is the actual work.
That act of choosing is context engineering: deciding what information the model gets to see for a given task, and just as importantly what it does not. It is a design problem, not a wording problem. What are the few facts this request truly depends on? Where do they live? How do I get exactly those into the window, current and complete, without drowning them in irrelevant text? Prompt engineering asks how do I say this. Context engineering asks what should be here to say it about.
Why this is the real lever for coding agents
Nowhere does this matter more than with coding agents, the systems that use a model to read, write, and change software across a real codebase. A codebase is enormous and, more to the point, its meaning lives in the relationships between files rather than in any one file. The facts a coding task depends on are scattered: the function you are changing, the places that call it, the shape of data it returns, the config that drives it, the other file that has always changed alongside it. Almost none of that is in the model’s frozen knowledge, and far too much of it exists to fit the window all at once.
So the quality of a coding agent is decided, more than by anything else, by how well it selects which slice of the codebase to place in the window for the task at hand. Pick the right slice, the connected handful of facts that actually bear on the change, and even a modest model does solid work. Pick the wrong slice, or pick by pasting whole files and hoping, and even the strongest model edits code that looked relevant instead of code that was, and fails in the quiet way that is hardest to catch.
This reframes what improving a coding agent even means. The instinct is to want a smarter model. Often the larger gain is in better context: a better answer to what should the model see for this task. The model supplies general skill. The context supplies the specific truth about your system. Between two agents on the same model, the one that assembles context better will win, because it is feeding a sharper picture of reality into the same intelligence.
Between two coding agents built on the same model, the one that chooses what the model sees will win. Context is the lever, not the size of the model.
A worked example of the two levers
Take one task and run it through both levers. The task: add rate limiting to an endpoint in a service you do not know well. A pure prompting approach polishes the wording. You write a careful request naming the endpoint, describing the limit you want, specifying the error to return, and asking for clean, well-commented code. It is a genuinely good prompt. And the model still cannot do the job well, because it does not know how this service is built: what framework handles routing, whether a rate limiter already exists somewhere, where shared middleware lives, what conventions the codebase follows. So it invents a plausible version against generic assumptions, and the result fights the real project in a dozen small ways.
A context-first approach spends its effort elsewhere. The wording can stay plain: add rate limiting to this endpoint. But before asking, you assemble the facts that actually decide the answer: the endpoint’s real handler, the existing middleware it already passes through, a rate-limiting helper the project turns out to have already, and the convention the codebase uses for returning errors. With those few true facts in the window, even a blunt request produces code that fits: it reuses the existing helper instead of inventing one, follows the real error convention, and slots into the middleware that is already there.
The gap between the two outcomes is not phrasing. Both requests asked for the same thing. The difference is entirely in what the model could see. That is the whole case for context engineering in a single example: the lever that moved the result was the selection of facts, not the choice of words.
Doing context engineering by hand, and its limit
On a small task you can do context engineering yourself, and you should. You know the one function that matters, so you paste it, plus a sentence about how it connects to the rest, and you leave everything else out. That is context engineering in miniature, done by a human who already holds the relevant part of the map in their head. It works precisely because the scope is small enough to fit in a person’s memory.
The approach breaks down as the system grows, and it breaks down for a sharp reason. To select the right slice by hand, you first have to know which slice is right, which means you already have to understand the web of relationships well enough to name the relevant few facts out of a million. On a large, unfamiliar codebase you do not have that map, and building it for every task is most of the work you were hoping the agent would help with. You are back to the original problem: the meaning is in the connections, and neither you nor the model can see them just by looking at files.
What you actually want is for the selection to be done for you, automatically and reliably: a system that, given a task, works out which facts in the codebase bear on it and assembles exactly those into the window, current, connected, and lean. That is a real engineering problem in its own right, distinct from the model and sitting between you and it.
Toward a dedicated context layer
Follow the argument to its end. Prompting is worth doing, but its ceiling is low once facts are missing. Context engineering is the larger lever, and for anything the size of a real codebase it cannot be done well by hand. So the natural conclusion is to build a dedicated piece of software whose entire job is to decide what goes into the model’s window for each request: holding a map of the system, working out what a given task depends on, retrieving exactly those facts, and handing them to the model in a form it can use. That dedicated piece is the idea of a context layer, and it is where these threads come together.
The pieces you would need to build it are the surrounding concepts. The hard budget it works against is the context window. The technique for pulling the relevant facts out of a large store on demand is retrieval-augmented generation. And the reason all of this pays off in practice, rather than in theory, shows up most clearly in agentic coding, where an agent working across a real codebase lives or dies by the quality of the context it is given. Prompt engineering got us thinking about how to ask. Context engineering is the bigger discipline of deciding what the model should know when we ask, and it points straight at building a layer dedicated to answering exactly that.
Connected concepts
Where this sits
