Smarter Guardrail
Overview
The Smarter Guardrail app is responsible for enforcing constraints on the interaction between an application and a large language model. Rather than relying solely on prompt instructions such as “do not reveal sensitive information” or “respond only in JSON,” guardrails validate inputs, outputs, and execution state before information is accepted or returned. They may sanitize user input, reject prompt injection attempts, enforce schema validation, filter unsafe or out-of-scope responses, verify citations, limit tool access, or require structured output that conforms to predefined contracts. Guardrails operate as deterministic software controls surrounding the probabilistic behavior of the model, ensuring that business rules and security requirements are enforced independently of the LLM’s reasoning.
A Smarter Guardrail is a manifest-declared control that inspects the text passing between a user and an LLM, and acts on what it finds. Each Guardrail runs on one or both stages of a prompt:
Input guardrails inspect the user’s latest message before it reaches the LLM, or the LLMClient’s plugins, MCP clients and functions. They redact PII and secrets, and block prompt injection, jailbreaks, abuse and off-topic requests.
Output guardrails inspect the LLM’s reply before it is returned to the user. They redact leaked PII and secrets, withhold unsafe or non-compliant content, and repair formatting.
Guardrails are deterministic software controls around the probabilistic behavior of the model, so that business rules and security requirements are enforced independently of the LLM’s reasoning, and every intervention is recorded for audit.
Note
Experimental. The Guardrail was designed and coded by Claude Code (Anthropic’s Claude Opus 5.5), with Lawrence McDaniel as co-author. It is experimental, and will be documented. The Smarter Guardrail app is included in v0.15.0 and later.
How It Works
A Guardrail is a Smarter resource, defined by a YAML manifest, and managed with the smarter CLI:
smarter apply -f pii-redaction.yaml
smarter describe guardrail pii_redaction
smarter get guardrails
smarter delete guardrail pii_redaction
An LLMClient uses Guardrails by listing them, by name, in its manifest’s spec.guardrails,
alongside spec.plugins and spec.functions. A name resolves to the user’s own Guardrail
first, and otherwise to a Guardrail shared with them, such as a built-in one.
apiVersion: smarter.sh/v1
kind: LLMClient
metadata:
name: support_assistant
spec:
config:
prompt:
provider: openai
defaultModel: gpt-6-luna
guardrails:
- pii_redaction_input
- prompt_injection_keyword_input
- moderation_output
- secrets_leak_output
On each prompt, the LLMClient’s active Guardrails for the stage run sequentially, in
ascending order of priority. Each Guardrail sees the text as changed by those before it, so
a redaction at priority 10 hides the redacted text from a Guardrail at priority 20. The first
Guardrail that blocks stops the pipeline:
A blocked input is never sent to the LLM. The user receives the Guardrail’s
message, as a reply whosefinish_reasoniscontent_filter, and the blocked message is replaced in the conversation’s history, so that it is not sent to the LLM on a later prompt.A blocked output is replaced with the Guardrail’s
message.
Each Guardrail that triggers records a GuardrailEvent: the Guardrail, LLMClient, session, stage, disposition, confidence and a masked excerpt of the matched text. Events are visible in the Django admin, where they can be marked reviewed, and through the Guardrail api. Old events are purged daily, except flagged and escalated events that await review.
The Manifest
apiVersion: smarter.sh/v1
kind: Guardrail
metadata:
name: pii_redaction
description: Redact credit card numbers and email addresses.
version: 1.0.0
spec:
config:
stage: both # input | output | both
category: pii # what the Guardrail protects against
strategy: detector # how it finds it
detectors: [credit_card, email]
action: redact # what it does when it finds it
replacement: "[REDACTED {label}]"
severity: 4 # 1 (lowest) to 5 (highest)
mode: enforce # enforce | monitor
failClosed: false
priority: 10
isActive: true
Categories classify a Guardrail, for reporting: pii, secrets, prompt_injection,
jailbreak, toxicity, self_harm, hallucination, off_topic, compliance,
formatting and custom.
Strategies
Strategy |
Fields |
Behavior |
|---|---|---|
|
|
Matches a regular expression. Locates its matches, so it can redact and transform. |
|
|
Matches any of a list of words or phrases, tolerant of extra whitespace. Locating. |
|
|
Built-in, validated detectors: |
|
|
Compares the text’s embedding with those of the reference texts. Triggers when the
cosine similarity reaches |
|
|
Scores the text with the provider’s moderation model. Triggers when a category’s score
reaches |
|
|
Asks an LLM for a JSON verdict |
regex, keyword and detector run locally, in microseconds. semantic, moderation
and llm_judge call the provider (default openai), with its API key, and add latency to
each prompt, so order them after the local Guardrails.
Actions
log: record an event, and do nothing else.
flag: record an event for review. The text is unchanged.
redact: replace each match withreplacement.{label}in the replacement is the detector’s name. Requires a locating strategy.
transform: rewrite each regex match withreplacement, which may use back references such as\1. Requires a locating strategy.
block: stop the pipeline, and answer withmessage.
escalate: flag the event for human review, with its severity, and send theguardrail_escalatedsignal. The text is unchanged.
Modes and Failure
mode: monitorevaluates the Guardrail and records what it would have done, as amonitoredevent, without changing or blocking anything. Use it to measure a new Guardrail’s false positives before you enforce it.
failCloseddecides what happens when a Guardrail cannot run, for example when its provider is unreachable. When false, the default, the failure is recorded and the Guardrail is skipped. When true, the text is blocked. Use it for Guardrails whose absence is unacceptable.
Built-in Guardrails
Smarter installs the following Guardrails, owned by the Smarter admin user, and shared with every
account. Install them with python manage.py add_builtin_guardrails.
Name |
Stage |
Category |
Strategy |
Action |
|---|---|---|---|---|
|
input |
pii |
detector |
redact |
|
input |
secrets |
detector |
redact |
|
input |
prompt_injection |
keyword |
block |
|
input |
prompt_injection |
llm_judge |
block |
|
input |
jailbreak |
semantic |
flag |
|
input |
toxicity |
moderation |
block |
|
input |
self_harm |
moderation |
escalate |
|
input |
off_topic |
llm_judge |
block |
|
input |
prompt_injection |
regex |
flag |
|
input |
compliance |
keyword |
escalate |
|
output |
pii |
detector |
redact |
|
output |
secrets |
detector |
redact |
|
output |
toxicity |
moderation |
block |
|
output |
toxicity |
keyword |
redact |
|
output |
compliance |
llm_judge |
flag |
|
output |
hallucination |
llm_judge |
flag (monitor) |
|
output |
formatting |
regex |
redact |
|
output |
formatting |
regex |
transform |
off_topic_input is a template: copy it, and describe your LLMClient’s scope in its judge prompt.
Security Notes
Guardrails reduce risk; they do not remove it. Keyword and regex Guardrails are easily evaded by paraphrase or encoding; the model-based strategies are stronger, and slower. Layer both, and keep least privilege in the LLMClient’s plugins and functions regardless.
An
llm_judgeGuardrail is itself an LLM, and may be manipulated by the text it judges. Smarter tells the judge that the text is untrusted data, and asks for a JSON verdict, and the built-in judge prompts quote the text, but a judge should not be the only control against a determined attacker.Input Guardrails scan only the user’s latest message. The system prompt, and earlier messages, were scanned when they were sent.
Event excerpts are masked: PII keeps its last four characters, and secrets only their length. Nevertheless, restrict access to the GuardrailEvent admin.
Start new Guardrails in
monitormode, and review their events, before you enforce them.