Guardrails and Moderation for LLM Applications

LLMAI SafetyGuardrailsModeration

"Add guardrails" is the most vague ticket in AI engineering. Product wants brand-safe outputs. Security wants no PII in responses. Legal wants disclaimers on medical and financial answers. Engineering wants JSON that parses. Those are four different problems sharing one word.

A production guardrails stack is a pipeline of checks with explicit failure modes — block, rewrite, escalate to human, or fall back to a safe template. Not a single moderation API call you bolt on after the demo works.

The three checkpoints

User input → [Input guardrails] → LLM → [Output guardrails] → User
                              ↘ Tool args → [Action guardrails] → Execute
Checkpoint Catches Typical mechanisms
Input Jailbreaks, injection, abuse Classifiers, rate limits, blocklists
Output Policy violations, PII, bad JSON Schema validation, DLP, moderation
Action Dangerous tool calls Allowlists, argument validators

Skipping any leg leaves a hole. Input-only moderation does not stop the model from hallucinating a credit card number in the output. Output-only validation does not stop a user from injecting instructions that reach your tools.

Input moderation: fast filters first

Run cheap checks before you spend tokens:

  1. Rate limiting and abuse signals — per-user, per-IP, per-API key. Obvious, often forgotten.
  2. Blocklists and regex — internal hostnames, competitor slurs your legal team maintains, known jailbreak prefixes.
  3. Classifier models — OpenAI Moderation API, Azure AI Content Safety, Perspective API, or open models like Llama Guard 3.
from openai import OpenAI
client = OpenAI()

def check_input(text: str) -> tuple[bool, str]:
    result = client.moderations.create(input=text)
    cats = result.results[0].categories
    if cats.hate or cats.sexual or cats.violence:
        return False, "content_policy_violation"
    return True, "ok"

Classifiers return probabilities, not truth. Set thresholds per category and log borderline cases for human review. A support bot can tolerate higher false-positive rates than a children's app.

For agent systems, also scan retrieved context and tool outputs before the next turn — indirect injection lives there. The input guardrail scope must include anything entering the context window, not just the user's latest message. See prompt injection and agent security for harness patterns that complement moderation.

Output validation: trust but verify

The model finished generating. Now enforce contracts:

Structured output guardrails

If downstream code expects JSON, validate with JSON Schema before it touches business logic:

import jsonschema

ORDER_SCHEMA = {
    "type": "object",
    "required": ["sku", "quantity"],
    "properties": {
        "sku": {"type": "string", "pattern": "^[A-Z0-9-]{4,20}$"},
        "quantity": {"type": "integer", "minimum": 1, "maximum": 99},
    },
    "additionalProperties": False,
}

def validate_order(raw: str) -> dict:
    data = json.loads(raw)  # catch parse errors
    jsonschema.validate(data, ORDER_SCHEMA)
    return data

OpenAI structured outputs with strict: true, Gemini responseSchema, and Anthropic tool use reduce parse failures at the source — but still validate server-side. Models drift across versions.

Content policy on output

Run the same moderation classifiers on the assistant response before display. Add domain rules:

Repair vs refuse

When validation fails, pick a policy:

Failure User-facing behavior
JSON syntax One retry with repair prompt
Schema violation Retry once, then safe error
Moderation hit Refuse with generic message
PII detected Redact and show, or refuse

Infinite retry loops burn money and leak context. Cap at one repair attempt.

Frameworks: NeMo Guardrails and Guardrails AI

NVIDIA NeMo Guardrails models guardrails as a dialog flow — Colang scripts define allowed paths, fact-checking rails, and topical boundaries. Good when you need conversational policy expressed declaratively and want to iterate without redeploying Python.

Guardrails AI wraps validators (.validate()) around LLM calls with a hub of pre-built checks — ValidJSON, ProfanityFree, ToxicLanguage. Good for output validation in Python services with minimal boilerplate:

from guardrails import Guard
from guardrails.hub import ToxicLanguage, ValidJSON

guard = Guard().use_many(ToxicLanguage(), ValidJSON())
result = guard(llm_api, prompt=user_prompt)

Neither replaces deterministic checks. Use them to orchestrate validators, not as magic safety dust.

Where rules beat models

Models paraphrase; rules do not get tired:

On a robotics fleet dashboard, I blocked any tool argument containing rm -, DROP, or URLs outside our domain with a 0.2ms regex pass. No classifier required.

Moderation for multilingual and regional apps

Serving Cairo, Gulf, and European users from one stack means one global moderation model is insufficient. Arabic dialect, code-switching, and cultural context produce false positives on English-centric classifiers.

Mitigations:

Metrics that prove guardrails work

Track in production, not just in staging:

Metric Why
Block rate by category Detect drift or attacks
False positive reports User appeals, support tickets
Repair retry rate Model format health
PII catch rate DLP effectiveness
Time-to-detect new jailbreak Red team cadence

Run a monthly red-team pass against your stack. New jailbreaks spread on social media within days; your guardrails need a human update loop.

Minimum viable guardrails stack

For a B2B SaaS assistant shipping in weeks, not months:

  1. Input moderation API + rate limits
  2. Output moderation + PII regex
  3. JSON Schema validation on structured responses
  4. Tool allowlist with argument validation
  5. Logging and alerting on block spikes

Add Colang flows or custom classifiers when evals show systematic gaps — not before you have evals.

Guardrails are not a substitute for least-privilege architecture. They are the last line of defense when the model does something you did not intend. Build them as a pipeline, measure them like any other service, and prefer rules where rules suffice.

Resources

Frequently asked questions

What is the difference between moderation and guardrails in LLM apps?

Moderation typically classifies content as safe or unsafe — hate speech, sexual content, violence. Guardrails are broader: they enforce output format, block policy violations, prevent PII leakage, and constrain tool use. Moderation is one layer inside a guardrails stack.

Should guardrails run before or after the LLM call?

Both. Input guardrails filter or rewrite prompts before inference. Output guardrails validate responses before users or downstream systems see them. High-risk apps add a third check on tool arguments between planning and execution.

Are LLM-based guardrails reliable enough for production?

As a secondary check, yes. As the only control, no. Combine deterministic rules (regex, schema validation, allowlists) with classifier models. Rules catch known failures cheaply; models catch paraphrases and edge cases.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →