Saltar al contenido principal
INTEGRACIÓN DE LANGGRAPH

Integración de pagos de LangGraph.

No se necesita ningún paquete LangGraph. Un nodo simple llama al cliente real de blockchain0x, interrupt() se suspende hasta que el webhook de pago llegue, y el gráfico se reanuda - duradero a través de ejecuciones.

RESPUESTA CORTA

No existe un paquete de LangGraph, y no lo necesitas. Un nodo simple en tu llama al cliente real de , un suspende el grafo hasta que llega el webhook de pago, y el handler lo reanuda con los propios + de LangGraph. Los pagos se liquidan en Base.

POR QUÉ LANGGRAPH SE ADAPTA A ESTE PATRÓN

La ejecución duradera hace que el patrón de reanudación después del pago sea natural.

La parte difícil de los pagos impulsados por agentes es la brecha asíncrona: solicitas el pago, el comprador paga minutos después (o nunca), y tienes que reanudar el trabajo sin perder el estado de dónde estabas. La mayoría de los marcos de agentes dependen de una cola de trabajos + un almacén de estado manual para cerrar esta brecha. LangGraph ya tiene el primitivo incorporado: interrupt() suspende un gráfico en un nodo y un checkpointer persiste el estado en el disco. Reanudar es una llamada.

La receta se basa en esto sin maquinaria especial. Un nodo de pago simple llama a blockchain0x.payments.create. Un nodo await_settlement llama a interrupt() para suspender, y el checkpointer persiste el estado. El manejador de webhook verifica la firma, establece settled en el hilo correspondiente con graph.updateState, y llama a graph.invoke para continuar desde la interrupción. El gráfico retoma exactamente donde lo dejó, incluyendo cualquier contexto LLM de nodos anteriores - todo usando las propias APIs de LangGraph.

INSTALACIÓN

Instala LangGraph y el SDK principal. Sin paquete adicional.

Node 18+ y @langchain/langgraph 0.2+ más el cliente real @blockchain0x/node. No hay un adaptador LangGraph para agregar en ningún idioma - los usuarios de Python LangGraph instalan langgraph y el cliente Python de blockchain0x y escriben la misma receta, con interrupt() y Command(resume=...) en el lado de Python.

INSTALAR
npm install @langchain/langgraph @blockchain0x/node
VARIABLES DE ENTORNO
export BLOCKCHAIN0X_API_KEY=sk_test_...        # sk_test_ = Base Sepolia, sk_live_ = Base mainnet
export BLOCKCHAIN0X_WEBHOOK_SECRET=...          # for the webhook handler

BLOCKCHAIN0X_API_KEY es una clave sk_test_ testnet o sk_live_ mainnet de tu panel de control; el cliente la lee del entorno. BLOCKCHAIN0X_WEBHOOK_SECRET (devuelto una vez cuando creas o rotas un webhook) es necesario en el proceso que maneja los webhooks. Si tu gráfico se ejecuta en un proceso y el manejador en otro, ambos necesitan el mismo checkpointer (por ejemplo, Postgres compartido) para que el manejador pueda encontrar el hilo suspendido.

EJEMPLO COMPLETO DE GRÁFICO

Un gráfico de tres nodos: pagar, suspender, entregar.

A continuación se muestra un flujo de trabajo completo de LangGraph con un Estado tipado, un nodo de pago que llama a la verdadera blockchain0x.payments.create, un nodo await_settlement basado en interrupciones, y un nodo de entrega que ejecuta el trabajo dependiente una vez que la cadena confirma que el pago se movió.

GRAPH.TS
import { StateGraph, START, END, MemorySaver, interrupt, Annotation } from "@langchain/langgraph";
import { createClient } from "@blockchain0x/node";

const blockchain0x = createClient({ apiKey: process.env.BLOCKCHAIN0X_API_KEY! });

const State = Annotation.Root({
  agentId: Annotation<string>(),
  to: Annotation<string>(),
  amountWei: Annotation<string>(), // USDC base units: "10000" = 0.01 USDC
  settled: Annotation<boolean>(),
});

// A plain node that calls the real SDK. No dedicated package needed.
async function pay(state: typeof State.State) {
  await blockchain0x.payments.create({
    agentId: state.agentId,
    to: state.to,
    amountWei: state.amountWei,
  });
  return {};
}

// Suspend the graph until the payment.sent webhook resumes this thread.
function awaitSettlement() {
  interrupt("awaiting on-chain settlement");
  return {};
}

async function deliver() {
  // Funds have moved - do the work that depended on the payment.
  return {};
}

const graph = new StateGraph(State)
  .addNode("pay", pay)
  .addNode("await_settlement", awaitSettlement)
  .addNode("deliver", deliver)
  .addEdge(START, "pay")
  .addEdge("pay", "await_settlement")
  .addConditionalEdges("await_settlement", (s) => (s.settled ? "deliver" : END))
  .addEdge("deliver", END)
  .compile({ checkpointer: new MemorySaver() });

When the graph runs, the pay node submits the USDC transfer through the SDK. The await_settlement node calls interrupt(), which suspends the graph and persists state via the checkpointer. The conditional edge waits to be told settled=true before routing to deliver; if settlement never lands, a timeout sweep routes it to END. amountWei is base units, so 0.01 USDC is "10000".

MANEJO DE WEBHOOK

Verifica el webhook, luego reanuda el hilo.

El controlador verifica la firma con webhooks.verify del SDK de Node, busca el hilo suspendido de LangGraph de tu propio mapeo, establece settled con graph.updateState y llama a graph.invoke(null, config) para continuar desde la interrupción. No hay ayudante especial - esas son las propias APIs de LangGraph.

WEBHOOK.TS
import express from "express";
import { webhooks } from "@blockchain0x/node";
import { graph } from "./graph";

const app = express();
// Capture the RAW body. The HMAC is over the exact bytes on the wire.
app.use(express.raw({ type: "application/json" }));

app.post("/webhooks/payment", async (req, res) => {
  const result = webhooks.verify({
    headers: req.headers,
    rawBody: req.body, // Buffer, raw bytes
    secret: process.env.BLOCKCHAIN0X_WEBHOOK_SECRET!,
  });
  if (!result.ok) return res.status(400).json({ code: result.code });

  if (result.eventType === "payment.sent") {
    // You map the event to the suspended graph thread (your own store).
    const config = { configurable: { thread_id: threadFor(result.eventId) } };
    await graph.updateState(config, { settled: true });
    await graph.invoke(null, config); // resume from the interrupt
  }
  res.status(200).send("ok");
});

webhooks.verify hace HMAC-SHA256 en tiempo constante sobre el cuerpo raw y devuelve una unión discriminada - ramifica en result.ok, sin try/catch. Mapea result.eventId al hilo que suspendiste, luego graph.updateState + graph.invoke(null, config) reanuda desde el punto de control persistido y el gráfico ejecuta entregas. Los eventos enviados son payment.received, payment.sent, wallet.deployed, y webhook.test.

CÓDIGO Y DOCUMENTOS

El cliente que estás envolviendo es abierto. Léelo.

No hay un paquete de inicio de LangGraph 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 los nodos y la verificación del webhook.

github.com/tosh-labs/blockchain0x-python

La superficie completa de métodos del SDK y el esquema de firma de webhook están documentados en la documentación. Comienza con una clave sk_test_ contra Base Sepolia, luego cambia a sk_live_ una vez que el gráfico reanude como esperas.

ERRORES COMUNES

Cinco trampas específicas de LangGraph a evitar.

El modelo de ejecución duradera de LangGraph es poderoso, pero tiene sus propias trampas en torno a puntos de control, interrupciones y actualizaciones de estado.

PITFALL 1

No hay paquete LangGraph - un nodo simple llama al SDK

Blockchain0x envía adaptadores para LangChain y CrewAI además del servidor MCP; no hay un paquete dedicado de LangGraph, en npm o pip. La receta anterior es el camino: un nodo de gráfico ordinario llama al cliente real de @blockchain0x/node, y usted continúa con el propio graph.updateState + graph.invoke de LangGraph. No hay una clase especial de nodo de pago ni un ayudante de reanudación para importar - esos nunca existieron.

PITFALL 2

Falta el checkpointer

El interrupt() de LangGraph solo funciona si el gráfico tiene un checkpointer. Sin uno, el estado se evapora cuando tu proceso sale y el controlador de webhook no tiene hilo para reanudar. Usa MemorySaver para desarrollo y SqliteSaver o PostgresSaver en producción. Si tu gráfico y el controlador de webhook se ejecutan en diferentes procesos, deben compartir el mismo checkpointer (por ejemplo, uno Postgres) para que el controlador pueda encontrar el hilo suspendido.

PITFALL 3

Mapear el webhook al hilo correcto es tu trabajo

El webhook te informa que un pago se liquidó; no conoce tu thread_id de LangGraph. Mantén tu propio mapeo - cuando inicies un gráfico, almacena thread_id claveado por el agente, el destinatario o una clave de idempotencia que establezcas, luego búscala en el controlador. La llamada threadFor() anterior es esa búsqueda. Si te equivocas, graph.invoke reanuda el hilo incorrecto o ninguno en absoluto.

PITFALL 4

Maneja el camino sin liquidación, o suspende para siempre

El borde condicional de await_settlement se dirige a entregar solo cuando settled es verdadero. Si un pago nunca llega, el hilo permanece suspendido indefinidamente. Agrega un tiempo de espera: una barrida programada que reanuda hilos obsoletos con settled=false para que el borde se dirija a END, o una verificación de payment.sent-versus-deadline. Un hilo suspendido no cuesta nada, pero tampoco termina por sí mismo.

PITFALL 5

Las cantidades son unidades base de USDC, como cadenas

payments.create takes amountWei: a string of USDC base units (6 decimals), so 0.01 USDC is "10000" and 5 USDC is "5000000". It also does not retry by default and can answer 503 until the chain adapter is wired for your network. Handle that in the pay node - route to END or a retry node on error rather than letting the graph wedge.

PREGUNTAS FRECUENTES

Tres preguntas específicas de LangGraph.

¿Hay un paquete LangGraph, en npm o pip?

No. LangGraph ya te da todo: un nodo es solo una función, interrupt() suspende, un checkpointer persiste, y graph.updateState + graph.invoke reanuda. Así que el camino honesto es un nodo simple que llama al cliente real @blockchain0x/node (o al cliente Python de blockchain0x), como se muestra arriba. Los únicos paquetes de framework enviados son blockchain0x-langchain y blockchain0x-crewai (ambos Python) más el servidor @blockchain0x/mcp.

¿Puedo hacer esto en Python LangGraph también?

Sí, la misma receta. Python LangGraph tiene las mismas primitivas - un nodo de función, interrupt(), un verificador de puntos de control, y Command(resume=...) o update_state + invoke para continuar. Tu nodo llama al cliente de Python blockchain0x (blockchain0x.payments.create(...)), y tu controlador de webhook verifica la firma y reanuda el hilo. No hay ningún paquete pip que instalar más allá de langgraph y blockchain0x; la definición del gráfico es casi idéntica a la de TypeScript.

¿Funciona esto con LangGraph Platform y nodos de humano en el circuito?

Sí. La receta es LangGraph simple, por lo que se ejecuta igual en la Plataforma LangGraph - apunta tu webhook de Blockchain0x a la implementación y reanuda el hilo allí. interrupt() también admite varios puntos de interrupción en un gráfico: una interrupción de pago reanudada por el webhook y una interrupción de revisión humana reanudada por una acción de UI pueden vivir lado a lado, siempre que cada reanudación actualice su propio campo en el estado. El gráfico los enruta en orden.

Agrega pagos duraderos a tu gráfico.

Pausa en el pago, reanuda en el webhook, todo con las propias APIs de LangGraph. Gratis para comenzar.