Skip to main content
HomeLanding pagesHow to add payments to a CrewAI agent
LANDING PAGE

How to add payments to a CrewAI agent

8 min read·Last updated June 2, 2026

CrewAI is Python and the x402 client ships for Node, so run a small local proxy built on createX402Client from @blockchain0x/x402. Your CrewAI BaseTool calls the proxy; when the upstream returns HTTP 402 the proxy settles in USDC on Base and returns the result. Set per-agent spend limits in the dashboard so the wallet enforces them before any payment.

What you will build

A CrewAI crew whose member agents pay for the services they call, settled in USDC on Base. The agent reasoning loop does not change. The crew manager does not change. You add one tool to an agent's tools list, that tool calls a small local proxy, and the proxy handles payment.

Here is the honest constraint, stated up front so you do not go hunting for a package that is not there. The x402 payment client ships for Node (@blockchain0x/x402). CrewAI is Python. So the shipped path today is a tiny Node proxy that holds the wallet and answers 402 Payment Required on the upstream, and your Python tool calls that proxy over localhost. It is about thirty lines of Node and one extra process. That is it.

This is the CrewAI-specific path through the Blockchain0x payment API. For the broader reference, see the CrewAI integration page.

Prerequisites

Have these ready:

  • A working CrewAI crew with at least one Agent and one Tool.
  • A Blockchain0x account, with one agent created per CrewAI agent you want to make payment-capable. The add-payments-to-agent guide covers that.
  • A sk_test_ API key for this walkthrough.
  • Node 18+ (for the proxy; the SDK targets >=18) and Python 3.11+ (for CrewAI).

Set the key in both shells:

BASH
export B0X_API_KEY=sk_test_...   # sk_test_ -> Base Sepolia, sk_live_ -> Base mainnet

Run a local x402 proxy

This is the only Node you write. It builds a fetch that answers 402s, then exposes one route the CrewAI tool can POST a URL to.

JAVASCRIPT
// pay-proxy.mjs  ->  npm i @blockchain0x/node @blockchain0x/x402 && node pay-proxy.mjs
import http from "node:http";
import { createClient } from "@blockchain0x/node";
import { createX402Client } from "@blockchain0x/x402/client";

const sdk = createClient({ apiKey: process.env.B0X_API_KEY }); // sk_test_ pins it to Base Sepolia
const fetchWithPay = createX402Client({ sdk });

http
  .createServer(async (req, res) => {
    const chunks = [];
    for await (const c of req) chunks.push(c);
    const { url } = JSON.parse(Buffer.concat(chunks).toString() || "{}");
    try {
      // fetchWithPay re-issues the request with an X-Payment: exact-usdc:<base64>
      // header once the upstream 402 is settled in USDC.
      const upstream = await fetchWithPay(url);
      res.writeHead(upstream.status, {
        "content-type": upstream.headers.get("content-type") ?? "text/plain",
      });
      res.end(await upstream.text());
    } catch (err) {
      res.writeHead(502).end(String(err));
    }
  })
  .listen(8787, () => console.log("pay-proxy listening on :8787"));

Start it next to your crew: node pay-proxy.mjs. One proxy per agent wallet; give each its own port and its own B0X_API_KEY.

Wrap the proxy in a CrewAI tool

A CrewAI tool is a BaseTool subclass with a name, a description, and a _run. The _run just calls the proxy. No Blockchain0x code lives in Python at all.

PYTHON
from crewai.tools import BaseTool
import requests

class RealtimeQuoteTool(BaseTool):
    name: str = "get_quote_realtime"
    description: str = "Fetch a real-time quote for a stock ticker."

    def _run(self, ticker: str) -> str:
        upstream = f"https://quotes.example.com/v1/quote?ticker={ticker}"
        res = requests.post("http://127.0.0.1:8787", json={"url": upstream}, timeout=30)
        if res.status_code != 200:
            # 402 is handled by the proxy; a non-200 here means the upstream failed
            # or the payment was rejected by the agent's spend limit.
            return f"Quote lookup failed with status {res.status_code}."
        return res.text

The tool's description is what CrewAI's planner reasons about. It does not mention price, and it does not need to. The wallet authorizes the spend at the proxy, invisibly.

Attach the tool to an agent

The payment-aware tool plugs into a CrewAI Agent exactly like an unpaid one.

PYTHON
from crewai import Agent, Crew, Task

researcher = Agent(
    role="Market researcher",
    goal="Get a real-time quote and write a one-line summary.",
    backstory="An equity research analyst.",
    tools=[RealtimeQuoteTool()],
    verbose=True,
)

task = Task(
    description="Get the real-time quote on TSLA and summarise it.",
    agent=researcher,
    expected_output="A one-line markdown summary with the price.",
)

crew = Crew(agents=[researcher], tasks=[task])
print(crew.kickoff())

When kickoff() runs, the planner asks for the quote, the tool calls the proxy, the proxy settles the 402, and the quote comes back. From the crew's side the only observable difference is a small delay on the first paid call.

Per-agent vs per-crew billing

A decision you make in the first hour: one wallet for the whole crew, or one per agent?

Per agent wins almost every time. The crew is a logical grouping; the agent is the thing that decides to spend. Per-agent wallets give you three things:

  • Isolation. A prompt injection that hijacks one agent only spends that agent's allowance. The rest of the crew keeps running.
  • Attribution. When the dashboard shows the researcher spent more than the summariser, you can price the crew and tune limits per role.
  • Independent limits. A researcher hitting premium data APIs needs a different ceiling than a summariser that only calls an LLM.

Share one wallet only for a small internal crew where every agent has the same risk profile and you want a single invoice. Even then the dashboard attributes spend per call, so you keep some visibility.

Set spending limits

You do not set limits from code, and you never put them in the prompt. They live in the dashboard, enforced by the wallet before settlement, which is the one layer prompt injection cannot reach. Read them back to confirm:

PYTHON
import os, requests

agent_id = "agt_..."
res = requests.get(
    f"https://api.blockchain0x.com/v1/agents/{agent_id}/spend-permissions",
    headers={"Authorization": f"Bearer {os.environ['B0X_API_KEY']}"},
    timeout=30,
)
permissions = res.json()
# Each permission carries allowance_wei, per_tx_wei, and period_seconds
# (86400 daily, 604800 weekly, 2592000 monthly), plus start_at / end_at.

A call that would break per_tx_wei or exhaust the period allowance_wei is refused before any USDC moves, and your proxy returns a non-200 the tool can surface. Set conservative numbers first, watch a week of real usage, then loosen. The agent-spend-controls guide covers the dashboard side.

Test on Base Sepolia

Run the whole flow on testnet before a sk_live_ key goes anywhere near it. A sk_test_ key settles on Base Sepolia (eip155:84532) with the same shapes as mainnet.

Fund the agent first: copy its wallet address from the dashboard (or its public page at https://wallet.blockchain0x.com/a/{slug}) and send it test USDC from a public Base Sepolia USDC faucet. Then start the proxy with the test key and run the crew.

One honest caveat: outbound settlement is in active rollout, and on some networks the settle path can return a 503 until the chain adapter is live. Your _run already handles a non-200, so a crew run will degrade cleanly rather than crash. The test-agent-payments guide has the full sandbox flow. Production costs are on the pricing page.

Common pitfalls

Four traps worth knowing before week one.

One agent profile for the whole crew. Simpler to set up, expensive in lost isolation and attribution. Create one Blockchain0x agent per CrewAI agent that pays, and run one proxy per wallet.

Putting the budget in the prompt. "Spend at most five dollars" in a backstory is a suggestion a crafted input can talk past. The dashboard spend limit is the real boundary. The prompt shapes behavior; the wallet controls money.

Exposing the proxy beyond localhost. The proxy holds a wallet key and pays whatever URL it is handed. Bind it to 127.0.0.1, never 0.0.0.0, and do not put it behind a public ingress. Treat it like a credential, because it is one.

Skipping the verification badges. The wallet works without them, but a counterparty deciding whether to accept your agent's payment looks at its public profile. The GitHub and domain badges take about five minutes each via the verify-agent-identity guide and change how merchants treat a new agent.

What to ship today

The shortest path from "I have a CrewAI crew" to "my crew pays for its tools":

  1. Start one pay-proxy.mjs per agent wallet, each with its own sk_test_ key.
  2. Point one BaseTool._run at its proxy.
  3. Add the tool to the agent's tools list and run kickoff().
  4. Set a dashboard spend limit before you switch to sk_live_.

That is the integration. If your crew is itself a paid service that charges external callers, the receive side lives in the crewai-payment-integration page. For the Node-native version of this pattern, how-to-add-payments-to-langchain-agent wires the x402 client straight into the tool with no proxy.

FAQ

Frequently asked questions.

Why a Node proxy instead of a Python package?

The x402 payment client ships for Node today (@blockchain0x/x402). CrewAI is Python. Rather than invent a Python client that does not exist yet, you run one small Node process that holds the wallet and answers 402s, and your CrewAI tools call it over localhost. It is about thirty lines and one process per host, and it keeps every payment identifier on the verified Node surface.

Do I need a wallet per agent or per crew?

Per agent is the right granularity for most crews. A crew is a group of cooperating agents; each has its own role and its own budget. If every agent shares one wallet you lose attribution, and a single prompt-injected agent can burn the whole crew's allowance. Per agent gives you isolation and per-role limits. Point each agent's tools at a proxy started with that agent's key.

What about hierarchical crews where one agent delegates to others?

That is an agent-to-agent payment pattern. The manager agent can pay a delegate for a sub-task the same way it pays an external endpoint: the delegate exposes a paid route, the manager's proxy settles it. Each delegate has its own wallet and its own spend limit, which is the cleanest way to attribute cost across a multi-agent crew without building a billing layer.

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. The only payment scheme today is exact-usdc.

Can multiple agents in a crew use the same paid tool?

Yes. Run one proxy per agent (each with that agent's key), and give each agent a tool that points at its own proxy port. Every agent then settles and is billed on its own wallet, so attribution stays clean even when two agents call the same upstream API at the same time.

How do I bound what an agent can spend?

Set the spend limit in the dashboard. The wallet enforces it server-side before settlement, so a call that would break the per-transaction or period allowance is rejected before any USDC moves. You can read the active limits back with GET /v1/agents/:agentId/spend-permissions to confirm what is enforced.

Create your free agent wallet in 5 minutes.

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