21 · Guardrails & safety
A model call sits between an untrusted input and a user who will trust the output. Input guards redact PII and refuse banned topics; output guards validate the schema and refuse ungrounded answers.
Guardrails are deterministic checks wrapped around the model call. Input guards redact PII/secrets and refuse banned topics before the prompt is sent; output guards validate the response against a schema and refuse answers the context doesn't support. They run as plain code — fast, auditable, and independent of the model.
Without this:
Without guardrails you leak customer emails into prompts and logs, answer questions you legally can't, and hand the user free-form text where your code expects strict JSON.
The model is the least trustworthy component in your stack: its input comes from a stranger and its output goes to someone who will believe it. Guardrails are the deterministic code you wrap around the model to make that safe. They split into two families:
Input guards (run before the call):
- PII / secret redaction — strip emails, phone numbers, API keys, credit-card numbers from the user's text before it enters the prompt and your logs. Replace each with a placeholder like
[EMAIL]so the model still sees the structure. - Banned-topic refusal — if the request matches a denylist (violence, medical/legal advice you're not licensed for, prompt-injection attempts), refuse without calling the model at all.
Output guards (run after the call):
- Schema validation — if you asked for JSON with specific keys, parse it and verify the shape. Reject or retry on malformed output instead of crashing downstream.
- Grounding gate — refuse to show an answer whose groundedness (lesson 20) is below a threshold; better to say "I don't know" than to emit a confident hallucination.
The key property: guardrails are plain deterministic code (regex, JSON parsing, set membership). They are fast, testable, and don't depend on the model behaving — exactly what you want on a safety boundary.
Here is a compact guardrail pipeline. The input guard redacts emails, phone numbers, and API-key-like strings with regex, then checks a banned-keyword denylist (refusing outright if it matches). The output guard validates that the model's reply is JSON of the allowed shape. We run it on three inputs — a clean one, one carrying PII, and one on a banned topic — and print exactly what each guard decided.
Python (in browser)
Input 1 passes clean, input 2 is allowed but redacted (PII never reaches the model), input 3 is refused before any model call; the output guard rejects malformed JSON.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Libraries like Guardrails-AI and NeMo Guardrails let you declare validators (PII, toxicity, JSON schema) and wire them around the call — the same checks our hand-coded pipeline runs.
A user message contains a banned keyword AND an email address. What should the guardrail pipeline do?
- Guardrails are deterministic code around the model: input guards (redact PII, refuse banned topics) and output guards (schema validation, grounding gate).
- Redact PII/secrets before they enter the prompt or logs, and refuse banned topics before spending a model call.
- Validate the output against a strict schema and refuse ungrounded answers — never hand downstream code free-form text it can't trust.
Every production LLM endpoint has input/output guards: PII scrubbers, moderation classifiers, JSON-schema validators, and grounding thresholds, often via Guardrails-AI or NeMo Guardrails.
If you remove it: Without guardrails you leak PII, answer prohibited or injected requests, and crash on malformed model output — the failures that turn a demo into an incident.