Policies
A policy is a set of rules attached to an agent that Canopy evaluates before every payment. You configure policies in the dashboard. Every call to pay(), preview(), and fetch() passes through the agent's policy.
If no policy is attached to an agent, the agent has no cap and can pay any recipient. Always attach a policy before exposing an agent to untrusted inputs.
The three controls
Spend cap
A spend cap limits how many USD an agent can spend within a rolling time window.
Example:
$10 / 24hlets the agent spend up to $10 total across any 24-hour window. Once the cap is hit, furtherpay()calls returndeniedwithreason: "Spend cap exceeded".
Use budget() to inspect remaining headroom before an expensive operation. See Budget management for examples.
Service allowlist
An allowlist restricts which paid services an agent can call. Allowlists key on service slugs (e.g. openai, browserbase) — the canonical identifiers in Canopy's registry. At sign time, the realm of the runtime 402 is mapped to a service slug; if the slug isn't on the agent's allowlist (or covered by an allow-listed category), pay() / fetch() returns denied.
Allowlist entries accept:
- Service slugs — e.g.
openai,browserbase,agentmail - Categories — e.g.
data,compute,api(any current or future service in that category is permitted)
The allowlist also filters discover() results. By default, only allowed services come back — pass includeBlocked: true (TS) or include_blocked=True (Py) to see blocked entries with policyAllowed: false.
Note: per-address allowlists were removed when the registry moved to service-keyed identity. The registry is now the trust boundary — a 402 from a realm not in the registry is denied at sign time, regardless of the recipient address.
Approval threshold
Payments above the approval threshold are not auto-executed. pay() returns pending_approval and the payment waits for a human to approve or deny in the dashboard.
Example: an approval threshold of
$5means any single payment above $5 requires a human decision. The agent receives anapprovalIdit can poll orwaitForApproval()on.
See Payment outcomes for how to handle pending_approval in code.
Configuring a policy
- Open the agent in the dashboard
- Click Policy settings
- Set the cap (amount + window), allowlist, and approval threshold. Any field left blank is unconstrained.
- Save
Changes take effect immediately. The next pay() from that agent uses the updated policy.
Previewing policy evaluation
Use preview() to dry-run the policy without signing or spending anything. Returns the same shape as pay():
const result = await canopy.preview({ to: "0x4838B106FCe9647Bdf1E7877BF73cE8B0BAD5f97", amountUsd: 7.50 });
if (result.status === "denied") console.log("Would be blocked:", result.reason);result = canopy.preview(to="0x4838B106FCe9647Bdf1E7877BF73cE8B0BAD5f97", amount_usd=7.50)
if result["status"] == "denied":
print("Would be blocked:", result["reason"])