243
Standing up an agent takes minutes. Getting real observability on it takes far longer: pick a backend, run an OTel collector, configure an exporter, wire env vars everywhere the agent runs, then figure out which spans the agent emits itself versus which you have to instrument by hand and redeploy to test. That gap is not a tooling problem. The tools are fine. The problem is that distributed tracing was designed for a different shape of program.
Tracing assumes a request tree: a call comes in, fans out to known downstream services, each hop is a span, the tree closes. The structure is known before the request starts, and instrumenting means labeling edges that already exist. An agent is a loop with a model in the middle deciding what happens next, so the structure is neither known in advance nor stable across runs. Four consequences follow:
The unit that matters is the tool call, not the network hop. When a run goes wrong, the question is what the agent decided to do, with what arguments, and what came back. Those are semantic events, and HTTP instrumentation captures none of them for free.
Identical inputs produce different traces. Two runs of the same task can take different paths and both succeed. Aggregate span statistics assume stable topology, so p95 on a span that appears three times in one run and zero times in the next is close to meaningless. You want to compare runs, not aggregate spans.
Most agent failures are not errors. A tool call fails, the agent reads the error, works around it, and finishes. Every span is green, error rate is zero, and the output is wrong. Nothing exists for a threshold alert to fire on, because the failure sits in the reasoning, upstream of anything being measured.
The payloads are the point, and they are big. Prompts, tool arguments, and tool results are what you need to read. Span attributes were not built for multi-kilobyte text, and truncating them discards the evidence.
OTel's GenAI semantic conventions will help, but conventions standardize field names. They do not fix a request-tree model describing a decision loop, and they do not save you the afternoon spent wiring a collector.
The alternative: Failproof instruments the tool call boundary instead of the network boundary. Every action becomes an event with call, arguments, result, and position in the run. Setup is npm i -g failproofai then failproofai config, plus an API key with events.add permission from the dashboard's Keys section. No collector, no exporter, no agent code changes. Existing history can be pulled in with failproofai backfill --since 7d.
First hour: skip dashboards. Read three or four real runs end to end and look for repeated calls (cheap to fix, invisible until seen), swallowed errors (succeeded runs containing failed tool calls, where the interesting bugs live), and divergence between two runs of the same task, which marks judgment calls you never specified. None of these throw exceptions or page anyone.
The CLI is open source; docs and dashboard at befailproof.ai.
Built with