How to Test an AI Guardrail Before Deploying It
Abhishek N
Co-founder, Zespan · Building agent observability for production AI teams. Previously ML infrastructure at scale.
Most teams running AI agents in production have far fewer guardrails than they need, and it's usually not because they don't know what could go wrong. It's because shipping a rule blind is a real risk in the other direction: a guardrail tuned too aggressively can block legitimate customer requests, and that failure mode is loud, immediate, and easy to blame on the rule you just shipped. So teams write the two or three rules they're most confident about and leave the rest as things they mean to get to.
The way out of that trade-off isn't writing rules more carefully by hand. It's testing them against reality before they can do any damage.
The problem with shipping a guardrail blind
A rule written in isolation is a hypothesis: "any response matching this pattern is a policy violation." Whether that hypothesis is actually true, and how often it's wrong in either direction, is unknown until it runs against real traffic. Ship it straight to enforcement and you find out two things at the same time, in production, with real customers: whether it catches what you wanted, and whether it also catches things you didn't mean to block.
The second failure is the one that makes teams guardrail-shy. A rule that's slightly too broad doesn't fail loudly the way a missing rule does — a missed violation just looks like the status quo. A rule that wrongly blocks a legitimate refund request generates an immediate, visible complaint, and it's directly attributable to a change you just made. Teams that have been burned by this once tend to respond by writing far fewer rules, which means far more of the failures covered in how to know when an AI agent is wrong in production go uncaught.
What backtesting a guardrail actually means
Instead of writing a rule and turning it on, replay it against conversations you've already served — real production traffic, not synthetic test cases you wrote to confirm your own assumption. This produces exactly the two numbers you need before trusting a rule with live traffic:
$ zespan policy test --against last:7d
refund_over_policy_limit caught 47 wrongly blocked 2
personal_data_in_reply caught 118 wrongly blocked 0
medical_advice_boundary caught 6 wrongly blocked 31
medical_advice_boundary: needs work before shipping
refund_over_policy_limit caught 47 real violations against 2 requests it would have wrongly flagged — a rule that's clearly ready. medical_advice_boundary caught only 6 real violations while wrongly blocking 31 legitimate requests — a rule that looked reasonable when it was written and is, in practice, far too broad. Without backtesting, you'd only learn this the second way, after both numbers were live customer impact instead of a test result.
This is the same distinction that matters in the underlying detection step, covered in how to know when an AI agent is wrong in production: checking a rule's real catch rate, not assuming it, is what turns a guess into something you can trust.
What good backtest results actually look like
A rule that's ready to enforce should show a catch count that reflects a real, recurring problem (not one or two coincidental matches) and a wrongly-blocked count low enough that the false-positive rate is acceptable for your business — what's acceptable varies by how costly a wrong block is versus a missed catch, and that's a judgment call the numbers inform rather than replace. A rule with a high catch count and a near-zero false-positive rate, like personal_data_in_reply above, is close to as good as backtesting gets. A rule with a low catch count and a high false-positive rate almost never means "this problem barely exists." It usually means the rule is defined too broadly and is matching on the wrong signal.
Critically, backtesting should show you the real conversation behind each result, not just the aggregate count. Seeing the actual transcript that a rule would have caught, and the actual transcript it would have wrongly blocked, is what lets you tell whether the rule needs a narrower condition or is genuinely ready.
Staged rollout: dry run, warn, block
Even a rule with good backtest numbers shouldn't jump straight to blocking live traffic. The standard progression:
- Dry run — the rule evaluates every request and logs what it would have done, with zero effect on production. This is effectively backtesting continued forward into live traffic, catching drift the historical backtest couldn't have seen.
- Warn — the rule surfaces a flag on matching requests without blocking them, giving you a chance to review real-time matches before enforcement has any customer-facing effect.
- Block — the rule actually enforces: blocking, redacting, or holding the response, per what the rule is configured to do.
A rule should only reach block once its dry-run and warn-stage behavior confirms what the backtest predicted. Rules live as code in your own repository and are reviewed in pull requests the same way any other change to production behavior would be, which is what makes this staged movement auditable rather than a one-time judgment call.
Where this fits in the loop
Backtesting is the step between catching a failure and trusting a rule to stop it — the connective step in how to stop an AI agent from making the same mistake twice. And because the rule has to actually run somewhere once it's enforcing, without adding latency to every request, the enforcement side of this is covered in why guardrails need to run without added latency.
In Zespan, this is Policy-as-Code: guardrails that compile into a bundle your SDK evaluates in-process, backtested against your own traffic with zespan policy test before they can enforce anything. Backtesting and enforcement are available from the Pro plan; the Solo plan supports authoring and enforcing pre-built and custom guardrails without the historical backtest step. See pricing for the full breakdown.
The takeaway
The reason most teams under-guardrail their agents isn't a lack of ideas about what could go wrong. It's that shipping a rule without knowing its real-world catch rate and false-positive rate is a bet, and a bad bet is worse than no rule at all. Backtesting turns that bet into a measurement: two numbers, from your own traffic, before a single real customer is affected by a rule you haven't verified yet.
Start free — 50K traces/month, no card needed
See every agent decision, tool call, and handoff in production. Setup takes a few minutes.
Start free →