NeMo Guardrails (Deprecated)
The built-in nemo_guardrails plugin is deprecated and scheduled for removal
in NeMo Relay 0.9. It remains available in NeMo Relay 0.8. There is no
replacement in NeMo Relay 0.8; any replacement will target 0.9 or later.
Do not start a new deployment on the built-in plugin. Use this documentation to maintain or remove an existing NeMo Relay 0.8 configuration.
The built-in plugin component has kind nemo_guardrails and is available as a
first-party NeMo Relay plugin.
The plugin supports these backend modes:
remote- Calls a Guardrails service over HTTP(S), including streaming over the same remote contract.
local- Calls
nemoguardrailsthrough a localpython3worker subprocess instead of a separate Guardrails service.
- Calls
Existing Uses
Existing NeMo Relay 0.8 deployments may use the built-in plugin to:
- Apply Guardrails input and output checks around managed
llm.execute(...)calls. - Apply Guardrails policy around managed tool execution.
- Configure Guardrails behavior through the same plugin config surface used by other first-party NeMo Relay components.
- Keep Guardrails policy authoring in Guardrails-native config while NeMo Relay owns when those checks run around managed execution.
Current Scope
The built-in plugin currently exposes two user-facing modes:
remotefor Guardrails-service integration over HTTP(S)localfornemoguardrailsintegration through a local Python worker
Both modes support managed LLM input and output. The current mode-specific
differences are:
remotesupportsrequest_defaultspass-through but does not support managedtool_inputlocalsupports managedtool_inputand broader LLM codec coverage, but it does not supportrequest_defaults
The local backend requires a python3 >= 3.11 executable that can import
nemoguardrails==0.22.0. It does not embed Python into the NeMo Relay binary.
Managed Surfaces Versus Request Defaults
Both remote mode and local mode share the same top-level plugin model, but
they do not implement every part of that model in the same way.
At the plugin-model level, NeMo Guardrails uses two different concepts:
- Top-level managed NeMo Relay execution surfaces:
inputoutputtool_inputtool_output
- Guardrails backend request defaults:
request_defaults.contextrequest_defaults.thread_idrequest_defaults.staterequest_defaults.railsrequest_defaults.llm_paramsrequest_defaults.llm_outputrequest_defaults.output_varsrequest_defaults.log
This distinction matters:
- Managed surfaces wrap real NeMo Relay execution boundaries such as
llm.execute(...)andtools.execute(...). - Managed surfaces give NeMo Relay an owned enforcement point around a known runtime step. Depending on the backend and surface, Relay can block work, allow it, or apply managed request or result handling before the application sees the outcome.
- Managed surfaces also give NeMo Relay a stable runtime boundary for its own middleware ordering, lifecycle behavior, and observability marks.
The forwarded request-default side is more mode-specific:
- In
remotemode,request_defaultsfields are forwarded to the selected Guardrails backend as request semantics. They do not create new NeMo Relay-native execution surfaces. - In
localmode,request_defaultsis rejected instead of passed through.
The overlap in names is important in remote mode:
- Top-level
inputis a managed NeMo Relay execution surface. request_defaults.rails.inputis a backend pass-through option.- Top-level
outputis a managed NeMo Relay execution surface. request_defaults.rails.outputis a backend pass-through option.- Top-level
tool_inputis a managed NeMo Relay execution surface in the plugin contract. The current stock-remote backend rejects it, while the local backend supports it. request_defaults.rails.tool_inputis a backend pass-through option.- Top-level
tool_outputis a managed NeMo Relay execution surface. request_defaults.rails.tool_outputis a backend pass-through option.
In particular, request_defaults.rails.dialog and
request_defaults.rails.retrieval are pass-through options. They are not
separate managed middleware surfaces in NeMo Relay.
Remote HTTP errors
In remote mode, NeMo Relay preserves received HTTP error status codes from 400 through 599 when returning gateway and lifecycle-hook errors. This applies to buffered requests, streaming setup, and tool input and output checks, even when reading an error response body fails. The existing response envelopes and header handling remain in place. Remote HTTP failures remain non-retryable.
Rust callers receive these failures as FlowError::Upstream with the original
status in UpstreamFailure.status, rather than FlowError::Internal.
Existing public API signatures and binding exception types remain unchanged,
but error messages and classifications change. Explicit guardrail rejections
continue to return HTTP 403. Agent-native hook decision responses retain their
existing protocol behavior.
The status is the final response received under the existing redirect policy. After streaming response headers have been sent, subsequent failures use the existing stream-error behavior and cannot change the HTTP status.
Pages
- NeMo Guardrails Configuration documents the built-in component shape, mode boundaries, and the detailed support matrix.