Skip to Content

My Pydantic AI agent fails without raising an error. Why?

Rius shows a Pydantic AI run that fails without raising an error as a recovered trace, where a child step errored but the run itself finished OK. The error was caught somewhere between that step and the root, so the run looks successful. Open the trace to see the failed step, and let the Swallowed Error alert catch it next time.

How it works

Pydantic AI emits its own OpenTelemetry spans, and Rius reads them directly. Each agent run is a root span named invoke_agent <agent name>. Each model request is a chat <model> span with tokens and cost. Each tool call is an execute_tool <tool name> span. A successful span arrives with status UNSET rather than OK. The trace status still reads Ok, so an UNSET span is not a failure.

Rius derives trace status from the spans, not from what your agent reports:

  • A trace is failed when at least one span carries an ERROR status.
  • A failed trace whose root span finished without an error of its own gets a recovered badge. The child spans errored, the agent retried or fell back, and the run completed clean.
  • If the root span never arrived, the badge reads recovered?, because the verdict is a guess.

The Swallowed Error alert is built for this shape. It fires when the root span finishes OK while at least one child step that is not a tool call ended with an error. Errored tool calls do not count, because a failed tool call is returned to the model as the tool’s result, so the agent saw the failure. Typical causes are a model call that fails and falls back to a canned answer, retries that run out and fall back to a cached value, or a sub-agent that crashes while the orchestrator ships a partial answer. It fires once per run, and only on finished traces.

Set it up

  1. Send Pydantic AI spans to Rius. Install the SDK with pip install glassflow-rius pydantic-ai, no extra needed, then turn on the framework’s instrumentation. Setup is covered in full on the Pydantic AI integration page, and the other frameworks are listed under Integrations.
import rius from pydantic_ai import Agent rius.init(api_key="ri_...", service_name="my-agent") Agent.instrument_all(True)
  1. Open Traces and look for the recovered badge or the failed status. Each row shows the error count, so a run that reads as successful but has errors stands out. The full walk-through is in Exploring traces.
  2. Open the trace. In the waterfall, failed spans are highlighted along the path from the root to the error. Select the failed chat or execute_tool span and read the exception and traceback at the top of the detail panel.
  3. To see the same failure across runs, open the Spans tab, filter by status, and use the All kinds menu to narrow to LLM or Tool. Sort by Time to find when it started.
  4. Check the trace tools. A retry chain collapses repeated identical calls into one row such as fetch_article · 3 attempts · recovered. On an LLM span, Since previous llm call shows what changed in the prompt between calls.
  5. If a run leaves no trace at all, because the process crashed or was killed, turn on partial spans. Rius then receives a content-free snapshot when each span starts, and a run that died mid-flight stays visible as running….
export RIUS_PARTIAL_SPANS=true
  1. Make the next one loud. Swallowed Error is pre-defined, so it is already on. To give one service its own bar or its own delivery, open the alert’s details page and click Narrow this alert, then filter by Root service. Narrowing is an admin action.

What you get

  • A recovered badge on every run that finished clean while a step inside it errored, so quiet failures are visible in the trace list.
  • The exact failed step, with its exception and traceback, in the waterfall of a single trace.
  • A Swallowed Error firing for each such run, sent to the channels attached to the alert, so you hear about it without opening the console.
  • A way to see how the same step behaves across many runs through the Spans tab, plus retry chains that show how many attempts a step needed.

For a wider picture of watching agents in production, see Monitor AI agents in production.

When something else fits

  • If the same error repeats across runs, such as a rotated credential or a rate-limited upstream, Consistent Error Pattern is the better detector. It groups errored spans by service, step and error message, and it also covers failed tool calls, which Swallowed Error skips. Both are described in Pre-defined alerts.
  • If no span errored and the agent just gave a wrong answer, there is nothing for an error alert to catch. Read the prompt and completion on the Input / Output tab, which needs content capture on.
  • If you want a threshold on error rate or cost instead of a failure shape, a custom alert fits better.

Still stuck? Get help

Last updated on