Guardrails
|
This content was generated with the assistance of AI and should be verified against the official documentation of each tool and framework before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
Written on 2026-10-01 against NeMo Guardrails 0.24.1, Guardrails AI 0.11.0, LangChain 1.x, Spring AI 2.0.x and the Llama Guard, Prompt Guard and ShieldGemma model families (see the version baseline). The code below is illustrative and was written from the official documentation; it was not run against a live DocsAssistant, and no benchmark or test results are reported on this page. The interface name of Spring AI’s moderation abstraction is discussed in its own section because the documentation page consulted does not state it explicitly.
A guardrail is a check that sits around a model call and can block, rewrite, escalate or log what passes through it. Guardrails are one control among several: they reduce the rate of bad inputs and outputs, but they are probabilistic when built on classifiers and bypassable when built on rules, so they complement, and never replace, the architectural controls described in Prompt Injection and Excessive Agency and Tool Security. Application-level treatments of the same topic are in LangChain Guardrails and Security, Spring AI Security and Guardrails, Agent Guardrails and Safety and Guardrails and Prompt Injection in RAG; this page is the security view that ties them together.
Layer architecture
Think of four places where a check can be placed, each seeing different data and failing in a different way.
| Layer | What it sees and checks | Typical tools |
|---|---|---|
Input |
The user message and conversation history, before the model. Personal data, injection phrasing, off-topic or abusive requests, size. |
Moderation endpoints, Prompt Guard, Llama Guard, NeMo input rails, Presidio, middleware hooks. |
Retrieval |
Documents and tool results that will enter the prompt. Per-user access filtering, source trust, hidden instructions in content. |
Vector-store metadata filters (see RAG and Vector Security), content scanners. |
Output |
The model’s reply before it reaches a user or a downstream parser. Harmful content, leaked personal data or prompts, outbound links, schema validity. |
Llama Guard and ShieldGemma on responses, Guardrails AI validators, NeMo output rails, schema validation (see Improper Output Handling). |
Action |
The tool name and arguments the model asked to run. Allow-lists, argument validation, quotas, human approval. |
Application code, Spring Security, human-in-the-loop middleware (see Human in the Loop). |
The layers are ordered by how much you can trust the check. The action layer is ordinary code with deterministic rules and is the strongest. The input and output layers usually rely on a model and give statistical protection. Place a deterministic rule wherever one is possible, and a classifier only where meaning has to be judged.
Tools
Llama Guard and Prompt Guard
Meta publishes safety classifiers as open-weight models. Llama Guard is an LLM fine-tuned to classify a prompt, or a prompt plus a response, against a taxonomy of hazard categories and to answer with a safe or unsafe verdict plus the violated categories. Because the taxonomy is part of the prompt template, a deployment can adapt categories to its policy. Prompt Guard is a much smaller classifier aimed at prompt-injection and jailbreak detection, which is why it is cheap enough to run on every request. Both are models, so they have the false-positive and false-negative behaviour of any classifier and need their own evaluation on your traffic. Check the model cards for the current version, licence terms and the supported languages before adopting either (see Choosing Models and Licences).
ShieldGemma
ShieldGemma is Google’s family of safety classifiers built on Gemma, trained to judge whether text violates a stated policy (for example sexually explicit content, dangerous content, hate speech and harassment) in user input or in model output. It is used the same way as Llama Guard: send the text with the policy, read back a verdict. Model sizes and policy wording are documented on the model card.
NeMo Guardrails
NeMo Guardrails (NVIDIA, 0.24.1 at the time of writing) is a programmable layer around an LLM. A configuration directory holds
a config.yml that declares the model and the active rails (input, dialog, retrieval, execution and output), plus optional
Colang flows and Python actions. The library wraps the model call, so the application talks to LLMRails instead of to the
model.
# config/config.yml
models:
- type: main
engine: openai
model: gpt-4o-mini # the key is read from OPENAI_API_KEY in the environment
rails:
input:
flows:
- self check input
output:
flows:
- self check output
from nemoguardrails import LLMRails, RailsConfig
config = RailsConfig.from_path("./config")
rails = LLMRails(config)
reply = rails.generate(messages=[{"role": "user", "content": "How do I install the docs site?"}])
The self check input and self check output flows ask the main model to judge the text against prompts that you must also
define in the configuration (a prompts.yml file); the structure follows the
NeMo Guardrails documentation, where the full set of built-in rails, including
integrations with Llama Guard and other classifiers, is listed. Self-check rails cost an extra model call per check, which matters for the latency budget below.
Guardrails AI
Guardrails AI (0.11.0 at the time of writing) takes a validator-centred approach: a Guard composes validators, each of which
checks a value and applies an on-fail action such as raising an exception, fixing the value, filtering it or re-asking the
model. Validators are distributed through the Guardrails Hub and installed separately, so the set you can use depends on what
you install.
# one-time: guardrails hub install hub://guardrails/detect_pii
from guardrails import Guard
from guardrails.hub import DetectPII
guard = Guard().use(
DetectPII, pii_entities=["EMAIL_ADDRESS", "PHONE_NUMBER"], on_fail="exception"
)
guard.validate("Contact the maintainer for help.") # raises if PII is detected
The pattern follows the Guardrails AI documentation; validator names, parameters and the
accepted on_fail values should be confirmed there for the installed version. Validators that wrap a local model add startup
and per-call latency, so measure them before placing them on the request path.
Provider moderation APIs
Several providers offer a moderation endpoint that classifies text (and, for some, images) into harm categories with scores and a flagged field. OpenAI’s moderation endpoint and Azure AI Content Safety are the best known; Azure’s prompt-shield capability targets injection attempts specifically. Their advantages are that they need no hosting and are tuned continuously; the costs are an extra network round trip, a dependency on a third party, and a taxonomy you cannot change. Check each provider’s current model names, free-tier terms and data-handling policy, because user text is sent to a service. Moderation endpoints catch harmful categories; they are not injection or data-loss controls unless the provider says so. Azure AI Content Safety’s harm categories, Prompt Shields and groundedness checks are covered with code on Foundry Tools: Content Safety.
Spring AI moderation
Spring AI provides a moderation abstraction with an OpenAI implementation. The pieces named in the reference documentation are
OpenAiModerationModel, ModerationPrompt, ModerationResponse and OpenAiModerationOptions, and the model is enabled with
the property spring.ai.model.moderation. The documentation page consulted for this page does not state the name of the common
interface explicitly: it is expected to be ModerationModel, which another page in this section also uses, but this is
unverified against the Spring AI 2.0 Javadoc, so confirm it before writing code against the interface and not the
implementation.
OpenAiModerationOptions options = OpenAiModerationOptions.builder()
.model("omni-moderation-latest")
.build();
ModerationResponse response = openAiModerationModel.call(new ModerationPrompt(userText, options));
boolean flagged = response.getResult().getOutput().getResults().get(0).isFlagged();
if (flagged) {
throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY, "Message rejected by content policy");
}
The API key is read from the Spring configuration (spring.ai.openai.moderation.api-key, normally bound to an environment
variable such as ${OPENAI_API_KEY}). The calls derive from the
Spring AI OpenAI moderation reference;
openAiModerationModel is an injected bean and userText the incoming message. The accessor chain for the results was
simplified here and should be checked against the Javadoc.
Implementing the layers in code
Python: LangChain middleware
LangChain 1.x ships built-in middleware for common guardrails. PIIMiddleware detects a PII type and applies a strategy
(documented strategies include redacting, masking, hashing and blocking), ModelCallLimitMiddleware and
ToolCallLimitMiddleware bound runaway loops, and HumanInTheLoopMiddleware implements the action-layer approval. Custom
middleware covers anything else, as shown in the middleware page.
from langchain.agents import create_agent
from langchain.agents.middleware import (
HumanInTheLoopMiddleware,
ModelCallLimitMiddleware,
PIIMiddleware,
ToolCallLimitMiddleware,
)
agent = create_agent(
model="openai:gpt-4o-mini", # reads OPENAI_API_KEY from the environment
tools=[search_docs, open_issue],
middleware=[
PIIMiddleware("email", strategy="redact", apply_to_input=True),
PIIMiddleware("credit_card", strategy="mask", apply_to_output=True),
ModelCallLimitMiddleware(run_limit=8, exit_behavior="end"),
ToolCallLimitMiddleware(tool_name="open_issue", run_limit=1),
HumanInTheLoopMiddleware(interrupt_on={"open_issue": True}),
],
)
The middleware names and the overall shape derive from the LangChain guardrails guide
and the middleware documentation; parameter names and the accepted
strategy values change between releases, so confirm them for the installed version. search_docs and open_issue are the
DocsAssistant tools defined elsewhere.
Java: Spring AI SafeGuardAdvisor
SafeGuardAdvisor blocks a request whose text contains any configured sensitive word and returns a fixed failure response
without calling the model. Registered through defaultAdvisors, it is a cheap deterministic input guardrail; a moderation or
classifier call can be wrapped in a custom advisor in the same position. Advisor order matters, as described in
Advisors.
ChatClient client = ChatClient.builder(chatModel)
.defaultAdvisors(
SafeGuardAdvisor.builder()
.sensitiveWords(List.of("ignore previous instructions"))
.failureResponse("I can only answer questions about the documentation.")
.order(Ordered.HIGHEST_PRECEDENCE + 50)
.build())
.build();
The builder follows the Spring AI advisors reference; confirm the exact builder methods against the 2.0.x Javadoc. A word list is a speed bump that paraphrase defeats, so treat this as the first and cheapest layer in front of the moderation and tool-level controls.
Latency budget
Every synchronous guardrail adds to time to first token, and output guardrails can also delay streaming because a complete reply must be judged before it is released. A simple model keeps the choice explicit. With a target end-to-end latency \( T \), a model call \( t_m \), and checks run in sequence with latencies \( t_i \) (inputs) and \( t_o \) (outputs):
Independent input checks can run in parallel, replacing their sum by their maximum, and some can run concurrently with the model call if the response is discarded when a check fails. Options that follow from the formula:
-
Put cheap deterministic checks first, so most rejections cost microseconds and never reach a classifier.
-
Run classifiers in parallel with each other, and with the model call when blocking is allowed to cancel it.
-
Use a small dedicated classifier (a Prompt Guard sized model) rather than a self-check call to the main model.
-
For streaming, either buffer in chunks and check each chunk, or accept that some text is shown before a late check fires; decide this per risk, because a leaked secret cannot be un-shown.
-
Measure the real values of \( t_i \) on your hardware and traffic; none are quoted here because none were measured for this page.
Fail-open or fail-closed
When a guardrail itself fails (timeout, provider outage, classifier error), the application must pick a default.
| Policy | Behaviour | Fits |
|---|---|---|
Fail closed |
Block or degrade the request when the check cannot run. |
Action guardrails, writes, regulated data, child-safety content, anything where one miss is an incident. |
Fail open |
Let the request through and log it. |
Low-risk read-only answers where availability matters more, ideally with a stricter fallback such as a rules-only check. |
Decide per layer and per risk, write the decision down, and test it by injecting failures in staging. Add a timeout to every remote check so a slow dependency becomes an explicit decision instead of a hung request, and alert on the rate of check failures, because a guardrail that silently fails open is a guardrail that is no longer there. The continuous operation side (dashboards, alerts, regression suites) is covered in LLMSecOps.
Test
Guardrails need their own tests, separate from the model’s. Measure the false-negative rate with an attack set and the false-positive rate with a set of ordinary documentation questions, because a guardrail that blocks legitimate users gets disabled. Re-run both whenever the guardrail model, taxonomy, prompt or threshold changes. garak, PyRIT and promptfoo can drive the attack side against the full application endpoint, which is the only way to test the guardrails together with the model; see AI Red Teaming for the commands. No scan was run for this page, so there are no detection or false-positive figures to report.
Map
| Framework | Entry |
|---|---|
OWASP LLM 2026 |
Mitigation for LLM01 Prompt Injection, LLM02 Sensitive Information Disclosure and LLM10 Improper Output Handling |
OWASP Agentic (ASI) |
ASI01 Agent Goal Hijack and ASI02 Tool Misuse and Exploitation (action layer) |
MITRE ATLAS |
AML.T0051 LLM Prompt Injection (detection and blocking) |
NIST AI 600-1 |
Information security; dangerous, violent or hateful content; data privacy |
The one-page summary is in the cheat sheet.
References
-
OWASP Top 10 for LLM Applications 2026: https://genai.owasp.org/resource/owasp-genai-llm-top-10-2026/
-
MITRE ATLAS: https://atlas.mitre.org/
-
NIST AI 600-1: https://doi.org/10.6028/NIST.AI.600-1
-
Llama Guard and Prompt Guard (Meta Llama Protections): https://www.llama.com/llama-protections/
-
Llama Guard (paper): https://arxiv.org/abs/2312.06674
-
ShieldGemma (paper): https://arxiv.org/abs/2407.21772
-
NeMo Guardrails documentation: https://docs.nvidia.com/nemo/guardrails/latest/
-
Guardrails AI documentation: https://www.guardrailsai.com/docs
-
OpenAI moderation guide: https://platform.openai.com/docs/guides/moderation
-
Azure AI Content Safety: https://learn.microsoft.com/azure/ai-services/content-safety/
-
Spring AI OpenAI moderation: https://docs.spring.io/spring-ai/reference/api/moderation/openai-moderation.html
-
Spring AI advisors: https://docs.spring.io/spring-ai/reference/api/advisors.html
-
LangChain guardrails: https://docs.langchain.com/oss/python/langchain/guardrails
-
LangChain middleware: https://docs.langchain.com/oss/python/langchain/middleware