Коротко
- Реальный сетап:
@BotFather→/newbot→ токен вchannels.telegram.botToken(или в переменнуюTELEGRAM_BOT_TOKEN) →openclaw gateway→openclaw pairing approve telegram <CODE>. Никакогоopenclaw channels login telegram: в доке прямо написано, что Telegram подключается не так. - «Работал, обновился — пропал» — обычно битое дерево зависимостей канал-плагина. Лечение:
openclaw doctor --fix, затемopenclaw gateway restart. - В свежих версиях доступ в группах не наследуется из DM-пейринга. В личке бот отвечает, в группе молчит — добавь свой numeric user ID в
groupAllowFrom. - ID — два разных: твой user ID идёт в
allowFrom/groupAllowFrom, а ID группы вида-100…— ключ подchannels.telegram.groups. Перепутал местами — получил «всё настроено, бот молчит».
По запросу «openclaw telegram bot not working» в выдаче одно и то же: официальная дока и её пересказы, где команды переписаны по памяти. Я держу OpenClaw, подключённый к Telegram, на боевых серверах — когда канал молчит, я узнаю об этом первым, и не из дашборда, а от людей, которым бот не ответил. Эта статья — маршрут целиком: подключить с нуля, впустить нужных людей и не впустить лишних, и разобрать типовые поломки — после апдейта, в группе, 401 по токену, рвущийся polling.
Сразу главное: это не `channels login`
В выдаче встречаются гайды, где Telegram подключают через openclaw channels login telegram. В доке на это дословно: «Telegram does not use openclaw channels login telegram; configure token in config/env, then start gateway». Токен кладётся в конфиг или в окружение, затем стартует gateway. Login-команды в этом маршруте нет вообще. Если ты полчаса дебажил, почему login «не видит» Telegram, — ты дебажил шаг, которого не существует. Кто такое советует, доку не открывал.
Подключение с нуля: четыре шага
Пара слов о том, что подключаем. Telegram-канал в OpenClaw — production-ready, личка и группы, под капотом grammY. Каналом владеет gateway-процесс, и роутинг детерминирован: что пришло из Telegram, в Telegram и вернётся — модель канал не выбирает.
Шаг 1. Бот у BotFather. В Telegram пишешь @BotFather — проверь, что handle именно такой, — команда /newbot, забираешь токен.
Шаг 2. Токен и DM-политика в конфиг:
{ channels: { telegram: {
enabled: true, botToken: "123:abc", dmPolicy: "pairing",
groups: { "*": { requireMention: true } },
} } }Запасной путь — переменная окружения TELEGRAM_BOT_TOKEN=…, но она работает только для default-аккаунта, и при конфликте конфиг побеждает env. Хранишь токен в файле через tokenFile — файл должен быть обычным, симлинки не проходят. И неочевидное: после успешного старта identity бота кешируется в state-директории, по докам — до суток; смена или удаление токена этот кеш сбрасывает.
Шаг 3. Gateway и первый апрув:
openclaw gateway
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>При дефолтной dmPolicy: "pairing" на первое сообщение боту в личку прилетает код пейринга. Код живёт час. pairing list telegram показывает, кто стучится; approve впускает. Первый одобренный пейринг заодно назначает владельца команд: проставляет commands.ownerAllowFrom, если тот ещё не задан.
Шаг 4. Группа и два ID. Чтобы бот заработал в группе, нужны два разных идентификатора, и их регулярно путают. Твой личный user ID — кто имеет право говорить с ботом — идёт в allowFrom/groupAllowFrom. ID самой группы — где боту разрешено отвечать — становится ключом под channels.telegram.groups. Отрицательный ID супергруппы вида -100… — это ID чата: его место под groups, а в groupAllowFrom его класть бесполезно.
Свой user ID проще всего подсмотреть в логах: напиши боту в личку и смотри openclaw logs --follow — в записи будет from.id. Либо спроси Bot API напрямую:
curl "https://api.telegram.org/bot<token>/getUpdates"Кто допущен: dmPolicy и группы
dmPolicy принимает четыре значения. pairing — дефолт: каждый новый собеседник ждёт апрува. allowlist — жёсткий список, требует хотя бы один numeric ID в allowFrom. open — впускает всех и требует явного allowFrom: ["*"], чтобы бот не оказался открытым случайно. disabled — личка закрыта.
Для бота с одним хозяином я держу allowlist с numeric user ID: доступ прописан в конфиге и не зависит от того, какие пейринги были одобрены когда-то. Пейринг удобнее, когда собеседники добавляются по одному. А open — осознанный exposure; чем он оборачивается и как его резать, разобрано в гайде по безопасности OpenClaw.
У групп политика отдельная: groupPolicy — open, allowlist (дефолт) или disabled. requireMention по умолчанию true: бот отвечает, только когда его упомянули. groupAllowFrom — это numeric user ID отправителей, не ID чатов. Полезная деталь про дефолты: если секции channels.telegram в конфиге нет вовсе, рантайм сам закрывается в groupPolicy="allowlist". Fail-closed, как и должно быть.
Смежный случай, чтобы не путать: если пейринга требует не Telegram-канал, а сам gateway при подключении устройства — это другая поломка с другой механикой, я разбирал её отдельно: почему OpenClaw пишет gateway pairing required.
Перестал работать после апдейта
Самый нервный сценарий: вчера бот отвечал, сегодня обновился — тишина. Первый порыв — найти «версию, которая сломала», и в поиске гуляют запросы с конкретными номерами. Я на номер валить не буду: дело обычно не в нём, а в том, в каком состоянии обновление оставило установку.
Типовой механизм такой: после обновления канал-плагин не загрузился, потому что дерево зависимостей плагина осталось битым. Проверка и лечение — четыре команды по порядку:
openclaw status --all
openclaw doctor --fix
openclaw gateway restart
openclaw status --allВ первом выводе ищи строку plugin load failed: dependency tree corrupted; run openclaw doctor --fix. Означает ровно то, что написано: канал настроен, но загрузка плагина упала на битом dep-tree. doctor --fix выметает устаревший plugin-staging и auth-shadow, gateway restart стартует уже с чистого состояния. Второй status --all — подтвердить глазами, что канал вернулся.
Вторая пост-апдейтная ловушка тоньше, и жалуются на неё как на «сломали обновлением». В свежих версиях group-авторизация отправителя не наследует DM-пейринг: одобрение в личке больше не даёт права голоса в группах. Симптом узнаваемый: в личке бот отвечает, в группе молчит, конфиг никто не трогал. Это не бага, а security boundary: пейринг остался механикой личных сообщений. Фикс: явно задать groupAllowFrom или per-group allowFrom.
Третья: после апгрейда тебя блокирует собственный allowlist. Лечится openclaw doctor --fix либо заменой @username на numeric ID в списках.
И рефлекс, который я вынес из прод-инцидентов: «обновление прошло» и «канал жив» — два разных утверждения. После апдейта я проверяю фактическое состояние — status --all, channels status --probe — а не верю зелёному выводу инсталлера. Как строить сам процесс обновления, чтобы сюрпризов было меньше, — в гайде по обновлению OpenClaw.
Бот онлайн, но группа молчит
Если два ID разложены по местам и groupAllowFrom заполнен, а в группе всё равно тишина, — скорее всего, это вообще не OpenClaw. Боты в Telegram по умолчанию живут в Privacy Mode и видят не все сообщения группы. Выключается у BotFather: /setprivacy → Disable. Дальше шаг, который легко пропустить: бота надо удалить из группы и добавить заново, иначе Telegram смену privacy-режима не применит. Альтернатива — сделать бота админом группы.
Второй слой — requireMention: true, дефолт: бот отвечает только на упоминание. Это поведение по конфигу, а не поломка; хочешь реакции на всё подряд — меняй requireMention для конкретной группы и понимай, что делаешь.
Третий слой — снова два ID: группа ключом под channels.telegram.groups, отправители numeric-ID в groupAllowFrom, и -100… — не user ID.
`getMe returned 401`
Самая честная из ошибок: Telegram отверг токен. Не сеть, не polling, не политика доступа. Токен обрезался при копировании или отозван. Лечение одно: перекопировать или пересоздать токен у BotFather и обновить его там, где он у тебя задан, — botToken, tokenFile или TELEGRAM_BOT_TOKEN, — затем рестарт.
Здесь же прод-урок, который стоил мне времени. Токен и конфиг применяются рестартом сервиса, а не сохранением файла. «Я же поправил токен» — поправил на диске; gateway продолжает жить со старым, пока его не перезапустили. Файл правильный, процесс вчерашний. Выглядит как мистика, лечится рестартом.
Polling рвётся: сеть, 409, watchdog
Режим по умолчанию — long polling: gateway сам ходит к api.telegram.org, входящий порт не нужен, публичный адрес не нужен. Webhook опционален (webhookUrl/webhookSecret, локальный листенер 127.0.0.1:8787) — большинству установок он не требуется.
Отсюда неудобный вывод: устойчивость Telegram-канала — это устойчивость egress твоего хоста. Когда polling рвётся и реконнектится, «модель тупит» тут ни при чём — разбираться надо с сетью между машиной и api.telegram.org. Реконнект-ретраи в канале есть, но они смягчают симптом; корень остаётся в сети.
Чек-лист в том порядке, в каком ловлю сам:
- `getUpdates` 409 conflict. На токене висит второй поллер: другой gateway, скрипт, забытая копия после переезда. Внутри одного gateway поллер на токен — один, а 409 — честный ответ Telegram, что апдейты этим токеном читает кто-то ещё. «Мигающий» после переезда инстанса бот — в моей практике это всегда он.
- DNS/IPv6. Быстрая проверка:
dig +short api.telegram.org A/AAAA. На Node 22+ вмешивается autoSelectFamily; лечитсяOPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4firstлибоchannels.telegram.network.autoSelectFamily: false. - Нестабильный egress на VPS. Прокси:
channels.telegram.proxy: socks5://…; стандартныеHTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXYтоже учитываются. Как вообще поднять и закрыть этот VPS — отдельный гайд. - apiRoot-грабля.
getMe/setMyCommandsотдают 404, а прямой curl к Bot API работает — значит,apiRootуказывает на полный/bot<TOKEN>-эндпоинт, а должен быть только корень Bot API.doctor --fixсрезает хвост/bot<TOKEN>сам.
Про watchdog. Если за 120 секунд (дефолт) не завершился ни один getUpdates, polling перезапускается сам. Порог pollingStallThresholdMs крутится в диапазоне 30000–600000, но только при явно ложных срабатываниях. Устойчивый stall тюнингом порога не лечится — это глушение пожарной сигнализации; корень ищи в proxy/DNS/IPv6.
И экзотика напоследок: Telegram отклонил setMyCommands с BOT_COMMANDS_TOO_MUCH — набралось слишком много plugin/skill/custom-команд. Урезай список или отключай native-меню.
Диагностическая лесенка
Когда непонятно, откуда заходить, я иду сверху вниз, от рантайма к каналу:
openclaw status
openclaw gateway status
openclaw logs --follow
openclaw doctor
openclaw channels status --probeЗдоровый бейзлайн: Runtime: running, Connectivity probe: ok, у Telegram-канала проба показывает подключённый transport. Любое отклонение — уже зацепка: не поднялся рантайм, нет связности, канал не загрузился. logs --follow держи открытым, пока пишешь боту: там виден и from.id отправителя, и причина, по которой сообщение не прошло. Классика — /start без ответа: почти всегда это висящий пейринг (openclaw pairing list telegram покажет) или слишком строгая DM-политика.
Когда OpenClaw не виноват
Раздел, которого в выдаче не хватает. Не всё из перечисленного — грехи OpenClaw, и валить всё на рантайм — верный способ дебажить неделю не в ту сторону.
- Privacy Mode — сторона Telegram. Бот не видит сообщения группы, потому что Telegram их по умолчанию не отдаёт. Чинится через BotFather и переприглашение бота; конфиг OpenClaw ни при чём.
- Egress — сторона хоста. DNS, IPv6, кривой прокси уронят любой софт, который ходит к
api.telegram.orgс этой машины. OpenClaw просто первый, на ком это заметно. - Второй поллер — рукотворное. 409 — не поломка канала, а сигнал, что этим токеном уже читает апдейты кто-то ещё. Обычно — твой же забытый инстанс.
Если возиться не хочется
Всё выше — обычная операторская работа: разложить ID, одобрить пейринг, последить за egress, прогнать doctor после апдейта. Она несложная, но она не кончается. Если хочется, чтобы Telegram-канал просто был, — на это есть Cain: он держит OpenClaw на выделенном под клиента сервере, один клиент на сервер, и Telegram там привязывается из панели Assistant Control одной кнопкой: без ручного конфига, кодов пейринга и охоты за numeric ID. Запросы при этом уходят напрямую тому провайдеру модели, которому ты и так платишь, а не через чьё-то общее облако. Это один из вариантов, не единственно правильный: всё то же самое делается руками по шагам выше.
Частые вопросы
Как подключить OpenClaw к Telegram? Создать бота у @BotFather командой /newbot, положить токен в channels.telegram.botToken (или в TELEGRAM_BOT_TOKEN), задать dmPolicy, запустить openclaw gateway, затем одобрить свой первый DM: openclaw pairing approve telegram <CODE>. Через openclaw channels login telegram Telegram не подключается — доки говорят это прямым текстом.
OpenClaw Telegram-бот перестал работать после обновления — что делать? По порядку: openclaw status --all → openclaw doctor --fix → openclaw gateway restart. Частая причина — plugin load failed: dependency tree corrupted в выводе статуса: doctor --fix чистит битый plugin-staging, рестарт перегружает канал начисто.
Какая команда пейринга Telegram в OpenClaw? openclaw pairing list telegram — посмотреть ожидающие запросы, openclaw pairing approve telegram <CODE> — одобрить. Коды живут 1 час. Это не channels login.
Бот онлайн, но не отвечает в группе. Почему? Чаще всего это Telegram privacy mode: у BotFather /setprivacy → Disable, потом удалить бота из группы и добавить заново (или сделать бота админом). При requireMention бот ждёт упоминания. И проверь, что группа задана ключом в channels.telegram.groups, а твой numeric ID — в groupAllowFrom.
Что значит `getMe returned 401`? Telegram отверг токен бота. Перекопировать или пересоздать токен у BotFather, обновить botToken/tokenFile/TELEGRAM_BOT_TOKEN и перезапустить gateway: токен перечитывается рестартом, а не сохранением файла.
Polling постоянно рвётся или реконнектит. Куда смотреть? Обычно это egress хоста: DNS/IPv6/прокси до api.telegram.org. Проверка — dig +short api.telegram.org A/AAAA; лечение — ipv4first или channels.telegram.proxy. getUpdates 409 — второй поллер на том же токене. Ложные рестарты watchdog — тюнить pollingStallThresholdMs (30000–600000).
Нужен ли публичный сервер или webhook, чтобы OpenClaw работал в Telegram? Нет. Режим по умолчанию — long polling: gateway сам опрашивает Telegram, входящий порт не нужен. Webhook опционален (webhookUrl/webhookSecret) и большинству установок не требуется.
Илья Прудников держит приватные инстансы OpenClaw и Hermes. Это заметки оператора про Telegram-канал в проде, а не документация проекта; точные команды, ключи конфига и дефолты сверяй по свежим докам OpenClaw.

