LangGraph ödeme entegrasyonu.
LangGraph paketi gerekmez. Düz bir düğüm gerçek blockchain0x istemcisini çağırır, interrupt() ödeme webhook'u gelene kadar askıya alır ve grafik devam eder - çalışmalarda dayanıklıdır.
LangGraph'e özel bir paket yok ve buna ihtiyacınız da yok. içindeki düz bir node gerçek istemcisini çağırır, bir ödeme webhook'u gelene kadar graph'ı askıya alır ve handler bunu LangGraph'in kendi + ile devam ettirir. Ödemeler Base üzerinde sonuçlanır.
Dayanıklı yürütme, ödeme sonrası devam etme modelini doğal hale getirir.
Ajan yönlendirmeli ödemelerin zor kısmı asenkron boşluktur: ödeme talep edersiniz, alıcı birkaç dakika sonra (veya asla) ödeme yapar ve nerede kaldığınızın durumunu kaybetmeden çalışmaya devam etmeniz gerekir. Çoğu ajan çerçevesi, bu boşluğu kapatmak için bir iş kuyruğu + manuel durum deposuna dayanır. LangGraph, zaten yerleşik bir ilkeye sahiptir: interrupt() bir grafiği bir düğümde askıya alır ve bir kontrol noktası durumu diske kalıcı hale getirir. Devam etmek bir çağrıdır.
Bu yaklaşım hiçbir özel mekanizma olmadan bundan yararlanır. Basit bir pay node'u blockchain0x.payments.create çağırır. await_settlement node'u askıya almak için interrupt() çağırır ve checkpointer state'i kalıcı hale getirir. Webhook handler imzayı doğrular, eşleşen thread üzerinde graph.updateState ile settled değerini ayarlar ve interrupt'tan devam etmek için graph.invoke çağırır. Graph, önceki node'lardaki tüm LLM context dahil olmak üzere tam kaldığı yerden devam eder - hepsi LangGraph'in kendi API'leri kullanılarak.
LangGraph'ı ve çekirdek SDK'yı kurun. Ek bir paket yok.
Node 18+ ve @langchain/langgraph 0.2+ artı gerçek @blockchain0x/node istemcisi. Her iki dilde de eklemek için bir LangGraph adaptörü yoktur - Python LangGraph kullanıcıları langgraph ve blockchain0x Python istemcisini yükler ve aynı tarifi yazar, Python tarafında interrupt() ve Command(resume=...) ile.
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'unuzdan alınan bir sk_test_ testnet veya sk_live_ mainnet anahtarıdır; client bunu ortamdan okur. BLOCKCHAIN0X_WEBHOOK_SECRET (bir webhook oluşturduğunuzda veya rotate ettiğinizde bir kez döndürülür) webhook'ları işleyen süreçte gerekir. Graph'iniz bir süreçte, handler başka bir süreçte çalışıyorsa, handler'ın askıya alınmış thread'i bulabilmesi için ikisinin de aynı checkpointer'a (ör. paylaşılan Postgres) ihtiyacı vardır.
Üç düğümlü bir grafik: ödeme, askıya alma, teslim etme.
Aşağıda, typed State, gerçek blockchain0x.payments.create'i çağıran bir pay node, interrupt tabanlı bir await_settlement node ve zincir ödemenin hareket ettiğini doğruladığında bağımlı işi çalıştıran bir deliver node içeren eksiksiz bir LangGraph workflow'u yer alıyor.
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".
Webhook'u doğrulayın, ardından iptal edin.
İşleyici, Node SDK'den webhooks.verify ile imzayı doğrular, kendi haritalamanızdan askıya alınmış LangGraph ipliğini bulur, graph.updateState ile yerleştiği durumu ayarlar ve kesintiden devam etmek için graph.invoke(null, config) çağrısını yapar. Özel bir yardımcı yok - bunlar LangGraph'ın kendi API'leridir.
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 ham gövde üzerinde sabit zaman içinde HMAC-SHA256 yapar ve ayrıştırılmış bir birleşim döner - result.ok üzerinde dallanın, try/catch yok. result.eventId'yi askıya aldığınız iş parçacığına eşleyin, ardından graph.updateState + graph.invoke(null, config) kalıcı kontrol noktasından devam eder ve grafik çalıştırır. Gönderilen olaylar payment.received, payment.sent, wallet.deployed ve webhook.test'tir.
Sarmaladığınız istemci açıktır. Okuyun.
Klonlanacak bir LangGraph starter package yok - yukarıdaki recipe entegrasyonun kendisidir. blockchain0x SDK'leri GitHub'da open source'dur; bu recipe Python SDK'yı (blockchain0x-python) sarar ve tam method surface dokümanlarda yer alır. Node body'leri ve webhook verify için bir referans olarak okuyun.
github.com/tosh-labs/blockchain0x-pythonTam SDK method surface ve webhook signature scheme the docs içinde belgelenmiştir. Base Sepolia üzerinde bir sk_test_ anahtarıyla başlayın, ardından graph beklediğiniz şekilde devam ettiğinde sk_live_ anahtarına geçin.
Beş LangGraph'a özgü kaçınılması gereken tuzak.
LangGraph'ın dayanıklı yürütme modeli güçlüdür ancak kontrol noktaları, kesintiler ve durum güncellemeleri etrafında kendi tehlikeleri vardır.
LangGraph paketi yoktur - sıradan bir düğüm SDK'yı çağırır.
Blockchain0x, LangChain ve CrewAI için adaptörler ve MCP sunucusu gönderir; npm veya pip'te özel bir LangGraph paketi yoktur. Yukarıdaki tarif, sıradan bir grafik düğümünün gerçek @blockchain0x/node istemcisini çağırdığı yoldur ve LangGraph'ın kendi graph.updateState + graph.invoke ile devam edersiniz. Özel bir ödeme düğümü sınıfı yoktur ve içe aktarılacak bir devam yardımcısı yoktur - bunlar hiç var olmadı.
Kontrol noktası eksik
LangGraph'ın interrupt() işlevi yalnızca grafikte bir kontrol noktası varsa çalışır. Kontrol noktası olmadan, durum işleminiz çıktığında buharlaşır ve webhook işleyicisinin devam ettirecek bir ipliği yoktur. Geliştirme için MemorySaver kullanın ve üretimde SqliteSaver veya PostgresSaver kullanın. Eğer grafiğiniz ve webhook işleyiciniz farklı işlemlerde çalışıyorsa, aynı kontrol noktasını paylaşmaları gerekir (örneğin bir Postgres) böylece işleyici askıya alınmış ipliği bulabilir.
Webhook'u doğru ipliğe eşlemek sizin işiniz
Webhook, bir ödemenin yerleştiğini bildirir; LangGraph thread_id'nizi bilmez. Kendi haritalamanızı tutun - bir grafik başlattığınızda, ajans, alıcı veya ayarladığınız bir idempotency anahtarı ile anahtarlanan thread_id'yi saklayın, ardından işleyicide bunu arayın. Yukarıdaki threadFor() çağrısı o aramadır. Bunu yanlış yaparsanız, graph.invoke yanlış ipliği veya hiçbiriyle devam eder.
Ödeme yapılmayan yolu yönetin veya sonsuza kadar askıya alın
await_settlement'dan gelen koşullu kenar, yalnızca yerleştiğinde teslimat yapar. Eğer bir ödeme asla gerçekleşmezse, iplik sonsuza kadar askıya alınır. Bir zaman aşımı ekleyin: settled=false olan bayat iplikleri yeniden başlatan planlı bir tarama, böylece kenar END'e yönlendirilir veya bir payment.sent-versus-deadline kontrolü. Askıya alınmış bir iplik hiçbir maliyet oluşturmaz, ancak kendi başına da asla bitmez.
Tutarlar, dize olarak USDC temel birimleridir
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.