Review AI-Written Components Like a Dependency
October 23, 2026
Agents can now write more code than I can carefully review.
That leaves two bad options. I can read every line with the same attention, and the review queue becomes the bottleneck. Or I can skim, approve, and hope the tests caught what I did not.
Neither scales. But there is a kind of code we already depend on every day without reading it line by line.
External libraries.
When I upgrade a library, I do not read the full diff between the two versions. I read the changelog. I check whether the interface I use has changed, whether something was deprecated, and whether a fix affects behaviour I rely on. If something looks relevant, I dig into the details. Otherwise, I run our tests and move on.
That works for a reason. The library sits behind a boundary. It has a public interface, it does not reach into my database, and it does not quietly depend on my application's internals. If it breaks, the damage is usually limited to the places where I call it.
The boundary is what makes the light review reasonable.
I think we can apply the same idea inside our own systems. If a component has a clear enough boundary, an agent can write the code inside it, another agent can review it, and I can review the result the way I review a library upgrade: by looking at what changed at the boundary.
Imagine a component that turns invoice data into a PDF. It receives a structured invoice and returns bytes. It does not query the database, call other services, or read global configuration. A set of contract tests describes what it must produce for a given input.
An agent can rework the layout code, replace the rendering library, or fix an edge case with long line items. As long as the interface stays the same and the contract tests pass, the risk of that change is contained. The worst case is a bad PDF, not a corrupted ledger.
What I want to see is something like:
Fixed — Invoice PDF: Long product names no longer overflow into the price column.
Changed — Invoice PDF: Rendering now uses a different PDF library. Output is unchanged for the existing contract tests.
That is the same kind of entry I described in Give Every Pull Request a Changelog. Here it does even more work. For a well-bounded component, the changelog and the boundary are most of what I need to review.
Not every module qualifies. A folder with a nice name is not a boundary. For this to work, a component needs a few properties:
- a small, explicit interface that the rest of the system uses
- no hidden access to shared state, such as the database, global settings, or another module's internals
- dependencies that point in one direction
- contract tests that describe the behaviour at the interface, not the implementation
- limited side effects, so a mistake stays inside the component
Some of this can be checked mechanically. An import rule can stop a component from reaching into the rest of the codebase. CI can flag any change to the public interface or the contract tests.
That gives the human review a clear focus. Changes inside the component can be written and reviewed by agents. Changes to the boundary itself get my full attention: a new parameter, a modified contract test, a new dependency, or a new permission. Those are the changes that affect everything else, and they are usually small enough to review properly.
In particular, the contract tests should not be something the implementing agent can quietly change to make its own code pass. If a test at the boundary changes, a human should know why.
This approach does not fit everything. Authentication, billing logic, data migrations, and code that touches many parts of the system are hard to isolate, and mistakes there are expensive. I still want to review those changes closely, whoever wrote them.
And just like with libraries, sometimes the boundary will not be enough. A dependency occasionally ships a bug that its changelog does not mention, and then you have to look inside. The same will happen here. The difference is that it becomes the exception rather than the default.
There is a nice side effect, too. Clear boundaries make code easier for agents to work with in the first place. A component with a small interface and its own tests is a well-defined task. The agent needs less context, makes fewer assumptions about the rest of the system, and has a concrete way to check its own work.
So part of improving how we review AI-generated code is not about the review at all. It is about the architecture.
If you want to review less of the code line by line, design more of your system so that it does not need to be.