Veto/docs

Economic Authorization

Cost-aware authorization for AI agents that spend money. Budget enforcement, payer validation, and protocol connectors.

Economic authorization adds cost-aware policy enforcement to veto.guard() and veto.wrap(). When a tool call carries a price, Veto validates the payer, checks the cost against scoped budgets, and returns allow, deny, or require_approval.

Three payment protocols are supported out of the box: x402 (HTTP 402), Stripe MPP (Managed Payment Protocol), and Google AP2 (Agent Payments Protocol). Each has a connector that extracts economic context automatically.

Pipeline: cost validationpayer checkbudget checkallow / deny / require_approval.

Quick start

Use the @veto/economic-agent policy pack to get sensible defaults:

version: "1.0"
extends: "@veto/economic-agent"

Then pass economic context to veto.guard():

import { Veto, type EconomicContext } from 'veto-sdk';

const veto = await Veto.init();

const result = await veto.guard('purchase', { item: 'GPU', quantity: 1 }, {
  economic: {
    cost: 42.50,
    currency: 'USD',
    payer: 'team-wallet',
    protocol: 'custom',
  }
});

if (result.decision === 'deny') {
  console.log(result.economicDenial);
  // { reason: 'budget_exceeded', budget_scope: 'session', budget_limit: 100, budget_spent: 80, budget_remaining: 20 }
}

The economic field on the options object triggers the economic evaluator. Without it, standard policy evaluation runs as usual.

Policy configuration

Add an economic section to your veto.config.yaml:

economic:
  budgets:
    - scope: session
      limit: 100.00
      currency: USD
      approval_threshold: 25.00
      window: session

  cost_extraction:
    default: "arguments.cost"
    overrides:
      search_api: "arguments.price_usd"
      trade: "arguments.amount"

  payer:
    required: true
    approved: ["team-wallet", "research-budget"]

  denial_reasons:
    budget_exceeded: "Would exceed {scope} budget ({spent}/{limit} {currency})"
    approval_required: "Cost {cost} exceeds threshold {threshold}"
    payer_missing: "No payer identified"
    payer_unauthorized: "Payer {payer} not approved"

Budget scopes

ScopeEngineDescription
sessionLocalBudgetEngine (in-memory)Resets per SDK session. No server needed.
agentCloudBudgetEngine (Veto Cloud)Tracks across sessions for one agent identity.
userCloudBudgetEngine (Veto Cloud)Tracks across agents for one user.
globalCloudBudgetEngine (Veto Cloud)Organization-wide budget.

session is local-only and works offline. The other three scopes require a Veto Cloud connection to maintain ledger state across processes.

Cost extraction

cost_extraction.default sets the dot-path used to read the cost from tool call arguments when no tool-specific override exists. For example, "arguments.cost" reads args.cost.

cost_extraction.overrides maps individual tool names to their own dot-path. If a tool appears in overrides, its path takes priority over default.

If the resolved value is not a finite non-negative number, the evaluator denies with invalid_cost.

Denial reasons

Seven reason codes the economic evaluator can return:

CodeWhen
budget_exceededCost would push spending over the scope limit.
approval_requiredCost exceeds the approval_threshold but is within budget.
payer_missingNo payer identified and payer.required is true.
payer_unauthorizedPayer not in the approved list.
currency_mismatchTool call currency does not match budget currency.
invalid_costCost is NaN, Infinity, or negative.
connector_errorProtocol connector failed to parse economic context.

All denial reasons can be customized in the denial_reasons section using {variable} interpolation.

Protocol connectors

Connectors extract EconomicContext from protocol-specific signals. They are auto-detected when using wrapFetch(), or you can call extract() manually:

import { createX402Connector, createMPPConnector, createAP2Connector } from 'veto-sdk';

// Manual extraction from an HTTP response
const x402 = createX402Connector();
const context = x402.extract(httpResponse);
if (context) {
  const result = await veto.guard('api_call', args, { economic: context });
}
ProtocolSignalUse case
x402HTTP 402 + X-Payment-* headersPay-per-call APIs
MPPStripe session metadataSaaS billing, managed payments
AP2Google mandate constraintsAgent-to-agent payments, spending caps

Each connector implements the same interface: extract(input) returns an EconomicContext or null if the signal is not present.

Evaluation pipeline

Economic evaluator pipeline: EconomicContext input, cost validation (deny invalid_cost), payer check (deny payer_missing or payer_unauthorized), budget check per scope (deny budget_exceeded, require_approval if above threshold, allow if within budget)

Steps are evaluated in order. The first deny short-circuits — later steps are skipped. require_approval is only returned if no step denied outright.