01SDK или визуальный редактор
- Визуальный редактор. Бот собирается в редакторе FlowCastle, токен вы отдаёте FlowCastle, и бот работает на нашей стороне. Код не нужен. Начните с Создайте первого Telegram-бота за 10 минут.
- Code SDK. Бот уже работает в коде, и вы хотите его оставить. Код, хостинг, polling или webhook остаются у вас. FlowCastle добавляет слой вокруг бота: контакты, живой диалог, рассылки, аналитику.
- И то и другое. С
runtime: { enabled: true }сценарии из редактора работают через вашего бота. Апдейт, который совпал с опубликованным триггером FlowCastle, обрабатывает сценарий, и до ваших хендлеров он не доходит. Двойных ответов не бывает. Всё остальное идёт в ваш код как раньше. Подробнее о триггерах: Триггеры: как запускается ваш бот. - Другой фреймворк или язык. Адаптера пока нет.
02Какой пакет ставить
| Фреймворк | Среда | Установка | Импорт |
|---|---|---|---|
| grammY ≥ 1.20 | Node.js ≥ 18 | npm i @flowcastle/grammy @flowcastle/sdk-runtime | import { flowcastle } from '@flowcastle/grammy' |
| Telegraf ≥ 4.16 | Node.js ≥ 18 | npm i @flowcastle/telegraf @flowcastle/sdk-runtime | import { flowcastle } from '@flowcastle/telegraf' |
| aiogram 3.x | Python ≥ 3.10 | pip install 'flowcastle[aiogram]' | from flowcastle.adapters.aiogram import AiogramAdapter |
| python-telegram-bot 21–22 | Python ≥ 3.10 | pip install 'flowcastle[python-telegram-bot]' | from flowcastle.adapters.python_telegram_bot import PythonTelegramBotAdapter |
Оба Node-пакета требуют @flowcastle/sdk-runtime как peer-зависимость. npm 7 и новее ставит её сам, но надёжнее указать явно. Других зависимостей у Node-пакетов нет. Python-ядро использует только стандартную библиотеку, а фреймворк ставится как extra.
03Ключ
- Войдите в панель. Бесплатный тариф, карта не нужна.
- Откройте приложение (или создайте новое) и нажмите Добавить бота.
- Выберите Code SDK.

Токен Telegram здесь не спрашивают. Назовите подключение и создайте его. Вы получите ключ fc_sdk_… и инструкцию под выбранную библиотеку.

Положите ключ в окружение рядом с BOT_TOKEN под именем FLOWCASTLE_API_KEY. Это секрет, в коде его не храните. BOT_TOKEN в FlowCastle не передавайте никогда.
04Минимальное подключение
Два правила порядка, одинаковые для всех библиотек:
- Подключайте FlowCastle раньше остальных хендлеров, чтобы он видел каждый апдейт.
- Вызывайте
ready()до запуска polling или webhook. Этот вызов загружает триггеры опубликованных сценариев. Без него первый подходящий апдейт может уйти в ваш хендлер.
grammY:
import { Bot, Context } from 'grammy';
import { flowcastle, FlowCastleFlavor } from '@flowcastle/grammy';
type BotContext = FlowCastleFlavor<Context>; // adds ctx.flowcastle
const bot = new Bot<BotContext>(process.env.BOT_TOKEN!);
const fc = flowcastle<BotContext>({
apiKey: process.env.FLOWCASTLE_API_KEY!,
privacy: {}, // see Privacy below
runtime: { enabled: true }, // only if no-code flows should run through this bot
onError: (e) => console.error('[flowcastle]', e),
});
bot.use(fc); // BEFORE other handlers
// ...existing handlers unchanged...
await fc.ready();
bot.start();
// on shutdown: await bot.stop(); await fc.flush(); fc.destroy();
aiogram 3:
import asyncio
import os
from aiogram import Bot, Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message
from flowcastle import FlowCastleContext, 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)
dp = Dispatcher()
# handlers receive the context by argument name `flowcastle`:
@dp.message(CommandStart())
async def start(message: Message, flowcastle: FlowCastleContext) -> None:
await flowcastle.identify({'displayName': message.from_user.full_name})
async def main() -> None:
bot = Bot(os.environ['BOT_TOKEN'])
await adapter.ready()
adapter.install(dp) # registers an outer middleware on dp.update
dp.shutdown.register(adapter.stop) # final flush
await dp.start_polling(bot)
asyncio.run(main())
Для Telegraf и python-telegram-bot всё устроено так же. В Telegraf добавляется fc.wrapTelegram(bot.telegram), чтобы SDK видел вызовы bot.telegram.* вне middleware. В python-telegram-bot adapter.install(application) вызывается до всех add_handler. Полные примеры: README для Telegraf и README для Python. У пакета для grammY тоже есть свой README.
С webhook всё работает так же.
Бот не ждёт FlowCastle. Событие попадает в очередь в памяти, хендлер выполняется сразу. Очередь ограничена 500 событиями, при переполнении самые старые вытесняются. Отправка идёт пачками раз в три секунды, при ошибке одна повторная попытка. Если FlowCastle недоступен, вы теряете часть аналитики, а пользователи ничего не замечают.
05Что вызывать из хендлеров
В контексте появляется небольшой API: ctx.flowcastle в Node, аргумент flowcastle в aiogram, context.flowcastle в python-telegram-bot.
| Задача | Node (ctx.flowcastle.) | Python (flowcastle. / context.flowcastle.) |
|---|---|---|
| Отметить цель (конверсию или шаг воронки) | goal(key, props?) | await goal(key, props=None) |
| Записать свойства контакта для CRM | identify(props) | await identify(props) |
| Передать чат оператору в живой диалог | requestLiveAgent({ note? }) | await request_live_agent(note=None) |
| Ведёт ли сейчас чат человек? | isLiveAgentActive (только Node) | нет |
| Запустить сценарий из редактора | await runFlow(flowKey, { inputs? }) | await run_flow(flow_key, inputs=None) |
Что важно знать:
goal,identifyиrequestLiveAgentставятся в очередь и хендлер не тормозят. Им нужен отправитель апдейта. Если его нет, вызов пропускается, а ошибка уходит вonError.- Имена целей ваши:
lead_qualified,order_paid, из чего у вас состоит воронка. Свойства передаются плоским JSON-объектом. Передайте числовоеvalue, и в аналитике появится выручка. - Свойства из
identifyне проходят через фильтр приватности. Не кладите туда сырой текст сообщений. isLiveAgentActiveдаёт подсказку, а не точный ответ: это окно на 30 минут, которое открывает запрос и продлевает каждый ответ оператора. Пока оно открыто, автоответы можно отключить:if (ctx.flowcastle.isLiveAgentActive) return;. В Python SDK этого поля нет, там проверку пропустите.runFlowждёт ответа сервера и возвращает id запуска. Без включённого runtime он выбрасывает ошибку. Сценарий должен быть опубликован и отмечен в панели как доступный из SDK. Оборачивайте вызов в try/catch.
Ответ оператора из живого диалога уходит пользователю через процесс вашего бота. Список методов Bot API, которые сервер может попросить выполнить, короткий и зашит в SDK. Всё, что касается токена, webhook и polling, отклоняется всегда.
06Приватность
Фильтрация идёт внутри вашего процесса, до того как что-то попадёт в очередь или уйдёт наружу.
privacy: {}включает режим по умолчанию, только маршрутизацию. Команды и id нажатых кнопок передаются, текст сообщений нет. У контакта будет только id в Telegram.contactFieldsзадаёт поля профиля, которые можно передавать, напримерcontactFields: ['username', 'languageCode']. Тогда контакты в CRM можно узнать по имени.messageContent: 'full'включает передачу текста. Нужно, если сценарии FlowCastle читают, что пишут люди: ИИ-ответы, триггеры по ключевым словам, ожидание ответа.- В
transformTextвы передаёте свою функцию, которая вычищает текст ещё в вашем процессе, например почту или номера карт. Упала или не уложилась в таймаут (по умолчанию 1 секунда), поле не уйдёт вовсе.
В Python те же параметры называются contact_fields, message_content и transform_text.
Передавайте privacy всегда. Если параметр не указан, SDK работает по-старому и отправляет текст сообщений целиком.
07Как проверить
- Код проходит проверку типов или импортируется:
tsc --noEmitилиpython -c "import bot". - Выводите ошибки через
onErrorи запустите бота. Если за 10 секунд нет ошибок[flowcastle], ключ принят. Неверный ключ даёт 401 примерно через 3 секунды после первого апдейта. - Напишите боту
/start. Через несколько секунд пользователь появится в Контактах, а SDK-бот будет отмечен как подключённый. - Если добавили
goal, вызовите его. Цель должна появиться в карточке контакта и в аналитике целей. - Если включили runtime, опубликуйте сценарий с триггером на
/команду, которой нет в вашем коде. Отправьте её: ответит FlowCastle, а команды из кода продолжат работать. - Остановите процесс через SIGINT (Ctrl+C). Он должен завершиться чисто, без зависания.
08Что почитать дальше
- CRM, живой диалог и аналитика для бота, который у вас уже есть: подробный разбор со скриншотами.
- SDK на GitHub: код, README, контракт приватности и производительности.
- Гайд для AI-агентов: все опции, типичные ошибки и список запретов в одном файле. Дайте его своему AI-агенту.
- Готовые примеры, один и тот же бот на каждой библиотеке: grammY, Telegraf, aiogram, python-telegram-bot.
- Вопросы задавайте в сообществе разработчиков ботов в Telegram или в issues на GitHub. Укажите библиотеку, версию пакета и вывод
onError.
