Integración de pago Pydantic AI.
No hay paquete de Pydantic AI, y no necesitas uno. Registra una función tipada con @agent.tool_plain, llama al cliente real de blockchain0x, y tu agente puede mover USDC en Base.
No existe un paquete específico de Pydantic AI, y no lo necesitas. Pydantic AI convierte una función en una herramienta validada con , así que envuelves el cliente Python real de en una función tipada y el agente puede enviar USDC, liquidar facturas y leer wallets. Funciona con OpenAI, Anthropic, Google, Mistral, Groq y cualquier otro proveedor de Pydantic AI, porque la herramienta llama a la HTTP API, no al modelo. Los pagos se liquidan en Base.
La tipificación de Pydantic AI gana. Úsala también para pagos.
El objetivo de Pydantic AI es la tipificación fuerte: las entradas del agente están tipadas, las salidas están tipadas, las dependencias están tipadas, los reintentos están tipados. El framework rechaza datos mal formados en el límite en lugar de permitir que se propaguen a través de la llamada LLM. Tu herramienta de billetera se basa exactamente en eso - declara los argumentos con tipos, y Pydantic AI construye un esquema validado a partir de la firma y la docstring antes de que el modelo tenga permitido llamarlo.
El beneficio práctico: si el modelo intenta llamar a send_usdc con un float en lugar de una cadena de unidad base, el fallo ocurre en la capa de validación de Pydantic antes de cualquier llamada HTTP a nosotros. Ves un ValidationError claro con un mensaje útil en lugar de un 422 de la API con rutas de campo crípticas. Esa es la razón principal para envolver el cliente tú mismo aquí en lugar de recurrir a un adaptador genérico - mantienes la tipificación hasta el cable.
Instala Pydantic AI y el SDK principal. Dos claves.
No hay paquete de blockchain0x Pydantic AI para agregar. Instalas Pydantic AI (Python 3.10+) y el verdadero SDK principal de blockchain0x, luego escribes la función a continuación. Esa es toda la lista de dependencias.
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 el equivalente para cualquier proveedor que uses). BLOCKCHAIN0X_API_KEY es una clave sk_test_ de testnet o sk_live_ de mainnet de tu panel; el cliente la lee del entorno. Si tu agente también recibe dinero, el manejador de webhook necesita adicionalmente BLOCKCHAIN0X_WEBHOOK_SECRET.
Una función tipada que paga, registrada como una herramienta.
A continuación se presenta toda la integración. send_usdc llama al cliente real de blockchain0x; @agent.tool_plain lo registra con un esquema construido a partir de las sugerencias de tipo y la docstring. Ejecútalo y el agente mueve USDC en Base, con los argumentos validados antes de la llamada.
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.
Confirme los pagos entrantes con un webhook firmado.
Si tu agente también recibe USDC, confírmalo con el webhook en lugar de sondear. El ayudante de verificación se envía en el SDK de Node; en un servicio de Python verificas manualmente contra el HMAC documentado. Si deseas eventos tipados, define tu propio modelo Pydantic y model_validate_json el cuerpo crudo después de que la firma sea válida - la tipificación es tu responsabilidad añadirla. Ejemplo de FastAPI a continuación.
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}
El algoritmo es HMAC-SHA256 sobre la cadena t.rawBody, una comparación en tiempo constante y una ventana de repetición de 300 segundos. Lee el cuerpo sin procesar a través de await request.body(), nunca request.json() re-serializado, porque eso cambia los bytes que cubre la firma. Los eventos enviados son payment.received, payment.sent, wallet.deployed y webhook.test; estrecha en el encabezado X-Blockchain0x-Event-Type para ramificar.
El cliente que estás envolviendo es abierto. Léelo.
No hay un paquete de inicio de Pydantic AI para clonar - la receta anterior es la integración. Los SDK de blockchain0x son de código abierto en GitHub; esta receta envuelve el SDK de Python (blockchain0x-python), con la superficie completa de métodos en la documentación. Léelo como referencia para los cuerpos de las funciones.
github.com/tosh-labs/blockchain0x-pythonLa superficie completa de métodos del SDK y los alcances están documentados en la documentación. Comienza con una clave sk_test_ contra Base Sepolia, luego cambia a sk_live_ cuando la función haga lo que esperas.
Cinco trampas específicas de Pydantic AI a evitar.
La fuerte tipificación de Pydantic AI captura la mayoría de los errores de integración en el límite; estos son los pocos que se escapan.
No hay paquete de Pydantic AI - registras una herramienta
Blockchain0x envía adaptadores para LangChain y CrewAI además del servidor MCP; no hay un paquete dedicado de Pydantic AI. La receta anterior es el camino: una función tipada simple decorada con @agent.tool_plain que llama al cliente real de blockchain0x. Pydantic AI lee la firma y la docstring para construir un esquema de herramienta validado, que es exactamente la ventaja de tipado por la que vino a Pydantic AI.
Mantén el monto como una cadena; deja que Pydantic mantenga la línea
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 puede responder 503 temprano
payments.create no reintenta por defecto y puede devolver 503 hasta que el adaptador de cadena esté conectado a su red. Capture el error dentro de su herramienta y devuelva un mensaje claro que el modelo pueda utilizar, en lugar de dejar que el agente se repita. La clave de idempotencia generada automáticamente significa que un reintento manual no pagará el doble.
Cadenas de modelo con prefijo de proveedor
Pydantic AI utiliza cadenas de modelo con prefijo de proveedor: 'openai:gpt-4o', 'anthropic:claude-3-5-sonnet-latest', 'google-gla:gemini-1.5-pro'. Omitir el prefijo da un error críptico de 'modelo desconocido'. Tu herramienta es agnóstica al proveedor porque llama a la API HTTP, no al modelo - cambia el prefijo libremente y la función de billetera no cambia.
tool_plain vs tool (RunContext)
Usa @agent.tool_plain cuando la función no necesita nada de la ejecución, como arriba. Si deseas las dependencias del agente dentro de la herramienta (un id de cliente por solicitud, un límite de gasto), usa @agent.tool y declara el primer argumento como ctx: RunContext[Deps] para leer ctx.deps. Mezclar los dos - declarar un argumento ctx en tool_plain - genera un TypeError en el registro.