AI Features
Guardrails
A guardrail is a named, reusable safety policy made up of one or more checks. Each check runs a single validator against your request and/or the model’s response, and can block, redact, or just monitor. This page documents every validator in the catalogue and explains each parameter you can tune.
How a guardrail runs
There are two ways a guardrail reaches a request. Bind it to a virtual key and every request authenticated with that key runs it — the caller sends nothing. Or name it per request with the x-guardrail: <slug> header (e.g. gr-a3f9c1b2; a comma-separated list runs several in order). Either way it applies to /chat/completions, /v1/prompts/{slug}/completions, and /responses. All checks within a phase run in parallel, so the added latency is the slowest single check — not the sum.
The two combine as a union, and the key’s guardrails are a floor: a header can add guardrails to a request but can never drop or replace what the key binds. A caller holding the key cannot opt out of the policy it was issued under. Where several guardrails apply they run in order — key bindings first — and each one’s redactions are what the next one inspects.
- Input phase runs before the provider call on your request messages. A block here stops the request entirely (the provider is never called).
- Output phase runs after the provider responds, on the response text. A block suppresses the response.
- Disabled guardrails are skipped. If the guardrail’s enabled flag is off, every phase returns BYPASS and nothing runs — including on keys that bind it. The binding survives and resumes when you re-enable it.
- A guardrail bound to a key cannot be deleted until it is detached. Deleting it would drop enforcement from live traffic with no other signal, so the API returns 409 naming the keys.
- The outcome — merged across every guardrail that applied, most severe wins — is returned on the x-guardrail-status response header: PASS, BLOCK, REDACT, MONITOR, or BYPASS.
Target and action — set on every check
Two settings apply to every validator regardless of type. The target chooses which phase(s) the check runs in; the action chooses what happens when it fires.
| Target | Runs on |
|---|
| INPUT | The request messages, before the provider call. |
| OUTPUT | The model’s response, after it returns. |
| BOTH | Input and output, independently. |
| Action | Effect when the check fires |
|---|
| BLOCK | Reject with HTTP 422. Input blocks prevent the provider call; output blocks suppress the response. |
| REDACT | Replace the matched content with indexed placeholders (e.g. [EMAIL_1]) and continue. Only some validators can redact. |
| MONITOR | Log the violation but let the request and response through unchanged. Use this to measure impact before enforcing. |
Deterministic vs. AI validators
Every validator carries a kind badge in the builder:
- det Deterministic — pure in-process logic (regex, parsing, math). No model call, no token cost, sub-millisecond.
- AI LLM-judge — sends the text to a small platform-managed classifier model and acts on its verdict. Adds one model round-trip and token cost to each guarded request.
AI validators fail closed by default: if the judge errors or times out, the check fires its configured action (a BLOCK check returns 422). Override per check with on_error: open. AI validators also require a Pro or Enterprise plan.
The validator catalogue
Validators are grouped by category. Parameter names below link to the parameter reference further down, where each is explained in depth.
PII
| Validator | What it does | Parameters |
|---|
| PII_DETECTOR | Detects and optionally redacts personally identifiable information — emails, phone numbers, SSNs, credit-card numbers, IP addresses — using compiled regex patterns. (Names are intentionally excluded; they need an NER model.) | pii_types |
Security
| Validator | What it does | Parameters |
|---|
| secrets_present det | Detects leaked credentials and API keys by signature (OpenAI, Anthropic, AWS, GitHub, Google, Slack, Stripe, PEM private keys, JWTs), plus an opt-in high-entropy scan for unknown secrets. | providers, entropy_threshold, min_token_length |
| web_sanitization det | Flags HTML/JavaScript injection (XSS) signatures: script/iframe tags, javascript:/vbscript: URIs, inline event handlers, data:text/html, eval(). | — |
| exclude_sql_predicates det | Flags SQL-injection-style predicates: boolean tautologies (OR 1=1), UNION SELECT, stacked queries, comment breakouts, and time/file functions. | predicates |
| detect_jailbreak AI | Uses an LLM judge to flag attempts to bypass or override the model’s safety instructions (roleplay framing, “DAN”, “developer mode”). | threshold, on_error |
| prompt_injection AI | Uses an LLM judge to flag instructions aimed at the AI system rather than a genuine user request — attempts to override prior instructions, exfiltrate the system prompt, or smuggle commands via retrieved content. | threshold, on_error |
Content Safety
| Validator | What it does | Parameters |
|---|
| banned_words det | Blocks or redacts a configured list of disallowed terms. Exact word-boundary matching by default; optional fuzzy matching catches near-misses and simple obfuscation. | words, case_insensitive, fuzzy, max_distance |
| competitor_mention det | Same engine as banned words, for competitor names. | competitors, case_insensitive, fuzzy, max_distance |
| mentions_drugs det | Flags mentions of illicit drugs from a built-in term list, extendable with your own terms. | gazetteer |
| toxic_language AI | LLM judge for toxic, hateful, harassing, or abusive language. | threshold, on_error |
| nsfw_text AI | LLM judge for sexually explicit / not-safe-for-work content. | threshold, on_error |
| restrict_to_topic AI | LLM judge that flags content falling outside a configured set of allowed topics. | allowed_topics, threshold, on_error |
Format
| Validator | What it does | Parameters |
|---|
| JSON_SCHEMA_VALIDATOR | Validates that the response is valid JSON conforming to a Draft-07 schema (top-level type + required fields). Output phase only. | schema |
| valid_choices | Passes only when the text exactly matches one of the allowed values. | choices, case_insensitive |
| valid_range | Passes when the text is a number within min/max bounds. | min, max |
| valid_length | Passes when the character length is within min/max bounds. | min, max |
| lowercase / uppercase | Passes only when the text is entirely lower- / upper-case. | — |
| one_line | Passes only when the text is a single line. | — |
| two_words | Passes only when the text is exactly two words. | — |
| ends_with | Passes only when the text ends with a configured suffix. | suffix, case_insensitive |
| has_url | Requires the text to contain a URL — or, in forbid mode, to contain none. | mode |
| valid_url | Passes only when the text is a single valid http(s) URL. | — |
| valid_html | Passes unless the text contains malformed HTML (jsoup parse errors). | — |
Code
| Validator | What it does | Parameters |
|---|
| valid_sql det | Validates that the response parses as SQL (parse-only, never executed). Output phase; BLOCK/MONITOR only. | strip_markdown |
Quality
| Validator | What it does | Parameters |
|---|
| reading_level | Passes when the Flesch–Kincaid grade level is at or below a max grade. | max_grade |
| reading_time | Passes when the estimated reading time is at or below a maximum. | max_seconds, wpm |
| redundant_sentences | Flags text that repeats the same sentence verbatim. | — |
Custom
| Validator | What it does | Parameters |
|---|
| REGEX_MATCH | Evaluates your own regular expressions against the content. | patterns, case_insensitive |
| contains_string | Flags or redacts occurrences of a substring anywhere in the text. | substring, case_insensitive |
| quotes_price | Flags or redacts text that quotes a monetary price. | — |
Parameter reference
Most checks work the moment you add them. Some take settings that tune how strict or broad they are. Below, every setting is listed with what it does in plain language, the values it accepts, and its default. Settings marked * are required.
Settings you’ll see on several checks
These appear on more than one validator and mean the same thing everywhere.
| Setting | What it does | Accepted values | Default |
|---|
| case_insensitive | Ignore capitalization when matching, so “Spam” and “spam” count as the same. | true or false | true for term lists, otherwise false |
| fuzzy | Also catch near-misses and typos, not just exact matches. | true or false | false |
| max_distance | Only with fuzzy on: how different a word can be and still count as a match. | a whole number, usually 1–2 | 1 |
| threshold | AI checks only: how confident the AI must be before a flag it raised actually fires. | a decimal above 0.0 and up to 1.0 | unset (use the AI’s yes/no) |
| on_error | AI checks only: what to do if the AI judge is unavailable. | open or closed | closed |
What “max_distance” means. It counts how many single-letter edits — adding, removing, or changing one character — separate a word in the text from a word on your list. A distance of 1 catches things like “spamm” (one extra letter) or “sp4m” (one swapped letter). A distance of 2 is looser and can start matching unrelated words, so leave it at 1 unless you need to catch heavier disguising.
What “threshold” means. When an AI check flags something it also returns a score from 0 to 1 for how strongly the content breaks the rule. The threshold is a confidence gate on that flag: set it high (e.g. 0.9) to act only on the clearest cases — fewer false alarms; leave it unset to act on every flag. It only ever holds a flag back, so it can never block content the AI decided was fine — raising or lowering it will not turn a passing request into a blocked one. Unlike entropy_threshold, a threshold of 0 is not “off” — leave the field empty instead; 0 is rejected when you save.
The direction catches people out: a higher threshold is more lenient, not stricter. 0.9 looks like “high security” but means “only act on the most blatant cases”. It is a sensitivity dial, not a strictness dial:
| threshold | what fires |
|---|
| unset | Every flag the AI raises fires — strictest |
| 0.1 | Nearly every flag fires — very strict |
| 0.5 | Middling violations and above |
| 0.9 | Only blatant violations fire — most lenient |
| 1 | Effectively only certainties — maximally lenient |
| 0 | Rejected when you save (it is not “off”) |
What “on_error” means. closed (the default) treats an AI outage as a violation — a blocking check still blocks, keeping you safe even when the judge is down. open lets the request through (recorded as monitor-only) so a judge problem never interrupts traffic. Pick closed for safety-critical checks, open where uptime matters most.
Security
secrets_presentdet
| Parameter | What it controls | Accepted values | Default |
|---|
| providers | Which known secret types to look for. Narrow this when you only care about specific vendors. | any of: openai, anthropic, aws, github, google, slack, stripe, private_key, jwt (a list) | all of them |
| entropy_threshold | Turns on the extra "random-looking secret" scan that catches keys with no known format, and sets how strict it is. | a decimal; 0 = off; 4.0–4.5 typical | 0 (off) |
| min_token_length | The shortest run of characters the random-secret scan will inspect — keeps it from flagging short, ordinary words. | a whole number | 20 |
What “entropy” is. Entropy is a measure of randomness. Ordinary writing is predictable and scores low; a real secret like a8Xv2… is unpredictable and scores high. The random-secret scan flags any long, random-looking string at or above your entropy_threshold. It is off by default — turn it on (try 4.0) to catch secrets that don’t match a known vendor format.
exclude_sql_predicatesdet
| Parameter | What it controls | Accepted values | Default |
|---|
| predicates | Extra phrases to block, on top of the built-in SQL-injection patterns (which are always on). | a list of text phrases | none extra |
detect_jailbreak and prompt_injection are AI checks — they use the shared threshold and on_error settings above and need no other configuration.
Content Safety
banned_wordsdet
| Parameter | What it controls | Accepted values | Default |
|---|
| words * | The terms to block. | a list of words or phrases | — |
| case_insensitive | Ignore capitalization. | true / false | true |
| fuzzy | Also catch near-misses and typos. | true / false | false |
| max_distance | With fuzzy on, how different a word can be and still match. | a whole number (1–2) | 1 |
competitor_mentiondet
| Parameter | What it controls | Accepted values | Default |
|---|
| competitors * | The competitor names to block. | a list of names | — |
| case_insensitive | Ignore capitalization. | true / false | true |
| fuzzy | Also catch near-misses and typos. | true / false | false |
| max_distance | With fuzzy on, how different a word can be and still match. | a whole number (1–2) | 1 |
mentions_drugsdet
| Parameter | What it controls | Accepted values | Default |
|---|
| gazetteer | Extra drug terms to detect, added to the built-in list. | a list of words | none extra (built-in list always on) |
restrict_to_topicAI
| Parameter | What it controls | Accepted values | Default |
|---|
| allowed_topics * | The topics the content must stay within. Anything off-topic is flagged. | a list of topic names | none = no restriction |
| threshold | How confident the AI must be (see shared settings). | above 0.0, up to 1.0 | unset |
| on_error | What to do if the AI judge is unavailable. | open / closed | closed |
toxic_language and nsfw_text are AI checks — they use the shared threshold and on_error settings and need no other configuration.
PII
PII_DETECTOR
| Parameter | What it controls | Accepted values | Default |
|---|
| pii_types | Which kinds of personal information to look for. | any of: EMAIL, PHONE, SSN, CREDIT_CARD, IP_ADDRESS | all of them |
Format
valid_choices
| Parameter | What it controls | Accepted values | Default |
|---|
| choices * | The exact set of allowed values; the text must equal one of them. | a list of values | — |
| case_insensitive | Ignore capitalization when comparing. | true / false | false |
valid_range
| Parameter | What it controls | Accepted values | Default |
|---|
| min | Lowest number allowed. | a number | no lower limit |
| max | Highest number allowed. | a number | no upper limit |
valid_length
| Parameter | What it controls | Accepted values | Default |
|---|
| min | Shortest allowed length, in characters. | a whole number | no minimum |
| max | Longest allowed length, in characters. | a whole number | no maximum |
ends_with
| Parameter | What it controls | Accepted values | Default |
|---|
| suffix * | The text the content must end with. | any text (e.g. .) | — |
| case_insensitive | Ignore capitalization. | true / false | false |
has_url
| Parameter | What it controls | Accepted values | Default |
|---|
| mode | Whether a URL is required or forbidden. | require (must contain one) or forbid (must not) | require |
JSON_SCHEMA_VALIDATOR
| Parameter | What it controls | Accepted values | Default |
|---|
| schema | The JSON shape the response must match. Leave empty to just require valid JSON. | a JSON Schema object (Draft-07) | none (any valid JSON passes) |
Code
valid_sqldet
| Parameter | What it controls | Accepted values | Default |
|---|
| strip_markdown | Pull the SQL out of a ```sql code block before checking it. | true / false | true |
Quality
reading_level
| Parameter | What it controls | Accepted values | Default |
|---|
| max_grade | The hardest reading level allowed. The check fails when the text reads harder than this. | a number (US school grade) | 8 |
Reading-level scale (US grade). Roughly: 5 ≈ very simple, 8 ≈ plain everyday English, 12 ≈ high-school, 16+ ≈ academic/technical. Set max_grade to the highest level your audience should have to read comfortably.
reading_time
| Parameter | What it controls | Accepted values | Default |
|---|
| max_seconds * | The longest the response should take to read. | a number of seconds | — |
| wpm | Assumed reading speed used for the estimate. | a number (words per minute) | 200 |
Custom
REGEX_MATCH
| Parameter | What it controls | Accepted values | Default |
|---|
| patterns * | The patterns to search for. A match triggers the action. | a list of regular expressions | — |
| case_insensitive | Ignore capitalization. | true / false | false |
contains_string
| Parameter | What it controls | Accepted values | Default |
|---|
| substring * | The text to look for, anywhere in the content. | any text | — |
| case_insensitive | Ignore capitalization. | true / false | false |
Checks with no settings
These work the moment you add them — just choose a target and action: web_sanitization, valid_url, valid_html, lowercase, uppercase, one_line, two_words, redundant_sentences, and quotes_price.
Setting one up: create a guardrail under
Guardrails, add checks from the catalogue, set each check’s target and action, then either bind it to a
virtual key so every request with that key enforces it, or name it per request with
x-guardrail: <slug>.