Your AI Coding Agent Doesn't Need a Better Prompt
Part 1 · Beyond the Prompt series
The honeymoon with "vibe coding" ends the moment you point an agent at a real, messy codebase. What replaces it is a discipline you have to practice.
The first time an AI agent one-shots a working app from a paragraph of description, it feels like magic. You type a wish, you get software. So you do it again, and again, and for a while the magic holds.
Then you point the same agent at the codebase you actually get paid to work on. Two hundred thousand lines. Five years of decisions, half of them load-bearing and undocumented. A test suite that takes nine minutes to run. And the magic curdles. The agent confidently edits the wrong module, reinvents a utility you already have three of, breaks an invariant nobody wrote down, and hands you a diff that looks plausible and is quietly wrong.
The instinct at this point is to write a better prompt. Add more detail. Be more specific. Try again. That instinct stops scaling fast. The agent's real handicap is how little of your system it can see at once.
The bottleneck is context
It is tempting to treat a struggling agent as a model problem, something the next release will fix. Usually it isn't. The models are already strong enough to write the code you need. What they lack is a faithful picture of your system at the moment they act.
A language model is stateless. Every request starts from nothing, and everything it knows about your task has to fit inside a single finite context window: your instructions, the relevant files, the conventions, the prior steps, the error output. That window is a budget, and it is smaller than your codebase. Fill it with the wrong things and the right things never make it in. Stuff it to the brim and quality degrades anyway, because models attend unevenly to long inputs and important details in the middle get lost.
So the real question becomes “what should the model see when I ask?” rather than “what should I ask for?” That shift, from prompting to managing the context window as a scarce resource, is what actually changes your results.
Context engineering: curating what the model sees
Once you accept that context is finite and precious, a set of moves falls out of it.
You give the agent durable, always-loaded ground truth: the conventions, the architectural rules, the things that are true on every task and should never have to be rediscovered. You pull in the specific files that matter for this change, and leave out the thousands that don't, which is really a retrieval problem. You prune aggressively, because every token spent on something irrelevant is a token stolen from something that matters. And you keep the working context clean as a task runs, so the model isn't reasoning over its own stale dead ends.
That is what context engineering actually is: the deliberate, ongoing work of deciding what enters the window and what stays out, so the model is always operating on a true and relevant picture of the system.
A prompt is a wish. A spec is a contract.
Even a perfectly informed agent can build the wrong thing, beautifully, if the only target it has is a vague sentence. “Add saved searches with alerts” can be satisfied a hundred different ways, and the agent will pick one, commit to it, and present it as finished. You discover the gap in review, or worse, in production.
The fix is to hand agents specifications instead. A spec states, concretely and verifiably, what the feature must do to be correct: the behavior, the edge cases, the acceptance criteria, what is explicitly out of scope. Asking for “a deck” leaves every real decision to the agent. A blueprint settles them up front. The spec becomes the source of truth the code is measured against.
This matters even more as agents get more capable. A more powerful agent given an ambiguous target just produces a more convincing version of the wrong thing.
The loop that makes it repeatable
A spec on its own is a document. What turns it into delivered software is a loop you run on purpose, the same way every time.
You start from durable project rules. You write a spec for the feature. You let the agent turn that spec into a plan, and the plan into small, reviewable tasks. The agent builds one task at a time, against the spec, and each step is small enough that you can actually check it before moving on. Then you verify the result against the acceptance criteria you wrote at the start.
The value of the loop is that each step stays bounded and inspectable. You are never staring at a thousand-line diff trying to reverse-engineer what the agent decided. You are reviewing a small change against a target you defined. That's supervision. Without it you're just cleaning up afterward.
Verification is the other half of the job
Agents are fluent, and fluency reads as competence even when it isn't. An agent will tell you the change is done, the tests pass, the edge cases are handled, with exactly the same confidence whether or not any of it is true. If your verification strategy is reading the summary and nodding, you aren't verifying anything.
The way out is to make correctness checkable by something other than your own optimism. Acceptance criteria become tests. Tests become the target the agent has to satisfy. Evaluations tell you whether the behavior actually holds, repeatably, instead of once by luck. You move from trusting the agent's account of its work to having an independent signal about it.
The hard part is the codebase you already have
Most of the writing about AI coding assumes a blank page. Real work rarely starts there. It starts in a brownfield codebase with existing patterns, existing debt, and existing reasons things are the way they are.
In that setting, the discipline pays off most. You anchor the agent to the patterns that already exist so it extends your system instead of introducing a second, foreign way of doing things. You point it at the services and modules to reuse, by name, so it stops reinventing them. And once more than one person is doing this, it becomes a team practice: shared conventions, shared specs, shared standards for what “verified” means, so the method becomes something an organization runs rather than a trick one developer keeps in their head.
The method outlasts the tools
None of this is tied to a particular vendor or a particular model. It is a way of working: treat context as a finite resource, engineer what the agent sees, write specs instead of wishes, run a bounded loop, and verify against a real target. The tools will keep changing. The discipline is what carries across them.
I spent a long time figuring out how to put all of this together in a way that holds up on production code, and then wrote it down. Beyond the Prompt: Spec-Driven Development and Context Engineering for AI Coding Agents is the full version of this argument, in much more depth than a blog post can hold. It walks through the context window as a resource, the core context-engineering moves, specs and the spec-driven loop, verification and evals, and the realities of brownfield work and team governance, with two worked examples you can clone and follow end to end: a brownfield analytics dashboard and a greenfield issue tracker, both taken from spec to verified feature.
If the wall I described at the top is one you have hit, the book is what I wish I'd had at the time. It's available now in paperback and Kindle. Find it on Amazon here.