What you will build
An AI agent that decides what to pay for and pays for it on its own, in USDC on Base, with no human approving each transfer, and with a hard ceiling it cannot cross. Autonomy and safety are not in tension here. The agent gets full freedom to spend inside an envelope, and the envelope is enforced somewhere the agent cannot reach. That combination is what makes unattended payment something you can actually ship rather than a risk you keep deferring.
This page assumes the agent already has a funded wallet. If not, start with how-to-add-wallet-to-my-agent. The payment API product page is the broader reference.
What autonomous payment really means
Autonomous does not mean unbounded. It means the per-payment decision moves from a human to the agent, while the budget decision stays with a human. Pulling those two apart is the whole trick.
A human still decides how much this agent may spend, over what period, and the largest single payment it may make. That decision is encoded once as a spend limit on the wallet. After that, the agent decides, call by call, whether a given payment is worth making, and it executes without waiting for anyone. The human is not in the loop on individual transfers, which is what unlocks the speed; the human is very much in the loop on the envelope, which is what keeps it safe.
If you only take one idea from this page, take that split: freedom inside the envelope, enforcement on the envelope, and the agent on one side of the line with the budget authority on the other.
Prerequisites
- A Blockchain0x account with one agent created and its wallet funded with test USDC.
- A
sk_test_API key for this walkthrough. - Node 18 or newer. The SDK targets
>=18.
export B0X_API_KEY=sk_test_... # sk_test_ -> Base SepoliaGive the agent the ability to pay
Autonomy on the pay side is one wrapper. Build the client, hand the agent a fetch that settles 402s.
import { createClient } from "@blockchain0x/node";
import { createX402Client } from "@blockchain0x/x402/client";
const sdk = createClient({ apiKey: process.env.B0X_API_KEY! });
const fetchWithPay = createX402Client({ sdk });
// Whatever the agent decides to call, it calls through fetchWithPay.
// A 402 is settled in USDC and the request is retried, with no human prompt.
const res = await fetchWithPay(endpointTheAgentChose);There is no approval step to wire, no callback to a human, no pending state. The agent picks an endpoint, calls it, and the payment happens. That is exactly why the next section matters as much as this one.
The guardrail that makes it safe
A pay capability with no ceiling is not autonomy, it is exposure. The ceiling is the spend limit, set in the dashboard and enforced by the wallet before any payment. Crucially, you do not set it from the agent's code, and the agent cannot change it. Read it back to confirm what is enforced:
const res = await fetch(
`https://api.blockchain0x.com/v1/agents/${agentId}/spend-permissions`,
{ headers: { Authorization: `Bearer ${process.env.B0X_API_KEY!}` } },
);
const permissions = await res.json();
// per_tx_wei (largest single payment), allowance_wei (total per period),
// period_seconds (86400 daily / 604800 weekly / 2592000 monthly)Set per_tx_wei close to the largest legitimate single payment and allowance_wei to two or three times a normal period. Now the worst an injected or buggy agent can do is one capped payment, and the period allowance caps the total even if many slip through. The full treatment is how-to-set-up-agent-spending-limits. This is the single most important step on the page; an autonomous agent without it is one bad input away from spending everything you funded.
Handle a refused payment in the loop
Because the wallet refuses an over-limit payment before settlement, your agent will sometimes get a non-2xx back from a paid call. An autonomous agent has to handle that gracefully, or it will loop on the same wall.
const res = await fetchWithPay(endpointTheAgentChose);
if (!res.ok) {
// The payment was refused or the upstream failed. Do not retry the same call.
// Record it, and let the planner choose: skip, defer to the next period, or escalate.
return { paid: false, status: res.status };
}
return { paid: true, body: await res.text() };Then tell the planner, in its instructions, what a refused payment means: do not retry the same call with the same arguments, and treat a refusal as a budget signal rather than a transient error. An agent that blindly retries a refused payment burns cycles and looks, in your logs, exactly like a runaway. Handling the refusal is what makes the autonomy calm instead of frantic.
When to give an agent this autonomy
Not every agent should pay on its own, even with a limit. The decision comes down to two questions: how reversible is a wrong payment, and how much does waiting for a human cost.
Autonomy is the clear win when payments are small, frequent, and feed work the agent is already trusted to do. An agent that calls a paid data API a hundred times an hour cannot wait for a human on each call, and a single wrong call costs a fraction of a cent. Here the limit does all the safety work and the speed gain is large.
Be more careful when a single payment is large, rare, or hard to claw back. Paying a hundred dollars to a new counterparty is not the same risk as a half-cent API call, and the per-transaction cap should reflect that. You can still let the agent operate autonomously for the small, frequent flow while keeping a tight per_tx_wei that forces anything unusually large to fail rather than slip through. The limit is not just a backstop; it is how you encode "the agent may do the routine thing freely, and the unusual thing not at all".
Test the autonomy on Base Sepolia
Exercise the full loop on testnet before a live key goes anywhere near it. With a sk_test_ key the agent settles on Base Sepolia (eip155:84532). Run three scenarios: a normal payment that settles and returns, a payment that exceeds per_tx_wei and is refused, and a run of payments that exhausts the period allowance. Confirm the agent handles all three without looping. When the refused cases are as clean as the happy path, swap to a sk_live_ key and re-check the limit on the live agent.
Common pitfalls
Three traps specific to autonomy.
Shipping the pay capability before the limit. The order matters. Set the spend limit first, then turn on autonomous paying. The reverse leaves a window where a bug spends freely.
Putting the budget in the prompt. A budget in the system prompt is a suggestion a crafted input can talk past. The wallet limit is the only real boundary. Use the prompt for behavior, the wallet for money.
Retrying refused payments. An agent that retries on a refusal turns one blocked payment into a tight loop. Make refusal a terminal outcome for that call and let the planner choose a different action.
What to ship today
Wire fetchWithPay, set a per-transaction and per-period limit in the dashboard, and run the three test scenarios until the refused cases are handled cleanly. That is a safely autonomous agent. Only then move the key from sk_test_ to sk_live_. Production pricing is on the pricing page.