Ок, делаем clawdini как “Houdini/Nuke для агентов” — вертикальные ноды, коннекты сверху-вниз, и простейший пайплайн:
Input → Agent A → (в параллель Agent B) → Merge → Output
Хорошая новость: на базе OpenClaw это реально сделать довольно прямолинейно, потому что у Gateway уже есть:
- WS-протокол с request/response + events (frames) (GitHub)
- методы agents.list / models.list / sessions.list (GitHub)
- чат-методы chat.send (стримит delta/final) и chat.abort (GitHub)
И важный референс: Crabwalk уже показывает, что ReactFlow + realtime WebSocket к Gateway работает и даже умеет автодоставать токен из ~/.openclaw/openclaw.json. Но Crabwalk — это monitoring, не “оркестратор” (не запускает граф вычислений). (GitHub)
-
Нарисовать граф в ReactFlow (вертикально, в стиле Houdini).
-
Добавить 4 типа нод:
- InputNode (текст промпта)
- AgentNode (выбор agentId из OpenClaw + запуск)
- MergeNode (тестовый merge: склейка/простая “композиция”)
- OutputNode (итог)
-
По кнопке Run:
- дергает OpenClaw Gateway два раза (Agent A и Agent B),
- ловит streaming события (delta/final),
- кладёт output в ноды,
- Merge объединяет и отдаёт в Output.
- сложные типы merge (consensus, voting, RAG, tool-routing)
- полноценный scheduler / retries / очереди / distributed runs
- marketplace навыков/нод
Gateway даёт мощные методы, и у тебя будет токен/скоупы. С точки зрения безопасности лучше:
- токен не светить в браузер
- соединяться с Gateway с сервера (локальный/на VPS), а UI общается с твоим сервером
Плюс в последних версиях часто всплывают нюансы со scope; chat.send требует operator.write, и если подключиться “не теми scopes”, словишь missing scope. (GitHub)
-
React + ReactFlow
-
Zustand/Redux (легко) для состояния графа
-
Панель:
- слева “палитра нод” (Input / Agent / Merge / Output)
- центр канвас
- справа “Node Inspector” (параметры выделенной ноды)
- снизу “Run log / streaming output”
Визуальный стиль Houdini:
-
вертикальный layout (один “стек”)
-
у нод:
- вход сверху (target handle)
- выход снизу (source handle)
-
edge — прямой/ступенькой вниз
-
перемещение по X ограничить (или автоснап к колонкам)
Два слоя:
-
GatewayClient (низкоуровневый WS клиент к OpenClaw)
- реализует протокол
req/res/event - handshake
connectсminProtocol/maxProtocol, client info, scopes, auth token (GitHub)
- реализует протокол
-
GraphRunner (выполнение графа)
- топологическая сортировка
- параллельный запуск веток (Agent A и B одновременно)
- сбор результатов
- пуш стрима в UI
UI ↔ Server:
- либо WebSocket (второй)
ui-events - либо SSE для стриминга + REST для команд
Я бы для MVP сделал:
POST /api/run→ старт ранa, возвращаетrunIdGET /api/runs/:runId/events→ SSE стрим событий (nodeStarted/nodeDelta/nodeFinal/nodeError)
По схеме frames у connect есть поля role, scopes, auth.token, client.*. (GitHub)
Тебе нужно просить хотя бы:
operator.readoperator.write
Иначе chat.send может падать по скоупам. (GitHub)
Дёргаем agents.list → получаем defaultId, mainKey, список агентов. (GitHub)
UI показывает dropdown “Agent” внутри AgentNode.
Есть понятие agent-scoped session keys вида agent:<id>:<name> (в docs по ACP это прям зафиксировано как рекомендуемый паттерн). (GitHub)
Для MVP можно делать так:
sessionKey = "agent:" + agentId + ":clawdini-" + graphId + "-" + nodeId
(И опционально: перед запуском дернуть sessions.reset чтобы каждый run был “чистым”, если ты хочешь строго повторяемый output.) (GitHub)
Используем chat.send:
Поля: sessionKey, message, thinking?, timeoutMs?, idempotencyKey (GitHub)
Gateway шлёт event фреймы, а payload для чата — это ChatEventSchema со state: delta|final|error|aborted, runId, seq, etc. (GitHub)
GraphRunner:
- копит
deltaв буфер - на
finalфиксирует output ноды и помечает done
chat.abort принимает sessionKey и опционально runId. (GitHub)
Детерминированная склейка:
=== Agent A ===
{a}
=== Agent B ===
{b}
=== Combined ===
- Key points A: …
- Key points B: …
То есть merge просто объединяет строки и чуть форматирует.
Merge нода сама делает ещё один chat.send в отдельную merge-session (например agent:<defaultId>:merge) и просит:
- “сделай consensus / summary / reconcile contradictions” Это уже “похоже на Houdini merge, но умный”.
Для MVP я бы делал Режим 0, а Режим 1 — флажком “LLM merge”.
pnpm monorepo
clawdini/
apps/
ui/
src/
nodes/ (InputNode, AgentNode, MergeNode, OutputNode)
panels/ (Inspector, RunLog)
graph/ (serializer, layout)
server/
src/
gateway/ (GatewayClient, frame types, reconnect)
runner/ (GraphRunner, topo sort, parallel exec)
api/ (run routes + SSE)
packages/
types/
src/ (Graph JSON schema, NodeData typings)
Цель дня: UI рисует ноды, сервер коннектится к Gateway, UI видит список агентов.
-
[server] GatewayClient:
-
[ui] ReactFlow:
- вертикальные ноды (минимальный стиль Houdini)
- add/remove nodes
- Node Inspector: у AgentNode выпадашка agentId
-
[ui↔server] REST:
/api/agents
Definition of done:
- открываю UI → добавляю AgentNode → выбираю agent из списка.
Цель дня: Run запускает два chat.send и стримит текст в ноды.
-
[server] реализовать
POST /api/run:- принять graph JSON
- вычислить порядок
- запустить Agent A и B параллельно
- слушать
chatevents и пушить в SSE
-
[ui] сделать:
- кнопка Run
- RunLog (видно delta текст)
- output внутри AgentNode
Definition of done:
- Input текст → Run → в обоих AgentNode появляется результат.
Цель дня: появился MergeNode, OutputNode, cancel, persist.
-
[server] MergeNode computation (Mode 0: concat)
-
[ui] OutputNode показывает итог
-
[server+ui] Stop:
- дергать
chat.abortпо sessionKey/runId (GitHub)
- дергать
-
[ui] сохранение графа:
- localStorage + export/import JSON
Definition of done:
- Input → A/B → Merge → Output полностью работает.
- Можно остановить run.
Если цель — максимально быстро поднять работающий WebSocket-клиент и визуализацию: да, Crabwalk — супер референс: там уже ReactFlow, realtime стриминг и подход к токену/URL. (GitHub)
Но Crabwalk архитектурно заточен под “мониторинг цепочек”, а тебе нужен “graph authoring + execution engine”. Поэтому мой практичный совет для MVP:
- не форкать целиком,
- а взять оттуда только идеи (как они подключаются к Gateway, как рисуют activity graph),
- и сделать чистый
clawdiniс нуля, чтобы не тащить лишний стек (tRPC/TanStack DB и т.п.) (GitHub)
Если хочешь — следующим шагом я могу:
- накидать Graph JSON schema (как именно хранить ноды/рёбра/параметры)
- расписать контракты API (
/run, SSE events payloads) - и дать “чеклист реализации GatewayClient” (корреляция req/res, подписка на chat events, idempotencyKey генерация).