Skip to main content
HomeLanding pagesHow to add payments to an OpenAI agent
LANDING PAGE

How to add payments to an OpenAI agent

7 min read·Last updated June 2, 2026

In TypeScript, wrap createX402Client from @blockchain0x/x402 inside an OpenAI Agents SDK tool so a paid call settles on a 402. In Python, call a small Node x402 proxy from a function_tool, because the client is Node-only. Either way the agent pays in USDC on Base. Fund the wallet, set a dashboard spend limit, and ship in about fifteen minutes.

What you will build

An agent built on the OpenAI Agents SDK that pays for the tools it calls, settled in USDC on Base, in about fifteen minutes. The agent loop does not change. You add one tool that pays, and the agent calls it like any other tool.

This is the task walkthrough. For the full compatibility matrix, handoff billing, and pricing detail, the companion reference is openai-agents-sdk-payments. The OpenAI Agents SDK integration page is the canonical reference, and the payment API product page covers the wider surface. The path you take depends only on whether you run the TypeScript or Python SDK.

The shared idea, whichever language you use, is that payment lives in the tool and nowhere else. The agent, its instructions, its model, and its run loop are untouched. You are giving one tool the ability to pay for what it calls, and the SDK keeps treating it as an ordinary tool. That is why this is additive: you can add it to a single tool on an existing agent, confirm it works, and leave everything else exactly as it was.

Prerequisites

  • A Blockchain0x account with one agent created, so it has a wallet.
  • A sk_test_ API key for this walkthrough.
  • Node 18+ (TypeScript SDK, or the Python proxy; the SDK targets >=18), or Python plus Node for the proxy.
BASH
export B0X_API_KEY=sk_test_...   # sk_test_ -> Base Sepolia

TypeScript: wrap the client in a tool

If you run the TypeScript Agents SDK, wrap the x402 client directly in a tool. No extra process.

TYPESCRIPT
import { Agent, run, 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 });

const getQuote = tool({
  name: "get_quote_realtime",
  description: "Fetch a real-time quote for a stock ticker.",
  parameters: z.object({ ticker: z.string() }),
  execute: async ({ ticker }) => {
    const res = await fetchWithPay(`https://quotes.example.com/v1/quote?ticker=${ticker}`);
    return res.ok ? await res.text() : `Lookup failed: ${res.status}`;
  },
});

const researcher = new Agent({ name: "Researcher", instructions: "Equity research analyst.", tools: [getQuote] });

On a 402 the client settles in USDC and retries, and the tool returns the result. The agent never sees the payment.

Python: call a Node proxy

If you run the Python Agents SDK, the x402 client is not available there, so run a small Node proxy (the same one used in the CrewAI guide) and call it from a function_tool.

PYTHON
from agents import Agent, function_tool
import requests

@function_tool
def get_quote_realtime(ticker: str) -> str:
    """Fetch a real-time quote for a stock ticker."""
    upstream = f"https://quotes.example.com/v1/quote?ticker={ticker}"
    res = requests.post("http://127.0.0.1:8787", json={"url": upstream}, timeout=30)
    return res.text if res.status_code == 200 else f"Lookup failed: {res.status_code}"

researcher = Agent(name="Researcher", instructions="Equity research analyst.", tools=[get_quote_realtime])

The proxy holds the wallet and answers the 402; the Python tool just calls localhost. Run one proxy per agent wallet.

Run the agent

Either way, run the agent normally. The paid tool behaves like any other.

TYPESCRIPT
const result = await run(researcher, "What is the live quote on TSLA?");
console.log(result.finalOutput);

The first time the agent calls the tool, the upstream returns 402, the wallet settles, and the retried request returns the quote. From the agent's view it was one tool call that took a beat longer.

Verify the full loop

Before you trust the agent with anything, confirm the payment path end to end on testnet. There are three things worth checking, and they catch different failures.

First, the happy path: call the paid tool against a funded wallet and confirm you get a real result, not a 402. If you see a 402 reach your agent, the client or proxy is not wired in, because it should have answered the 402 itself.

Second, the unfunded path: drain or use a fresh wallet and confirm the call fails cleanly rather than hanging. A paid call against an empty wallet should return a non-2xx your tool turns into a sensible message, not a timeout.

Third, the logs: watch the settlement happen. On the TypeScript path, log around fetchWithPay; on the Python path, watch the proxy output. Seeing the 402, the settle, and the 200 in order is how you know the loop is real and not a cached or mocked response. Run all three on Base Sepolia, where mistakes cost test USDC, before a live key is anywhere near the code.

Handle a failed payment

A paid call will sometimes come back as a non-2xx: the wallet refused an over-limit payment, the balance ran out, or the upstream itself failed. The agent has to handle that, or it will loop on the same wall.

TYPESCRIPT
const res = await fetchWithPay(url);
if (!res.ok) {
  // Do not retry the same call. Surface it so the planner can choose another action.
  return `Paid call failed with status ${res.status}; skipping.`;
}
return await res.text();

Then tell the agent, in its instructions, what a failed paid call means: do not retry the identical call, and treat a failure as a budget or availability signal rather than a transient blip. An agent that blindly retries a refused payment burns turns and, in your logs, looks exactly like a runaway. The instruction to stop is what keeps a failed payment calm.

Fund and set a spend limit

The agent pays from its wallet, so fund it. On sk_test_ that is Base Sepolia; send the wallet test USDC from a public faucet. Then set a spend limit in the dashboard and confirm it over the API:

TYPESCRIPT
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, allowance_wei, period_seconds, ...

The wallet refuses any call over the per-transaction cap or the period allowance before settling, so the limit is the real boundary. Set a tight per_tx_wei first; it is the cheapest protection against a single runaway payment.

Ship to mainnet

When the loop works on testnet, going live is a key swap. Replace the sk_test_ key with a sk_live_ one and the same code settles on Base mainnet (eip155:8453). Re-check the spend limit on the live agent, because limits are per agent, and confirm the key prefix at boot so a test key never runs in production; the server rejects a mismatch with apikey.network_mismatch.

Common pitfalls

Three traps.

Writing your own 402 handling. The client (or the proxy) already does the 402, settle, and retry. Adding your own branch makes you pay twice. Await the final response.

Sharing one wallet across a handoff graph. Give each agent its own wallet so a prompt-injected agent only spends its own allowance and attribution stays clean. The reference page covers this.

Exposing the Python proxy beyond localhost. It holds a wallet key. Bind it to 127.0.0.1 and treat it like a credential.

What to ship today

Pick your path by language, wire one paid tool, fund the test wallet, and watch a 402 settle on Base Sepolia. Set a dashboard spend limit, then swap to a sk_live_ key. For the full integration reference, handoff billing, and tier math, see openai-agents-sdk-payments. Pricing is on the pricing page.

FAQ

Frequently asked questions.

Is there an OpenAI Agents SDK package from Blockchain0x?

No, and you do not need one. In TypeScript you wrap createX402Client from @blockchain0x/x402 in the SDK's tool definition. In Python you call a small Node proxy from a function_tool because the x402 client is Node-only. Both depend only on @blockchain0x/node and @blockchain0x/x402.

TypeScript or Python, which should I use?

Use whatever your agent already runs in. The TypeScript path wraps the client inline with no extra process. The Python path runs the proxy alongside the agent. If you are starting fresh and language is open, TypeScript has one fewer moving part because there is no proxy to deploy. Both settle identically.

Does this work with handoffs?

Yes. When one agent hands off to another, the receiving agent pays for its own tool calls through its own wallet. The handoff itself costs nothing. Give each agent in the graph its own wallet so attribution and limits stay per agent. The integration reference, openai-agents-sdk-payments, covers handoff billing in depth.

Which networks and token does settlement use?

USDC, 6 decimals, on Base. A sk_test_ key settles on Base Sepolia (eip155:84532); a sk_live_ key settles on Base mainnet (eip155:8453). The SDK reads the network from the key prefix, so switching chains is a key swap. The only scheme is exact-usdc.

How do I stop the agent overspending?

Set a spend limit in the dashboard. The wallet enforces a per-transaction cap and a per-period allowance before settlement, so an over-limit call is refused before any USDC moves and your tool gets a non-2xx to handle. Read the active limits with GET /v1/agents/:agentId/spend-permissions.

Create your free agent wallet in 5 minutes.

First payment confirmed in under ten minutes. Free to start.