Skip to main content
LLAMAINDEX INTEGRATION

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.

SHORT ANSWER

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.

WHY LLAMAINDEX FITS PAID RAG

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.

INSTALLATION

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.

INSTALL
pip install llama-index blockchain0x
ENVIRONMENT VARIABLE
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 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.

THE RECIPE

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.

AGENT.PY
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.

WEBHOOK HANDLING

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.

WEBHOOK.PY
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.

SOURCE AND DOCS

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-python

The 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.

COMMON PITFALLS

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.

PITFALL 1

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.

PITFALL 2

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.

PITFALL 3

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.

PITFALL 4

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.

PITFALL 5

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.

FREQUENTLY ASKED

Three LlamaIndex-specific questions.

Is there a dedicated LlamaIndex package to install?

No. LlamaIndex already turns a plain function into a tool with FunctionTool.from_defaults, so the honest path is to wrap the real blockchain0x client yourself, as shown above. The only shipped framework packages are blockchain0x-langchain and blockchain0x-crewai (both Python) plus the @blockchain0x/mcp server. LlamaIndex, like the other frameworks without a dedicated adapter, is this few-line recipe.

How do I charge per RAG query (the paid QueryEngine pattern)?

Build it yourself - there is no shipped helper for it, and it is only a few lines. Wrap your QueryEngineTool's function so it first checks whether the caller has paid (a flag in your own store that the webhook below flips on payment.received) and either runs the retrieval or returns a price challenge. That keeps the gating policy in your hands: per query, per session, free tier then paid, whatever fits.

Does the recipe work with LlamaIndex Workflows too?

Yes. The payment logic is a plain function, so nothing ties it to a particular agent primitive. Call it from a ReActAgent, a FunctionAgent, or a step in a LlamaIndex Workflow. In a Workflow, a natural shape is to call send_usdc (or your gated query) inside a step and emit the result as an event the next step consumes. Inbound payments confirm via the payment.received webhook below.

Charge for your RAG responses.

Wrap the real client in a FunctionTool, gate your query the same way. Free to start.