Skip to main content
PYDANTIC AI INTEGRATION

Pydantic AI payment integration.

Add USDC payments to any Pydantic AI agent. Strongly-typed tools, provider-agnostic, Pydantic models all the way down.

SHORT ANSWER

Blockchain0x provides drop-in payment tools for Pydantic AI agents via register_payment_tools(agent). Install blockchain0x-pydantic-ai, call the registration helper after constructing your Agent, and the agent can request and refund USDC payments. Works across OpenAI, Anthropic, Google, Mistral, Groq, and every other Pydantic AI provider. Payments settle on Base.

WHY TYPED PAYMENT TOOLS

Pydantic AI's typing wins. Use it for payments too.

Pydantic AI's whole point is strong typing: Agent inputs are typed, outputs are typed, dependencies are typed, retries are typed. The framework rejects malformed data at the boundary instead of letting it propagate through the LLM call. Our payment tools are built the same way - request_payment takes a Pydantic-validated amount_usdc string, returns a typed PaymentRequest object, and surfaces typed errors when something goes wrong.

The practical benefit: if your agent tries to call request_payment with a float instead of a decimal string, the failure happens at Pydantic's validation layer before any HTTP call to us. You see a clear ValidationError with a useful message rather than a 422 from the API with cryptic field paths. The tool also returns typed objects rather than dicts, so your downstream code gets autocomplete, mypy/pyright support, and clean refactoring.

INSTALLATION

One pip install. Four environment variables.

Targets Python 3.10+ and Pydantic AI 0.0.50+. Pydantic AI is a peer dependency; install it separately if not already present (pip install pydantic-ai).

INSTALL
pip install blockchain0x-pydantic-ai
ENVIRONMENT VARIABLES
export OPENAI_API_KEY=sk-...
export BLOCKCHAIN0X_API_KEY=sk_live_...
export BLOCKCHAIN0X_AGENT_ID=agt_abc123
export BLOCKCHAIN0X_SIGNING_SECRET=whsec_...

OPENAI_API_KEY (or the equivalent for whichever LLM provider you use). BLOCKCHAIN0X_API_KEY and BLOCKCHAIN0X_AGENT_ID come from the agent's settings page after creation in the Blockchain0x dashboard. BLOCKCHAIN0X_SIGNING_SECRET is needed only in the FastAPI process that handles webhooks.

FULL AGENT EXAMPLE

A typed agent with payment-pending output state.

Below is a complete Pydantic AI agent with a typed ResearchOutput that can represent either payment-pending or delivered states, a typed Deps for client info, and the payment tools registered via the helper.

AGENT.PY
from pydantic_ai import Agent, RunContext
from pydantic import BaseModel
from blockchain0x.pydantic_ai import register_payment_tools

class ResearchOutput(BaseModel):
    payment_url: str | None = None
    report_summary: str | None = None
    status: str  # "payment_pending" | "delivered"

class Deps(BaseModel):
    client_id: str
    amount_usdc: str = "5.00"

agent = Agent[Deps, ResearchOutput](
    "openai:gpt-4o",
    deps_type=Deps,
    output_type=ResearchOutput,
    system_prompt=(
        "You produce paid research reports. Before doing any research, "
        "use request_payment to charge the client. Return ResearchOutput "
        "with payment_url and status='payment_pending'. Wait for the "
        "webhook to trigger a follow-up run before delivering the report."
    ),
)

register_payment_tools(agent)

result = await agent.run(
    "Write me a Q4 LLM market analysis.",
    deps=Deps(client_id="client_xyz", amount_usdc="5.00"),
)
print(result.output)  # Pydantic-validated ResearchOutput

When the agent runs, the LLM reads the system prompt, calls request_payment via the registered tool, populates payment_url and status="payment_pending", and returns a fully-typed ResearchOutput. The webhook handler later triggers a follow-up agent.run with status="delivered" and a report_summary populated. Both runs produce Pydantic-validated outputs you can serialize to JSON, store in a database, or pipe to downstream code.

WEBHOOK HANDLING

Typed webhook events all the way through.

Pydantic AI's typing extends to webhook handling. The SDK exports a PaymentEvent model that validates and types incoming events; you get autocomplete on event.data.payment_request_id rather than dict["data"]["payment_request_id"].

WEBHOOK.PY
from fastapi import FastAPI, Request, HTTPException
from blockchain0x.pydantic_ai import verify_webhook, PaymentEvent
import os

app = FastAPI()
SIGNING_SECRET = os.environ["BLOCKCHAIN0X_SIGNING_SECRET"]

@app.post("/webhooks/payment")
async def receive(request: Request):
    signature = request.headers.get("X-Blockchain0x-Signature", "")
    body = await request.body()
    if not verify_webhook(body, signature, SIGNING_SECRET):
        raise HTTPException(status_code=401)

    # Parse into a typed Pydantic event
    event = PaymentEvent.model_validate_json(body)
    if event.type == "payment.confirmed":
        await resume_research_for(event.data.payment_request_id)
    return {"ok": True}

PaymentEvent is a discriminated union over the five webhook event types (payment.requested, payment.received, payment.confirmed, payment.failed, agent.verified). After model_validate_json, narrowing on event.type gives you typed access to event.data fields specific to that event. verify_webhook does HMAC-SHA256 in constant time and accepts the raw body bytes.

STARTER REPOSITORY

Working example with classic Agent + Graph patterns.

A complete Pydantic AI repository at the GitHub link below. Includes the typed-output example above, a Pydantic AI Graph variant for multi-step workflows, a FastAPI webhook handler with PaymentEvent parsing, and a docker-compose stack with Redis for the resume-after-payment pattern.

github.com/blockchain0x/agent-wallet-pydantic-ai

Repository structure: agent.py (classic Agent), graph.py (Pydantic AI Graph variant), webhook.py (FastAPI), deps_store.py (Postgres-backed deps persistence), docker-compose.yml, README with provider-switching notes for OpenAI/Anthropic/Google.

COMMON PITFALLS

Five Pydantic AI-specific traps to avoid.

Pydantic AI's strong typing catches most integration bugs at the boundary; these are the few that slip through.

PITFALL 1

Mismatched output_type when payment is pending

Pydantic AI's output_type defines the strict schema for agent.run() return values. If your output_type includes a non-optional 'report' field but the agent returns a payment-pending state without the report, Pydantic raises a validation error before you see the partial output. Make payment-related fields Optional, or use a Union type (PaymentPending | ReportDelivered) so the agent can return either shape legally.

PITFALL 2

Deps singleton across runs

Pydantic AI's Deps mechanism is per-run; the same Deps instance is not shared across multiple agent.run() calls. For the resume-after-payment pattern, the webhook handler must reconstruct the Deps (looking up client_id and amount from the original payment_request_id). The starter repo includes a Postgres-backed deps store for this; do not try to keep Python globals around between the original run and the resume.

PITFALL 3

Streaming vs non-streaming

Pydantic AI supports both agent.run() (full result) and agent.run_stream() (streaming chunks). The payment tool works with both, but in streaming mode, the tool call appears as a tool-call delta in the stream, not as a complete tool result. If your UI consumes the stream and tries to extract hosted_url from a partial tool delta, you get a malformed URL. Wait for the stream to complete (or filter for tool-result events specifically) before reading the payment URL.

PITFALL 4

Model string format

Pydantic AI uses provider-prefixed model strings: 'openai:gpt-4o', 'anthropic:claude-3-5-sonnet-latest', 'google-gla:gemini-1.5-pro'. A common pitfall is omitting the provider prefix and getting a cryptic 'unknown model' error. The payment tools work across providers (the tool-call mechanic is provider-agnostic), but the prefix is required.

PITFALL 5

RunContext vs Deps confusion

Pydantic AI provides both RunContext (passed to tool functions, includes deps + retries + usage) and Deps (the typed dependency injection). Tools registered by register_payment_tools(agent) use RunContext internally to access your Deps. If you write a custom tool that needs to read deps, declare it as 'async def tool(ctx: RunContext[Deps], ...)' - the ctx.deps gives you the typed Deps. Confusing the two leads to TypeError on tool registration.

FREQUENTLY ASKED

Three Pydantic AI-specific questions.

Does this work across LLM providers (OpenAI, Anthropic, Google)?

Yes. The payment tools are provider-agnostic - they call the Blockchain0x HTTP API, not any LLM-specific surface. As long as Pydantic AI supports the underlying provider (which it does for OpenAI, Anthropic, Google GLA, Google VertexAI, Groq, Cohere, Mistral, Bedrock), the payment tools work without changes. Just swap the model string in the Agent constructor: 'anthropic:claude-3-5-sonnet-latest' instead of 'openai:gpt-4o'.

How do I use Pydantic models for the payment-request inputs?

register_payment_tools(agent) injects two tools with pre-defined Pydantic schemas: request_payment(amount_usdc: str, reason: str, callback_url: str | None) and refund_payment(payment_request_id: str, reason: str). If you want stricter validation (e.g. amount_usdc must be a valid decimal in dollars), wrap the tool with @agent.tool yourself using a custom Pydantic args model that delegates to our underlying SDK. The starter repo has an example showing this pattern with PaymentArgs model with constrained decimals.

What about Pydantic AI Graph for multi-step workflows?

Pydantic AI Graph is the newer graph-based execution model (similar to LangGraph). The payment tools work in Graph nodes the same way they do in Agent.run - register them on the relevant agent, attach the agent to a node. The pattern: a BillingNode that uses request_payment, transitions to a PaymentPendingState that waits on webhook events, transitions to a WorkNode when payment.confirmed arrives. The starter repo includes a Graph example for direct comparison with the classic Agent shape.

Add typed payments to your agent.

Five minutes from pip install to your first typed paid agent run. Pro at $9/agent/month.