Ваш Telegram-бот работает. Но стоит OpenAI вернуть 500 ошибку - он молча падает, и клиенты думают, что вы закрылись. А когда нужно добавить новую команду, вы лезете в код и тратите полдня. Знакомо?
В этой статье разбираем, как сделать бота надёжным и гибким - с помощью продвинутых приёмов n8n. Никакого программиста, только визуальные ноды и немного JavaScript (который можно просто скопировать).
Разберём на примере турагентства: бот принимает заявки на подбор тура, резюмирует отзывы и переводит на английский. Но подход подойдёт любой нише - стройфирме, онлайн-школе, шоуруму.
Code-нода: пишем JavaScript прямо в n8n - парсим JSON, трансформируем данные, вызываем внешние библиотеки
Code-нода - это полноценный Node.js в браузере. Используется когда встроенных нод не хватает для нужной трансформации данных.
Основная структура Code-ноды:
// items - входящие данные из предыдущей ноды
for (const item of items) {
// Работаем с каждым item
const text = item.json.message?.text || '';
// Добавляем новое поле
item.json.processedText = text.toLowerCase().trim();
item.json.wordCount = text.split(' ').length;
}
// Обязательно возвращаем items
return items;
Реальные примеры использования:
Парсинг сложного JSON:
for (const item of items) {
const raw = item.json.choices[0].message.content;
// Иногда GPT возвращает JSON обёрнутый в markdown
const cleaned = raw.replace(/```json\n?/, '').replace(/```/, '').trim();
item.json.parsed = JSON.parse(cleaned);
}
return items;
Форматирование даты:
for (const item of items) {
const date = new Date(item.json.timestamp * 1000);
item.json.formattedDate = date.toLocaleDateString('ru-RU', {
day: 'numeric', month: 'long', year: 'numeric'
});
}
return items;
Вызов внешних библиотек. В n8n доступны некоторые npm-модули без дополнительной установки: lodash, moment, uuid, crypto. Для остальных нужно либо использовать HTTP Запрос-ноду, либо в self-hosted варианте добавить пакет в Docker-контейнер.
Mode настройки: «Run Once for All Items» - код выполнится один раз и получит все items как массив. «Run Once for Each Item» - код выполнится для каждого item отдельно. Для большинства трансформаций удобнее первый вариант.
Switch-нода: ветвим сценарий по значению поля (например, команда /summarize vs /translate vs дефолт)
Switch - это аналог switch/case в программировании. Позволяет разделить сценарий на разные ветки в зависимости от значения поля.
Типичный сценарий: бот принимает команды /summarize, /translate, /help. Каждая команда запускает свою логику.
Настройка Switch-ноды:
Mode: Rules
Input: {{ $json.message.text }}
Добавляете правила:
- Rule 1: Contains
/summarize-> Output 1 - Rule 2: Contains
/translate-> Output 2 - Rule 3: Contains
/help-> Output 3 - Fallback Output: Output 4 (всё остальное)
К каждому выходу подключаете соответствующую логику.
Пример для AI-бота с несколькими режимами:
Rule 1: {{ $json.message.text }}.startsWith('/summarize') -> ветка резюмирования
Rule 2: {{ $json.message.text }}.startsWith('/translate') -> ветка перевода
Rule 3: {{ $json.message.text }}.startsWith('/analyze') -> ветка анализа
Fallback -> обычный чат-режим
В ветке резюмирования системный промпт OpenAI: «Кратко изложи суть текста в 3 предложениях». В ветке перевода: «Переведи текст на английский язык». Это позволяет одному боту делать несколько разных вещей.
Важный нюанс: все ветки в конце должны сходиться к одной Telegram Send Сообщение ноде. Или у каждой ветки должна быть своя отправка ответа. Первый вариант чище - используйте ноду Merge для объединения потоков.
Loop over Items: обходим массив результатов поиска и шлём каждый в отдельное Telegram-сообщение
Когда сценарий обрабатывает массив данных - например, 10 результатов поиска - нужно обойти каждый элемент и что-то с ним сделать.
n8n обрабатывает массивы автоматически: если нода получает 5 items, следующие ноды выполнятся 5 раз. Но иногда нужен явный контроль над итерацией.
Нода Loop Over Items (Split in Batches) позволяет:
- Обрабатывать items пачками по N штук
- Добавлять задержку между итерациями
- Накапливать результаты и передавать дальше
Пример: получаем список из 20 статей, для каждой делаем запрос к OpenAI для генерации резюме, потом отправляем все резюме одним сообщением.
HTTP Request (получаем список) -> Loop Over Items (batch_size: 5) -> OpenAI (резюме) -> [конец цикла] -> Telegram Send
Настройка:
- Batch Size: 5 (обрабатываем по 5 статей за раз)
- После Loop Over Items ноды подключаете нужные действия
- В конце цикла Loop Over Items автоматически продолжает до конца массива
Для отправки массива результатов одним сообщением: добавьте Code-ноду после цикла, которая склеивает все item.json.summary в одну строку через '\n\n'.join().
Важно: при массовой отправке в Telegram соблюдайте rate limit - не больше 30 сообщений в секунду и 1 сообщение в секунду в один чат. Добавьте ноду Wait (задержка 1.1 секунды) внутри цикла чтобы не получить бан от Telegram.
Error Сценарий: настраиваем запасной сценарий, который ловит ошибки и шлёт алерт в Telegram-чат
В боевой среде сценарии падают. OpenAI возвращает 500, Telegram недоступен 10 минут, кончились деньги на счёте. Нужно об этом знать.
Error Сценарий - это отдельный сценарий, который запускается автоматически при ошибке в другом сценарии.
Создание Error Сценария:
- Создаёте новый сценарий, называете «Error Handler».
- Триггер: Error Trigger (нода специально для ошибок).
- К триггеру подключаете Telegram Send Сообщение:
- Chat ID: ваш личный chat_id
- Text:
❌ Ошибка в workflow: {{ $json.workflow.name }}
Сообщение: {{ $json.execution.error.message }}
Время: {{ $now.toLocaleString('ru-RU') }}
- Активируете Error Сценарий.
Подключение к основному сценарию:
Открываете настройки основного сценария (кнопка настроек справа вверху) -> «Error Сценарий» -> выбираете «Error Handler».
Теперь при любой ошибке в основном сценарии вам придёт уведомление в Telegram с описанием ошибки.
Дополнительно можно добавить в основной сценарий Try/Catch через Error Output ноды: к каждой критичной ноде подключите ветку с красной стрелкой. Которая отправляет пользователю вежливое сообщение об ошибке вместо тихого падения.
Sub-сценарий: выносим повторяющуюся логику в отдельный сценарий и вызываем через Execute Сценарий
Когда одна и та же логика нужна в нескольких сценариях - выносим её в отдельный sub-сценарий.
Пример: проверка что пользователь авторизован (есть в белом списке). Это нужно делать в каждом боте. Создаём sub-сценарий «Check User Auth»:
Execute Workflow Trigger -> Code-нода (проверка chat_id) -> возвращаем { authorized: true/false }
Вызов из основного сценария:
Telegram Trigger -> Execute Workflow (Check User Auth, передаём chat_id) -> IF (authorized == true) -> дальнейшая логика
Ещё один кейс: форматирование ответа для Telegram. Если у вас несколько ботов с одинаковым форматом вывода - вынесите форматирование в sub-сценарий. При изменении формата правите в одном месте.
Настройка Execute Сценарий ноды:
- Сценарий: выбираете нужный сценарий
- Inputs: передаёте данные (JSON)
- Wait for sub-execution: On (ждём ответа от sub-сценария)
Sub-сценарий получает данные через «Execute Сценарий Trigger» и возвращает через обычный конец сценария.
Работа с бинарными данными: принимаем голосовое сообщение из Telegram, транскрибируем через OpenAI Whisper
Telegram поддерживает голосовые сообщения. Сценарий для их обработки:
Нода 1: Telegram Trigger
- Updates: Voice (добавьте к Сообщение)
Нода 2: IF
- Условие:
{{ $json.message.voice }}is not empty - True -> обрабатываем голос, False -> обычный текстовый ответ
Нода 3: HTTP Запрос (скачиваем файл)
- URL:
https://api.telegram.org/bot<токен>/getFile?file_id={{ $json.message.voice.file_id }} - Сначала получаем file_path
Нода 4: HTTP Запрос (скачиваем бинарные данные)
- URL:
https://api.telegram.org/file/bot<токен>/{{ $json.result.file_path }} - Ответ Format: File
Нода 5: OpenAI
- Resource: Audio
- Operation: Transcribe
- Binary Property: data
- Language: ru
Нода 6: продолжаем сценарий с текстом транскрипции
- Используем
{{ $json.text }}как входные данные для GPT
Этот паттерн открывает возможность голосового ввода в Telegram-ботах без дополнительных сервисов.
Rate limiting и retry: настраиваем Wait-ноду и механизм повтора при 429 от OpenAI
OpenAI возвращает ошибку 429 (Too Many Запросы) когда превышен rate limit. Для бесплатного плана - 3 запроса в минуту, для Tier 1 ($5+ потрачено) - 500 запросов в минуту.
Wait-нода добавляет задержку в сценарий. Использование:
- После Loop Over Items: задержка 1 секунда между итерациями
- Перед повторным запросом: задержка 60 секунд после 429
Механизм retry через Error Output:
- К ноде OpenAI добавляете Error Output.
- В Error Output-ветке добавляете IF: проверяете
{{ $json.error.status }}equals 429. - Если 429: Wait 60 секунд -> снова запрос к OpenAI (Loop обратно).
- Если другая ошибка: отправляете алерт и завершаете.
Простой вариант retry - настройка в самой ноде. У большинства нод в n8n есть Settings -> On Error: Continue (игнорировать), Stop Сценарий (остановить). Или Retry on Fail (повторить N раз с интервалом X секунд).
Для боевых ботов рекомендуется:
- Retry: 3 попытки с интервалом 10 секунд для временных ошибок
- Wait 1.1 секунды при отправке в Telegram (rate limit)
- Error Сценарий для уведомления об ошибках
Эти три паттерна (Code-нода, Error Сценарий, retry) переводят бота из «работает на демо» в «работает в бою».
Частые вопросы
Как отлаживать Code-ноду - есть ли console.log в n8n?
Да. В Code-ноде работает console.log() и он выводится в execution-лог. Нажмите на выполнение в разделе Executions и ищите вкладку «Browser logs» или просто смотрите output ноды. Также можно добавить временное поле item.json.debug = 'значение' и увидеть его в output.
Можно ли в Code-ноде сделать fetch к внешнему API?
Да, работает стандартный fetch или axios. Но для большинства задач лучше использовать отдельную ноду HTTP Запрос - она даёт визуальное отображение в логах и проще в отладке. Code-нода с fetch полезна когда нужен сложный запрос с динамическими заголовками или несколько запросов в цикле внутри одной ноды.
Как сделать так, чтобы сценарий запускался не чаще одного раза в секунду?
Добавьте ноду Wait сразу после Telegram Trigger с задержкой 1 секунда. Это не защищает от параллельных запросов - несколько пользователей одновременно всё равно запустят несколько экземпляров сценария. Для настоящего rate limiting нужна очередь через Redis или ограничение через IF по timestamp последнего запроса пользователя.
Где хранить секреты (API-ключи) в n8n, чтобы не светить в коде?
Все API-ключи храните в разделе Credentials (левое меню n8n). Credentials зашифрованы и не отображаются в открытом виде. В Code-ноде доступ к Credentials напрямую невозможен - используйте HTTP Запрос ноду или специализированные ноды, которые подтягивают Credentials через выпадающий список.
Как мониторить упавшие сценарии - есть ли алерты?
Да - через Error Сценарий (описано в статье). Дополнительно n8n Cloud имеет встроенные email-уведомления о падениях. Для self-hosted: настройте Health Check конечная точка API и пингуйте его из Uptime Robot или аналога. n8n также поддерживает отправку метрик в Prometheus для тех кто строит полноценный мониторинг.
Что внедрить прямо сейчас
- Создайте Error Сценарий с уведомлением в Telegram - это займёт 15 минут. Скопируйте шаблон из раздела выше.
- Добавьте Switch-ноду в вашего бота, чтобы он реагировал на разные команды.
- Настройте retry для нод OpenAI - 3 попытки с интервалом 10 секунд.
Эти три шага превратят вашего бота из игрушки в рабочий инструмент, которому можно доверить общение с клиентами.
AI Компас (t.me/kosmoslab_ai) - канал для предпринимателей в РФ и СНГ, которые применяют AI в своём бизнесе без программиста. Разбираем инструменты и схемы - без курсов и теории.