Skip to main content
Identity answers who an agent is. Bounded authority answers what it may do with money. In A-Identity, a limit you set on an agent is not a suggestion. It is enforced in three independent ways, so no single layer failing can move value it shouldn’t. A human in the tower sets the policy and approves anything above it.
Three cards: server pre-check labelled advisory, on-chain policy vault labelled source of truth, and Circle Agent Wallet labelled hosted screening

The three layers side by side, with the module each one lives in. Layer 2 is the source of truth because the USDC sits inside the contract, so the cap is enforced by code rather than by a server that could be bypassed. Layers 1 and 3 are a pre-check and a hosted screen around it.

Three independent enforcement layers

1

Server policy engine (pre-check)

The fast first gate: daily cap, auto-approve ceiling, payee allowlist, freeze, and the human-approval requirement. Resets at 00:00 UTC. This is a check, not the source of truth: it is the fallback, not the guarantee.
2

On-chain policy vault (the source of truth)

Each agent can get its own AgentSpendPolicy contract on Arc that holds the USDC and enforces the same policy on-chain. An over-limit pay() reverts on Arc with a typed error you can read on the explorer, not a server “no”. The human owner can override an approved payment, adjust limits, freeze, or withdraw.
3

Circle Agent Wallet (hosted screening)

Optionally, the agent’s USDC lives in a Circle Developer-Controlled Wallet whose hosted policy engine screens every transfer at the wallet layer (sanctions, address allow/block, freeze). A screening denial is authoritative.
At settlement, executeInstruction routes a payment vault, then Circle, then direct, each additive with a fallback, so one layer hitting an infra error never fabricates a success, and a real policy rejection always stops the payment.

The money shot: an on-chain revert

The difference between a demo and a product is where the “no” comes from. Here it comes from the chain:
An agent that tries to overspend doesn’t get a server error page. Its transaction reverts on Arc, verifiably, for anyone to check.
Owner vs operator. The vault’s owner is a human wallet (sets policy, overrides, freezes, withdraws). The operator is the agent’s signer (may only pay within policy). They are genuinely separate keys, and the agent can never change its own limits.

What an owner should know about the limits

  • The cap is a calendar day. It resets at 00:00 UTC, so up to twice the cap can go within seconds around that time. With a cap that does not change, the agent’s payments reach at most 2x the cap between any two moments up to 24 hours apart. Lowering the cap does not undo today’s spending, so to stop an agent now, freeze the vault.
  • An owner payment counts toward the agent’s day and can stop the agent until 00:00 UTC, unless the owner raises the cap. A withdrawal does not count.
  • setPolicy writes both limits and the allowlist setting in one call, so a caps change that sends false turns the allowlist off. The list survives, so turning it on again restores it.
  • 0 means no limit, not no spending, on the cap, the ceiling and the end date. The vault page and our backend refuse it; the contract accepts it.
  • The end date belongs to the vault, not to one key. A new end date after a revoke turns the same key back on, and a new key keeps the end date already there. If a key may have leaked, replace it first: that alone stops it.
The integration guide has the details, and the page holds a warning at each of these.

What each layer actually enforces

See it on the explorer

Provision a vault from the Permissions screen, then watch an over-limit payment revert on Arc testnet.