Skip to content

Verdicts

An interceptor returns exactly one of three decisions.

Decision Class Host obligation
allow permit proceed with target unchanged; record any warnings
transform permit apply the transform to target, then proceed with the rewritten value
deny block do not proceed; at post_* points, discard the already-produced result
{
  "decision": "deny",
  "reason": "egress_blocked",
  "message": "confidential marker in tool arguments"
}

Warnings are metadata, not decisions

There is no warn decision. A warning is an allow carrying a warnings array; it is recorded on the audit record and unioned across all interceptors in an emission, but it never affects control flow. SDKs ship Verdict.warn(...) sugar that produces exactly that shape.

{ "decision": "allow", "warnings": [{ "reason": "quota_80_percent" }] }

Escalation is a liftable deny

There is no escalate decision either. An escalation is a deny carrying an approval block: denied as-is, unless the approval seam lifts it. This makes fail-closed a property of the type. An unresolved escalation is not a state the host must remember to handle; it is simply a deny. A host with no approval resolver enforces it as a plain deny, and that is conformant behaviour, not an error.

{ "decision": "deny", "reason": "requires_human_approval", "approval": {} }

Severity

Aggregation across multiple interceptors uses a total order fixed by the specification:

deny  >  deny+approval  >  transform  >  allow

A plain deny dominates a liftable one: if any interceptor unconditionally denies, consulting an approver is pointless. The order is not host-configurable; two hosts running the same profile must agree on every outcome.

Validation and fail-closed handling

The host validates every returned verdict against the ยง5 rules before acting on it: a transform body is required exactly when the decision is transform, an approval block is permitted only on deny, a reason must never use the reserved host_error: prefix, and evidence is capped at 10,240 canonical bytes. Anything malformed, and any interceptor that throws or times out, becomes a synthesized deny with a reserved reason such as host_error:verdict_invalid or host_error:interceptor_failed. A crashing control fails closed, never open.