Agents write the code. People write the scenarios.

AI agents can turn a ticket into a merged change today. A green build still does not prove that the agent understood what was wanted. On our own products we work with a fixed chain, Spec → ADR → Feature, that puts the human at the start of the process instead of the end.

There is a lot of talk about “dark factories” for software: an issue goes in, a release comes out, and nobody touches anything in between. For small, well-described changes we are close to that. For anything that carries risk, the deciding factor is not how autonomous the agent is. It is whether anybody wrote down, precisely enough, what “correct” means.

This article describes the process we use when agents implement our own software. The first half is for anyone who is responsible for a product. The second half shows what the artefacts look like.

A green build proves only what was written down

Imagine a service portal for machine operators. A customer exports the service reports for their fleet and receives the reports for another customer’s machines along with them. Every test passed, and the code did what the ticket said. The ticket simply never said that an export must contain only the requester’s machines.

That is the typical failure of agent-built software, and of human-built software too. The code has no bug. A requirement was never stated. Agents make this worse in one specific way: they are very good at making tests pass, including tests they wrote themselves from their own reading of the task. If the same agent interprets the requirement, writes the code and writes the check, nothing has been tested independently.

So the useful question is not “how much may the agent do?”. It is “who decides what done means, and is that decision fixed before the agent starts?”

The chain: Spec → ADR → Feature

Before any implementation, we fix three artefacts in this order. Each answers a different question, and each has a person who owns it.

  1. 01SpecWhat must be true, and what is out of scopePerson
  2. 02ADRWhy we decided it this way, and what we rejectedPerson
  3. 03FeatureScenarios that define “done” in plain sentencesPerson approves
  4. 04ImplementationCode, tests and documentation drafts against the scenariosAgent
  5. 05GatesChecks the agent did not write and cannot changePipeline
  6. 06ReleaseSign-off on the basis of the evidence producedPerson
People spend their time on steps one to three and six. The agent spends its time on step four. Step five checks the agent’s work against something it did not write.

Spec: what must be true

The specification states the system’s obligations in normative language: MUST, MUST NOT, SHOULD. It says what is in scope for this version and, just as importantly, what is not. It defines data formats and interfaces precisely enough that two independent implementations would produce the same result. Ours also contains a list of claims the product must never make. That list matters later.

A spec is not a ticket. A ticket describes a change. A spec describes the state the system must be in after every change.

ADR: why we decided it this way

An Architecture Decision Record documents one decision: the context, the decision itself, the alternatives we rejected and the consequences we accept. It has a status. An agent may draft an ADR, but only a person moves it from Proposed to Accepted.

An example from one of our own products, a workflow in which several parties approve a document. The first version recorded “party 1 approved” in its evidence. Months later, nobody could have said who party 1 was. The ADR that fixed this decided to bind the party’s verified identity into the signed evidence. It also decided what not to claim. The e-mail address is verified. The display name, typed in by whoever started the process, is not, and the record says so plainly. An agent would not have invented that second half. It is a judgement about honesty, not a technical choice.

Feature: what “done” means, in sentences

The feature file turns the spec and the ADR into scenarios written in Gherkin, a structured plain-language format: Given a situation, When something happens, Then this must be true. Because it reads like ordinary sentences, a quality manager or an auditor can check it without reading code. And it runs like a test.

Here is one scenario from the same product, slightly shortened. In sequential mode, parties approve in a fixed order, and someone whose turn has not come must not learn who is holding things up:

@feature:F-020 @p0 @security
# Traceability: ADR-016, THREAT_MODEL.md
Feature: Sequential approval

  Scenario: An out-of-turn rejection does not reveal who is blocking
    Given a sequential process with several parties still outstanding
    When a later party submits out of turn
    Then the rejection is identical regardless of which predecessor is outstanding
    And it never names the outstanding predecessor

Three things are worth noticing. First, the scenario describes something the system must not do. Agents rarely come up with negative scenarios like this on their own, and this is exactly the kind of scenario the service portal was missing. Second, the tag @p0 marks it as release-blocking. Third, the traceability line links it to the decision it comes from and to the threat model, so a reviewer can follow the chain in both directions.

Then the agent builds, inside the lines

Only now does an agent implement. It writes the code, the glue that connects the scenarios to the code, unit tests and documentation drafts. It works against the feature files and does not edit them to make them pass.

Some rules are stricter still. Reference values, for example the expected output of a cryptographic function, are marked as normative in the repository. An agent that changes an expected value to turn a test green has broken a rule. It has not fixed a bug.

The pipeline then checks the result, independently of the agent:

  • Every release-blocking scenario must be automated, or explicitly marked as a manual check with a written justification. A failing one stops the release.
  • Every release-blocking feature file must reference at least one ADR, and every security feature must reference the threat model. A script checks this on every change, so the chain cannot quietly break.
  • A claim check scans product texts and documentation for statements the product cannot back up, in English and German. An agent drafting copy cannot promise more than the spec allows.
  • The release notes must point to the passing evidence for every release-blocking feature, together with the decisions behind it.

Where the human stays in the loop

Put together, the person is not at the end of the line, reviewing a diff thousands of lines long. The person sits at the four points where judgement is needed: changing what the system must do, accepting a decision and its trade-offs, approving what “done” means, and signing off a release on the basis of evidence. Everything in between runs as a loop between the agent and the pipeline.

PERSON AGENT PIPELINE agent works only inside these limits defines done may not edit submits change fail: agent fixes pass + evidence wrong? revise Spec ADR Scenarios Sign-off Implement Gates

Swipe to see the whole diagram.

The agent works between two things it does not own: the scenarios above it and the gates below it. A failing gate sends the work back to the agent. A scenario that turns out to be wrong goes back to a person.

Everything between those points can be delegated, because it is checked against something the agent did not write. For us, that is the difference between vibe coding and agentic engineering. The degree of autonomy is not the issue. What matters is whether the autonomy runs inside boundaries that people own.

Why this matters to manufacturers, not only to software teams

If you place products with digital elements on the EU market, the Cyber Resilience Act will ask for technical documentation that shows how you addressed the security requirements, and for vulnerability handling that keeps working for years. Gherkin is not a CRA requirement. But the chain above happens to be a very practical evidence format:

requirement → decision → scenario → automated test → release evidence

You can trace each security decision from the requirement to the test that proves it, and the evidence is produced with every release instead of being assembled before an audit. That is the pipeline we describe in question five of our article on whether the CRA applies to your product.

The same logic carries over beyond software. Wherever an agent takes over routine work, in a quality management system or in supplier assessments, the question stays the same: who defines what “correct” means, and is it written down before the agent starts?

What it costs, and where it does not fit

None of this is free. Writing a spec, an ADR and scenarios takes time, and for a typo fix it is overkill. We use the full chain for changes that touch behaviour, security or evidence, and a lighter path for the rest.

Scenarios can be wrong too. A green build now proves that the result matches what a person decided. It does not prove that the person decided well. That is still a better position, because the decision is visible and can be reviewed, but it does not remove the need for people who understand the domain.

And the bottleneck moves. Implementation stops being the slow part, and precise specification takes its place. In our experience that is the right bottleneck to have.

How we help. For manufacturers under the CRA, this chain is what turns every release into evidence. We start with the CRA applicability check: which of your products are affected, in which class, and why, at a fixed price with the result in two weeks. If the answer is yes, release evidence from your own pipeline is the ongoing service that follows. Product Security & CRA

How to start

  1. Pick one change that matters, not a greenfield project: something that touches behaviour a customer would notice.
  2. Write three to five scenarios for it before anyone implements, including at least one about what must not happen.
  3. Write down the one decision behind it as a short ADR: context, decision, rejected alternatives, consequences.
  4. Let the agent implement against the scenarios, and do not allow it to change them.
  5. Add one pipeline check that fails the build when a release-blocking scenario fails. Then look at what your release notes can say now that they could not say before.

Gherkin is a notation, not a legal requirement. This article is general information, not legal advice. References to the Cyber Resilience Act refer to Regulation (EU) 2024/2847 as adopted.

Next step

Want every release to come with its own evidence?

Start with the CRA applicability check: a classification per product family with the reasoning written out. Fixed price, result in two weeks.