Last month I asked an agent to “add a cancellation flow to the billing page.” It shipped a working feature in nine minutes. It also deleted the wrong subscription record, sent the confirmation email before the refund cleared, and stored the cancellation reason as a free-text field nobody could report on. Every one of those decisions was defensible given what I wrote. None of them were what I wanted. The agent did not fail. My prompt did.

That experience is why I now write a spec before I let an agent touch a repo. Spec-driven development is the shift from prompt-and-pray to spec-first: you write down intent, constraints, and acceptance criteria, keep that document in version control, and hand it to the agent as the contract for the task. This post covers how to write a spec an agent can build against, the tooling that formalized this pattern in 2025 and 2026, and the honest cost of doing it.

Why Prompt-and-Pray Breaks Down

A coding agent fills gaps with the most statistically likely choice, not the right choice for your business. When your prompt says “add caching,” the agent picks a cache layer, a TTL, and an invalidation strategy on its own. When it says “make the form accessible,” the agent decides which WCAG criteria count. Multiply that by every unstated assumption in a feature request and you get output that is technically functional and practically wrong.

The failure mode scales with autonomy. A single-file edit from a vague prompt costs you a code review comment. A multi-step agent run across twenty files costs you an afternoon of archaeology. I wrote about the extreme version of this in what happens when unsupervised agents hit runaway loops, and the root cause is the same: the agent had freedom the task never granted. A spec removes that freedom on purpose.

There is also a reviewability problem. If the only record of intent is a chat message, the reviewer has nothing to check the diff against. “Did the agent do what we wanted?” is unanswerable when “what we wanted” was never written down. A spec turns review from taste into verification.

Abstract digital art visualization of a structured technical specification schema radiating organized algorithmic flows into clean modular blocks, no text labels

What a Spec an Agent Can Build Against Looks Like

A useful spec has four parts: intent, context, constraints, and acceptance criteria. Intent is the user-facing outcome in one or two sentences. Context is what the agent needs to know about the existing system. Constraints are the hard rules: libraries you will not add, patterns the codebase already uses, performance budgets. Acceptance criteria are testable statements a reviewer can check one by one.

Here is a real excerpt, trimmed, from a spec I used for the cancellation flow that went wrong the first time:

## Intent
A subscriber can cancel a paid plan from /billing without contacting
support. The subscription stays active until the end of the paid period.

## Constraints
- Use the existing Stripe client in lib/stripe.ts. No new dependencies.
- Follow the repository's server action pattern (see actions/billing.ts).
- No database schema changes. Use the existing subscriptions.status enum.
- Refunds are out of scope. Never call stripe.refunds in this task.

## Acceptance Criteria
1. Cancel button is disabled while the request is in flight.
2. On success, subscriptions.status = "cancel_at_period_end" and the
   UI shows the access end date.
3. The confirmation email sends only after Stripe acknowledges the
   cancellation, using the existing email queue.
4. Cancellation reason uses the predefined enum, not free text.
5. All new code paths have tests mirroring tests/billing.test.ts.

Notice what that spec does. It kills the three bad decisions from my failed prompt before the agent can make them. It names the exact files that establish the patterns to copy. It defines “done” as five checkable statements. The agent’s second run against this spec produced a diff I approved in one pass.

Keep specs short. Mine run 60 to 150 lines for a feature that takes an agent one to three sessions. If your spec needs 800 lines, the task is too big and needs slicing, which I cover below.

Abstract comparative visualization showing chaotic fragmented loops versus an aligned crystalline sequence of geometric verification gates, no text labels

Specs Live in the Repo, Not the Chat

The chat window is where specs go to die. A spec only pays off if it is versioned, reviewed, and updated like code. My convention: durable product behavior specs live in a specs/ directory, one Markdown file per feature, named specs/2026-10-billing-cancellation.md. They go through pull request review like any other change, because a wrong spec is more expensive than a wrong test.

Two repo-level files sit underneath those feature specs and shape every agent run. CLAUDE.md (read by Claude Code) and AGENTS.md (the cross-tool convention documented at agents.md, picked up by most coding agents in 2026) hold the standing rules: how to run the test suite, which commands are safe, code style, directories the agent must not touch. Think of them as the spec for the agent itself. The feature spec says what to build; these files say how work happens here. Holding standing rules in version control also protects against security misconfigurations; our guide on MCP server security hardening details how to fence in tool execution and protect sensitive credentials.

The living-document part matters. When the implementation reveals the spec was wrong, and it will, you update the spec in the same commit as the code fix. A spec that drifts from reality teaches the agent the wrong contract. I treat stale specs like stale tests: a defect, not documentation debt.

The Tooling That Formalized This

This workflow was folk practice in 2024. By 2026 it has names and tools.

GitHub’s Spec Kit is the most direct implementation. It scaffolds a /specify, /plan, and /tasks flow inside your existing agent CLI: you describe the feature, the agent drafts a structured spec, you review and correct it, then it generates an implementation plan and a task breakdown, and only then does it write code. The value is not the templates; it is that the review gates are mandatory steps instead of good intentions.

Kiro, AWS’s agentic IDE at kiro.dev, took the same idea further with requirements in EARS notation (Easy Approach to Requirements Syntax), design documents, and task lists that stay synced to the code. If Spec Kit is a workflow bolted onto your current agent, Kiro is an environment built around the spec as the primary artifact.

You do not need either one to start. I ran this pattern for months with a specs/ folder, an AGENTS.md, and the rule “no agent task starts without a linked spec file.” The tools enforce discipline; they do not create it. If you are still getting the basics out of your assistant, my notes on using AI coding assistants effectively cover the prompting layer underneath all of this.

A Working Loop: Spec, Slice, Review

Here is the loop I run on client work now, and it fits the broader AI-assisted development workflow I have written about before.

First, write the spec yourself. Not the agent. The intent and constraints are the parts you actually know better than the model. You can have the agent interview you to fill gaps, and Spec Kit’s clarify step does exactly that, but the first draft of “what done means” comes from a human.

Second, slice the work. A spec that touches more than one subsystem becomes multiple agent tasks, each referencing the same spec file plus a task-local section. Agents degrade as scope grows; five tasks with tight boundaries beat one task with a wide mandate.

Third, let the agent plan against the spec and push back on the plan. This is the cheapest review you will ever do. Correcting “I will add a new refunds table” in a plan costs one sentence. Correcting it in a 600-line diff costs an hour.

Fourth, review the diff against the acceptance criteria, one by one. This is the whole point: review becomes a checklist, not a vibe. If criterion three fails, you point at the sentence, and the agent fixes against written language instead of your follow-up guess. Pairing crisp specifications with human-in-the-loop agent design guarantees that high-stakes state changes and external communications always halt for human authorization before merging.

Abstract sequential workflow roadmap composed of modular interlocking crystalline stages and translucent inspection portals, no text labels

The output quality also compounds. Code written against a spec with named patterns tends to match the habits in how to write clean code: small functions, existing conventions, no speculative abstractions. Vague prompts produce vague architecture.

The Honest Trade-Offs

Spec-driven development costs real time upfront. I spend 20 to 45 minutes writing a spec for a feature I used to kick off with a two-line prompt. For a task the agent would have nailed anyway, that time is waste. Be honest about which tasks those are: copy changes, dependency bumps, mechanical refactors with tests already in place. Spec those and you are writing paperwork, not software.

The payoff shows up only when the task has ambiguity with consequences: anything touching money, auth, data shape, or user-facing behavior. There, my rework rate dropped hard. Before specs, I rejected or heavily rewrote maybe half of multi-file agent output. Now most diffs land in one or two review rounds. The 30 minutes of writing replaces hours of diff archaeology, and it replaces the worst category of cost, the wrong thing deployed quietly.

Abstract precision engineering sculpture representing structured code reliability and development velocity with balanced interlocking polyhedra, no text labels

Two more trade-offs worth stating. Specs can calcify: teams start writing specs for everything, and the documents become theater nobody reads. And a spec does not make a weak agent strong; it makes a capable agent predictable. You still need tests, review, and the judgment to know when the spec itself was wrong.

The Bottom Line

Prompt-and-pray treats the agent like a slot machine. Spec-driven development treats it like a contractor: a written statement of work, standing house rules in AGENTS.md, and acceptance criteria you verify line by line. Write the spec yourself, keep it in the repo, slice agent tasks against it, and review diffs against the criteria instead of your memory. Start with your next money-touching or auth-touching feature. Write the 100-line spec. My bet is the first diff comes back closer to done than anything you have prompted cold.