
Всё, что мы собираем в этой статье, уже есть в виде готового сценария — установите его и настройте под себя.
Открыть шаблонБота написать несложно. Сложности начинаются, когда в него приходят живые люди. И вопросы уже не про код: кто вообще с ним общается? Сколько из них доходят до оплаты? Что делать, когда бот зашёл в тупик и человеку нужен человек? Как написать тем, кто бросил корзину?
Это всё не логика бота. В хендлерах этому не место. Это слой вокруг бота — и обычно он продаётся в комплекте с условием «отдайте нам токен, мы будем хостить бота сами». То есть выбросить свой код.
Есть третий путь. Бот на grammY, Telegraf, aiogram или python-telegram-bot остаётся у вас как есть. Слой вокруг него добавляет открытая middleware из нескольких строк. Ниже — как это выглядит на примере бота с командами /start, /qualify и /human. Пример целиком лежит в репозитории, для каждой из четырёх библиотек.
Что остаётся у вас и что появляется
| У вас, как и было | Появляется |
|---|---|
| Фреймворк, хендлеры, база, хостинг | Контакты: свойства, теги, история каждого |
| Токен бота — FlowCastle его не видит | Живой диалог: оператор отвечает в том же чате, через вашего бота |
| Polling или webhook | Рассылки и цепочки — тоже через вашего бота |
| Всё, что должно жить в git | Цели, воронки, конверсии |
| Карта того, что бот уже умеет, — собранная из трафика |
SDK открытый, лицензия MIT, код на GitHub. На Node без зависимостей, на Python — только стандартная библиотека. Панель FlowCastle — с бесплатным тарифом, карта не нужна.
Шаг 1. Ключ
В панели откройте приложение → Добавить бота → Code SDK.

Токен Telegram здесь не спрашивают. Назовите подключение, нажмите «Создать» — и получите ключ fc_sdk_… вместе с инструкцией под вашу библиотеку.

Переключатель меняет и команду установки, и сниппет. Для aiogram:

Ключ кладём в окружение рядом с BOT_TOKEN — как FLOWCASTLE_API_KEY. Это секрет.
Шаг 2. Три строки
grammY:
import { Bot, Context } from 'grammy';
import { flowcastle, FlowCastleFlavor } from '@flowcastle/grammy';
type BotContext = FlowCastleFlavor<Context>;
const bot = new Bot<BotContext>(process.env.BOT_TOKEN!);
const fc = flowcastle<BotContext>({
apiKey: process.env.FLOWCASTLE_API_KEY!,
privacy: {}, // команды и кнопки — да, текст сообщений — нет
runtime: { enabled: true }, // чтобы визуальные сценарии работали через этого бота (шаг 6)
});
bot.use(fc); // раньше остальных хендлеров
// ...ваши хендлеры, без изменений...
await fc.ready();
bot.start();
aiogram 3:
from flowcastle import FlowCastleCore, FlowCastleOptions
from flowcastle.adapters.aiogram import AiogramAdapter
core = FlowCastleCore(FlowCastleOptions(api_key=os.environ["FLOWCASTLE_API_KEY"], privacy={}, runtime_enabled=True))
adapter = AiogramAdapter(core)
await adapter.ready()
adapter.install(dp) # outer middleware; в хендлеры приходит `flowcastle`
await dp.start_polling(bot)
Для Telegraf и python-telegram-bot — то же самое, все четыре варианта есть в README.
Два момента, о которых лучше знать заранее.
Что уходит наружу, решаете вы. privacy: {} — режим по умолчанию для новых подключений: команды и нажатия кнопок передаются, текст сообщений вырезается ещё в вашем процессе. У контакта будет только id в Telegram; имя или язык — только если разрешите явно: contactFields: ['username', 'languageCode']. Нужен текст (например, для ИИ-ответов) — включите messageContent: 'full'. К нему можно добавить transformText — свою функцию, которая вырезает почту или номера карт до отправки. Упала или не уложилась в таймаут — поле не уйдёт вовсе.
Бот не ждёт FlowCastle. Событие попадает в очередь в памяти, хендлер выполняется сразу. Очередь ограничена 500 событиями, лишнее вытесняется. Отправка — пачками раз в три секунды, при ошибке одна повторная попытка. FlowCastle лёг — вы потеряли часть аналитики, пользователи ничего не заметили.
Запускаем бота, пишем ему /start. В панели у бота вкладка SDK показывает «Подключено», а автор /start появился в контактах.

Интеграция на этом закончена. Дальше — что с ней делать.
Шаг 3. Из хендлеров — в CRM
В контексте появляется небольшой API: ctx.flowcastle в Node, аргумент flowcastle в aiogram, context.flowcastle в python-telegram-bot. Почти всё делают три вызова.
identify — записать свойства контакта. В примере /start сохраняет имя, а /qualify — три вопроса на inline-кнопках, целиком в коде, — по завершении отдаёт ответы:
const lead = { leadNeed: 'website_lead_bot', leadBudget: '500_2k', leadTimeline: 'this_month' };
ctx.flowcastle.identify(lead);
goal — отметить событие, которое важно бизнесу. В примере одна цель висит на демо-кнопке, вторая срабатывает, когда все три ответа собраны:
ctx.flowcastle.goal('lead_qualified', lead);
Имена целей — ваши: subscription_started, order_paid, из чего у вас состоит воронка. Передайте числовое value — в аналитике появится выручка.
Контакт после одного прохода /qualify. Свойства прислал ваш код, теги и статус ведёт FlowCastle:

Вкладка «Цели» того же контакта:

В боте изменились две строки внутри хендлера, который и так был. База данных осталась вашей. А это — та самая «админка», которую просили маркетинг и поддержка.
Шаг 4. Позвать человека
Третий вызов — requestLiveAgent. В примере он на команде /human:
bot.command('human', async (ctx) => {
ctx.flowcastle.requestLiveAgent({ note: 'User asked to talk to a human.' });
await ctx.reply('Соединяю с коллегой — ответ придёт прямо сюда. 💬');
});
bot.on('message:text', async (ctx) => {
if (ctx.flowcastle.isLiveAgentActive) return; // диалог ведёт человек — молчим
await ctx.reply(`Echo: ${ctx.message.text}`);
});
Диалог открывается у оператора в живом чате FlowCastle. Его ответ уходит пользователю через ваш процесс: SDK забирает задание и отправляет сообщение соединением вашего бота. Список того, что сервер вообще может попросить ваш процесс выполнить, зашит в SDK — sendMessage, sendPhoto, answerCallbackQuery и ещё несколько. Всё, что касается токена, webhook и polling, отклоняется независимо от того, что пришло с сервера.
В журнале контакта видна вся цепочка: сообщения пользователя, запрос оператора, ответ бота и ответ человека, ушедший через бота:

isLiveAgentActive — подсказка, а не истина: окно на 30 минут, которое открывает запрос и продлевает каждый ответ оператора. Пока оно открыто, автоответы бота молчат. В Python SDK этого поля пока нет.
Шаг 5. Бот, каким его видит FlowCastle
Самая неожиданная часть. По очищенному трафику — какая команда к какому ответу ведёт, какие кнопки нажимают — FlowCastle восстанавливает диалоги вашего бота и кладёт их на холст Автоматизации рядом с обычными сценариями. По одной карте на точку входа, с пометкой Наблюдаемый. У примера их четыре: /start, /qualify, /human и ответ на произвольный текст. Открываем /qualify, нажимаем Авторасстановку — и то, что было написано в коде, лежит перед нами как сценарий: три вопроса, девять кнопок, финальное сообщение.

Источник истины по-прежнему ваш репозиторий. Карту можно удалить в любой момент — она соберётся заново из нового трафика. Зачем она нужна: коллега, который не читает ваш код, теперь видит, что бот делает. И каждый шаг на карте связан с аналитикой. «На каком вопросе /qualify люди отваливаются?» — теперь на это может ответить не только автор кода.
Шаг 6, по желанию. Сценарии рядом с кодом
Раз runtime: { enabled: true } включён, в том же пространстве можно собирать сценарии в визуальном редакторе — онбординг, дожим после брошенной оплаты, FAQ, — и работать они будут через процесс вашего бота. Правила такие:
- Апдейт, который совпал с опубликованным триггером FlowCastle (например,
/faq, которого нет в вашем коде), обрабатывает сценарий. До ваших хендлеров он не доходит — двойных ответов не бывает. - Всё остальное идёт в ваш код как раньше.
- Ваш код может запустить сценарий сам. В примере — по завершении
/qualify, ответы передаются на вход:
await ctx.flowcastle.runFlow('lead-follow-up', { inputs: lead });
Так запускаются только сценарии, которые в панели отмечены как доступные из SDK. После этого маркетолог правит текст дожима, добавляет шаг или меняет время отправки — и ни одно из этих действий не требует деплоя вашего бота.
Что видно в панели
Цели, контакты, рассылки и карты сходятся в одну аналитику: рост подписчиков, какая рассылка сдвинула какую цель, выручка, если вы передаёте value.

Рассылки собираются в панели и уходят через вашего бота. Сегменты — по свойствам и целям, которые записали хендлеры: «все с leadBudget = 2k_plus, кто так и не дошёл до order_paid» — это фильтр, а не скрипт.
Дальше
- Пример бота для всех четырёх библиотек — папка
examples/в репозитории:/startс identify, кнопка с целью,/qualifyв коде,/human, необязательный сценарий-дожим. Копируйте папку под свою библиотеку и меняйте хендлеры на свои. - Подключаете через AI-агента? Дайте ему гайд для агентов — один файл: порядок установки под каждую библиотеку, все опции, чек-лист проверки, типичные ошибки. Claude Code, Cursor или Codex подключат SDK сами.
- Контракт приватности и производительности целиком — в README.
- Вопросы — в сообществе разработчиков ботов в Telegram.
Бесплатный аккаунт — на dashboard.flowcastle.ai, без карты. SDK на GitHub — под MIT.
