Skip to content

Guardrails

GatewAI can scan for PII and secrets both on the way in (the request, before it reaches the backend) and on the way out (the model’s response, before it returns to the client — output DLP). Guardrails run on the sync LLM-proxy path (POST /v1/*) and are configured per service.

Guardrails are enabled on a service by declaring a non-empty checks list:

services:
- type: llm
model: "chat-smart"
provider: passthrough
guardrails:
checks: [pii, secrets] # which detector groups to run
action: block # block (default) | redact | flag

Guardrails are opt-in per service — omit the guardrails block (or leave checks empty) to disable them. There is no global toggle.

The top-level checks/action are the input stage (scans the request). Add an optional output block to also scan the model’s response (output DLP):

guardrails:
checks: [pii, secrets] # input stage — the request
action: redact
output: # output stage — the response (optional)
checks: [pii, secrets]
action: redact # block | redact | flag

Output actions mirror input but operate on choices[*].message.content: redact masks matches before the response is returned (and the redacted body is what gets cached), block returns 422 {"error":"response blocked by guardrails"}, flag logs only.

ActionBehaviour
block (default)Reject the request with 422 Unprocessable Entity; the backend is never called.
redactReplace each match in-place with a placeholder (e.g. [REDACTED_EMAIL]) and forward the cleaned body.
flagForward the request unchanged; only emit a log line and a metric.

checks selects which detector groups run. Country groups are strictly opt-in.

GroupDetects
piiemail, credit card, IBAN, IPv4 address, international (E.164) phone
pii_frFrench phone, NIR (social security), SIREN, SIRET
pii_usUS Social Security Number
pii_ukUK National Insurance Number
pii_esSpanish DNI / NIF
pii_itItalian Codice Fiscale
secretsAWS access keys, private-key blocks, JWTs, GitHub / Slack / Google tokens

The scanner reads the messages array of the OpenAI-compatible JSON body and inspects all text content:

  • messages[*].content as a string (standard chat payload)
  • messages[*].content[*].text as content parts (multimodal payloads)

For redact, matches are replaced inside that content and the body is re-serialised as valid JSON; all other fields are preserved. Placeholders are not re-matched, so redaction is idempotent.

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{"error": "guardrails violation: email, aws_access_key"}
gatewai_guardrails_total{service_type, model, stage, action, result} # stage = input | output; result = blocked | redacted | flagged
gatewai_guardrails_pii_blocked_total{service_type, model} # retained for continuity (block only)
gatewai_guardrails_evaluations_total{service_type, model, stage} # every evaluation, regardless of outcome — denominator for a hit rate