Skip to content

AI

Spec-driven development with coding agents: write the spec first

How to give a coding agent a short specification, a task list and acceptance tests so it builds what you meant, with a template you can copy.

By · Published · 3 min read

Short answer: spec-driven development means writing down what you want in a short document before the agent writes code, then letting it plan and implement against that document, and checking the result against acceptance tests. It replaces a long chat of corrections with one clear brief. A good spec is half a page to two pages.

Why does it work?

A coding agent is only as good as its picture of the goal. In an open-ended chat, the picture is built from your first message and whatever you remember to add. Gaps get filled with guesses. A spec forces you to settle the guesses before they become code, and gives the agent something stable to return to when its context gets long.

What goes in a spec?

  • Goal: one or two sentences on what changes for the user.
  • Context: which parts of the codebase are involved, and any constraint such as "use the existing Money type".
  • Behaviour: inputs, outputs and the rules, with two or three concrete examples.
  • Non-goals: what the agent must not touch or build.
  • Edge cases: empty input, duplicates, permissions, large input.
  • Acceptance tests: how you will decide it is done.

Can you show a short example?

# Spec: credit note numbering

Goal
  Credit notes get their own number series, CN-0001, CN-0002, ...
  per company, with no gaps.

Context
  - Invoices already use src/billing/numbering.go (see NextInvoiceNo).
  - Numbers are allocated inside the same transaction as the document.

Behaviour
  - Finalising a credit note allocates the next CN number.
  - Two companies have independent counters.
  - Drafts have no number.

Non-goals
  - Do not change invoice numbering.
  - No UI changes in this task.

Edge cases
  - Two requests finalise at the same time: numbers must be unique.
  - Transaction rolls back: no number is consumed.

Acceptance
  - Unit test: numbers are sequential per company.
  - Concurrency test: 50 parallel finalisations produce 50 unique numbers.
  - go test ./... passes.

That took ten minutes to write and saves an hour of back and forth.

What is the workflow?

  • 1. Write the spec in a markdown file in the repository.
  • 2. Ask for a plan. Have the agent restate the goal, list the files it will touch and name the risks. Correct the plan, not the code.
  • 3. Ask for tests first from the acceptance section, and read them.
  • 4. Implement in small steps, one task at a time, committing after each.
  • 5. Run the checks yourself: tests, linter, type check.
  • 6. Review the diff against the spec, including the non-goals.

Why ask for a plan before code?

A plan is cheap to correct. If the agent says it will add a new table and you wanted a column, you find out in thirty seconds instead of after four files change. Ask for the list of files it intends to touch and read it.

What are the common mistakes?

  • A spec that describes the solution instead of the problem, locking the agent into a bad approach.
  • No non-goals, so the agent tidies unrelated code.
  • Acceptance criteria that are vague, like "works well".
  • A giant spec for a giant task. Split it. Several small specs beat one big one.
  • Never updating the spec when the decision changes, so it lies to the next session.

Where should the spec live?

In the repository, next to the code, in a specs/ or docs/ folder. It is reviewed in the pull request and survives the chat window. Teams that keep an ADR (architecture decision record) habit already have the right instinct. A short note on the trade-offs, like the ones in stock balances belong in application code, is the same discipline.

Author

Raktim Ranjit is a software engineer and the founder of NodeDR Infotech. He builds and maintains the software described here.

Have something in mind?

Let’s build something useful.

Tell me about the idea, product, or workflow you’re working through.

Tap to say hello