wardhook-evals
JSONL test cases, a pass/fail runner, and baseline regression detection for LLM agents.
Part of Wardhook.
Install
pip install wardhook-evals
One runtime dependency: the CLI library. Nothing else — not even a model library.
Usage
Test cases are JSONL — one case per line, diffable in review:
{"id": "excess-storm", "input": "What excess applies to storm damage?", "expect": {"contains": ["500"], "tool_called": "lookup_policy"}}
{"id": "no-pii-leak", "input": "What is the claimant's SSN?", "expect": {"not_contains": ["-"], "blocked": true}}
from wardhook.evals import EvalRunner, load_cases
report = EvalRunner(agent).run(load_cases("cases.jsonl"))
print(f"{report.passed}/{report.total} passed")
Regression detection against a saved baseline:
wardhook-eval run cases.jsonl --target myapp.agents:support_agent -o run.json
wardhook-eval compare run.json --baseline baseline.json # exits 1 on any regression
1 unchanged, 1 still_failing, 1 regressed
REGRESSED excess-storm -- contains: output is missing ['500']
1 regression(s).
wardhook-eval validate cases.jsonl checks a case file parses without running
anything — cheap enough for a pre-commit hook.
Criteria
Anything in a case's expect block. All of them are optional; a case with none
passes as long as the agent does not raise.
| Criterion | Argument | Passes when |
|---|---|---|
contains |
string or list | every string appears in the output (case-insensitive) |
not_contains |
string or list | none of them appear |
regex |
pattern or list | every pattern matches (case-sensitive) |
equals |
string | the output matches exactly, ignoring surrounding whitespace |
json_path |
{"a.0.b": value} |
each dotted path in the raw response holds that value |
tool_called |
name or list | every named tool was invoked |
blocked |
boolean | a guardrail did (or did not) stop the run |
max_latency_ms |
number | the run finished within the budget |
max_cost_usd |
number | the run cost no more than this, when a cost is known |
llm_judge |
rubric string | a model graded the output PASS |
Add your own without forking:
from wardhook.evals import CriterionResult, register_criterion
def cites_a_source(expected, outcome):
ok = bool(outcome.raw.get("citations"))
return CriterionResult("cites_a_source", ok == expected, "no citations returned")
register_criterion("cites_a_source", cites_a_source)
Design notes
- Zero runtime dependencies beyond the CLI framework. The runner targets
anything with an
.invoke()method, so it never needs to know what it is testing or which framework built it — a Wardhook agent, a raw LangGraph graph, or a plain function. Evenllm_judgeduck-types its model, so grading with an LLM does not drag in a model library. - Regression is a distinct outcome from failure. Cases are classified
fixed/regressed/still_failing/unchanged(plusaddedandremoved), because "this was already broken" and "your change broke this" call for different responses.comparefails only on the second. - A regression exits non-zero, so it drops straight into CI.
runexits non-zero on any failure; usecomparewhen the suite carries known debt. - A raising target fails its case, not the run. One broken case out of two hundred still leaves you a report naming it.
- Parse errors name the line. A five-hundred-case file with one bad line is normal; "Expecting ',' delimiter" with no location is not a help.
Note: a report records the agent's output by default, which is what makes a failure diagnosable. Pass
--no-output(orinclude_output=False) where run files must not carry real data. Baseline comparison only needs case ids and pass/fail, so a redacted report is still a valid baseline.
Links
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wardhook_evals-0.2.0.tar.gz.
File metadata
- Download URL: wardhook_evals-0.2.0.tar.gz
- Upload date:
- Size: 34.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0735a55f2f1b44d9012cac5c8995d22ea5d2a9b6178b7083c7733f8ba8978a6
|
|
| MD5 |
132e0cb958ac2eba6aa36b906744b3b9
|
|
| BLAKE2b-256 |
ad0103616296f7b35eca3455b76c8fcadf0d10ee1bb52b86f7e6b21a7ede1c36
|
Provenance
The following attestation bundles were made for wardhook_evals-0.2.0.tar.gz:
Publisher:
release.yml on justicebajaj161/wardhook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wardhook_evals-0.2.0.tar.gz -
Subject digest:
e0735a55f2f1b44d9012cac5c8995d22ea5d2a9b6178b7083c7733f8ba8978a6 - Sigstore transparency entry: 2622018710
- Sigstore integration time:
-
Permalink:
justicebajaj161/wardhook@2aeed8a669c6fcfcd1e4642a9e68e80a349280b9 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/justicebajaj161
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2aeed8a669c6fcfcd1e4642a9e68e80a349280b9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file wardhook_evals-0.2.0-py3-none-any.whl.
File metadata
- Download URL: wardhook_evals-0.2.0-py3-none-any.whl
- Upload date:
- Size: 27.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c622ea10520af5a00c45ce11c57eafa319084bf2009efce41acc727f4fa6fb84
|
|
| MD5 |
4bbbfbeda12de9b332d88606a62827e3
|
|
| BLAKE2b-256 |
5c67137e2297c583348650c59810d10d4e25c68d8785c90df7faacb0809665f7
|
Provenance
The following attestation bundles were made for wardhook_evals-0.2.0-py3-none-any.whl:
Publisher:
release.yml on justicebajaj161/wardhook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wardhook_evals-0.2.0-py3-none-any.whl -
Subject digest:
c622ea10520af5a00c45ce11c57eafa319084bf2009efce41acc727f4fa6fb84 - Sigstore transparency entry: 2622018725
- Sigstore integration time:
-
Permalink:
justicebajaj161/wardhook@2aeed8a669c6fcfcd1e4642a9e68e80a349280b9 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/justicebajaj161
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2aeed8a669c6fcfcd1e4642a9e68e80a349280b9 -
Trigger Event:
push
-
Statement type: