Why your AI coding agent needs a spec, not just a prompt
Published 26 September 2026
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/specifyand/plandescribe 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
- Andrej Karpathy (@karpathy), post on X coining "vibe coding", 2 February 2025: https://x.com/karpathy/status/1886192184808149383
- Anthropic, "Building Effective AI Agents": https://www.anthropic.com/engineering/building-effective-agents
- GitHub, "Spec Kit": https://github.com/github/spec-kit
- AWS, "Kiro": https://kiro.dev/ and https://kiro.dev/docs/specs/
- Fission-AI, "OpenSpec": https://github.com/Fission-AI/OpenSpec
- Cursor, "Plan Mode": https://cursor.com/docs/agent/plan-mode
- BMad Code, "BMAD-METHOD": https://github.com/bmad-code-org/BMAD-METHOD
- Google, "Antigravity": https://antigravity.google/ and https://antigravity.google/docs/home