CustomLabs
Agents & tools

Why is our agent confidently wrong right after a tool call failed?

Answer

The tool returned HTTP 200 with an error message in the body, or an empty result set, and the agent read the absence of data as evidence rather than as a failure — because nothing in the response forced a distinction between "nothing matched" and "something broke."

Also known as swallowed error, false-success tool response

Symptoms

What does this look like in production?

  • The agent states something as fact ("there are no open orders") immediately downstream of a tool call that actually errored
  • Logs show a 200-status response with an error string embedded in the body, treated by the agent as normal data
  • An empty list comes back from a tool and the agent proceeds as if that confirms absence rather than possible failure
  • Per-tool error rates in your metrics are near zero while user-reported wrongness for the same tool is not
Root cause

Why does it happen?

Many internal tools and APIs are built to always return a 200 with a JSON body, using an error field or message inside the payload to signal a problem, rather than a non-2xx status the calling code is forced to branch on. An agent that just reads the body as data has no structural reason to check for that field, and a capable model will happily synthesize a confident statement from whatever shape of data it received — including an error message it misreads as content, or an empty array it reads as "confirmed nothing exists" rather than "the call didn't actually run."

The result looks identical to a correct, grounded answer from the outside: fluent, specific, and delivered without hedging, because the model has no idea anything went wrong upstream. It is not lying — it is accurately reporting what it was told, and what it was told was itself a masked failure.

Detect

How do you confirm it's this?

  • Correlate per-tool error rate (from logs, not from agent behavior) against downstream task success — a tool with silent errors will show low logged errors but low correlated success
  • Assert in your eval suite that every tool result carries an explicit, checkable status field, and flag any tool that doesn't
  • Deliberately force a tool to fail in a test run and check whether the agent's final answer reflects that failure or treats the result as normal
  • Sample raw tool responses for anything containing "error," "failed," or similar strings inside an otherwise-200 body
Fix

How do you fix it?

  1. Return typed, discriminated ok/error results

    Every tool response should carry an explicit status the calling code — and the model — can branch on, not an error string buried in a body shaped like success.

  2. Make empty results explicit

    "0 rows matched" and "the query failed to run" must be distinguishable results, both to your code and in what gets fed back to the model, never collapsed into the same empty array.

  3. Fail the step instead of continuing on ambiguous data

    When a tool's result is ambiguous or malformed, stop that step and surface the failure rather than letting the agent proceed and paper over it with a fluent guess.

  4. Add an eval where the tool is forced to fail

    Include test cases where a dependency is deliberately broken, and assert the correct behavior is for the agent to say so — not to produce a plausible answer anyway.

Limits

What this doesn't cover

This applies when the tool itself masks failure as success — if the tool correctly reports an error and the agent still proceeds confidently, the defect is in the agent's handling of a correctly-signaled error, not in the tool response shape.

Not sure if this is the one?

A Ship Audit runs this full checklist against your actual system and hands back a written, prioritized plan.

Book a Ship Audit

navigate select esc close