Debugging Tool-Call Failures in Agent Chains: A Field Guide for GaaS Teams
Most agent failures aren't model failures. They're tool-call failures, the agent picked the wrong tool, passed garbage arguments, mis-parsed the response, or quietly gave up after the third retry. In agentic AI-as-a-service, where you bill per task or per outcome, every broken tool call is a refund waiting to happen. This guide breaks down the real failure modes, how to instrument for them, and the debugging workflow that actually finds root cause instead of just papering over symptoms with another retry loop.
Table of Contents
- Why Tool Calls Are the Weakest Link
- The Five Failure Modes That Cause 90% of Incidents
- Selection Failures: The Agent Picks the Wrong Tool
- Argument Failures: Right Tool, Wrong Inputs
- Execution and Response-Parsing Failures
- The Debugging Workflow That Finds Root Cause
- Instrumentation: What to Log Before You Need It
- Where Tool Failures Hide in Multi-Step Chains
- Insights Most People Overlook
- References
Why Tool Calls Are the Weakest Link
Spend a week reading agent traces from a production GaaS system and a pattern emerges fast: the language model itself is rarely the thing that broke. The model reasoned fine. It understood the task. Then it called search_orders when it should have called search_invoices, or it passed a date string in the wrong format, or it got back a 200 response with an empty array and decided that meant "done."
This matters more for agentic services than for chatbots because the tool call is where the agent touches the real world. A chatbot that hallucinates produces an annoyed user. An agent that fires a malformed tool call against a payment API, a CRM, or a shipping system produces a wrong action with consequences. And in the per-outcome pricing model that defines so much of this market, a tool-call failure isn't a soft cost, it's a task you don't get paid for, or worse, one you have to make a customer whole on.
The uncomfortable truth is that tool calling sits at a seam in the stack. The model is non-deterministic. The tool is deterministic but unforgiving. The glue code between them, argument validation, response parsing, retry logic, is usually the least-tested part of the whole system. That seam is where chains break. Anthropic's own guidance on building effective agents makes the point that the hard engineering is rarely in the model prompt; it's in the tooling and the loop around it.
The Five Failure Modes That Cause 90% of Incidents
Before you can debug efficiently, you need a taxonomy. When I triage tool-call incidents, almost everything falls into one of five buckets:
- Selection failure, the agent called the wrong tool, or called a tool when it should have answered directly.
- Argument failure, right tool, but the arguments were malformed, missing, hallucinated, or wrongly typed.
- Execution failure, the tool itself errored: timeout, rate limit, 500, auth expired.
- Response-parsing failure, the tool returned valid data, but the agent misread it (empty result treated as success, partial result treated as complete).
- Loop/termination failure, the agent retried forever, gave up too early, or declared victory without doing the work.
The reason this taxonomy is worth memorizing is that each bucket has a different owner and a different fix. Selection and parsing failures are usually prompt, tool-description, or schema problems, your problem. Execution failures are usually the downstream system's problem. Conflating them is how teams waste a sprint "fixing the model" when the actual issue was an expired API token. Tag every incident with its bucket before you do anything else.
Selection Failures: The Agent Picks the Wrong Tool
Selection failures spike when your tool catalog grows. With five tools, the model rarely confuses them. With forty, three of which do subtly different flavors of "look up a customer", confusion becomes routine.
The single highest-leverage fix here is not prompt engineering. It's tool-description engineering. The model chooses a tool almost entirely from its name and description, and most teams write those descriptions for human readers, not for the model. A description like "Searches the order database" is useless next to "Searches the order database. Use this ONLY for orders placed in the last 90 days. For older orders, use search_archived_orders. Do NOT use for invoices." Specificity, negative examples, and explicit disambiguation against neighboring tools cut selection error dramatically.
When you're debugging a selection failure, the question to ask is: given only the tool names and descriptions the model saw, would a smart human have picked the right one? If the answer is no, the model was set up to fail. I've watched teams add three layers of retry logic to route around a selection problem that vanished the moment someone rewrote two ambiguous tool descriptions. OpenAI's function calling documentation is blunt about this: description quality is the primary lever for correct selection, and overlapping tools should be consolidated or sharply differentiated.
A related selection failure is the agent calling a tool when it should have just answered. If your agent reaches for web_search to answer "what's 2+2," your descriptions aren't scoping when to use the tool, only what it does.
Argument Failures: Right Tool, Wrong Inputs
This is the messy middle, and it's where I spend the most debugging time. The agent chose correctly, then fed the tool bad inputs. Common variants:
- Type and format errors, a date passed as "next Tuesday" instead of ISO-8601, a number passed as a string, an enum value the model invented.
- Hallucinated arguments, the schema says
customer_idis required, the model doesn't have one, so it fabricates a plausible-looking ID rather than calling a lookup tool first. - Dropped or partial arguments, multi-field calls where the model fills three of five fields and leaves the rest null.
The structural fix is to make your tool schemas do the work. If your tool framework supports it, use strict schema enforcement so the model is constrained to valid JSON matching your types, most current function-calling APIs offer a structured-output or strict mode that eliminates an entire class of malformed-JSON failures at the source. Then add a validation layer before the tool fires that returns a clear, model-readable error on bad input ("order_date must be ISO-8601; you provided 'next Tuesday'"). A well-written validation error is a second chance: a good agent reads it and self-corrects on the next turn. A cryptic stack trace is a dead end.
The hallucinated-argument case deserves special attention because it's the most dangerous. When a required field is missing, the model's training pushes it toward producing something rather than admitting it lacks the data. The fix is design-level: don't make a tool require an ID the agent can't plausibly have. Instead, expose a lookup tool and write the description to chain them ("First call find_customer to get a customer_id, then pass it to get_orders"). You're encoding the dependency the agent would otherwise have to guess at.
Execution and Response-Parsing Failures
Execution failures, timeouts, 429s, expired auth, downstream 500s, feel like they should be the easy bucket. They're deterministic and they come with error codes. The trap is treating every execution error as transient and retriable. A 429 rate limit deserves a backoff retry. A 401 auth failure does not, retrying a bad token just burns latency and budget before failing anyway. Your retry logic needs to branch on error class, not blindly loop. This is the heart of the latency-reliability tradeoff in production agents: every blind retry buys a sliver of reliability at the cost of seconds the user feels.
Response-parsing failures are sneakier and, in my experience, the single most under-instrumented category. The tool returns HTTP 200. The data is valid. And the agent draws the wrong conclusion. The classic is the empty result: a search returns [], which is a perfectly valid "no matches," but the agent treats it as task completion and reports success to the user. Nothing errored. No alert fired. The customer just got a confidently wrong answer, the silent-failure problem that haunts agentic systems.
Debugging these requires looking at the agent's interpretation of the tool output, not just the tool output itself. Your trace needs to capture both the raw response and the reasoning step that consumed it. If you only log "tool returned 200," you will never find this class of bug. You have to log what the agent decided the 200 meant.
The Debugging Workflow That Finds Root Cause
Here's the workflow I'd hand a new engineer joining a GaaS reliability team:
Step 1, Reproduce with the exact trace. Pull the full execution trace for the failed run: every tool call, its arguments, its raw response, and the model's reasoning between steps. If you can't reproduce from the trace, your observability is the first bug to fix. (The replay problem, recreating an agent's exact run, is hard enough that it deserves its own engineering investment.)
Step 2, Find the first divergence, not the last error. Agents fail forward. The error you get paged on is often three steps downstream of where things actually went wrong. Walk the trace from the top and find the first tool call whose arguments or result were already wrong. That's your root cause; everything after it is cascade.
Step 3, Bucket it. Tag the root-cause step with one of the five failure modes. This tells you who owns the fix and what kind of fix it is.
Step 4, Ask the counterfactual. Would a careful human, seeing only what the agent saw at that step, have made the same mistake? If yes, it's a context/tooling problem (fix the descriptions, schemas, or available data). If no, it's a model-reasoning problem (fix the prompt, add an example, or consider a verification step).
Step 5, Fix at the earliest possible layer. Prefer a schema constraint over a prompt instruction, prefer a prompt instruction over a retry, prefer a retry over a human escalation. The further upstream you fix it, the fewer downstream incidents you create.
This workflow sounds obvious written down. The discipline is in resisting the urge to jump straight to "add a retry" because it's the fastest patch. Retries hide root cause and inflate your cost-per-task.
Instrumentation: What to Log Before You Need It
You cannot debug what you didn't capture, and tool-call failures are notoriously hard to reproduce after the fact because of model non-determinism. So instrument ahead of the incident. At minimum, every tool call in your chain should emit:
- The tool name and the full arguments as the model produced them (pre-validation).
- The validation outcome, pass, or the specific rejection reason.
- The raw tool response and the HTTP/error status.
- The model's reasoning text in the step that consumed the response.
- Latency and retry count for the call.
- A correlation ID tying the call to the parent run and the user-facing task.
The pre-validation arguments matter enormously. If you only log what the tool received after your validation layer cleaned it up, you've erased the evidence of what the model actually tried to do. The bug lives in the difference. Treat this as part of the broader audit trail every autonomous agent should produce, the same data that satisfies an enterprise buyer's compliance review is the data you need to debug at 2 a.m.
Standard tracing semantics are converging here. The OpenTelemetry project's GenAI semantic conventions now define spans for model and tool invocations, which means you can build on a shared schema rather than inventing bespoke logging that no observability vendor understands. Adopting a standard early is cheaper than retrofitting one after you've outgrown print statements.
Where Tool Failures Hide in Multi-Step Chains
Single tool calls are tractable. The difficulty compounds in long chains, because a small early error doesn't error, it propagates. The agent looks up the wrong customer in step two, and every subsequent step operates faithfully on the wrong data, producing a fully coherent, completely incorrect outcome. McKinsey's analysis of agentic AI in the enterprise repeatedly returns to this theme: the bottleneck to deployment isn't raw capability, it's reliability across multi-step workflows where errors accumulate.
Two practices contain this. First, add cheap verification checkpoints between expensive or irreversible steps, a quick consistency check ("does this customer_id belong to the user who made the request?") catches a propagated error before it becomes an irreversible action. Second, design idempotency and rollback into any tool that mutates state, so a bad call in the middle of a chain doesn't leave the system in a corrupt half-finished state.
In multi-agent setups the problem worsens, because one agent's malformed hand-off becomes another agent's malformed input, and the trace now spans process boundaries. That's a deep enough topic to be its own node in this cluster, multi-agent reliability is where a single weak tool call can break the entire chain, but the debugging principle is identical: instrument the seams, find the first divergence, fix it upstream.
Insights Most People Overlook
The model is usually right; your tool descriptions are usually wrong. Teams instinctively blame the LLM when an agent picks the wrong tool. In practice, the overwhelming majority of selection failures trace to ambiguous, overlapping, or human-oriented tool descriptions. Audit your tool catalog the way you'd audit an API: any two tools a smart reader could confuse will be confused by the model, predictably and at scale.
A good error message is a debugging tool the agent uses on itself. Most teams treat validation errors as something the human reads. The bigger win is writing errors the model can act on. "Invalid input" forces a retry blind. "amount must be a positive integer in cents; you passed 12.50, did you mean 1250?" lets the agent self-correct on the next turn, turning a hard failure into a soft one and cutting your escalation rate without any model change.
Empty-result-as-success is the most expensive bug you're not measuring. Because it never throws, it never alerts, and it produces confident wrong answers that erode customer trust faster than visible errors do, customers forgive an agent that says "I couldn't find that," but not one that cheerfully reports a wrong answer. Add explicit instrumentation for "tool returned a successful-but-empty result and the agent terminated," and you'll likely find it's a meaningful slice of your silent-failure rate.
Retries are a reliability tax, not a reliability fix. Every retry that papers over a root cause inflates your latency and your cost-per-task, which in a per-outcome pricing model directly compresses your margin. Treat your aggregate retry rate as a reliability KPI on par with task success rate. A rising retry rate with a flat success rate means you're spending more money to deliver the same result, a slow bleed that's invisible unless you're watching for it.
Non-determinism makes "fixed it" a probabilistic claim. Because the same input can produce different tool calls across runs, a single passing test after a fix proves almost nothing. You need to re-run the failing case many times and measure the rate, then add it to a regression suite. Otherwise you'll "fix" a flaky failure that simply didn't recur on the one run you checked.
References
More in Reliability
- Observability for Agent Memory: What Did It Remember, and Why?
- The Replay Problem: Why Recreating an Agent's Exact Run Is Harder Than It Looks
- Synthetic vs. Real-World Evals: Getting the Mix Right
- Guardrail Testing: How to Red-Team Your Own AI Agents Before They Embarrass You
- The Famous Agent Failures of 2025-2026, Dissected