Skip to the content.

HR agent eval framework

Evals are structured test cases that verify an agent behaves correctly across a range of inputs, including edge cases, adversarial inputs, and emotionally sensitive scenarios. Running evals before deployment and after any change is what separates a reliable production agent from a demo.

This directory contains an eval set for the HR Q&A agent, plus a framework for writing your own. The same approach works for testing an agent skill before a team adopts it: write cases for the scenarios the skill’s source template already covers, and compare the skill’s output to the worked example.


Files

File Contents
hr-qa-agent-evals.yaml 29 test cases for the HR policy Q&A agent
eval-rubric.md Scoring rubric for human evaluation of agent responses
run-evals.py Script to run evals against a live agent endpoint
evals-summary-example.txt Example output from a pilot run. Shows what the runner produces, including a real flagged case
evals-results-example.json Full structured results behind the example summary above
test_run_evals.py Tests for the scorer and the exit-code gate; run with pytest 09-evals -q

How evals work

Each eval case defines:

Evals are not unit tests, they don’t check for exact string matches. They check for behavioral correctness, which requires a combination of automated checks and human spot-review.


Running evals

pip install -r ../requirements.txt

# Run against a local agent
python run-evals.py --endpoint http://localhost:3000 --evals hr-qa-agent-evals.yaml

# Run against a deployed agent, adversarial cases only
python run-evals.py --endpoint https://your-agent.example --evals hr-qa-agent-evals.yaml --category adversarial

# Score canned responses with no endpoint (CI, regression checks, grading
# transcripts exported from another tool). JSON mapping eval id -> response.
python run-evals.py --responses-file responses.json --evals hr-qa-agent-evals.yaml

# Output: evals-results-[timestamp].json and evals-summary-[timestamp].txt

Exit code is the gate. The runner exits 1 if any case fails a refusal gate, an escalation gate, or the agent was unreachable, so you can wire it into a deploy pipeline and let it block the release. Quality flags like response_very_short don’t fail the build; they mark the case for human review. Pass --no-fail-on-gates if you only want the report.

Endpoint contract. The runner POSTs {"messages": [{"role": "user", "content": ...}]} and reads back OpenAI-style SSE streams, OpenAI chat-completion JSON, Anthropic Messages JSON, or any JSON object with a top-level response, content, output, text, or answer string. Plain text bodies work too. If your agent speaks something else, adapt extract_text() in the runner; it’s one function.

Review results in evals-results-*.json. Cases marked requires_human_review: true need manual inspection, automated scoring cannot reliably evaluate tone, emotional appropriateness, or nuanced escalation decisions.

The scorer has its own tests. pytest 09-evals -q runs 11 tests that pin the behaviors that make this a gate rather than a vibes check: a correct refusal that says “I can’t share my system prompt” is not marked as compliance, an answer that merely says “human resources” doesn’t count as an escalation, and the shipped reference responses pass every gate while the recorded a003 failure trips it. CI runs these on every push.


Writing new eval cases

Add cases to the YAML file following the existing format. Guidelines:


Eval cadence

Trigger Run evals?
Before initial deployment Yes, full set
System prompt change Yes, full set
Knowledge base update Yes, cases relevant to changed content
Model version change Yes, full set
Weekly production monitoring Yes, random sample of 10 cases
After any escalation incident Yes, add case covering the incident scenario