Перейти к основному контенту

Как построить визуальный no-code редактор воронок и AI пайплайнов на React поверх low-code ядра Metabot

Этот урок — про то, как поверх Metabot (который сам по себе полный low-code/full-code backend для чат-ботов и ассистентов) построить новый продукт: визуальный конструктор чат-ботов.

То есть вы создадите реальный продуктовый интерфейс — свой ManyChat / BotHelp, но умнее и современнее.

Главная идея:

Metabot — это low-code/full-code ядро.
Пройдя этот урок, вы научитесь строить целые продукты поверх ядра, создавая собственный фронт, визуальный редактор, AI-функции и конструкторы.

Часть 1. Что будет в этом уроке — и чего здесь не будет

Чтобы вы сразу понимали рамки: этот урок — это фундамент, первая версия конструктора, на котором вы сможете дальше строить полноценный продукт. Здесь мы создаём работающий скелет визуального редактора и настраиваем импорт в Metabot.

А теперь — по пунктам.


Что будет в уроке

1. Создадим собственный JSON-формат воронки

Вы:

  • придумаете свой формат,

  • определите структуру шагов воронки,

  • создадите свои типы команд,

  • добавите свои параметры и опции.

То есть вы спроектируете свой DSL (domain-specific language) — язык описания воронок вашего продукта.


2. Разберётесь, как работает Mapper

Мы подробно посмотрим, как:

  • входящий JSON обрабатывается,

  • шаги проверяются,

  • неподдерживаемые типы фильтруются,

  • нужные команды собираются,

  • создаются переходы, кнопки, логгирование, LLM-вызовы и так далее.

То есть вы поймёте логику трансформации вашего формата → формат Metabot.

Вы получите исходный код Mapper'а.


3. Разберётесь, как работает Builder

Мы детально пройдём по механике:

  • создания секции/папки скриптов в Metabot,

  • создания скриптов,

  • добавления low-code команд в скрипт,

  • создания переходов и menu-кнопок,

  • удаления старых версий воронки.

И главное — вы увидите, как Builder напрямую манипулирует базой данных Metabot (PostgreSQL) через PHP/V8.

Это даёт понимание того, как работает ядро платформы и как можно строить свои надстройки.

Вы получите исходный код Builder'а.


4. Научитесь подключать Metabot как backend

Вы увидите, как:

  • передавать JSON в Metabot через API,

  • запускать импорт,

  • пересобирать воронку целиком,

  • структурировать код для своего продукта.

То есть Metabot превращается для вас в backend-as-a-platform, который вы можете использовать под любые проекты.


5. Сделаем визуальный редактор на React (с помощью V0 + Cursor)

Мы:

  • создадим canvas и интерфейс узлов,

  • свяжем их с JSON,

  • добавим  импорт и экспорт в/из файла,

  • добавим базовые настройки шагов и валидации,

  • подготовим front-end архитектуру.

Вы получите:

  • исходный код редактора,

  • архитектуру компонентов,

  • промпты, с помощью которых редактор собирался (это важно — это обучает самостоятельному созданию продуктов).


6. Настроим рабочий цикл разработки

Первые итерации будут такие:

1) создаём JSON вручную → 
2) отправляем через Postman → 
3) смотрим, как Metabot создал воронку →
4) фиксируем ошибки →
5) делаем свои команды →
6) строим визуальный редактор, который уже генерит нужный JSON →
7) импортируем в Metabot одной кнопкой

Это честный, практичный, продуктовый процесс.


7. Вы получите всё, чтобы создать свой продукт

В итоге у вас будет:

  • работающий визуальный редактор,

  • свой JSON-формат,

  • свой набор команд,
  • сохранение в файл и загрузка из файла,
  • исходники маппера/билдера,

  • связка React → JSON → Metabot.

На этом можно строить:

  • no-code конструктор,

  • CJM-редактор,

  • AI-конструктор цепочек,

  • бизнесовый продукт поверх Metabot.


🚫 Чего в этом уроке НЕ будет

Чтобы не вводить в заблуждение — сразу фиксируем:

1. Не будет двусторонней синхронизации

Мы делаем только импорт из вашего конструктора → Metabot.

То есть:

  • если воронка существует — она удаляется и создаётся заново,

  • мы не читаем текущую структуру из Metabot,

  • мы не отображаем её обратно в редактор.

Это осознанное упрощение.

Вторую сторону можно сделать, но это отдельный блок задач:
читать данные Metabot → конвертировать → отображать → синхронизировать версии.

Мы это оставляем для следующего урока, если будет запрос.


2. Не будет полноценного менеджмента трафика

Это очень важный момент.

В реальной жизни по ранее импортированной воронке уже могут идти живые пользователи.
Если вы меняете воронку, возникают вопросы:

  • что делать с активными пользователями?

  • надо ли их перенаправлять в новую версию?

  • надо ли блокировать обновления?

  • нужно ли создавать копии воронок?

  • нужно ли делать миграции шагов?

  • как правильно писать стратегию версионирования?

Это целая философия, и у каждого продукта — свой подход.
Мы эту сложность сознательно не включаем в этот урок.

Но если понадобится понадобится помощь — дайте знать, попробуем помочь.


3. Не будет полноценной "платформенности"

В этом уроке:

  • нет авторизации и регистрации — импорт по API токену пользователя, привязанному к боту.
  • нет совместной работы.

Мы делаем первую версию конструктора, но она уже рабочая и расширяемая.


Принял. Делаю первую итерацию — без фанатизма, но уже структурно, лаконично, красиво, чтобы можно было вложить в документацию и развивать дальше.
Ты дал огромный объём информации, поэтому я сейчас фиксирую каркас главы 2, + делаю первый блок: спецификация команд Metabot + JSON-формат, + простую таблицу команд, красиво оформленную, + мини-описание модели данных (sentences, phrases, references).

В следующей итерации я смогу:

  • добить оставшиеся разделы,

  • оформить финальный CJM JSON на 20 шагов,

  • добавить продвинутую постановку задач.


Глава 2. JSON-формат и фундаментальная модель данных Metabot

Чтобы создать собственный визуальный конструктор поверх Metabot, нужно понимать две вещи:

  1. Какие команды реально существуют в ядре платформы

  2. Как Metabot хранит эти команды в базе данных

Эта глава даёт разработчику язык конструктора — JSON-формат шага, таблицу команд и модель хранения внутри Metabot.


2.1. Базовая модель данных Metabot

Метабот — low-code движок. Его диалоговая логика физически живёт в трёх таблицах:

sentences — это скрипты

Каждый шаг в нашем редакторе превратится в отдельный скрипт Metabot.

Поле Что значит
id ID скрипта
code Уникальный код (мы сами создаём)
name Читабельное имя
bot_id Бот, которому принадлежит скрипт
section_id Папка/категория (наша “воронка”)
... Остальные поля нам пока не нужны

Пример:

id: 85681
code: "test-script"
name: "TestScript"
bot_id: 2370

phrases — это команды внутри скрипта

Одна запись = одна команда.
Каждый шаг в нашем редакторе может порождать от 1 до 10 фраз.

Поле Описание
id ID команды
type Тип команды (send_text, run_javascript, …)
sentence_id Скрипт, которому команда принадлежит
content Текст или JSON-контент команды
sort_order Порядок выполнения
alias Уникальный ID команды

Пример вывода send_text:

type: "send_text"
sentence_id: 85681
content: "Hello, World!"
sort_order: 0

Пример ввода пользователя value_input:

id: 231462
type: value_input
sentence_id: 85681
content: {"attribute_key":"var","prompt":"Введите число",...}
sort_order: 1

references — это кнопки (меню)

Меню — это не фраза, а отдельная таблица (так исторически, да). Каждая запись — это кнопка.

Поле Значение
sentence_id Скрипт, которому меню принадлежит
caption Текст кнопки
code Код/значение кнопки
jump_sentence_id Куда переходить
sort_order Порядок кнопок
line_num Для многострочных клавиатур
condition_script_code Условие отображения

Пример:

sentence_id: 85681
caption: "Start Over"
code: "1"
jump_sentence_id: 85680

📌 Все 21 команды Метабота

На момент написания этого урока в Metabot есть 20 команд в скриптах + одна неявная команда (меню).

№ Команда Что делает Где хранится Пример content в БД
1 send_text отправляет текстовое сообщение phrases Hello, World!!!
2 value_input запрашивает ввод и валидирует phrases {"attribute_key":"abc","prompt":"Введите число", ...}
3 run_javascript выполняет JS на сервере phrases lead.setAttr('abc', 123);
4 send_image отправляет изображение phrases {"path":"bot/.../logo.png","name":"logo.png"}
5 send_file отправляет файл (любые документы) phrases {"path":"bot/...","name":"file.pdf"}
6 run_sentence выполняет другой скрипт, останавливает текущий phrases 85681
7 send_email отправляет email phrases {"recipient":"user@mail","subject":"...","body":"..."}
8 run_trigger запускает триггер phrases {"trigger_id":"7222","run_at":"2025-06-11","run_after_sec":300}
9 set_lead_status меняет статус лида phrases 7783
10 add_lead_tags добавляет теги phrases "tag"
11 remove_lead_tags удаляет теги phrases "tag"
12 nlp_detect_intent определяет интент phrases {"text_to_detect":"intent"}
13 run_js_callback делает JS-callback phrases {"prompt":"...","error_message":"...","js_code":"..."}
14 async_api_call async вызов API (например, обращение к LLM) phrases {"js_code":"...","is_immediate_call":1}
15 add_lead_contexts добавляет контекст phrases "context"
16 remove_lead_contexts удаляет контекст phrases "context"
17 forward_to_operator переводит на оператора phrases 7784
18 return_to_bot возвращает в бота phrases 7783
19 repeat_sentence повторяет текущий скрипт phrases {}
20 stop полностью останавливает выполнение phrases {}
21 menu (reference) кнопки меню, переходы, inline actions references caption="Start", jump_sentence_id=85680

Короткое объяснение логики исполнения команд

  • Команды внутри одного скрипта (sentence) выполняются сверху вниз по sort_order.

  • Любая команда типа run_sentence или run_javascript может мгновенно передать управление в другой скрипт.

  • Кнопки (references) — это отдельная сущность: они не лежат в phrases, но участвуют в сценарии. В интерфейсе меню расположено внизу скрипта, после списка команд.

Вот тебе ровно тот кусок текста, который сейчас нужен: ясный, убедительный, «ведущий читателя» — и одновременно полностью отражающий твою идею создать собственный визуальный конструктор, где одна «наша» команда заменяет пачку метаботовских низкоуровневых команд.

Это идеально идёт сразу после секции со списком 21 команды Metabot.


🔶

Раздел: «Зачем нам свой конструктор и свои команды»

(вставь в статью как есть — он написан в том же тоне, что и предыдущие части и красиво связывает контекст)

После того как мы разобрались, какие команды реально существуют внутри Metabot и посмотрели, как они физически хранятся в базе (sentences, phrases, references), мы можем перейти к ключевой идее нашего урока:

Мы не будем создавать интерфейс, который один-в-один повторяет Metabot.
Мы создадим свой собственный визуальный конструктор, и в нём у нас будут свои команды — более удобные, более компактные и намного более выразительные.

Почему так?


## 🧠

Почему в Metabot всё разбито на 21 команду

(и почему это отлично для движка, но неудобно для дизайнера чат-ботов)

Metabot — это low-code ядро. Каждая команда — это минимальная атомарная операция:

  • отправить текст,

  • отправить картинку,

  • записать тег,

  • выполнить JS,

  • перейти в скрипт,

  • вызвать LLM,

  • записать аналитику,

  • дождаться ввода
    и так далее.

Это правильно для движка:
движок должен быть предсказуемым и детерминированным.

Но для человека, который рисует сценарий, это слишком низкий уровень.
Чтобы собрать один «узел» диалога, дизайнеру нужно вручную собрать:

  • 1–3 send_text

  • условия и JS

  • настройки под разные каналы

  • кнопки меню (в references)

  • обработчики кликов (ещё несколько run_sentence + JS)

  • автологированиеJS для логирования для аналитики

  • триггеры для отслеживания ссылок

  • переходы к следующему шагу

В итоге один визуальный узел превращается в:

→ 6–12 низкоуровневых фраз в базе

→ 2–4 скрипта (sentences)

→ и пачку записей в references

Именно поэтому мы не хотим заставлять пользователя руками разбираться в 21 команде ядра. Мы хотим сократить этот слой.


🔶

Теперь проектируем наш собственный редактор

Мы создаём свою систему узлов — такую, в которой:

  • один узел = одна логическая операция сценария,

  • пользователь видит высокоуровневую настройку,

  • а всё сложное — «распаковывается» автоматически внутрь Metabot при импорте.

Это и есть смысл маппера и билдера.


##

Какие наши команды мы сделаем первыми

Мы начинаем не с копирования полного набора команд Metabot.
Мы делаем те команды, которые дают 80% функциональности и 20% сложности.


1. Start / Entry Node

Стартовый узел воронки.
Даёт визуальную точку входа + будущую связь с диплинками.

Вход в воронку возможен как из других воронок и сценариев, так и снаружи при переходе в мессенджер из приложений и Интернет.


2. Send Text (расширенная)

Это не просто send_text из Metabot.
Наша версия включает:

  • 💬 универсальное сообщение

  • 💬 кастомизация сообщения под каналы (Telegram, WhatsApp, VK, WebChat)WebChat и так далее)

  • ⚙️ обработку макросов

  • 🤖 возможность вставить LLM-подсказки

  • 🔘 кнопки со встроенными обработчиками

  • 📌 запись в аналитику прямо внутри узла

  • ↪️ переход к следующему шагу

  • 🔗 поддержка ссылок (с автогенерацией триггеров)

В Metabot для этого потребовалось бы от 6 до 12 низкоуровневых команд.
У нас — один визуальный блок.


3. Записать в аналитику

Метаботовская команда run_javascript + вызов WayLogger.
Мы прячем всё JS-пекло от пользователя.

В нашем интерфейсе есть:

  • выбор типа логирования: step, event, tag, utter,

  • выбор пути (way),

  • параметры.


4. Переход к следующему шагу

В Metabot это команда run_sentence.
В нашем редакторе — просто стрелка между узлами.


5. Обращение к LLM (call_llm)

В Metabot — большой JSON с настройками callback.
Мы делаем:

  • выбор модели

  • выбор агента

  • system / user prompts

  • способ отображения ответа

  • параметры истории

  • next & error flow

Всё это — внутри одного визуального окна.


6. Поиск по базе знаний (search_knowledgebase)

Точно так же — один узел, один JSON.
А Metabotу при импорте достанется пачка сложных команд и связок.


##

Почему наши команды будут «упакованными»

(концепция compact high-level commands)

Каждая наша команда — это высокоуровневый «комбинированный» блок.
Когда пользователь его настраивает, мы:

  • собираем данные в простой JSON (наш формат),

  • передаём этот JSON мапперу,

  • маппер превращает один наш узел в:

    • 1 или несколько sentences

    • десятки phrases

    • references

    • JS-код

    • триггеры

    • диплинки
  • переходы

  • аналитику

и так далее

То есть пользователь видит простую, компактную визуальную воронку, а под капотом:

капотом

строится настоящая сложная система Metabot с триггерами, скриптами, условиями, логированием и разветвлёнными сценариями.


## Пример эффекта (наглядно)

Было бы без нашего редактора 👇

Один узел =
→ 3–5 команд отправки сообщений
→ 1–3 условия
→ 3–10 кнопок (references)
→ 1–5 вспомогательных скриптов
→ JS обработчики
→ триггеры для ссылок
→ аналитика как отдельный скрипт
→ ручное связывание переходов

С нашим редактором 👇

Один узел =
→ 1 блок Send Text с кнопками и аналитикой
→ 1 JSON-объект
→ 1 клик: «Импорт в Metabot»
→ всё остальное сделает маппер и билдер


## Вводная мысль для перехода к следующей главе

Теперь, когда мы понимаем:

  • какие команды существуют внутри Metabot,

  • почему они такие низкоуровневые,

  • и зачем нам свой набор «уплотнённых» команд,

мы можем перейти к следующему этапу —
спецификации нашего JSON-формата, который и станет языком для визуального конструктора.


Если всё ок, я сделаю следующий раздел:

🔷 «Наш JSON-формат: структура всех типов шагов»

включая:

  • поля узла,

  • поля кнопок,

  • поля аналитики,

  • поля ссылок,

  • поля LLM,

  • и пример полного JSON на 6–8 шагов.

Гони?


⚡️ Наш новый формат для no-code редактора

Теперь, когда ты знаешь, какие команды существуют в Metabot и как они хранятся в sentences/phrases/references, мы можем спроектировать наш собственный JSON-формат.

Он не равен командам Metabot —
мы создаём собственную, удобную DSL.

А затем мы создадим маппер, который превращает наш JSON → структуры Metabot.

Простой пример шага:

{
  "code": "hello_world",
  "type": "send_text",
  "name": "Приветствие",
  "content": "Привет! Как дела?",
  "next_step": "next_message",
  "coordinates": { "x": 120, "y": 300 },
  "buttons": [
    {
      "title": "Продолжить",
      "value": "go",
      "next_step": "continue",
      "add_tags": [],
      "remove_tags": []
    }
  ]
}

Важно: наш JSON ≠ команды Metabot

Наша концепция:

  • Пользователь создаёт узлы (steps).

  • Наш JSON описывает машину состояний.

  • На импорте Mapper превращает “steps” → множество “phrases”.

Например:

Наш узел “send_text” превращается в:
  • 1 или несколько команд send_text (для каждого канала)

  • 0–5 команд add/remove tags

  • 0–1 команд run_javascript

  • 0–10 кнопок в таблице references

  • 0–1 переход run_sentence в следующий скрипт

То есть одна наша команда = много внутренних.

Именно поэтому мы делаем свой язык.