Skip to content
Oris Docs

Spending policies

LIVE

Every agent payment passes through the L2 policy engine before any rail hears about it. Six rule primitives compose the envelope. Evaluation latency is well under ten milliseconds at p95.

The six rules

RuleWhat it checks
max_per_txSingle-transaction ceiling in USD.
max_dailyCumulative spend in the configured timezone day.
max_monthlyCumulative spend in the configured timezone month.
counterparty_whitelistDestination address or domain allowlist.
allowed_categoriesMerchant category restrictions.
escalation_thresholdAbove this amount, route to human approval.

Combine them to draw a precise envelope. A procurement bot can be capped at fifty dollars per transaction, five hundred per day, restricted to a specific vendor list, and escalated above two hundred dollars.

Performance

Stepp95
Policy cache read< 1 ms
Rule evaluation< 3 ms
Counter atomic update (Lua)< 2 ms
Audit log write< 4 ms
Total< 10 ms

The cache is invalidated atomically on every policy update. There is no propagation delay between dashboard edit and live enforcement. Counters are atomic Lua scripts so concurrent payments do not race.

SDK methods

# Create a policy
policy = client.policies.create(
agent_id=agent.id,
max_per_tx=50.00,
max_daily=500.00,
max_monthly=5000.00,
allowed_categories=["cloud_compute", "api_consumption"],
counterparty_whitelist=["0xA1b2...", "0xC3d4..."],
escalation_threshold=200.00,
)
# Pre-evaluate without sending (optional; payments.send does it inline)
verdict = client.policies.evaluate(
agent_id=agent.id, to_address="0xA1b2...", amount=12.50, category="api_consumption",
)
# Update a rule
client.policies.update(policy.id, max_daily=750.00)

Escalation flow

When a payment exceeds escalation_threshold, the engine returns an escalated verdict instead of allow. The payment is held in a pending state until a human approver signs off through the dashboard or the escalation API. Approval signatures are recorded in the audit log.

Versioning

Every update produces a new policy version. The Merkle root commits on-chain to OrisL2PolicyRegistry on Base. Every bundle records the policy version that authorized it, so a verifier can reconstruct the exact rule set in effect at payment time.

Rollback is a forward edit; restore the previous configuration and the next evaluation uses it. The historical chain stays.

Where to go next