Quick Start
1
Automatic (recommended)
Run an
EvalSuite — the fingerprint is stamped onto the result. Compare two suite results with assert_comparable.2
Manual
Compute a fingerprint yourself when you are not using
EvalSuite.3
Diagnose a mismatch
Use
fingerprint_parts to see exactly what changed.How It Works
EvalSuite.run() reads model, prompt, and tools from each evaluator’s agent and stamps the fingerprint onto the result at the start of the run.
Reading is best-effort — anything unreadable is left out rather than raised, so the fingerprint is never the reason an evaluation fails to run. If nothing can be read, fingerprint is "".
What Goes Into a Fingerprint
Each input is reduced to a stable shape before hashing.Deliberately excluded
- Timestamps, run ids, sample order, latency. Anything that varies run to run without changing what a score means is left out. A fingerprint that changed every run would refuse every comparison and be switched off.
- Tool order. A reordered tool list is the same setup. A guard that changed on reordering would refuse valid comparisons.
- The prompt text itself. Hashed, never stored, so fingerprints can safely land in shared result files.
Public API
Missing fingerprints are unknown, not equal.
compare_fingerprints("", "") returns False, and assert_comparable("", "") raises FingerprintMismatch. Assuming legacy unstamped runs are equal would let every old baseline silently pass the check — the guard refuses instead.Prompts are hashed, never stored. A fingerprint is written to result files and shared, so the full prompt text is never included.
Common Patterns
Gate CI on a stable baseline
Saveresult.fingerprint alongside the score, then guard before comparing numbers on the next run.
Persist fingerprints with results
result.summary already includes the fingerprint — write it to disk with the score.
Compare setups on purpose
When A/B’ing prompts, skipassert_comparable and record both fingerprints so the difference is visible in the graph.
Best Practices
Always call assert_comparable before charting deltas
Always call assert_comparable before charting deltas
A silent side-by-side of two different setups is the failure this guards against. Guard first, then subtract scores.
Bump FINGERPRINT_VERSION only when the recipe changes
Bump FINGERPRINT_VERSION only when the recipe changes
Old fingerprints will not compare equal to new ones after a bump — that is intentional, so scores from a changed recipe are never treated as comparable to older runs.
Use extra= for anything setup-affecting that isn't model/prompt/tool/evaluator
Use extra= for anything setup-affecting that isn't model/prompt/tool/evaluator
Temperature, seed, retrieval index name — pass them through
extra= so they become part of the fingerprint.Never wrap the fingerprint in try/except and swallow
Never wrap the fingerprint in try/except and swallow
The fingerprint code already fails silently at compute time (best-effort). Failing loud at compare time is deliberate — if two runs are not comparable, that is real.
Related
Evaluation Suite
Run every evaluator as one CI gate
Harness Evaluator
Score test-harness traces
Loop Evaluator
Score loop health and convergence
EvalPort Adapter
Export and import suites in the EvalPort open spec

