Agentic Payments & Stablecoins · TypeScript SDK

Put spending limits on an agent that pays in stablecoins

Your procurement agent can sign a stablecoin transfer on its own. The TypeScript SDK checks the counterparty wallet and the agent’s caps first, and gives each transfer an idempotency key your wallet service can use to recognize a retry.

Wallet and cap facts

The agent payment simulator sends these fields. Caps come from your treasury configuration, not from the agent.

FactWhat it holds
counterparty_wallet_flaggedTrue when the wallet is on your restricted list.
counterparty_newTrue when the counterparty hasn’t been verified yet.
amount_usdTransfer amount in US dollars.
assetusd_stablecoin or eur_stablecoin.
agent_daily_spend_usdWhat this agent has already spent today.
per_transaction_cap_usdThe agent’s limit for one transfer.
daily_cap_usdThe agent’s daily limit.
human_preapproval_presentTrue when a person pre-approved this payment.
cross_borderTrue when the transfer crosses borders.

TypeScript: send with an idempotency key

invocationId is stable for one run, so your wallet service can treat a repeat as the same transfer.

TypeScript · @veriproof/sdk-core

const result = await veriproof.govern(
  'payment.transfer',
  transfer,
  ({ input, invocationId, signal }) =>
    wallet.send(input, { idempotencyKey: invocationId, signal }),
  {
    facts: {
      counterparty_wallet_flagged: restrictedWallets.has(transfer.to),
      counterparty_new: !vendors.isVerified(transfer.to),
      amount_usd: transfer.amountUsd,
      asset: transfer.asset,
      agent_daily_spend_usd: ledger.spentTodayUsd(agent.id),
      per_transaction_cap_usd: agent.limits.perTransactionUsd,
      daily_cap_usd: agent.limits.dailyUsd,
      human_preapproval_present: Boolean(transfer.preapprovalId),
      cross_border: transfer.crossBorder,
    },
  },
);

if (result.execution === 'completion_unknown') {
  await reconcile(transfer);
}

When execution is completion_unknown, the transfer may already have gone out. Check the chain before any retry.

Why TypeScript here: Wallet and payment services are commonly built on Node.js, and there’s an OpenAI Agents adapter if the agent is built with it.

Three transfers

Each row is a scenario in the agent payment simulator. Run agent payment simulator

ResultWhenWhat your code seesWho picks it up
AllowedA routine invoice to a known vendor.The transfer is signed and sent, and the record keeps the wallet facts and the rule version.The Business Owner sees what the agent pays on its own. Auditors read the record inside an engagement.
Sent to a personA first payment to a vendor that hasn’t been verified.The transfer waits for treasury.The treasury approver with that authority, in the VeriProof Inbox, by email, or in Slack or Microsoft Teams, with reminders and escalation.
StoppedThe agent approved a payment to a wallet on the restricted list.The status is blocked, and nothing is signed.The Governance Engineer sees the wallet rule that stopped it.

Using the OpenAI Agents SDK?

The @veriproof/sdk-adapter-openai-agents package applies the same check around model and local tool calls in an OpenAI Agents run. Streaming output isn’t covered, so keep transfers in a tool call or behind govern.

When treasury changes the limits

Developer fix request

If treasury adds a rule on the vendor’s invoice reference and your agent doesn’t send it, the Developer gets a fix request naming the field.

Changing the rule

Raising an agent’s daily cap is a rule change. It can run in Shadow against real transfers first, and an administrator or compliance officer approves an engineer’s change before it enforces in production.

See how the six role portals hand off work

More to explore

Watch treasury pick up a transfer

Try the demo portal as the treasury approver, then follow the same transfer as the Governance Engineer.