Policies, rules & bundles
A policy is a versioned set of rules. Each rule is one statement like “block PII above threshold 0.6” or “only allow models from this list”. Assigned policies compile together into one bundle per agent; the kernel evaluates that bundle on every call.
Anatomy
Section titled “Anatomy”Policy ──▶ PolicyVersion (draft → shadow → active → retired) │ └── PolicyRule[] — kind + params + mode (enforce | shadow) │ ▼ compile compiled rule ──▶ per-agent bundle ──▶ kernel- Params — the threshold, the model list, the domain allowlist. Same kind, many rules.
- Mode —
enforce(decides) orshadow(evaluated and recorded in the decision’s evidence, never blocks). Shadow is how you prove a rule before you trust it.
Assignment scopes
Section titled “Assignment scopes”Policies attach to the org tree at four levels:
| Scope | Applies to |
|---|---|
org |
every agent in the organization |
project |
agents in one project |
team |
agents owned by one team |
agent |
one agent |
An agent’s governance is the union of all policies assigned up its tree. Scopes compose in precedence order (org first, agent last); on conflict the more specific scope wins. Assignments can be time-bounded (effective_from / effective_until) — e.g. a stricter policy for an incident window.
The bundle
Section titled “The bundle”Composition produces one artifact per agent:
package tappass.policy— the merged rules from every assigned,activepolicy version, plus the merge resolver.- Sidecar data — per-rule payloads, origin, kind, order, and mode, so the decision evidence can name exactly which rule fired.
- Content addressing — each bundle is content-addressed, and every audit record carries the hash that decided it, which is what makes decisions replayable.
Composition happens eagerly: publishing a policy version recompiles every reached agent inline and fails loudly if any agent’s bundle doesn’t compile. A broken policy can never reach the hot path.
Merge semantics
Section titled “Merge semantics”All rules across all layers vote; the resolver applies:
- Rules ordered by composition order (scope precedence, then rule ordinal).
- First blocking rule wins — the decision names it, with all other violations in
evidence.all_reasons. - Shadow rules never vote; their would-have-fired results are recorded under
evidence.shadow. - Numeric caps (
MaxTokensPerRequest,MaxTokensPerDay) merge as the minimum across layers — the strictest applicable limit wins. - No blocking rule →
allow(the org’s configureddefault_action).
Rules can’t call out
Section titled “Rules can’t call out”Rules cannot call out; everything is supplied in the policy input, which keeps evaluation fast and replayable.
No hidden floor
Section titled “No hidden floor”The kernel composes no hardcoded safety policy. A fresh org starts empty: nothing blocked, everything audited. Every block in every audit record traces to a rule someone in your org wrote and activated. Combined with fail-closed evaluation (missing bundle → block), you get both properties: nothing enforced you didn’t ask for, and nothing silent when enforcement breaks.
Next steps
Section titled “Next steps”- Authoring policies — create your first policy
- Lifecycle & rollout — draft → shadow → active, safely