I built an agent framework. A real one. Manager on top, specialized sub-agents underneath, an orchestration layer wiring them together. A registry so the manager knew who existed. Routing rules so work went to the right specialist. Shared-context passing so each stage handed off cleanly to the next.
It ran in production for several weeks. Then I deleted most of it.
This is the field note on why, and what I kept.
Why did I build the orchestration layer in the first place?
I built the orchestration layer because the work looked complex, so I assumed it needed a complex structure to hold it. That assumption was the whole mistake. A manager routing to specialized sub-agents felt like the “grown-up” architecture, the thing you build when you’re past the toy stage. I mistook the shape of a serious system for the substance of one.
The logic was seductive. If I have many kinds of work, I should have many specialists. If I have many specialists, I need something to route between them. If I’m routing, I need a registry and rules and clean handoffs. Each step follows from the last. Every one of them felt responsible.
None of them were load-bearing. I just didn’t know that yet, because I’d built the framework before I had the traffic to test it against.
What actually happened when it ran in production?
In production, three things surfaced, and all three argued against the framework I’d built. Most of the routing never fired. The specialized agents weren’t actually specialized. And every failure took longer to trace. The abstraction I built to manage complexity had become the complexity.
Here is what I saw, in the order it hurt.
Most of the routing never fired
I’d engineered paths for rare cases. Edge conditions. The unusual request that might come once a month. In practice, one or two common paths carried nearly everything. The clever branches sat cold. I had spent real effort making the machine handle situations it almost never encountered, and that effort bought me nothing except more surface area to maintain.
The specialization was cosmetic
Each sub-agent had its own brief, its own scope, its own reason to exist. But when I read the transcripts side by side, they were mostly reproducing what a single well-briefed agent already did. The boundaries I’d drawn between them were lines on a map, not walls in the world. I’d split one competent worker into several narrower ones and called it architecture.
Every bug got slower to trace
This was the one that ended it. When something failed, the fault could live in the orchestration layer, in the routing logic, or in the agent itself. And I had to rule out all three, every single time. The framework didn’t localize failure. It smeared failure across three places that all had to be checked before I could trust any of them. Debugging a simple system means reading a loop. Debugging this meant interrogating a bureaucracy.
Wasn’t the framework compensating for something the models couldn’t do?
It was compensating for gaps that had quietly closed. The scaffolding (the planning layer, the parallel dispatch, the sub-agent delegation) was built to make the model do things it couldn’t reliably do on its own. By 2026 the models do most of that natively. They plan. They call tools in parallel. They delegate. So my elaborate layer wasn’t enabling those behaviors anymore. It was constraining them, forcing native capability through pipes I’d hand-cut a year too early.
That is the trap with framework-building right now. You engineer around a limitation, ship it, and then the floor rises underneath you. The workaround outlives the problem it solved. And a workaround with no problem left to solve is just weight.
What did I keep when I rebuilt it smaller?
I rebuilt around one manager making direct model calls, with structured handoffs kept only where two things genuinely ran in parallel and had to rejoin. No registry. No routing rules. No orchestration layer standing between intent and execution. The smaller version did the same work, failed in obvious places, and fit in my head. That last part matters more than it sounds.
The parallel handoffs earned their place because they solved a real problem: two operations that truly ran at the same time and needed their results merged. That’s coordination you can’t fake with a loop. Everything else went in the bin: the routing, the registry, the ceremony of passing context through stages. Not refactored. Deleted.
What I got back was legibility. When something breaks now, there is one place to look. The manager called the model, and either the call was wrong or the brief was wrong. Two suspects, not three layers. I can reason about the whole thing without a diagram.
Should you build the abstraction, or will you regret it?
Default to not building it. Start with the smallest thing that works, one loop, direct API calls, a good brief, and run it against real traffic before you abstract anything. Add structure only when a specific failure forces your hand, and only the structure that failure demands. If you build the framework first, you’ll engineer for cases that never arrive and pay for it on every bug you trace afterward.
Here is the test I use now. Before I add a layer, I ask what it does that a well-briefed single agent can’t. If the honest answer is “it feels more organized,” that is not a reason. Organization that isn’t load-bearing is decoration, and decoration in a system you have to debug at 2am is a liability.
The instinct to build the big thing is real. It feels like competence. It looks like the architecture serious people ship. But I ran the serious architecture in production and watched most of it sit idle while the rest made my failures harder to find. The version I trust now is smaller, dumber, and legible.
Build the loop first. Earn every layer after it.