There is a version of Springsteen’s Born to Run where the production is stripped back to voice and acoustic guitar. The bones of the song. Every element that remains is load-bearing: the melody, the words, the rhythm that carries the verse. Everything else that was added in the studio was arrangement. Beautiful arrangement in some cases, but not the thing that makes the song work.
This is how I think about agent systems now.
What orchestration actually costs
Every agent system reaches a point where adding routing feels like the obvious move. You have multiple agents, multiple models, usage costs you want to track, fallback behavior when the primary inference endpoint is slow. An LLM routing layer solves all of these things simultaneously. The value proposition is real.
The catch is what the routing layer adds: a new failure surface, a new debugging layer, and a dependency that sits between your agents and the thing they need. When the routing layer works, you do not notice it. When it breaks, everything breaks through it.
My system ran an LLM routing layer for months. It handled model selection, cost tracking across providers, and request normalization. It worked. Then we removed it.
flowchart TD
subgraph before["Before"]
A1([Agent 1]) --> R{{LLM Routing Layer}}
A2([Agent 2]) --> R
R --> M1[Primary Model]
R --> M2[Fallback Model]
end
subgraph after["After"]
B1([Agent 1]) --> M3[Primary Model]
B2([Agent 2]) --> M3
end
style R fill:#1a1917,stroke:#c1121f,color:#e8e5deWhat changed: fewer pods going into bad states for routing-layer reasons. Fewer debugging sessions that started at “is this the agent or the router.” The cost tracking moved to a simpler log aggregation approach. The fallback routing was replaced with a retry at the agent level, which is easier to reason about.
Pod count: unchanged. The simplification was architectural, not hardware.
What persona actually does for a system
Voice, in the Springsteen sense, is the element that makes everything else coherent. You recognize a Springsteen song because the voice is consistent. The production changes, the band changes, the decade changes. The voice stays.
For an agent, persona is the equivalent. Not personality quirks, not tone of voice in the theatrical sense. The predictable pattern of how the agent approaches work. What it checks before starting. What it escalates vs. decides autonomously. How it handles ambiguous specs. What it does when something fails.
A consistent persona is an interface contract. If you are running multiple agents and routing tasks between them, you need to be able to predict how each agent behaves. An agent without a stable persona is unpredictable: it may handle the same class of task differently on consecutive runs depending on context it happened to pick up.
Persona consistency is not about personality. It is about predictability. A consistent agent is a debuggable agent. You know what it should do, so you know when it is doing something wrong.
The important thing about persona: it is nearly free. It lives in the system prompt. It does not require a larger model, a fine-tune, or additional compute. The cost is specification quality. You have to write the persona clearly enough that the model reproduces it consistently across a range of inputs.
This is harder than it sounds, and easier than routing.
The task loop is the instrument
Guitar is what carries the structure. In the acoustic version of the song, the guitar is all you have for rhythm and harmony. It has to be solid, or nothing else works.
For an agent, the task loop is the guitar: receive task, read spec, execute, verify, report. This loop runs on every task. If it is reliable, the rest of the system can depend on it. If it is fragile, everything downstream is fragile.
The mistake I see most often in agent designs is moving complexity into the loop. Branching routing logic inside the dispatch. State machines that track task dependencies. Retry logic that tries to guess whether a failure is transient or permanent. All of these make the loop harder to understand and harder to debug.
The principle I use: if a task requires branching, that branching lives inside the task execution, not in the dispatch loop. The loop stays dumb. The task spec handles complexity. When something goes wrong, you know whether to look at the loop (stable, rarely changes) or the task spec (where the complexity is).
Observability follows simplicity. A three-step loop with clear inputs and outputs is fully debuggable. A loop that conditionally routes through five different handlers depending on task type, model availability, and previous retry count is not observable until something goes wrong, at which point it is extremely observable in the worst possible way.
What you can add without breaking the bones
Stripping to voice and guitar is not a permanent state. Born to Run has orchestration. The stripping is to find out whether the bones work, and to be honest about what is load-bearing.
For agents, the equivalent: what can you add back without increasing failure surface?
Memory is the obvious addition. An agent that can read its own history of decisions, failures, and learned patterns does better work than one that starts fresh every session. Memory does not change the task loop. It adds a read step at the beginning and a write step at the end. The loop stays observable.
Behavioral testing is another clean addition. A check that runs after task completion and verifies the agent’s output against expected patterns. Does not touch the loop. Adds coverage without complexity.
flowchart LR
A[(Memory read)] --> B([Receive task])
B --> C[Read spec]
C --> D[Execute]
D --> E[Verify]
E --> F([Report])
F --> G[(Memory write)]
F --> H[Behavioral test]
style A fill:#1a1917,stroke:#c9a84c,color:#e8e5de
style G fill:#1a1917,stroke:#c9a84c,color:#e8e5de
style H fill:#1a1917,stroke:#c9a84c,color:#e8e5deWhat to be careful with: anything that makes the loop conditional. Routing decisions that depend on task type, agent availability, or model state add branching that is hard to observe. Not impossible to manage, but the cost rises faster than the benefit suggests.
The objections worth taking seriously
“This does not scale to enterprise.” Probably true. At hundreds of concurrent agents with hard SLA requirements and multi-provider cost constraints, routing layers earn their complexity. The claim I will defend is narrower: at small-to-medium fleet scale, routing layers often add more failure surface than value. The threshold where that equation flips is not a number I have determined.
“You’re just not using the routing layer correctly.” Possibly. I used it for about eight months and found the failure modes more expensive than the features. That is evidence, not proof. A better-configured routing layer might have been worth keeping.
“Persona consistency is trivial, why are you treating it as an achievement.” It is trivial to specify and maintain when things are stable. It gets harder when the system prompt needs to evolve, when you are running multiple agent types with related but distinct personas, or when a model update subtly changes how the same prompt is interpreted. The trivial case is not the case where it matters.
What to strip first
If you are building an agent system and something is consistently hard to debug, start by removing it. Not redesigning it, not adding logging to it. Removing it.
Run without it. See what breaks. If nothing breaks, you have found something that was arrangement rather than structure. If something breaks, you have found a real dependency, which is useful information. Either way you know more than you did.
The agent fleet I run today has a stable persona for each agent type, a reliable five-step task loop, memory reads and writes at the boundaries, and behavioral tests after completion. That is the whole system. Everything I tried to add on top of that eventually got removed because it cost more in debugging than it provided in features.
Voice. Guitar. Everything else is negotiable.
Casey Gager builds a personal AI orchestration system. He writes about what works, what breaks, and what he is still figuring out. Views are his own.
See also
- prom-memory: building episodic memory for an AI system that actually remembers — the memory layer that makes persistent agent identity possible. Voice and guitar requires continuity; prom-memory is what delivers it.
- PADCN: a 5-dimensional affective state model for AI personas — the behavioral modulation framework. Strip to voice and guitar first; PADCN is what you add when the core is load-bearing.
- Writing to the Next Session — session handoff as an expression of the same principle. The handoff document is the minimal recoverable state: everything load-bearing, nothing else.
- ISA-driven development: structured contracts for autonomous AI agents — structured work contracts are the specification analog of voice and guitar. Eliminate everything that isn’t load-bearing from the agent’s task description.
- My agent couldn’t read its own name for months — what happens when the load-bearing element (agent identity) silently fails. The bones of the system were invisible because the template was never verified.