Reference docs fixes: - cli-commands.md: remove non-existent --provider alibaba, add hermes profile/completion/plugins/mcp to top-level table, add --profile/-p global flag, add --source chat option - slash-commands.md: add /yolo and /commands, fix /q alias conflict (resolves to /queue not /quit), add missing aliases (/bg, /set-home, /reload_mcp, /gateway) - toolsets-reference.md: fix hermes-api-server (not same as hermes-cli, omits clarify/send_message/text_to_speech) - profile-commands.md: fix show name required not optional, --clone-from not --from, add --remove/--name to alias, fix alias path, fix export/ import arg types, remove non-existent fish completion - tools-reference.md: add EXA_API_KEY to web tools requires_env - mcp-config-reference.md: add auth key for OAuth, tool name sanitization - environment-variables.md: add EXA_API_KEY, update provider values - plugins.md: remove non-existent ctx.register_command(), add ctx.inject_message() Feature docs additions: - security.md: add /yolo mode, approval modes (manual/smart/off), configurable timeout, expanded dangerous patterns table - cron.md: add wrap_response config, [SILENT] suppression - mcp.md: add dynamic tool discovery, MCP sampling support - cli.md: add Ctrl+Z suspend, busy_input_mode, tool_preview_length - docker.md: add skills/credential file mounting Messaging platform docs: - telegram.md: add webhook mode, DoH fallback IPs - slack.md: add multi-workspace OAuth support - discord.md: add DISCORD_IGNORE_NO_MENTION - matrix.md: add MSC3245 native voice messages - feishu.md: expand from 129 to 365 lines (encrypt key, verification token, group policy, card actions, media, rate limiting, markdown, troubleshooting) - wecom.md: expand from 86 to 264 lines (per-group allowlists, media, AES decryption, stream replies, reconnection, troubleshooting) Configuration docs: - quickstart.md: add DeepSeek, Copilot, Copilot ACP providers - configuration.md: add DeepSeek provider, Exa web backend, terminal env_passthrough/images, browser.command_timeout, compression params, discord config, security/tirith config, timezone, auxiliary models 21 files changed, ~1000 lines added
14 KiB
sidebar_position, title, description
| sidebar_position | title | description |
|---|---|---|
| 1 | Telegram | Set up Hermes Agent as a Telegram bot |
Telegram Setup
Hermes Agent integrates with Telegram as a full-featured conversational bot. Once connected, you can chat with your agent from any device, send voice memos that get auto-transcribed, receive scheduled task results, and use the agent in group chats. The integration is built on python-telegram-bot and supports text, voice, images, and file attachments.
Step 1: Create a Bot via BotFather
Every Telegram bot requires an API token issued by @BotFather, Telegram's official bot management tool.
- Open Telegram and search for @BotFather, or visit t.me/BotFather
- Send
/newbot - Choose a display name (e.g., "Hermes Agent") — this can be anything
- Choose a username — this must be unique and end in
bot(e.g.,my_hermes_bot) - BotFather replies with your API token. It looks like this:
123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
:::warning
Keep your bot token secret. Anyone with this token can control your bot. If it leaks, revoke it immediately via /revoke in BotFather.
:::
Step 2: Customize Your Bot (Optional)
These BotFather commands improve the user experience. Message @BotFather and use:
| Command | Purpose |
|---|---|
/setdescription |
The "What can this bot do?" text shown before a user starts chatting |
/setabouttext |
Short text on the bot's profile page |
/setuserpic |
Upload an avatar for your bot |
/setcommands |
Define the command menu (the / button in chat) |
/setprivacy |
Control whether the bot sees all group messages (see Step 3) |
:::tip
For /setcommands, a useful starting set:
help - Show help information
new - Start a new conversation
sethome - Set this chat as the home channel
:::
Step 3: Privacy Mode (Critical for Groups)
Telegram bots have a privacy mode that is enabled by default. This is the single most common source of confusion when using bots in groups.
With privacy mode ON, your bot can only see:
- Messages that start with a
/command - Replies directly to the bot's own messages
- Service messages (member joins/leaves, pinned messages, etc.)
- Messages in channels where the bot is an admin
With privacy mode OFF, the bot receives every message in the group.
How to disable privacy mode
- Message @BotFather
- Send
/mybots - Select your bot
- Go to Bot Settings → Group Privacy → Turn off
:::warning You must remove and re-add the bot to any group after changing the privacy setting. Telegram caches the privacy state when a bot joins a group, and it will not update until the bot is removed and re-added. :::
:::tip An alternative to disabling privacy mode: promote the bot to group admin. Admin bots always receive all messages regardless of the privacy setting, and this avoids needing to toggle the global privacy mode. :::
Step 4: Find Your User ID
Hermes Agent uses numeric Telegram user IDs to control access. Your user ID is not your username — it's a number like 123456789.
Method 1 (recommended): Message @userinfobot — it instantly replies with your user ID.
Method 2: Message @get_id_bot — another reliable option.
Save this number; you'll need it for the next step.
Step 5: Configure Hermes
Option A: Interactive Setup (Recommended)
hermes gateway setup
Select Telegram when prompted. The wizard asks for your bot token and allowed user IDs, then writes the configuration for you.
Option B: Manual Configuration
Add the following to ~/.hermes/.env:
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
TELEGRAM_ALLOWED_USERS=123456789 # Comma-separated for multiple users
Start the Gateway
hermes gateway
The bot should come online within seconds. Send it a message on Telegram to verify.
Home Channel
Use the /sethome command in any Telegram chat (DM or group) to designate it as the home channel. Scheduled tasks (cron jobs) deliver their results to this channel.
You can also set it manually in ~/.hermes/.env:
TELEGRAM_HOME_CHANNEL=-1001234567890
TELEGRAM_HOME_CHANNEL_NAME="My Notes"
:::tip
Group chat IDs are negative numbers (e.g., -1001234567890). Your personal DM chat ID is the same as your user ID.
:::
Voice Messages
Incoming Voice (Speech-to-Text)
Voice messages you send on Telegram are automatically transcribed by Hermes's configured STT provider and injected as text into the conversation.
localusesfaster-whisperon the machine running Hermes — no API key requiredgroquses Groq Whisper and requiresGROQ_API_KEYopenaiuses OpenAI Whisper and requiresVOICE_TOOLS_OPENAI_KEY
Outgoing Voice (Text-to-Speech)
When the agent generates audio via TTS, it's delivered as native Telegram voice bubbles — the round, inline-playable kind.
- OpenAI and ElevenLabs produce Opus natively — no extra setup needed
- Edge TTS (the default free provider) outputs MP3 and requires ffmpeg to convert to Opus:
# Ubuntu/Debian
sudo apt install ffmpeg
# macOS
brew install ffmpeg
Without ffmpeg, Edge TTS audio is sent as a regular audio file (still playable, but uses the rectangular player instead of a voice bubble).
Configure the TTS provider in your config.yaml under the tts.provider key.
Group Chat Usage
Hermes Agent works in Telegram group chats with a few considerations:
- Privacy mode determines what messages the bot can see (see Step 3)
TELEGRAM_ALLOWED_USERSstill applies — only authorized users can trigger the bot, even in groups- You can keep the bot from responding to ordinary group chatter with
telegram.require_mention: true - With
telegram.require_mention: true, group messages are accepted when they are:- slash commands
- replies to one of the bot's messages
@botusernamementions- matches for one of your configured regex wake words in
telegram.mention_patterns
- If
telegram.require_mentionis left unset or false, Hermes keeps the previous open-group behavior and responds to normal group messages it can see
Example group trigger configuration
Add this to ~/.hermes/config.yaml:
telegram:
require_mention: true
mention_patterns:
- "^\\s*chompy\\b"
This example allows all the usual direct triggers plus messages that begin with chompy, even if they do not use an @mention.
Notes on mention_patterns
- Patterns use Python regular expressions
- Matching is case-insensitive
- Patterns are checked against both text messages and media captions
- Invalid regex patterns are ignored with a warning in the gateway logs rather than crashing the bot
- If you want a pattern to match only at the start of a message, anchor it with
^
Private Chat Topics (Bot API 9.4)
Telegram Bot API 9.4 (February 2026) introduced Private Chat Topics — bots can create forum-style topic threads directly in 1-on-1 DM chats, no supergroup needed. This lets you run multiple isolated workspaces within your existing DM with Hermes.
Use case
If you work on several long-running projects, topics keep their context separate:
- Topic "Website" — work on your production web service
- Topic "Research" — literature review and paper exploration
- Topic "General" — miscellaneous tasks and quick questions
Each topic gets its own conversation session, history, and context — completely isolated from the others.
Configuration
Add topics under platforms.telegram.extra.dm_topics in ~/.hermes/config.yaml:
platforms:
telegram:
extra:
dm_topics:
- chat_id: 123456789 # Your Telegram user ID
topics:
- name: General
icon_color: 7322096
- name: Website
icon_color: 9367192
- name: Research
icon_color: 16766590
skill: arxiv # Auto-load a skill in this topic
Fields:
| Field | Required | Description |
|---|---|---|
name |
Yes | Topic display name |
icon_color |
No | Telegram icon color code (integer) |
icon_custom_emoji_id |
No | Custom emoji ID for the topic icon |
skill |
No | Skill to auto-load on new sessions in this topic |
thread_id |
No | Auto-populated after topic creation — don't set manually |
How it works
- On gateway startup, Hermes calls
createForumTopicfor each topic that doesn't have athread_idyet - The
thread_idis saved back toconfig.yamlautomatically — subsequent restarts skip the API call - Each topic maps to an isolated session key:
agent:main:telegram:dm:{chat_id}:{thread_id} - Messages in each topic have their own conversation history, memory flush, and context window
Skill binding
Topics with a skill field automatically load that skill when a new session starts in the topic. This works exactly like typing /skill-name at the start of a conversation — the skill content is injected into the first message, and subsequent messages see it in the conversation history.
For example, a topic with skill: arxiv will have the arxiv skill pre-loaded whenever its session resets (due to idle timeout, daily reset, or manual /reset).
:::tip
Topics created outside of the config (e.g., by manually calling the Telegram API) are discovered automatically when a forum_topic_created service message arrives. You can also add topics to the config while the gateway is running — they'll be picked up on the next cache miss.
:::
Recent Bot API Features
- Bot API 9.4 (Feb 2026): Private Chat Topics — bots can create forum topics in 1-on-1 DM chats via
createForumTopic. See Private Chat Topics above. - Privacy policy: Telegram now requires bots to have a privacy policy. Set one via BotFather with
/setprivacy_policy, or Telegram may auto-generate a placeholder. This is particularly important if your bot is public-facing. - Message streaming: Bot API 9.x added support for streaming long responses, which can improve perceived latency for lengthy agent replies.
Webhook Mode
By default, the Telegram adapter connects via long polling — the gateway makes outbound connections to Telegram's servers. This works everywhere but keeps a persistent connection open.
Webhook mode is an alternative where Telegram pushes updates to your server over HTTPS. This is ideal for serverless and cloud deployments (Fly.io, Railway, etc.) where inbound HTTP can wake a suspended machine.
Configuration
Set the TELEGRAM_WEBHOOK_URL environment variable to enable webhook mode:
# Required — your public HTTPS endpoint
TELEGRAM_WEBHOOK_URL=https://app.fly.dev/telegram
# Optional — local listen port (default: 8443)
TELEGRAM_WEBHOOK_PORT=8443
# Optional — secret token for update verification (auto-generated if not set)
TELEGRAM_WEBHOOK_SECRET=my-secret-token
Or in ~/.hermes/config.yaml:
telegram:
webhook_mode: true
When TELEGRAM_WEBHOOK_URL is set, the gateway starts an HTTP server listening on 0.0.0.0:<port> and registers the webhook URL with Telegram. The URL path is extracted from the webhook URL (defaults to /telegram).
:::warning Telegram requires a valid TLS certificate on the webhook endpoint. Self-signed certificates will be rejected. Use a reverse proxy (nginx, Caddy) or a platform that provides TLS termination (Fly.io, Railway, Cloudflare Tunnel). :::
DNS-over-HTTPS Fallback IPs
In some restricted networks, api.telegram.org may resolve to an IP that is unreachable. The Telegram adapter includes a fallback IP mechanism that transparently retries connections against alternative IPs while preserving the correct TLS hostname and SNI.
How it works
- If
TELEGRAM_FALLBACK_IPSis set, those IPs are used directly. - Otherwise, the adapter automatically queries Google DNS and Cloudflare DNS via DNS-over-HTTPS (DoH) to discover alternative IPs for
api.telegram.org. - IPs returned by DoH that differ from the system DNS result are used as fallbacks.
- If DoH is also blocked, a hardcoded seed IP (
149.154.167.220) is used as a last resort. - Once a fallback IP succeeds, it becomes "sticky" — subsequent requests use it directly without retrying the primary path first.
Configuration
# Explicit fallback IPs (comma-separated)
TELEGRAM_FALLBACK_IPS=149.154.167.220,149.154.167.221
Or in ~/.hermes/config.yaml:
platforms:
telegram:
extra:
fallback_ips:
- "149.154.167.220"
:::tip
You usually don't need to configure this manually. The auto-discovery via DoH handles most restricted-network scenarios. The TELEGRAM_FALLBACK_IPS env var is only needed if DoH is also blocked on your network.
:::
Troubleshooting
| Problem | Solution |
|---|---|
| Bot not responding at all | Verify TELEGRAM_BOT_TOKEN is correct. Check hermes gateway logs for errors. |
| Bot responds with "unauthorized" | Your user ID is not in TELEGRAM_ALLOWED_USERS. Double-check with @userinfobot. |
| Bot ignores group messages | Privacy mode is likely on. Disable it (Step 3) or make the bot a group admin. Remember to remove and re-add the bot after changing privacy. |
| Voice messages not transcribed | Verify STT is available: install faster-whisper for local transcription, or set GROQ_API_KEY / VOICE_TOOLS_OPENAI_KEY in ~/.hermes/.env. |
| Voice replies are files, not bubbles | Install ffmpeg (needed for Edge TTS Opus conversion). |
| Bot token revoked/invalid | Generate a new token via /revoke then /newbot or /token in BotFather. Update your .env file. |
Exec Approval
When the agent tries to run a potentially dangerous command, it asks you for approval in the chat:
⚠️ This command is potentially dangerous (recursive delete). Reply "yes" to approve.
Reply "yes"/"y" to approve or "no"/"n" to deny.
Security
:::warning
Always set TELEGRAM_ALLOWED_USERS to restrict who can interact with your bot. Without it, the gateway denies all users by default as a safety measure.
:::
Never share your bot token publicly. If compromised, revoke it immediately via BotFather's /revoke command.
For more details, see the Security documentation. You can also use DM pairing for a more dynamic approach to user authorization.