Automating Code and Change Review With AI, Under Approval Gates
Let AI find problems in code and change review while a person approves, with gate ledgers and what to automate.
You automate review safely by splitting it in two. An AI reviewer finds and proposes: it reads the change, lists what looks wrong and says why. A person approves: they decide which findings matter and whether the change goes ahead. The reviewer can be fast, tireless and wrong, so nothing it produces should be able to merge, deploy or close a finding on its own authority.
This post describes the patterns we use and the ones the product supports, with the status of each stated plainly. Several are working practices on our own code. Some are built in the product but not run by us. A few are design intent. One content pipeline of ours uses an AI check where a person would be needed for real approval, and we say so below.
Why separate finding from approving?
Because the two jobs fail differently, and mixing them hides the failures.
A finder's mistake is a false alarm or a miss. Both are tolerable if a person is looking at the result: a false alarm costs a minute, a miss is covered by the next layer. An approver's mistake is a bad change that proceeds. If the same AI that raised the concern also decides it is resolved, there is no independent check left.
So keep three rules. The reviewer's output is a document, not an action. Closing a finding needs evidence, ideally a commit or a test result that someone can open. And the approval of the change itself is recorded as a decision by an identifiable person, not inferred from silence or from the absence of objections.
This is the same idea as controls that run at the point of action instead of afterwards, which why AI governance must run at runtime argues in more detail. Review is one place to apply it.
What does an adversarial review document look like?
In use at Swfte: our Cortex application repository holds dated review documents written to find faults, not to praise. One backend review states at the top that it was a read-only pass and that no code was modified by it. It then lists numbered findings, each with what is wrong, where, and why it matters. A separate review of the user interface lists its findings and ends with a closure table: for each numbered finding, the commit that closed it. A production-readiness review reached a verdict of "release blocked" and said why.
Three features make this pattern worth copying. The review is read-only, so the reviewer cannot quietly fix what it finds and hide the evidence. The findings are numbered, so a later reader can ask what happened to number nine. And the closure table turns "we fixed things" into a list that a person can check line by line.
A caution about provenance. These documents do not name their reviewer. The vocabulary in them points to our multi-agent working method, so we describe them as AI-assisted by inference, not as a stated fact. If you adopt the pattern, name the reviewer in the document. It matters to anyone relying on the result.
How does a gate ledger work?
A gate ledger is a list written before the work starts. Each gate has three parts: a command to run, the result you expect, and a place to record the evidence. When the work is finished, you run each command and paste in what happened, such as an exit code or a checksum.
The rule that makes it honest is this: a ticked box without evidence counts as unmet. Ticking a box is an opinion. Evidence is something a second person can re-run. If the evidence line is empty, the gate is open, however confident the agent sounded when it reported back.
In use at Swfte: the audit of our Cortex application used a ledger of this kind, where every gate pairs a check with an expected result and recorded evidence, and an early gate checks the ledger itself. One gate concerned a real, paid test transaction, which had to be refunded or explicitly marked as kept by the owner. The handover note said the owner's decision must not be inferred from a commit request or an automated hook. Later, the owner made the decision and it was recorded. That is a small case, but it shows where the line sits: automation prepared the question, a person answered it.
Our website's ledgers are less tidy. Only some of their gates carry a runnable command; many rest on written evidence. The automated review page explains where that leaves us, and we would rather say so than imply the website matches the stronger example.
Who approves the command that runs a check?
A gate is only as trustworthy as the command behind it, so decide who may run what.
The pattern is straightforward. The agent proposes a command. A person approves that exact command. It runs. The output is recorded against the gate. Without the approval step, an agent can reach a passing result by changing the check, running a gentler variant, or writing the evidence line itself.
Built in the product: when Cortex hands coding work to an agent through Nexus, shell commands belong to run mode, calls that policy flags are held and shown as approval cards, and an unanswered prompt times out into a denial. Nexus also has a completion-gates command, and Cortex exposes tools to delegate a task, verify it and read the audit. Approvals are bound to the exact call that was shown. We covered the controls in shipping faster with an AI workspace and dev tools. The product side is on the Nexus page.
If you build this yourself, give each approval three properties: it names the command, it expires, and it cannot be reused for another command.
Is an AI fact-check gate the same as human approval?
No. It is automated quality assurance, which is useful and different.
In use at Swfte, as definitions: we have workflow definitions in Swfte Studio for our content and audit pipelines. They include review gates, and those gates are LLM reviewers. They check drafts against sources and send work back. There is no human step in them. Nothing in the repository tells us that they currently run in production, so we describe them as definitions, not as a live process.
The distinction matters because the word "gate" suggests a person has looked. An LLM fact-check can catch a wrong figure or an unsupported claim. It cannot take responsibility, and it can be wrong in the same way as the model that wrote the draft. If publication has consequences, such as a regulated claim or a statement about a customer, add a human input step before it goes out. Studio's workflow engine has a node that pauses a run, addresses a person, applies a timeout and branches on approve or reject. Our workflow pages describe it, and Studio is where it lives.
Say which kind of gate you have. "Reviewed by an AI check, then published" and "approved by Name" are different statements, and a reader deserves to know which one applies.
What happens when hosted CI is unavailable?
You run the same gates locally, from one script, and you say that you did.
In use at Swfte: for a period, hosted continuous integration for our Cortex application was unavailable, because of a billing problem with the hosting provider, and every workflow failed immediately. Nothing gated a merge. Our runbook recorded this and pointed to a single local script that runs the same gates: toolchain, lint, format, type check, translations, unit tests, release scripts, secret scanning and a dependency-advisory comparison against a baseline.
Two lessons. First, a gate that lives only in a hosted pipeline disappears when the pipeline does, so keep a local equivalent and write down how to use it. Second, we also had a workflow configured to have an AI reviewer comment on pull requests. During that period it did not run, and we have no posted AI pull request review to show you. So we are not claiming that AI pull request review is running, only that the workflow is configured.
What kind of finding does an AI review surface?
The useful ones are about how a control is built, not about style.
One finding in our backend review is a good example of a class worth testing for. It observed that the model chose who reviewed its own gated action: the person to whom an approval request was addressed was read from arguments that the model itself controlled. Whether any given system has this flaw depends on how its approvals are built, and we are not saying here whether ours has been fixed. As a pattern it is worth a test in your own system: can the agent influence who approves, how long the request waits, or what the approver sees?
Related questions deserve the same suspicion. Can the requester approve their own request? Does a timeout approve or deny? Does the approver see the same action that will run? Approver-differs-from-requester is design intent in our platform, not something it enforces today, so if you need separation of duties you enforce it by how you assign gates. The approvals and governance page is candid about that.
What should you automate first?
Start where a wrong answer is cheap and the evidence is easy to check.
- Read-only review of existing changes. Let an AI reviewer produce numbered findings on pull requests or on a module. It changes nothing, so it can be wrong safely.
- Mechanical checks. Move every rule you can into a script that fails the build. The cheapest review is the one a machine does.
- Evidence collection. Have the agent run the approved checks and fill the ledger. A person reads the ledger.
- Triage of findings. Let it group and rank. A person still closes each one.
- Anything that acts. Merging, deploying or changing access comes last, and stays behind a named human approval.
The same ordering applies outside code. Our post on AI SOC agents and human approval works through it for security operations, and the AI agent governance page sets out the general model.
What is built, and what is design intent?
In use at Swfte: dated, read-only review documents with numbered findings and closure tables; gate ledgers with a command, an expected result and recorded evidence; owner-decided steps; a local script that runs the same gates when hosted CI is down; and Studio workflow definitions whose review gates are LLM reviewers with no human step. Built in the product: Nexus-governed delegation to coding agents with held calls, approval cards and timeouts that deny, plus a workflow node that pauses for a person. Designed for: enforcing that an approver differs from the requester, and a single approval record across the platform. Exact fit depends on your use case, deployment and configuration, and nothing here is legal advice.