Skip to main content
AI Product Safety

Guardrails that do not break the product

Guardrails get added after an incident, tuned by whoever is most worried, and measured only on what they catch. The cost sits entirely on the other side of the ledger, where nobody is looking: real users blocked, real questions refused, and latency added to every request.

Every guardrail has two error rates, and teams measure one

A control that blocks bad output also blocks some good output, and the second number is almost never on the dashboard. It is invisible in a way the first is not: a harmful response that escapes becomes an incident with a name and a review, while a legitimate question wrongly refused becomes a user who quietly stops using the feature. One generates a meeting. The other generates churn nobody attributes to anything. So the incentives push in exactly one direction, and six months later the product has a reputation for being unhelpful and no one can point to the change that did it.

The arithmetic is worth doing once, because it is more brutal than intuition suggests. Suppose half a percent of your traffic is genuinely something you want to block. Your filter catches ninety-five percent of it, which sounds excellent, and it flags two percent of everything else, which sounds negligible. At a hundred thousand requests a day: five hundred are genuinely bad and you catch four hundred and seventy-five. The other ninety-nine thousand five hundred are fine, and you block one thousand nine hundred and ninety of them.

So of roughly two thousand four hundred and sixty-five blocked requests, fewer than one in five deserved it. Four out of five blocked users did nothing wrong, and every one of them saw a refusal. That is not a bad filter. Two percent false positives is a good filter. It is what a low base rate does to any classifier, and it is the reason a guardrail conversation that never mentions base rates is going to produce something users hate.

False positive rateLegitimate requests blocked per dayShare of blocks that were correctWhat users experience
2.0%1,99019%Four in five refusals are wrong. The feature feels broken
1.0%99532%Two in three refusals are wrong. Complaints are constant
0.5%49849%A coin flip. Tolerable only with an easy appeal path
0.1%10083%Mostly correct. This is the target for anything auto-blocking
0.02%2096%Achievable only for narrow, well-specified categories

Assumes 100,000 requests a day, a 0.5% genuine rate, and 95% recall throughout. Change the base rate and every number moves, which is the point: you cannot reason about a threshold without knowing how rare the thing you are catching actually is. Measure it first.

You are probably here because

  • Users say the assistant refuses ordinary requests, and you cannot reproduce it
  • A filter was added after an incident and nobody has revisited the threshold since
  • Safety checks doubled your latency and the product feels slow now
  • Someone asked what your false positive rate is and the honest answer was that nobody knows

The last one is the root of the other three. A control whose cost is unmeasured will always be tightened, because only one of its two error rates ever generates a complaint anyone can act on.

Name the risk before choosing a mechanism

"Guardrails" covers at least seven distinct concerns that get one budget line and one implementation. They have different frequencies, different consequences and different correct mechanisms, and merging them produces a filter that is simultaneously too strict for one and useless for another.

RiskMechanism that actually worksWhere it belongsWhat it costs
Harmful content generatedProvider-level safety plus a narrow output classifier for your domainOutput, before displayLatency; a real false positive rate
Sensitive data in the outputNever retrieve it: filter at retrieval by the caller’s permissionsRetrieval, before scoringAlmost none. Structural, not probabilistic
Injected instructions in contentCapability limits and validated destinations, not detectionTool designDesign effort once
Actions with consequencesPrepare-and-commit with a human-readable previewTool designOne extra call; a real UI
Claims not supported by sourcesProgrammatic check that every cited passage exists and contains the figureOutput, deterministicLow, and no false-positive problem
Out-of-scope questionsA cheap classifier with a soft response, not a blockInputTens of milliseconds
Statements you are not licensed to makeTemplate-constrained output for those categoriesGenerationLess fluency in a narrow set of answers

Look at the second column and notice how few of the good answers are classifiers. That is the central point of this piece.

The best guardrail is a capability the model does not have. A control that is structural has no false positive rate, no threshold to tune, and no incident where it was slightly off.

Put the control where it is structural, not probabilistic

A model cannot leak a document that was never retrieved. It cannot email an address that is not on the validated list. It cannot delete a record when the deletion tool was not in the list assembled for this caller. It cannot issue a refund without a prepared token that a person approved. None of those require a classifier, a threshold, or a review of borderline cases, and none of them fail on an input someone phrased cleverly.

Compare that to detecting the same risks in text. An output filter looking for leaked account numbers has to know every format an account number takes, including the ones in an attachment nobody thought about. A prompt injection detector is in an open-ended contest with an adversary who can rewrite the input indefinitely. These controls are worth having as a second layer and they are a poor first layer.

So the design order is: remove the capability, then constrain the interface, then check deterministically, then classify, and only then ask a model to judge. Every step down that list adds latency, adds a false positive rate, and adds a threshold someone has to own. Most systems we review have started at the bottom of the list because a classifier is the thing you can add in a day without touching the architecture.

The latency budget nobody wrote down

Controls are additive and they are usually added one at a time by different people. An input classifier, an output classifier, a moderation call, a citation checker, a second model reviewing the first. Each addition is defensible; the sum is a product that takes four seconds to answer a question it used to answer in one.

Rough orders of magnitude, so a design conversation can happen before the code exists. A small local classifier costs tens of milliseconds. A hosted moderation endpoint costs a network round trip, typically well under a couple of hundred milliseconds. A model-based check is a full generation — hundreds of milliseconds to seconds depending on the size of what it reads. A second model reviewing the whole output roughly doubles your total cost and latency, which is a real decision rather than a detail.

Run independent checks in parallel rather than in sequence, and run input checks concurrently with the beginning of generation rather than before it, cancelling generation if a check trips. That one change often recovers most of the added latency for a modest amount of wasted compute.

Streaming makes output checks genuinely hard, because a token you have sent cannot be recalled. Three workable options, each with an honest cost. Buffer a window of output and check on sentence boundaries, which adds a visible stutter but keeps the stream. Stream freely and retract in the interface if a check trips afterwards, which is fast and means a user may briefly see something you intended to block. Or do not stream the categories where the risk is real. Pick deliberately; the common outcome is that nobody picks and output checks are silently skipped in the streaming path while the dashboard still shows them enabled.

Design Note

Every block goes into a review queue, and somebody reads it

Log the input, the output if there was one, which control fired, and the score. Sample the queue weekly and label whether the block was correct. That gives you a measured false positive rate instead of an assumed one, and it is the only way a threshold conversation becomes a decision rather than an argument about temperament. Teams that do this typically discover their most aggressive control is firing mostly on legitimate traffic, and they find it in the first session.

Send us your controls and we will tell you what they are costing you.

Email the list of checks in your request path, where each sits, and a sample of blocked requests to contact@precisionfederal.com. You get back a short written note on which ones we would make structural, which thresholds look wrong for your base rate, and the latency we would recover. One business day. No charge, no meeting, no deck.

contact@precisionfederal.com

A refusal is a product surface, so design it

Most refusals are a dead end: a flat sentence, no explanation, no way forward. For the four in five users who were blocked wrongly, that is the whole experience of your product that day. It also generates support load, because the only remaining option is to ask a person.

Four things make a refusal survivable. Say what category of thing was declined, in plain words, without revealing the rule that fired — enough for a user to understand, not enough for someone to tune against it. Offer the nearest thing you can do, because a large share of refusals are near misses on scope. Give a route to a human, and make it one click. And keep a record the user can reference, so the conversation with support starts from a fact instead of a description.

Never expose the raw classifier output or the matched rule. It teaches evasion and it reads as an accusation. "I cannot help with account changes here — here is how to reach the team that can" is a better outcome on every axis than a score and a category name.

Thresholds are a product decision, and they are not one number

The same model serving an internal tool used by twelve trained analysts and a public feature open to anyone does not warrant the same threshold. Internally, the cost of a miss is low and the cost of a block is high, because the analyst is on deadline and will route around the tool permanently. Publicly, the calculation inverts.

So make thresholds configurable per surface, and where you serve multiple organizations, per tenant. Some customers will want stricter controls than your default and will say so in procurement; others will be furious at anything that slows their staff down. One global constant guarantees you are wrong for most of them.

Consider a middle state as well. Not everything has to be allow or block. A flagged response can be shown with a caution, routed for review before it is sent, or delivered with the sources placed more prominently. Binary controls on a continuous score throw away most of the information the score contains.

Test the controls like a feature, including what must not be blocked

Two sets, and the second is almost always missing. A set of inputs that must be blocked, which everybody builds. And a set of inputs that must not be blocked — ordinary, legitimate, slightly awkward requests drawn from real traffic, including the ones that sit near a boundary. That second set is what stops the ratchet, because without it every incident tightens the threshold and nothing ever loosens it.

Populate the must-not-block set from your review queue: every wrongly blocked request becomes a permanent test case. Report both numbers on every change, and treat a rise in false positives as a regression with the same weight as a miss. Then watch the behavioural signal in production, which is more honest than either: what share of users abandon the session after a refusal, and does that share move when a threshold moves? Users do not file tickets about over-blocking. They leave.

Where guardrail effort pays — our default weights

Structural limits: capabilities, permissions, validated destinations
28
Deterministic output checks with no threshold to tune
20
A measured false positive rate from a reviewed queue
18
Refusal design: reason, alternative, route to a person
14
Per-surface and per-tenant thresholds
11
Classifier quality itself
9

Weights sum to 100. Our starting allocation, not a measurement. The last row is where most teams spend first and it is the smallest lever on the list.

The failure that is invisible by construction

Worth stating on its own because it survives every review. Over-blocking produces no artifact. There is no error in the log, no alert, no incident report, no unhappy message in the channel. There is a user who asked a reasonable question, got told no, and formed a view about whether this tool is worth using. Multiply by months.

The only defenses are measurement and a standing counterweight. Measure the false positive rate on sampled real traffic and publish it beside the miss rate on the same dashboard, at the same size. Give someone explicit ownership of the cost of over-blocking, so the tightening conversation has two sides. Without that, the ratchet only turns one way, and every individual turn is justified.

A two-week pass over controls already in production

Guardrail Review

1
Inventory every check in the request path: what it protects, who owns it, what it costs in milliseconds
Days 1–2
2
Log all blocks with input and score; sample and label 200 by hand to get a real false positive rate
Days 3–5
3
Measure the base rate of the thing each control catches, then reset thresholds against it
Days 6–7
4
Replace the checks that can be structural: retrieval permissions, tool lists, validated destinations
Days 8–10
5
Parallelize what remains; decide the streaming policy explicitly and write it down
Days 11–12
6
Build the must-block and must-not-block sets; wire both into the release path
Days 13–14

Days three to five are the ones that change minds. A room that has been arguing about thresholds from instinct behaves very differently once it has read two hundred actual blocked requests, and the discovery is nearly always the same: the majority of them were fine.

The mistakes we are called in to fix

  • A threshold set during an incident and never revisited once the pressure lifted
  • No measured false positive rate, so every tightening is free and every loosening is a fight
  • Classifiers doing work a permission check should do, probabilistically and slowly
  • Five checks in sequence where four could run in parallel
  • Output checks silently skipped on the streaming path while the dashboard shows them on
  • Refusals with no reason, no alternative and no route to a person
  • The raw rule or score shown to the user, teaching evasion and reading as an accusation
  • One global threshold across an internal tool and a public product
  • No must-not-block test set, so the ratchet only turns one way

Before you ship a control

  • The risk is named specifically, not as "safety"
  • You checked whether it can be structural before reaching for a classifier
  • The base rate of the thing being caught has been measured, not assumed
  • Both error rates are on the dashboard, at the same size
  • Every block is logged and a sample is labelled by a person on a schedule
  • Independent checks run in parallel and the latency cost is written down
  • The streaming policy is an explicit decision, not an omission
  • Refusals name a category, offer an alternative and route to a human
  • Thresholds are configurable per surface and per tenant
  • A must-not-block set exists and gates releases alongside the must-block set
  • Someone owns the cost of over-blocking by name

Bottom line

Guardrails are an engineering trade-off, not a virtue, and the trade is invisible unless you measure both sides. Start by naming the specific risk. Prefer controls that make the bad outcome impossible over controls that try to recognize it, because structural limits have no threshold and no false positives. Measure the base rate before choosing a cut point, or the arithmetic will surprise you in a direction your users feel. Design the refusal, since for most of the people who see one it is wrong. Put both error rates on the same dashboard and give the second one an owner. A product that is safe and unusable has not managed risk; it has moved it somewhere nobody is counting.

Frequently asked questions

What false positive rate is acceptable for an AI guardrail?

It depends entirely on the base rate of what you are catching, which is why the number has to be measured rather than chosen. If half a percent of traffic is genuinely problematic, a two percent false positive rate means roughly four in five blocks are wrong. For anything that blocks automatically with no appeal, aim below about a tenth of a percent, and accept that this is only achievable for narrow, well-specified categories.

Where should guardrails sit — on the input, the output, or both?

Neither, first. The strongest controls are structural: filter retrieval by the caller’s permissions, assemble the tool list from real authorization, validate destinations against a list, and put consequential actions behind a prepare-and-commit step with a preview. Input and output classifiers are a useful second layer with a real cost, not a first line.

How do you check output when the response is streamed?

Pick one of three and say so in writing. Buffer a window and check on sentence boundaries, accepting a visible stutter. Stream freely and retract in the interface if a check trips, accepting that a user may briefly see the content. Or do not stream the categories where the risk is real. The common failure is making no decision, which leaves the check enabled on the dashboard and skipped in the code path most users hit.

How do you detect that a system is over-blocking?

Not from complaints — users who are refused generally leave rather than write in. Log every block, sample it weekly, and have a person label whether it was correct. Then watch session abandonment after a refusal as a behavioural signal, and turn every confirmed wrong block into a permanent test case in a must-not-block set that gates releases.

Can guardrails stop prompt injection?

Detection reduces the rate; it does not close the hole, because an attacker can rewrite the input indefinitely and you are guessing at intent in text. The controls that hold are the ones that limit consequences: capabilities the model does not have, recipients and destinations drawn from validated lists, and actions that require a prepared token a person approved. Treat labelling of untrusted content as hygiene and capability design as the actual control.

1 business day response

Do you know what your controls are costing you?

Send the list of checks in your request path and a sample of blocked requests. Our engineers will come back with which ones we would make structural, which thresholds look wrong for your base rate, and the latency we would recover. Email bo@precisionfederal.com.

Email an engineerCapabilitiesMore insights →
AI Product SafetyModel RiskEvaluationPlatform Engineering