Agents report success for actions that never happened — no error, clean trace, and every observability tool reads it as a success, because they're all reading the agent's own account of itself.
This doesn't read the trace differently. It queries the authoritative system instead — the actual Gmail mailbox — and returns confirmed / contradicted / inconclusive with the evidence attached: the account queried, the search window, and what was found in it.
Two failure classes, different evidence. If there's no tool call in the trace at all, the absence is the evidence and nothing external is needed. If the call happened and returned cleanly but nothing landed, only the mailbox can tell you.
The parts I'd most want criticised:
Inconclusive is a first-class verdict. If the trace can't be shown complete, or the tool span has a name I don't recognise, or the mailbox can't be established — it refuses to judge rather than calling a working agent a liar. A false accusation costs more than a missed detection. I may have that balance wrong.
It cannot catch a correct call with a wrong argument. Asked to mail one person, confidently mails another — the send is real, Gmail confirms it, verdict is confirmed, correctly. The instruction is recorded next to the arguments so a human can see it. No verdict catches it.
Gmail only so far. LangChain via a callback handler, or the SDK by hand. No n8n, no CrewAI. Zero users — this is day one.
matrixverify.dev
Top comments (1)
Keeping inconclusive as a first-class verdict is the right call. The quickest way an observability tool gets turned off is crying hallucination whenever an upstream token expired or a telemetry span got dropped. Treating missing evidence as unknown rather than failure preserves trust in the alerts that actually fire.
The semantic argument mismatch is the nastier edge case. When an agent emails the wrong recipient or overwrites the wrong file, the external API will happily return a 200 with valid metadata. In our pipelines, the only check that caught those without running another judge model was extracting the explicit target entities from the initial user prompt and asserting that the tool arguments had non-empty overlap with that set before checking external confirmation.