Guide

Why your AI coding agent needs a spec, not just a prompt

A prompt is consumed: you send it, the model acts on it, and the only surviving record of what you meant is a chat log nobody will open again. A spec is an artifact that sits in the repo, can be read by someone who was not in the room, and can be disagreed with before any code exists. That difference matters most for the failure code review is structurally unable to catch.

The failure is not bad code, it is correct code doing the wrong thing

Reviewers catch code that is wrong on its own terms: the off-by-one, the unhandled null, the query that will not scale. They are much worse at code that is internally correct and answers the wrong question, because the diff has nothing to compare against except the reviewer's private guess at what you wanted.

Say you ask an agent to sync records from an upstream API into your database on a schedule. It paginates, it retries, it logs, the tests pass, the diff reads well. Nobody wrote down that a second run must not re-insert rows the first run already wrote. The failure shows up the first time the schedule double-triggers, and every reviewer who approved was reading the diff correctly.

That requirement was never in the code, so it could never be caught in the code. It had to exist earlier, in a form a person could read and object to. That is what a spec is: not documentation of what you built, but a statement of intent specific enough to be wrong in advance.

A prompt has one reader, once

A prompt lives in the session, is reviewed after the code exists, and is compared against the reviewer's own assumption about it. A spec lives in the repo next to the code, is reviewed before the code exists, and is compared against the written requirement.

A prompt A spec
Where it lives the session the repo, next to the code
When it is reviewed after the code exists before the code exists
What a reviewer compares it to their own assumption about it the written requirement
What disagreement looks like re-prompting until the output changes editing a sentence, and the edit is visible
When the requirement changes a new prompt, nothing recorded a diff of what the intent used to be

The last row is the one people underrate. Months later, when someone asks why the sync is not idempotent, a prompt history gives you increasingly frustrated instructions. A spec gives you a line, a commit, and a name.

Vibe coding is a real workflow, and its limits are in its own description

Vibe coding is a real workflow that fits a weekend build or a throwaway tool, and it fits badly anywhere a second person maintains the result. The limit is in Karpathy's own description of the loop: correctness has been defined as the absence of an error message, and code that runs cleanly and does the wrong thing produces none.

The term comes from Andrej Karpathy, who described the practice in a post on X on 2 February 2025. He was specific about what he does with the model's output:

I "Accept All" always, I don't read the diffs anymore

On failure handling:

When I get error messages I just copy paste them in with no comment, usually that fixes it

None of this needs a sneer. It is an honest description of a workflow that fits a weekend build or a throwaway tool, anything where the cost of being wrong is that you delete it.

It fits badly anywhere a second person maintains the result, and the reason is in the description rather than in the code. If you do not read the diffs and error messages are the feedback channel, correctness has been defined as the absence of an error message. Code that runs cleanly and does the wrong thing produces none, so nothing in that loop would ever surface it.

One footnote, since these lines get quoted constantly: the coining sentence is the opening line of a longer post, and the widely circulated version expands Karpathy's contraction and drops the quotation marks he put around the term, so it is a paraphrase rather than a quote.

The tooling agrees, and it is worth naming accurately

Several shipping tools now put an editable artifact between your request and the code. The common mechanic is not the file format. It is that something reviewable exists before the code, and changing it is cheaper than changing the code.

  • GitHub Spec Kit describes itself as a toolkit to help you get started with Spec-Driven Development. Its CLI installs slash commands into a coding agent so the sequence is specify, plan, tasks, then implement. The commands are namespaced /speckit.* now; write-ups citing bare /specify and /plan describe a pre-1.0 command set.
  • AWS Kiro turns a prompt into three files: requirements.md for user stories and acceptance criteria, design.md for technical architecture, and tasks.md for a trackable plan. Its docs define specs as structured artifacts that formalize the development process for features and bug fixes.
  • OpenSpec, from Fission-AI, is a lightweight Markdown workflow in an openspec/ folder so humans and assistants agree on scope before code. The name is heavily cloned on GitHub, and Fission-AI/OpenSpec is the upstream.
  • Cursor Plan Mode, per its docs: "Plan Mode creates detailed implementation plans before writing any code." You review and edit the plan in chat or as a markdown file, then build from it.

Two projects routinely swept into this category do not claim the label themselves. BMAD-METHOD frames itself as Agile AI Driven Development. Google Antigravity produces reviewable Plan artifacts but never markets itself as spec-driven. Calling either an SDD tool is an outside characterization.

What has to be in it for anyone to disagree with it

A spec that says "build a reliable sync" cannot be disagreed with, because no sentence in it could be false. A useful one is specific enough to be objected to:

  • what the system explicitly does not do
  • the exact shape of the output
  • the observable condition that triggers each tool call
  • what happens when a step fails
  • when it stops

It should also settle the architectural question before you start. Anthropic's engineering post Building Effective AI Agents separates the two shapes plainly: "Workflows are systems where LLMs and tools are orchestrated through predefined code paths." Agents, by contrast, direct their own processes and tool usage. It is often misread as advising against agents. It is not: it recommends a ladder, "finding the simplest solution possible, and only increasing complexity when needed", and it is blunt about the price of climbing too fast, naming higher costs, the potential for compounding errors, and the need for sandboxed testing and guardrails.

That is a decision about intent. It belongs in a document you can argue about on a Tuesday, not in a code path someone discovers in production.

Where this fits if you use Bespoke Prompting

Bespoke Prompting's Agent build type emits a spec in named sections rather than prose, and one section the engine treats as core is the tool registry. Every tool gets a five-part contract: what it does, when to call it stated as a specific observable condition rather than "when needed", what it returns with fields and types, what to do if it fails as a named fallback rather than "handle the error", and one concrete example call. Those are exactly the sentences a colleague can read and say no to before anything runs.

Sources

Suggested internal links