Кейс: движок Telegram-ботов, где новый бот - это записи в базе
В 2025 году я делал серию Telegram-ботов для AI-генерации изображений и видео. Боты похожи, но не одинаковы: разные сценарии диалога, разные тарифы, разные наборы кнопок. Классическая ситуация, в которой второй бот делается копипастой первого, а к четвёртому у тебя четыре расползшихся копии одной и той же логики.
Этот кейс - про то, как я вместо четырёх ботов сделал один движок. И про принцип, который окупается почти в любом проекте: изменчивое надо выносить из кода в данные.
Как это делается обычно - и где ломается
Стандартный путь: сценарий диалога зашивается прямо в воркфлоу n8n или в код бота. Пользователь нажал "Старт" - ветка, выбрал стиль - ветка, оплатил - ещё ветка. Пока бот один и сценарий короткий, всё отлично.
Ломается это в двух местах. Первое - тираж: новый бот означает копию воркфлоу, и с этого момента любую правку нужно вносить во все копии. Второе - правки сценария: поменять текст шага или добавить вопрос может только тот, кто умеет редактировать воркфлоу. Каждая мелочь превращается в задачу разработчику.
Решение: конечный автомат, сценарий - в базе
Я построил движок на связке Directus + n8n с конечным автоматом (state machine) в основе. Идея простая:
- Сценарий диалога - это данные, а не код. В Directus живут коллекции этапов и переходов: у этапа - текст сообщения, кнопки, действие (например, запустить генерацию картинки); у перехода - из какого этапа в какой и по какому событию.
- Состояние пользователя - тоже данные. У каждого пользователя хранится текущий этап диалога.
- n8n - универсальный исполнитель. Один набор воркфлоу на все боты: пришло сообщение - читаем текущее состояние пользователя - выполняем действие этапа - переводим по подходящему переходу - отвечаем.
Воркфлоу при этом ничего не знает о конкретном сценарии. Он умеет ровно одно: исполнять любой сценарий, описанный в базе.
Что это дало
Главный результат: новый бот заводится записями в базе, без переписывания воркфлоу. Завести этапы, тексты, кнопки и переходы - и бот работает. Движок получился переиспользуемым: запуск следующего бота - это работа с данными, а не новая разработка.
Побочные эффекты оказались не менее ценными:
- Правки сценария перестали быть задачей разработчика. Поменять текст шага или добавить кнопку можно прямо в админке Directus.
- Отладка стала прозрачной. Состояние каждого пользователя видно в базе: на каком он этапе, как сюда попал. Не нужно реконструировать путь по логам.
- Логика перестала расползаться. Исправление бага в исполнителе автоматически чинит все боты сразу - копий больше нет.
- Появилась воронка бесплатно. Раз состояние каждого пользователя лежит в базе, ответ на вопрос "сколько людей дошло до оплаты и где отваливаются" - это один запрос к базе, а не отдельный проект по аналитике.
Границы подхода
Честности ради - конечный автомат нужен не всегда.
Если бот - это три линейных шага и он один, автомат избыточен: вы потратите время на движок, который не окупится. Прямолинейный воркфлоу будет дешевле.
С другой стороны, для свободного диалога автомата мало: когда пользователь пишет что угодно, нужна LLM. Но и здесь автомат не мешает, а помогает: агент со свободным диалогом хорошо живёт поверх автомата, который держит каркас сценария - оплату, лимиты, обязательные шаги. LLM отвечает за разговор, автомат - за то, чтобы бот не потерял пользователя и деньги.
Точка окупаемости подхода - второй похожий бот или первый сценарий, который придётся часто править. У меня оба условия сработали.
Вывод
Принцип старше меня: то, что часто меняется, должно жить в данных, а не в коде. Новизна в том, что связка low-code инструментов - Directus как админка и хранилище, n8n как исполнитель - делает этот принцип дешёвым в реализации. Не нужно писать свою админку и свой интерпретатор сценариев: 80 процентов инфраструктуры уже готово.
Если у вас в планах "нам нужен бот, а потом ещё пара похожих" - закладывайте автомат сразу. Второй бот скажет вам спасибо деньгами и сроками.