Coding agents write most of the code at Ayion. This is not a prediction or a pilot scheme, it is how the work is organised, and it is worth writing down honestly because a lot of what gets said about it is either triumphal or fearful and neither is much use to someone deciding how to run a team.
The short version: the middle of the job got much faster, and the two ends got harder. Everything interesting follows from that.
The work moved to the ends
Take an ordinary change: a new control that blocks an action when a budget is exhausted. Traditionally that is a couple of days of work, most of it typing, with the thinking distributed unevenly through it. A good engineer does the design while writing, notices the awkward case at line ninety, and adjusts.
Hand the same change to an agent and the typing collapses to minutes. The design does not. It moves entirely to the front, because an agent will implement whatever it is given, at speed, with great confidence, and without the moment of doubt at line ninety. Then the proving moves entirely to the back, because the usual signal that a human wrote something carefully — the diff looks laboured over — is no longer available.
So the shape of the job is: specify hard, generate fast, review as if a stranger wrote it, verify against tests that would notice if it were wrong.
What a specification has to contain now
The specifications we write are longer than they used to be, and the extra length is almost all in one place: what the code must refuse to do.
A specification that says what should happen is enough for a person, because a person fills the gaps with judgement about what obviously should not happen. An agent fills the gaps too. It fills them with the most statistically ordinary thing, which is frequently a reasonable-looking default that quietly widens the behaviour.
So a specification here carries, at minimum: the interface and its types; the states the thing can be in and the transitions that are legal; the invariants that must hold after every operation; the cases where the correct behaviour is to stop and raise rather than proceed; and the failure modes with the expected handling for each. If the change touches a control, it also carries the exact condition under which the control blocks, the record of that block, and what the caller sees.
Writing that takes longer than writing the code used to. It is also the artefact that survives: it is what the review is conducted against, and what the tests are derived from.
Generated code is third-party code
This is the rule that does the most work, and it is not a metaphor. Code written by an agent has the same properties as code from an outside contributor you have never met. It may be excellent. It was not written with the context in your head. It follows conventions it inferred rather than ones it was taught. And nobody on the team has yet put their name to it.
So it gets read the way third-party code gets read. Line by line, by a person who did not produce it, with particular attention to the parts that were not in the specification — because the parts an agent adds unbidden are where the interesting mistakes are. A helper that silently catches an exception. A retry that turns one action into two. A default parameter that widens a permission.
Nobody approves their own diff here, and that includes diffs an agent produced on their behalf. The person who prompted it is the author, not the reviewer.
Two habits make the review possible rather than theatrical. Diffs stay small enough that a reviewer can hold all of one in their head at once, which usually means a change is broken into several. And the agent is asked to explain its own diff — what it chose, what it rejected, what it assumed — because the explanation is much faster to check than the code, and a bad explanation is a reliable signal to go and read the code very slowly.
Tests that fail on purpose
A passing test suite is a weak fact, of the same family as a tool call that returns success: it tells you a thing ran, not that the thing is true. Agents are extremely good at producing code that passes the tests it can see, which makes the weakness of the fact worse rather than better.
The rule we use is simple to state and slightly annoying to follow. For every control, there is a test that fails when the control is removed. Not when the code is deleted — when the control is neutered while the surrounding code still works. Take out the threshold check, leave everything else, and something must go red.
That test is the deliverable, as much as the control is. It is also the honest answer to “how do you know the guardrails do anything”, which is a question every serious buyer of this kind of software eventually asks, and which a coverage percentage does not answer.
The same thinking runs through the product, for the same reason. A control that has never blocked anything has not been shown to work, which is why the exceptions are the most valuable part of an evidence pack.
What agents are worst at
Worth saying plainly, because the failure modes are not the ones people expect.
Agents are not especially bad at writing correct code. They are bad at knowing what should exist. Asked to make something work, they will make it work, including by adding a concept the system did not need and now has to carry forever. Architecture is the thing a person holds, and holding it means saying no to several reasonable-looking additions a day.
They are also bad at telling you the specification is wrong. A person given a contradictory brief pushes back within a paragraph. An agent implements both halves of the contradiction and leaves the seam for you to find. So the specification review — a person reading the specification before anything is generated, looking for the parts that cannot both be true — is a real step rather than a formality.
Two things we will not trade
First, nobody approves their own work, whoever or whatever typed it. The moment that slips under deadline pressure, the review stops being a control and becomes a queue.
Second, nothing ships in enforce mode — where a control can block a real action in a customer’s system — without an external penetration test first. Not for a deadline, not for a pilot, not for a demo. A system that is allowed to stop a payment is a system worth attacking, and we would rather find that out from someone we paid than from someone we did not.
Neither of those is a claim about how well this works. It is how the work is arranged, and it is arranged that way because the alternative is a fast team shipping confident code that nobody has read into a product whose entire proposition is that it can be checked.