Перейти до змісту

Загальна архітектура ланцюжків

Сценарій у MyCode.Bot будується як ланцюжок нод. Кожна нода має свою роль у сценарії: запускає виконання, показує повідомлення, чекає ввід, викликає API, перевіряє умову, записує дані або завершує виконання.

Нода починає роботу, коли виконання приходить на її вхід. Після завершення вона або передає керування в наступну ноду, або показує екран і чекає нової дії користувача, або завершує сценарій.

Як читати схему

Поняття Що означає
Вхід Connection, яким виконання приходить у ноду. До одного входу можуть вести різні попередні ноди.
Звичайний вихід Перехід NextAction до однієї наступної ноди.
Спеціальний вихід Окрема гілка, наприклад True / False, Prompt / Invalid або вихід конкретної кнопки.
Точка входу Нода, з якої система запускає новий сценарій: Trigger, Agent trigger, Error або системна подія.
Термінальна нода Нода без наступного переходу. Наприклад, JSON output повертає JSON, а Chat передає діалог оператору.

Редактор зберігає connections як action-рядки. Звичайні ноди мають action node:{id}, екрани - go_to_screen:{id}, а event/webhook можуть мати системний або користувацький action. У панелі слід з'єднувати ноди через конектори, а не вводити ці службові рядки вручну.

Швидкий каталог

Нода Технічна назва Для чого використовується Виходи Чекає користувача Типовий режим
Event Event Запускає сценарій за подією. Детальніше: Типи подій. 1 Ні Messenger
HTTP webhook Soon HttpWebhook Запускає сценарій зовнішнім HTTP POST 1 Ні Webhook
Screen Screen Показує повідомлення, зображення та кнопки Кнопки + fallback Так Messenger
Keyboard Screen Screen Показує екран із клавіатурними варіантами відповіді Кнопки + fallback Так Messenger
Carousel screen CarouselScreen Показує карусель карток із кнопками (тільки Instagram) Кнопки карток + fallback Так Instagram
Share phone screen SharePhoneScreen Просить користувача поділитися телефоном 1 Так Messenger
Input UserInput Перевіряє та нормалізує введене значення Next / Prompt / Invalid За потреби Messenger
Viber survey ViberSurvey Показує опитування й розгалужує сценарій за відповіддю По одному на варіант + fallback Так Viber Business
HTTP request HttpRequest Викликає зовнішній HTTP API 1 Ні Messenger / AI tool
JSON processor JsonProcessor Перетворює JSON або текст на змінні 1 Ні Messenger / AI tool
Condition Condition Обирає true- або false-гілку за JS-умовою 2 Ні Messenger / AI tool
Switch SwitchNode Маршрутизує сценарій за точним значенням По одному на case + default Ні Messenger
Set user tag SetUserTag Додає тег поточному учаснику 1 Ні Messenger
Get user tag GetUserTag Читає теги учасника у змінну (JSON-масив) 1 Ні Messenger
User has tag UserHasTagNode Перевіряє теги учасника й розгалужує сценарій 2 (True / False) Ні Messenger
Remove user tag RemoveUserTagNode Видаляє один тег поточного учасника 1 Ні Messenger
Set memory SetMemory Зберігає набір полів між execution-запусками 1 Ні Messenger
Get memory GetMemory Читає збережені поля у змінні 1 Ні Messenger
Chat Soon Chat Передає діалог оператору 0 Ні Messenger handoff
JSON output JsonOutput Повертає фінальний JSON із AI tool 0 Ні AI tool

Processor видно в GET /api/BotSchema/node-types із кодом 3, але це лише зарезервоване enum-значення. Для нього немає concrete node, DTO/mapper, форми налаштування, CRUD endpoint або runtime-поведінки, тому створити й використовувати його як ноду не можна.

HttpWebhook має backend API створення і runtime endpoint, але в поточному backend немає HttpWebhookNodeMapper. Через це нода не повертається у загальній DTO-відповіді схеми й не є повністю доступною для стандартного editor UI. На фронті вона наразі не використовується; до уточнення інтеграції позначається як Soon.

Типи подій

Event є технічною нодою для кількох точок входу. У швидкому каталозі вона показана як Event, але конкретний сценарій запуску визначає EventType.

EventType Коли використовується
OnMemberFollow Стартовий entry-flow для Telegram /start і Viber conversation_started; може запускатися і для вже наявного учасника.
OnEnd Зарезервована подія завершення; автоматичний host-trigger у перевіреному backend не знайдено.
OnError Окрема гілка обробки помилки. У конструкторі може відображатися як Error.
OnTrigger Запуск користувацьким action/параметром.
OnChatClosed Новий сценарій після закриття операторського чату.
OnAgentTriggered Вхід у синхронний AI tool; у конструкторі відповідає ноді Agent trigger.

Як працює виконання

У межах одного execution ноди виконуються послідовно: нода отримує керування на вході, виконує свою дію і передає керування далі через звичайний або спеціальний вихід.

Event -> HTTP request -> Condition -> Screen

Якщо нода показує екран і чекає дію користувача, поточний execution завершується. Наступне повідомлення або натискання кнопки починає новий execution. Backend переносить у нього поточний ввід і системний member context, але не весь словник результатів попереднього запуску.

Через це дані, які мають пережити кілька повідомлень користувача, потрібно зберігати окремо: через Set memory / Get memory або теги користувача.

Змінні #var

Змінна зберігається в контексті без #, але в шаблоні перед її ключем ставиться #:

#member.name
#node.12.http.statusCode
#node.25.customerName

Імена можуть містити латинські літери, цифри, _ і сегменти через крапку. Наприклад, #node.12.http.statusCode - валідний ключ, а ключ із дефісом не зчитається як одна змінна. Пошук ключів не залежить від регістру, однак для читабельності варто зберігати однаковий стиль написання.

У звичайному тексті відсутня змінна замінюється порожнім рядком. Тому текст Вітаємо, #member.name! перетвориться на Вітаємо, !, якщо ім'я не задане.

Окремого escape-синтаксису для literal #name немає: така послідовність буде сприйнята як змінна і, якщо ключ відсутній, зникне з результату.

Системні змінні

Коли сценарій запущено з member context, доступні такі змінні:

Змінна Значення
#member.name Ім'я учасника
#member.phone Телефон учасника
#member.second_name Друге ім'я або прізвище з моделі учасника
#member.nick Nickname учасника
#member.external_id ID учасника у зовнішньому месенджері
#member.tags Теги учасника як JSON-рядок масиву, наприклад ["vip","kyiv"]. Оновлюється під час поточного execution після Set user tag або Remove user tag.
#bot.name Назва бота

У webhook без знайденого учасника та в AI tool member context відсутній, тому ці значення порожні або недоступні.

Змінні, які створюють ноди

Більшість нод записує результат у просторі #node.{id}.*. Наприклад, якщо HTTP request має ID 12, код відповіді буде доступний як #node.12.http.statusCode.

Джерело Типовий ключ
Ввід після Screen або Keyboard Screen #node.{screenId}.{TargetKey}
Input #node.{id}.{TargetKey}
Viber survey #node.{id}.{TargetKey}
Event #node.{id}.event_triggered, #node.{id}.trigger_param
HTTP request #node.{id}.http.statusCode, #node.{id}.http.isSuccess, #node.{id}.http.rawBody, #node.{id}.http.reasonPhrase, #node.{id}.http.queued в async-режимі та поля JSON
JSON processor Поля JSON або #node.{id}.json.source
Condition #node.{id}.condition.result, #node.{id}.condition.action, іноді #node.{id}.condition.error
User has tag #node.{id}.userHasTag.result
Switch #node.{id}.switch.result, #node.{id}.switch.action
Get user tag #node.{id}.{OutputKey}
Get memory #node.{id}.{memoryField}
JSON output #node.{id}.json.raw перед завершенням execution

Точний список доступних значень для ноди можна отримувати з variable picker. Значення в такому списку можуть бути порожніми: це підказка про ключ, а не обіцянка, що runtime вже має дані.

Скільки живе змінна

Звичайні #var живуть лише в межах одного execution ланцюжка. Коли бот показав Screen і зупинився, наступне повідомлення користувача починає новий execution.

Backend переносить у новий execution поточний ввід і системний member context, але не весь словник результатів попереднього запуску.

Практичне правило:

  • використовуйте звичайні змінні між нодами, які виконуються без паузи;
  • після Screen гарантовано доступний новий ввід як #node.{screenId}.{TargetKey};
  • щоб зберегти інші дані через кілька повідомлень, використовуйте Set memory / Get memory або теги користувача.

Де працює підстановка

Поле #var {{ JS }}
Screen: title/text/photo URL повідомлення Так Так
Share phone screen: повідомлення і текст share-кнопки Так Так
Viber survey: question text Так Так
HTTP request: body template Так Так
HTTP request: headers - значення Так Так
HTTP request: URL Так Так
JSON processor: JSON template Так Так
JSON output: JSON template Так Так
Set memory: value template Так Так
Set user tag: значення тегу Ні Ні
Condition: expression Так Так, як boolean expression

Звичайні кнопки Screen, тексти варіантів Viber survey, назви memory-полів, MemoryName і TargetKey не проходять через template renderer.

JavaScript у нодах

У тексті або JSON-шаблоні JavaScript записується між {{ і }}:

Вітаємо, {{ truncate(#member.name, 20) }}!
{
  "customer": {{ JSON.stringify(#member.name) }},
  "is_success": {{ #node.12.http.isSuccess }}
}

Перед виконанням #var перетворюються на JS-значення:

  • true / false стають boolean;
  • число в invariant-форматі стає number;
  • інший текст стає безпечним JS string literal;
  • відсутній ключ стає null.

Для JSON краще використовувати JSON.stringify(...), коли значення вставляється не всередину вже відкритих лапок. Проста конструкція "name": "#member.name" може створити невалідний JSON, якщо значення саме містить лапки або службові символи.

Умови

Condition.Expression приймає raw JS expression або вираз в одній зовнішній парі {{ ... }}:

#node.12.http.statusCode == 200 && #node.12.http.isSuccess
parseJson(#node.12.http.rawBody).items.length > 0

Результат приводиться до boolean. Порожній рядок, 0, false, no, null, undefined і NaN означають false. Ненульове число, true, yes та інший непорожній рядок означають true. Object або array напряму до boolean не приводяться - порівняйте конкретну властивість або довжину.

Доступні helper-функції

Функція Призначення Приклад
truncate(value, length) Обрізає текст і додає ... {{ truncate(#member.name, 10) }}
parseJson(json) Перетворює JSON-рядок на JS object {{ parseJson(#node.12.http.rawBody).order.id }}
parseBase64Json(base64) Декодує base64 JSON і повертає object {{ parseBase64Json(#node.5.payload).status }}

Стандартні expression-можливості JavaScript, зокрема доступ до полів, масивів, .map(...), .join(...) і глобальний JSON, виконує engine Jint.

Обмеження й помилки JS

  • Condition.Expression відхиляє вираз із ; як недозволені statements. У звичайному {{ JS }} template вираз із ; не виконується й мовчки дає порожній фрагмент.
  • На один вираз встановлено timeout 100 мс, максимум 50 statements і recursion depth 5.
  • У звичайному template JS-помилка зупиняє ноду. Виняток - undefined identifier: він дає порожній фрагмент.
  • У Condition відсутня #var стає null і зазвичай веде у false-гілку без помилки.
  • Синтаксична або runtime-помилка Condition додає execution error і зупиняє сценарій. Вона не є автоматичним переходом у false-гілку.
  • HTML entities усередині виразу декодуються, тому збережене редактором > виконується як >.

Які ноди можна використовувати в AI tool

Синхронний AI tool не може чекати нове повідомлення людини або показувати messenger screen. Практично підтримуваний skeleton:

Agent trigger -> HTTP request / JSON processor / Condition -> JSON output у кожній гілці
Нода У AI tool Причина
Agent trigger Так Вхід і валідація аргументів
HTTP request Так Синхронний зовнішній API call
JSON processor Так Синхронне формування variables
Condition Так Синхронне розгалуження
JSON output Так Обов'язковий terminal result
Screen, Keyboard Screen, Carousel screen, Share phone screen, Input, Viber survey Ні Очікують взаємодію користувача
Chat Ні Terminal handoff без JSON
Set user tag, Get user tag, User has tag, Remove user tag Ні Немає member context/post-processing tool flow
Set memory, Get memory Ні Memory dispatcher потребує member UserId
Switch Ні Не входить у перевірений skeleton AI tool
HTTP webhook Не рекомендовано Це зовнішня точка входу, а не tool processing step
Інші Event Не рекомендовано Tool має запускатися через єдиний Agent trigger
Processor Ні Зарезервоване enum-значення без реалізації ноди