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.

flowchart LR U["User message"] --> I["Input guardrails: PII, injection, topic, length"] I --> R["Retrieval guardrails: ACL filter, source trust, content scan"] R --> M["Model: untrusted component"] M --> O["Output guardrails: moderation, PII, links, schema, grounding"] O --> A["Action guardrails: tool allow-list, argument validation, approval"] A --> X["Reply or tool execution"] I -. "decision log" .-> L["Audit and monitoring"] R -. "decision log" .-> L O -. "decision log" .-> L A -. "decision log" .-> L
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.

NeMo Guardrails configuration with input and output rails
# 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.

A Guard with a PII validator
# 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.

Calling the OpenAI moderation model
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.

Input, output and action guardrails composed on the DocsAssistant
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.

A deterministic input guardrail with a fixed refusal
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.