LangGraph भुगतान एकीकरण।
कोई LangGraph पैकेज की आवश्यकता नहीं है। एक साधारण नोड वास्तविक blockchain0x क्लाइंट को कॉल करता है, interrupt() भुगतान वेबहुक के लैंड होने तक निलंबित रहता है, और ग्राफ फिर से शुरू होता है - रन के बीच टिकाऊ।
कोई LangGraph package नहीं है, और आपको इसकी आवश्यकता नहीं है। आपके में एक plain node वास्तविक client को call करता है, एक payment webhook आने तक graph को suspend करता है, और handler उसे LangGraph के अपने + के साथ resume करता है। Payments Base पर settle होते हैं।
स्थायी निष्पादन भुगतान के बाद फिर से शुरू करने के पैटर्न को स्वाभाविक बनाता है।
एजेंट-चालित भुगतानों का कठिन हिस्सा असिंक्रोनस गैप है: आप भुगतान का अनुरोध करते हैं, खरीदार कुछ मिनट बाद (या कभी नहीं) भुगतान करता है, और आपको उस स्थिति को खोए बिना काम फिर से शुरू करना होता है जहाँ आप थे। अधिकांश एजेंट ढांचे इस गैप को भरने के लिए एक कार्य कतार + मैनुअल स्थिति-स्टोर पर निर्भर करते हैं। LangGraph में पहले से ही अंतर्निहित प्राइमिटिव है: interrupt() एक नोड पर ग्राफ को निलंबित करता है और एक चेकपॉइंटर स्थिति को डिस्क पर बनाए रखता है। फिर से शुरू करना एक कॉल है।
इस recipe में किसी विशेष machinery की जरूरत नहीं है। एक साधारण pay node blockchain0x.payments.create को call करता है। एक await_settlement node suspend करने के लिए interrupt() call करता है, और checkpointer state को persist करता है। webhook handler signature verify करता है, graph.updateState के साथ matching thread पर settled set करता है, और interrupt से आगे जारी रखने के लिए graph.invoke call करता है। graph वहीं से resume करता है जहां वह रुका था, earlier nodes के किसी भी LLM context सहित - और यह सब LangGraph के अपने APIs का उपयोग करके होता है।
LangGraph और कोर SDK इंस्टॉल करें। कोई अतिरिक्त पैकेज नहीं।
Node 18+ और @langchain/langgraph 0.2+ और वास्तविक @blockchain0x/node क्लाइंट। किसी भी भाषा में जोड़ने के लिए कोई LangGraph एडाप्टर नहीं है - Python LangGraph उपयोगकर्ता langgraph और blockchain0x Python क्लाइंट स्थापित करते हैं और उसी नुस्खे को लिखते हैं, Python पक्ष पर interrupt() और Command(resume=...) के साथ।
npm install @langchain/langgraph @blockchain0x/node
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 आपके dashboard से एक sk_test_ testnet या sk_live_ mainnet key है; client इसे environment से पढ़ता है. BLOCKCHAIN0X_WEBHOOK_SECRET (जो webhook create या rotate करने पर एक बार मिलता है) webhooks को handle करने वाली process में जरूरी है. अगर आपका graph एक process में चलता है और handler दूसरी में, तो दोनों के लिए same checkpointer (जैसे shared Postgres) चाहिए ताकि handler suspended thread ढूंढ सके.
एक तीन-नोड ग्राफ: भुगतान करें, निलंबित करें, वितरित करें।
नीचे एक complete LangGraph workflow है, जिसमें typed State, एक pay node है जो real blockchain0x.payments.create को call करता है, एक interrupt-based await_settlement node है, और एक deliver node है जो chain द्वारा payment के move होने की पुष्टि के बाद dependent work चलाता है.
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".
वेबहुक को सत्यापित करें, फिर थ्रेड को फिर से शुरू करें।
हैंडलर Node SDK से webhooks.verify के साथ सिग्नेचर की पुष्टि करता है, आपके अपने मैपिंग से निलंबित LangGraph थ्रेड को देखता है, graph.updateState के साथ निपटारा सेट करता है, और interrupt से जारी रखने के लिए graph.invoke(null, config) को कॉल करता है। कोई विशेष सहायक नहीं - ये LangGraph के अपने APIs हैं।
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 कच्चे शरीर पर स्थायी समय में HMAC-SHA256 करता है और एक विभेदित संघ लौटाता है - result.ok पर शाखा करें, कोई प्रयास/पकड़ नहीं। result.eventId को उस धागे पर मैप करें जिसे आपने निलंबित किया था, फिर graph.updateState + graph.invoke(null, config) संग्रहीत चेकपॉइंट से फिर से शुरू होता है और ग्राफ़ चलाता है। भेजे गए घटनाक्रम हैं payment.received, payment.sent, wallet.deployed, और webhook.test।
आप जिस क्लाइंट को लपेट रहे हैं वह खुला है। इसे पढ़ें।
clone करने के लिए कोई LangGraph starter package नहीं है - ऊपर दिया गया recipe ही integration है। blockchain0x SDKs GitHub पर open source हैं; यह recipe Python SDK (blockchain0x-python) को wrap करता है, और पूरा method surface docs में है। node bodies और webhook verify के reference के लिए इसे पढ़ें।
github.com/tosh-labs/blockchain0x-pythonपूरी SDK method surface और webhook signature scheme the docs पर documented हैं. Base Sepolia के against एक sk_test_ key से शुरुआत करें, फिर जब graph अपेक्षा के अनुसार resume करे तो sk_live_ पर switch करें.
पांच LangGraph-विशिष्ट जाल से बचें।
LangGraph का स्थायी-निष्पादन मॉडल शक्तिशाली है लेकिन इसके पास चेकपॉइंट, इंटरप्ट, और स्थिति अपडेट के चारों ओर अपने खुद के खतरे हैं।
कोई LangGraph पैकेज नहीं है - एक साधारण नोड SDK को कॉल करता है
Blockchain0x LangChain और CrewAI के लिए एडाप्टर और MCP सर्वर भेजता है; npm या pip में कोई समर्पित LangGraph पैकेज नहीं है। ऊपर दिया गया नुस्खा यह है: एक सामान्य ग्राफ नोड असली @blockchain0x/node क्लाइंट को कॉल करता है, और आप LangGraph के अपने graph.updateState + graph.invoke के साथ आगे बढ़ते हैं। कोई विशेष भुगतान-नोड वर्ग नहीं है और न ही आयात करने के लिए कोई फिर से शुरू करने वाला सहायक है - वे कभी नहीं थे।
चेकपॉइंटर गायब है
LangGraph का interrupt() केवल तभी काम करता है जब ग्राफ में एक चेकपॉइंटर हो। बिना एक के, राज्य आपके प्रोसेस के बाहर निकलने पर वाष्पित हो जाता है और वेबहुक हैंडलर के पास फिर से शुरू करने के लिए कोई थ्रेड नहीं होता है। विकास के लिए MemorySaver का उपयोग करें और उत्पादन में SqliteSaver या PostgresSaver का उपयोग करें। यदि आपका ग्राफ और वेबहुक हैंडलर विभिन्न प्रक्रियाओं में चलते हैं, तो उन्हें समान चेकपॉइंटर (जैसे एक Postgres) साझा करना चाहिए ताकि हैंडलर निलंबित थ्रेड को ढूंढ सके।
वेबहुक को सही थ्रेड से मैप करना आपका काम है
वेबहुक आपको बताता है कि एक भुगतान निपटारा हुआ; यह आपके LangGraph thread_id को नहीं जानता। अपना खुद का मैपिंग रखें - जब आप एक ग्राफ शुरू करते हैं, तो एजेंट, प्राप्तकर्ता, या एक idempotency कुंजी द्वारा कुंजीबद्ध thread_id को स्टोर करें, फिर इसे हैंडलर में देखें। ऊपर दिया गया threadFor() कॉल वही लुकअप है। इसे गलत प्राप्त करें और graph.invoke गलत थ्रेड को फिर से शुरू करता है या बिल्कुल भी नहीं।
कोई निपटान पथ संभालें, या हमेशा के लिए निलंबित करें
await_settlement से शर्तीय किनारा केवल तभी वितरित करने के लिए रूट करता है जब निपटारा सत्य हो। यदि कोई भुगतान कभी नहीं पहुंचता है, तो थ्रेड अनिश्चितकाल के लिए निलंबित रहता है। एक टाइमआउट जोड़ें: एक अनुसूचित स्वीप जो निपटारा=false के साथ पुराने थ्रेड को फिर से शुरू करता है ताकि किनारा END पर रूट हो, या एक payment.sent-विरुद्ध-डेडलाइन जांच। एक निलंबित थ्रेड का कोई खर्च नहीं है, लेकिन यह अपने आप कभी समाप्त नहीं होता।
राशियाँ USDC आधार इकाइयाँ हैं, स्ट्रिंग के रूप में
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.