Загальна архітектура ланцюжків
Сценарій у 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 | Так | |
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-значення без реалізації ноди |