๐Ÿ“Š Evaluating the agent

July 4, 2026 ยท View on GitHub

A human-in-the-loop agent has to be judged on two things: is the answer good, and did it pause for approval before acting? The harness in backend/evals/ scores both.

Quick start (offline, no API keys)

cd backend
python -m evals.run_evals

This runs every example in evals/dataset.py through the agent (auto-approving tool calls) and prints a scored table:

=== Eval results ===
  solid-state-batteries    paused_for_approval=1.00  completed=1.00  no_pii_leak=1.00
  tcp-vs-udp               paused_for_approval=1.00  completed=1.00  no_pii_leak=1.00
  ...

=== Summary (mean) ===
  completed              1.000
  no_pii_leak            1.000
  paused_for_approval    1.000

The evaluators

Deterministic (run offline with the mock model โ€” no keys):

MetricWhat it checks
paused_for_approvalThe agent interrupted for human approval on the expected tool before running it โ€” the behaviour this template exists to enforce.
completedIt produced a non-empty final answer without erroring.
no_pii_leakThe final answer contains no recognisable raw PII (pairs with the guardrail middleware).

Model-graded (needs a real model):

MetricWhat it checks
correctnessAn LLM-as-judge score (0โ€“1) comparing the answer to a reference. Automatically skipped on the mock model.

Set a real model to include the judge:

LLM_MODEL=gpt-4o-mini OPENAI_API_KEY=sk-... python -m evals.run_evals

Tracked experiments with LangSmith

To log results as a comparable experiment over time, set LANGSMITH_API_KEY and run:

LANGSMITH_API_KEY=... LLM_MODEL=gpt-4o-mini OPENAI_API_KEY=sk-... \
  python -m evals.run_evals --langsmith

This creates (once) a hitl-research-agent dataset in your LangSmith workspace and runs evaluate against it, so each run shows up as an experiment you can diff.

Extending it

  • Add examples โ€” append to DATASET in evals/dataset.py with the questions that matter for your domain and the tool you expect the agent to pause on.
  • Add evaluators โ€” write a fn(example, result) -> float and register it in DETERMINISTIC_EVALUATORS (or add another model-graded one alongside correctness). Ideas: citation presence, answer length bounds, refusal on out-of-scope questions, latency budgets.
  • Wire into CI โ€” the deterministic metrics run offline, so you can gate a PR on, e.g., paused_for_approval == 1.0 for every example.