2026-07-07 · Architecture
BDD in agent-driven development
Definition
Behavior-Driven Development is a methodology in which a unit of work is described through the system's observable behavior rather than its implementation. The behavior is fixed before work begins: Given (precondition) — When (event) — Then (result). A single scenario serves as specification, acceptance criterion, and — once automated — an executable test.
The defining property is a shared, ubiquitous language. Whoever sets the task, whoever does it, and whoever verifies it read the same text and understand it the same way. "Done" stops being a matter of interpretation.
Origin
The term was coined by Dan North in 2006 as a reframing of TDD. TDD says to write the test before the code, but not which test or at what level. North noticed that the word "test" pulls attention toward implementation, while describing behavior is more productive. The Given/When/Then form took shape in the Gherkin notation (Cucumber). The idea of a shared language traces back to Eric Evans' Domain-Driven Design (2003). An academic account of the method's characteristics is Solís & Wang (2011): the core of BDD is a scenario that blends natural language with structural keywords.
Applying it with agents
An agent is an executor with no common sense by default. "Build an MCP server" admits any degree of completeness: 30 endpoints out of 100 formally satisfy the wording. BDD closes the gap at the input: the criterion "coverage ≥ 95%" leaves no reading under which 30% counts as done.
(rule: if you can't state the Then, the task isn't understood well enough to begin)
BDD on top of the pipeline
So far, BDD is an agreement about how to write. A scenario in prose stays a recommendation: it can be read, nodded at, and ignored. The next step is to wire the scenario into the delivery pipeline so it becomes a gate — until the criterion is confirmed, work physically cannot move forward.
A criterion as an object, not text
An acceptance criterion stops being a line in the task description and becomes a separate record in storage — with Given / When / Then fields, a link to its task, and a MoSCoW priority (Must / Should / Could). The record has its own status and history. The point: only Must criteria block closing the task; Should and Could can stay open and don't hold up delivery.
The criterion's lifecycle
Each criterion moves through a state machine — a set of statuses with allowed transitions. The exact status names differ from team to team; what matters is not the nomenclature but the two mandatory barriers. A rough route:
proposed → agreed → ready for check → claimed by executor → confirmed by a human → closed
- proposed / agreed — the criterion is stated and accepted as part of the definition of done. Work must not start before this.
- ready for check — the executor (agent or human) claims the behavior is implemented.
- claimed by executor — first hard barrier: the automated check passed green. A red test rolls the criterion back; it does not proceed to closing.
- confirmed by a human — second hard barrier: the result was verified by a live person, not the author of the work. The machine checks that the test is green; the human checks that the green test tests the right behavior.
- closed — both barriers cleared; the criterion no longer blocks the task.
Check runs are best stored append-only: the history of attempts accumulates rather than being overwritten. Then "it went green on the tenth try" is visible instead of hidden.
A gate, not advice
The key move is to shift the check from the level of agreement to the level of data. The task's transition to "Done" is controlled not by a button in the interface or the executor's discipline, but by storage itself: if even one Must criterion is unclosed, the transition is rejected and the response returns the list of what remains. The gate lives below any client — it can't be bypassed from the UI, from a script, or by an agent's hand, because the ban is not in the client but in the layer everyone passes through.
The same principle scales to release: a rollout can be triggered not on a schedule but on a mechanically defined "green" — the smoke test on the build passed, zero new error signatures in the logs, no spike in server errors over a control window. The task's acceptance criterion and the release's readiness criterion are the same construct at two levels.
A human signature, not a flag
Separating roles is the heart of the loop: the executor does the work, a human confirms it, and these are different subjects. An agent can report "done" at 30% real completeness — the task is formally closed, the defect alive. The gate doesn't let this through: every closed Must criterion carries the name of the confirmer and a timestamp, and the confirmation record itself is protected against after-the-fact tampering (any change stays visible). "It just passed on its own" stops being an argument — behind every closed Must stands a specific person.
Consequence
The "closed but not done" defect is the most expensive class of bug in agent-driven development, because it masquerades as success. The loop removes it not with a rule that can be broken, but by construction: closing a task around an unclosed Must criterion is impossible, because the decision is made not by someone who can be talked into it, but by storage, which simply won't perform the transition.
Sources
- Behavior-driven development — Wikipedia.
- Dan North. Introducing BDD. Better Software, March 2006.
- History of BDD — Cucumber Docs (Gherkin, Given/When/Then).
- C. Solís, X. Wang. A Study of the Characteristics of Behaviour Driven Development. 37th EUROMICRO Conference on Software Engineering and Advanced Applications (SEAA), 2011, pp. 383–387.
- E. Evans. Domain-Driven Design (ubiquitous language). Addison-Wesley, 2003.