Articles
Why Most Agent Failures Are System Failures

Why Most Agent Failures Are System Failures

When an agent fails, suspect the system before the model. Corruption enters on the write path, upstream.

There is a classic shape of production incident. A payment processor double-charges about one customer in ten thousand. The code in front of you is correct. You read it forty times. The actual bug is a retry policy three layers down that fires on a timeout the database has already committed. The failure was never in the function that looked guilty. The function with the red stack trace was the one reporting the problem, not the one causing it. That gap between where an error surfaces and where it originates is most of what makes hard bugs hard.

I keep thinking about that gap now, because the AI industry has built an entire reflex around the place the error surfaces. An agent does something dumb in production and the post-mortem is, reliably, about the model. We picked the wrong model. We need a smarter model. The next model will fix it. Sometimes that's true. Mostly, in the agents I've built and torn apart, it isn't. The failures were memory, retrieval, tooling, orchestration. The model was doing exactly what a reasonable system would do given the inputs it was handed. The inputs were wrong, and nobody could see where they came from.

There's a fact the model-ranking conversation keeps stepping around. An agent isn't a model with some plumbing attached. It's a distributed system that happens to have a model in it. Distributed systems fail in distributed-systems ways, in the handoffs and the state, not in the one component you happen to be staring at.

Let me be precise, because "it's not the model's fault" can sound like an excuse, and I don't mean it as one.

When an agent gives a bad answer, there's a chain of events behind it. Something was retrieved. A tool was called and returned something. A prior step's output became this step's input. A memory was read back and treated as true. The model is the last link in that chain, the thing that turns all of those inputs into a token stream you can actually see. So when the output is wrong, the model is the part that's visibly wrong. It said the wrong thing. It's the one standing over the body.

But the model is deterministic-ish in the way that matters here: given the same context, it produces roughly the same answer. Feed it a poisoned context (a stale fact, a tool result from the wrong tenant, a retrieval that surfaced a six-month-old runbook, a previous step that silently truncated) and it reasons faithfully from garbage and produces a confident, well-formatted, completely wrong answer. It didn't fail. It reported a failure that happened two steps upstream, and it reported it well.

That's why "swap in the better model" so often changes nothing. Picture a team burning most of a quarter on a model upgrade for a problem that is, the whole time, a retrieval layer pulling the wrong document because two customers share a name. The newer model just describes the wrong customer's situation in more fluent prose. Fluent and wrong is still wrong.

Autonomy multiplies the system, not the intelligence

There's a second-order version of this that's worse, and it's the one I'd warn anybody scaling agents about.

The more autonomous you make an agent, the more the surrounding software architecture matters, not less. This is counterintuitive. People reach for autonomy expecting the model to absorb complexity. Give it more freedom, more tools, more steps, and let the intelligence figure it out, they think. What actually happens is that every additional step is another place for the system to inject a bad input, and the model's job becomes building on top of whatever the previous steps produced, whether or not those steps were right.

A single-shot agent (one prompt, one answer) has almost no system around it. The blast radius of a bug is one response. But a multi-step agent that retrieves, calls tools, writes intermediate state, reads it back, and loops has turned itself into a pipeline. Each stage's output is the next stage's input. An error in stage three doesn't announce itself. It gets laundered through stages four, five, and six until it surfaces as a strange final answer that traces back to nothing obvious. The intelligence didn't compound the way people imagine. The fragility did. Every extra step is one more place to inject a bad input, and a few more bad inputs to inject it.

I've started thinking of autonomy as leverage on whatever architecture you already have. Sound architecture, and autonomy multiplies the value. Shaky architecture, and autonomy multiplies the shakiness, quietly, because each individual step still looks locally reasonable when you inspect it alone. The model isn't the lever here. The orchestration is.

The substrate is the system, and the substrate is memory

So if the failures are systemic, where in the system do they actually live? In my experience, overwhelmingly: in the part of the system that holds and serves state. Memory and retrieval. That's the substrate everything else stands on.

Think about what an agent's "context" for any given decision actually is. It's a pile of stuff that got assembled from somewhere: recent turns, retrieved memories, tool outputs, prior conclusions. The model never sees the world directly. It sees whatever the memory and retrieval layer hands it. That layer is the agent's reality. If it hands over a fact that was true eight months ago, the agent lives eight months in the past for that one decision and has no way to know. If it merges two entities, the agent acts on a person who doesn't exist. If it recalls a background process's speculative guess with the same authority as something a user actually said, the agent believes a rumor it generated itself.

This connects to everything I've been writing in this series. The memory layer isn't a feature bolted onto an agent. It's the substrate the agent's cognition runs on, the durable, untrusted, self-modifying state I keep coming back to. And because it's the substrate, its failures don't look like memory failures. They look like the model being dumb. The corruption enters in one layer and the symptom shows up in another, two or three steps downstream, where the model happens to be holding the output.

Which makes the central debugging problem for agents easy to state and miserable to satisfy. You can't debug what you can't reconstruct. When the agent gives a bad answer, the only question that matters is which input was wrong, and where did it come from. Almost no agent stack in production today can answer it. The retrieval happened inside a black box. The memory that got recalled carries no record of where it was born or when it was last true. The intermediate steps left no trace. So the team does the only thing a black box permits: it changes the model and hopes.

You can't debug what you can't reconstruct

I want to make this concrete, because "observability" is one of those words that has been sanded down to meaninglessness.

The failure that eats weeks of engineering time looks like this. An agent produces a bad answer on Tuesday. Someone notices Thursday. By the time anyone investigates, the conversation is over, the context window that produced the answer is gone, and the memory store has been written to ten thousand times since. The investigation is: stare at the final output, stare at the prompt template, form a theory, change the prompt, hope. No flight recorder. The decision is unreconstructable, so the fix is a guess, and the next guess is another guess, and you ship a prompt tweak that papers over one symptom and surfaces a new one a week later.

This keeps happening because almost everyone instruments the wrong half of the system. Teams trace retrieval obsessively, what got pulled back at read time, because that's the step sitting right next to the visible error. But corruption doesn't enter on the read path. It enters on the write path: the moment something gets ingested, classified, extracted, and committed to durable state. By the time you're tracing retrieval, the bad fact is already stored, already authoritative, already being served back. The crime scene is the write, and nobody's looking at it.

This is the specific problem I built SmartMemory's pipeline around, so let me describe the actual mechanism instead of the aspiration.

When SmartMemory ingests a memory, it doesn't do a single opaque store(). It runs an eleven-stage pipeline (classify, coreference, simplify, entity_ruler, llm_extract, ontology_constrain, store, link, enrich, ground, evolve) and every stage emits a trace record. Not a log line you have to grep for at 2am. A structured record: the stage name, how long it took, whether it ran or skipped or failed, a summary of what went in and what came out, and for the stages that call a model, which model, how many prompt and completion tokens it burned, what it cost. The whole run rolls up into one trajectory object you can pull straight off the memory after ingestion. The flight recorder is on, on the write path, by default.

What that buys you is an answer to the question the black box can't field. A memory got the wrong entity attached? Don't theorize about the model. Open the trajectory, look at the entity_ruler and llm_extract stages, and see which one made the bad call and the input it was reasoning over. Ingestion is mysteriously expensive? The per-stage cost breakdown points at the stage burning the budget instead of handing you a vague aggregate. A fact is wrong and you need to know how it came to exist? The trace is the chain of custody from raw input to stored memory. The bad answer is traceable to a stage, and the stage is traceable to the memory it produced.

That's the gap between debugging an agent and praying at one. Instead of restarting at the visible error, you walk back up the chain to the stage where the input first went wrong, and you fix that: the producer, not the consumer. Distributed-systems engineers have applied this discipline to request tracing for fifteen years. It's overdue at the layer where agent cognition actually lives.

This is why I keep insisting the memory substrate isn't a database with a fuzzy SELECT bolted to a vector index. It's a first-class component of the agent's control flow, and it needs the engineering that implies: structured stages, a trace on each of them, and the ability to reconstruct any decision long after it happened. Build that, and "the agent failed" becomes something you can actually investigate. Skip it, and "the agent failed" stays a synonym for "the model is dumb, let's wait for the next one."

What this changes about how you build

If you take one thing from this, make it a reflex: when an agent fails, suspect the system before you suspect the model. Walk the chain backward from the visible error and find the first input that was wrong. It's almost always upstream of the model, in the layer that held and served state.

Concretely, here is where the leverage actually is:

  • Trace the write path, not just retrieval. Bad state enters when something is committed, not when it's read back. If your ingestion is a single opaque store(), you have no flight recorder for the exact moment corruption enters. Instrument the stages.
  • Treat every step as a component with a contract. Each stage's output is the next stage's input. An unvalidated handoff three steps back is where your "model failure" was actually born. Make the handoffs observable.
  • Reconstruct before you theorize. If you can't replay the exact chain of inputs that produced a bad answer, every fix is a guess. Keep the trajectory around so the decision is reconstructable hours or days later, after the context window is long gone.
  • Resist the model-swap reflex. Before you spend a quarter chasing a smarter model, prove the inputs were clean first. Mine usually weren't.

The industry is going to keep shipping better models, and good. I want them too. But the leverage right now isn't where the conversation is pointed. As long as the substrate stays a black box, every bad answer is a dead end: you can see it, but you can't walk back to where it came from. The teams that come out ahead in the next phase are the ones who stop treating the agent as a model with plumbing attached, start treating it as a system with a model inside, and then go engineer the substrate that system runs on.

An agent that can't reconstruct how it reached a decision doesn't really know anything. It has a confident guess and no record of where the guess came from. That's the gap I keep coming back to in this series, and a memory layer you can't see into never closes it. Make the substrate observable and most of your "model failures" turn out to have a return address: a bad answer traces back to the stage that produced it, and that stage back to the exact memory it was reasoning over. That's a less dramatic conclusion than "we need a smarter model," which is probably why it's the one worth acting on.


I'm building SmartMemory, the expertise layer for AI agents: provenance-tagged, bi-temporal, graph-backed memory that knows not just what's true, but what to do, and when it stopped being true.

Try it: pip install smartmemory (docs) · hosted beta (private): smartmemory.ai/signup