Engineering

How to write a design doc an agent can implement from

Editorial · Reveneau · October 15, 2026

How to write a design doc an agent can implement from

We have watched two engineers review the same design doc and reach different conclusions about what it asked for, then resolve the difference in four minutes over Slack. Neither of them thought the doc was unclear. It was unclear in one specific spot, they both noticed, and a question closed the gap before anyone wrote a line of code. That protection does not exist when the reader is an agent. The agent does not ask. It picks the most plausible reading and starts building on top of it, and by the time anyone notices, the gap has become behavior in released software.

That is the whole problem with using an old design doc format for AI-driven work. The format assumes a reader who can ask. Once the reader cannot, every place the doc was silent turns into a decision made by someone who was never part of the discussion about the trade-off.

Here is what has to change: three places a human-oriented doc stays vague on purpose, and what to write there instead.

Interfaces: state the exact format

A doc written for a colleague often says something like "the endpoint returns the user's order history." A person reads that, has a rough idea what an order history looks like, and if their guess is wrong, they ask before writing code.

An agent reads the same sentence and has to decide: which fields, in what order, paginated or not, what happens with zero orders, what status code, what happens on a malformed request. None of those questions are unreasonable. The doc just never answered them, so the agent answers them itself, consistently and confidently, and the answer it picks is whichever one is statistically the most common pattern in code it has seen before, not necessarily the one your system needs.

The fix is to write the interface as a precise set of rules instead of a description:

  • The exact request format, including which fields are required and which are optional.
  • The exact response format, field by field, including type and whether it can be null.
  • The status code for the success case and for each failure case, named separately.
  • One worked example: a real input and the exact output it produces. Prose can be read two ways. A concrete example can only be read one way, which is why it resolves ambiguity that a paragraph of description cannot.

This is more writing than "returns the user's order history." It is also the only version of that sentence that two different people, or two different agent runs, would implement identically.

Failure modes: name every case beyond normal use

Most design docs describe what the feature does when everything goes right, because that is the part everyone agrees on and the part that is interesting to design. What happens when it goes wrong gets a line or two, if it gets anything.

That gap matters more with agent-built code than it used to. Independent testing from Veracode's spring 2026 research, covering generated output from more than 150 models, found code compiling and running correctly over 95 percent of the time while being secure in only about 55 percent of generations. The failures are concentrated exactly where design docs say nothing: access control, input validation, and the paths that only run when something has already gone wrong. A doc that never names those paths gives an agent nothing to build against, so it either invents its own handling or skips it, and both are silent until something breaks in front of a real user.

A design doc that is agent-ready states, for every interface it defines:

  • What happens on invalid input, and what the caller sees.
  • What happens when a dependency the feature relies on is slow or unavailable.
  • What happens if the same request arrives twice.
  • What happens when the caller does not have permission to do this.

Writing these down gives you the same information a good test suite needs, stated at design time instead of discovered at review time. We have written before about turning exactly this kind of statement into something a machine can check for itself, in how to write an acceptance test a machine can run.

Non-goals: say what the change will deliberately not do

This is the piece a human-oriented doc almost never includes, because a human reviewer does not need it. If a colleague reads a spec for a search endpoint and it does not mention pagination, they assume pagination is out of scope for now, and if they are unsure, they ask.

An agent does not default to "out of scope." A spec that describes a feature in general terms looks more like a request to be thorough than a limit. Without stated limits, it is common for a generated implementation to add handling nobody asked for: retries around a call that was meant to fail immediately, caching that introduces a bug where old data is shown, or an extra parameter that quietly becomes something another part of the system starts depending on.

A non-goals section prevents that directly:

  • "This endpoint does not support pagination in this version."
  • "This change does not add retry logic. A failed call returns an error to the caller."
  • "This does not change the existing rate limit."

Each line is short, and each one removes a decision the agent would otherwise have to make for itself. The rule for writing them is simple: if a competent engineer reading the doc might reasonably build more than what you intended, write the sentence that rules it out.

What this costs, and what it saves

Writing a design doc this way takes longer than writing one for a colleague who can fill gaps by asking. For a medium-sized feature, the exact interfaces, the failure modes, and the non-goals typically add an hour or two of writing time.

That cost does not disappear if you skip it. It comes later and is larger. A vague doc costs a Slack thread to clarify, then a wrong implementation built on the wrong reading, then a review cycle to catch it, then a rewrite. Every one of those steps is more expensive than the extra hour would have been, and unlike the extra hour, none of them is guaranteed to happen before the code is released.

This is also the same discipline that makes an eval suite, the set of automated checks a build has to pass before it is released, worth writing. A check can only test for a failure mode the doc actually named. A doc that never says what happens on a duplicate request gives the eval suite nothing to verify there, so the gap gets past both the design step and the testing step, and it is found in production.

What we have learned from doing this

This is a claim about who is responsible for resolving ambiguity. In the work we do, a design doc that reads clearly to the team writing it has passed an easier test than a design doc an agent can implement from without guessing, and the two get confused constantly because the first one feels like enough.

The two conditions are close enough to look the same until an agent is the one reading. A design doc is finished when nobody has to ask what it meant.

Sources

  • Veracode, Spring 2026 GenAI Code Security update: across more than 150 models, generated code compiled and ran correctly in over 95 percent of cases while being secure in roughly 55 percent, with failures concentrated in access control and input handling.

Common questions

What makes a design doc "agent-ready"?

An agent-ready design doc states every interface, every failure mode, and every non-goal explicitly, with no detail left for a later conversation. A human reader can tolerate a gap and ask about it; an agent fills the same gap with a plausible-looking guess and keeps building on top of it.

Why does a design doc that works fine for a human team fail with an agent?

Because a human design doc relies on shared context that never gets written down: the reviewer already knows the team's conventions, can imagine the unusual cases, and will ask a question in Slack if something is unclear. An agent has none of that shared history and cannot tell the difference between an intentional omission and an oversight, so it picks an answer and moves on.

What are non-goals and why do they matter for AI agents?

Non-goals are the things a design doc explicitly says the change will not do, such as "this endpoint does not support pagination in this version." Without them, an agent implementing the endpoint may add pagination, retries, or caching on its own initiative, because a spec with no stated limits looks like a request to be thorough rather than a limit to follow.

How specific do interface definitions need to be for an agent to implement from them?

Specific enough that two different engineers, or two different agent runs, would produce the same function signature, request and response format, and error codes without guessing. Vague language like "return the user's data" leaves open which fields, what happens when the user has none, and what status code an empty result returns.

What failure modes should a design doc always cover?

At minimum: what happens on invalid input, what happens when a dependency is slow or down, what happens on a duplicate or repeated request, and what happens when the caller lacks permission. These are exactly the paths a human tester skips because they use the feature in the normal way, and they are exactly where generated code is weakest.

Does writing this level of detail slow down design doc writing?

It adds time up front, typically an hour or two for a medium-sized feature, but it saves far more time later: a vague doc costs a discussion, a wrong implementation, a review cycle to catch it, and a rewrite. When the doc is vague, the cost comes later and is bigger.

Should a design doc for an agent include example inputs and outputs?

Yes. A worked example, one realistic input and the exact expected output, resolves ambiguity that prose alone cannot, because prose can be read two ways and a concrete example can only be read one way. This is one of the fastest ways to fill a gap an agent would otherwise guess at.

How does this relate to Reveneau's eval suite process?

The design doc and the eval suite describe the same promises in two ways: the doc states what must be true before anything is built, and the eval suite is the automated check that confirms the finished code actually behaves that way. A doc that never names a failure mode gives the eval suite nothing to test for, so writing the doc precisely is the first step in writing checks that actually catch mistakes.

Who is responsible for a design doc gap an agent fills incorrectly?

The team, not the agent and not one individual. If a doc leaves a gap and the resulting code is released with a wrong assumption built in, that is a process failure to fix with a better doc template and a wider eval suite, not a mistake to blame on whoever wrote the prompt that day.

Is a longer design doc always a better one?

No. Length does not predict agent-readiness. A short doc that states every interface, failure mode, and non-goal precisely will implement more reliably than a long doc full of background and rationale that never states exactly what the change must do.

Start a project