Skip to content

Lifecycle & rollout

Policy changes are versioned, staged, and reversible. Nothing you author can break the hot path, and everything that ever governed a call stays provable forever.

draft ──▶ shadow ──▶ active ──▶ retired
▲ │ │
└─────────┴──────────┘ pull-back (if never governed)
State Meaning
draft Editable. Not evaluated.
shadow Evaluated on real traffic, results recorded in decision evidence, never blocks.
active Enforced. Exactly one active version per policy.
retired Superseded. Immutable provenance — audit records still reference it.

Two lock-in rules keep history honest:

  • Publishing probe-compiles the version and recompiles every reached agent’s bundle inline. Failure aborts the publish; the previous version stays active.
  • A version that governed a real call is hard-locked. It cannot be pulled back to draft or deleted — it is part of the audit trail’s provenance. You supersede it; you don’t erase it.

Shadow exists at two granularities:

  • Version-level — set the whole version to shadow status to evaluate it against live traffic with zero enforcement.
  • Rule-level — individual rules carry mode: shadow inside an active version. Their would-have-fired results land in decision.evidence.shadow.

The workflow: add rules in shadow → inspect shadow evidence on real sessions → flip to enforce → publish.

  1. Draft the change (new version of an existing policy — drafts fork the current state).
  2. Preview impact: GET /api/v2/policies/{id}/publish-impact shows which agents the publish recompiles.
  3. Publish: the previous active version retires atomically; superseded_version_id is recorded.
  4. Monitor: blocked/warned calls surface in the activity feed and audit trail within seconds.
  5. Roll back with pull-back if needed — the superseded version is restored to active.
Terminal window
tappass policy v2 version list <policy-id>
tappass policy v2 version publish <policy-id> <version-no>
tappass policy v2 version pull-back <policy-id> <version-no>
tappass policy v2 version diff <policy-id> --from 3 --to 4

Policies attach at orgprojectteamagent. Composition unions all applicable layers; on conflict the more specific scope wins, and numeric caps merge as the strictest value. Assignments can be time-bounded:

Terminal window
tappass policy v2 assignment create <policy-id> --scope-type project --scope-id <project> \
--effective-until 2026-08-01T00:00:00Z # optional expiry
tappass policy v2 agent assignments <agent-id>

Typical topology:

Scope What lives there
org Baseline: injection blocking, secrets, model allowlist
project Product-specific limits: budgets, tool constraints
team Team-owned tool access
agent Exceptions and tight envelopes for sensitive agents

The agent’s effective policy is the compiled bundle — inspect it any time:

Terminal window
tappass policy effective <agent-id> # resolved rules
tappass policy explain <agent-id> --event-type TOOL_CALL --input '{"tool":"send_email"}'

explain evaluates a hypothetical call against the current bundle and shows which rules fire — the fastest way to answer “why would this block?” without touching production traffic.