Telegram 设置
Hermes Agent 与 Telegram 集成,作为一个全功能对话机器人。连接后,您可以从任何设备与您的 agent 聊天,发送自动转录的语音备忘录,接收定时任务结果,并在群聊中使用 agent。该集成基于 python-telegram-bot,支持文本、语音、图片和文件附件。
第 1 步:通过 BotFather 创建机器人
每个 Telegram 机器人需要由 Telegram 的官方机器人管理工具 @BotFather 颁发的 API 令牌(token)。
- 打开 Telegram 搜索 @BotFather,或访问 t.me/BotFather
- 发送
/newbot - 选择一个显示名称(例如 “Hermes Agent”)— 可以是任意内容
- 选择一个用户名 — 必须唯一且以
bot结尾(例如my_hermes_bot) - BotFather 会回复您的 API 令牌。格式如下:
123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
:::warning
请保管好您的机器人令牌。任何拥有此令牌的人都可以控制您的机器人。如果泄露,请立即在 BotFather 中使用 /revoke 撤销。
:::
第 2 步:自定义您的机器人(可选)
以下 BotFather 命令可改善用户体验。给 @BotFather 发送消息并使用:
| 命令 | 用途 |
|---|---|
/setdescription | 用户在开始聊天前看到的”此机器人能做什么?“文本 |
/setabouttext | 机器人个人资料页上的简短文字 |
/setuserpic | 上传机器人的头像 |
/setcommands | 定义命令菜单(聊天中的 / 按钮) |
/setprivacy | 控制机器人是否能看到所有群组消息(见第 3 步) |
:::tip
对于 /setcommands,一个有用的起始设置:
help - 显示帮助信息
new - 开始新对话
sethome - 将此聊天设为主频道
:::
第 3 步:隐私模式(群组关键)
Telegram 机器人有一个默认启用的隐私模式(privacy mode)。这是在群组中使用机器人时最常见的困惑来源。
隐私模式开启时,您的机器人只能看到:
- 以
/命令开头的消息 - 直接回复机器人自己消息的回复
- 服务消息(成员加入/离开、置顶消息等)
- 机器人作为管理员的频道中的消息
隐私模式关闭时,机器人接收群组中的每条消息。
如何关闭隐私模式
- 给 @BotFather 发送消息
- 发送
/mybots - 选择您的机器人
- 进入 Bot Settings → Group Privacy → Turn off
:::warning 更改隐私设置后,您必须将机器人从群组中移除并重新添加。 Telegram 在机器人加入群组时会缓存隐私状态,在移除并重新添加之前不会更新。 :::
:::tip 关闭隐私模式的替代方案:将机器人提升为群组管理员。管理员机器人无论隐私设置如何都会接收所有消息,这避免了切换全局隐私模式的需要。 :::
观察群组对话而不自动回复
要实现 OpenClaw/元宝风格的群组行为,配置 Telegram 使机器人可以看到普通群组消息但仅在直接触发时回复:
telegram:
allowed_chats:
- "-1001234567890"
group_allowed_chats:
- "-1001234567890"
require_mention: true
observe_unmentioned_group_messages: true启用此模式后,来自明确白名单聊天/主题的未提及群组消息会被追加到共享的聊天/主题会话记录中作为观察到的上下文,但不会分发给 agent 处理。allowed_chats 控制机器人在哪里回复;group_allowed_chats 授权用于观察上下文的共享群组会话,因此对此模式请使用相同的聊天 ID。稍后在该白名单聊天/主题中通过 @botname 提及、回复机器人或配置的提及模式可以使用该观察到的上下文。触发的消息还会标记为 [昵称|用户ID] 并获得每轮安全提示,以便模型将之前的观察行视为上下文,而非发给机器人的指令。
等效环境变量:
TELEGRAM_ALLOWED_CHATS=-1001234567890
TELEGRAM_GROUP_ALLOWED_CHATS=-1001234567890
TELEGRAM_OBSERVE_UNMENTIONED_GROUP_MESSAGES=true这需要 Telegram 将普通群组消息传递给网关,因此请按上述说明禁用 BotFather 隐私模式或将机器人提升为群组管理员。
第 4 步:查找您的用户 ID
Hermes Agent 使用 Telegram 数字用户 ID 来控制访问。您的用户 ID 不是您的用户名——它是一个像 123456789 这样的数字。
方法 1(推荐): 给 @userinfobot 发送消息——它会立即回复您的用户 ID。
方法 2: 给 @get_id_bot 发送消息——另一个可靠的选择。
保存此数字;下一步会用到。
第 5 步:配置 Hermes
选项 A:交互式设置(推荐)
hermes gateway setup根据提示选择 Telegram。向导会询问您的机器人令牌和允许的用户 ID,然后为您写入配置。
选项 B:手动配置
将以下内容添加到 ~/.hermes/.env:
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
TELEGRAM_ALLOWED_USERS=123456789 # 多个用户用逗号分隔启动网关
hermes gateway机器人应在几秒内上线。在 Telegram 上给它发送一条消息以验证。
从 Docker 后端终端发送生成的文件
如果您的终端后端是 docker,请记住 Telegram 附件是由网关进程发送的,而不是从容器内部发送的。这意味着最终的 MEDIA:/... 路径必须在运行网关的主机上可读。
常见陷阱:
- agent 在 Docker 内部将文件写入
/workspace/report.txt - 模型发出
MEDIA:/workspace/report.txt - Telegram 发送失败,因为
/workspace/report.txt只存在于容器内部,不在主机上
推荐模式:
terminal:
backend: docker
docker_volumes:
- "/home/user/.hermes/cache/documents:/output"然后:
- 在 Docker 内部将文件写入
/output/... - 在
MEDIA:中发出主机可见的路径,例如:MEDIA:/home/user/.hermes/cache/documents/report.txt
如果您已有 docker_volumes: 部分,将新的挂载点添加到同一列表中。YAML 重复键会静默覆盖前面的值。
支持的 MEDIA: 文件扩展名
网关从 agent 回复中提取 MEDIA:/path/to/file 标签,并将引用的文件作为平台原生附件发送。所有网关平台支持的扩展名:
| 类别 | 扩展名 |
|---|---|
| 图片 | png, jpg, jpeg, gif, webp, bmp, tiff, svg |
| 音频 | mp3, wav, ogg, m4a, opus, flac, aac |
| 视频 | mp4, mov, webm, mkv, avi |
| 文档 | pdf, txt, md, csv, json, xml, html, yaml, yml, log |
| 办公文档 | docx, xlsx, pptx, odt, ods, odp |
| 压缩包 | zip, rar, 7z, tar, gz, bz2 |
| 电子书/应用包 | epub, apk, ipa |
列表中的任何类型都会在支持的平台上作为原生附件发送(Telegram、Discord、Signal、Slack、WhatsApp、飞书、Matrix 等);在不支持原生附件的平台上则回退为链接或纯文本指示。粗体类别是在最近几个版本中添加的——如果您之前依赖模型说”这里是文件:/path/to/report.docx”,请改用 MEDIA:/path/to/report.docx 以实现原生发送。
Webhook 模式
默认情况下,Hermes 使用**长轮询(long polling)**连接 Telegram——网关发出出站请求到 Telegram 服务器以获取新更新。这对本地和始终在线的部署效果良好。
对于云部署(Fly.io、Railway、Render 等),webhook 模式更具成本效益。这些平台可以在入站 HTTP 流量时自动唤醒休眠的机器,但出站连接无法唤醒。由于轮询是出站的,轮询机器人永远无法休眠。Webhook 模式反转了方向——Telegram 将更新推送到您的机器人的 HTTPS URL,从而实现空闲时休眠的部署。
| 轮询(默认) | Webhook | |
|---|---|---|
| 方向 | 网关 → Telegram(出站) | Telegram → 网关(入站) |
| 最适合 | 本地、始终在线的服务器 | 支持自动唤醒的云平台 |
| 设置 | 无需额外配置 | 设置 TELEGRAM_WEBHOOK_URL |
| 空闲成本 | 机器必须保持运行 | 机器可在消息间隔休眠 |
配置
将以下内容添加到 ~/.hermes/.env:
TELEGRAM_WEBHOOK_URL=https://my-app.fly.dev/telegram
TELEGRAM_WEBHOOK_SECRET="$(openssl rand -hex 32)" # 必需
# TELEGRAM_WEBHOOK_PORT=8443 # 可选,默认 8443| 变量 | 必需 | 描述 |
|---|---|---|
TELEGRAM_WEBHOOK_URL | 是 | 公开的 HTTPS URL,Telegram 将向此发送更新。URL 路径会被自动提取(例如示例中的 /telegram)。 |
TELEGRAM_WEBHOOK_SECRET | 是(当设置了 TELEGRAM_WEBHOOK_URL 时) | 秘密令牌,Telegram 在每个 webhook 请求中回传用于验证。没有它网关拒绝启动——请参阅 GHSA-3vpc-7q5r-276h。使用 openssl rand -hex 32 生成。 |
TELEGRAM_WEBHOOK_PORT | 否 | webhook 服务器的本地监听端口(默认:8443)。 |
当设置了 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 的 API 被封锁,或者您需要通过代理路由流量,请设置 Telegram 特定的代理 URL。此设置优先于通用的 HTTPS_PROXY / HTTP_PROXY 环境变量。
选项 1:config.yaml(推荐)
telegram:
proxy_url: "socks5://127.0.0.1:1080"选项 2:环境变量
TELEGRAM_PROXY=socks5://127.0.0.1:1080支持的协议:http://、https://、socks5://。
代理适用于主 Telegram 连接和回退 IP 传输。如果未设置 Telegram 特定代理,网关会回退到 HTTPS_PROXY / HTTP_PROXY / ALL_PROXY(或 macOS 系统代理自动检测)。
主频道
在任意 Telegram 聊天(DM 或群组)中使用 /sethome 命令将其设为主频道(home channel)。定时任务(cron job)会将结果发送到此频道。
您也可以在 ~/.hermes/.env 中手动设置:
TELEGRAM_HOME_CHANNEL=-1001234567890
TELEGRAM_HOME_CHANNEL_NAME="我的笔记":::tip
群组聊天 ID 是负数(例如 -1001234567890)。您的个人 DM 聊天 ID 与您的用户 ID 相同。
:::
主题模式下的定时任务投递
如果您的机器人 DM 启用了主题模式(topic mode),发送到根聊天的定时任务消息会落在仅系统区域——在此回复不会打开会话,您会看到”主聊天保留给系统命令使用”的提示。创建一个专用的论坛主题(例如 Cron)并设置:
TELEGRAM_CRON_THREAD_ID=<topic_thread_id>TELEGRAM_CRON_THREAD_ID 会覆盖 TELEGRAM_HOME_CHANNEL_THREAD_ID,仅用于定时任务投递。该主题中的回复会继续该主题的现有会话。
语音消息
接收语音(语音转文本)
您在 Telegram 上发送的语音消息会被 Hermes 配置的 STT 提供商自动转录并作为文本注入对话中。
local使用运行 Hermes 的机器上的faster-whisper— 无需 API keygroq使用 Groq Whisper,需要GROQ_API_KEYopenai使用 OpenAI Whisper,需要VOICE_TOOLS_OPENAI_KEY
跳过 STT:将原始音频文件传递给 agent
如果您希望agent 自己处理音频——用于说话人分离、自定义转录工具或仅仅归档录音——请在 ~/.hermes/config.yaml 中设置 stt.enabled: false:
stt:
enabled: false禁用 STT 后,网关仍然会将语音/音频附件下载到 Hermes 的音频缓存中,但不会进行转录。agent 会收到带有标记的消息,例如:
[用户发送了一条语音消息:/home/<user>/.hermes/cache/audio/<hash>.ogg]
您的工具或技能可以直接读取该路径(例如,传递给本地的说话人分离管道、更强大的转录模型,或上传到长期存储)。文件扩展名反映了 Telegram 提供的原始格式(语音笔记为 .ogg,音频附件为 .mp3/.m4a 等)。
这与下文本地 Bot API 服务器部分自然配合,后者将 Telegram 的 20MB getFile 上限提升到 2GB——当您要处理的录音超过几分钟时非常有用。
发送语音(文本转语音)
当 agent 通过 TTS 生成音频时,会作为 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 提供商。
大文件(>20MB)通过本地 Bot API 服务器
Telegram 的公共 Bot API 将 getFile 下载限制在 20 MB,因此任何大于此的语音笔记、音频文件、视频或文档都会被 Hermes 静默拒绝并回复”文件过大”。记录的解决方案是运行一个本地 telegram-bot-api 守护进程——与 Telegram 使用的相同服务器软件,但在您的网络上运行。本地服务器将文件上限提升到 2 GB,当 Hermes 检测到配置了自定义 base_url 时,会自动解除其内部上限。
这开启了以下工作流程:
- 发送长语音备忘录(45 分钟的会议、播客)给机器人
- 上传大视频用于视觉工具处理
- 归档原始音频用于离线管道,如说话人分离、对齐或训练数据
第 1 步:获取 Telegram API 凭证
本地服务器直接与 Telegram 的 MTProto 层通信(而非公共 Bot API),因此需要 MTProto 凭证:
- 访问 my.telegram.org/apps 并使用您的 Telegram 账户登录。
- 创建一个新应用(任意名称和简短描述即可)。
- 复制
api_id和api_hash— 两者都是必需的。
第 2 步:运行 telegram-bot-api 服务器
社区维护的 aiogram/telegram-bot-api Docker 镜像是最简单的方式。最小化的 docker-compose.yaml(使用 --local 模式以启用更高的上限):
services:
tg-bot-api:
image: aiogram/telegram-bot-api:latest
container_name: tg-bot-api
restart: unless-stopped
ports:
- "127.0.0.1:8081:8081" # 仅绑定到回环地址;见安全说明
environment:
TELEGRAM_API_ID: "12345" # 来自第 1 步的 api_id
TELEGRAM_API_HASH: "abcdef..." # 来自第 1 步的 api_hash
TELEGRAM_LOCAL: "1" # 启用 --local 模式(将 20MB 提升至 2GB)
volumes:
- ./tg-bot-api-data:/var/lib/telegram-bot-api启动它:
docker compose up -d tg-bot-api
docker logs --tail 20 tg-bot-api:::warning 安全性
本地 Bot API 服务器在 URL 路径中接收您的机器人令牌(例如 /bot<TOKEN>/getMe),并且没有额外的认证。任何能访问该端口的人都可以完全控制您的机器人——读取它能看到的每条消息、以它的身份发送消息等。将容器绑定到 127.0.0.1 和/或在私有网络前放置反向代理。永远不要将端口 8081 暴露到公共互联网。
:::
第 3 步:将机器人从公共 API 注销(一次性)
一个机器人一次只能在一个 Bot API 服务器上活动。如果您的机器人之前一直在使用 api.telegram.org(几乎肯定如此),您必须先显式地在那里注销它,本地服务器才会接受它:
curl "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/logOut"
# 预期响应:{"ok":true,"result":true}这是一次性迁移步骤——每次重启无需重复。Telegram 将 logOut 之后收到的消息通过新服务器发送。
验证本地服务器能以机器人身份与 Telegram 通信:
curl "http://127.0.0.1:8081/bot<YOUR_BOT_TOKEN>/getMe"
# 预期响应:{"ok":true,"result":{"id":...,"is_bot":true,...}}第 4 步:将 Hermes 指向本地服务器
在 ~/.hermes/config.yaml 的 platforms.telegram.extra 下添加 URL:
platforms:
telegram:
extra:
base_url: "http://127.0.0.1:8081/bot"
base_file_url: "http://127.0.0.1:8081/file/bot"
local_mode: true # 见下面的第 5 步——仅当机器人的数据
# 目录对 Hermes 进程可读时设置:::caution 使用 platforms.telegram.extra,而非 telegram.extra
目前只有 platforms.<name>.extra 形式会深度合并到平台配置中。直接放在顶层 telegram.extra 块下的键会被静默忽略。
:::
当设置了 base_url 时,Hermes:
- 会针对本地服务器构建 python-telegram-bot 客户端
- 自动将内部文档/音频大小上限从 20 MB 提升到 2 GB
- 在”文件过大”错误消息中报告当前限制(
最大:2048 MB),以便清楚知道当前处于哪种模式
重启网关并查找确认日志行:
hermes gateway restart
grep -E "Using custom Telegram base_url|Using Telegram local_mode" ~/.hermes/logs/gateway.log | tail第 5 步:local_mode — 磁盘文件访问
本地服务器有两种交付文件的方式:
- 没有
--local(默认):文件通过 HTTP 在/file/bot<TOKEN>/<path>提供,与公共 Bot API 相同。20MB 限制仍然有效。仅用作网络修复(例如当api.telegram.org不可访问但您可以自托管时);不是您要的提升大小限制的方式。 - 使用
--local(通过上面的TELEGRAM_LOCAL=1设置):文件写入服务器的文件系统,getFile返回绝对路径而非 HTTP URL。20MB 限制被解除。Hermes 必须从磁盘读取字节,而不是通过 HTTP。
要使磁盘读取路径生效,在上述配置中设置 local_mode: true 并且确保 Hermes 进程可以读取服务器返回的路径。两种场景:
- 同一台机器 — telegram-bot-api 和 Hermes 运行在同一主机上。将数据卷绑定挂载到 Hermes 可读的目录(例如
/var/lib/telegram-bot-api),并确保文件所有权匹配。容器会降权到其内部的telegram-bot-api用户(uid 因镜像而异);最简单的修复方法是在 compose 服务中添加user: "<UID>:<GID>",使文件属于 Hermes 已经运行的 uid。 - 不同的机器 — bot 服务器在一台主机上(例如 NAS、独立的 VM),Hermes 在另一台。服务器的数据目录必须以服务器报告的相同绝对路径(通常为
/var/lib/telegram-bot-api)共享给 Hermes 机器。NFS 对此效果很好;如果您不想在文件系统层面处理 uid 不匹配,使用uid=挂载重映射的 CIFS/SMB 更友好。
如果设置了 local_mode: true 但 Hermes 无法 stat 返回的文件路径(权限问题或挂载错误),python-telegram-bot 会静默回退到对本地服务器进行 HTTP getFile——而 --local 模式的本地服务器会返回 404 Not Found。症状会在 gateway.log 中显示为:
[Telegram] Failed to cache voice: Not Found
telegram.error.InvalidToken: Not Found
如果您看到这个,说明上限提升已生效但文件共享未生效。以网关运行的用户身份,从 Hermes 主机验证 ls -la /var/lib/telegram-bot-api/<TOKEN>/voice/,并确认单个文件可以 cat 而不会出现权限错误。
第 6 步:测试
给机器人发送一个大于 20 MB 的语音笔记或音频文件。实时查看网关日志:
tail -f ~/.hermes/logs/gateway.log | grep -iE "telegram|cache"您应该会看到 [Telegram] Cached user voice at /home/<user>/.hermes/cache/audio/... 行,并且没有”文件过大”的拒绝。结合 stt.enabled: false(上文),原始音频文件的路径会进入 agent 的入站消息,供下游处理。
群聊使用
Hermes Agent 在 Telegram 群聊中工作,但有一些注意事项:
- 隐私模式决定机器人能看到哪些消息(见第 3 步)
TELEGRAM_ALLOWED_USERS仍然适用——即使在群组中,也只有授权用户能触发机器人- 您可以通过
telegram.require_mention: true阻止机器人响应普通群聊内容 - 当设置了
telegram.require_mention: true时,群组消息在以下情况下被接受:- 回复了机器人的某条消息
- 包含
@botusername提及 - 包含
/command@botusername(Telegram 的机器人菜单命令形式,包含机器人名称) - 匹配您配置的正则唤醒词
telegram.mention_patterns
- 在有多个 Hermes 机器人的群组中,
telegram.exclusive_bot_mentions保持路由确定性。当一条消息显式提及一个或多个 Telegram 机器人用户名时,只有被提及的机器人配置文件会处理它;其他 Hermes 机器人在回复和唤醒词回退运行之前忽略它。此功能默认启用。 - 使用
telegram.ignored_threads让 Hermes 在特定的 Telegram 论坛主题中保持静默,即使群组本来允许自由回复或提及触发的回复 - 如果
telegram.require_mention未设置或为 false,Hermes 保持之前开放群组的行为,响应它能看到的普通群组消息
一个群组中的多个 Hermes 机器人
如果您在同一个 Telegram 群组中运行多个 Hermes 配置文件,请为每个配置文件创建一个 Telegram 机器人令牌,并为每个配置文件启动一个网关。不要在多个正在运行的网关中重复使用同一个机器人令牌;Telegram 会拒绝同一令牌的并发轮询。
推荐的群组配置:
telegram:
require_mention: true
exclusive_bot_mentions: true
mention_patterns: []使用此设置,群组消息如 @research_bot @ops_bot summarize this 仅由 research_bot 和 ops_bot 处理。群组中的其他 Hermes 机器人保持静默,即使该消息是对它们之前某条消息的回复,或者本可能匹配共享的唤醒词。
仅在旧版群组中将 exclusive_bot_mentions: false 设置为 false,即当您希望显式提及不应覆盖回复和唤醒词触发器时。
要运行多个配置文件,请为每个配置文件运行一次网关命令。例如:
# 默认配置文件
hermes gateway start
hermes gateway status
hermes gateway stop
# 命名配置文件
hermes -p research gateway start
hermes -p research gateway status
hermes -p research gateway stop对于小型固定集群,使用 shell 循环或脚本,对默认配置文件调用 hermes gateway <action>,对每个命名配置文件调用 hermes -p <profile> gateway <action>。这比假设一个进程级命令能控制每个服务管理器上的每个命名配置文件更可靠。
故障排除:DM 正常但群组不工作
如果机器人在私聊中正常响应但在群组中保持静默,请按顺序检查以下环节:
- Telegram 投递: 关闭 BotFather 隐私模式,将机器人提升为管理员,或直接提及机器人。Hermes 无法响应 Telegram 从未投递给机器人的群组消息。
- 更改隐私后重新加入: 在更改 BotFather 隐私设置后,将机器人从群组中移除并重新添加。Telegram 可能对现有成员保留旧投递行为。
- Hermes 授权: 确保发送者在
TELEGRAM_ALLOWED_USERS或TELEGRAM_GROUP_ALLOWED_USERS中列出,或通过TELEGRAM_GROUP_ALLOWED_CHATS允许群组聊天。 - 提及过滤器: 如果设置了
telegram.require_mention: true,普通群组聊天会被忽略,除非消息是斜杠命令、回复机器人、@botusername提及或匹配配置的mention_patterns。 - 多机器人路由: 如果群组包含多个机器人,请确保每个 Hermes 配置文件使用唯一的机器人令牌,并保持
exclusive_bot_mentions启用,除非您有意使用旧版共享触发行为。
Telegram 群组和超级群组的聊天 ID 为负数。如果使用聊天范围授权,请将这些 ID 放入 TELEGRAM_GROUP_ALLOWED_CHATS,而非发送者用户白名单。
群组触发配置示例
将此添加到 ~/.hermes/config.yaml:
telegram:
require_mention: true
exclusive_bot_mentions: true
mention_patterns:
- "^\\s*chompy\\b"
ignored_threads:
- 31
- "42"此示例允许所有常用的直接触发器,以及以 chompy 开头的消息,即使它们不使用 @mention。
在提及和自由响应检查运行之前,Telegram 主题 31 和 42 中的消息总是被忽略。
关于 mention_patterns 的说明
- 模式使用 Python 正则表达式
- 匹配不区分大小写
- 模式同时检查文本消息和媒体说明文字
- 无效的正则表达式模式会被静默忽略(网关日志中会有警告),不会使机器人崩溃
- 如果您希望模式仅匹配消息开头,请使用
^锚定
私聊主题(Bot API 9.4)
Telegram Bot API 9.4(2026 年 2 月)引入了私聊主题(Private Chat Topics)——机器人可以在 1 对 1 DM 聊天中直接创建论坛风格的主题线程,无需超级群组。这让您可以在现有 DM 中与 Hermes 运行多个隔离的工作区。
使用场景
如果您同时处理多个长期项目,主题可以保持各自的上下文隔离:
- “网站”主题 — 处理您的生产 Web 服务
- “研究”主题 — 文献综述和论文探索
- “通用”主题 — 杂项任务和快速问答
每个主题拥有自己的对话会话、历史和上下文——完全与其他主题隔离。
配置
:::caution 先决条件 在将主题添加到配置之前,用户必须在与机器人的 DM 聊天中启用主题模式:
- 在 Telegram 中打开与 Hermes 机器人的私聊
- 点击顶部的机器人名称以打开聊天信息
- 启用主题(将聊天变为论坛的开关)
没有这一步,Hermes 会在启动时记录 The chat is not a forum 并跳过主题创建。这是 Telegram 客户端侧设置——机器人无法以编程方式启用。
:::
在 ~/.hermes/config.yaml 的 platforms.telegram.extra.dm_topics 下添加主题:
platforms:
telegram:
extra:
dm_topics:
- chat_id: 123456789 # 您的 Telegram 用户 ID
topics:
- name: 通用
icon_color: 7322096
- name: 网站
icon_color: 9367192
- name: 研究
icon_color: 16766590
skill: arxiv # 在此主题中自动加载技能字段:
| 字段 | 必需 | 描述 |
|---|---|---|
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} - 每个主题中的消息拥有自己的对话历史、内存刷新和上下文窗口
根 DM 处理
默认情况下,发送到根 DM(任何主题之外)的消息会被正常处理。设置 ignore_root_dm: true 将根 DM 变为大厅——对于配置了 DM 主题的用户,普通消息被静默忽略,而系统命令(/start、/help、/status 等)仍然有效。
platforms:
telegram:
extra:
ignore_root_dm: true
dm_topics:
- chat_id: 123456789
topics:
- name: 通用检查是按聊天进行的:只有至少有一条 dm_topics 记录的用户才会受到根 DM 影响。没有配置主题的用户不受影响。
技能绑定
带有 skill 字段的主题会在新会话开始时自动加载该技能。这就像在对话开始时输入 /skill-name——技能内容被注入到第一条消息中,后续消息可以在对话历史中看到它。
例如,带有 skill: arxiv 的主题在其会话重置时(由于空闲超时、每日重置或手动 /reset)会预加载 arxiv 技能。
:::tip
在配置之外创建的主题(例如通过手动调用 Telegram API)会在收到 forum_topic_created 服务消息时自动发现。您也可以在网关运行时向配置添加主题——它们会在下次缓存未命中时被拾取。
:::
多会话 DM 模式(/topic)
ChatGPT 风格的多会话 DM — 一个机器人,多个并行对话。与上面操作员策划的 extra.dm_topics 不同,此模式是用户驱动的:无需配置,无需预先声明的主题名称。最终用户通过 /topic 开启,然后点击 Telegram + 按钮创建任意数量的主题,每个都是一个完全独立的 Hermes 会话。
/topic 子命令
| 形式 | 上下文 | 效果 |
|---|---|---|
/topic | 根 DM,尚未启用 | 检查 BotFather 功能,启用多会话模式,创建置顶的系统主题 |
/topic | 根 DM,已启用 | 显示状态:可恢复的未链接会话列表 |
/topic | 主题内部 | 显示当前主题的会话绑定 |
/topic help | 任意 | 内联用法说明 |
/topic off | 根 DM | 禁用多会话模式并清除此聊天的所有主题绑定 |
/topic <session-id> | 主题内部 | 将之前的 Telegram 会话恢复到当前主题 |
只有授权用户(通过 TELEGRAM_ALLOWED_USERS / 平台认证配置的白名单)可以运行 /topic。未授权的发送者会收到拒绝而非激活。
DM 主题 vs 多会话 DM 模式
extra.dm_topics(配置驱动) | /topic(用户驱动) | |
|---|---|---|
| 谁激活 | 操作员,在 config.yaml 中 | 最终用户,通过发送 /topic |
| 主题列表 | 配置中声明的固定集合 | 用户自由创建/删除主题 |
| 主题名称 | 由操作员选择 | 由用户选择;自动重命名以匹配 Hermes 会话标题 |
| 根 DM 行为 | 正常聊天(如果 ignore_root_dm: true 则为大厅) | 成为系统大厅(非命令消息被拒绝) |
| 主要用例 | 带有可选技能绑定的永久工作区 | 临时并行会话 |
| 持久化 | extra.dm_topics 在 config 中 | telegram_dm_topic_mode + telegram_dm_topic_bindings SQLite 表 |
这两个功能可以在同一机器人上共存——您可以从用户的 DM 运行 /topic,同时 extra.dm_topics 继续为其他聊天管理操作员声明的主题。
先决条件
在 @BotFather 中,打开您的机器人 → Bot Settings → Threads Settings:
- 打开线程模式(启用
has_topics_enabled) - 不要禁用用户创建主题(保持
allows_users_to_create_topics开启)
当用户首次运行 /topic 时,Hermes 调用 getMe 验证两个标志。如果任何一个关闭,Hermes 会发送 BotFather 线程设置页面的截图并解释需要切换什么——在满足先决条件之前不会进行激活。
激活流程
从根 DM 发送:
/topic
Hermes 将:
- 检查
getMe().has_topics_enabled和allows_users_to_create_topics - 如果两者都为 true,为此 DM 启用多会话主题模式
- 创建并置顶一个系统主题用于状态/命令(尽力而为)
- 回复用户之前未链接的 Telegram 会话列表,供用户恢复
激活后,根 DM 成为大厅:普通提示被拒绝,并附带指向所有消息的指引。系统命令(/status、/sessions、/usage、/help 等)在根 DM 中仍然有效。
创建新主题(最终用户流程)
- 在 Telegram 中打开机器人 DM
- 点击机器人界面顶部的所有消息,然后发送任何消息
- Telegram 为该消息创建一个新主题
- Hermes 在该主题内回复 — 该主题现在是一个独立会话
每个主题都有自己的对话历史、模型状态、工具执行和会话 ID。隔离键为 agent:main:telegram:dm:{chat_id}:{thread_id}——与配置驱动 DM 主题的隔离方式相同。
自动重命名主题
当 Hermes 为主题生成会话标题时(通过自动标题管道,在第一次交流之后),Telegram 主题本身会被重命名以匹配——例如”新主题”变成”数据库迁移计划”。重命名是尽力而为的:失败会被记录,但不会中断会话。
要禁用此功能并保持您手动选择的主题名称不变,请设置:
gateway:
platforms:
telegram:
extra:
disable_topic_auto_rename: true当此标志开启时,Hermes 仍然会生成内部会话标题(供 hermes sessions、TUI 等使用),但永远不会编辑 Telegram 主题名称。当您手动在 BotFather 线程模式下组织主题,且不希望每次首次回复都覆盖标题时,此功能很有用。
主题内的 /new
重置当前主题的会话(新会话 ID,清空历史),不影响其他主题。Hermes 会回复提醒:对于并行工作,通过所有消息创建另一个主题通常是您想要的。
恢复之前的会话
在主题内发送:
/topic <session-id>
这会将当前主题绑定到现有 Hermes 会话,而不是从头开始。对于在启用主题模式之前开始的对话,此功能很有用。限制:
- 目标会话必须属于同一 Telegram 用户
- 目标会话不得已绑定到另一个主题
Hermes 确认会话标题并重放最后一条助手消息以提供上下文。
要发现会话 ID,在根 DM 中发送 /topic(不加参数)——Hermes 列出用户的未链接 Telegram 会话。
主题内的 /topic(无参数)
显示当前主题的绑定:会话标题、会话 ID,以及 /new 与创建另一个主题的提示。
底层实现
- 激活持久化到
state.db中的telegram_dm_topic_mode(chat_id, user_id, enabled, ...) - 每个主题绑定持久化到
telegram_dm_topic_bindings(chat_id, thread_id, session_id, ...),带有ON DELETE CASCADE作用于session_id——清理会话会自动清除其主题绑定 - 主题模式的 SQLite 迁移是选择加入的:它在首次调用
/topic时运行,从不在网关启动时运行。直到用户在此配置文件中运行/topic前,state.db保持不变 - 每个入站 DM 消息查找其
(chat_id, thread_id)绑定。如果存在,查找通过SessionStore.switch_session()将消息路由到绑定的会话,使会话键到会话 ID 的映射在磁盘上保持一致 - 主题内的
/new重写绑定行,指向新的会话 ID,因此下一条消息停留在新会话上 - 在
extra.dm_topics中声明的主题永远不会被自动重命名——即使启用了多会话模式,操作员选择的名称也会被保留 - 设置
extra.disable_topic_auto_rename: true可关闭聊天中所有主题的自动重命名(包括通过线程模式创建的临时主题) - 启用论坛的 DM 中的 General(置顶顶部)主题被视为根大厅,无论 Telegram 是以
message_thread_id=1还是无 thread_id 投递其消息 - 根大厅提醒每个聊天每 30 秒限制一条消息——忘记主题模式已开启并在根中输入了十条提示的用户不会收到十条回复
- BotFather 设置截图每个聊天每 5 分钟限制发送一次——当线程设置仍然禁用时重复尝试
/topic不会重新上传相同的图片 - 在主题内启动的
/background <prompt>将其结果投递回同一主题;后台会话不会触发所属主题的自动重命名 /topic本身受限于机器人的用户授权检查——未授权的 DM 会收到拒绝而非激活
禁用多会话模式
在根 DM 中发送 /topic off。Hermes 关闭该行,清除聊天的 (thread_id → session_id) 绑定,根 DM 恢复为普通 Hermes 聊天。Telegram 中现有的主题不会被删除——它们只是不再作为独立会话进行门控。稍后重新运行 /topic 可重新开启。
如果您需要手动清理(例如跨多个聊天的大规模重置),直接删除行:
sqlite3 ~/.hermes/state.db \
"UPDATE telegram_dm_topic_mode SET enabled = 0 WHERE chat_id = '<your_chat_id>'; \
DELETE FROM telegram_dm_topic_bindings WHERE chat_id = '<your_chat_id>';"降级 Hermes
如果您降级到 /topic 之前的 Hermes 版本,该功能只是停止工作——telegram_dm_topic_mode 和 telegram_dm_topic_bindings 表保留在 state.db 中,但被旧代码忽略。DM 恢复到原生按线程隔离(每个 message_thread_id 仍然通过 build_session_key 获得自己的会话),因此您现有的 Telegram 主题仍然可以作为并行会话工作。根 DM 不再是大厅——那里的消息像以前一样进入 agent。重新升级会精确地重新激活多会话模式。
群组论坛主题技能绑定
启用了主题模式(也称为”论坛主题”)的超级群组已经为每个主题提供了会话隔离——每个 thread_id 映射到自己的对话。但您可能希望在消息到达特定群组主题时自动加载一个技能,就像 DM 主题技能绑定一样。
使用场景
一个有论坛主题的团队超级群组,用于不同工作流:
- 工程主题 → 自动加载
software-development技能 - 研究主题 → 自动加载
arxiv技能 - 通用主题 → 无技能,通用助手
配置
在 ~/.hermes/config.yaml 的 platforms.telegram.extra.group_topics 下添加主题绑定:
platforms:
telegram:
extra:
group_topics:
- chat_id: -1001234567890 # 超级群组 ID
topics:
- name: 工程
thread_id: 5
skill: software-development
- name: 研究
thread_id: 12
skill: arxiv
- name: 通用
thread_id: 1
# 无技能 — 通用用途字段:
| 字段 | 必需 | 描述 |
|---|---|---|
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字段,该技能会被自动加载到会话中——与 DM 主题技能绑定相同 - 没有
skill键的主题仅获得会话隔离(现有行为,不变) - 未映射的
thread_id值或chat_id值静默通过——无错误,无技能
与 DM 主题的区别
| DM 主题 | 群组主题 | |
|---|---|---|
| 配置键 | extra.dm_topics | extra.group_topics |
| 主题创建 | 如果 thread_id 缺失,Hermes 通过 API 创建主题 | 管理员在 Telegram UI 中创建主题 |
thread_id | 创建后自动填充 | 必须手动设置 |
icon_color / icon_custom_emoji_id | 支持 | 不适用(管理员控制外观) |
| 技能绑定 | ✓ | ✓ |
| 会话隔离 | ✓ | ✓(论坛主题已内置支持) |
:::tip
要查找主题的 thread_id,在 Telegram Web 或桌面版中打开主题,查看 URL:https://t.me/c/1234567890/5 — 最后的数字(5)就是 thread_id。超级群组的 chat_id 是群组 ID 加前缀 -100(例如群组 1234567890 变为 -1001234567890)。
:::
近期 Bot API 功能
- Bot API 9.4(2026 年 2 月): 私聊主题 — 机器人可以通过
createForumTopic在 1 对 1 DM 聊天中创建论坛主题。Hermes 将其用于两个不同的功能:操作员策划的私聊主题(配置驱动,固定主题列表)和用户驱动的多会话 DM 模式(通过/topic激活,无限用户创建的主题)。 - 隐私政策: Telegram 现在要求机器人拥有隐私政策。通过 BotFather 使用
/setprivacy_policy设置,否则 Telegram 可能会自动生成占位内容。如果您的机器人面向公众,这一点尤为重要。 - Bot API 9.5(2026 年 3 月): 通过
sendMessageDraft实现原生流式传输。Hermes 支持 Telegram 的原生流式草稿 API,作为私聊的选择加入传输方式。默认保持传统的editMessageText路径,因为草稿预览在某些 Telegram 客户端上可能会折叠和重新渲染。
流式传输方式(gateway.streaming.transport)
当流式传输启用时(gateway.streaming.enabled: true),Hermes 选择四种传输方式之一:
| 值 | 行为 |
|---|---|
auto | 在支持的聊天中(目前为 Telegram DM)使用原生草稿流式传输;否则使用传统的基于编辑的路径。如果草稿帧失败,优雅回退。 |
draft | 强制使用原生草稿。如果聊天不支持草稿(例如群组/主题),会记录降级并回退到编辑。 |
edit(默认) | 对所有聊天类型使用传统的渐进式 editMessageText 轮询。 |
off | 完全禁用流式传输(仅最终回复,无渐进更新)。 |
在 ~/.hermes/config.yaml 中:
gateway:
streaming:
enabled: true
transport: edit # edit | auto | draft | off使用 edit(默认)在 DM 中看到的效果 — 网关发送一条普通预览消息,并通过 editMessageText 逐步更新它,避免了 Telegram 草稿预览的折叠/回滚效果。
使用 auto 或 draft 在 DM 中看到的效果 — Telegram 显示一个逐 token 更新的动画草稿预览。回复完成时,作为普通消息投递,草稿预览在客户端自然清除。草稿没有消息 ID,因此最终答案会保留在您的聊天历史中。
群组、超级群组、论坛主题呢? Telegram 将 sendMessageDraft 限制为私聊(DM)。网关对所有其他类型透明地回退到基于编辑的路径——与之前相同的用户体验。
如果草稿帧失败怎么办? 任何失败(临时网络错误、服务端拒绝、较旧的 python-telegram-bot 安装)都会将该回复切换到基于编辑的路径,用于流的剩余部分。下一条回复会重新尝试。
渲染:表格和链接预览
Telegram 的 MarkdownV2 没有原生表格语法——如果直接传递,管道表格会渲染为反斜杠转义的乱码。Hermes 会自动规范化 markdown 表格:
- 小表格被展平为行分组项目符号——每行在列标题下变成可读的项目符号列表。适用于 2–4 列和短单元格。
- 较大或较宽的表格回退到围栏代码块,对齐列,确保不折叠。添加一行提示提示,使 agent 知道在 Telegram 上更喜欢散文后续而非更多表格。
无需配置——适配器会为每条消息选择正确的回退方式。如果您想要传统的”始终使用代码块”行为,请在 config.yaml 中设置 telegram.pretty_tables: false 禁用表格规范化(默认:true)。
链接预览。 Telegram 会自动为机器人消息中的 URL 生成链接预览。如果您想抑制这些预览(长 /tools 输出、agent 回复中提及十个链接等):
gateway:
platforms:
telegram:
extra:
disable_link_previews: true启用后,Hermes 会为每条出站消息附加 Telegram 的 LinkPreviewOptions(is_disabled=True),并在较旧的 python-telegram-bot 版本上回退到传统的 disable_web_page_preview 参数。
群组白名单
Telegram 群组和论坛聊天有两个您可配置的正交闸门:
- 发送者用户 ID(
group_allow_from/TELEGRAM_GROUP_ALLOWED_USERS)— 仅适用于群组/论坛消息的发送者范围白名单。当您希望特定用户能在群组中调用机器人,但不想将他们添加到TELEGRAM_ALLOWED_USERS(也会授予 DM 访问权限)时使用。 - 聊天 ID(
group_allowed_chats/TELEGRAM_GROUP_ALLOWED_CHATS)— 聊天范围白名单。这些群组/论坛的任何成员都可以与机器人交互。适用于团队/支持机器人,其中群组成员身份本身就是访问信号。
gateway:
platforms:
telegram:
extra:
# 全局访问(DM + 群组)。这些用户可以随时调用机器人。
allow_from:
- "123456789"
# 仅在群组/论坛中允许的发送者 ID。不授予 DM 访问权限。
group_allow_from:
- "987654321"
# 整个群组/论坛 — 任何成员均被授权。
group_allowed_chats:
- "-1001234567890"等效环境变量:
TELEGRAM_ALLOWED_USERS="123456789"
TELEGRAM_GROUP_ALLOWED_USERS="987654321"
TELEGRAM_GROUP_ALLOWED_CHATS="-1001234567890"行为:
TELEGRAM_ALLOWED_USERS覆盖所有聊天类型(DM、群组、论坛)。TELEGRAM_GROUP_ALLOWED_USERS仅在群组/论坛中授权列出的发送者。除非在TELEGRAM_ALLOWED_USERS中列出,否则他们仍然无法 DM 机器人。TELEGRAM_GROUP_ALLOWED_CHATS中的聊天授权该聊天的每个成员,无论发送者是谁。- 在上述任何一个中使用
*来允许任何发送者/聊天。 - 这叠加在现有的提及/模式触发器和
group_topics+ignored_threads之上。
从 PR #17686 之前的版本迁移
在此分拆之前,TELEGRAM_GROUP_ALLOWED_USERS 是唯一的控制项,用户会将聊天 ID 放入其中。为向后兼容,TELEGRAM_GROUP_ALLOWED_USERS 中以聊天 ID 形式的值(以 - 开头)仍然会作为聊天 ID 被识别,并记录一次弃用警告。迁移:
# 旧方式(仍然有效,但已弃用)
TELEGRAM_GROUP_ALLOWED_USERS="-1001234567890"
# 新方式
TELEGRAM_GROUP_ALLOWED_CHATS="-1001234567890"访客 @mention 绕过(guest_mode)
在典型设置中,group_allowed_chats 是一个硬闸门:来自列表外群组的消息被静默丢弃,即使成员显式 @提及机器人。这对于支持/团队机器人是正确的默认设置。
对于更休闲的设置——朋友群聊中您希望机器人大部分时间静默但在显式 @ 时偶尔可用——启用 guest_mode:
gateway:
platforms:
telegram:
extra:
group_allowed_chats:
- "-1001234567890" # 您的主要白名单群组
guest_mode: true # 非白名单群组:仅允许 @mention环境变量等效:
TELEGRAM_GUEST_MODE=true默认值:false。
使用 guest_mode: true 时,来自非白名单群组的消息仅当显式 @提及机器人时才会被处理。每次轮次都需要提及——访客交互没有会话粘性,因此机器人永远不会在没有被 @的情况下自动参与朋友群组的线程中。
DM 和白名单群组的行为与之前完全相同。
斜杠命令访问控制
默认情况下,每个被允许的用户可以运行所有斜杠命令。要将您的白名单拆分为管理员(完全斜杠命令访问权限)和普通用户(仅限您显式启用的命令),请在平台的 extra 块中添加 allow_admin_from 和 user_allowed_commands:
gateway:
platforms:
telegram:
extra:
# 现有白名单(不变)
allow_from:
- "123456789" # 管理员
- "555555555" # 普通用户
- "777777777" # 普通用户
# 新增 — 管理员获得所有斜杠命令(内置 + 插件)
allow_admin_from:
- "123456789"
# 新增 — 非管理员允许用户只能运行这些斜杠命令。
# /help 和 /whoami 始终允许,以便用户查看其访问权限。
user_allowed_commands:
- status
- model
- history
# 可选:用于群组的独立管理员/命令列表
group_allow_admin_from:
- "123456789"
group_user_allowed_commands:
- status行为:
- 在某个作用域(DM 或群组)的
allow_admin_from中列出的用户可以通过实时注册表运行每个已注册的斜杠命令——内置命令和插件注册的命令。 - 在
allow_from中但不在allow_admin_from中的用户只能运行user_allowed_commands中列出的命令,加上始终允许的基础命令:/help和/whoami。 - 普通聊天(非斜杠消息)不受影响。非管理员用户仍然可以正常与 agent 对话,只是不能触发任意命令。
- 向后兼容: 如果某个作用域未设置
allow_admin_from,则该作用域的斜杠命令门控被禁用。现有安装无需更改即可继续工作。 - DM 管理员身份并不意味着群组管理员身份。每个作用域都有自己的管理员列表。
- 如果只设置了
group_allow_admin_from,DM 作用域保持在无限制(向后兼容)模式。
使用 /whoami 查看当前作用域、您的层级(管理员/用户/无限制)以及您可以运行的斜杠命令。
交互式模型选择器
当您在 Telegram 聊天中发送不带参数的 /model 时,Hermes 会显示一个交互式内联键盘用于切换模型:
- 提供商选择 — 按钮显示每个可用提供商及模型数量(例如 “OpenAI (15)”、”✓ Anthropic (12)” 表示当前提供商)。
- 模型选择 — 分页模型列表,带有上一页/下一页导航、返回提供商的返回按钮和取消。
当前模型和提供商显示在顶部。所有导航通过原地编辑同一条消息完成(无聊天杂乱)。
:::tip
如果您知道确切的模型名称,直接输入 /model <name> 跳过选择器。您也可以输入 /model <name> --global 使更改跨会话持久化。
:::
DNS-over-HTTPS 回退 IP
在某些受限网络中,api.telegram.org 可能解析为不可达的 IP。Telegram 适配器包含一个回退 IP 机制,可透明地重试连接替代 IP,同时保持正确的 TLS 主机名和 SNI。
工作原理
- 如果设置了
TELEGRAM_FALLBACK_IPS,则直接使用这些 IP。 - 否则,适配器自动通过 DNS-over-HTTPS(DoH)查询 Google DNS 和 Cloudflare DNS,以发现
api.telegram.org的替代 IP。 - DoH 返回的 IP 中与系统 DNS 结果不同的作为回退使用。
- 如果 DoH 也被阻止,使用硬编码的种子 IP(
149.154.167.220)作为最后手段。 - 一旦回退 IP 成功,它会变得”粘性”——后续请求直接使用它,无需先重试主路径。
配置
# 显式回退 IP(逗号分隔)
TELEGRAM_FALLBACK_IPS=149.154.167.220,149.154.167.221或在 ~/.hermes/config.yaml 中:
platforms:
telegram:
extra:
fallback_ips:
- "149.154.167.220":::tip
您通常不需要手动配置此项。通过 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 配置——如果设置了环境变量,它会被自动使用。
:::note
这涵盖了 Hermes 用于 Telegram 连接的自定义回退传输层。其他地方使用的标准 httpx 客户端已原生尊重代理环境变量。
:::
消息反应
机器人可以向消息添加表情反应,作为视觉处理反馈:
- 👀 当机器人开始处理您的消息时
- ✅ 当响应成功投递时
- ❌ 如果处理过程中发生错误
反应默认禁用。在 config.yaml 中启用:
telegram:
reactions: true或通过环境变量:
TELEGRAM_REACTIONS=true:::note 与 Discord(反应是累加的)不同,Telegram 的 Bot API 在单次调用中替换所有机器人反应。从 👀 到 ✅/❌ 的切换是原子性的——您不会同时看到两者。 :::
:::tip 如果机器人没有权限在群组中添加反应,反应调用会静默失败,消息处理正常继续。 :::
每频道提示
为特定的 Telegram 群组或论坛主题分配临时系统提示。提示在每轮运行时注入——从不持久化到会话历史——因此更改立即生效。
telegram:
channel_prompts:
"-1001234567890": |
你是一个研究助手。专注于学术来源、
引用和简洁的综合。
"42": |
此主题用于创意写作反馈。请温暖且
有建设性。键是聊天 ID(群组/超级群组)或论坛主题 ID。对于论坛群组,主题级提示会覆盖群组级提示:
- 群组
-1001234567890中主题42的消息 → 使用主题42的提示 - 主题
99中的消息(无显式条目)→ 回退到群组-1001234567890的提示 - 群组中无条目 → 不应用频道提示
数字 YAML 键会自动规范化为字符串。
故障排除
| 问题 | 解决方案 |
|---|---|
| 机器人完全不响应 | 验证 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 转换需要)。 |
| 机器人令牌已撤销/无效 | 在 BotFather 中通过 /revoke 然后 /newbot 或 /token 生成新令牌。更新您的 .env 文件。 |
| Webhook 未接收更新 | 验证 TELEGRAM_WEBHOOK_URL 可公开访问(使用 curl 测试)。确保您的平台/反向代理将来自 URL 端口的入站 HTTPS 流量路由到 TELEGRAM_WEBHOOK_PORT 配置的本地监听端口(它们不必是相同数字)。确保 SSL/TLS 已启用——Telegram 仅发送到 HTTPS URL。检查防火墙规则。 |
执行审批
当 agent 尝试运行潜在危险命令时,它会在聊天中请求您的批准:
⚠️ 此命令有潜在危险(递归删除)。回复”yes”以批准。
回复 “yes”/“y” 以批准,或 “no”/“n” 以拒绝。
交互式提示(clarify)
当 agent 调用 clarify 工具时——询问您偏好的方法、获取任务后反馈或在非平凡决策前检查——Telegram 会使用内联键盘按钮渲染问题:
❓ 我应该为仪表板使用哪个框架?
[1. Next.js] [2. Remix] [3. Astro] [✏️ 其他(输入答案)]
点击按钮回答,或点击其他输入自由格式的回复(您发送的下一条消息成为答案)。开放式的 clarify 调用(无预设选项)跳过按钮,直接捕获您的下一条消息。
通过 ~/.hermes/config.yaml 中的 agent.clarify_timeout 配置响应超时(默认 600 秒)。如果您在超时内未回复,agent 会发送一个哨兵消息并适应,而不是挂起。
推送通知音量
Telegram 对机器人发送的每条消息触发推送通知。对于长时间 agent 轮次,工具进度气泡、流式更新和状态回调会快速变得嘈杂。Telegram 适配器有两种通知模式:
| 模式 | 行为 |
|---|---|
important(默认) | 仅最终回复、审批提示和斜杠命令确认响铃。工具进度、流式块和状态消息以 disable_notification=true 投递。 |
all | 每条出站消息触发推送通知。旧版行为;如果您确实想听到每个工具调用,请选择加入。 |
在 ~/.hermes/config.yaml 中配置:
display:
platforms:
telegram:
notifications: important # 或 "all"环境变量覆盖(便于快速 A/B 测试):
HERMES_TELEGRAM_NOTIFICATIONS=all未知值记录警告并回退到 important。
安全性
:::warning
始终设置 TELEGRAM_ALLOWED_USERS 以限制可与您的机器人交互的用户。否则,网关默认拒绝所有用户作为安全措施。
:::
切勿公开分享您的机器人令牌。如果泄露,请立即通过 BotFather 的 /revoke 命令撤销。