15 KiB
name, description, version, author, license, platforms, metadata, related_skills
| name | description | version | author | license | platforms | metadata | related_skills | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hermes-telegram | Configure, troubleshoot, and manage Telegram integration for Hermes Agent — bot setup, .env configuration, gateway restart, and common failure modes. | 1.0.0 | Hermes Agent | MIT |
|
|
|
Hermes Telegram Integration
Configure the Hermes Agent gateway to send and receive messages on Telegram. Covers bot creation, .env setup, allowed users, home channel, gateway restart, and troubleshooting.
Prerequisites
- Hermes Agent gateway installed and running (
hermes gateway statusorps aux | grep 'hermes gateway run') - A Telegram account to create and manage the bot
Setup Steps
1. Create a Bot on Telegram
Message @BotFather on Telegram:
/newbot
Follow the prompts to choose a name and username. BotFather will return a bot token like:
8971430276:AAFu...Amq4
Save this token — you'll need it in the next step.
2. Find Your Numeric IDs
You need numeric Telegram IDs, not usernames. Message @userinfobot on Telegram — it will reply with:
- Your user ID (a number like
123456789) — used forTELEGRAM_ALLOWED_USERS - For groups/channels: add the bot to the group, send a message, then use @userinfobot in the group to get the chat ID
Note: TELEGRAM_ALLOWED_USERS and TELEGRAM_HOME_CHANNEL require numeric IDs, not @username strings.
3. Configure .env
Edit the .env file. The default template has all Telegram variables commented out — you must uncomment and fill them in:
hermes config env-path # prints the path (typically ~/.hermes/.env)
The relevant lines (find them under the # TELEGRAM INTEGRATION section):
TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_ALLOWED_USERS=123456789 # Comma-separated numeric user IDs
TELEGRAM_HOME_CHANNEL=123456789 # Numeric chat ID for cron deliveries
TELEGRAM_HOME_CHANNEL_NAME=@yourusername # Display name (optional, username is fine here)
Important: The default template uses a combined single-line format:
# TELEGRAM_BOT_TOKEN=*** TELEGRAM_ALLOWED_USERS=
When uncommenting, split this into separate lines as shown above — one variable per line. Use your editor or sed to do it cleanly.
For the HOME_CHANNEL, if you only want DM delivery (bot messages you directly), set it to your own user ID — same as ALLOWED_USERS.
4. Restart the Gateway
Configuration changes in .env are read at startup. Restart the gateway to pick them up:
hermes gateway restart
Or if running as a systemd user service:
systemctl --user restart hermes-gateway
Manual Restart (no systemd service)
If systemctl --user list-units --type=service --all | grep hermes returns nothing, the gateway was started manually. Kill and restart it:
# Find the gateway PID
ps aux | grep 'hermes gateway run'
# Kill it (use -9 if plain kill won't work)
kill -9 <PID>
# Wait for it to die
sleep 2
# Start fresh — MUST use background=true (nohup/disown is blocked by tool policy)
# In the Hermes CLI session:
# terminal(background=true, notify_on_complete=true, command="hermes gateway run")
Important: Do not use nohup, disown, or trailing & in a foreground terminal() call — the tool policy blocks shell-level background wrappers. Always use terminal(background=true) so Hermes tracks the process.
5. Verify It's Working
Send a message to your bot on Telegram. It should respond. Check the gateway logs for confirmation:
grep -i telegram ~/.hermes/logs/gateway.log | tail -20
Look for these lines to confirm a successful connection:
Connecting to telegram...
[Telegram] Auto-discovered Telegram fallback IPs: 149.154.166.110
[Telegram] set_my_commands OK for scope BotCommandScopeDefault (30 cmds)
[Telegram] Connected to Telegram (polling mode)
✓ telegram connected
If you see Connected to Telegram (polling mode) and ✓ telegram connected, the bot is live.
For a full reference of restart commands, log signatures, curl test-message patterns, and sed snippets, see references/gateway-restart-and-test.md.
Sending a Test Message from the CLI
The Hermes send_message tool only works in sessions initiated from a messaging platform (Telegram, Discord, etc.). In a CLI session, it returns "No messaging platforms connected" even when the gateway has Telegram active.
Workaround — use the Telegram Bot API directly via curl:
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=Hello from Hermes! 👋"
The ${TELEGRAM_BOT_TOKEN} is the value set in .env and ${CHAT_ID} is the numeric user/chat ID. This sends a message bypassing the Hermes gateway — useful for testing or one-off notifications from the CLI.
Gateway Check
To see if the gateway is running before troubleshooting:
ps aux | grep 'hermes gateway run'
Key Configuration Variables
| Variable | Required | Description |
|---|---|---|
TELEGRAM_BOT_TOKEN |
Yes | Bot token from @BotFather |
TELEGRAM_ALLOWED_USERS |
Recommended | Comma-separated numeric user IDs allowed to chat. Leave empty to allow anyone (not recommended for production). |
TELEGRAM_HOME_CHANNEL |
For cron | Default chat ID for cron job deliveries |
TELEGRAM_HOME_CHANNEL_NAME |
No | Display name for the home channel |
TELEGRAM_CRON_THREAD_ID |
No | Forum topic ID for cron deliveries in topic-mode groups |
Long-Running Tasks & Blocking Behavior
The gateway processes one turn at a time per session. While the agent is inside a turn (thinking, running tools, waiting for a terminal command), it cannot receive or process new messages from you. Telegram shows "typing..." the entire time.
Why the bot blocks
| Phase | What's happening | Can you message? |
|---|---|---|
🔄 Agent calls a tool (e.g. terminal()) |
Blocks waiting for result | ❌ Queued |
| 🤖 Agent calls the LLM again with tool output | Generating next action | ❌ Queued |
| 📨 Agent sends you a progress update | Brief mid-turn message | ❌ Still in same turn |
| ✅ Agent sends final response and ends turn | Done | ✅ Next message processed |
"Typing..." = active LLM calls = cost
Every iteration of the agent loop makes a new API call to your LLM provider. While the bot shows "typing...", it is actively making LLM calls — you are being charged for input + output tokens each round. Input tokens grow each iteration as tool results are appended to the conversation context.
How to avoid blocking the bot
Three approaches, in order of preference:
| Approach | How | Best for |
|---|---|---|
| ⏰ Cron job | cronjob(action='create', schedule='...', prompt='run my script', no_agent=True) — script runs independently, stdout delivered verbatim to Telegram |
Standalone scripts that run on a schedule or fire-and-forget |
| 🏃 Background terminal | terminal(command='python long_script.py', background=true, notify_on_complete=true) — agent returns immediately, pings you when done |
One-off long scripts the user triggers |
| 📋 /queue | In CLI: /queue <prompt> — queues work for after current turn ends |
Quick follow-ups during an active session |
The cron approach is cleanest: the bot never blocks, and no_agent=True means zero LLM calls during execution — the script's stdout is delivered verbatim.
Verifying the bot is stuck mid-turn
Check the gateway logs for the last activity:
tail -20 ~/.hermes/logs/gateway.log
Look for:
inbound message: ... msg='your prompt'— last message receivedFlushing text batch ... (N chars)— last update sent (but turn not over)- No new
inbound messageentries — session is blocked, new messages are queued
Pitfalls
- Usernames are not IDs.
TELEGRAM_ALLOWED_USERSandTELEGRAM_HOME_CHANNELneed numeric Telegram IDs, not@usernamestrings. Use @userinfobot to get them. - All vars start commented out. The
.envtemplate ships with#prefix on every Telegram line. You must uncomment them. - Multi-variable line trap. The default
.envtemplate writesTELEGRAM_BOT_TOKENandTELEGRAM_ALLOWED_USERSon the same line:# TELEGRAM_BOT_TOKEN=*** TELEGRAM_ALLOWED_USERS=. This is NOT valid env format with the token value — split into two separate lines when configuring. - Gateway restart required.
.envis read at process startup. Simply runninghermesin a new CLI session does not reload the gateway's env vars. Usehermes gateway restart(orsystemctl --user restart hermes-gateway) every time you changeTELEGRAM_*variables. - Config schema warnings can block clean startup. If gateway status/logs show
custom_providers is a dict — it must be a YAML list, fix it in~/.hermes/config.yamlby makingcustom_providersa list (or clear it withhermes config set custom_providers "[]"), then restart the gateway. - Token secrecy. The bot token is a secret — anyone with it can control your bot. Keep it out of version control and shell history.
- Gateway API server must be running. The gateway also starts the API server (typically port 8642). If tools or web UI can't reach the agent, the root cause is often a stopped gateway, not Telegram itself.
- send_message tool is CLI-blind to Telegram. From a CLI session,
send_message(action=list)returnsNo messaging platforms connectedeven when the gateway has Telegram active. This is by design — the tool only routes through gateway-originated sessions. Use the Telegram Bot API directly via curl to send messages from CLI sessions (see the Verification section for the exact curl command).
Bot Commands: Registration & Limits
The gateway auto-registers bot commands from hermes_cli.commands.telegram_bot_commands() on startup. Commands come from three sources: built-in CommandDef entries, plugin slash commands, and skill entries. Gateway caps the command list at MAX_COMMANDS_PER_SCOPE = 30 (telegram.py:108) to stay under Telegram's undocumented ~4KB payload limit.
Adding a custom command persistently:
- Edit
~/.hermes/hermes-agent/hermes_cli/commands.py-- add your (name, description) pair at the end oftelegram_bot_commands():result.append(("imagine", "Generate an image from a text prompt")) - Add the command to
_TELEGRAM_MENU_PRIORITYif the cap is tight -- commands outside the priority list get trimmed first. - If you go over 30 commands, raise
MAX_COMMANDS_PER_SCOPEintelegram.py. - Restart the gateway to pick up changes.
Without these three changes, custom commands get overwritten on gateway restart or silently truncated at the 30-command cap.
Troubleshooting
Diagnostic Flow: Bot Not Responding
Start with a status check first — it's the fastest way to narrow the cause.
hermes gateway status # Primary check
If that's unavailable, fall back to:
ps aux | grep 'hermes gateway run' # Second — gateway process exists?
systemctl --user status hermes-gateway 2>/dev/null # Third — systemd service?
Branch A: Gateway is not running
The most common cause of "stopped working" is the gateway having been shut down. Check the logs to find out why:
grep -i "telegram\|error\|fail\|warn\|sigterm\|sigkill\|oom" ~/.hermes/logs/gateway.log | tail -20
Common shutdown signatures in the logs:
| Log pattern | Likely cause | Action |
|---|---|---|
WARNING ... Shutdown context: signal=SIGTERM under_systemd=yes parent_pid=1 |
systemd sent SIGTERM (user logout, reboot, service stop) | Restart gateway or install as permanent service |
ERROR ... signal=SIGKILL |
OOM killer or forced kill | Check memory pressure, `dmesg |
ERROR ... Traceback (most recent call last) |
Crash / unhandled exception | Read the traceback, fix the root cause |
| Logs end abruptly with no shutdown message | Process was killed externally (shell session closed, SSH disconnect) | Restart gateway |
| No Telegram-related log entries at all | Telegram may not be configured or enabled in config | Check .env for TELEGRAM_* vars, check config.yaml → telegram section |
If the log shows the gateway was working fine then received SIGTERM, the fix is straightforward — restart it:
hermes gateway run # foreground (session-dependent)
hermes gateway install # as permanent systemd user service (auto-restarts)
If no systemd service exists (systemctl --user list-units --type=service --all | grep hermes returns empty), the gateway was started manually and won't survive a logout/reboot without the service.
Branch B: Gateway is running but not responding
grep -i telegram ~/.hermes/logs/gateway.log | tail -30
Look for:
[Telegram] Connected to Telegram (polling mode)— connection was establishedinbound message: platform=telegram user=...— messages are being receivedSending response (... chars) to 1498679692— responses are being sentERRORorWARNINGentries — something went wrong
If messages arrive but responses fail, check:
TELEGRAM_BOT_TOKENis correct and uncommented in.env- The bot hasn't been blocked by Telegram (try sending a test from a different bot)
- Network/firewall: Telegram polling needs outbound connectivity to
api.telegram.org
Branch C: Never worked (first-time setup)
If the user says the bot never responded:
- Follow the full Setup Steps section above
- Check that
TELEGRAM_BOT_TOKENis on its own line (not merged with another var) - Verify with
curldirectly:curl -s "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getMe"— should return{"ok":true,"result":{"id":...,"is_bot":true,"first_name":"...","username":"..."}} - Check
TELEGRAM_ALLOWED_USERS— without it, the bot defaults to allowing everyone; if it's set to the wrong numeric ID, the bot ignores your messages - After fixing, restart the gateway
- Wait 5-10 seconds, then send a message to the bot on Telegram
Symptom: "Bot responds to everyone / ignores me"
Check TELEGRAM_ALLOWED_USERS is set to your numeric user ID. Without this, the bot is open to anyone who finds it.
Symptom: "Cron messages don't arrive on Telegram"
- Ensure
TELEGRAM_HOME_CHANNELis set to the correct numeric chat ID - The home channel is where cron delivers by default — if you DM'd the bot manually but set the home channel to a group, cron goes to the group, not your DMs
Symptom: "send_message tool says 'No messaging platforms connected' from CLI"
This is expected behavior — the send_message tool only routes through a session that was initiated from that platform. From a CLI session, it cannot discover Telegram even if the gateway has it connected.
Workaround: Call the Telegram Bot API directly:
curl -s -X POST "https://api.telegram.org/bot${TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=Your message"
Symptom: "Can't restart — no systemd service found"
If systemctl --user list-units shows no hermes service, the gateway was started manually (e.g., via hermes gateway run in a background terminal). See the Manual Restart (no systemd service) section in step 4 above.