ok hides one.
Why empty is split out
A call that succeeded and returned nothing is the failure the outcome field hides. Burying it inside the green bar is exactly how it stays hidden — sook is drawn as ok − empties and empty gets its own slice.
Both the overview and the tool page render this from the same function, so the two cannot disagree about what “ok” counts. See Empty results.
crashed versus tool_error
These look identical from outsideMcpServer, which catches everything a tool does and converts it into { isError: true }. The SDK wraps your tool callbacks as well as the request handler so the difference survives.
It matters because the two have opposite fixes:
tool_error— your tool decided to refuse. Often correct behaviour. Worth checking the model understands why it was refused.crashed— your tool has a bug. Nothing about the model’s behaviour will fix it.
bad_args is a description problem
bad_args means the model constructed arguments your schema rejected, and your handler never ran. That is not a bug in your code; it is a gap between what your schema requires and what your description implies.
A tool with a high bad_args share almost always has an under-described required field, an enum whose values are not listed, or a name that suggests something other than what it takes.
The error rate
The error rate on the overview isbad_args + tool_error + crashed as a share of calls. empty is deliberately not in it — an empty result is a different failure with a different rate beside it.
Counted by name, in both tables
The tool table and the clients panel both carryBad args, Tool errors, Crashes and Empty as their own columns, from one shared definition — so a row means the same thing on both.
They were one column called Failed, and pooling is what made it useless. 13.4% failed says open the tool and nothing about what to change inside it. 389 bad arguments is a schema the model cannot fill in; 42 tool errors is a handler refusing work it was given; 3 crashes is a bug. One number, three fixes.
Counts, not rates. Both tables already carry calls, so the denominator is on the row — and a crash is an event rather than a proportion. Three of them reads as something to go and fix, where the same three as 0.1% is the figure your eye skips. A zero from real traffic is muted; a row with no calls dashes all four, because zero failures out of zero calls is not a measurement.
The one pooled figure left is the line above the outcome breakdown — “13.4% failed · 0.4% empty” — which is a summary sitting on top of a panel that lists all five by name underneath it.
Filtering
Outcomes scope cleanly to both filters:tool_hours carries per-outcome counters per tool, per client, per hour. So does the error rate, and so does everything derived from them.
Related
- Empty results
- First-call success — which counts
okand non-empty and un-retried - Tool detail — the same breakdown for one tool