PROJECT 4
×00

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 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 up a random idea and boom, you get software.

Then you point the same agent at the codebase you actually get paid to work on. 200,000 lines of code, a test suite that takes 9 minutes to run, and 5 years of decisions, with half of them undocumented. That vibe-coding honeymoon just hit an iceberg. The agent confidently edits the wrong module, reinvents a utility you already have 3 of, breaks business logic nobody wrote down, and hands you a diff that looks plausible, yet is quietly wrong.

The instinct at this point is to write a better prompt and add more detail. You could be more specific and try again. That thinking stops scaling fast. The agent's real handicap is how little of your system it can see at once.

The bottleneck is context

First reaction is to look at a struggling agent as a model problem, something the next release will fix. That assumption varies quite a bit. The models are already strong enough to write the code you need. What they lack is an exact 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 pretty fast, because models work 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 is what actually changes your results.

Context engineering: curating what the model sees

Once you accept that context is finite and every inch of it valuable, a set of moves falls out of it.

You give the agent durable, always-loaded truth: the conventions, the architectural rules, the things that are true on every task and should never have to be resaid. 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 compact aggressively, because every token spent on something irrelevant is a token stolen from something that matters. You also keep the working context clean as a task runs, so the model isn't reasoning over its own stale reasoning.

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 and task at hand.

A prompt is asking for something, where a spec is a contract defining the ask.

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 mark 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 “an app" 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 bound to a small task. 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

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 like having 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 legacy codebase with existing patterns, tech debt, and TODOs that no one will touch.

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. Making this a team practice is the biggest benefit: 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 basic prompts, run a bounded loop, and verify against a real target. The tools will keep changing, but the mindset can persist.

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, 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 2 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.

Beyond the Prompt by Chris Tagliaferro: brilliant in demos, lost in your real codebase. View the book on Amazon

Beyond the Prompt · paperback & Kindle