Overview
A guardrail is a named, configured instance of a plugin. Guardrails run inside every workflow that references them, in one of three phases:- prompt: after routing, before the request reaches the provider
- response: on the complete response, before it reaches the client
- stream: on each streamed event (or on the buffered stream, depending on the plugin)
/v1/chat/completions/v1/responses/v1/messages
Guardrails for images, TTS, STT, and video models are planned as a separate
system and are not covered here.
Quick Start
Add aguardrails section to your config/config.yaml:
Manage from the Dashboard
Guardrail definitions can also be created and edited from the admin dashboard instead ofconfig.yaml — useful for iterating on rules without a
redeploy, or for operators who don’t manage this repo’s config directly.
Open Guardrails in the sidebar and click Create Guardrail: give it a
name, pick a type (every loaded plugin with a prompt, response, or stream
hook is listed), optionally scope it to a user_path, and fill in the form
the plugin declares. The Advanced section holds the failure mode and
timeout. config.yaml entries are seeded into the same store at startup and
stay in sync with it, so dashboard-created and config-declared guardrails
appear side by side. The Plugins list at the bottom of the page shows
every loaded plugin type, its hooks, source, and health.
Runtime guardrail execution still depends on
GUARDRAILS_ENABLED. With it
off, the page still lets you manage definitions — they just don’t run on
live traffic yet.How It Works
- The request is mapped to a unified
Prompt(system, user, assistant, and tool messages with stable IDs) - The prompt chain runs: each guardrail edits the prompt, or decides to block, respond, or warn
- Edits are applied back to the original request, which continues to the provider
- The response chain runs on the complete response (or the stream chain on the stream) before anything reaches the client
Exchange. The same guardrail works
identically for /chat/completions, /responses, and /messages.
Execution Order
Each guardrail has anorder value (the workflow step) that controls when it
runs within its phase:
- Same order → run in parallel (concurrently)
- Different order → run sequentially (ascending)
system_prompt, llm_based_altering,
string_replace) cannot share an order with another editing guardrail; only
one editor per order, and any number of non-editing checks (llm_judge,
header_edit) next to it. When several guardrails at one order decide
differently, the most severe decision wins: block > respond > warn >
allow.
Configuration
Full Structure
system_prompt and llm_based_altering also accept their settings in a typed
block named after the type (system_prompt: / llm_based_altering:), as in
the Quick Start. The typed block and config: are equivalent; use config:
for every other type. Line-oriented keys such as string_replace.rules and
the header_edit lists accept either a block scalar (|) or a YAML list of
strings, joined by newlines.
Environment Variable
You can toggle guardrails without editing the config file:Rule Fields
Guardrail Types
Five types ship with GoModel. Each is a built-in plugin; the tables list its config keys as they appear underconfig: and on the dashboard form.
system_prompt
Adds, replaces, or decorates the system prompt on every request.
Phases: prompt. Edits content: yes.
Settings
Modes
- inject
- override
- decorator
Adds a system message only if none exists. Existing system prompts are left untouched.Behavior:
- Request has no system prompt → adds one
- Request already has a system prompt → no change
llm_based_altering
Rewrites the text of selected message roles by calling an auxiliary model.
In the prompt phase it rewrites the request; in the response phase it
rewrites the assistant’s reply (when roles includes assistant). This is
useful for PII anonymization and other content-preserving rewrites.
The default prompt is derived from LiteLLM’s data_anonymization guardrail,
so a minimal config acts as an anonymizing preprocessor.
Phases: prompt, response. Edits content: yes.
Settings
Rewrites run through the normal translated request path in-process, so
workflow selection, failover, usage, audit, and cache behavior still apply.
The internal request uses:
- path:
/v1/chat/completions - user path:
{guardrail.user_path or caller user path}/guardrails/{guardrail name} - request origin:
plugin
fail_mode).
Example
string_replace
Replaces, flags, or blocks text that matches a list of literal or regular
expression rules. Works on prompts, responses, and streams.
Phases: prompt, response, stream. Edits content: yes.
Settings
In the stream phase,
replace and warn transform events in flight with the
configured lookbehind. block and respond buffer the whole stream so
nothing leaks before the decision, at the cost of delaying the first token
until the response is complete.
Example
header_edit
Sets, adds, and removes HTTP headers on the request, the client response, and
the upstream provider call. It never edits content, so it can share an order
with an editing guardrail.
Phases: prompt, response. Edits content: no.
Settings
Every key is a list of lines. Set and add lines look likeName: value;
remove lines are a bare Name. Blank lines and # comments are ignored.
Credential headers (
Authorization, X-Api-Key, Cookie, …) can never be
edited, and names containing secret or token cannot be set.
Example
llm_judge
Asks a judge model whether the prompt (or the response) violates a policy and
blocks, answers, or flags it based on the verdict. The judge must reply with
one JSON object {"verdict":"allow"|"block","reason":"..."}; the default
instructions do that and tell the model to ignore instructions inside the
content.
Phases: prompt, response, stream (buffered). Edits content: no.
Settings
Identical text is judged once per request, so an instance that runs in both
the prompt and the response phase does not double-charge for the same
content. In the stream phase the whole stream is buffered and judged as a
complete response.
Example
Examples
Single Safety Guardrail
The simplest setup — add a safety prefix to every request:Checks in Parallel with an Editor
A non-editing check shares order0 with the system prompt editor and runs
concurrently with it:
Sequential Pipeline
Guardrails with different orders run one after another. Later groups see the output of earlier ones:Response Phase: Redact Secrets on the Way Out
Runs on the complete response before it reaches the client. Setfail_mode: open if you prefer an unredacted answer over a 500 when the
guardrail itself fails.
Stream Phase: Redact In Flight and Judge the Whole Answer
The same instance can be referenced in several phases.mask-keys transforms
streamed chunks in flight (64 characters of lookbehind, so a key split across
two chunks is still caught). answer-judge needs the whole answer, so it
buffers the stream and the client receives it once the verdict is in.
How It Works With Different Endpoints
Guardrails operate on a unified message format internally. The adaptation between API-specific request types and this format happens automatically:
For
/v1/messages, a request that runs any guardrail takes the translated
path (the native passthrough is skipped). A response cut by a guardrail is
reported with finish_reason: "content_filter" on OpenAI-compatible
endpoints and stop_reason: "end_turn" on /v1/messages.
Decisions, Errors, and Rejection
A blocked request never reaches the provider; a blocked response never
reaches the client. See Plugins for how
decisions merge when several guardrails run at the same order.