What the wallet tool is
An OpenAI Agents SDK wallet is a reusable tool that gives an agent the ability to pay. The agent calls it with a target, the tool settles any 402 in USDC on Base, and the result flows back into the run. Because the SDK runner invokes tools automatically when the model picks them, the agent gets a wallet the way it gets any capability: as a tool in its tools list, called when a task needs to pay.
There is no dedicated adapter package. The wallet tool is a pattern you build from @blockchain0x/node and @blockchain0x/x402, which keeps it on the verified surface. This page is the focused artifact; for the broad integration overview see openai-agents-sdk-payments, and for the task walkthrough see how-to-add-payments-to-openai-agent. The payment API product page is the reference.
Build it in TypeScript
On the TypeScript SDK you are in Node, so the wallet tool wraps createX402Client directly inside the tool() helper. No proxy.
import { tool } from "@openai/agents";
import { createClient } from "@blockchain0x/node";
import { createX402Client } from "@blockchain0x/x402/client";
import { z } from "zod";
const sdk = createClient({ apiKey: process.env.B0X_API_KEY! });
const fetchWithPay = createX402Client({ sdk });
export const walletTool = tool({
name: "pay_and_fetch",
description: "Fetch a URL, paying in USDC if it requires payment. Returns the body.",
parameters: z.object({ url: z.string() }),
execute: async ({ url }) => {
const res = await fetchWithPay(url);
return res.ok ? await res.text() : `Failed: ${res.status}`;
},
});Add walletTool to an Agent's tools and the runner will call it when the model decides a task needs a paid resource. This is the cleanest path, with no extra process to run.
Build it in Python
On the Python SDK the wallet tool is a @function_tool whose body calls the local Node proxy, since the x402 client is Node-only.
import requests
from agents import function_tool
@function_tool
def pay_and_fetch(url: str) -> str:
"""Fetch a URL, paying in USDC if it requires payment. Returns the body."""
res = requests.post("http://127.0.0.1:8787", json={"url": url}, timeout=30)
return res.text if res.status_code == 200 else f"Failed: {res.status_code}"Start the proxy (the thirty-line service from the walkthrough), add pay_and_fetch to an Agent's tools, and the Python agent pays exactly as the TypeScript one does. The proxy is the bridge the Python runtime needs; everything above it is identical.
The description is what the model sees
In the OpenAI Agents SDK, the model decides to call a tool from its name and description (the docstring, in Python's @function_tool), so that text is the interface. Write it for the model: say plainly that the tool fetches a URL and pays if the URL requires payment, and that it returns the body. That is usually enough for the agent to reach for it when a task needs a paid resource and to leave it alone otherwise.
Decide deliberately whether to mention cost. If you want the model to weigh price, note that calls may cost a small amount in USDC; if you would rather it not hesitate over routine sub-cent calls, leave cost out and let the wallet's spend limit be the control. Either is valid, but be intentional, because a vague description leaves the model guessing about when the tool applies, while a precise one tells it exactly. The execute body is small; the description is where you shape behavior, and in this SDK that description is exactly what the model reads when it plans.
A wallet per agent across handoffs
The OpenAI Agents SDK is built around handoffs, where one agent passes control to another mid-run, and the wallet tool fits that cleanly: each agent in the chain should have its own wallet. Build the tool with a factory and bind each agent's copy to its own wallet, by key in TypeScript or by proxy port in Python.
export function makeWalletTool(apiKey: string) {
const sdk = createClient({ apiKey });
const fetchWithPay = createX402Client({ sdk });
return tool({
name: "pay_and_fetch",
description: "Fetch a URL, paying in USDC if required.",
parameters: z.object({ url: z.string() }),
execute: async ({ url }) => {
const res = await fetchWithPay(url);
return res.ok ? await res.text() : `Failed: ${res.status}`;
},
});
}Give the triage agent makeWalletTool(triageKey) and the specialist makeWalletTool(specialistKey), and when the run hands off, the active agent pays from its own wallet. The dashboard attributes spend per agent, and a compromised agent can only spend its own balance. Shared code, separate accounts, which is what a handoff chain of paying agents wants.
Verify the loop
Before trusting the tool in a real run, prove the loop on Base Sepolia. With a sk_test_ key (in the client for TS, on the proxy for Python) and a funded wallet, run an agent on a task that needs a paid URL and watch the run: the model should choose pay_and_fetch, the runner should execute it, and the proxy or client should settle the 402 and return the body. Then confirm a matching payment.sent in the dashboard for that agent.
If the model never calls the tool, the description is too vague; if it calls it but nothing settles, check the key and the wallet balance. Both are quick fixes on testnet, and once the loop holds, swapping the key to sk_live_ moves it to Base mainnet unchanged.
Compatibility
Because the wallet tool is an ordinary SDK tool, it works across the framework's surfaces.
| OpenAI Agents SDK surface | Works? | Notes |
|---|---|---|
TypeScript tool() |
Yes | Wraps createX402Client directly, no proxy |
Python @function_tool |
Yes | Calls the local Node proxy |
Runner.run / run loop |
Yes | The runner calls the tool when the model picks it |
| Handoffs between agents | Yes | Each agent has its own wallet via the factory |
| Payment client language | Node | Python calls a proxy; TS calls the client directly |
When to use it
Reach for the wallet tool when agents need to pay for what they call and you want that capability as one reusable unit rather than per-tool glue. It fits when several agents, including the agents in a handoff chain, share the same paying behavior, since you build the tool once and bind it per agent, and when payment should be a capability the model can invoke deliberately during a run.
It is the wrong shape when only one specific tool should ever pay (wrap that tool's own call instead) or when the agent is purely internal with no paid calls. Match it to whether paying is a general capability the agents need or a one-off behavior of a single tool.
Pricing
The tool is free; you build it from open packages. What you pay is the wallet platform fee per agent on the pricing page: Free is $0 per agent per month at a 5% transaction fee, Pro is $9 at 2%, and Business is $29 at 1%. Per-agent pricing means each agent that transacts through its tool is billed on its own wallet, so a handoff chain where only two agents pay only incurs fees for those two.
What to ship today
Build pay_and_fetch (around createX402Client on TypeScript, around the proxy on Python), add it to an Agent's tools, and make one paid call on Base Sepolia. For a handoff chain, use the factory so each agent has its own wallet. For the broad integration overview see openai-agents-sdk-payments. Pricing is on the pricing page.