A follow-up to Designing Tech Stacks for AI-Generated Code
AI agents are moving from code generation into live system intervention. That transition changes what "good architecture" means, and most current stacks are not designed for it.
The previous piece was about reducing the surface area agents have to reason about when writing code. This one is about a harder question: what architectural conditions make it safe for an agent to modify the thing it's already running on?
Two different problems
There is a meaningful gap between an AI agent that writes code and one that maintains a running system. The first is a productivity story. The second is an architectural one, and it's the one the industry has not seriously engaged with yet.
When an agent can not only write a schema migration but also apply it, validate the system's behavior afterward, and roll back autonomously if something looks wrong, the infrastructure is no longer a static target. It is a dynamic surface the agent is continuously touching. That is a different class of problem.
Self-modifying software is not new. Stored procedures, metaprogramming, adaptive systems: code that changes its operating environment at runtime is as old as the discipline. But those patterns were always bounded. A program adjusted its internal state within a runtime. The schema, the API contracts, the deployment configuration were maintained by humans, on a different timescale, with different tools.
What agents introduce is a collapse of that boundary. The autonomous loop writing the migration is the same loop running the system. And that changes the question you have to ask about architecture fundamentally.
What the failure looks like
Before the theory, the concrete case.
An agent adds a column to a user profile schema. Simple enough. But in a conventional multi-service stack, here is what that change touches:
The database migration runs. The new column exists.
The cache layer is still serving serialized user objects in the old shape. It does not know the schema changed.
The API layer has deserialized expectations about the structure of that data. Its contracts are now subtly wrong.
Background jobs consuming user events were written against the old schema. They will silently handle the new shape incorrectly, or fail loudly, depending on how they were written.
The agent attempts a rollback. The database reverts. But the cache is still populated with objects that were written during the window when the new schema was live. The message queue still has events that were produced in that window. The rollback does not reach them, because rollback is a database primitive, not a system primitive.
This is not an edge case. It is the ordinary failure mode of autonomous change in a fragmented architecture. Each component has its own notion of version, its own failure mode, and its own rollback semantics. There is no system-level transaction boundary. The agent modified a distributed agreement, not a thing.
Now contrast the same change in a unified runtime, where database, cache, application logic, and messaging are the same in-memory process deploying as a single atomic unit. Either the new version is running or the old version is running. The cache cannot hold objects in the old shape because the cache is the same process as the database. The API layer cannot have deserialized expectations that diverge from the schema because they are derived from the same schema definition. Rollback means rolling back one artifact, not coordinating across five systems with different rollback mechanics.
The failure mode does not disappear. But the blast radius is bounded by a coherent system boundary, not distributed across a web of implicit contracts.
Coherence as a prerequisite
Here is the thesis: safe self-modification requires a coherent self. That sounds philosophical, but it has a precise architectural meaning.
A system has a coherent self when there is a single shared notion of version, state, and transaction boundary. When you can answer the question "what is the system's current state" with one answer rather than aggregating across multiple components that may have diverged.
It's worth being precise about what this does and does not mean. Coherence is not the same as monolithic. Formally coordinated distributed systems, well-typed service contracts, transactional deployment patterns, migration frameworks that enforce compatibility across versions, and policy engines that make inter-service dependencies legible are all genuine paths toward a more coherent distributed system. Teams with deep investment in those approaches are not doing it wrong.
But there is a structural argument for why runtime coherence, fusing the components into a single process with a shared transaction model, is particularly suited to the self-modification problem. It is not just that the agent can reason about fewer files. It is that the agent can reason about the change as an atomic operation against a unified state. Deploy, validate, roll back: one action, one artifact, one audit trail. The alternative requires the agent to coordinate that sequence across components whose failure modes interact in ways that are difficult to observe and harder to reverse.
The unified runtime is a strong answer to the self-modification problem. It is not the only answer. But it is the one where the guarantees are structural rather than procedural, which matters when the entity enforcing those guarantees is an autonomous agent rather than a careful human.
The constraint that cannot live inside the system
There is one piece of this architecture that cannot be automated, and it is worth being direct about it.
The permission model for agent self-modification cannot live inside the agent. It cannot live inside the system the agent is modifying. It has to be external and structurally inaccessible to the agent itself.
This is not a novel security principle. It is the same logic that makes a well-designed access control layer work: the control layer is not accessible to the entities it controls. We are applying that principle to a new kind of entity.
What this means practically: the agent operates against a defined API surface that enforces what it can read, write, and deploy. That surface is not controlled by the agent. Certain schema primitives are immutable to the agent regardless of its reasoning. Core identity structures, audit log tables, and permission tables: not writable by an agent under any circumstances. Every action the agent takes is logged to an append-only audit trail that the agent cannot modify or delete.
An agent that can grant itself new permissions is not a safe agent. The coherent runtime buys you legibility. The external permission boundary buys you control. Legibility without control is a transparent but ungoverned system. Control without legibility is a safe but opaque one. You need both, and they require deliberate design rather than emergent safety from capable agents.
The hard edges we have not solved
The honest version of this argument has to name what we do not know.
Schema evolution under live load is a genuinely hard problem that the unified runtime framework does not fully resolve. Backward and forward compatibility, dual writes during transitions, schema version skew across concurrent clients, and the observability lag that makes autonomous validation difficult during partial rollout states are all real constraints. A coherent runtime makes these problems more legible. It does not make them disappear.
We do not have a strong empirical answer to where the right boundary sits between what an agent can safely modify autonomously and what requires human review. The intuitions are informed but not validated at the scale and concurrency that real multi-tenant systems operate at. Many agents operating against shared infrastructure with different permission surfaces is a genuinely open problem.
And the failure mode of an agent that reasons confidently but incorrectly about the downstream effects of a change is not well characterized. Human error tends to occur at human speed, with natural review steps built into workflows. Agent errors can compound across many instances before anyone notices, faster than any human escalation path.
The teams with the right instinct are the ones asking hardest about rollback semantics and audit trails before they ask about capability. Open-source, non-critical paths, and environments with instrumentation to closely observe agent behavior are where this should be proven out before it reaches regulated or high-stakes systems.
Where this leaves the architecture conversation
The previous piece described a shift in evaluation criteria: not just "how productive is a human developer on this stack" but "how well does an AI agent perform against this architecture." Stacks that score well on both dimensions will have an advantage.
This piece describes the next frame after that one. Not just stacks that AI can write against, but stacks that AI can maintain, modify, and redeploy autonomously. Infrastructure that is not just a target but a participant.
The prerequisite for that is not more capable agents. It is infrastructure with a coherent self to reason about and a permission boundary that the agent cannot reach. Both of those are design decisions that can be made now, before the agents are sophisticated enough to act on them.
Most of the conversation about AI and backend architecture has been about what the agents can do. The more consequential question is what we build for them to do it against.
Top comments (0)