Skip to content

Guardrails

Rules of your own that refuse a request before it costs anything, or flag a response after.

6 min read

What a guardrail is

A rule you configure that inspects a request on its way in, or a response on its way out, and either blocks it or records that it fired. They are set up under Guardrails and evaluated on every request the account makes, API and playground alike.

A block returns 422 guardrail_blocked. Not 400: the request was well-formed and the model would have answered it — policy is what stopped it, and the caller needs to be able to tell those apart. The message names the rule, because the person who hits it is usually not the person who wrote it.

The six kinds

KindDescription
piiEmail addresses, payment card numbers, IBANs, US social security numbers and phone numbers in the prompt. Cards are Luhn-checked and IBANs are mod-97 checked, so an order id that happens to be 16 digits does not read as a card. There is deliberately no name, address or date-of-birth detection — those cannot be matched by pattern without refusing ordinary requests all day.
blocked_termsA list of terms you supply, matched case-insensitively anywhere in the prompt.
max_input_tokensRefuses prompts above a token ceiling, using the same estimate the balance check uses.
max_costRefuses a request whose worst-case cost exceeds a per-request cap. Same estimate again, on purpose — two ceilings asking the same question of two different numbers is how they end up disagreeing.
json_outputFlags a response that does not parse as JSON. A fenced ```json block counts as JSON: models wrap it constantly, and refusing that would fire on responses that are correct for every practical purpose.
output_regexFlags a response matching a pattern you do not want emitted.

Input stage and output stage

The first four run before the balance check and before any provider — the last point at which refusing a request is free. A block there costs nothing and nothing is sent anywhere.

An output-stage block is still billed
By the time a response can be inspected, the provider has generated it and billed us for it. So an output rule refuses to hand over the answer; it does not make it free. The error says so explicitly, and the request row records both the charge and the rule. The alternative would let anyone write a rule matching everything and take free inference.

On a stream, output rules are warn-only. The client is already reading; a rule can record a verdict but it cannot un-send text. That is a real difference in protection between streamed and non-streamed calls, and it is worth knowing before you rely on one.

What a verdict records

A rule that fires records its category and never the text that matched it — “payment card number, IBAN”, not the number. The whole point of the PII rule is that card numbers do not end up somewhere they can be read, and the verdict is written to the request row, shown in the dashboard and exported to CSV.

Blocked terms are the one exception, and only because the matched text is your own configured term: naming it is what makes the verdict actionable rather than a leak.

Two rules they all follow

  • A rule that is unsure does not fire. These refuse real requests from paying customers. A false positive is worse than a miss, because you cannot work around it and often cannot tell why.
  • They fail open. If the rules cannot be loaded, the request proceeds. A guardrail that cannot be read must not become a guardrail that silently refuses everything — these are your policy, not our authentication.

Something here disagrees with what the API actually did? That is a bug in this page, and worth reporting.

Report it