R-01 · allow-list
What this agent may call at all
A named set of tools. Anything absent from it is not permitted, by omission rather than by an explicit refusal.
allowcrm.contact.read
Allow-lists, deny rules and thresholds, bound to one agent and versioned. A deterministic engine reads them and records which rule decided. The point is not that it is clever - the point is that it is reproducible.
The same request against the same policy version produces the same decision, every time. A control that can be talked into a different answer is not a control, and one you cannot reproduce afterwards is not evidence.
The decision engine reads policy; nothing in a request can soften what it says. There is no risk parameter in the evaluate request - the engine computes risk_score itself.
An agent with no applicable policy binding does not fall through to allow. The absence of a rule is not a rule that permits.
Policies are data evaluated by the shipped engine, not a sandbox that runs code you supply. That is a smaller surface on purpose.
Everything a policy can say is one of these three, which is what keeps the evaluation order small enough to hold in your head.
R-01 · allow-list
What this agent may call at all
A named set of tools. Anything absent from it is not permitted, by omission rather than by an explicit refusal.
allowcrm.contact.read
R-02 · deny rule
A refusal that outranks the list
Evaluated before the allow-list, so a tool can be generally permitted and still refused for a specific shape of call.
blockbulk_export where record_count > 1000
R-03 · threshold
A boundary on a computed value
Risk score, amount, record count. Crossing it sends the call to a human instead of resolving it either way.
holdrefund_amount > 5000
Six months later somebody asks why an agent was allowed to do something. With policy_id and policy_version on the record you can point at the exact policy content that was enforced. With only the display name you can point at whatever it has since been renamed to.
decision_source is what separates “policy refused this” from “the agent was contained and policy was never reached”. During an incident that distinction is the whole answer.
It is not a model. No LLM participates in the authorization decision, and no prompt can change one.
It is not a policy language runtime you extend. Policies are data evaluated by the shipped engine.
It does not take risk from the caller. There is no risk field in the request. The engine computes the score.
It does not fall through to allow. No applicable binding is a refusal, not a default permission.
Private access
We will write the policy for it in front of you and show you what the decision records.