Skip to main content
Guardrails let you enforce content policies and tool access rules at the agent level, not inside individual handlers. Pass a guardrails array to defineAgent and every request through that route is automatically screened — user input before it reaches the model, model output before it reaches the client, and tool calls before they execute. Anvil ships four built-in guardrails covering the most common needs; you can also implement the Guardrail interface directly for custom logic.

The Guardrail interface

  • onText receives the raw text and a TextContext with role: 'input' | 'output'. Return a (possibly modified) string to continue, or throw GuardrailError to block the run entirely.
  • onToolCall receives the tool name, its input, and a tainted flag indicating whether untrusted (tool or retrieved) content is already in the conversation. Return a ToolDecision to explicitly allow, deny, or route the call to human approval.

ToolDecision

The most restrictive decision across all guardrails in the chain wins: deny beats approve, approve beats allow.

GuardrailError

Throw GuardrailError from onText to immediately stop the run:
The guardrail property on the error holds the name string so downstream error handlers can identify which policy fired.

Built-in guardrails

contentFilter

Block or redact text matching custom regular expression patterns.
RegExp[]
required
Patterns to screen. Each pattern is tested against the incoming text; the first match triggers the configured action.
'block' | 'redact'
default:"'block'"
What to do when a pattern matches. 'block' throws GuardrailError; 'redact' replaces every match with replacement.
string
default:"'[REDACTED]'"
Substitution string used in 'redact' mode.
Array<'input' | 'output'>
default:"['input', 'output']"
Which text direction to inspect. Restrict to ['input'] to screen only user messages, or ['output'] for model responses.

redactPII

Automatically redact common PII patterns from input and/or output without needing to supply regexes:
The following patterns are redacted:
Array<'input' | 'output'>
default:"['input', 'output']"
Which text direction to redact. Defaults to both.

toolPolicy

Enforce an explicit allowlist, denylist, or approval requirement on tool names:
string[]
When set, only tools whose names appear in this list may run. Any other tool call returns a deny decision.
string[]
Tools that are unconditionally blocked regardless of allow.
string[]
Tools that require human approval before executing. Matching tool calls receive an approve decision, suspending the run and adding it to the HITL queue.

injectionGuard

Defend against prompt-injection attacks. Once untrusted content (from a tool result or a retrieval) has entered the conversation, the model may have been instructed to make malicious tool calls. injectionGuard detects this “tainted” context and gates subsequent tool calls:
'block' | 'approve' | 'allow'
default:"'approve'"
Action to take when a tool call arrives in a tainted context:
  • 'block' — denies the call outright with a deny decision.
  • 'approve' — routes the call to human approval via the HITL queue.
  • 'allow' — disables the guard (useful for temporarily turning it off without removing the guardrail).
string[]
Tool names that are always permitted even when context is tainted. Use this for idempotent, read-only lookups that carry no injection risk.

Wiring multiple guardrails into defineAgent

Guardrails run in the order they appear in the array. For onText, each guardrail’s return value is passed as input to the next — they compose as a transform pipeline. For onToolCall, the most restrictive decision across all guardrails wins (deny beats approve, approve beats allow).

Implementing a custom guardrail

Return void or undefined from onText to pass the text through unchanged. Return void or undefined from onToolCall to abstain, letting other guardrails in the chain decide.