Accueil / Articles / Spec-First Development: Agree on Intent Before AI Writes the Code

Cet article est publié en anglais.

Spec-First Development: Agree on Intent Before AI Writes the Code

When code is cheap, intent is the bottleneck. A practical spec-driven workflow with OpenSpec, scenarios to review before coding, and tips to roll it out on a team.

1821 mots

For thirty years, code was the scarce thing. AI coding agents have made it cheap, and that moves the bottleneck to something harder to buy: knowing exactly what you meant to build. Here's the shift in thinking, a workflow that holds up in daily use, and the people side of getting a team to adopt it.

Everyone was guessing

A familiar failure goes like this. A change ships, and only in review, or worse in production, does the team realize the result isn't what anyone intended. The requirements were scattered across a chat thread, a ticket comment and a few people's heads, and each source said something slightly different.

Concretely, someone picks up a task whose requirements are:

  • a one-line ticket title,
  • a Slack thread that fizzled out,
  • and an assumption everybody thought was shared but wasn't.

They build it. Review catches some of the mismatch and lets the rest through, since the reviewer only sees a diff and has to work backward from the code to a guess about what was wanted. That's exactly the wrong direction. After release, the sole record of what the feature should do is the code, plus whatever the team still remembers.

That last point does the quiet damage. Context evaporates once the conversation is over. Half a year later nobody, human or agent, can say what the behavior was supposed to be, only what the code happens to do.

Why agents change the math

Agents flipped the economics overnight. For decades writing code was the costly, careful step, so every process was built around it. An agent, on the other hand, is a fast, confident guesser. Hand it a vague prompt and in seconds it returns plausible, nicely structured and completely wrong code. Generation is nearly free now. Deciding what's correct is the whole job.

So the durable, scarce artifact becomes a precise, shared statement of intent: a spec. Not as paperwork, but as the thing humans agree on and the context you feed to the agents. The experiment, then, is to write the spec first, agree on it, and have people and agents build against it.

What spec-driven development means

The idea: before implementing a change, put its intended behavior on paper as a structured spec that people can review, and get agreement on it. Afterward the spec lives in the repo next to the code, recording what the system does and why.

Three objections come up right away, so here's what it isn't:

  • It isn't waterfall. A spec only needs to be good enough to start, and you keep editing it as you learn. Think living document, not a signed-off requirements binder.
  • It isn't heavy. Tiny changes can get by with a ten-line spec delta inside one pull request. The effort grows only as the change grows.
  • It isn't a design doc. Design docs argue why an approach was chosen, while a spec describes what the system does today. That boundary gets its own section below.

The payoff is simple: settle on the target first, then spend effort hitting it, and keep that agreement after the chat is long gone.

Your job description changes

Everything else rests on one mindset shift. Your core responsibility now is writing strong specs, reviewing them, and editing code by hand only in the cases where the AI can't get it right.

That inverts what most developers trained for. Writing code used to be the job. Now it's what you do least. Your real work, ranked by importance, starts with the spec and its review, and only after that comes any hand-written code.

Six principles worth repeating

When people ask how much spec is enough, the same handful of answers keep coming up:

  • Agree first. Write or update the spec, get a fast review, and only then implement.
  • Keep specs beside the code. They sit in the repo, get reviewed with the same change, and belong to the people who own that code.
  • Prefer small deltas to big rewrites. Each change states what's added, changed or removed instead of restating the whole world.
  • Write behavior as verifiable scenarios. Where something can be tested, use given/when/then rather than prose.
  • Stay fluid. If reality drifts from the spec, update the spec instead of letting it rot.
  • Give each capability one source of truth, one place where its current behavior lives.

The daily loop

The approach doesn't depend on tools. Plain Markdown files in a specs/ folder are enough. Still, a little tooling reduces friction, and OpenSpec is an open-source spec workflow that plugs into AI coding agents and provides slash commands matching the loop:

  1. Explore, optionally. When the shape of a change is fuzzy, let the agent read the code, weigh options and sketch a plan before committing.
  2. Propose. Give a one-line description and the tool generates a proposal, a brief design note, a task list and a spec delta, the piece that matters most because it shows how the living spec will change.
  3. Review the spec first. This is the entire game. The proposal and delta are reviewed before any code exists, because changing a sentence is cheap and changing a shipped implementation isn't.
  4. Apply. Build against the agreed spec, either yourself or with an agent.
  5. Verify. Run the checks, ideally with acceptance scenarios that map directly to tests.
  6. Archive. Merge the delta into the living spec so it always describes the present, and move the proposal into history.

If you keep only one step, keep the third: review the spec before the code.

Setting up OpenSpec with a coding agent

Current coding agents, such as Claude Code, can learn this workflow and run it alongside you, so you aren't narrating every move. OpenSpec packages that knowledge as agent skills and slash commands. Two commands wire it into your repo and your agent:

# install the CLI (drives everything below)
npm install -g @fission-ai/openspec@latest

# scaffold the spec structure AND generate agent skills + slash commands
openspec init --tools claude

The init step does two things. First, it creates the home for specs: a specs/ folder for living specs, a changes/ folder for in-flight proposals, and a small config where you record your stack and conventions. Second, it installs the agent skills. For Claude that means skill files plus /opsx:* commands, namely explore, propose, apply, archive and sync. The skills teach the agent how to draft a proposal, produce a spec delta, implement against it and fold the result back into the living spec.

What a change looks like

Imagine a background job that needs a configurable timeout. A job that overruns its limit should be cancelled and marked timed_out.

It starts life as a spec delta, meaning a diff against the living spec that shows precisely what will move:

### Requirement: Job timeout
- The system SHALL run a job to completion.
+ The system SHALL cancel a job that exceeds a configurable timeout
+ (default 30s) and record the outcome as `timed_out`.+ #### Scenario: Job exceeds the configured timeout
+ - GIVEN a job configured with a 5s timeout
+ - WHEN the job has run for 5s without completing
+ - THEN the system cancels the job
+ - AND sets its status to `timed_out`
+ - AND emits a `JobTimedOut` event with the job id

That diff is what people review, before any implementation exists. A teammate can question the default, the status name or the event while it's still just a sentence. Once everyone agrees, the build has an unambiguous target, and the scenario turns into a test.

Once it ships, archiving folds that requirement into the living spec as a plain statement of how the system behaves now, with no plus or minus markers left over. Whoever touches this code next, human or agent, reads it and doesn't have to guess.

Spec or design doc

People mix these up, which causes duplication and confusion. A split that stuck:

  • A design doc explains a decision: why this approach, what the trade-offs were. It's a snapshot in time and is expected to go stale, because it's a historical record.
  • A spec describes current behavior, meaning what the system does right now. It's alive and must never go stale, because it works as the contract.

In practice, explore options and make the call in a design doc, capture the lasting behavior in the spec, and link the two instead of duplicating. If the same behavior is maintained in both places, shrink the design doc down to a link.

Rolling it out to a team

A short checklist helps. For your next change: describe it and generate the proposal and spec delta, put the spec up for review before writing code, implement and make the scenarios pass once it's approved, then archive so the living spec matches reality.

For the team: confirm repos have the tooling set up, add a short context note covering stack and conventions so agents write better specs, and spec your top two or three capabilities first.

Don't try to spec the whole existing system up front. Write specs as you touch things, and coverage grows where the work happens.

Try it on the next change

You don't need a big initiative or a mandate. On your next non-trivial change, write down what it should do as a few given/when/then scenarios before coding. Ask a teammate to look at those scenarios before anything else. After that, build it, get the scenarios passing, and check the spec in alongside the code.

That's all there is to it. Do it a few times, let your pull requests quietly improve, and your team will start asking you where the spec is.

For decades, code was treated as the final word on behavior, since a person had written and understood each line. That's no longer the case. Generated code is cheap and disposable, and the lasting, human-owned artifact is the spec. Teams that absorb this will out-ship the ones still reviewing diffs and hoping intent survived. Agree on what you're building before you build it. In this new paradigm that isn't process overhead. It's the job.