By now you've built LLM applications and RAG pipelines, so you know how to get a model to answer well. This week we tackle a different problem: how do you stop a model from doing something you don't want — wandering off-topic, discussing a banned subject, leaking a secret, or producing an unsafe response — without retraining it? The answer is a guardrails framework: a separate, programmable layer that sits in the request path, inspecting, blocking, rewriting, or escalating traffic at runtime. This is the single most important idea this week, so let's say it plainly: a guardrails framework is not part of the model, and it does not replace the model's safety training. It's closer to a firewall or an API gateway than to a fine-tuning run. It complements model-level alignment and least-privilege architecture; it never substitutes for either.
NVIDIA's NeMo Guardrails (Apache-2.0, pip install nemo-guardrails, Python 3.10–3.13) is built around the idea that conversations are multi-turn, stateful things, and that safety often depends on where you are in the conversation, not just the text of a single message. NeMo organizes protections into five rail types:
| Rail type | What it guards | Example use |
|---|---|---|
| Input | The user's incoming message | Detect jailbreak attempts before they reach the LLM |
| Dialog | The flow of the conversation | Keep the bot on-topic; enforce a canonical conversation shape |
| Retrieval | Content pulled from a RAG store | Filter retrieved chunks before they're injected into the prompt |
| Output | The model's generated response | Self-check the answer before it's returned to the user |
| Execution | Tool/function calls the model triggers | Gate which tools can run and with what arguments |
Rails are defined declaratively using Colang, a small domain-specific language purpose-built for describing dialog flows — things like "if the user asks about off_topic, respond with the refusal message" or "if the bot's draft response matches unsafe_response, block it and try again." Colang's job is to let you express topical and dialog-flow policies without hand-rolling a state machine in Python. As of v0.23.0, NeMo also added lightweight Hugging Face classifier rails (fast local models that flag things like toxicity without an extra network call) and Polygraf-based PII masking, so you can scrub personal data before it ever reaches the LLM or before it leaves in the response. Here's the part that trips people up, and it's our first misconception to correct directly: NeMo's topic and intent matching is not deterministic. Under the hood, it generates a "canonical form" of the user's utterance and compares it against known intents using vector similarity — a probabilistic judgment call, not a hard-coded rule. That means it can be wrong, and it can be gamed. In testing, multi-turn cipher attacks — where an attacker spreads a malicious request across several turns, or encodes it so it doesn't match known bad patterns — reportedly defeated NeMo's rails more than 50% of the time. So: guardrails reduce risk; they do not guarantee safety. Treat every rail as a probabilistic filter with a false-negative rate, not a lock.
LLM Guard (Protect AI, MIT-licensed, pip install llm-guard) takes a different architectural bet. Instead of modeling conversation flow, it gives you a library of roughly 15 input scanners and 20+ output scanners — independent checks you compose in a pipeline. Each scanner does one job: detect prompt injection, redact PII, catch toxic language, enforce a ban-topics list, find leaked secrets (API keys, credentials) in a response, and more. There's no Colang, no canonical-form matching, no notion of "where are we in the conversation." You call scan_prompt() on the way in and scan_output() on the way out, and each scanner returns a pass/fail plus a risk score. This makes LLM Guard the better fit when what you need is stateless, composable I/O scanning — you don't want to model dialog flow, you just want a checklist of independent filters applied to every request and response. NeMo is the better fit when you need topical/dialog control — keeping a bot inside a defined conversational lane across multiple turns. Many production systems in fact use both: LLM Guard as a fast first-pass scanner layer, NeMo for anything requiring genuine conversation-state awareness.
Every rail or scanner you add sits on the critical path of a request, so it adds latency (an extra classifier call, an extra LLM call for self-checking) and cost (compute, and sometimes a second model invocation). This is a real engineering tradeoff, not a free lunch — which is our second misconception to name directly: installing a guardrails framework does not mean your system is now deterministically safe. It means you've added a filter with its own error rates and its own performance budget. You also must explicitly decide: if a rail check fails, times out, or errors — does the system fail open (let the request through) or fail closed (block it)? Neither is a framework default you can take for granted; NVIDIA is explicit that fail-closed is a design decision your team makes, matched to your risk tolerance, not something guardrails give you automatically. A customer-support bot might reasonably fail open on a minor classifier timeout; a system handling regulated data almost certainly should fail closed. Finally — our third misconception — do not assume the built-in rails ship ready for your use case. NVIDIA states directly that the default NeMo rails may not suit a given production deployment. The same caution applies to LLM Guard's default scanner thresholds. Both frameworks give you strong starting points, not certified, drop-in guarantees. Validating rails against your own industry, audience, and threat model is part of the job, not an optional extra step.