A specification can be extremely detailed and still be useless. It can describe the wrong outcome with impressive precision, freeze an implementation before we understand the problem, or repeat information which the code already expresses better.
It can also be the difference between delegating work and delegating guesswork.
When an agent performs the implementation, the specification becomes the main interface through which we exercise engineering judgement. I use “specification” broadly here. It may be a paragraph, a set of examples, an API description, a test, a diagram or a collection of invariants. The format matters less than the decisions it makes explicit and the feedback it enables.
That does not make specification-driven development a universal methodology. If anything, cheaper implementation makes it more important to choose the smallest useful specification, because prose can now be overproduced as easily as code.
What the Interface Must Carry
A useful interface separates intent from implementation.
Suppose the request is “add retries to payment submission”. That sentence names a mechanism, but leaves the important questions open. Which failures are retryable? Can two attempts create two charges? How long may the caller wait? What should an operator observe? Is the existing provider contract allowed to change?
The specification should carry what the implementation cannot decide responsibly:
- Outcome: what becomes possible, for whom, and why it matters.
- Examples: representative success, denial, failure and recovery cases.
- Invariants: what must remain true throughout the change.
- Boundaries: interfaces and systems which may or may not change.
- Non-goals: plausible work which is deliberately outside scope.
- Evidence: the checks and observations required before acceptance.
- Escalation: contradictions or decisions the agent must return to a human.
It should usually leave local class names, helper functions and control flow open. If every implementation decision is prescribed, we have written code badly in prose. If no externally visible outcome is prescribed, we have written a wish.
This extends the argument from declarative development. The valuable part of a specification is not that it appears before the code. It is that it provides a source of intent which the generated implementation cannot quietly redefine.
Different Uncertainty Needs Different Specifications
There is no single best specification format. Each one reduces a different kind of uncertainty and introduces its own blind spots.
| Form | Useful when | What it does not prove |
|---|---|---|
| Short task brief | Scope is small and local conventions are strong | That ambiguous words mean the same thing to everyone |
| Worked examples | Behaviour depends on awkward inputs or state transitions | That the examples cover the important space |
| Acceptance criteria | Product behaviour needs review before implementation | That the implementation satisfies the criteria |
| Types and schemas | Data shape and valid states are central | That the data has the right business meaning |
| Executable tests | Behaviour can be observed cheaply and repeatedly | That the assertions are complete or independent |
| Architectural decision | A consequential option and its trade-offs need preserving | That the decision will remain correct as constraints change |
| Prototype | We need to discover feasibility, usability or an unknown dependency | That the exploratory implementation is ready to operate |
These forms can reinforce one another. A natural-language outcome gives meaning to an executable test. An OpenAPI description constrains the messages at an HTTP boundary. The OpenAPI Specification defines this as a language-agnostic interface description which humans and computers can use without reading the service’s source, but even a precise schema cannot tell us whether issuing a refund is permitted in a particular business situation.
More forms also mean more things which can disagree. If the prose says a retry is safe, the acceptance test expects one charge, and the API contract allows clients to omit the idempotency key, which one wins? The specification needs ownership and precedence, not just volume.
A Spec Is Not the Same as Repository Context
Persistent project instructions and task specifications solve related but different problems.
The repository may say that database migrations require a rollback, public functions need documentation, and a particular module owns payment state. Those rules apply across many changes. The retry specification should describe this change: the outcome, constraints, exceptions and evidence.
Mixing them creates two familiar problems. Repeating all project knowledge in every task produces long, stale briefs. Hiding task-critical behaviour in a large instruction file makes it easy for both people and agents to miss.
Birgitta Böckeler’s analysis of specification-driven development tools makes a similar distinction between a task-oriented specification and the persistent “memory bank” around it. She also offers a useful spectrum:
- Spec-first: write a specification for the task before implementation.
- Spec-anchored: retain and maintain the specification as the feature evolves.
- Spec-as-source: humans edit the specification rather than the generated code.
Those are materially different commitments. A design note can be valuable during one migration and disposable afterwards. An HTTP contract used by several teams must evolve with the service. A spec-as-source system needs generation which is repeatable enough, and an escape route for behaviour the specification language cannot express comfortably.
Calling all three “SDD” does not resolve those differences.
Tooling Can Add Discipline and Paperwork
GitHub’s Spec Kit is a concrete example of a structured workflow. Its current documented path establishes project principles, specifies what to build, plans the technical approach, breaks it into tasks, implements them and converges the result against the artefacts. That separation can prevent an agent from jumping from a vague idea straight into code. It also gives reviewers explicit places to challenge intent and design.
The files are not enforcement by themselves.
An agent may misunderstand a requirement while producing every requested document. Two generated artefacts may agree because they repeat the same mistaken assumption. A checklist can record that security was considered without detecting a vulnerability. The output looks controlled because it is orderly, which is not the same as being correct.
Böckeler reached a related conclusion in her 2025 evaluation of Kiro, Spec Kit and Tessl. She found value in spec-first work but also encountered disproportionate ceremony, repetitive Markdown and instructions which agents still ignored. Her objection is not that specifications are pointless. It is that one workflow does not fit every problem, and more specification artefacts create another review burden.
That burden matters. Reviewer attention is finite. Asking somebody to read a task brief, research note, design, data model, API contract and task list before inspecting a small change may reduce scrutiny rather than improve it. The specification has then become a lossy copy of the code and the organisation has two maintenance problems.
I would judge a specification practice by three questions:
- Which uncertainty does this artefact remove?
- Who checks that it expresses the intended outcome?
- What mechanism detects divergence between it and the implementation?
If the answers are vague, adopting a more elaborate framework will not make them precise.
Discovery Still Needs Room to Move
Specifications are hardest to write when the problem contains an unknown we cannot settle by thinking harder. We may not know whether an external API has the required behaviour, whether a query meets the latency target, or whether users understand the interaction.
In those cases, the right specification may be an experiment:
Question
Can the provider safely deduplicate retries after a client timeout?
Probe
Build the smallest integration which submits the same operation twice
with a controlled timeout between attempts.
Evidence
Record provider responses and resulting transaction identifiers.
Boundary
Use the test account. Do not change production configuration.
Stop
Report the result; do not turn the probe into the production implementation.
This is still specification. It specifies learning rather than pretending the final design is already known.
The result should feed the next version of the brief. Perhaps the provider supports idempotency and the production design becomes simple. Perhaps it does not, and we need a local state machine. The cheap prototype has earned its keep by replacing an assumption with evidence.
The danger is allowing exploratory code to become authoritative merely because it works once. A prototype optimises for learning. Production code must also account for operation, maintenance, security and failure recovery. Crossing that boundary deserves a new decision.
Keep the Human on the Intent Side
An agent can help expose gaps in a specification. Ask it to identify undefined terms, construct counterexamples, trace affected interfaces and propose tests. A fresh review can find assumptions which the implementation conversation has normalised.
It should not silently own both the requirement and the proof. If the same agent turns a vague sentence into acceptance criteria, writes the code and writes the tests, all three can share one coherent misunderstanding.
Human ownership does not mean typing every word. It means deciding which outcomes matter, resolving product and architectural trade-offs, and approving movement of the boundary. For higher-risk work, the acceptance criteria or verifier may need a separate owner. For a reversible local refactor, a brief and focused diff review may be entirely adequate.
The previous chapter argued that greater autonomy needs explicit authority, evidence and stop conditions. A specification carries those decisions into the agent’s working loop. Its strength should rise with the cost of a wrong interpretation, not with our enthusiasm for a methodology.
The best specification is therefore not the longest or the most formal. It is the smallest interface which preserves the important human decisions and produces useful objections while there is still time to act on them.
That last requirement leads to the next part of the control system: Tests Are Backpressure.