SDYJ benchmarks are designed as regression checks for agent behavior, not as one-off demos. A benchmark run should answer three questions:
- Did the agent produce a useful answer?
- Was the answer grounded in traceable evidence?
- Can failures be diagnosed from the trace?
Offline benchmark with canned evidence and fake LLM:
python main.py benchmark run --max-scenarios 1 --max-iterations 2Use it as a CI gate:
python main.py benchmark run --fail-under 0.75Override individual metric thresholds:
python main.py benchmark run \
--threshold trace_completeness=0.9 \
--threshold citation_id_coverage=0.8Check deterministic behavior by repeating offline runs:
python main.py benchmark run --determinism-repeats 2Compare against a saved summary:
python main.py benchmark run --compare-summary outputs/eval_reports/eval_summary_YYYYMMDD_HHMMSS.json
python main.py benchmark compare baseline.json candidate.jsonThe older command remains supported:
python main.py eval --max-scenarios 1| Scenario | What it tests |
|---|---|
agent_reliability_hard |
RAG, web search, MCP-style tools, human approval, ablation, latency/cost thresholds |
tool_failure_recovery_hard |
Timeout, empty result, duplicate URLs, fallback, source quality, review strategy |
mcp_rag_ops_hard |
Customer-support MCP+RAG with privacy, refusal, safety boundaries, SLO, and cost budget |
llm_failure_recovery_hard |
Injected transient + permanent LLM failures: gates require ≥1 recorded retry AND ≥1 recorded degradation while the report still ships |
| Metric | Meaning |
|---|---|
plan_coverage |
Required concepts covered by plan/report |
section_completeness |
Expected report sections present |
citation_id_coverage |
Evidence IDs cited in the report BODY (reference list excluded — it enumerates every id by construction) |
citation_validity_rate |
[E#] mentions that reference real evidence; fabricated ids lower it |
invalid_citation_count |
Fabricated mentions surviving in the final report (expected 0) |
citation_density_per_1k_chars |
Citation density normalized by length |
tool_success_rate |
Retrieval batches without errors |
grounded_key_finding_rate |
Key findings carrying a valid evidence citation |
faithfulness_score |
LLM-judged claim↔evidence support; own threshold (0.70), NOT part of overall_score |
citation_precision |
LLM-judged share of claims at least partially supported |
retries_total |
Transient LLM failures recovered by retry |
degraded_event_count |
Recorded graceful degradations |
trace_completeness |
Trace has required fields, nodes, events, tool/LLM details, and replay cache |
overall_score |
Compact dashboard score (deterministic metrics only, incl. validity) |
The judge is dual-track: offline runs grade with a canned verdict (CI stays
deterministic and key-free), --live grades with the real provider.
Each scenario can define thresholds. A benchmark summary includes:
passedfailed_scenariosfailed_thresholdsdeterminismcomparison- paths to generated report and trace artifacts
Run a real model while keeping canned evidence stable:
python main.py benchmark run \
--live \
--provider deepseek \
--model deepseek-v4-flash \
--scenario agent_reliability_hardAlso evaluate real retrieval:
python main.py benchmark run --live --live-searchLive-search scores can drift because external search results change. Use them as smoke tests, not as deterministic regression gates.