Passer au contenu principal
INTÉGRATION LANGGRAPH

Intégration de paiement LangGraph.

Aucun package LangGraph nécessaire. Un nœud simple appelle le véritable client blockchain0x, interrupt() suspend jusqu'à ce que le webhook de paiement arrive, et le graphe reprend - durable à travers les exécutions.

RÉPONSE COURTE

Il n'existe pas de package LangGraph, et vous n'en avez pas besoin. Un simple nœud dans votre appelle le vrai client , un suspend le graphe jusqu'à l'arrivée du webhook de paiement, et le handler le reprend avec les propres + de LangGraph. Les paiements sont réglés sur Base.

POURQUOI LANGGRAPH S'INSCRIT DANS CE MODÈLE

L'exécution durable rend le modèle de reprise après paiement naturel.

La partie difficile des paiements pilotés par des agents est le décalage asynchrone : vous demandez un paiement, l'acheteur paie quelques minutes plus tard (ou jamais), et vous devez reprendre le travail sans perdre l'état de là où vous en étiez. La plupart des frameworks d'agents s'appuient sur une file d'attente de tâches + un magasin d'état manuel pour combler ce fossé. LangGraph a déjà la primitive intégrée : interrupt() suspend un graphique à un nœud et un point de contrôle persiste l'état sur le disque. Reprendre est un appel.

La recette s'appuie sur cela sans machinerie spéciale. Un nœud de paiement simple appelle blockchain0x.payments.create. Un nœud await_settlement appelle interrupt() pour suspendre, et le vérificateur persiste l'état. Le gestionnaire de webhook vérifie la signature, définit le statut sur 'settled' dans le fil correspondant avec graph.updateState, et appelle graph.invoke pour continuer à partir de l'interruption. Le graphique reprend exactement là où il s'était arrêté, y compris tout contexte LLM des nœuds précédents - le tout en utilisant les propres API de LangGraph.

INSTALLATION

Installez LangGraph et le SDK de base. Aucun package supplémentaire.

Node 18+ et @langchain/langgraph 0.2+ plus le véritable client @blockchain0x/node. Il n'y a pas d'adaptateur LangGraph à ajouter dans l'un ou l'autre langage - les utilisateurs de LangGraph Python installent langgraph et le client Python blockchain0x et écrivent la même recette, avec interrupt() et Command(resume=...) du côté Python.

INSTALLER
npm install @langchain/langgraph @blockchain0x/node
VARIABLES D'ENVIRONNEMENT
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 est une clé sk_test_ testnet ou sk_live_ mainnet de votre tableau de bord ; le client la lit depuis l'environnement. BLOCKCHAIN0X_WEBHOOK_SECRET (renvoyé une fois lorsque vous créez ou faites tourner un webhook) est nécessaire dans le processus qui gère les webhooks. Si votre graphe s'exécute dans un processus et le gestionnaire dans un autre, les deux ont besoin du même point de contrôle (par exemple, Postgres partagé) afin que le gestionnaire puisse trouver le fil suspendu.

EXEMPLE DE GRAPHE COMPLET

Un graphique à trois nœuds : payer, suspendre, livrer.

Ci-dessous se trouve un flux de travail LangGraph complet avec un état typé, un nœud de paiement qui appelle le véritable blockchain0x.payments.create, un nœud await_settlement basé sur des interruptions, et un nœud de livraison qui exécute le travail dépendant une fois que la chaîne confirme que le paiement a été effectué.

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

GESTION DES WEBHOOKS

Vérifiez le webhook, puis reprenez le fil.

Le gestionnaire vérifie la signature avec webhooks.verify du SDK Node, recherche le fil LangGraph suspendu dans votre propre mappage, définit settled avec graph.updateState, et appelle graph.invoke(null, config) pour continuer à partir de l'interruption. Pas d'aide spéciale - ce sont les propres API 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 effectue HMAC-SHA256 en temps constant sur le corps brut et renvoie une union discriminée - branchez sur result.ok, pas de try/catch. Mappez result.eventId au thread que vous avez suspendu, puis graph.updateState + graph.invoke(null, config) reprend à partir du point de contrôle persistant et le graphique exécute les livraisons. Les événements expédiés sont payment.received, payment.sent, wallet.deployed et webhook.test.

SOURCE ET DOCUMENTS

Le client que vous enveloppez est ouvert. Lisez-le.

Il n'y a pas de package de démarrage LangGraph à cloner - la recette ci-dessus est l'intégration. Les SDK blockchain0x sont open source sur GitHub ; cette recette encapsule le SDK Python (blockchain0x-python), avec la surface complète des méthodes dans la documentation. Lisez-le pour une référence sur les corps de nœuds et la vérification du webhook.

github.com/tosh-labs/blockchain0x-python

La surface complète des méthodes SDK et le schéma de signature du webhook sont documentés dans la documentation. Commencez avec une clé sk_test_ sur Base Sepolia, puis passez à sk_live_ une fois que le graphique reprend comme vous l'attendez.

PIÈGES COURANTS

Cinq pièges spécifiques à LangGraph à éviter.

Le modèle d'exécution durable de LangGraph est puissant mais a ses propres pièges autour des points de contrôle, des interruptions et des mises à jour d'état.

PITFALL 1

Il n'y a pas de package LangGraph - un nœud simple appelle le SDK

Blockchain0x expédie des adaptateurs pour LangChain et CrewAI ainsi que le serveur MCP ; il n'y a pas de package LangGraph dédié, dans npm ou pip. La recette ci-dessus est le chemin : un nœud de graphe ordinaire appelle le véritable client @blockchain0x/node, et vous reprenez avec graph.updateState + graph.invoke de LangGraph. Il n'y a pas de classe de nœud de paiement spéciale et pas d'assistant de reprise à importer - ceux-ci n'ont jamais existé.

PITFALL 2

Checkpointer manquant

L'interrupt() de LangGraph ne fonctionne que si le graphique a un point de contrôle. Sans lui, l'état s'évapore lorsque votre processus se termine et le gestionnaire de webhook n'a pas de fil à reprendre. Utilisez MemorySaver pour le développement et SqliteSaver ou PostgresSaver en production. Si votre graphique et votre gestionnaire de webhook s'exécutent dans des processus différents, ils doivent partager le même point de contrôle (par exemple, un Postgres) afin que le gestionnaire puisse trouver le fil suspendu.

PITFALL 3

Mapper le webhook au bon fil est votre travail

Le webhook vous informe qu'un paiement a été réglé ; il ne connaît pas votre LangGraph thread_id. Gardez votre propre mappage - lorsque vous démarrez un graphique, stockez thread_id indexé par l'agent, le destinataire, ou une clé d'idempotence que vous définissez, puis recherchez-le dans le gestionnaire. L'appel threadFor() ci-dessus est cette recherche. Si vous vous trompez, graph.invoke reprend le mauvais fil ou aucun.

PITFALL 4

Gérez le chemin sans règlement, ou suspendez pour toujours

Le bord conditionnel de await_settlement achemine la livraison uniquement lorsque settled est vrai. Si un paiement n'atterrit jamais, le fil reste suspendu indéfiniment. Ajoutez un délai d'attente : un balayage programmé qui reprend les fils périmés avec settled=false afin que le bord achemine vers END, ou un contrôle payment.sent-versus-deadline. Un fil suspendu ne coûte rien, mais il ne se termine jamais par lui-même.

PITFALL 5

Les montants sont des unités de base USDC, sous forme de chaînes

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.

QUESTIONS FRÉQUEMMENT POSÉES

Trois questions spécifiques à LangGraph.

Y a-t-il un package LangGraph, dans npm ou pip ?

Non. LangGraph vous donne déjà tout : un nœud est juste une fonction, interrupt() suspend, un point de contrôle persiste, et graph.updateState + graph.invoke reprennent. Donc le chemin honnête est un nœud simple qui appelle le véritable client @blockchain0x/node (ou le client Python blockchain0x), comme montré ci-dessus. Les seuls packages de framework expédiés sont blockchain0x-langchain et blockchain0x-crewai (tous deux en Python) plus le serveur @blockchain0x/mcp.

Puis-je faire cela dans Python LangGraph aussi ?

Oui, la même recette. Python LangGraph a les mêmes primitives - un nœud de fonction, interrupt(), un vérificateur, et Command(resume=...) ou update_state + invoke pour continuer. Votre nœud appelle le client Python blockchain0x (blockchain0x.payments.create(...)), et votre gestionnaire de webhook vérifie la signature et reprend le fil. Il n'y a pas de package pip à installer au-delà de langgraph et blockchain0x ; la définition du graphique est presque identique à celle de TypeScript.

Cela fonctionne-t-il avec LangGraph Platform et les nœuds humains dans la boucle ?

Oui. La recette est un LangGraph classique, donc elle fonctionne de la même manière sur la plateforme LangGraph - pointez votre webhook Blockchain0x vers le déploiement et reprenez le fil là-bas. interrupt() prend également en charge plusieurs points d'interruption dans un seul graphe : une interruption de paiement reprise par le webhook et une interruption de révision humaine reprise par une action UI peuvent coexister, tant que chaque reprise met à jour son propre champ dans l'état. Le graphe les route dans l'ordre.

Ajoutez des paiements durables à votre graphique.

Mettez en pause sur le paiement, reprenez sur le webhook, le tout avec les propres API de LangGraph. Gratuit pour commencer.