Skip to main content

Gates

Every scored event produces one gate decision and one enforcement action. The API answers synchronously. What it does not do is withhold anything: the producer holds the output, and the SDKs make that the default.

The four statuses

Seed thresholds, from policy version 1. Your org's active policy may differ; the digest on every record says which numbers were in force.

GateBIIWhat VIGIL recordsWhat the producer must do
passat or above 0.75An enforcement action with requires_human_review: falseLet the output propagate.
hold0.60 to 0.7499An action flagged for human review; a gate.hold webhookWithhold the output. Show the user the review path. Wait for a reviewer or a timeout you choose.
alert0.41 to 0.5999An action flagged for review and escalation; a gate.alert webhookWithhold the output. Treat as an incident: page the on-call reviewer.
collapseat or below 0.40An action flagged for review; composite trust forced to 0; a gate.collapse webhookWithhold the output. Stop the agent's further actions until a reviewer decides.

requires_human_review is true for hold, alert and collapse.

Honoring the gate

The contract is the same on every surface. The API returns gate_status and action_id. The producer either honors the gate or records that it did not.

  • Python and TypeScript SDKs: gate.honor() raises HeldOutput on hold, alert or collapse. honor(allow_propagation=True) lets the output through after emitting an output_generated event with source: "vigil" and {"gate_ignored": true, ...}, so the override is on the ledger.
  • Claude Code hooks: PreToolUse exits 2 and the tool does not run.
  • OpenAI Agents SDK: the output guardrail trips and the SDK raises instead of returning the output.
  • LangGraph: hook.last_gate.held is set; you park the result.

What happens to a held action

A held action stays pending until a reviewer decides it through vigil-gate, a separate service with its own database role. Outcomes are released, rejected or escalated. The decision is terminal and appends a review record to the org's ledger chain.

Your code learns the outcome one of two ways:

  • Poll GET /enforcement/{action_id} and read review_outcome. The SDKs wrap this as wait_for_release(action_id, timeout).
  • Subscribe a webhook to review.released, review.rejected, review.escalated.

Which gate is an agent under right now

curl -sf -H "Authorization: Bearer $VIGIL_KEY" "$VIGIL_URL/enforcement/agent/docs-quickstart/latest"

The latest action's gate_status is the agent's current gate. review_outcome is null while a hold is pending. Run the quickstart first so the agent has an action.