SpendOS

Spending controls for autonomous AI agents

Base Mainnet — Live

SpendOS is autonomous financial enforcement infrastructure for AI agents on Base. Owners define a spend policy — daily limits, per-transaction caps, domain allowlists, and risk mode. Agents spend within those rules. Every payment is enforced on-chain by the SpendOSVault smart contract.

No agent can exceed its policy. No payment settles without matching the owner-signed policy digest stored on-chain. When a rule is violated, the payment is blocked — not just logged.

Chain

Base (8453)

Asset

USDC

Protocol

x402 (HTTP 402)

Agent Interface

SDK + MCP (16 tools)

How It Works

SpendOS sits between an autonomous agent and the APIs it wants to pay for. Every payment request flows through three layers: policy check, on-chain enforcement, and receipt logging.

1

Owner sets policy

Daily limit, per-transaction cap, allowed domains, allowed contracts, risk mode. Policy digest is signed and stored on-chain via SpendOSVault.

2

Agent calls a paid API

The API endpoint returns HTTP 402 Payment Required with payment requirements — amount, domain, contract address.

3

SpendOS checks policy

Proxy evaluates the request: Is the domain allowlisted? Is the amount within limits? Is the agent paused? Risk score updated.

4

On-chain settlement

SpendOSVault verifies operator authorization, checks daily limit, checks per-transaction limit, and transfers USDC to the recipient.

5

Receipt issued

A ReceiptRecorded event is emitted on-chain. The proxy returns a receipt ID. Agent retries the original request with X-Payment: spendos:{receiptId}.

6

API responds

The API verifies the receipt and returns the data. The spend is logged in the audit ledger.

Quickstart

1. Install

npm install

2. Configure

Create .env.local in the project root:

SPENDOS_DEPLOY_NETWORK=base
CHAIN_ID=8453
BASE_RPC_URL=https://mainnet.base.org
PRIVATE_KEY=0x...
SPENDOS_VAULT_ADDRESS=0x...
USDC_ADDRESS=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
SPENDOS_REQUIRE_AUTH=true
SPENDOS_API_KEYS=spos_live_...

Create config.local.js for the frontend (gitignored):

window.SPENDOS_CONFIG = {
  apiKey: "spos_live_...",
  proxyUrl: "http://127.0.0.1:4191",
  vaultContract: "0x...",
  network: "base",
  chainId: 8453,
};

3. Start

npm start

Starts three services:

  • Frontend UI → http://127.0.0.1:4180
  • Proxy API → http://127.0.0.1:4191
  • x402 demo API → http://127.0.0.1:4192

4. Run the demo agent

npm run demo:agent

The demo agent calls three paid endpoints via x402, paying real USDC on Base mainnet for each one. Each run costs ~0.23 USDC and produces three on-chain transactions.

Check launch readiness

curl "http://127.0.0.1:4191/v1/launch/readiness?agentId=research-agent"
{
  "status": "ready",
  "score": { "passed": 7, "total": 7 }
}

x402 Payment Flow

SpendOS implements the x402 protocol — a standard for HTTP-native API payments. When an agent hits a paid endpoint, the server returns 402 Payment Required with payment requirements. The agent pays through SpendOS and retries with a receipt header.

402 Response

HTTP/1.1 402 Payment Required
Content-Type: application/json

{
  "error": "payment_required",
  "payment": {
    "domain": "api.tokensight.io",
    "contract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "amount": 0.05,
    "currency": "USDC",
    "network": "base"
  }
}

Auto-payment with the SDK

const result = await spendos.fetch402("http://api.tokensight.io/v1/token-price", {
  task: "Get ETH price for portfolio rebalancing",
});

// result.data     — the API response
// result._payment — receipt id, tx hash, amount spent

Manual payment flow

// 1. Check policy
const check = await spendos.checkPolicy({
  domain: "api.tokensight.io",
  contract: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  amount: 0.05,
  task: "Token price lookup",
});

// 2. Pay
const payment = await spendos.payX402({
  domain: "api.tokensight.io",
  contract: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  amount: 0.05,
  task: "Token price lookup",
  idempotencyKey: "price-lookup-001",
});

// 3. Retry original request with receipt
fetch("http://api.tokensight.io/v1/token-price", {
  headers: { "X-Payment": `spendos:${payment.receiptId}` }
});

Policy Engine

Every agent has a policy file — a JSON document defining its spend authority. The SHA-256 digest of this policy is signed by the owner and stored on-chain. The proxy enforces the policy off-chain; the vault enforces limits on-chain.

Policy fields

{
  "agentId": "research-agent",
  "dailyLimit": 10,
  "perTransactionLimit": 0.25,
  "domains": [
    "api.tokensight.io",
    "risk.baseintel.net",
    "decode.calldata.run"
  ],
  "contracts": [
    "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "0x4200000000000000000000000000000000000006"
  ],
  "riskMode": "adaptive",
  "paused": false
}

Risk modes

  • monitor — Log all spend, never block.
  • adaptive — Block high-risk payments, approve normal ones.
  • strict — Block anything outside explicit allowlists.
  • enforce — Every payment requires owner approval.

Approval queue

When a payment is blocked by policy (domain not allowlisted, amount over limit, high risk score), it enters the approval queue. The owner can approve or deny via the UI or the resolve_approval MCP tool.

SpendOSVault Contract

SpendOSVault is a minimal, dependency-free Solidity contract deployed on Base. It enforces all spend rules on-chain — no off-chain enforcement can be bypassed.

What it enforces

  • Per-transaction USDC limit — rejects any single payment above the cap
  • Rolling 24-hour daily limit — tracks spend in a sliding window
  • Owner-signed policy digest — payment calldata must match the stored digest
  • Operator delegation — only the authorized operator signer can call spendUSDC
  • Pause state — owner can suspend an agent instantly
  • ReceiptRecorded event — every approved payment emits a verifiable on-chain receipt

Key functions

// Register an agent vault
function registerAgent(address agentVault) external

// Fund agent with USDC
function fundAgent(address agentVault, uint256 amount) external

// Authorize a new spend policy
function authorizePolicy(
  address agentVault,
  bytes32 policyDigest,
  uint256 dailyLimit,
  uint256 perTxLimit,
  bytes calldata signature
) external

// Set operator (proxy signer)
function setOperator(address operator) external

// Execute a payment (operator only)
function spendUSDC(
  address agentVault,
  address recipient,
  uint256 amount,
  bytes32 receiptHash,
  bytes32 policyDigest
) external

// Emergency pause
function pauseAgent(address agentVault) external
function resumeAgent(address agentVault) external
Base Mainnet: 0xC3C474a7917eCFDE5A25B64A58a190f901F9241A
Contract source is in contracts/SpendOSVault.sol — no external dependencies, no upgradability proxy.

Agent SDK

A lightweight ESM client for the SpendOS proxy. Use it in custom agents, backend workers, MCP servers, or any Node.js environment.

Install

import { SpendOS } from "./sdk/spendos-agent.mjs";

const spendos = new SpendOS({
  baseUrl: "http://127.0.0.1:4191",
  agent: "research-agent",
  apiKey: "spos_live_...",
});

Budget flow

// Reserve budget before a multi-step task
await spendos.requestBudget({
  task: "Analyze 10 wallets for risk scoring",
  maxSpend: 1.00,
  idempotencyKey: "wallet-scan-2025-001",
});

// Check individual payments
const decision = await spendos.checkPolicy({
  domain: "risk.baseintel.net",
  contract: "0x4200000000000000000000000000000000000006",
  amount: 0.10,
  task: "Wallet risk score",
});

if (decision.status === "approved") {
  await spendos.payX402({ ... });
}

All methods

  • fetch402(url, options) — auto x402 pay and retry
  • requestBudget(payload) — reserve bounded budget
  • checkPolicy(payload) — evaluate before paying
  • payX402(payload) — authorize and record payment
  • updatePolicy(payload) — update limits, allowlists, risk mode
  • previewSettlement(payload) — build calldata without spending
  • preflightSettlement(payload) — on-chain read-only check
  • submitSettlement(payload) — submit on-chain transaction
  • getSettlementConfig() — vault readiness and operator status
  • getVaultStatus(options) — on-chain vault state
  • getLaunchReadiness(options) — 7-point launch check
  • getReceipts(options) — spend history
  • getApprovals(options) — pending or resolved approvals
  • resolveApproval(payload) — approve or deny a request
  • pauseAgent(options) — suspend spend authority
  • resumeAgent(options) — restore spend authority

Idempotency

Pass idempotencyKey on payment and budget calls when the agent might retry. SpendOS replays the original response instead of spending twice.

MCP Server

SpendOS exposes 16 tools via the Model Context Protocol. Connect Claude Desktop, Codex, or any MCP-compatible client to give AI models direct access to spend controls.

Config (Claude Desktop)

{
  "mcpServers": {
    "spendos": {
      "command": "node",
      "args": ["/path/to/spendos/mcp/spendos-mcp-server.mjs"],
      "env": {
        "SPENDOS_PROXY_URL": "http://127.0.0.1:4191",
        "SPENDOS_AGENT": "research-agent",
        "SPENDOS_API_KEYS": "spos_live_..."
      }
    }
  }
}

Available tools

get_agent_file

Policy, vault metadata, daily limits, policy digest.

request_budget

Reserve bounded USDC budget for a task.

check_policy

Evaluate a payment before authorizing.

update_policy

Update limits, allowlists, risk mode, pause state.

pay_x402

Authorize an x402 API payment on-chain.

preview_settlement

Build settlement calldata without spending.

preflight_settlement

Read-only on-chain preflight before submitting.

get_settlement_config

Vault readiness, operator status, function selector.

get_vault_status

On-chain policy, balance, paused state.

get_launch_readiness

Aggregated 7-point launch check.

submit_settlement

Submit vault settlement transaction.

get_receipts

Spend history for audit and accounting.

get_approvals

Pending or resolved approval requests.

resolve_approval

Approve or deny a pending spend request.

pause_agent

Suspend spend authority immediately.

resume_agent

Restore spend authority after review.

Proxy API

All requests require X-SpendOS-Key: spos_live_... except public paths (/health, /v1/ops/readiness, /v1/settlement/config).

Method Endpoint Description
GET/healthHealth check
GET/v1/agents/:idAgent policy and vault metadata
POST/v1/request_budgetReserve bounded USDC budget
POST/v1/check_policyEvaluate payment before authorizing
POST/v1/pay_x402Authorize and record payment
POST/v1/update_policyUpdate limits, allowlists, risk mode
POST/v1/settlement/previewBuild settlement calldata (read-only)
POST/v1/settlement/preflightOn-chain preflight check
POST/v1/settlement/submitSubmit on-chain settlement transaction
GET/v1/settlement/configVault readiness and operator status
GET/v1/vault/statusOn-chain vault state for an agent
GET/v1/launch/readinessAggregated 7-point launch check
GET/v1/receiptsSpend history for audit
GET/v1/receipts/:idSingle receipt verification
GET/v1/approvalsPending or resolved approvals
POST/v1/approvals/:id/resolveApprove or deny a request
POST/v1/pause_agentSuspend agent spend authority
POST/v1/resume_agentRestore agent spend authority

Example: check policy

curl -X POST http://127.0.0.1:4191/v1/check_policy \
  -H "Content-Type: application/json" \
  -H "X-SpendOS-Key: spos_live_..." \
  -d '{
    "agentId": "research-agent",
    "domain": "api.tokensight.io",
    "contract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "amount": 0.05,
    "task": "Token price lookup"
  }'
{
  "status": "approved",
  "reason": "within_policy",
  "riskScore": 12,
  "dailyRemaining": 9.77
}

Contract Addresses

SpendOSVault — Base Mainnet

0xC3C474a7917eCFDE5A25B64A58a190f901F9241A

USDC — Base Mainnet

0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913

WETH — Base Mainnet

0x4200000000000000000000000000000000000006

Chain ID

8453

Environment Variables

Variable Description
Network
BASE_RPC_URLBase mainnet RPC URL
CHAIN_IDChain ID (8453 for mainnet)
PRIVATE_KEYOwner/deployer private key
Vault
SPENDOS_VAULT_ADDRESSDeployed SpendOSVault address
USDC_ADDRESSUSDC contract address
SPENDOS_OPERATOR_ADDRESSOperator signer address
SPENDOS_AGENT_VAULTAgent vault wallet address
Policy
SPENDOS_DOMAINSComma-separated allowed domains
SPENDOS_CONTRACTSComma-separated allowed contract addresses
SPENDOS_POLICY_DIGESTActive policy digest (SHA-256)
Auth
SPENDOS_REQUIRE_AUTHEnable API key auth (true/false)
SPENDOS_API_KEYSComma-separated valid API keys
SPENDOS_ALLOWED_ORIGINSComma-separated CORS origins