Перейти к основному содержимому
ИНТЕГРАЦИЯ LANGGRAPH

Интеграция платежей LangGraph.

Пакет LangGraph не нужен. Обычный узел вызывает реальный клиент blockchain0x, interrupt() приостанавливается до тех пор, пока вебхук платежа не поступит, и граф возобновляется - устойчивый между запусками.

КРАТКИЙ ОТВЕТ

Специального пакета для LangGraph нет, и он вам не нужен. Обычный node в вашем вызывает реальный client , приостанавливает graph, пока не придет payment webhook, а обработчик возобновляет его с помощью собственных + LangGraph. Платежи завершаются в Base.

ПОЧЕМУ LANGGRAPH ПОДХОДИТ ПОД ЭТУ СХЕМУ

Надежное выполнение делает паттерн возобновления после платежа естественным.

Сложная часть платежей, управляемых агентами, - это асинхронный разрыв: вы запрашиваете платеж, покупатель платит через несколько минут (или никогда), и вам нужно продолжить работу, не теряя состояние того, где вы были. Большинство фреймов агентов полагаются на очередь задач + ручное хранилище состояния, чтобы преодолеть этот разрыв. LangGraph уже имеет встроенный примитив: interrupt() приостанавливает граф на узле, а контрольная точка сохраняет состояние на диск. Возобновление - это один вызов.

Рецепт использует это без какой-либо специальной механики. Обычный pay node вызывает blockchain0x.payments.create. Узел await_settlement вызывает interrupt(), чтобы приостановиться, а checkpointer сохраняет состояние. Обработчик webhook проверяет подпись, устанавливает settled в соответствующем thread через graph.updateState и вызывает graph.invoke, чтобы продолжить с места прерывания. Graph продолжает ровно с того места, где остановился, включая любой LLM context из предыдущих узлов - все через собственные APIs LangGraph.

УСТАНОВКА

Установите LangGraph и основной SDK. Без дополнительных пакетов.

Node 18+ и @langchain/langgraph 0.2+ плюс реальный клиент @blockchain0x/node. Нет адаптера LangGraph для добавления в любом из языков - пользователи LangGraph на Python устанавливают langgraph и клиент blockchain0x на Python и пишут тот же рецепт, с interrupt() и Command(resume=...) на стороне Python.

УСТАНОВИТЬ
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 - это ключ sk_test_ для testnet или sk_live_ для mainnet из вашего dashboard; client читает его из environment. BLOCKCHAIN0X_WEBHOOK_SECRET (выдается один раз при создании или ротации webhook) нужен в процессе, который обрабатывает webhook. Если ваш graph работает в одном процессе, а handler - в другом, обоим нужен один и тот же checkpointer (например, общий Postgres), чтобы handler мог найти приостановленный thread.

ПОЛНЫЙ ПРИМЕР ГРАФА

Граф из трех узлов: оплатить, приостановить, доставить.

Ниже приведен полный LangGraph workflow с типизированным State, pay node, который вызывает реальный blockchain0x.payments.create, interrupt-based await_settlement node и deliver node, который запускает зависимую работу после того, как chain подтверждает перевод payment.

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

ОБРАБОТКА WEBHOOK

Проверьте вебхук, затем продолжите поток.

Обработчик проверяет подпись с помощью webhooks.verify из Node SDK, ищет приостановленный поток LangGraph в вашем собственном отображении, устанавливает settled с помощью graph.updateState и вызывает graph.invoke(null, config), чтобы продолжить с места прерывания. Никаких специальных помощников - это собственные API 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 выполняет HMAC-SHA256 за постоянное время над сырым телом и возвращает дискриминированный союз - ветвитесь по result.ok, без try/catch. Соответствуйте result.eventId потоку, который вы приостановили, затем graph.updateState + graph.invoke(null, config) возобновляет с сохраненной контрольной точки, и граф выполняет доставку. Отправленные события: payment.received, payment.sent, wallet.deployed и webhook.test.

ИСТОЧНИК И ДОКУМЕНТАЦИЯ

Клиент, который вы оборачиваете, открыт. Читайте его.

Нет starter package для LangGraph, который можно было бы клонировать - рецепт выше и есть интеграция. SDK Blockchain0x открыты в GitHub; этот рецепт оборачивает Python SDK (blockchain0x-python), а полный набор методов приведен в docs. Используйте его как reference для body nodes и проверки webhook.

github.com/tosh-labs/blockchain0x-python

Полный набор методов SDK и схема подписи webhook описаны в the docs. Начните с ключа sk_test_ в Base Sepolia, затем переключитесь на sk_live_, когда graph возобновит работу так, как вы ожидаете.

ОБЩИЕ ОШИБКИ

Пять ловушек, специфичных для LangGraph, которых следует избегать.

Модель долговременного выполнения LangGraph мощная, но имеет свои собственные подводные камни вокруг контрольных точек, прерываний и обновлений состояния.

PITFALL 1

Нет пакета LangGraph - простой узел вызывает SDK.

Blockchain0x поставляет адаптеры для LangChain и CrewAI, а также сервер MCP; нет отдельного пакета LangGraph в npm или pip. Рецепт выше - это путь: обычная графовая нода вызывает реальный клиент @blockchain0x/node, и вы продолжаете с помощью graph.updateState + graph.invoke от LangGraph. Нет специального класса payment-node и нет помощника для импорта - их никогда не существовало.

PITFALL 2

Отсутствует контрольный пункт

Функция interrupt() LangGraph работает только в том случае, если граф имеет контрольную точку. Без нее состояние исчезает, когда ваш процесс завершается, и обработчик вебхука не имеет потока для возобновления. Используйте MemorySaver для разработки и SqliteSaver или PostgresSaver в производстве. Если ваш граф и обработчик вебхука работают в разных процессах, они должны делить одну и ту же контрольную точку (например, один Postgres), чтобы обработчик мог найти приостановленный поток.

PITFALL 3

Сопоставление вебхука с правильным потоком - это ваша работа

Вебхук сообщает вам, что платеж был завершен; он не знает ваш LangGraph thread_id. Сохраняйте свое собственное отображение - когда вы начинаете граф, храните thread_id, ключом которого является агент, получатель или ключ идемпотентности, который вы установили, затем ищите его в обработчике. Вызов threadFor() выше - это тот самый поиск. Если вы ошибетесь, graph.invoke возобновит неправильный поток или вообще не возобновит.

PITFALL 4

Обработайте путь без расчетов или приостановите навсегда

Условный переход от await_settlement маршрутизирует доставку только когда settled истинно. Если платеж никогда не поступает, поток остается приостановленным на неопределенный срок. Добавьте тайм-аут: запланированную очистку, которая возобновляет устаревшие потоки с settled=false, чтобы переход маршрутизировался к END, или проверку payment.sent-versus-deadline. Приостановленный поток ничего не стоит, но он также никогда не завершится самостоятельно.

PITFALL 5

Суммы представлены в базовых единицах 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.

ЧАСТО ЗАДАВАЕМЫЕ

Три вопроса, специфичных для LangGraph.

Существует ли пакет LangGraph в npm или pip?

Нет. LangGraph уже дает вам все: узел - это просто функция, interrupt() приостанавливает, контрольный пункт сохраняется, а graph.updateState + graph.invoke возобновляются. Поэтому честный путь - это обычный узел, который вызывает реальный клиент @blockchain0x/node (или клиент blockchain0x на Python), как показано выше. Единственные поставляемые пакеты фреймворка - это blockchain0x-langchain и blockchain0x-crewai (оба Python) плюс сервер @blockchain0x/mcp.

Могу ли я сделать это в Python LangGraph тоже?

Да, тот же рецепт. Python LangGraph имеет те же primitives - function node, interrupt(), checkpointer и Command(resume=...) или update_state + invoke для продолжения. Ваш node вызывает Python client blockchain0x (blockchain0x.payments.create(...)), а ваш webhook handler проверяет подпись и возобновляет thread. Помимо langgraph и blockchain0x, ничего из pip устанавливать не нужно; определение graph почти идентично TypeScript-версии.

Работает ли это с платформой LangGraph и узлами с человеком в цикле?

Да. Рецепт - это простой LangGraph, поэтому он работает так же на платформе LangGraph - укажите ваш вебхук Blockchain0x на развертывание и возобновите поток там. interrupt() также поддерживает несколько точек прерывания в одном графе: прерывание платежа, возобновленное вебхуком, и прерывание human_review, возобновленное действием UI, могут существовать бок о бок, при условии, что каждое возобновление обновляет свое собственное поле в состоянии. Граф маршрутизирует их по порядку.

Добавьте надежные платежи в вашу граф.

Приостановите на оплате, возобновите на вебхуке, все с помощью собственных API LangGraph. Бесплатно для начала.