Integrazione dei pagamenti Pydantic AI.
Non esiste un pacchetto Pydantic AI, e non ne hai bisogno. Registra una funzione tipizzata con @agent.tool_plain, chiama il vero client blockchain0x, e il tuo agente può muovere USDC su Base.
Non esiste un package specifico per Pydantic AI, e non ne hai bisogno. Pydantic AI trasforma una funzione in uno strumento validato con , quindi avvolgi il vero client Python in una funzione tipizzata e l'agente può inviare USDC, saldare fatture e leggere i wallet. Funziona con OpenAI, Anthropic, Google, Mistral, Groq e ogni altro provider Pydantic AI, perché lo strumento chiama l'HTTP API, non il modello. I pagamenti si regolano su Base.
Il typing di Pydantic AI vince. Usalo anche per i pagamenti.
L'intero punto di Pydantic AI è il forte typing: gli input degli agenti sono tipizzati, le uscite sono tipizzate, le dipendenze sono tipizzate, i retry sono tipizzati. Il framework rifiuta i dati malformati al confine invece di lasciarli propagare attraverso la chiamata LLM. Il tuo strumento wallet si basa esattamente su questo - dichiara gli argomenti con i tipi, e Pydantic AI costruisce uno schema validato dalla firma e dalla docstring prima che il modello possa mai chiamarlo.
Il beneficio pratico: se il modello tenta di chiamare send_usdc con un float invece di una stringa di unità base, il fallimento avviene al livello di validazione di Pydantic prima di qualsiasi chiamata HTTP a noi. Vedi un chiaro ValidationError con un messaggio utile piuttosto che un 422 dall'API con percorsi di campo criptici. Questo è il motivo principale per cui avvolgere il client da solo qui piuttosto che cercare un adattatore generico - mantieni la digitazione fino alla connessione.
Installa Pydantic AI e il core SDK. Due chiavi.
Non esiste un pacchetto blockchain0x Pydantic AI da aggiungere. Installa Pydantic AI (Python 3.10+) e il vero core SDK blockchain0x, quindi scrivi la funzione qui sotto. Questa è l'intera lista delle dipendenze.
pip install pydantic-ai blockchain0xexport OPENAI_API_KEY=sk-... export BLOCKCHAIN0X_API_KEY=sk_test_... # sk_test_ = Base Sepolia, sk_live_ = Base mainnet
OPENAI_API_KEY (o l'equivalente per qualunque provider tu usi). BLOCKCHAIN0X_API_KEY è una chiave sk_test_ per testnet o sk_live_ per mainnet dalla tua dashboard; il client la legge dall'ambiente. Se il tuo agent riceve anche denaro, l'handler del webhook richiede inoltre BLOCKCHAIN0X_WEBHOOK_SECRET.
Una funzione tipizzata che paga, registrata come strumento.
Di seguito è l'intera integrazione. send_usdc chiama il reale client blockchain0x; @agent.tool_plain lo registra con uno schema costruito dagli suggerimenti di tipo e dalla docstring. Eseguilo e l'agente sposta USDC su Base, con gli argomenti convalidati prima della chiamata.
from pydantic_ai import Agent from blockchain0x import Client blockchain0x = Client() # reads BLOCKCHAIN0X_API_KEY from the environment agent = Agent( "openai:gpt-4o", system_prompt="You pay vendor invoices in USDC within owner-set limits.", ) # Register a plain function as a tool. No dedicated package needed. @agent.tool_plain 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}) ) result = agent.run_sync( "Pay 0.01 USDC from agent agt_123 to 0xVendor for the dataset." ) print(result.output)
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_. Want a typed result object instead of a string? Set the agent's output_type to your own Pydantic model and return it from the tool. Add read and settle functions the same way.
Conferma i pagamenti in entrata con un webhook firmato.
Se il tuo agente riceve anche USDC, confermalo con il webhook piuttosto che tramite polling. L'helper di verifica è incluso nel Node SDK; in un servizio Python verifichi manualmente contro l'HMAC documentato. Se desideri eventi tipizzati, definisci il tuo modello Pydantic e model_validate_json il corpo raw dopo che la firma è stata verificata - la tipizzazione è tua da aggiungere. Esempio FastAPI qui sotto.
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 - run the next step return {"ok": True}
L'algoritmo è HMAC-SHA256 sulla stringa t.rawBody, un confronto a tempo costante e una finestra di replay di 300 secondi. Leggi il corpo grezzo tramite await request.body(), mai request.json() rieseguito, perché ciò cambia i byte coperti dalla firma. Gli eventi spediti sono payment.received, payment.sent, wallet.deployed e webhook.test; restringi sull'intestazione X-Blockchain0x-Event-Type per ramificare.
Il client che stai avvolgendo è aperto. Leggilo.
Non esiste un starter package Pydantic AI da clonare - la ricetta sopra è l'integrazione. Gli SDK blockchain0x sono open source su GitHub; questa ricetta incapsula il Python SDK (blockchain0x-python), con la superficie completa dei metodi nella documentazione. Consultala come riferimento per i body delle funzioni.
github.com/tosh-labs/blockchain0x-pythonLa superficie completa dei metodi dell'SDK e gli scope sono documentati in the docs. Inizia con una chiave sk_test_ su Base Sepolia, poi passa a sk_live_ quando la funzione si comporta come previsto.
Cinque trappole specifiche di Pydantic AI da evitare.
Il forte typing di Pydantic AI cattura la maggior parte dei bug di integrazione al confine; questi sono i pochi che sfuggono.
Non esiste un pacchetto Pydantic AI - registri uno strumento
Blockchain0x fornisce adattatori per LangChain e CrewAI oltre al server MCP; non esiste un pacchetto Pydantic AI dedicato. La ricetta sopra è il percorso: una funzione tipizzata semplice decorata con @agent.tool_plain che chiama il reale client blockchain0x. Pydantic AI legge la firma e la docstring per costruire uno schema di strumento convalidato, che è esattamente il vantaggio di tipizzazione per cui sei venuto a Pydantic AI.
Mantieni l'importo come stringa; lascia che Pydantic mantenga la linea
payments.create takes amountWei: a string of USDC base units (6 decimals), so 0.01 USDC is "10000" and 5 USDC is "5000000". Type the tool argument as str and Pydantic AI rejects a float at the boundary with a clear ValidationError, before any HTTP call. That is the whole point of doing this in Pydantic AI - the malformed value never reaches the API.
send_payment può rispondere 503 all'inizio
payments.create non ripete per impostazione predefinita e può restituire 503 fino a quando l'adattatore della catena non è collegato alla tua rete. Cattura l'errore all'interno del tuo strumento e restituisci un messaggio chiaro su cui il modello può agire, piuttosto che lasciare che l'agente continui a girare. La chiave di idempotenza auto-mintata significa che un tentativo manuale non comporterà un pagamento doppio.
Stringhe di modello con prefisso del fornitore
Pydantic AI utilizza stringhe di modello con prefisso del fornitore: 'openai:gpt-4o', 'anthropic:claude-3-5-sonnet-latest', 'google-gla:gemini-1.5-pro'. Omettere il prefisso dà un errore criptico 'modello sconosciuto'. Il tuo strumento è agnostico rispetto al fornitore perché chiama l'API HTTP, non il modello - scambia liberamente il prefisso e la funzione del wallet rimane invariata.
tool_plain vs tool (RunContext)
Usa @agent.tool_plain quando la funzione non ha bisogno di nulla dall'esecuzione, come sopra. Se vuoi le dipendenze dell'agente all'interno dello strumento (un ID client per richiesta, un limite di spesa), usa @agent.tool e dichiara il primo argomento come ctx: RunContext[Deps] per leggere ctx.deps. Mescolare i due - dichiarare un argomento ctx su tool_plain - solleva un TypeError durante la registrazione.