AI Wrote the Code. Now Who Owns the Architecture?
Imagine the following scenario: You give an AI agent a development task:
Add an endpoint that lets customers update the shipping address for an order
A few minutes later, you have an endpoint, validation, business logic, database changes, unit tests, and so forth. Everything compiles. The tests all pass. The feature works…
And the architecture is a mess.
If an AI agent writes most of the implementation, who is responsible for maintaining the architecture?
Guess what??? You are.
Local Optimization
AI is really good at local optimization. The agent is usually focused on one thing: satisfying the task that was put in front of it.
If the requirement is: Allow customers to update the shipping address for an order, the easiest implementation runs straight from the endpoint to the table. But your application’s dependency rules probably look more like the right-hand column below, where each arrow means “depends on”:
Both implementations can work just fine, but only one of them actually respects the architectural decisions that you’ve already made.
A Thought Experiment
Let’s imagine a .NET application with the following projects in our solution:
Store.Api
Store.Application
Store.Domain
Store.Infrastructure
We’ve also defined the following architectural rules:
- API doesn’t directly access EF Core.
- Domain has no infrastructure dependencies.
- Business rules live in the domain/application layers.
- Infrastructure implements persistence.
- Endpoints remain thin.
- Tests should exercise business behavior independently of infrastructure.
Then we give the AI coding agent a normal requirement to fulfil.
Add the ability for a customer to change the shipping address for an order. Validate the address and prevent changes once that order has shipped.
Don’t tell the agent how to implement it. Let it decide what approach to use.
The AI Implementation
You never know what an agent left to its own devices will implement. It might come up with something like this:
app.MapPut("/orders/{id}/address", async (
Guid id,
UpdateAddressRequest request,
AppDbContext db) =>
{
var order = await db.Orders.FindAsync(id);
// Omitted: check that the order exists and belongs to the customer,
// validate the address, and reject changes if the order has shipped.
order.ShippingAddress = request.Address;
await db.SaveChangesAsync();
return Results.NoContent();
});
This isn’t necessarily bad code. Assuming the omitted checks are implemented, it can fulfil the functional requirement. In a small, simple application, you probably would implement something similar. But you’re not creating a simple application. You’re creating an enterprise-level application, and this code violates the architectural decisions that have been laid out for the application in question.
Drift
This deviation represents architectural drift. It’s a shortcut around the intended design. One shortcut isn’t catastrophic. But repeat this across dozens of AI-generated changes:
Eventually, the architectural diagram represents the application you designed, not the application that got built. This isn’t uncommon. Drift happens even amongst the best development teams. The problem is that AI can accelerate this drift because it can implement changes so quickly. It’s both the advantage and the disadvantage of AI coding.
But the Tests Pass?!?!?!
Sure. Anyone can write passing tests. AI can write them faster. Assume the omitted checks are implemented and the functional tests pass:
Does the feature work? Yes.
Does it compile? Yes.
Does it handle errors and behave properly? Yes.
Automated tests protect those concerns. But functional correctness is not the same as architectural correctness.
Architecture Has to Be a Requirement
Let’s revisit the thought experiment with the same functional requirement:
Add the ability for a customer to change the shipping address for an order. Validate the address and prevent changes once that order has shipped.
Then add more explicit architectural constraints. For example:
Implement this feature following the existing Clean Architecture structure. API endpoints must not access DbContext directly. Business rules belong in the Domain or Application layer. Infrastructure concerns must remain in Infrastructure. Domain must not reference Infrastructure. Follow existing patterns in the repository before introducing new abstractions.
The goal is an implementation that satisfies the same requirement while respecting the boundaries we’ve defined. AI can follow those constraints, but we have to make them explicit and check the result.
Give Your AI an Architecture Manual
You don’t want to have to lay out those constraints with every prompt. You’ll get tired of it, and you’ll forget sometimes. Don’t assume instructions from a previous thread carry into the current one.
So, instead of repeating architectural rules in every prompt, keep them in a repository-level instruction set. The exact method varies by agent. Put the rules in a Markdown document, then use the agent’s instructions file, such as .github/copilot-instructions.md or AGENTS.md, to point to it. Tell the agent to read and follow those rules whenever it implements a requirement.
For example, a file structure like this:
/docs
architecture.md
testing.md
coding-standards.md
/.github
copilot-instructions.md
And in the copilot-instructions.md file, include a section like:
- The application follows an architectural pattern as laid out in the /docs/architecture.md file. Whenever you implement new code, read and follow the architectural guidance defined in that file.
This tells the agent to read architecture.md before implementing changes. It gives the agent guidance to work from, but you still need to check that the resulting code follows it.
Your architecture document doesn’t need to be extensive. It might simply document the following items:
- Layer responsibilities
- Dependency rules
- Approved patterns
- Forbidden dependencies
- Testing expectations
- Naming conventions
- Examples of existing implementations
All you need to do is write your architecture document with both AI coding agents and humans in mind.
Make Your Architecture Executable
Documentation tells the agent what it should do. Tests can tell you when it didn’t follow those rules. You can run those checks automatically. For example, if you have defined the following rules:
There are plenty of ways you can enforce those rules, including architectural tests, project-reference restrictions, analyzers, dependency tests, and CI pipeline checks. And there are a bunch of different tools and libraries to help implement all those. But having such enforcement in place can also help the AI know when it has broken the rules and needs to fix how it implemented the code.
Your Job Is Changing
Like it or not, your job as a developer is fundamentally changing. Traditionally, a developer’s time was largely spent producing implementation. These days, a lot of your time is spent defining constraints, describing intent, and then reviewing the results. The question is increasingly shifting from Can I write this code? to Can I define what good code looks like clearly enough that something else can produce it?
Historically, that was largely the responsibility of the architect. Now, it’s really become the job of every developer from top to bottom.
AI Makes Good Architecture More Important Than Ever
One assumption seems to be growing in the industry:
If AI can rewrite software easily, maybe architecture doesn’t matter as much anymore.
I think that gets it backward. Rewriting code still costs time and money, and someone has to understand and review the result. AI increases the rate of change. If a team goes from 10 changes per week to 30 with AI, architectural mistakes could accumulate three times as quickly too, assuming the same architectural error rate.
AI can reduce the cost of producing code. It doesn’t automatically reduce the cost of understanding that code. And if the architecture isn’t thought through and enforced, the cost of maintaining that code can grow. So boundaries, conventions, and proper architectural constraints have become more important and more valuable than ever before.
The Architecture Feedback Loop
Let’s look at everything in a single workflow:
That last step is critical. When the agent repeatedly makes the same mistake, don’t just correct the generated code. Revise the architectural guidance to improve the instructions or automate the guardrails so that the same category of mistake is less likely to slip through again.
Conclusion
The AI wrote the code.
The AI wrote the endpoint.
The AI wrote the tests.
The AI created the migration.
The AI may have done 80% of the work. But it can’t own the consequences of the architectural decisions that it makes. In the end, as the developer, you still own the architecture. You still own the output. It’s your responsibility. So remember this, if nothing else:
The future of software development will probably involve a lot less typing of code. But it will require considerably more thinking about constraints, boundaries, and intent. AI can write your code. You still own it.


