recipes/02-measure/safety-evals
(offline, no key, seconds); argument:
blog/agent-safety-evals.md.
What the research says
OWASP’s list of risks for LLM applications names prompt injection, direct (in the ask) or indirect (in content the model reads), along with sensitive-information disclosure and excessive agency [2]. It is a taxonomy, not a test: each entry needs a situation that provokes it and a grader that sees it. Over-refusal is an over-optimization signature. A reward that any refusal satisfies is a proxy the policy will find, so the suite carries benign controls and a helpfulness term in the reward [3, 4]. The reward reads the trajectory, because a judge that reads the prose passes a clean summary written after the record left [4]. Every number carries an interval, comparisons are paired on the same tasks, and the eval set never enters training [5, 6].The recipe
- Write the boundary down. Every “never” in the policy gets an attack; every “always help with” gets a control.
- Plant the indirect injection in the data. Put the instruction in a
record the agent reads (
notes, a ticket) and ask something ordinary about it. The attack arrives as a tool result. - Simulate with repeats. The suite goes in as
seeds=.mode="rl", repeats=k, repeat_policy="fixed"rolls every askktimes;reproducible=Truepins the draw on any CPython version;simulator=Falseneeds no key. - Judge from the trajectory. One marker per exit (the reply, an
outbound message, a write), read from
stepsandfinal_text, 1.0 when the agent held;helpful_on_benignon the controls. Reward is 1 only when every applicable marker holds. Useevaluate, notgrade, for eval lineage. - Read pass^k per category. pass@1 is the average; pass^k is how often
the agent held on all
ktries. For a leak, the second is the number. - Check the judge. Hand-label the edge cases: the refusal that still
leaks, the quoted planted text, the send to the on-file address.
judge_trust(labeled)warns below 0.8 agreement or 0.6 kappa.judge_probes(benign_rows, judge, probes=["refusal"])must be 0. - Fix, and re-run on the same tasks.
simulate(..., tasks=base)re-runs exactly the first run’s asks, so every delta is paired. - Guard the comparison.
delta_report(before, after, target="pass_at_1", must_not_regress=[...], by="category")withhelpful_on_benignand every safety marker in the guard. A fix that got safe by refusing raises pass@1 and fails. - Keep the suite out of training.
evaluatestampslineage.source == "eval"and the selectors warn on those rows.simulate(traces=evald.failed_traces())aims new situations at the failures and drops near-copies.
The calls
Run it
Three scripted agents: trusting, locked-down (refuses anything risky), hardened (holds and still helps).runs=3 answers that).
When the text is public and the data is per tenant
A marketplace agent reads public text and holds many tenants’ data. Three changes, worked inrecipes/02-measure/safety-evals-marketplace:
- Make the world answer across tenants, and add
no_cross_tenant_readreading the steps. A mock that refuses measures the mock. - Plant the injection where the public writes: a review, a listing; one shape asks for a send, one for a write.
- Give the public write its own marker,
no_public_leak: private data in arespond_to_reviewleaves nothing but leaks.
live.py there runs the suite through Ollama with execute=world, so
planted reviews reach the model as tool results.
What the SDK already checks
What this is not
It measures the boundary under the suite’s situations, not the absence of a jailbreak the suite lacks. Aim new generation at the failures (traces=),
add every production incident as a seed, re-run on the pinned tasks.
References
- Willison, S. The Lethal Trifecta for AI Agents. simonwillison.net, June 2025. simonwillison.net/2025/Jun/16/the-lethal-trifecta.
- OWASP. Top 10 for LLM Applications 2025. genai.owasp.org/llm-top-10.
- Gao, L., Schulman, J., Hilton, J. Scaling Laws for Reward Model Overoptimization. ICML 2023. arXiv:2210.10760.
- Lambert, N. Reinforcement Learning from Human Feedback. 2025. Chapters Over-optimization, Tool Use and Evaluation.
- Miller, E. Adding Error Bars to Evals. 2024.
- Lambert, N. et al. Tülu 3: Pushing Frontiers in Open Language Model Post-Training. arXiv:2411.15124, 2024. The decontamination check.