Skip to content

Agent wallets

An agent wallet lets an AI agent or an automated service send payouts without your merchant key. You fund it with part of your balance, and give the agent a wallet key (ak_test_… or ak_live_…) that can only:

  • read its own wallet and balance, and
  • create payouts within a fixed policy: one provider, a maximum per payout, an optional daily maximum (max_daily_amount, counted per Dakar calendar day), and an allowlist of recipient phones (1–20).

The wallet’s funded balance is the agent’s total spending limit. It can never touch the rest of your balance.

You (merchant key) The agent (wallet key)
POST /v1/agent-wallets — create with a policy (Idempotency-Key required) GET /v1/agent/wallet — its policy
POST /v1/agent-wallets/{id}/fund · …/reclaim — move money in / take unreserved money back GET /v1/agent/balance
POST /v1/agent-wallets/{id}/keys — issue a key (shown once) POST /v1/agent/payouts — pay out within the policy
POST /v1/agent-wallets/{id}/disable — stop new agent writes GET /v1/agent/payouts · …/{id}
GET /v1/agent-wallets/{id}/payouts · …/transfers · …/keys

Every agent payout carries an action_id from your application (e.g. the approved task’s id), not invented by the model. Xaalis binds one payout to each action_id in the wallet, so a retried tool call returns the original payout instead of paying twice. Reusing an action_id with a different amount or recipient returns 409.

Owner approval above the limits (test mode)

Section titled “Owner approval above the limits (test mode)”

Tight limits are safer, but an agent then stops dead on the first unusual payout. With owner approval, a payout over the wallet’s soft caps waits for a person instead of failing:

  • Policy (merchant key or dashboard): approval_above_limit: true and approval_max_amount — a hard ceiling, at least max_payout_amount. Off by default; test wallets only for now.
  • An otherwise valid agent payout above the per-payout cap or the day’s total answers 202 with an agent_payout_approval (apr_…, status: "pending", 30 minutes). Nothing is reserved while it waits. A recipient outside the allowlist, another provider, or an amount above approval_max_amount still fails; a wallet holds at most 20 pending approvals (422 limit_exceeded).
  • The agent polls GET /v1/agent/approvals/{id}: pending → approved (with payout_id), declined or expired. It never sees a PIN link or the full phone number.
  • The owner decides in the dashboard or on WhatsApp, and confirms an approval with their PIN on a Xaalis page — never in a chat or a tool. The page shows the full number, amount and fee. Approval admits the payout; it’s not a success: read the payout’s own status.

Retries: keep the same action_id and Idempotency-Key. A retry returns the same approval while it’s pending, declined or expired — widening the caps doesn’t change that — then the one payout once approved. That retry answers 201 with the payout even if its reservation failed afterwards (status: "failed", failure_reason): check it, and don’t start a new action automatically. A new action_id is a new request for the owner.

SDK: agent.payouts.request(…) / requestForAction(…) return a Payout or an AgentPayoutApproval; poll agent.approvals.retrieve(id). The older create / createForAction still return a Payout and throw XaalisApprovalRequiredError (with .approval) when approval is needed. An unreadable answer to a write throws XaalisProtocolError with outcomeUnknown: true: retry with the same action, or poll the approval you know.

In live mode, only a signed-in owner of the merchant account can create a wallet, change its policy, fund or reclaim it, and issue its ak_live_ key — in the merchant dashboard, never with an API key. So an agent holding your sk_live_ key (or any API key) can’t create or top up a wallet for itself. Your live API keys can still read wallets and disable a wallet or revoke its key — stopping an agent is always one call away.

The owner can raise or lower the per-payout and daily caps or replace the recipient list at any time; the next payout is checked against the new policy.

  • Live agent payouts support Wave wallets only for now (Orange Money payouts aren’t available yet).
  • A live agent key is only accepted over HTTPS.
  • Disabling a wallet blocks new agent writes; payouts already accepted still finish.

The TypeScript SDK includes agent-wallet helpers (xaalis.agentWallets for you, an agent client with payouts.createForAction for the agent), with an example tool handler.