TDD With AI Coding Agents: Tests as the Spec
TDD with AI coding agents works better than with humans because agents excel at making a red test green. Here is how to use tests as the spec the agent codes to.
Test-driven development works better with AI agents than it ever did with humans, and almost nobody uses it that way. The reason is simple: an agent is exceptional at making a failing test pass. Give it a red test with a clear target and it will drive to green fast and precisely. That is the one thing the loop needs, and it is the thing agents do best. Write the tests first, hand them to the agent as the specification, and you get code that hits your definition of correct instead of the agent's guess at it.
The usual objection to TDD was cost: writing tests first is slow for a human, and humans resent it. That objection evaporates with an agent, because the agent writes the implementation, so the human only has to write the tests, which is the cheap part. TDD's economics flip. The expensive step is automated and the valuable step, defining correctness up front, is the one you keep.
Why tests make a better spec than a prompt
A prompt describes what you want in prose, and prose is ambiguous. The agent interprets it, and its interpretation is optimistic and averaged. A failing test describes what you want in code that either passes or does not. There is no interpretation. The test says the function returns 401 on an expired token, and the agent either makes that true or it does not. You have replaced a fuzzy target with an exact one.
This is why tests-as-spec beats prompt-as-spec for agents specifically. The agent's core weakness is producing plausible output that is subtly wrong, and a prompt cannot catch that because a prompt is not checkable. A test is checkable, so the plausible-but-wrong output fails and the agent has to keep going. I make the broader argument for defining correctness before you generate in write the spec before the prompt; TDD is that principle in its sharpest, executable form.
The loop: red, agent, green, review
The workflow is tight. You write a failing test from the acceptance criteria. The agent implements until the test passes. You review the implementation, not to check whether it works, the test already told you that, but to check whether it works well. Then the next test. Each cycle is small, verified, and reviewable.
The key is that the test comes from you, before the agent writes anything, so it cannot inherit the code's blind spots. This is exactly the independence that agent-written tests lack, the circularity problem I dig into in should AI write its own tests. When the test predates the code, it is a genuine external check. When it postdates the code, it tends to ratify whatever the code already does. Order is everything.
Where the human attention goes
TDD with agents does not remove the human, it relocates the human. Instead of writing implementation, you write the tests that define correct behavior, which is the higher-leverage work. Getting the tests right, covering the real edge cases, asserting the actual requirement, is where your understanding of the problem gets encoded. The agent then executes against that encoding.
This means your job becomes thinking hard about what correct means and expressing it as tests, which is a better use of a senior engineer than typing out the fortieth CRUD handler. The edge cases you choose to test are where your expertise lives now. This connects to how I run review of AI-generated pull requests: if the tests were written first and well, the review is fast, because correctness is already established and you are only judging quality.
Where TDD with agents does not fit
Be honest about the limits. Not everything reduces cleanly to a test before you write it. Exploratory work, where you do not yet know what correct looks like, resists test-first, because you cannot write a test for behavior you have not designed. UI and visual work is hard to pin with tests alone. In those cases, use TDD for the parts that have clear correctness, the logic, the data handling, the API contract, and use other checks for the parts that do not.
The failure mode is forcing tests onto genuinely exploratory work and slowing yourself down writing tests for a design that is about to change. Reach for TDD when the requirement is clear enough to express as a check, which is most backend and logic work, and reach for planning-first exploration when it is not. Used where it fits, tests-as-spec is the most reliable way I know to get correct code out of an agent, and it is central to how the build loop works at Bootspring. Write the test, let the agent go green, review for quality, repeat. The agent does what it is best at, and you keep control of what correct means.