{
  "question": "How do I gate an agent wallet or card with per-task caps and an outside-agent spend record?",
  "slug": "how-to-gate-an-agent-wallet-or-card-with-per-task-caps-and-an-outside-agent-spend-record",
  "url": "https://www.rightshold.com/answers/how-to-gate-an-agent-wallet-or-card-with-per-task-caps-and-an-outside-agent-spend-record",
  "short_answer": "Handing an agent a funded wallet or virtual card is incomplete without four controls the agent cannot rewrite: a per-task (and per-agent) spend cap, a human approval gate above a threshold, a one-call revoke path, and a spend record written outside the agent's editable session. Put hard limits on the instrument itself (Stripe Issuing spending_controls with per_authorization and period caps; a small dedicated wallet plus a signing policy such as Coinbase CDP Policy Engine), re-check each purchase in a real-time authorization or authorize_spend step, require request_human_approval when the task budget or a single charge exceeds policy, and append every allow/deny to a ledger or server DB the agent's tools cannot UPDATE. Caps in prompt text or session JSON are not a gate.",
  "checklist": [
    "Give each agent its own card or wallet credential (one Stripe Issuing card or one crd_/wallet per agent). Never share a treasury key across agents.",
    "Set instrument-level caps first: per-authorization and daily/monthly limits, allowed merchant categories/countries, and (for wallets) a policy that rejects over-cap signing. Stripe applies a default 500 USD/day when you set no spending_limits, plus an unconfigurable 10,000 USD per-authorization ceiling.",
    "Add a per-task budget: when a task starts, mint task_id, remaining_minor, and expires_at in storage the agent cannot edit. Every charge decrements that budget; on zero or expiry, refuse further spend for that task.",
    "Above a threshold (or for new merchants), call request_human_approval bound to amount, payee/merchant, task_id, and currency; re-verify the hash immediately before capture or broadcast.",
    "On each purchase attempt, run an outside check (Stripe issuing_authorization.request within 2 seconds, or authorize_spend against set_spend_policy) and write the signed allow/deny where the agent cannot edit it.",
    "Wire revoke: cancel or deactivate the card, drain/freeze the wallet, and revoke_agent / revoke the credential so later checks fail closed. Test the path before you need it.",
    "Log allows, denies, timeouts, and revocations with agent_id, task_id, amount, merchant, decision, and receipt id. A missing deny is how silent retries rewrite history.",
    "Keep only a receipt id in the agent session — never approved=true, remaining budget, or card PAN/secret material the model can read or overwrite."
  ],
  "sections": [
    {
      "heading": "Instrument caps are necessary but not enough",
      "points": [
        "Stripe Issuing for agents lets you set spending_controls at card creation (and update them later): spending_limits with intervals such as per_authorization and monthly, plus allowed_categories and country controls. Real-time authorization sends issuing_authorization.request so you can approve or decline from task context before the charge lands.",
        "Aggregation is best-effort (Stripe documents up to ~30 seconds lag), and tips or delayed captures can push a limit over — so treat card caps as a ceiling, not a precise task ledger.",
        "For crypto wallets, fund a dedicated agent wallet with only the task or daily budget and enforce reject rules at signing (for example CDP Policy Engine). Code in the agent process can be skipped; money the wallet does not hold cannot be spent.",
        "x402 per-request and per-run client caps are a different layer (see the related x402 page). This page is about the card/wallet instrument plus a task budget and an immutable spend record."
      ]
    },
    {
      "heading": "Per-task caps, approval, and a record the agent cannot edit",
      "points": [
        "Per-agent daily caps stop one runaway bot; per-task caps stop one ticket from burning the whole daily budget. Key the budget row on (agent_id, task_id) and refuse charges that name a different or missing task_id.",
        "set_spend_policy on a Rightshold credential sets per_tx_max_minor, daily_max_minor, allowed_domains/categories, and optional expires_at. authorize_spend returns a signed allow/deny against that policy and the running daily total — decision only; it never moves money.",
        "request_human_approval above threshold binds a person's yes to a hash of the exact purchase (amount, merchant, task_id). verify_human_approval fails if those fields changed after the yes.",
        "Write each decision to server storage or the ledger. OpenAI's HITL guidance keeps RunState on the server and does not treat client-uploaded state as authorization; the same rule applies to spend totals and \"already approved\" flags."
      ]
    },
    {
      "heading": "What can go wrong",
      "points": [
        "One shared corporate card or hot wallet for every agent — a single compromise or prompt injection spends everyone's budget.",
        "Caps live only in the system prompt (\"never spend more than $20\") with no instrument limit or authorization webhook.",
        "Real-time auth times out and Autopilot/default settings approve; for agent cards, configure timeout to decline and keep the webhook fast.",
        "The spend CSV or JSON sits in the workspace where the agent can edit or delete rows after a bad purchase."
      ]
    }
  ],
  "checks": [],
  "ask_rightshold": {
    "start": "https://www.rightshold.com/start?ref=seo",
    "mcp_endpoint": "https://www.rightshold.com/mcp",
    "ask": "Set a spending policy for this agent credential with a per-purchase and daily cap, then require my approval before any charge above the per-task threshold.",
    "mcp_call": {
      "tool": "set_spend_policy",
      "arguments": {
        "credential_id": "crd_…",
        "currency": "USD",
        "per_tx_max_minor": 2500,
        "daily_max_minor": 10000,
        "allowed_domains": [
          "api.vendor.example"
        ],
        "allowed_categories": [
          "saas"
        ],
        "expires_at": "2026-11-07T00:00:00Z"
      }
    },
    "also": [
      "Needs your API key (owner). set_spend_policy replaces the previous policy; every version stays on the ledger. authorize_spend then returns a signed allow/deny for each purchase (records only; never moves money).",
      "request_human_approval above your task threshold binds a human yes to amount, merchant and task_id; verify_human_approval fails if those changed.",
      "revoke_agent (kill switch) irreversibly refuses the credential on later checks; also cancel/deactivate the card or freeze the wallet at the issuer.",
      "How to set per-request and per-run spend caps for x402 agent payments and How to keep an agent risk/approval record outside the agent's editable session cover the x402 client layer and where to store approvals."
    ],
    "scope": "Rightshold records spending policies, spend authorizations and human approvals for agents that call it. It does not issue cards, hold balances, sign chain transactions, sit in your Stripe webhook, or stop an agent that never asks. Enforce caps on the card/wallet and in your authorization path too. Not legal advice."
  },
  "sources": [
    {
      "title": "Stripe Docs: Issuing for agents (spend controls; real-time authorization)",
      "url": "https://docs.stripe.com/issuing/agents"
    },
    {
      "title": "Stripe Docs: Issuing spending controls (per_authorization and period limits; defaults)",
      "url": "https://docs.stripe.com/issuing/controls/spending-controls"
    },
    {
      "title": "Stripe Docs: Issuing real-time authorizations (issuing_authorization.request; respond within 2 seconds)",
      "url": "https://docs.stripe.com/issuing/controls/real-time-authorizations"
    },
    {
      "title": "Coinbase CDP: Policy Engine overview",
      "url": "https://docs.cdp.coinbase.com/wallets/security-and-policies/policy-engine/overview"
    },
    {
      "title": "OpenAI Agents SDK (JS): Human-in-the-loop (keep approval state on the server)",
      "url": "https://openai.github.io/openai-agents-js/guides/human-in-the-loop/"
    },
    {
      "title": "Agent spending policies on Rightshold",
      "url": "https://www.rightshold.com/agent-spending-policies"
    },
    {
      "title": "Human approvals on Rightshold",
      "url": "https://www.rightshold.com/human-approvals"
    }
  ],
  "related": [
    {
      "title": "How to set per-request and per-run spend caps for x402 agent payments",
      "url": "https://www.rightshold.com/answers/how-to-set-per-request-and-per-run-spend-caps-for-x402-agent-payments"
    },
    {
      "title": "How to keep an agent risk/approval record outside the agent's editable session",
      "url": "https://www.rightshold.com/answers/how-to-keep-an-agent-risk-approval-record-outside-the-agents-editable-session"
    },
    {
      "title": "How to give an AI agent a virtual card with a spending limit",
      "url": "https://www.rightshold.com/answers/how-to-give-an-ai-agent-a-virtual-card-with-a-spending-limit"
    },
    {
      "title": "How to revoke an AI agent's access immediately",
      "url": "https://www.rightshold.com/answers/how-to-revoke-an-ai-agents-access-immediately"
    }
  ],
  "computed_from": "Curated guidance; license verdicts computed from Rightshold's license profiles at render time. Not legal advice.",
  "updated": "2026-11-06"
}