ai_guardrails
On this page
Calls an external AI guardrail provider to evaluate request and response bodies. The provider determines whether content should be passed, blocked, or redacted.
Configuration Notes
Registered as a security filter. Pipeline validation rejects failure_mode: open unless insecure_options.allow_open_security_filters is set. insecure_options.skip_pipeline_validation also bypasses this check. With either option, a provider timeout or error can silently skip screening.
Request conditions: are rejected for the same reason: a security filter must not be skipped for non-matching requests. Body hooks do not run inside a branch, so a router branch is not a substitute. A non-empty request body without a Chat Completions messages array fails the request with 500. Serve /v1/responses and /v1/embeddings from a listener that does not include this filter; put ai_guardrails only on a listener whose routes are Chat Completions.
Every provider callout runs through Praxis’s filtered-subrequest executor. The optional outbound_chain adds destination-bound authentication, authorization, audit, and static service credentials; when omitted it defaults to an empty pass-through chain. Parent and child contexts stay isolated; user-scoped credential projection is handled separately in #880.
Because this filter reads the request body before the header-phase security filters on the main chain run, operators should treat the pre-read body as untrusted input and configure an outbound chain whenever the provider requires destination-bound policy enforcement.
Wire format: client request/response evaluation supports Chat Completions only (messages on requests, choices[].message on responses). phase.tool_results separately evaluates canonical local Responses tool results inside an IRR step. Other Responses content, Anthropic Messages, and MCP wire bodies are not supported yet (see ai#1043). For phase.tool_results, a provider modified verdict fails closed with 502 guardrail_error; sanitized text is not forwarded because it cannot yet be safely mapped back to the canonical tool-result items. Only a passed verdict permits model re-entry.
A provider modified verdict on the request rewrites each targeted user message and forwards the masked body. A request rewrite that cannot be applied is rejected with HTTP 502 so the original text is not sent upstream. On the response, each targeted choice is rebuilt from index, finish_reason, and a message containing only role and the masked content. A choice whose message has array content, tool_calls, or function_call cannot be redacted; the client receives the original HTTP 200 with an evaluation_failed error document. on_response drops Content-Length so core reframes the buffered body at its natural size.
When phase.response is enabled, Chat Completions requests with "stream": true are rejected with HTTP 422 until incremental SSE response evaluation is supported (see #1108).
For NeMo, provider.guardrails.config_ids selects deployed guardrail configurations. When provider.guardrails is omitted, the request omits config_ids so the service can use its default configuration. Omit provider.model to leave the selected configuration’s models unchanged; a non-empty value replaces or adds its main model.
Configuration
| Field | Type | Required | Description |
|---|---|---|---|
outbound_chain | string | object | no | Outbound filter chain executed for every NeMo callout. Optional. Callouts always run through the filtered-subrequest executor; omitting this field uses an empty inline chain (pure passthrough). |
provider | object | yes | External provider configuration (required). |
provider.type | nemo | yes | Provider type selector. |
phase | object | no | Which phases to evaluate. |
phase.request | bool | no | Evaluate client requests before forwarding to the upstream. |
phase.response | bool | no | Evaluate upstream responses before forwarding to the client. |
phase.tool_results | bool | no | Evaluate newly produced local Responses tool results before the next inference round. Intended for placement inside an IRR step after its local dispatchers and before openai_agentic_loop. |
Example
filter: ai_guardrails
outbound_chain: nemo-outbound # optional
provider:
type: nemo
endpoint: "http://nemo:8000/v1/checks"
guardrails:
config_ids: ["your-config"]
timeout_ms: 5000
phase:
request: true
response: true
tool_results: false