- Request stage — before the request is forwarded to the upstream model.
- Response stage — after the model responds, before the reply reaches your app.
The decision contract
A policy returns a singledecision object. This is the only value the runtime reads — allow/deny rules or a bare redact_fields set are ignored.
- Write
package xenovia. The control plane strips yourpackageline and re-packages the rule under a system namespace, so the package name you choose does not matter. actionis required;ruleis a short identifier recorded on the trace. Any other key (includingreason) is ignored by the runtime.- Multiple complete
decisionrules must have mutually exclusive conditions. If two can be true at once, OPA reports a conflict and the request fails closed. Guard each rule with distinct conditions (for example oninput.agent_role).
The Rego is compiled with
opa check --strict when you save it. Compilation errors are returned as 422 with the OPA diagnostics.Actions
When several enabled policies run at the same stage, the strongest action wins:
block over escalate over redact over allow (and block_response over redact_response at the response stage). An unrecognised action ranks below allow and can never block.
Redaction
Return the labels to strip inredact_fields:
email, ssn, phone, creditcard (Luhn-validated), ip, url. Redaction applies to message text, tool descriptions, and the Responses instructions field at the request stage, and to the reply text at the response stage. Streamed replies are buffered and checked before any content is sent, so response redaction applies to them too.
Monitor vs enforce
Enforcement is a property of the policy, set in the dashboard (Monitor or Enforced) or through the API, not something you express in Rego:- Enforced policies apply their action.
- Monitor policies are evaluated and their would-be decision is recorded on the trace, but the action is never applied. Use monitor mode to trial a policy against live traffic before enforcing it.
Policy input
Both stages receive the same base fields; each stage adds its own.Base fields (both stages)
Request stage adds
Response stage adds
Examples
Block a tool
Require the agent’s model to be on an allowlist
input.model is the model configured on the agent, so this rule guards against an agent routed to an unapproved model rather than a client choosing one.
Cap output tokens (request stage)
Block a refusal in the reply (response stage)
Templates
Instantiate a shipped template with its parameters instead of writing Rego. Thirteen templates were removed because the runtime never produces the inputs they read, or because they always escalated:pii-pattern-block, rapid-call-rate-block, repeat-denial-escalation, anomalous-tool-pattern-escalation, tenant-boundary-match, external-disclosure-consent-gate, block-shadow-model-fallback, low-confidence-escalation, high-risk-tool-human-approval, financial-threshold-escalation, eu-ai-act-fundamental-rights-review, destructive-tool-confirmation, and workflow-intent-aggregate-escalate. Policies you already created from them are unchanged; review whether they can still fire.
Guardrails
Guardrails replace the former intent check. A guardrail is a named check that Xenovia’s guardrail model evaluates at one or more stages (model_request, model_response, tool_call, tool_result, memory_write, context_summary), with an action (allow, block, redact, or escalate) and, like a policy, Enabled and Monitor or Enforce. The agent’s scope guardrail (kind scope) describes in plain language what the agent is for; requests outside it are flagged. A guardrail can be limited to one agent role. tool_result, memory_write, and context_summary guardrails run only when your code sends those stages with the Python SDK.
What a block looks like to your app
A blocked request returns403. The runtime uses the gateway error envelope:
PermissionDeniedError. The message is deliberately generic; the rule that fired is recorded on the trace, not returned to the caller. The X-Xenovia-Trace-Id response header identifies the trace.
Escalations
escalate is for actions you want flagged for human attention. When a policy escalates:
- The call is blocked with
403: a request-stage escalation returnsrequest blocked by policy, and a response-stage escalation suppresses the reply withresponse blocked by policy. - An escalation is recorded, carrying the agent and matched rule.
- Any alert rule watching for escalations fires (see Alerts).
escalate records an escalation the same way but lets the request proceed.