Guardrails is the runtime view. Policies is where they come from. A guardrail rule on this page was either hand-built here, or compiled from a policy — a versioned document authored in the dashboard’s Policies section or as a YAML file in your repository. Guardrails shows what’s enforcing and what fired; Policies is where you author, review, backtest, and apply the change. This page’s ownership model — Code-managed vs. dashboard-managed, and Detach — is the same mechanism either way.

The Guardrails page — and every action on it (create, enable, disable, delete, install from a template) — is available on the Solo plan and above. The Free plan has no access.
How guardrails work
When your SDK is initialized withguardrails: true on a provider wrapper, it sends a check request to POST /v1/guardrails/check before the LLM call (pre-check) and after the LLM response (post-check). The backend evaluates all active policies for your project against the content and returns a verdict.
The SDK receives the verdict and either:
- Allows the call to proceed normally
- Blocks it by throwing a
GuardrailBlockedError - Redacts sensitive content and substitutes the cleaned text
- Warns (logs the trigger but allows the call through)
Creating a guardrail
Every guardrail is created from one page — there’s no separate “quick install” grid or creation dialog. Add guardrail on the Guardrails page always opens it.1
Open the Guardrails page
Navigate to Guardrails in the left sidebar.
2
Click Add guardrail
Opens the guardrail-creation page.
3
Start from a template, or from scratch
Pick a starting point from the Content or Agent safety template chips at the top of the page — each pre-fills a working configuration (type, phase, action, and default settings) for one of the guardrail types below — or click Blank to start from an empty draft. Below the chips, Preset templates (bundles Zespan maintains and auto-updates) and Your templates (custom bundles saved for this project) are also available — see Guardrail templates.
The following types apply specifically to agent traces — they inspect tool calls and agent names rather than raw prompt/response text:
4
Name it
Give it a descriptive name that explains what it protects against, e.g.
block-competitor-mentions or toxicity-filter.5
Choose phase and action
Phase selects whether the check runs pre-LLM (the prompt), post-LLM (the completion), or both — the pipeline preview above the fields shows which stages are solid (checked) versus dashed (skipped) as you change it. Action selects what happens when the guardrail triggers:
- Block — reject the request and throw
GuardrailBlockedErrorin the SDK - Redact — remove the matched content and use the cleaned text
- Warn — allow the request but surface the trigger as a warning
- Log — allow the request and record the trigger in execution history, without surfacing it as a warning (useful while you’re still tuning a new policy)
6
Configure the type-specific settings
Fill in the fields for the type you picked. For keyword-based types (topic boundary, scope enforcement, tool misuse allow/blocklists), enter the terms. For regex, enter the patterns. For toxicity and prompt-injection types, pick a sensitivity level (low/medium/high). For PII detection, choose a compliance preset and, optionally, fine-tune the confidence threshold under advanced detection. For custom LLM judge, write your evaluation prompt.
7
Set advanced options (optional)
Open Advanced settings to set max latency, priority (lower numbers run first), what happens if the check can’t run, whether the rule applies project-wide or only to specific agents, and whether it’s enabled on create.If the check can’t run decides what happens when a check errors, exceeds its max latency, or — for Semantic Judge — gets no usable answer from the model, times out, or is asked to read more text than it can. It also covers a rule that is misconfigured so it cannot be evaluated: a regex or secret pattern that is invalid or longer than 500 characters, a scope enforcement pattern that is not a valid regular expression, a schema contract with an invalid schema, a Semantic Judge pass threshold that is not a number between 0 and 1, or a rate limit check whose usage store is unavailable. PII detection is covered too when its name detection is unavailable and nothing else matched. A real match from another pattern in the same rule still takes effect:
This setting governs a check that genuinely could not run. It does not apply to a rule-based type (regex, topic boundary, cost ceiling, agent rate limit, tool misuse, and similar) simply running slower than its max latency — that’s treated as a performance event, not a correctness failure, and never starts blocking traffic on its own; see Latency impact.Creating or editing a guardrail is rejected with a
400 error if a regex pattern, or a custom pattern on a secret detection rule, is invalid, longer than 500 characters, or unsafe (for example a pattern with nested quantifiers that could take very long to evaluate). Fix the pattern and save again. A rule saved before this check existed that still contains such a pattern isn’t rejected retroactively; it follows this setting when it runs and is recorded as a check that could not run.A check that could not run is recorded as such in the execution history and is left out of the blocked, warned and redacted counts on the Guardrails page and of the guardrail outcome figures in compliance reports and agent compliance scores — it is not a decision the guardrail made about your content, so counting it would overstate what the rule actually caught.8
Test, then create
The right-hand column runs a client-side Live preview against sample text as you configure, and a Deterministic test panel that evaluates your unsaved draft against the real guardrail engine. Once you’re happy with the result, click Create guardrail in the sticky footer. The guardrail activates immediately — all subsequent SDK check requests will include it.
Promoting a violation to a policy
Every guardrail hit recorded against a trace can become a permanent rule with one click, right from where it happened — no need to reconstruct the pattern from scratch.1
Open the trace
Find the trace with the violation you want to codify. The guardrail hit shows as its own span in the flame graph, colored to match its outcome.
2
Open the guardrail span
Click it to see the policy, the check phase, and the exact value that triggered it.
3
Click Promote to Policy
Zespan pre-fills a new guardrail draft with the same tool, field, and value that triggered the violation.
4
Review and save
Adjust the draft if you want — tighten a keyword list, change the action, scope it to specific agents — then save it like any other guardrail.
Guardrail templates
Instead of creating guardrails one at a time, you can bundle several rules into a reusable template and apply that bundle to a project (optionally scoped to specific agents, the same way a single guardrail can be). Templates live on the guardrail-creation page (Add guardrail), below the built-in template chips described in Creating a guardrail — there’s no separate templates tab. Zespan ships a set of preset templates that are managed and auto-updated with new threat patterns:
Under Preset templates and Your templates you can:
- Apply a preset or a custom template to your project, project-wide or scoped to specific agents
- Clone a preset into an editable copy you can tweak (presets themselves can’t be edited or deleted)
- Create your own template from scratch by combining any of the guardrail types above into one bundle
- Edit or delete your own templates, and remove an application without deleting the template itself
Managing guardrails
The Guardrails page has two tabs: Rules and Activity.Status band
At the top of the page, a single status band answers “what’s running and is anything wrong”:- A posture headline — “Fully protected”, “N protections active, M gaps”, or “Your agents are running unguarded” — plus an N of 5 active count, scored across five protection categories: PII, Injection, Content, Cost, and Secrets.
- Any category with no active rule shows as a chip (e.g. Secrets +) that links straight to Add guardrail so you can close the gap.
- A range control (
24h,7d, or30d; it opens on7d). The choice is saved in the page address as?range=, so a reload or a shared link opens the same window.
Rules table
The Rules tab lists every guardrail as a row, sorted by phase (pre, then both, then post) and then by priority within each phase:
Each row has a ⋯ menu with Configure (opens the guardrail’s detail page), Enable/Disable, and Delete. A code-managed row only offers Configure — see Dashboard-managed vs code-managed.
Click a guardrail’s name (or Configure) to open its detail page, with Configure, Test, and Logs tabs for editing settings, running the guardrail against sample text, and reviewing its recent trigger history. The Configure tab also shows the pipeline diagram — the same Pre → Both → Post chain that used to sit on the landing page — highlighting where this specific rule sits.
Activity tab
The Activity tab is the project-wide event log — see Execution history.Dashboard-managed vs code-managed
A guardrail can be owned either by the dashboard or by a policy file in your repository. Code-owned guardrails carry a Code-managed badge in the Rules table’s Rule column, with the file path in the tooltip. On a code-managed guardrail’s detail page:- The settings form is read-only, and a banner names the file that owns it:
Managed in
policies/hipaa-phi-egress.yaml. Edit it there, or Detach to take over from the dashboard. - The Delete button is replaced by Detach.
- Enable/disable and delete are unavailable from the row’s ⋯ menu — only Configure shows.
zespan policy apply, with nothing to warn you it had happened.
The API enforces the same rule: a request that changes what a policy-managed
guardrail enforces (its action, settings, type, phase, agents or priority) is
refused with 409 and code: POLICY_OWNED, because it would skip the policy’s
test-before-deny check. Turning the rule off or renaming it still works.
Detach it first if you want to edit it here.
Detaching
Detach hands ownership of that policy to the dashboard: the form becomes editable immediately, and the nextzespan policy apply reports the policy as a
conflict and refuses to overwrite it without --force. Use it when you need to
change a control faster than a pull request allows — during an incident, for
example — then fold the change back into the file afterwards.
Detaching is recorded in the audit log as policy.detached.
Detach requires the same permission as applying policies: owner or
admin. Editors can view a code-managed guardrail but not take it over.
Adopting a dashboard guardrail into code
If you want a guardrail you built here to live in git instead, you do not have to rewrite it:zespan policy pull generates the file from what already exists,
and zespan policy apply --adopt takes it over in place — the guardrail
keeps its id, so its execution history and metrics carry over unchanged. See
Adopting a project that already has guardrails.
Reviewing and applying a policy’s changes
For a policy authored in the dashboard, reviewing and applying its pending changes now lives in Policies — open the policy from its inventory row and use Review changes on its detail page. That screen renders exactly whatzespan policy plan would print for the same change,
computed through the same endpoint, so the two can never disagree. Reviewing
needs only policy:read, which every role has; applying needs
policy:apply.
For policy files that haven’t been committed to your repository yet, the
equivalent check is zespan policy plan from the CLI — see
zespan policy.
Execution history
The Guardrails page’s Activity tab is a log of recent guardrail events, filterable by rule (and each guardrail’s own detail-page Logs tab shows just its events), with:- Timestamp
- The guardrail and check phase (pre/post)
- The action taken (blocked, redacted, warned, logged)
- The reason the guardrail triggered (e.g. which PII types or keyword matched — not the full prompt)
- A link to the underlying trace
Testing a guardrail
Every guardrail (and the form for a new one) has a test panel where you can paste sample text and run it through the guardrail’s current configuration — this evaluates the real rule synchronously and returns a verdict, without needing a live trace from your application:- While creating a guardrail, the test panel runs against your unsaved draft settings
- On an existing guardrail’s Test tab, it runs against the saved configuration
- Each result says which one it ran against — Ran your current settings (a draft) or Ran the saved rule — and that nothing was logged. The API returns the same fact as
source:draftorsaved - You can optionally supply the extra inputs a rule type reads: a model name, region, and operation name (model governance and Semantic Judge), spend and tokens already used (cost ceiling), and a tool call with its arguments plus the calls made earlier in the trace (tool misuse, loop detection, scope enforcement, delegation control). Only the inputs a type reads are shown
- The result shows an overall verdict — Blocked, Redacted, Warned, Allowed, or Check errored when a rule couldn’t run (a check that errored is never reported as Blocked or Allowed) — plus the modified text (if a redact rule matched) and a per-guardrail breakdown of which rule fired, what action it took, whether it passed, and its latency
What was checked, and what wasn’t
A pass on its own doesn’t tell you what the rule looked at, so each rule that ran cleanly adds a line saying so — for example “Checked for: email, SSN.” for a PII rule, “Checked against 3 blocked keywords.” for a topic boundary, or “Checked against 2 patterns.” for a regex rule. A rule with nothing configured says so instead (“No patterns are set, so nothing can trigger this rule.”). For PII rules, the test also looks for PII your rule doesn’t cover. If the sample contains an email address but Email isn’t in the rule’s entity list, the result says “This text also contains an email address, but Email isn’t enabled in this rule.” and, where the rule form is on the page, offers an Enable Email button that adds it. This uses the engine’s pattern detectors only (email, phone, credit card, SSN, IBAN, and IP address) and sends nothing to a model, so a pass is never mistaken for “this text has no PII”. On the API,POST /projects/{id}/guardrails/test returns these as checked (a list of one-line summaries) and, for PII rules, notCovered (the entity ids found in the text that the rule doesn’t check) on each entry in results, and source at the top level. The endpoint requires permission to manage guardrails.
The test panel can’t run agent rate limit rules: they keep a per-agent counter, so a test would spend the real budget. For the other agent-context types, the result is only as complete as the context you give it. Supply the tool call and earlier calls in the panel; a real trace supplies them for you. Validate agent rate limits by checking their execution history after live traffic runs through them.
Latency impact
Guardrail checks add latency to your LLM calls. The check runs synchronously before (and optionally after) the LLM call. Typical check latency:Semantic Judge is the only type that calls a model for every check — every other type runs entirely on pattern matching, keyword lists, or counters. A check that exceeds its max latency counts as unable to run and follows the rule’s If the check can’t run setting, so raise max latency if a slower judge model is timing out. Input too long for the judge to read in full is also treated as a check that could not run — it is never judged on a truncated prefix — and follows the same If the check can’t run setting; the limit is 20,000 characters when the project has connected its own LLM, and roughly 12,000 characters (counting your judge prompt as well as the checked text) on Zespan’s own key (see AI usage limits).For every other guardrail type, exceeding max latency is treated as a performance-budget event, not a correctness failure: the request is allowed through and the check is recorded as unable to run, so a brief slowdown in the underlying check (for example, in agent rate limit, tool misuse, or cost ceiling) never starts blocking real traffic on its own. Semantic Judge is the exception — a Semantic Judge timeout follows If the check can’t run like any other Semantic Judge failure, since a slow or unreachable model is treated the same as one that fails outright.
Human approval gates
Beyond automatic block, redact, and warn actions, the SDK exposes a real human-in-the-loop primitive:awaitApproval() pauses execution until an admin approves or rejects the call from the dashboard — not just a log entry, an actual gate your code waits on.
Near-miss capture and suggested rules
Zespan also learns from traffic that almost triggered a numeric guardrail rule but didn’t. When a threshold-based check —cost_ceiling, agent_rate_limit, and similar types — evaluates close to its limit without firing, that near-miss is logged instead of silently discarded.
A background worker clusters recurring near-misses into suggested policy rules, surfaced in a panel on the Guardrails page: “Your agents have hit this pattern 6 times this week — no rule governs it yet. Want one?”
- Click Promote to Policy on a suggestion you agree with — it reuses the same promote flow described above
- Click Dismiss to clear a suggestion that isn’t worth a standing rule
AI usage limits
A Semantic Judge (custom_llm) guardrail calls a model on every check, so unlike every other guardrail type it can’t run on pattern matching alone. Zespan runs these checks on its own key by default, metered against a monthly quota that scales with your plan:
Usage is counted per Semantic Judge rule evaluated: a check that runs three Semantic Judge rules on Zespan’s AI counts three times. These don’t count:
- A repeat of the same check served from the short-lived verdict cache. A verdict for identical input is reused for 120 seconds when the rule’s temperature is 0 or unset.
- Rules that are skipped, for example because an earlier phase already decided the outcome.
- Rules that run on your own LLM connection (Run on: your connection).
Previously a check counted once however many Semantic Judge rules ran. If you have several Semantic Judge rules, expect higher counts for the same traffic.
A self-hosted deployment with no AI provider configured at all (no LLM connection, and no platform key set up in the environment) is a distinct, expected state — not a runtime failure. Semantic Judge checks are allowed through in that case, regardless of the guardrail’s action or its If the check can’t run setting, since there’s genuinely nothing broken to fail closed against. The check is still recorded as unable to run, with a reason pointing to Settings → LLM Connections.
When AI processing is off
If your organization has turned off AI processing, Semantic Judge rules set to run on Zespan AI credits aren’t evaluated. In the/v1/guardrails/check response, each such rule is an errored result with the reason Guardrail could not run: ai_processing_disabled, handled by its If the check can’t run setting; the response shape doesn’t change. No credit is used, and Zespan doesn’t fall back to your own LLM connection for these rules. Rules set to Run on: your connection and non-AI rules run normally. The guardrail editor disables the Zespan AI credits option and explains why, and policy backtests skip these rules in the same way.
How the Semantic Judge scores
The judge scores how well the content complies with your policy on a fixed scale: 1.0 clearly compliant, 0.75 compliant with minor ambiguity, 0.5 unclear, 0.25 likely violates, 0.0 clearly violates. Only the Pass threshold decides the outcome (the default is 0.7, so 0.75 passes and 0.5 does not). When content fails, the judge must quote the part of the text that violates your policy. If that quote cannot be found in the checked content, the check still fails but the explanation is replaced with a note that it was withheld, rather than showing an unverified reason. Use the{{text}} placeholder in your judge prompt to insert the checked content.
Plan requirement
The Guardrails page, and every action on it — creating, editing, enabling, disabling, deleting a guardrail, and installing a template — is available from the Solo plan up. The Free plan has no access.Next steps
Policies
Author, review, backtest, and apply policies from the dashboard.
Policy as code
Manage these policies as YAML in your repository, reviewed in pull requests.
Policy file reference
Every field in a policy file, and the supported YAML subset.
zespan policy
validate, plan and apply from the CLI or CI.
SDK guardrails
Enforce these policies from your application.
LLM Connections (BYOK)
Connect your own provider key to run Semantic Judge checks unmetered.

