Telegram 设置
Hermes Agent 可作为完整的 Telegram 对话机器人运行。连接后,你可以从任意设备与代理聊天、发送语音备忘录(自动转录)、接收定时任务结果,并在群组中使用它。此集成基于 python-telegram-bot,支持文本、语音、图片和文件附件。
第一步:通过 BotFather 创建机器人
每个 Telegram 机器人都需要由 @BotFather(Telegram 官方机器人管理工具)颁发的 API 令牌。
- 打开 Telegram 并搜索 @BotFather,或访问 t.me/BotFather
- 发送
/newbot - 选择一个 显示名称(例如:“Hermes Agent”)—— 可以是任意内容
- 选择一个 用户名 —— 必须唯一且以
bot结尾(例如my_hermes_bot) - BotFather 会回复你的 API 令牌。格式如下:
123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
请妥善保管您的机器人密钥。任何持有该密钥的人都能控制您的机器人。若密钥泄露,请立即通过 BotFather 中的 /revoke 撤销。
第二步:自定义您的机器人(可选)
以下 BotFather 命令可提升用户体验。向 @BotFather 发送相应命令:
| 命令 | 用途 |
|---|---|
/setdescription | 用户开始聊天前显示的“此机器人能做什么?”说明文字 |
/setabouttext | 机器人资料页上的简短描述 |
/setuserpic | 上传机器人的头像 |
/setcommands | 定义命令菜单(聊天中的 / 按钮) |
/setprivacy | 控制机器人是否查看群组中的所有消息(参见第三步) |
对于 /setcommands,一个实用的初始设置示例:
help - Show help information
new - Start a new conversation
sethome - Set this chat as the home channel
第三步:隐私模式(群组使用的关键)
Telegram 机器人默认启用 隐私模式。这是在群组中使用机器人时最常见的困惑来源。
当隐私模式开启时,您的机器人只能看到:
- 以
/命令开头的消息 - 直接回复机器人自身消息的回复
- 系统消息(成员加入/离开、置顶消息等)
- 机器人是管理员的频道中的消息
当隐私模式关闭时,机器人将收到群组中的每一条消息。
如何关闭隐私模式
- 向 @BotFather 发送消息
- 发送
/mybots - 选择您的机器人
- 进入 机器人设置 → 群组隐私 → 关闭
更改隐私设置后,必须将机器人从群组中移除并重新添加。Telegram 在机器人加入群组时会缓存其隐私状态,只有在重新添加后才会更新。
另一种替代方案:将机器人提升为 群组管理员。管理员机器人无论隐私设置如何,都会收到所有消息,避免了全局隐私模式的切换。
第四步:查找您的用户 ID
Hermes Agent 使用数字型 Telegram 用户 ID 来控制访问权限。您的用户 ID 不是您的用户名 —— 而是一个类似 123456789 的数字。
方法一(推荐): 向 @userinfobot 发送消息 —— 它会立即回复您的用户 ID。
方法二: 向 @get_id_bot 发送消息 —— 另一个可靠的选项。
请保存此数字,下一步需要用到。
第五步:配置 Hermes
选项 A:交互式设置(推荐)
hermes gateway setup
提示时选择 Telegram。配置向导会要求您输入机器人令牌和允许的用户 ID,然后为您自动生成配置。
选项 B:手动配置
将以下内容添加到 ~/.hermes/.env 中:
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
TELEGRAM_ALLOWED_USERS=123456789 # Comma-separated for multiple users
启动网关
hermes gateway
机器人应在数秒内上线。在 Telegram 上向它发送一条消息以进行验证。
Webhook 模式
默认情况下,Hermes 通过 长轮询(long polling)方式连接 Telegram —— 网关主动向 Telegram 服务器发起请求以获取新消息。这种方式适用于本地或始终在线的部署。
对于 云部署(Fly.io、Railway、Render 等),Webhook 模式 更具成本效益。这些平台可在收到外部 HTTP 请求时自动唤醒休眠的实例,但无法通过出站连接唤醒。由于轮询是出站行为,使用轮询的机器人永远无法休眠。Webhook 模式则反转了方向 —— Telegram 将更新推送到您机器人的 HTTPS 地址,从而实现“空闲时休眠”的部署。
| 轮询(默认) | Webhook | |
|---|---|---|
| 方向 | 网关 → Telegram(出站) | Telegram → 网关(入站) |
| 适用场景 | 本地、始终在线服务器 | 具有自动唤醒功能的云平台 |
| 配置 | 无需额外设置 | 设置 TELEGRAM_WEBHOOK_URL |
| 空闲成本 | 机器必须持续运行 | 机器可在消息之间休眠 |
配置
将以下内容添加到 ~/.hermes/.env 中:
TELEGRAM_WEBHOOK_URL=https://my-app.fly.dev/telegram
# TELEGRAM_WEBHOOK_PORT=8443 # optional, default 8443
# TELEGRAM_WEBHOOK_SECRET=mysecret # optional, recommended
| 变量 | 是否必需 | 描述 |
|---|---|---|
TELEGRAM_WEBHOOK_URL | 是 | Telegram 将推送更新的公共 HTTPS 地址。路径部分会自动提取(例如,从上例中提取为 /telegram)。 |
TELEGRAM_WEBHOOK_PORT | 否 | Webhook 服务器监听的本地端口(默认:8443)。 |
TELEGRAM_WEBHOOK_SECRET | 否 | 用于验证更新确实来自 Telegram 的密钥令牌。强烈建议在生产环境中使用。 |
当 TELEGRAM_WEBHOOK_URL 设置后,网关将启动 HTTP Webhook 服务器而非轮询模式。未设置时则使用轮询模式 —— 与旧版本行为一致。
云部署示例(Fly.io)
- 将环境变量添加到您的 Fly.io 应用密钥中:
fly secrets set TELEGRAM_WEBHOOK_URL=https://my-app.fly.dev/telegram
fly secrets set TELEGRAM_WEBHOOK_SECRET=$(openssl rand -hex 32)
- 在您的
fly.toml中暴露 webhook 端口:
[[services]]
internal_port = 8443
protocol = "tcp"
[[services.ports]]
handlers = ["tls", "http"]
port = 443
- 部署:
fly deploy
网关日志应显示:[telegram] Connected to Telegram (webhook mode)。
主频道
在任意 Telegram 聊天(私聊或群组)中使用 /sethome 命令,可将其设为 主频道。定时任务(cron 作业)的结果将发送至此频道。
您也可以在 ~/.hermes/.env 中手动设置:
TELEGRAM_HOME_CHANNEL=-1001234567890
TELEGRAM_HOME_CHANNEL_NAME="My Notes"
群组聊天 ID 为负数(例如 -1001234567890)。您的个人私聊 ID 与您的用户 ID 相同。
语音消息
接收语音(语音转文字)
您在 Telegram 中发送的语音消息将由 Hermes 配置的 STT 提供商自动转录,并作为文本注入对话中。
local使用faster-whisper在运行 Hermes 的机器上执行 —— 无需 API 密钥groq使用 Groq Whisper,需提供GROQ_API_KEYopenai使用 OpenAI Whisper,需提供VOICE_TOOLS_OPENAI_KEY
发送语音(文字转语音)
当代理生成音频时,将以原生 Telegram 语音气泡 形式发送 —— 即可内联播放的圆形图标。
- OpenAI 和 ElevenLabs 原生输出 Opus 格式 —— 无需额外配置
- Edge TTS(默认免费提供者)输出 MP3 格式,需使用 ffmpeg 转换为 Opus:
# Ubuntu/Debian
sudo apt install ffmpeg
# macOS
brew install ffmpeg
若无 ffmpeg,Edge TTS 生成的音频将以普通音频文件形式发送(仍可播放,但使用矩形播放器而非语音气泡)。
在您的 config.yaml 中,通过 tts.provider 键配置 TTS 提供商。
群组聊天使用
Hermes Agent 在 Telegram 群组中使用时需注意以下几点:
- 隐私模式 决定了机器人能看到哪些消息(参见 第 3 步)
TELEGRAM_ALLOWED_USERS依然适用 —— 即使在群组中,也只有授权用户才能触发机器人- 您可通过
telegram.require_mention: true让机器人不响应普通群组闲聊 - 当启用
telegram.require_mention: true时,群组消息仅在以下情况被接受:- 以斜杠命令开头
- 回复机器人自身的某条消息
- 包含
@botusername的提及 - 匹配您在
telegram.mention_patterns中配置的正则唤醒词
- 若
telegram.require_mention未设置或为 false,Hermes 将保持之前的开放群组行为,对可见的普通群组消息作出响应
群组触发配置示例
将以下内容添加到 ~/.hermes/config.yaml 中:
telegram:
require_mention: true
mention_patterns:
- "^\\s*chompy\\b"
此示例允许所有常规的直接触发方式,以及以 chompy 开头的消息,即使这些消息未使用 @mention 也是如此。
关于 mention_patterns 的说明
- 模式使用 Python 正则表达式
- 匹配不区分大小写
- 模式会同时检查文本消息和媒体标题
- 无效的正则表达式模式将被忽略,并在网关日志中发出警告,而不会导致机器人崩溃
- 若希望模式仅匹配消息开头,请用
^锚定
私人聊天话题(Bot API 9.4)
Telegram Bot API 9.4(2026年2月)引入了 私人聊天话题 —— 机器人可在一对一私聊中直接创建类似论坛的话题线程,无需超级群组。这使得你可以在与 Hermes 的现有私聊中运行多个相互隔离的工作空间。
使用场景
如果你同时处理多个长期项目,话题可保持各自上下文独立:
- “网站”话题 —— 处理你的生产级网页服务
- “研究”话题 —— 文献综述与论文探索
- “通用”话题 —— 杂项任务和快速提问
每个话题都有自己的对话会话、历史记录和上下文——彼此完全隔离。
配置方法
在 ~/.hermes/config.yaml 中添加话题配置,位于 platforms.telegram.extra.dm_topics 下方:
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
字段说明:
| 字段 | 必填 | 描述 |
|---|---|---|
name | 是 | 话题显示名称 |
icon_color | 否 | Telegram 图标颜色代码(整数) |
icon_custom_emoji_id | 否 | 话题图标的自定义表情 ID |
skill | 否 | 新会话启动时自动加载的技能 |
thread_id | 否 | 话题创建后自动填充 —— 不要手动设置 |
工作原理
- 网关启动时,Hermes 会为每个尚未拥有
thread_id的话题调用createForumTopic thread_id会被自动保存回config.yaml—— 后续重启将跳过该 API 调用- 每个话题对应一个独立的会话密钥:
agent:main:telegram:dm:{chat_id}:{thread_id} - 每个话题中的消息拥有独立的对话历史、内存清空机制和上下文窗口
技能绑定
带有 skill 字段的话题,在新会话开始时会自动加载指定技能。其行为与在对话开头输入 /skill-name 完全一致:技能内容会被注入第一条消息,后续消息将看到其在对话历史中的存在。
例如,一个设置了 skill: arxiv 的话题,每当会话重置(因空闲超时、每日重置或手动 /reset)时,arxiv 技能都会被预先加载。
通过手动调用 Telegram API 创建的话题,会在收到 forum_topic_created 服务消息时被自动发现。你也可以在网关运行期间向配置中添加话题——它们将在下一次缓存未命中时被识别。
群组论坛话题技能绑定
启用了 话题模式 的超级群组(也称为“论坛话题”)已具备按话题进行会话隔离的功能——每个 thread_id 对应一个独立的对话。但你可能希望在特定群组话题接收到消息时,自动加载某个技能,就像私聊话题的技能绑定一样。
使用场景
一个团队超级群组,设有不同工作流的论坛话题:
- 工程 话题 → 自动加载
software-development技能 - 研究 话题 → 自动加载
arxiv技能 - 通用 话题 → 不加载技能,作为通用助手
配置方法
在 ~/.hermes/config.yaml 中,于 platforms.telegram.extra.group_topics 下添加话题绑定:
platforms:
telegram:
extra:
group_topics:
- chat_id: -1001234567890 # Supergroup ID
topics:
- name: Engineering
thread_id: 5
skill: software-development
- name: Research
thread_id: 12
skill: arxiv
- name: General
thread_id: 1
# No skill — general purpose
字段说明:
| 字段 | 必填 | 描述 |
|---|---|---|
chat_id | 是 | 超级群组的数字 ID(以 -100 开头的负数) |
name | 否 | 话题的人类可读标签(仅用于信息参考) |
thread_id | 是 | Telegram 论坛话题 ID —— 可在 t.me/c/<group_id>/<thread_id> 链接中查看 |
skill | 否 | 新会话启动时自动加载的技能 |
工作原理
- 当消息到达映射的群组话题时,Hermes 会在
group_topics配置中查找对应的chat_id和thread_id - 如果匹配项包含
skill字段,则该技能将被自动加载到会话中——与私聊话题绑定行为完全相同 - 无
skill键的话题仅获得会话隔离(原有行为,不变) - 未映射的
thread_id值或chat_id值将静默忽略——无错误,无技能加载
与私聊话题的区别
| 私聊话题 | 群组话题 | |
|---|---|---|
| 配置键 | extra.dm_topics | extra.group_topics |
| 话题创建 | Hermes 通过 API 自动创建(若 thread_id 缺失) | 管理员在 Telegram UI 中手动创建 |
thread_id | 创建后自动填充 | 必须手动设置 |
icon_color / icon_custom_emoji_id | 支持 | 不适用(管理员控制外观) |
| 技能绑定 | ✓ | ✓ |
| 会话隔离 | ✓ | ✓(论坛话题已内置) |
要查找话题的 thread_id,请在 Telegram Web 或桌面客户端中打开该话题,查看 URL:https://t.me/c/1234567890/5 — the last number (5) is the thread_id. The chat_id for supergroups is the group ID prefixed with -100 (e.g., group 1234567890 becomes -1001234567890。
最新 Bot API 功能
- Bot API 9.4(2026年2月): 私人聊天话题 —— 机器人可通过
createForumTopic在一对一私聊中创建论坛话题。详见上方 私人聊天话题。 - 隐私政策要求: Telegram 现在要求机器人必须提供隐私政策。可通过 BotFather 设置
/setprivacy_policy,否则 Telegram 可能自动生成占位符。如果机器人面向公众,这一点尤为重要。 - 消息流式传输: Bot API 9.x 增加了对长响应流式传输的支持,可显著改善长回复的感知延迟。
交互式模型选择器
当你在 Telegram 聊天中发送 /model 且不带参数时,Hermes 会显示一个交互式内联键盘,用于切换模型:
- 提供商选择 —— 显示每个可用提供商及其模型数量的按钮(如“OpenAI (15)”、“✓ Anthropic (12)”表示当前提供商)。
- 模型选择 —— 分页的模型列表,包含 上一页/下一页 导航按钮,返回 按钮回到提供商列表,以及 取消 按钮。
当前模型和提供商名称显示在顶部。所有导航操作均通过原地编辑同一消息实现(避免聊天混乱)。
如果你知道确切的模型名称,可直接输入 /model <name> 跳过选择器。你也可以输入 /model <name> --global 来使更改在所有会话中持久生效。
Webhook 模式
默认情况下,Telegram 适配器通过 长轮询 连接 —— 网关主动向外连接至 Telegram 服务器。这种方式适用于所有环境,但会维持一个持久连接。
Webhook 模式 是另一种替代方案,由 Telegram 通过 HTTPS 将更新推送到你的服务器。这非常适合 无服务器和云部署(如 Fly.io、Railway 等),因为入站 HTTP 请求可以唤醒休眠的机器。
配置方法
设置 TELEGRAM_WEBHOOK_URL 环境变量以启用 webhook 模式:
# 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
或在 ~/.hermes/config.yaml 中配置:
telegram:
webhook_mode: true
当 TELEGRAM_WEBHOOK_URL 被设置后,网关将启动一个监听 0.0.0.0:<port> 的 HTTP 服务器,并向 Telegram 注册 webhook URL。URL 路径从 webhook URL 中提取(默认为 /telegram)。
Telegram 要求 webhook 端点必须配备 有效的 TLS 证书。自签名证书将被拒绝。请使用反向代理(nginx、Caddy)或提供 TLS 终止的平台(Fly.io、Railway、Cloudflare Tunnel)。
DNS-over-HTTPS 备用 IP 地址
在某些受限网络中,api.telegram.org 可能解析为不可达的 IP 地址。Telegram 适配器内置了 备用 IP 机制,可在不改变正确 TLS 主机名和 SNI 的前提下,透明地尝试其他 IP 地址进行重连。1. 如果设置了 TELEGRAM_FALLBACK_IPS,则直接使用这些 IP 地址。
2. 否则,适配器会自动通过 DNS-over-HTTPS(DoH)查询 Google DNS 和 Cloudflare DNS,以发现 api.telegram.org 的备用 IP 地址。
3. 通过 DoH 返回且与系统 DNS 结果不同的 IP 地址将作为备用选项使用。
4. 如果 DoH 也受到阻止,则使用一个硬编码的种子 IP 地址(149.154.167.220)作为最后手段。
5. 一旦某个备用 IP 成功连接,它就会“固定”下来——后续请求将直接使用该 IP,不再尝试主路径。
配置
# Explicit fallback IPs (comma-separated)
TELEGRAM_FALLBACK_IPS=149.154.167.220,149.154.167.221
或在 ~/.hermes/config.yaml 中配置:
platforms:
telegram:
extra:
fallback_ips:
- "149.154.167.220"
通常无需手动配置。通过 DoH 的自动发现机制可处理大多数受限网络场景。仅当您的网络中 DoH 也被阻断时,才需要设置 TELEGRAM_FALLBACK_IPS 环境变量。
代理支持
如果您的网络需要通过 HTTP 代理才能访问互联网(常见于企业环境),Telegram 适配器会自动读取标准的代理环境变量,并将所有连接通过代理路由。
支持的变量
适配器按顺序检查以下环境变量,使用第一个已设置的:
HTTPS_PROXYHTTP_PROXYALL_PROXYhttps_proxy/http_proxy/all_proxy(小写变体)
配置
在启动网关前设置代理环境变量:
export HTTPS_PROXY=http://proxy.example.com:8080
hermes gateway
或添加到 ~/.hermes/.env 中:
HTTPS_PROXY=http://proxy.example.com:8080
该代理适用于主传输通道以及所有备用 IP 传输通道。无需额外配置 Hermes —— 只要环境变量被设置,便会自动生效。
这涵盖了 Hermes 用于 Telegram 连接的自定义备用传输层。其他地方使用的标准 httpx 客户端本身已原生支持代理环境变量。
消息反应
机器人可以为消息添加表情符号反应,作为视觉处理反馈:
- 👀 当机器人开始处理您的消息时
- ✅ 当响应成功送达时
- ❌ 若处理过程中发生错误时
反应功能默认关闭。您可在 config.yaml 中启用:
telegram:
reactions: true
或通过环境变量:
TELEGRAM_REACTIONS=true
与 Discord(反应是累加的)不同,Telegram Bot API 在单次调用中会替换所有机器人的反应。从 👀 到 ✅/❌ 的转换是原子性的——您不会同时看到两个反应。
如果机器人在群组中没有添加反应的权限,相关调用将静默失败,但消息处理将继续正常进行。
故障排除
| 问题 | 解决方案 |
|---|---|
| 机器人完全无响应 | 确认 TELEGRAM_BOT_TOKEN 正确。检查 hermes gateway 日志中的错误信息。 |
| 机器人回复“未授权” | 您的用户 ID 不在 TELEGRAM_ALLOWED_USERS 中。请通过 @userinfobot 再次确认。 |
| 机器人忽略群组消息 | 可能开启了隐私模式。请禁用它(第 3 步),或让机器人成为群组管理员。记得更改隐私设置后重新删除并添加机器人。 |
| 语音消息无法转录 | 确保 STT 功能可用:安装 faster-whisper 实现本地转录,或在 ~/.hermes/.env 中设置 GROQ_API_KEY / VOICE_TOOLS_OPENAI_KEY。 |
| 语音回复为文件而非气泡 | 安装 ffmpeg(用于 Edge TTS Opus 编码转换)。 |
| 机器人令牌已撤销/无效 | 通过 /revoke 生成新令牌,然后在 BotFather 中执行 /newbot 或 /token 命令。更新您的 .env 文件。 |
| Webhook 无法接收更新 | 确认 TELEGRAM_WEBHOOK_URL 可公开访问(可用 curl 测试)。确保您的平台/反向代理将来自 URL 端口的入站 HTTPS 流量转发至由 TELEGRAM_WEBHOOK_PORT 配置的本地监听端口(两者不必相同)。确保启用了 SSL/TLS —— Telegram 仅向 HTTPS 地址发送数据。检查防火墙规则。 |
执行审批
当代理尝试运行潜在危险命令时,会在聊天中向您请求批准:
⚠️ 此命令可能具有危险性(递归删除)。回复 "yes" 以批准。
回复 "yes"/"y" 表示批准,回复 "no"/"n" 表示拒绝。
安全性
始终设置 TELEGRAM_ALLOWED_USERS 以限制可与您的机器人交互的用户。若不设置,网关将默认拒绝所有用户,这是一种安全措施。
切勿公开分享您的机器人令牌。若泄露,请立即通过 BotFather 的 /revoke 命令撤销。