Skip to main content
CREWAI INTEGRATION

CrewAI payment integration.

Give a CrewAI crew a wallet. A dedicated treasurer agent sends USDC, settles invoices, and reads balances while the work agents stay focused on the work.

SHORT ANSWER

Blockchain0x ships a real Python package, . Install it, set , call , and hand the tools to a dedicated treasurer agent. That agent can send USDC, settle an invoice with on-chain proof, and read wallets, while the work agents in the crew carry no wallet access. USDC settles on Base.

WHY A DEDICATED TREASURER ROLE

CrewAI's strength is role separation. Use it for the wallet too.

Other frameworks pile every tool onto a single agent. CrewAI's design encourages role separation: a researcher researches, a writer writes, a reviewer reviews. Money deserves the same treatment - a dedicated treasurer agent holds the wallet tools, and the work agents hold none. Spending authority lives in one place instead of leaking across every agent that happens to be in the crew.

This shape also makes audit trails clearer. When USDC moves, you know exactly which agent moved it (the treasurer) and which task it was for (the one that handed off to it). Single-agent integrations blur that line and make per-task spend analytics harder.

INSTALLATION

One pip install. One environment variable.

The package needs Python 3.10 or newer and works with poetry or pip. It pulls in the core blockchain0x SDK and crewai as dependencies; nothing else to add.

INSTALL
pip install blockchain0x-crewai
ENVIRONMENT VARIABLES
export BLOCKCHAIN0X_API_KEY=sk_test_...   # sk_test_ = Base Sepolia, sk_live_ = Base mainnet

BLOCKCHAIN0X_API_KEY is a sk_test_ testnet or sk_live_ mainnet key from your Blockchain0x dashboard, and it is the only variable the adapter needs - it forwards the key to the backend and holds no secret of its own. For the webhook handler below you also set BLOCKCHAIN0X_WEBHOOK_SECRET, which the dashboard returns once when you create or rotate a webhook.

FULL CREW EXAMPLE

A working two-agent crew with billing + research roles.

Below is a complete CrewAI crew where a treasurer agent pays a data vendor in USDC, and a researcher agent uses the result. The treasurer holds the wallet tools; the researcher holds none. This is the canonical pattern for a crew that spends.

CREW.PY
from crewai import Agent, Task, Crew
from blockchain0x import Client
from blockchain0x_crewai import create_blockchain0x_toolset

client = Client()  # reads BLOCKCHAIN0X_API_KEY from the environment
tools = create_blockchain0x_toolset(client)

# A dedicated treasurer holds the wallet tools; the work agents do not.
treasurer = Agent(
    role="Treasurer",
    goal="Pay vendor invoices in USDC within owner-set limits",
    backstory="Operates a Blockchain0x agent wallet on Base.",
    tools=tools,
    allow_delegation=False,
)

researcher = Agent(
    role="Senior Market Analyst",
    goal="Produce a thorough Q4 LLM market analysis",
    backstory="A specialist analyst with 10 years in tech-market research.",
    tools=[],
    allow_delegation=False,
)

pay_task = Task(
    description="Pay 0.01 USDC from our agent wallet to the data vendor at 0xVendor.",
    expected_output="The transaction hash of the settled payment.",
    agent=treasurer,
)

research_task = Task(
    description="Using the purchased dataset, write the Q4 LLM market analysis.",
    expected_output="A 1,500-word market analysis.",
    agent=researcher,
    context=[pay_task],
)

crew = Crew(agents=[treasurer, researcher], tasks=[pay_task, research_task])
result = crew.kickoff()

When you call crew.kickoff(), the pay_task runs first: the treasurer calls blockchain0x_send_payment, the SDK submits the transfer on Base, and the transaction hash is the task output. The research_task runs next and uses the purchased result. amount_wei is USDC base units, so 0.01 USDC is the string "10000". On a sk_test_ key the whole flow runs on Base Sepolia, and payments.create can answer 503 until the chain adapter is wired for your network.

WEBHOOK HANDLING

Triggering the next crew when a payment lands.

When USDC settles to your agent, Blockchain0x POSTs a signed event to your webhook URL. The verify helper ships in the Node SDK; a Python service verifies by hand against the documented HMAC, which is all the helper does anyway. Flask example below; the same code works in FastAPI or any Python web framework.

WEBHOOK_HANDLER.PY
import hmac, hashlib, os, time
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = os.environ["BLOCKCHAIN0X_WEBHOOK_SECRET"].encode()

@app.post("/webhooks/payment")
def receive():
    raw = request.get_data()  # RAW bytes - do not parse first
    sig = request.headers.get("X-Blockchain0x-Signature", "")
    ts = request.headers.get("X-Blockchain0x-Timestamp", "")
    # Header is "t=<unix>,v1=<hex>"; some proxies send bare hex + the ts header.
    parts = dict(p.split("=", 1) for p in sig.split(",") if "=" in p)
    t, v1 = parts.get("t", ts), parts.get("v1", sig)
    want = hmac.new(SECRET, t.encode() + b"." + raw, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(want, v1) or abs(time.time() - int(t)) > 300:
        abort(401)
    if request.headers.get("X-Blockchain0x-Event-Type") == "payment.received":
        run_followup_for(request.get_json())  # USDC landed - do the work
    return "ok", 200

This is the real algorithm: HMAC-SHA256 over the string t.rawBody, a constant-time compare, and a 300-second replay window. Read the raw body (request.get_data()), never request.get_json() re-serialized, because that changes the bytes the signature covers. Architecture: have the handler enqueue a job (Celery, RQ, a Redis list) that triggers the actual CrewAI run. Calling crew.kickoff() inside the handler can take minutes and times out the HTTP request.

ONE TOOL, OR ALL FIVE

Hand the crew the whole toolset, or just one tool.

create_blockchain0x_toolset returns all five tools: blockchain0x_send_payment, blockchain0x_settle_invoice, blockchain0x_get_wallet, blockchain0x_list_wallets, and blockchain0x_get_transaction. If a crew only needs to pay, give it just that one with a single factory.

SINGLE_TOOL.PY
from blockchain0x_crewai import create_payment_tool

pay = create_payment_tool(client)
# amount_wei is USDC base units: 6 decimals, so 10000 = 0.01 USDC.
pay.run(agent_id="agt_123", to="0xRecipient", amount_wei="10000")

The per-capability factories are create_payment_tool, create_invoice_tool, create_wallet_tool, create_wallets_list_tool, and create_transaction_tool. Source and testnet examples live at the Python SDK repo; the CrewAI support matrix is at the docs.

COMMON PITFALLS

Five things to watch when wiring billing into a crew.

CrewAI's role-based design is what makes payment integration cleaner than other frameworks. It also has its own footguns. Knowing these in advance saves time.

PITFALL 1

Putting the wallet tools on the wrong agent

CrewAI agents have roles. Hand the wallet tools to the researcher, who should be researching, and the LLM starts trying to move money mid-analysis. The clean pattern is a dedicated treasurer agent that holds the tools and runs as its own task; the work agents carry no wallet access at all. The example above follows that shape. Copy it.

PITFALL 2

Sequential vs hierarchical processes

CrewAI supports sequential (default) and hierarchical execution. With hierarchical, a manager agent orchestrates the crew. If the manager is allowed to delegate the wallet tools, it can hand them to any subordinate, which is exactly what you do not want for spending authority. Either keep the tools on one dedicated agent and run sequential, or restrict the manager's delegation rules.

PITFALL 3

Reading settlement status from task context

Inbound settlement is asynchronous. If the research task lists the pay task in its context (fine) but the LLM then tries to read a final payment status from that context (not fine, the confirmation arrives later by webhook), you get muddled output. Gate the downstream work on a webhook-triggered signal, not on task context. CrewAI's task callbacks are the right hook.

PITFALL 4

Amounts are USDC base units, as strings

blockchain0x_send_payment takes amount_wei: a string of USDC base units, not a float and not a dollar figure. USDC has 6 decimals, so 0.01 USDC is "10000". CrewAI passes tool inputs through as-is, so a Python float arrives as a float and the SDK rejects it - but the error reads like a CrewAI tool error, which throws off first integrators. Pass a string.

PITFALL 5

Webhook handler outside the crew process

Your webhook handler is usually a separate Flask or FastAPI process, not part of the crew runtime. The crew finishes its kickoff() and returns; the webhook lands later when a payment settles. Bridge the two with a queue or a database row the webhook writes and the crew reads on its next run. Do not keep a crew alive waiting on a webhook - CrewAI runs are short-lived by design.

FREQUENTLY ASKED

Three CrewAI-specific questions.

Does this work with CrewAI Flows (the newer graph-based execution)?

Yes. create_blockchain0x_toolset returns standard CrewAI tools, so they work in classic Crew + Task structures and in CrewAI Flow's @start/@listen patterns. In Flow, put the payment or settlement step on a dedicated treasurer step before the work steps, and have the work steps listen on a Flow event that fires once your webhook handler updates the shared state.

Can the same crew run multiple paid tasks concurrently?

Yes. payments.create (which blockchain0x_send_payment wraps) auto-mints a stable Idempotency-Key, so a retried submission collapses to a single on-chain transfer rather than double-paying. If you fan out concurrent kickoffs that each move money, give each its own intent (distinct recipients or metadata) so they do not look like duplicates of one another. You do not manage the idempotency header yourself unless you want to dedupe across processes.

Can the crew settle invoices, and is there a refund tool?

It can settle: blockchain0x_settle_invoice settles a payment request you created in the dashboard and records the on-chain proof (tx hash, payer, verified USDC amount). There is no refund helper - that identifier does not exist. To return funds, the treasurer simply sends a new USDC payment back to the payer with blockchain0x_send_payment. Keep that on the treasurer role so spending authority stays in one place.

Add a billing role to your crew.

From pip install to your first paid crew kickoff in minutes. Free to start.