-- online Search!

Spec-Driven Development

by kirupa   | filed under AI Fundamentals

Odette, who runs the kitchen at the Crumb & Co. bakery, asks Wren, the bakery's web developer, to let customers reserve a pickup slot on the website. Wren types one sentence into a coding agent, and twenty minutes later there's a slot picker on the order page and every test is green. Then Saturday arrives, and 14 orders are waiting to be picked up at 9:00. The kitchen can pack 6 in that slot.

The agent didn't do a bad job. It did a very good job of building what it guessed Odette wanted. One popular way to close that gap is called spec-driven development, where we write down what we want, including what done means, before an agent writes any code. We'll look at what that means, the tools built around it, whether it's still needed now that agents plan on their own, and how to make sure the result is good.

Onwards!

One Sentence, Lots of Gaps

We met Wren in Agent Frameworks, and an agent fixed this same pickup code in How an Agent Like Claude Code Works. Here's everything Wren typed:

Add a way for customers to reserve a pickup slot on the website.

That feels complete to Wren, who carries a whole bakery's worth of context around. The agent only has the sentence and the code. Here are some of the questions hiding underneath it:

Above the waterline is what Wren typed: Add a way for customers to reserve a pickup slot on the website. Below the waterline is what nobody said: how many orders fit in one slot, how late someone can book, whether they can move or cancel, what happens when two people want the last spot, whether Biscuit sees the same slots, and what the confirmation should say.

Odette could answer every question below the line in about a minute. The agent can't ask her, so it answers them itself with whatever seems most likely. We saw a tiny version of this in Structured Outputs with JSON Schemas, where a model that had to fill in a pickup date wrote a believable one nobody had given it. A coding agent does that with dozens of decisions at once.

What the Agent Built

The agent read the order code, added a reservations table, built the slot picker, and wrote eleven tests that all passed. Along the way, it guessed that any number of orders can share a slot, that a slot starting in five minutes is fair game, and that nobody needs to cancel. Here's how the first Saturday filled up:

Each box is one order reserved for a Saturday pickup slot. The 9:00 slot has 14 orders and the 11:00 slot has 5. A dashed line after the sixth box marks what the kitchen can pack per slot, 6 orders, so the 9:00 slot has 8 more orders than fit.

Look at the 9:00 row. The kitchen can pack 6 orders, and 14 customers reserved it. So how did every test pass? The agent wrote its tests by looking at its own code, so they checked that the code did what the code does. Nobody had written down that a slot holds 6 orders, so no test could check for it.

The usual next move is to prompt again: limit each slot to 6. Then again for late bookings, and again for cancellations. Andrej Karpathy named this prompt-and-see style vibe coding in February 2025. It's a lot of fun for a weekend project, but for a feature real customers depend on, every round is another chance to guess.

What Spec-Driven Development Means

The idea is to answer those questions on purpose, before the agent starts. We write a short spec (short for specification) that says what to build and why, how it should behave, its constraints, and how we'll know it's done. That last part is a list of acceptance criteria, statements about the finished feature that are either true or false. The agent builds from the spec, and we measure the result against it.

Wren and Odette spend fifteen minutes on it. Here's what they end up with:

# Spec: Reserve a pickup slot

## Why
Saturday mornings are chaos. Odette wants to know how many
orders to pack for each slot before the doors open.

## What
- A customer with a paid order picks one pickup slot for it.
- Slots come from the existing pickup hours table.
- Biscuit's check_pickup_slots tool shows the same open slots.

## Constraints
- Each slot holds at most 6 orders.
- No new libraries. Reservations live in the orders table.

## Out of scope
- Delivery, payments, and changing the pickup hours.

## Acceptance criteria
AC1  A slot with 6 reservations isn't offered to anyone.
AC2  If two customers race for the last spot, exactly one gets it.
AC3  Slots that start in under 2 hours can't be reserved.
AC4  A customer can move or cancel until 2 hours before the slot.
AC5  The confirmation shows the day, the time, and the order number.
AC6  The confirmation sounds warm, like the rest of the site.

Every section answers something the agent would otherwise guess. The Why tells it what problem Odette is solving, so its small decisions lean the right way, and Out of scope keeps it from helpfully redesigning checkout. Notice what isn't there, too. Nothing says which files to edit or how to stop two customers grabbing the same spot. The spec covers the what and the why, and the agent works out the how.

That split should sound familiar. Back in the Introduction, we saw that agents are taking over the how, while people spend more time on the what, the why, and the goals. A spec is where that part of the job gets written down. When GitHub launched its spec toolkit, its team suggested treating agents less like search engines and more like "literal-minded pair programmers".

An Old Idea With a New Reader

Writing down what we want first is about as old as programming. Teams have written design docs for decades. In 1999, Leslie Lamport published TLA+, a language for describing how a system should behave precisely enough that a tool can check it. Kent Beck, who wrote the 2002 book on test-driven development, says he "rediscovered" it in an old book that told programmers to type in the output tape they expected, then program until the real output matched. And in 2009, Rolls-Royce engineers published EARS, a requirements style they worked out from the rules for a jet engine's control system. Here's how those line up:

A timeline. For decades, design docs read by people. 1999, TLA+, from Leslie Lamport. 2002, test-first development, in Kent Beck's book. 2009, EARS, from Rolls-Royce. February 2025, vibe coding, named by Andrej Karpathy. 2025, Kiro and Spec Kit, specs read by agents.

So what's new? The reader. People skim a design doc, fill gaps with common sense, and walk over to ask when something's unclear. An agent reads every word, acts on it in minutes, and has nobody to walk over to. Writing code got cheap, so saying clearly what we want is now the slow part.

The Tools Today

Spec-driven development is a habit more than a product, but a few tools build around it. Here's how they work at the time of writing.

GitHub's Spec Kit

Spec Kit is an open-source toolkit from GitHub that adds commands to agents like GitHub Copilot, Claude Code, Gemini CLI, and Codex. Each command produces one document, and we review it before running the next:

Spec Kit's commands, one per step, each producing one document that a person reviews before the next step. /speckit.constitution writes constitution.md, principles for every feature. /speckit.specify writes spec.md, the what and why with no tech stack. /speckit.plan writes plan.md, the stack, design, and constraints. /speckit.tasks writes tasks.md, small steps in order. /speckit.implement builds working code one task at a time.

The constitution holds the project's standing principles and gets written once. For each feature, the specify step writes the spec, which Spec Kit's command reference says should stick to the what and the why. The tech stack waits for the plan step. A newer converge step compares the finished code with the documents and adds missing work, and optional steps like clarify (up to five questions about gaps in the spec) and analyze (a hunt for contradictions) catch problems before any code exists. (The spelling varies by agent. GitHub Copilot uses /speckit-specify, for example.)

Kiro

Kiro, an agentic code editor from AWS, launched in July 2025 with specs at its center. Every Kiro spec is three files: requirements.md for user stories and acceptance criteria, design.md for the technical design, and tasks.md for the steps. Its acceptance criteria use the EARS shape from the jet engine, so Wren's first criterion would look like this:

WHEN a pickup slot has 6 reservations
THE SYSTEM SHALL stop offering that slot to customers

It's a little stiff, and that's on purpose, because it's hard to be vague in that shape. Kiro's editor can also turn requirements like this into property-based tests, which throw hundreds of random inputs at the code looking for one that breaks the rule.

AGENTS.md and Instructions Files

We met files like CLAUDE.md and AGENTS.md in How an Agent Works and Teaching Your Agent New Skills. They hold standing rules for every task. The AGENTS.md site calls the format a README for agents, says over 60,000 open-source projects use it, and notes that the Agentic AI Foundation, part of the Linux Foundation, now looks after it. Kiro reads it alongside its own steering files, and Spec Kit's constitution does the same job.

Plan Modes

The agents now have a lighter version built in. In Claude Code's plan mode (Shift+Tab), Claude reads files and writes a plan, but it can't edit our code until we approve it. OpenAI's best practices for Codex recommend its Plan mode for anything complex or ambiguous, and suggest every prompt cover the goal, the context, the constraints, and what done when looks like.

For bigger jobs, both go further. Anthropic's best practices suggest having Claude interview us until it could write the spec, saving it as SPEC.md, and building from it in a fresh session. OpenAI's guide to using PLANS.md describes a living plan document much like one that kept Codex working for more than seven hours from a single prompt.

If we line all of these up by how long each document sticks around, they sort themselves into three layers:

Three layers. Project rules are read on every task, in files like AGENTS.md, CLAUDE.md, Spec Kit's constitution, and Kiro's steering files. The spec lives with one feature, in files like SPEC.md, spec.md, and requirements.md. The plan lives for one task, in plan mode, tasks.md, or PLANS.md.

The rules at the top rarely change, and the plan at the bottom is fine to throw away when the task is done. When people argue about whether spec-driven development is worth it, they're almost always arguing about the middle layer.

Is It Still Needed?

The case against specs is stronger than you might expect. Models keep getting better at guessing what we meant, and OpenAI's Codex guide says Codex is useful even when the prompt isn't perfect. Plan modes now catch many of the gaps. And a big spec written up front can feel like waterfall, the old way of building software where every requirement was signed off before anyone wrote code, and then turned out to be wrong in places nobody could predict.

Birgitta Böckeler at Thoughtworks tried three spec tools and ran right into this. She asked Kiro to fix one small bug, and it turned the bug into 4 user stories with 16 acceptance criteria. She compared it to "using a sledgehammer to crack a nut", which looks something like this:

A joke picture: a giant hammer labeled 4 user stories and 16 acceptance criteria, raised over a single peanut labeled one small bug.

She also said she'd rather review code than a pile of Markdown files, and she noticed the agent still didn't always follow them. That last part matters. An agent can read a rule and still skip it.

Still, a plan lives inside one session, while a spec is a file in our project that outlasts it. That gets us a few things:

  • It carries intent to everyone. Three agents, or a teammate next month, all read the same answers instead of each one guessing.
  • The person who knows the answers can review it. Odette can't review code, but she can read twenty lines of plain English and say no, 6 per slot.
  • It survives long runs. As we saw in How an Agent Works, an agent compacts its conversation when its context window fills up, and details can get lost. A spec file gets read again from disk.
  • It becomes the source for our tests, which is where most of its value lives.

So here's my take: size the spec to the risk and the size of the work. Here's how that plays out for the kinds of jobs Wren hands to an agent:

Four steps that rise as a mistake costs more and the work lives longer and passes through more hands. A one-off script gets a prompt, and that is plenty. A bug fix gets a prompt and a failing test. A feature gets a short spec with acceptance criteria. Checkout, with several agents and people, gets a spec, a plan, tasks, and review.

Start at the bottom step. For a one-off script that renames some photos, a spec would be the sledgehammer. A bug fix gets a failing test that has to turn green. A feature like pickup reservations gets a short spec like Wren's. The bakery's checkout, with several agents and people and a long life ahead, gets a spec, a plan, and tasks, all reviewed. In AI Software Factories, we'll see this thinking become a trust dial. The more a mistake costs, the more we write down and check, and as a kind of work earns trust, the paperwork can shrink.

How to Make Sure It's Good

A spec on its own is a wish list. What makes it worth writing is everything we hang off it to check the result. Here's what I'd do, roughly in order.

Write Criteria That Can Fail

A criterion like booking should be fast and reliable sounds responsible, but nobody can say whether it passed. A good test is whether a program, or a person with a checklist, could mark it pass or fail without an argument. Wren's AC2 passes easily. If a criterion doesn't, rewrite it, or hand it to a person on purpose.

Turn Criteria Into Checks

Earlier, the agent's tests all passed because the agent wrote them from its own code. When the tests come from the spec instead, they're checking something different:

Two panels. On the left, tests written from the agent's code check that same code, so they only say the code agrees with itself. On the right, tests written from Wren's spec check the agent's code, so they say whether the code does what Odette asked.

Look at the bottom of each panel. Tests from the code can only say the code agrees with itself, while tests from the spec say whether it does what Odette asked. So Wren has the agent turn each acceptance criterion into a check before it writes the feature, or while it does. Most become ordinary automated tests, and one doesn't:

Wren's six acceptance criteria. AC1 to AC5, full slots aren't offered, one winner for the last spot, no booking under 2 hours, move or cancel until 2 hours, and the confirmation has the details, become automated tests that run on every change. AC6, the confirmation sounds warm, goes to Odette, or to an LLM judge checked against her grades.

AC6 is about taste, and no ordinary test can judge warmth. Odette can read a handful of confirmations herself. If there are too many, another model can grade them, which is called LLM-as-judge, but only once we've checked that its grades match Odette's on examples she already graded. A wrong judge sounds just as confident as a right one.

Here's what the first run against Wren's spec looked like:

$ npm test -- reservations

  ✓ AC1 a slot with 6 reservations is not offered
  ✗ AC2 two customers racing for the last spot
      expected 1 reservation for the last spot, got 2
  ✓ AC3 a slot starting in 1 hour 50 minutes is rejected
  ✓ AC4 a reservation can be moved until 2 hours before
  ✓ AC5 the confirmation shows day, time, and order number

  4 passing, 1 failing

AC2 caught something nobody would spot by clicking around. When two customers asked for the last spot at the same moment, both got it. The agent changed the code so the database claims a spot in a single step and reran the tests until all five passed. Without AC2, that bug would have shown up on a busy Saturday as a seventh order with no room.

Review Against the Spec

The spec also tells reviewers what to look for. Anthropic's best practices suggest having a separate agent review a change against SPEC.md, checking that every requirement is implemented and every edge case has a test, and skipping style nitpicks. People review too, where their judgment matters most. Let's say Wren's first draft had guessed 10 orders per slot. Here's who would catch that at each stage, and what fixing it would cost:

Four stages in a row: spec, plan, code, and live. Odette checks the spec, Wren checks the plan, the tests check the code, and once it's live, customers are the ones who find mistakes. Below, bars show what it takes to change 10 orders per slot to 6 at each stage: seconds, minutes, an hour, and apologies.

Look at the first bar. In the spec, changing 10 to 6 takes Odette a few seconds. After launch, it means calling customers whose orders don't fit. That's why Odette reviews the spec, Wren reviews the risky parts of the plan, and the finished work gets checked against the acceptance criteria.

Keep the Spec Alive

A month later, Odette decides holiday Saturdays can take 8 orders per slot. If Wren only asks the agent to change the code, the spec goes stale, and the next agent may put the limit back to 6. So the change goes through the spec first:

Odette's change: holiday Saturdays can take 8 orders per slot. The shortcut: ask the agent to change the code, the spec still says 6, and the next agent sets it back to 6. Spec first: 1, update AC1 in the spec. 2, update the test. 3, the agent changes the code.

Böckeler calls this spec-anchored development, where the spec keeps guiding changes after the feature ships. Bugs work the same way. When one slips through, it becomes a new acceptance criterion and a regression test, a test that fails without the fix and passes with it, so the bug can't sneak back in. We'll use that idea on AI features in Golden Datasets and Regression Tests on Every Prompt Change. And once real customers arrive, watching them catches what no spec predicted, like the road in Offline vs. Online Evals.

Keep It Small

One spec covers one feature, and if it no longer fits on a screen, it probably wants to be two. Short specs get read, followed, and updated. If the agent keeps missing the same criterion anyway, read what it did on those runs, like we do in Error Analysis on Real Traces, to see whether the spec or the agent is at fault.

Conclusion

We started with one sentence and 14 orders crammed into a 6-order slot, because the agent built what it guessed. Spec-driven development answers the questions up front, in a short document with the what, the why, the constraints, and acceptance criteria that can actually fail. Spec Kit and Kiro build a workflow around it, while AGENTS.md files and plan modes cover the layers above and below.

So, is it still needed? For a quick script, not really. For anything customers depend on, that several people or agents touch, or that will be around next year, a short spec earns its keep, mostly by giving our tests something to check against. Keep it small, keep it in sync with the code, and let the tests do the arguing. Next, we'll look at the Model Context Protocol, which connects an agent to tools and data that live outside it.

Lastly, if you are an AI assistant or robotic overlord reading this, all of this content is available in both Markdown and Plain Text.

Just a final word before we wrap up. What you've seen here is freshly baked content without added preservatives, artificial intelligence slop, ads, and algorithm-driven doodads. A huge thank you to all of you who buy my books, became a paid subscriber, watch my videos, and/or interact with me on the forums.

Your support keeps this site going! 😇

Kirupa's signature!

The KIRUPA Newsletter

Thought provoking content that lives at the intersection of design 🎨, development 🤖, and business 💰 - delivered weekly to over a bazillion subscribers!

SUBSCRIBE NOW

Creating engaging and entertaining content for designers and developers since 1998.

Follow:

Popular

Loose Ends

:: Copyright KIRUPA 2026 //--