LlamaIndex payment integration.
There is no LlamaIndex package, and you do not need one. Wrap the real blockchain0x client in a FunctionTool and your agent can move USDC and gate a paid RAG query on Base.
There is no LlamaIndex-specific package, and you do not need one. LlamaIndex turns a plain function into a tool with , so you wrap the real Python client in a function and add it to a or . The agent can send USDC, settle invoices, and read wallets. To charge per RAG query, gate your own QueryEngineTool the same way. Payments settle on Base.
RAG queries are expensive. Charging per query makes the economics work.
LlamaIndex's strength is retrieval-augmented generation: you have a vector index over proprietary documents (your company's docs, a research dataset, a legal corpus), and the agent answers by retrieving and summarizing the relevant chunks. Each query costs real money in embeddings, LLM tokens, and often third-party API calls. Free unlimited access burns budget; per-query billing fits the cost shape.
There is no shipped helper for this, and you do not need one. You gate it yourself: inside your QueryEngineTool's function, check whether the caller has paid (your own flag, flipped by the payment webhook) and either run the retrieval or return a price. The wallet function and the gating are both a few lines over the real blockchain0x client, which keeps the policy - per query, per session, free tier then paid - entirely in your hands.
Install LlamaIndex and the core SDK. One environment variable.
There is no blockchain0x LlamaIndex package to add. You install LlamaIndex (Python 3.10+, the modern FunctionAgent / ReActAgent / Workflows APIs) and the real blockchain0x core SDK, then write the function below. Works alongside any vector store - Pinecone, Qdrant, Chroma, Weaviate, LlamaIndex Cloud.
pip install llama-index blockchain0xexport 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 dashboard; the client reads it from the environment. If you gate paid queries, the webhook handler additionally needs BLOCKCHAIN0X_WEBHOOK_SECRET, which the dashboard returns once when you create or rotate a webhook.
A function that pays, wrapped as a FunctionTool.
Below is the whole integration. send_usdc calls the real blockchain0x client; FunctionTool.from_defaults wraps it, and FunctionAgent picks it up as a callable tool. LlamaIndex reads the type hints and docstring to build the schema. Add your own QueryEngineTool to the list and the same agent can answer RAG queries too.
from llama_index.core.tools import FunctionTool from llama_index.core.agent.workflow import FunctionAgent from llama_index.llms.openai import OpenAI from blockchain0x import Client blockchain0x = Client() # reads BLOCKCHAIN0X_API_KEY from the environment def send_usdc(agent_id: str, to: str, amount_wei: str) -> str: """Send a USDC payment from an agent wallet. amount_wei is USDC base units (6 decimals), so "10000" is 0.01 USDC. """ return str( blockchain0x.payments.create(body={"agentId": agent_id, "to": to, "amountWei": amount_wei}) ) # Wrap the plain function as a LlamaIndex tool. No dedicated package needed. pay_tool = FunctionTool.from_defaults(fn=send_usdc) agent = FunctionAgent( tools=[pay_tool], # plus your own QueryEngineTool over a RAG index llm=OpenAI(model="gpt-4o"), system_prompt="You pay vendor invoices in USDC within owner-set limits.", ) response = await agent.run( "Pay 0.01 USDC from agent agt_123 to 0xVendor for the dataset." )
When the agent decides to pay, it calls send_usdc, the SDK submits the transfer, and you get a transaction hash back. amount_wei is base units, so 0.01 USDC is "10000". A sk_test_ key keeps it on Base Sepolia until you switch to sk_live_. To charge for a query instead, put the same paid check at the top of your QueryEngineTool's function.
Flip the paid flag when the webhook lands.
When a payment settles, Blockchain0x POSTs a signed payment.received event to your webhook URL. The verify helper ships in the Node SDK; in a Python service you verify by hand against the documented HMAC. Mark the caller paid in your own store, and your gated query tool lets the next call through. FastAPI example below.
import hmac, hashlib, os, time from fastapi import FastAPI, Request, HTTPException app = FastAPI() SECRET = os.environ["BLOCKCHAIN0X_WEBHOOK_SECRET"].encode() @app.post("/webhooks/payment") async def receive(request: Request): raw = await request.body() # RAW bytes - do not parse first sig = request.headers.get("X-Blockchain0x-Signature", "") ts = request.headers.get("X-Blockchain0x-Timestamp", "") 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: raise HTTPException(status_code=401) if request.headers.get("X-Blockchain0x-Event-Type") == "payment.received": await trigger_followup() # USDC landed - serve the paid query return {"ok": True}
The algorithm is HMAC-SHA256 over the string t.rawBody, a constant-time compare, and a 300-second replay window. Read the raw body via await request.body(), never request.json() re-serialized, because that changes the bytes the signature covers. The shipped events are payment.received, payment.sent, wallet.deployed, and webhook.test. For heavy follow-up work, enqueue a job (Celery, arq) and respond 200 immediately rather than blocking the handler.
The client you are wrapping is open. Read it.
There is no LlamaIndex starter package to clone - the recipe above is the integration. The blockchain0x SDKs are open source on GitHub; this recipe wraps the Python SDK (blockchain0x-python), with the full method surface in the docs. Read it for a reference for the function bodies.
github.com/tosh-labs/blockchain0x-pythonThe full SDK method surface and scopes are documented at the docs. Start on a sk_test_ key against Base Sepolia, then switch to sk_live_ when the function does what you expect.
Five LlamaIndex-specific traps to avoid.
These come from our support inbox. Each saves at least an hour of debugging once you know about it.
There is no LlamaIndex package - you wrap the SDK
Blockchain0x ships adapters for LangChain and CrewAI plus the MCP server; there is no dedicated LlamaIndex package. The recipe above is the path: a plain typed function that calls the real blockchain0x client, wrapped with FunctionTool.from_defaults. LlamaIndex reads the signature and docstring to build the schema, so keep the docstring accurate.
Gate a QueryEngineTool yourself - no helper does it
The paid-RAG pattern is real and good, but there is no paid_query_engine_tool helper. You build it: in your query tool's function, check whether the caller has paid (your own store, updated by the webhook below) and only run the retrieval if they have, otherwise return a price. It is a few lines, and you keep control of the gating policy.
Amounts are USDC base units, as strings
payments.create takes amountWei: a string of USDC base units, not a float. USDC has 6 decimals, so 0.01 USDC is "10000" and 5 USDC is "5000000". Type the tool argument as str. LlamaIndex passes tool args through pydantic, which will happily coerce a float and lose precision, so keep it a string end to end.
FunctionAgent.run is async; the SDK call is sync
LlamaIndex agents are async-first - await agent.run(...). The blockchain0x client call inside your tool is synchronous, which is fine for a single quick payment but blocks the loop under load. If you are serving many concurrent queries, wrap the SDK call with asyncio.to_thread so the event loop stays responsive.
send_payment can answer 503 early on
payments.create does not retry by default and can return 503 until the chain adapter is wired for your network. Catch the error inside your tool function and return a clear message the model can act on, rather than letting the agent loop. The auto-minted idempotency key means a manual retry will not double-pay.