faultgate 0.3.1 · fixes from the first outside test, 180 real tau2-bench runsRead the changelog →
faultgate docs

Checks Reference

Built-in checks

Check Kind Fires when
search_loop rule The run ended with no answer at its step budget and most tool calls returned nothing.
abstention rule The final answer explicitly says the information could not be found: an inability to find (couldn't find / locate / retrieve / determine), no matching documents, information not available, don't know. A bare cannot / unable to does not count: a support agent that “cannot modify the order again” or is “unable to verify” an unauthenticated caller has not abstained.
policy rule A tool call broke the policy: unlisted tool, denied argument pattern, oversized argument, call budget, argument limit, identity mismatch, or missing prerequisite.
repeated_call rule The same tool was called with identical arguments and returned identical results >= 3 times.
unrecovered_tool_error rule A tool call produced a structural error with no later successful call of the same tool, or a span errored (error.type or status code 2) and no later span made a successful tool call.
context_overflow rule The run hit the model’s context window or output token limit: a span’s gen_ai.response.finish_reasons says length / max_tokens, or a provider error naming the context limit (context_length_exceeded, “maximum context length”, “prompt is too long”) in a span status, error.type, tool result or faultgate.termination.
wrong_answer golden Answered, and the expected answer is not in the final answer.
truncation golden The answer has the head of the expected token but not the whole token (Onyx for Onyx-4413).
wrong_direction judge On a multi-hop task, the agent walked the dependency chain backwards.

Run faultgate checks to list them from the CLI. For the policy checks, see Business Rules.

Measured on real agent traces

faultgate reads chat-only OpenTelemetry GenAI traces where tool calls live inside messages (as exported by many agent harnesses), in addition to execute_tool spans.

Run make demo-real (first run downloads ~220 MB, ~1 min) to fetch and evaluate 30 real traces: 5 per benchmark from Exgentic/agent-llm-traces-v2 (AppWorld, BrowseComp-Plus, SWE-bench, tau2 airline, tau2 retail, and tau2 telecom).

$ faultgate check .demo/real_traces.json
trace         search_loop       abstention        policy            repeated_call     unrecovered_tool_error  context_overflow
------------------------------------------------------------------------------------------------------------------------------
8a224e8eacdd  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
3cf53cafee61  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
0ff67ea879fc  ok   1.00         ok   1.00         ok   1.00         ok   1.00         FAIL 1.00         ok   1.00
0f2709401932  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
a182fd9c1858  ok   1.00         ok   1.00         ok   1.00         FAIL 1.00         ok   1.00         ok   1.00
9bf471687b5f  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
16b13ee29724  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
9dc71e9167b0  ok   1.00         ok   1.00         ok   1.00         ok   1.00         FAIL 1.00         ok   1.00
3524b4b6ef7e  ok   1.00         ok   1.00         ok   1.00         ok   1.00         FAIL 1.00         ok   1.00
9ca4051344ef  ok   1.00         ok   1.00         ok   1.00         ok   1.00         FAIL 1.00         ok   1.00
56e646e603b2  FAIL 1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
f406d07bd94c  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
012e74b002d9  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
f0cd792c3105  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
7c69e4d47302  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
fadbf538c24a  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
8e611f21829d  ok   1.00         ok   1.00         ok   1.00         ok   1.00         FAIL 1.00         ok   1.00
70722761fb7a  FAIL 1.00         ok   1.00         ok   1.00         FAIL 1.00         ok   1.00         ok   1.00
4ab9ef2c7e60  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
910a177350e2  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
a585b61b1598  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
3d7d24721847  ok   1.00         ok   1.00         ok   1.00         ok   1.00         FAIL 1.00         ok   1.00
4422dd26b177  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
bff8bb4c1b2e  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
e42782af7315  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
53fdb0601422  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
1dff5fc97b54  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
88733a4ec841  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
dc97bf8af1d8  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00
192bf8092eb8  ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00         ok   1.00

9/30 traces failed · search_loop=2, abstention=0, policy=0, repeated_call=2, unrecovered_tool_error=6, context_overflow=0 · judge none · 2.1s

Two new checks have measured trust. They were ported from FAULTLINE P18 (projects/p18_trace_triage):

Check Kind Measured trust Source
repeated_call rule κ 0.95 vs a blind second rater (Claude Opus 5.5) on 97 real runs FAULTLINE P18
unrecovered_tool_error rule Caught 13 of 23 unrecovered errors confirmed by the blind second rater (Claude Opus 5.5) (recall 0.57, κ 0.54); misses plain-text errors and run-ending API failures (faultgate has no check for those yet; read flagged traces manually) FAULTLINE P18

Span error = error.type or OTLP status code 2; P18 measured error.type only.

These are public benchmark traces, not production traffic. The P18 sample was stratified half passed and half failed, so its rates are not production failure rates. The dataset licence is unstated, so faultgate does not ship or redistribute the traces. The demo downloads them from Hugging Face.

Swap the judge

Judges implement this protocol:

class Judge(Protocol):
    name: str
    budget: int | None          # max characters of trace it can read
    def ask(self, state: str, question: str) -> Verdict: ...   # Verdict(detected, confidence, reason)

laya and litellm:<model> ship in the box. Add a judge, run scripts/calibrate.py --judge yours, and publish the row. See Trust & Calibration for what the existing judges score.