CAIN-42 CAIN Studio

Developer documentation

Policies

Last reviewed 31 August 2026

All docs

Default deny#

cain init writes policy.default: deny. Anything without an explicit rule is refused. This is the point of the platform; change it deliberately, and `cain doctor will warn you for as long as it is allow.

policy:
  default: deny

Where policy is evaluated#

Policy is evaluated server-side, by the fabric, from the tenant resolved from your credential. It is not evaluated in the SDK and cannot be influenced by anything the caller sends -- an agent cannot raise its own ceiling.

Inspecting and testing#

cain policy show
cain policy test --action /refund --resource billing
cain policy test --action /refund --resource billing --payload '{"amount":100000}'

policy test is a dry run: it evaluates and reports, with no enforcement and no side effects. Use it to answer "would this be allowed?" before shipping a change.

Policy versions#

Every decision records the policy version that produced it, captured at decision time rather than looked up later. That is what keeps an old decision explainable after the policy changes -- resolving the version at explain-time would describe today's policy while claiming to explain last month's decision.

cain explain <decision-id>     # shows the policy version column

Tool restrictions#

tools:
  allow: [send_email, read_crm]
  deny:  [delete_customer]

An empty allow list means "no tool-level restriction *here*" -- server-side policy still applies. It does not mean everything is denied. cain doctor warns when both lists are empty, because "no restriction configured" is easy to mistake for "restricted".

Requiring a human#

policy:
  require_approval_above_risk: high

Produces the REQUIRE_APPROVAL verdict rather than ALLOW or DENY. Note that decision.allowed is false for REQUIRE_APPROVAL -- the action must not proceed while approval is outstanding.