Writing

When an Agent Goes Sideways, Read the Tool-Call Chain

When an Agent Goes Sideways, Read the Tool-Call Chain - abstract illustration

An agent does something wrong: it skips a batch of emails, files a note in the wrong place, sends a follow-up that shouldn't have gone out. The instinct is to open the prompt and start rewriting it, or to argue with the model in a fresh chat about why it was wrong. That's almost always the slow path. The fast path is to read the exact sequence of tool calls the agent made and what each one returned. That log tells you, precisely, where its reasoning diverged from what you intended.

I run a fleet of scheduled agents in production, and I log tool-call chains at the infrastructure level for exactly this reason. When one misbehaves, the answer is in the log, not in my head.

It's usually not that the model is dumb

When an agent goes sideways, the tempting story is "the model messed up." Occasionally that's true. Far more often the model did something entirely reasonable given the information it actually had, which was different from the information you assumed it had.

A few real shapes this takes:

  • A tool returned an empty result, and the model read it as "nothing to do." The email query came back with zero rows, so the agent concluded there was nothing to process and exited cleanly. The model behaved correctly. The query was wrong, or the cutoff timestamp it passed in excluded everything.
  • An ambiguous tool description led it to pick the wrong tool. You have two tools that sound alike; one finds message IDs, one finds full metadata. The description didn't make the distinction sharp, so the model picked the cheaper-sounding one and then didn't have the fields it needed downstream.
  • A cutoff timestamp was off, so it reprocessed or skipped work. A stored "last processed" value was in seconds and the tool expected milliseconds, or a timezone offset got added instead of subtracted. The agent then re-did yesterday's work or skipped a day entirely. Every step it took was internally consistent; the input state was bad.

In all of these the model acted correctly on bad or missing information. If you go straight to rewriting the prompt, you're tuning the reasoning of an agent that was already reasoning fine. You'll add words, feel productive, and change nothing, because the fault was upstream in what a tool handed it.

The tool-call chain is the ground truth

Here's the thing that took me a while to fully internalize: the tool-call chain is the only record of what the agent actually did, as opposed to what you assume it did.

The prompt tells you what you asked for. The final output tells you what it produced. Neither tells you the path in between. The tool-call chain does. It's the sequence of concrete actions with concrete arguments and concrete return values: this tool, these parameters, this response, then the next decision. It's not a summary the model wrote after the fact, and it's not your mental model of how the agent "should" work. It's the receipts.

This matters because agents fail in the gap between intent and action. You intended for it to process new emails since 9am. It called the query tool with a cutoff of midnight UTC, which your logs will show was 5pm the previous day in local time, and pulled in a hundred old messages. You'd never find that by re-reading the prompt, because the prompt says "since 9am" and reads perfectly. The bug is in the timestamp it computed and passed, and that value only exists in the tool-call chain.

If you build or run agents and you're not capturing this, capturing it is the highest-leverage debugging investment you can make. I go deeper on the operational side of this in running AI agents in production, but the short version is: log every tool call, its arguments, and its raw return value, and keep those logs where you can read them per run.

Reading it in practice

When I open a tool-call chain for a run that went wrong, I read it as a four-column story and walk it top to bottom:

  1. Which tool did it call? Is this even the right tool for the step? If it reached for a search tool when it should have reached for a write tool, stop there; you've found it.
  2. What arguments did it pass? This is where most bugs live. Look hard at anything computed: timestamps, cutoffs, IDs, filter values, folder paths. Compare them against what you expected the value to be, not against whether they look plausible.
  3. What came back? Empty result? Error? A false return? Fewer rows than there should be? A payload missing a field the next step needs? The return value is the model's entire view of reality at that moment.
  4. What did it do next? Given that return value, was the next action reasonable? Usually it was. That's the tell that the problem is the data flowing through the chain, not the model's judgment.

You're looking for the first step where the actual value diverges from the intended value. Everything after that point is the agent faithfully building on a bad foundation, so don't get distracted debugging the downstream steps. Find the divergence, fix the source, and the rest of the chain usually corrects itself.

The common divergence points

After enough of these, the same handful of causes come up over and over:

  • Wrong tool selected from ambiguous descriptions. If two tools could plausibly serve the step and the model picked the wrong one, the description is doing a bad job of distinguishing them. This is a tooling problem wearing a model-problem costume.
  • A silent tool failure the model didn't notice. A tool returned false, or an empty object, or a soft error string instead of raising, and the model interpreted that as a benign result and moved on. The model can only react to what a tool tells it, and a tool that fails quietly tells it nothing is wrong.
  • Missing state or context. The agent needed a value it was never given: the last-processed cursor, a config flag, a piece of the contact record. It did the best it could without it, which usually means it guessed or defaulted to something wrong.
  • A bad input value. The state was there but wrong: a stale timestamp, an off-by-one cursor, an ID that pointed at the wrong record. Giving your AI the context it needs to work includes making sure the state you feed it is actually correct, not just present.

Note how few of these are "the model reasoned badly." Almost all of them are about the tools and the state around the model. That's not a coincidence. Once you give an agent tools, most of your reliability problems move out of the prompt and into the tool boundary.

The fixes follow directly from what you find

The nice property of debugging this way is that the fix is usually obvious once you've located the divergence, and it's rarely "reword the prompt."

  • Ambiguous tool picked? Sharpen the tool description. Say exactly what it returns, when to use it, and when not to. Name the sibling tool it's often confused with. The model reads that description every time; a better one fixes the class of bug, not just this instance.
  • Silent failure? Make the tool fail loudly. Return a real error the model has to handle instead of a false it can shrug off. An agent can recover from an error it can see; it can't recover from one it never learns about.
  • Missing state? Feed it. Pass the cursor, the config, the record into context explicitly rather than hoping the model infers it.
  • A recurring gotcha? Write it down where the AI will read it. When I hit a bug that's specific and likely to recur - the seconds-versus-milliseconds trap, a tool that silently returns false on a particular input - it goes in a gotchas file the agent reads before it works, which I wrote about in keeping a gotchas file for your AI. That's how a one-time debugging session turns into a permanent fix.

Some of my most stubborn agent bugs came down to a single wrong argument in a single tool call: a cutoff computed in the wrong unit, a path with an HTML-encoded ampersand that made a lookup silently miss. None of those were visible in the prompt or the output. All of them were sitting in plain text in the tool-call chain, waiting to be read.

The discipline is simple to state: when an agent surprises you, don't theorize and don't rewrite the prompt first. Open the log, find the first tool call where reality diverged from intent, and fix the thing that produced that value. The model is usually telling you the truth about what it did. You just have to read it.

Building something like this?

This is the kind of work I do for clients. Tell me what you're building and I'll give you a straight read on the approach.

Book a 30-minute call