# Guardrail vocabularies

Every closed enum the guardrail layer speaks, one table each, cross-linked to the page that explains it.

Source: https://tokentriage.com/docs/reference/guardrail-vocabularies

---
import Callout from '../../../components/Callout.astro';
import NextSteps from '../../../components/NextSteps.astro';

Every classification the guardrail layer emits is a **closed vocabulary**: a member is named, or
the value is refused. The enums are additive-only — a member is never quietly dropped, which is why
two of them below carry a value with no producer in this build.

## Category

What a binding declares it is about. Nine members; **seven have a detector in this build**.

| Value | Detectors in this build |
|---|---|
| `pii` | nine embedded `pii.*` plus `sidecar.ner_pii` |
| `secrets` | `secrets.entropy`, `secrets.generic`, `secrets.ruleset` |
| `injection` | `injection.heuristic`, `injection.judge`, `sidecar.injection` |
| `toxicity` | `toxicity.wordlist`, `sidecar.safety` |
| `topical` | `topical.keywords` |
| `code` | `code.patterns` |
| `multimodal` | `media.inventory` |
| `format` | **none** |
| `custom` | **none** — only the `drill.echo` stub registers here |

<Callout type="key">
**The category vocabulary is the closed set the *ledger* speaks, not a claim about what the binary
can find.** Empty detector lists are rejected; a binding must name registered detectors of the
matching category. `custom` is where
your own detector would register; `format` is reserved for output-shape validation this build does
not ship. See the [detector inventory](/docs/reference/guardrail-detectors).
</Callout>

**`injection` is the only *adversarial* category in this build**, and that has a hard consequence:
no interval is ever rendered for it, at any basis. Attacker-chosen traffic is out-of-distribution
by intent, so the exchangeability a conformal or binomial bound assumes is false for it.

## Phase

| Value | What it inspects |
|---|---|
| `input` | the request, before the model |
| `output` | the buffered, non-streaming response |
| `stream` | the response incrementally, on the tap's guard lane |

A detector *declares* which phases it supports. **Binding one to a phase it does not declare is
refused at boot** — the process does not start. See
[Phases & streaming](/docs/guardrails/phases-and-streaming).

## Locality

| Value | What it is | Leaves the process? |
|---|---|---|
| `embedded` | pure Go, in-process | **no** — the subtree is import-restricted |
| `judge` | an LLM call to a configured judge model | **yes**, and refused at boot without `guardrails.judge.external: allow` |
| `sidecar` | an HTTP classifier protocol | **yes** in a custom embedding; stock activation is rejected pending runtime/model qualification |

A consented judge also follows the [activation and budget restrictions](/docs/guardrails/air-gap-and-limits).

## Mode

| Value | Meaning |
|---|---|
| `enforce` | selected supported actions may change or suppress bytes; incomplete protection follows failure posture |
| `monitor` | the guard runs and discloses, and **changes no byte** |
| `simulate` | **not a configurable mode.** It is the stamp the off-path dry-run puts on its own report |

<Callout type="warning">
Writing `mode: simulate` in a binding is refused by validation:
`mode 'simulate' is the off-path simulate API's stamp, never a configured mode`. Simulation is a
property of a *report*, not of a policy. See
[Proving it before you arm it](/docs/guardrails/proving-it-before-you-arm-it).
</Callout>

## Severity

`low` · `medium` · `high` · `critical` — the rungs a `ladder` maps to verbs. `severity_bands` sets
the score cut-points. With no bands configured every finding lands at `low`, which is exactly what
the one-rung `action:` sugar means.

## Posture (`on_error`)

| Value | Meaning |
|---|---|
| `open` | a detector that cannot run degrades to a **disclosed suspension** and traffic flows. The default |
| `closed` | enforcing mode withholds affected unreleased bytes on protection failure; monitor preserves traffic. **Requires `fail_closed_ack`** |

## Verb

The action table is canonical and the **reversibility bit is derived from it, never authored**.

| Verb | Mutates bytes? | Reversible? | Terminal? | Phases |
|---|---|---|---|---|
| `observe` | no | no | no | all |
| `warn` | no | no | no | all |
| `block` | no — it *suppresses* | no | **yes** | all |
| `redact` | yes | **no** | no | all |
| `mask` | yes | **no** | no | all |
| `tokenize` | yes | **yes** (vault round-trip) | no | all |
| `pseudonymize` | yes | **yes** | no | all |
| `rewrite` | yes | no | no | output |
| `reask` | no | no | no | output |
| `reidentify` | yes | **yes** | no | output, stream |

This is vocabulary, not a stock activation table. `rewrite` and `reask` are rejected;
`reidentify` is engine-internal and its automatic reverse leg is buffered-output only. See
[Verbs & effects](/docs/guardrails/verbs-and-effects) for supported activation and effects.

## Effect

**What actually happened to the bytes** — not the same thing as the verb.

| Value | Meaning |
|---|---|
| `mutated` | bytes were changed |
| `blocked` | content was suppressed |
| `annotated` | the fire was recorded and nothing changed — `monitor` mode's effect; read execution and transformation receipts for incomplete work |
| `warned` | allowed, with a disclosure |
| `reasked` | **no producer in this build.** You will not see it on a row |

## Suspension reason

**The field to alert on.** A suspension can identify incomplete extraction, detector execution or
transformation; it does not by itself prove zero inspection or zero released bytes. Read the
execution stage and delivery receipt.

| Value | Meaning |
|---|---|
| `detector_timeout` | the detector exceeded its own bound |
| `budget_exceeded` | a work budget was exhausted: cumulative embedded detector time or bounded external call/byte/concurrency work; inspect the execution stage |
| `detector_error` | the detector returned an error — including the **oversize-input refusal** at 128 KiB (embedded) and 32 KiB (judge) |
| `detector_panic` | the detector panicked and was contained |
| `sidecar_down` | the configured sidecar could not be reached |
| `judge_unavailable` | the configured judge could not be reached |
| `cost_ceiling` | a spend ceiling stopped the call |
| `invalid_span` | a proposed span or transformation could not be applied safely; read the execution stage and binding/detector attribution |
| `uninspectable_body` | the body carries no seam this detector can read — how a `no-media` binding discloses on `bedrock` and `gemini` |
| `stream_unsupported` | the detector declares the stream phase but implements no incremental matcher; the binding took its `stream_fallback` |
| `stream_window_exceeded` | a match's span exceeded the stream matcher's retention bound |
| `scan_exhausted` | a bounded scanner could not complete coverage |
| `internal_error` | an unclassified internal fault |
| `caller_canceled` | **the one that is not about your configuration** |

<Callout type="warning">
**`caller_canceled` means the request context was canceled.** Cancellation can arrive before
inspection or after local work, an external send or partial stream delivery. Read execution,
invocation and delivery receipts to determine what actually happened; this reason alone proves
neither zero work nor zero released bytes. Raising `local_budget_ms` does not repair caller
cancellation. Investigate client and network behavior separately from detector budget exhaustion.
</Callout>

## Stream fallback

What a stream-phase binding does when the framing is not guardable. Whichever you choose, **the row
discloses it**.

| Value | Meaning |
|---|---|
| `monitor` | disclose missing coverage and apply the effective mode and failure posture; does not override enforcing `on_error: closed`. **The default** |
| `buffer` | recognized syntax, rejected by stock gateway activation; no stock full-stream buffering |
| `closed` | suppress unreleased bytes in enforcing mode; requires `fail_closed_ack`. Monitor mode preserves traffic |

## Confidence basis

| Value | Meaning | May carry an interval? |
|---|---|---|
| `exact` | a deterministic validator passed; point is 1.0 by construction | no |
| `fixture` | this detector **version's** measured precision on a seeded corpus | no |
| `calibrated` | a calibration artifact licenses the bound | **yes — and only this one** |
| `reported` | the detector's raw score, explicitly unlicensed | no |
| `insufficient` | a refusal: no number at all | no |

<Callout type="key">
**An interval exists if and only if a calibration artifact id is beside it.** Both directions are
enforced, at the write boundary and again on every read surface. An envelope that violates it is
**refused and counted** in `confidence_refused`, never downgraded into a bare number — so "this
detector reported no confidence" and "this layer declined to record the confidence it reported" are
different facts on the row. See [Confidence](/docs/guardrails/confidence).
</Callout>

<NextSteps items={[
  { title: "Ledger fields", href: "/docs/reference/ledger-fields", description: "Where these values land on a decision row, including the disclosures.guardrails block." },
  { title: "Configuring a guard", href: "/docs/guardrails/configuring-a-guard", description: "The binding schema that names most of these enums." },
  { title: "Guardrail detectors", href: "/docs/reference/guardrail-detectors", description: "Which detectors exist under each category, and on which phases." }
]} />
