- Trading skills (OKX, dividend, lottery, quantitative) - Creative skills (ASCII art, diagrams, video) - Development skills (GitHub, debugging, TDD) - Research skills (arXiv, blog monitoring) - Productivity skills (email, documents, notes) - MCP integration skills - Custom user skills
5.5 KiB
Telegram Adapter Diagnostics
Quick Health Check
# 1. Is the adapter connected?
journalctl --user -u hermes-gateway --since '10 min ago' --no-pager | grep -i "telegram" | tail -5
# 2. Is the proxy working?
curl -s -o /dev/null -w "%{http_code}" --proxy http://127.0.0.1:7890 https://api.telegram.org
# 3. Is the bot alive?
# (replace TOKEN with actual bot token from ~/.hermes/.env)
curl -s "https://api.telegram.org/bot<TOKEN>/getMe" --proxy http://127.0.0.1:7890
# 4. Is the bot in the target group?
curl -s "https://api.telegram.org/bot<TOKEN>/getChatMember?chat_id=<GROUP_ID>&user_id=<BOT_ID>" --proxy http://127.0.0.1:7890
Diagnosing "Bot Not Processing Group Messages"
Step 1: Check if adapter is alive
journalctl --user -u hermes-gateway --no-pager --since '1 hour ago' | grep "\[Telegram\]" | tail -10
- If only crash/reconnect-failed logs → adapter is dead, restart gateway
- If "Reconnecting telegram" entries → watcher is alive, proxy may be down
- If no Telegram logs at all → either adapter connected silently or watcher died
Step 2: Check if proxy is the issue
curl -s -o /dev/null -w "%{http_code}" --proxy http://127.0.0.1:7890 https://api.telegram.org
# 302 = proxy working, timeout/ConnectError = proxy down
Step 3: Check bot group membership
# Get bot info
python3 -c "
import json, urllib.request
with open('/home/openclaw/.hermes/.env') as f:
token = [l.split('=',1)[1].strip() for l in f if l.startswith('TELEGRAM_BOT_TOKEN')][0]
proxy = urllib.request.ProxyHandler({'https': 'http://127.0.0.1:7890'})
opener = urllib.request.build_opener(proxy)
resp = opener.open(f'https://api.telegram.org/bot{token}/getChatMember?chat_id=<GROUP_ID>&user_id=<BOT_ID>')
print(json.loads(resp.read()))
"
Step 4: Check config
In ~/.hermes/config.yaml, under telegram::
free_response_chatsorfree_response_channelsmust include the group IDchannel_promptscan be set per group for custom behaviorallowed_chatswhen set acts as a whitelist (empty = no restriction)require_mention: truemeans bot only responds when @mentioned (unless infree_response_chats)
Editing channel_prompts: Values are unicode-escaped with YAML line continuations (\ at line end). Don't use patch() — it breaks on multi-line unicode. Use Python regex instead:
import re
with open('/home/openclaw/.hermes/config.yaml') as f:
content = f.read()
# Match across line breaks with [\s\\]* for YAML continuations
pattern = re.compile(r'\\uXXXX[\s\\]*\\uYYYY')
content = pattern.sub(r'\\uNEW1\\uNEW2', content)
with open('/home/openclaw/.hermes/config.yaml', 'w') as f:
f.write(content)
# Always verify YAML validity after
import yaml; yaml.safe_load(open('/home/openclaw/.hermes/config.yaml'))
The same prompt string is duplicated across slack, discord, mattermost, and telegram sections — replace in all 4.
Step 5: Check forwarder
# Is the forwarder running?
docker ps | grep forwarder
# Check forwarder config
sqlite3 ~/TelegramForwarder/db/forward.db "SELECT * FROM chats;"
sqlite3 ~/TelegramForwarder/db/forward.db "SELECT * FROM forward_rules;"
sqlite3 ~/TelegramForwarder/db/forward.db "SELECT * FROM keywords;"
# Check recent forwarding activity
docker logs telegram-forwarder --tail 20 | grep "已发送"
Gateway Restart Constraints
- Cannot restart from inside the gateway:
hermes gateway restartis blocked when run from a gateway session (SIGTERM propagation prevention) kill <PID>also blocked: Security scanner interceptskillcommands targeting the gateway PID. Terminal returnsBlocked: cannot restart or stop the gateway from inside the gateway process.- Workaround 1: User runs
hermes gateway restartfrom a separate SSH shell (recommended) - Workaround 2:
systemctl --user restart hermes-gatewayfrom a separate shell - Workaround 3: Write a small helper script to
/tmp/and ask user to run it manually
Reconnect Watcher Architecture
When a platform adapter hits a fatal error:
_set_fatal_error()→ setsadapter._running = False_handle_adapter_fatal_error()→ disconnects adapter, removes fromself.adapters- If
fatal_error_retryable=True→ adds toself._failed_platformswith backoff _platform_reconnect_watcher()→ background asyncio task, retries with exponential backoff (30s→300s cap)
Known bug: The watcher task can silently die. No upstream fix yet. Workaround: external gateway restart.
Root cause (observed 2026-06-23): When multiple platforms crash simultaneously (Telegram + WeChat + QQBot), the watcher may die. Evidence: journalctl shows the fatal error at 09:27 but ZERO "Reconnecting telegram" or "Reconnect telegram error" entries afterward — the watcher's while self._running loop exited without logging. On a previous crash (2026-06-22) with only Telegram affected, the watcher worked correctly and kept retrying with backoff.
Edge case — already-queued platform: _handle_adapter_fatal_error() checks adapter.platform not in self._failed_platforms before queueing. If Telegram was already in the queue from a prior failure, the new fatal error doesn't re-queue or reset the backoff. The existing entry's next_retry timer may be at the 300s cap, causing long silent gaps between reconnection attempts even when the watcher IS alive.
Definitive diagnosis: If after a crash you see zero reconnection attempt logs for >10 minutes, the watcher is dead. Restart the gateway from an external shell.