· 4 min read

Architecture as feedback for AI coding

Spanish version available: Versión en español.

One of the most useful principles when coding with AI agents is this: give them ways to verify their work.

A final tip: probably the most important thing to get great results out of Claude Code -- give Claude a way to verify its work.
Boris Cherny, X post

That verification can be very direct. Run the tests. Open the browser. Click through the UI. Check that the feature works for actual users.

But there is another kind of verification that matters too: feedback about whether the change fits the internal rules of the codebase.

Does this new code respect the intended architecture? Did it cross a boundary it should not cross? Did it import from a layer it should not know about?

That is the angle I care about here.

We already know this architecture idea

The architecture idea itself is not new.

We have had it for a long time under different names: layered architecture, Clean Architecture, Onion Architecture, Hexagonal Architecture. Different names, different emphases, same general instinct. Give the system a shape. Limit what each part is allowed to know about. Do not let dependencies spread arbitrarily.

So no, I am not proposing a new architecture pattern. If anything, I am arguing for resurfacing an old one.

On the frontend, this may look like routes depending on features, features depending on state and shared UI, and shared code not depending on product features. On the backend, it may look like API and infrastructure sitting at the edges, with application and domain logic protected from arbitrary coupling.

You can arrive at this from classic layered architecture, from hexagonal architecture, or even from something like Feature-Sliced Design on the frontend. The exact label matters less than the principle.

The principle is simple: dependencies should have a direction.

Architecture as feedback for agents

Traditionally, teams have tried to protect architecture with documentation, code review, and good intentions.

That helps, but it is not enough. Good intentions, as usual, do not compile.

Documentation explains the rules, but it does not fail the build. Code review catches some violations, but not all of them. And when AI is writing more of the code, small violations can appear faster simply because more code is being produced. Have you seen how often these things hallucinate?

Programmatic enforcement is not new. These tools and techniques existed before AI coding. My point is that they deserve more attention now that agents are writing more code, faster.

Tools like eslint-plugin-boundaries, dependency-cruiser, and even targeted no-restricted-imports rules let the codebase check those restrictions automatically. You can think of them as architectural fitness functions. Instead of relying only on documentation and memory, the codebase can verify its own structural rules.

That changes the role these checks play in an AI-assisted codebase. Without enforcement, the architecture is mostly a request: "Please do not import from there." With enforcement, it becomes feedback: "That import is not allowed. Try again." This matters a lot when an agent is doing the work. Agents respond very well to feedback loops. If the linter or CI tells the agent that it crossed a forbidden boundary, it can often correct itself and try a better design.

Verification goes both ways

When people talk about verifying AI-generated code, they often mean user-facing verification:

  • does the test suite pass?
  • does the browser flow work?
  • does the UX feel correct?

That is necessary, but it is only half the story.

There is also structural verification:

  • did the new code stay within the allowed layer?
  • did a feature reach into another feature's internals?
  • did something "shared" quietly start depending on product code?

These violations are easy to miss in a PR because each one can look reasonable in isolation. A one-line import does not feel dramatic. Neither does the next one. But enough of those shortcuts and the codebase loses its shape.

That is why I like the idea of a self-defending architecture. The codebase itself should help preserve its structure through checks that fire early and automatically.

Suppose an agent is building a feature and reaches for a module across an unallowed boundary. The lint rule fails. That failure is useful information. And the agent will fix it and refactor the code without you even having to intervene.

That is the part I want to highlight. Verification for AI coding is not only about whether the feature works for users. It is also about whether the change respects the shape of the codebase. Tests, browser automation, and architecture checks all serve the same purpose: they give the agent feedback in real time.