Skip to main content
RAG failures split into two kinds - the retriever fetched the wrong chunks, or the generator ignored the right ones - and a single end-to-end score can’t tell you which. AgentX ships the standard component-split metrics as seeded judge-scorer templates (New scorer → Template scorer on the Scorers page), usable online (live traffic) and offline (dataset runs) with the same configs.

The metric pack

Add one from the template picker and it becomes an ordinary judge scorer of your own: tune its criteria, enable its live scoring, or pass it as scorer_id on a run. Deleted ones stay deleted; a metric added in a release is backfilled once to existing projects.

Where the context comes from

{context} in these judge prompts resolves through the same precedence everywhere:
  1. Explicit - metadata.retrievalContext on a trace, or retrieval_context returned by your agent function in a run (string or list of chunk strings).
  2. Recorded retrievals - the trace’s own retrieval spans: tracer.trace_retrieval(...), LangChain/LlamaIndex retriever callbacks, OTel retrieval spans. No caller changes needed: if your integration already records retrievals, the judges see the chunks. Custom span names are fine (trace_retrieval("kb_search", ...)) - retrieval spans carry an explicit span kind, so they’re recognized regardless of what you name them.
  3. Pinned (offline only) - the dataset case’s static retrievalContext.

Online: score live RAG traffic

Add the metric as your own scorer (Scorers → New scorerTemplate scorerAdd), then enable its live scoring - in the editor’s Live scoring step, or from the SDK - and every sampled trace is judged with whatever it actually retrieved:
A response claiming a 90-day refund while the retrieved policy chunk says 30 days scores 0, with the contradiction named in the justification - and raises a signal you can send straight to a regression dataset.

Offline: dataset runs with dynamic context

A real RAG agent retrieves per query, so return what it retrieved alongside the answer - the faithfulness judge grades against that run’s chunks, not a stale pin:
The explicit retrieval_context return is optional here - with the retrieval recorded on the linked trace, the engine pulls the chunks from its retrieval spans automatically; returning it just takes precedence. Contextual Recall additionally needs expected_results on the case (it attributes the reference answer’s claims to the context).

Deterministic: expected context match (no judge)

The five metrics above are LLM judges - each score is a model call. For retriever regression checks, a case can instead pin the chunks a correct retriever should fetch, and the engine compares them against what was actually retrieved with token-level Jaccard similarity - deterministic, free, and safe to run on every retriever, chunking, or embedding change:
The same field is editable in the dashboard: open a dataset case and fill Expected retrieval context (blank line between chunks), next to Expected tool calls. Full parameter reference: Build a dataset. Each result gets a Context match (jaccard) scorer row (0-1) next to any judge scores, computed from the same actual context the judges see (the result’s retrieval_context, else the linked trace’s retrieval spans). Jaccard measures token overlap, not meaning - use it to catch “the retriever stopped returning the right chunk”, and the judge metrics for whether the chunks are semantically right.

The loop

Capture retrievals → RAG pack scores live traffic → low scores raise signals → failing traces become dataset cases → offline runs guard the fix → CI gates keep it from regressing.

Runnable examples

Four end-to-end scripts in sample-scripts/sdk_rag_samples: online Faithfulness with automatic retrieval-span context, online Context Relevancy catching a broken retriever (and raising a high-severity signal), offline Faithfulness with dynamic per-case context, and the deterministic Jaccard retriever regression check.