IDInternals Decoded
AI System Design
Deep DivesAdvanced11 min readMay 2026

Debugging Agent Systems: Traces, Replays, Root Causes

Agent failures raise no errors. The logging, tracing, and replay toolkit that makes them debuggable.

Part 12 of 14AI System DesignView series →

Part 11 gave you the tools to measure whether your agent works. Now we face the harder problem: when the evaluation says it's broken, how do you find out why?

Agent failures are invisible. No stack trace, no exception, no segfault. A Mailmind reply that fabricates a refund amount looks just like a correct one. Debugging means reconstructing what the agent thought, saw, and did. This article covers the structured logging, tracing, replay, and root cause analysis that turn agent failures into fixable bugs.

Here's the uncomfortable truth: rerunning an agent with the same input rarely reproduces the same failure. Nondeterministic sampling, tool call order, and retrieval noise mean that the bug you saw yesterday is gone today. You can't fix what you can't see twice. That's why replay debugging, not fresh reruns, is the cornerstone of agent observability.

Why do agent failures produce no errors?

Traditional code fails deterministically. A null pointer dereference crashes the same way every time. An agent fails by producing a wrong output that looks completely valid. The system never raises an error because, from its perspective, everything worked. The LLM (large language model) returned a coherent response. Tools executed without exceptions. The pipeline completed.

The analogy that sticks: debugging code is fixing a broken pipe. You see the leak and trace it back. Debugging an agent is figuring out why a person made a bad decision. You need their full reasoning, what they saw, and what they believed at each step. Without that record, you're guessing.

Mailmind illustrates this perfectly. A user asks "Did my refund for order #4521 go through?" The agent checks the order database, sees a refund status of "pending," and replies "Your refund of $47.23 has been processed." The answer is confident, fluent, and completely wrong. No error was thrown. The refund tool returned valid data. The agent simply hallucinated the amount and the completion. You only discover the bug when the user complains.

This failure mode is why observability in agent systems must be built differently. You can't rely on error rates. You need a record of every thought, every tool call, every retrieval result, and every guardrail trigger. That record becomes your debugger.

What are the four categories of agent failures?

Every agent failure falls into one of four buckets. Knowing which bucket you're in cuts diagnosis time from hours to minutes.

Reasoning failures: the agent had the right information but drew the wrong conclusion. In Mailmind, the agent correctly retrieved a meeting invite for 3 PM but replied "I'll see you at 2 PM." The chain-of-thought log shows it misread the time. Diagnosis: inspect the exact reasoning trace. Fix: add clearer prompts, constraints, or few-shot examples that anchor the correct behavior.

Tool failures: the agent called a tool but got bad data, no data, or a malformed response. Mailmind's calendar tool might return an empty JSON (JavaScript Object Notation) because of an auth token expiry, and the agent proceeds as if no meetings exist. Diagnosis: log every tool call's input and output. Fix: add retries, validation, and explicit error handling so the agent knows when a tool has failed.

Memory failures: the wrong information was retrieved, or critical information was dropped. Mailmind's retrieval step might pull an old refund policy instead of the current one, or the context window might truncate the order history. Diagnosis: log what was retrieved and what was in context. Fix: adjust embedding models, retrieval parameters, chunk overlap, or context window management.

Orchestration failures: the wrong agent was called, state was lost between steps, or the pipeline deadlocked. In a multi-agent Mailmind setup, the manager agent might route a receipt-filing task to the meeting scheduler. Diagnosis: trace the full flow of agent handoffs. Fix: tighten routing criteria, validate state passing, and add heartbeats.

These categories aren't mutually exclusive. A single bad output often cascades through multiple layers. The debugging process isolates the first domino.

How do you trace an agent run end-to-end?

A trace is a timestamped, structured record of every step in an agent run. It captures thoughts, actions, observations, tool I/O, retrieval results, confidence scores, handoffs, and guardrail triggers. This is not a log file of print statements. It's a machine-readable, queryable timeline.

For Mailmind, a trace of a single email handling might look like this:

Every node in that diagram carries a payload: the exact prompt fragment, the tool response JSON, the retrieved document chunk, the guard score. When a user reports a wrong refund amount, you pull the trace and see that at step E the order status was "pending" but step I's reasoning says "refund completed." The bug is in the reasoning step, not the tool.

The tracing system must be built into the agent framework from day one. You can't bolt it on later. Every component emits spans. OpenTelemetry conventions are emerging for LLM calls, but you'll need custom attributes for agent-specific events like handoffs and retrieval scores.

How does replay debugging work for nondeterministic systems?

Fresh reruns are useless for debugging agent failures. The LLM sampling, the order of async tool calls, and the retrieval noise will all differ. Replay debugging solves this by storing the complete input state of a run and feeding it back deterministically.

A replay record includes the exact sequence of LLM responses (you can force the model to return the same tokens if you cache the logits or use a fixed seed, but more practically you store the generated text and feed it back as the "observation" at each step), the tool responses (cached, not re-executed), and the retrieval results. When you replay, the agent follows the same path because every decision point gets the same inputs.

Mailmind's replay system captures the full state: the user email, the retrieved order data, the refund policy chunk, the generated draft. You can step through the run in a debugger, inspect the prompt at each thought, and see exactly where the agent went wrong. This is the equivalent of a core dump for agent systems.

Step-through mode takes this further in development. You pause after each thought and inspect the state. You can even edit the prompt or tool response mid-run to test hypotheses. This is how you answer "what would have happened if the retrieval returned the correct policy?"

What does a systematic debugging process look like?

When a Mailmind user reports a wrong reply, you follow a repeatable process.

Reproduce. Pull the trace for that specific run. If you have replay, execute the replay and confirm the bug appears. Without replay, you're stuck trying to reconstruct the state from logs.

Isolate the component. Use the trace to identify which step first produced wrong information. Was it a retrieval that returned stale data? A tool that timed out silently? A reasoning step that hallucinated?

Inspect the reasoning chain. Look at the exact prompt assembled at that step. Often the bug is visible right there: garbage tool output injected into the prompt, truncated instructions, or a missing few-shot example.

Identify the root cause. Classify it into one of the four categories: wrong information (memory or tool), wrong reasoning, wrong configuration (orchestration), or infrastructure (timeouts, auth). This classification tells you where to fix.

Fix and verify. Apply the fix and run the replay. The bug should disappear. Then run the full evaluation suite from Part 11 to make sure you haven't regressed elsewhere.

Post-mortem and golden set. Write a brief post-mortem. Add the exact input and expected output to your golden set so this failure never silently passes again.

This process turns agent debugging from a mystical art into a disciplined engineering practice.

What failure signatures should you recognize immediately?

Some failure patterns are so common they have signatures. Learn to spot them in the trace without deep inspection.

Hallucination spiral: the output is confident, fluent, and completely unsupported by any citation. In the trace, you'll see no tool calls or retrieval steps that back the claim. Fix: add a factuality guard that requires citations, and log when the guard fires.

Tool call loop: the agent calls the same tool with slightly different parameters, over and over, never making progress. Mailmind might call the calendar availability check 15 times with dates one day apart. The trace shows a repeating pattern. Fix: add a maximum tool call count or a semantic deduplication check.

Context contamination: a reply about order #4521 suddenly references details from a different thread. The trace shows that the agent's context included both threads. Fix: isolate context per conversation, clear state between runs, and scan outputs for cross-thread leakage.

Silent truncation: the agent consistently misses information buried deep in long threads. The trace shows that the context window dropped the relevant messages. Fix: add coverage checks that verify all critical sections are present, and use chunking strategies from Part 8.

Deadlock: the pipeline simply stops. In a multi-agent Mailmind, the manager waits for a worker that has already crashed or is waiting for a response that never comes. Fix: add heartbeats and timeouts on all inter-agent communication.

Confidence inflation: the agent assigns high confidence scores to wrong outputs. The trace shows a confidence of 0.97 on a hallucinated refund amount. Fix: calibrate confidence with examples, and add an independent scorer that evaluates the output separately.

Recognizing these signatures in the trace lets you jump straight to the fix.

Quick Reference: Failure Categories at a Glance

Failure CategoryDiagnosisFix
Reasoning failureInspect chain-of-thought logClearer prompts, constraints, examples
Tool failureLog tool call input/outputRetries, validation, error handling
Memory failureLog what was retrievedRe-embed, adjust retrieval params, chunk overlap
Orchestration failureTrace full flow of handoffsValidate state passing, tighten routing, heartbeats

Frequently Asked Questions

Q: Why can't I just rerun the agent to reproduce a bug? Nondeterministic sampling, tool call ordering, and retrieval noise mean the same input rarely produces the same output. The bug you saw yesterday may not appear today. Replay debugging stores the exact state so you can reproduce the failure deterministically.

Q: How do I log agent runs without blowing up storage costs? Log structured events, not full text dumps. Store only what you need for replay: tool responses, retrieval results, and the final LLM output at each step. You don't need to store every token probability. Sample a fraction of runs in production and keep full traces for failures only.

Q: What's the difference between a trace and a log? A log is a stream of discrete events. A trace is a directed acyclic graph of spans that shows causal relationships. In agent debugging, you need the trace to see which thought led to which action and what observation came back. Logs alone can't reconstruct the decision tree.

Q: How do I debug a tool call loop that never errors? Look at the trace for the repeating pattern. Add a maximum call count or a semantic deduplication check that compares the current tool call to the last N calls. If the parameters are nearly identical, break the loop and return a clear signal to the agent.

Q: When should I use replay vs. step-through debugging? Use replay to reproduce a production failure exactly. Use step-through in development to pause after each thought, inspect state, and test hypotheses by editing prompts or tool responses mid-run. Replay is for diagnosis; step-through is for experimentation.

Test yourself

You added a fourth worker, attachment analysis, to Mailmind's three-worker pipeline (order lookup, calendar, refund policy). Now the pipeline is 3x slower, and some email threads show no attachment results at all. No errors appear in the logs.

Answer: You have two separate bugs. The speed drop suggests the new worker joined the pipeline sequentially instead of in parallel with the others. Check your orchestration code: if the manager calls workers one by one, adding a fourth linearly increases latency. Fix the fan-out. The missing results are a routing or execution problem. Trace whether the manager routes threads with attachments to the new worker at all. The routing criteria might be too narrow. If the worker does receive the task, inspect its trace: it may be running but returning nothing because its prompt is too strict about what constitutes a valid attachment. Finally, add a coverage check: every email thread that contains an attachment must produce an output record from the attachment worker. Missing records should raise an alert, never silently omit results.

If you want this kind of breakdown every week, how real systems actually work under the hood, subscribe to Internals Decoded at internalsdecoded.com. Next, we move from debugging a single run to monitoring a fleet. How do you detect when an agent system is degrading in production, before users notice?

Sources

#debugging-agents#observability#tracing#agent-failures
More from the library
The Newsletter

Keep up with AI. One email a week.

One thoughtful email each week. Unsubscribe whenever you like.