Policies

Spending policies are guardrails that constrain what an autonomous agent can do with its wallet. Before deploying any agent with real funds, configure a policy.

Why policies matter

An autonomous agent with unconstrained wallet access is a liability. A bug, a prompt injection, or a runaway loop can drain a wallet in seconds. Policies let you define hard limits that the orbserv platform enforces server-side — your code cannot override them.

Policy fields

| Field | Type | Description | |-------|------|-------------| | dailyLimit | string | Maximum USDC to spend per rolling 24-hour window | | maxPerTx | string | Maximum USDC per individual transaction | | allowedDomains | string[] | Whitelist of domains for x402 payments (empty = all allowed) | | allowedTokens | string[] | Tokens the agent may spend (default: ['USDC']) | | allowedChains | Chain[] | Chains the agent may use | | paused | boolean | If true, all spending is blocked |

Getting the current policy

const agent = await orb.wallet.get(walletId)
const policy = await agent.policy.get()
 
console.log(policy)
// {
//   dailyLimit: '100.00',
//   maxPerTx: '10.00',
//   allowedDomains: ['api.openai.com'],
//   allowedTokens: ['USDC'],
//   allowedChains: ['base'],
//   paused: false,
// }

Updating a policy

await agent.policy.update({
  dailyLimit: '10.00',
  maxPerTx: '2.00',
  allowedDomains: ['api.openai.com', 'api.anthropic.com'],
  allowedChains: ['base'],
})

Updates are partial — only fields you provide are changed. To clear allowedDomains (allow all domains), pass an empty array:

await agent.policy.update({ allowedDomains: [] })

Pausing and resuming

Use pause() to immediately block all spending without deleting the wallet:

await agent.policy.pause()
// All transactions will now fail with 403 PolicyViolation

Resume when ready:

await agent.policy.resume()

Example: $10/day agent

A minimal safe configuration for a research agent with a tight budget:

import { OrbWallet } from '@orbserv-labs/orb-wallet'
 
const orb = new OrbWallet({ apiKey: process.env.ORB_API_KEY! })
const agent = await orb.wallet.get(process.env.AGENT_WALLET_ID!)
 
await agent.policy.update({
  dailyLimit: '10.00',
  maxPerTx: '1.00',
  allowedTokens: ['USDC'],
  allowedChains: ['base'],
  allowedDomains: [
    'inference.orbmarket.co',
    'search.orbmarket.co',
  ],
})
 
console.log('Policy applied. Agent is ready.')

Policy violations

When an agent exceeds its policy, the SDK throws a PolicyViolationError:

import { PolicyViolationError } from '@orbserv-labs/orb-wallet'
 
try {
  await agent.send({ to: '0x...', amount: '50.00', token: 'USDC', chain: 'base' })
} catch (err) {
  if (err instanceof PolicyViolationError) {
    console.error('Blocked:', err.reason)
    // e.g. "Transaction exceeds dailyLimit of $10.00 (used: $9.50)"
  }
}

Covenant integration

orbserv policies are enforced server-side by the platform. For an additional client-side gate, you can configure the SDK to call a Covenant daemon before each spend is signed. The daemon checks capability, per-call cap, and budget, then returns a decision_id for audit correlation.

When covenant.perCallCap is omitted, the SDK uses the wallet's maxPerTx as the per-call cap. Updating the policy invalidates the cached cap so authorizations always reflect the current bound.

See Covenant Spend Authorization for setup, configuration, settlement recovery, and error handling.