Вход и выход воркфлоу

У графа две границы: entry, куда приходит запрос, и exit, откуда уходит ответ. Обе подчиняются жёстким правилам — их нарушение раньше не ломало запуск заметно, а тихо выбрасывало половину работы.

Entry ровно один

Entry — это и есть вход запуска, а не метка старта. Движок разбирает один и тот же входной объект для каждой entry-ноды, поэтому вторая не может принести второй вход: она дублирует первый и запускает вторую, ни с чем не синхронизированную ветку. Обе цепочки выполняются целиком, и обе оплачиваются.

Поэтому два entry — ошибка graph.multiple_entry. Она безусловна: черновика, в котором две entry ведут к чему-то валидному, не бывает. Сохранить граф ошибка не мешает, но деплой и запуск блокирует.

Редактор не даст создать вторую entry: перетаскивание из палитры игнорируется, если entry уже есть на холсте, а при вставке готового сниппета его entry подставляется к уже существующей — все рёбра сниппета приходят на неё.

Два выхода entry

  • output — сообщение. Для чата, Telegram и вебхука это строка, у неё нет полей. Если запуск сделан с произвольным JSON-объектом (ручной запуск, API, вызов из другого воркфлоу), это весь объект целиком.
  • data — контекст триггера фиксированной формы: trigger, workflow_id, execution_id, workspace_id, user_id, chat.session_id и блоки telegram / webhook / cron.

Exit — хотя бы один, и он должен быть достижим

Граф без exit получает предупреждение graph.no_exit. Хуже другой случай: exit есть, но до него не доходит ни одного exec- или execute_data-ребра. Такой exit не выполнится никогда, а запуск закончится пустым результатом — валидатор отбивает это ошибкой exec.exit_no_exec_trigger.

Ссылка в шаблоне ноду не запускает: {{ nodes.<id>.output }} читает значение, но не даёт exit сработать.

Что делает exit

  • Порт end принимает финальное значение. Поле Output Expression (output_mapping) при непустом значении заменяет то, что пришло на end.
  • Отдельный вход files принимает ссылки на файлы, и они уходят вместе с ответом: в чате картинки, аудио и вложения показываются рядом с сообщением.
  • Поле Error message (error_text) задаёт текст, который увидит пользователь при необработанной ошибке. Доступны error (короткое безопасное описание сбоя), error_code, error_id (код обращения в поддержку), failed_node_id и failed_node_type. Технических подробностей — ответа провайдера, текста запроса к базе — здесь нет ни при какой настройке: это сообщение читает ваш собеседник, а не вы. Полная картина остаётся в карточке ноды и в логах запуска.

Несколько exit: только для взаимоисключающих ветвей

Все отработавшие exit пишут в один и тот же объект результата. Побеждает не тот, кто закончил позже, а последний в порядке нод внутри определения графа — то есть перестановка списка нод меняет ответ. В чате правило другое: показывается тот exit, который первым начал стримить, токены второго уходят в пустоту.

Поэтому два exit, способные сработать в одном запуске, — это exec.multi_exit_race: ошибка на деплое и запуске, предупреждение, пока вы редактируете граф.

Если / Иначе
Выход
Выход
  • Исполнение + данные
Каждая ветка условия может иметь свой exit: сработает ровно одна.

Как чинить гонку

Сведите ветви в один exit. Если они действительно идут параллельно, поставьте перед ним wait_all и заведите каждую ветвь в его вход barrier_in. Раздавать каждой параллельной ветке собственный exit — не выход: это ровно та форма, из-за которой один ответ затирает другой.