Skip to content

Verdicts, obligations & mandates

govern() returns a Decision, a frozen, auditable record of what the policy concluded and what must happen next.

Field Meaning
outcome allow, block, or needs_approval (when a rule requires human approval). (escalate, modify, and dispatch_to_sandbox are reserved internal names the pipeline does not emit yet.)
reason Machine-readable cause, e.g. pii_in_input, no_policy_compiled.
behavior_id, pipeline_id Correlation IDs echoed back; the audit trail is queryable by both.
decided_at UTC timestamp of the verdict.
details evidence, rule_id, rule_kind, category, which rule decided, and everything it saw.
obligations Effects the caller must apply (see below).
mandate short-lived signed token minted on allow (see below).
approval Approval evidence when the call resumes a granted approval.

A blocked call carries the full evidence of why, the same evidence written to the audit trail. There is no difference between what the caller sees and what an auditor sees.

A verdict can carry obligations, typed instructions the runtime applies around the decision:

Obligation Timing Effect
redact pre / post Mask detected spans (PII, secrets) in the prompt, messages, tool args, or response, the call continues with clean content
redact_tool_arg pre Regex-replace a pattern in a named tool argument
route_to_model pre Rewrite the target model (e.g. force a tier: frontier → local)
require_approval pre Suspend the call and open a human-approval request
rewrite_response post LLM auto-correct the response against a criterion (fail-open)
filter_tools pre Restrict the visible tool list (MCP tool visibility)
requires_audit_signing , Mark the record for the signing layer

Obligations are discharged by registered handlers, and a failing handler fails closed, if redaction can’t be applied, the call doesn’t go through. The one deliberate exception is rewrite_response, which is fail-open by design.

Redaction is the important mental shift: policy isn’t only yes/no. “Strip the SSN and let the call through” is a first-class outcome, expressed as allow + a redact obligation.

A rule of kind RequireApproval turns the verdict into an approval request instead of a block. The caller gets a request_id and a fingerprint; a human decides in the dashboard, the CLI, or via WebAuthn-signed approval. When the call is resubmitted, the granted approval appears in subject.approval and the rule passes. One approval authorizes exactly the fingerprinted action, not the agent’s next fifty actions.

On allow, the kernel mints a mandate: a compact, short-lived signed mandate naming the authorized capabilities:

llm:call:gpt-4o tool:call:send_email sor:write:customer.email

Executors verify mandates offline against the JWKS published at /.well-known/jwks.json (or via POST /v1/tokens/verify). The mandate is how a decision made at the gateway stays meaningful at the point of execution: a tool server can prove this exact call was authorized, moments ago, by policy it never had to load.

There is no revocation list, the TTL is the revocation window.

Verdicts are deterministic: the same policy and input always produce the same verdict, which is what makes replay provable. This is what makes the audit trail more than a log: you can replay any historical decision against a different policy version and get a provable what-if answer.