For decades, the software industry has treated a particular sequence as gospel: specify first, build second. Write the requirements document. Design every interface. Plan every module. Only then, after months of upfront analysis, write the first line of code. The logic was sound. Planning was cheap. Coding was expensive. Every hour of specification saved ten hours of rework. This worked when production was the bottleneck.
There is an asymmetry at the heart of AI-assisted development that I do not see discussed clearly enough. Production speed has accelerated dramatically. A competent developer with Claude Code can now generate code at 10 to 66 times the traditional rate. This is real and verified. I have the commit logs and the timelines to prove it. But comprehension speed has not accelerated at the same rate. Reading code, understanding architecture, finding the right file in a 700-file codebase. These are roughly where they were before AI arrived.
For most of my career, analysis meant asking a question and getting an answer. How many deployments last quarter? Which modules have the most open defects? What is the test coverage of the payment service? The tools were built for this. You formulated a query, you ran it, you got a number. The number was correct. And the quality of your insight was entirely bounded by the quality of your question.
I did not think of this as a limitation. It was just how analysis worked. You got better at it by learning to ask better questions. Thirty years of architecture experience is, in large part, thirty years of learning which questions to ask and in what order. The senior architect's advantage was not access to better data. It was knowing which query to run.
That model is breaking. Not because the tools got faster at answering questions, but because a new class of tooling -- AI-augmented, temporally aware, relationship-tracking -- does something structurally different. It does not just answer your question. It tells you what you should have asked instead.
Most writing about AI agents is aspirational. Autonomous systems that plan, reason, and execute complex workflows end-to-end. The vision is compelling. The reality, after building and running agents in production across multiple projects, is more mundane and more useful. The patterns that survive contact with real workloads are not the clever ones. They are the simple ones that fail in predictable ways.
What follows are five architectural decisions that made the difference between agents that reliably complete tasks and agents that confidently fail. None of them are universal. Each has a specific context where it works and a specific context where it does not. I have learned both sides, sometimes expensively.
Most systems I have built over thirty years answer one question well: what is the current state? A database query returns the latest row. A service responds with the live configuration. A dashboard shows what is happening right now. Current state is the default, and it is sufficient most of the time.
Some systems go further. They add history. An audit table, an event log, a change data capture stream. Now you can answer: what was the state at time T? Useful for compliance, useful for debugging. But still a limited question, because history stored as a sequence of snapshots tells you what changed without telling you how those changes relate to each other.
The questions I keep running into -- the ones that matter most -- are different. How did we get here? In what order? What does that trajectory mean? Those questions require something most architectures are not built to answer.
I have been writing software and designing systems since 1994. That is thirty-two years. Long enough to have watched several waves arrive with the promise that everything was about to change, and long enough to have noticed that the pattern of arrival is remarkably consistent. Breathless proclamation. A period of confusion as people try to apply old practices to new technology. Then a gradual, quieter recognition of what actually changed and what did not.
The fear is intuitive and sounds right: the more you delegate to AI, the less you understand your codebase, the less you control what ships. You become a passenger in your own project. Every prompt you type is a piece of agency you surrender.
I have thirty years of shipping software. I have watched entire teams lose control of codebases they wrote themselves, without any AI involved. And I have watched my own control over a codebase increase as I delegated more to AI. The intuition is wrong. But it is wrong in a specific way, and understanding that specificity matters.
For most of my thirty years in software, iteration has been expensive. Not in theory. In practice, in the way that shapes every decision a team makes. When changing a core data structure takes two weeks of careful refactoring across dozens of files, you do not change the data structure on a hunch. You analyze. You write a proposal. You get approval. You schedule it for the next sprint, or the one after that. The cost of being wrong is measured in weeks, and so the entire machinery of software engineering orients itself around not being wrong.
That cost has collapsed. Not gradually. Not by half. By orders of magnitude. And I am not sure we have reckoned with what that means for the way we work.
For thirty years I have broken work into tasks. Decompose the feature into subtasks, estimate the hours, write the code, move the ticket. The unit of progress was the line of code. The measure of a good day was how much I shipped. That loop was so deeply embedded in how I worked that I did not notice it was a loop. It was just what development meant.
Then I started delegating implementation to AI, and the loop broke. Not gradually. In about a week.
I have been writing software for thirty years. In that time I have sat through thousands of daily standups, hundreds of onboarding sessions, and more planning ceremonies than I care to count. Most of them existed for one reason: transferring context from people who had it to people who did not. The new developer needs to know how the deployment pipeline works. The team lead missed yesterday's discussion about the API change. The architect needs to understand why the data model looks the way it does before approving the next feature.
These are not bad reasons to meet. But they are expensive reasons. And increasingly, they are avoidable ones.