字节笔记本
2026年6月21日
hermes教程-Telegram
Telegram 设置
Hermes Agent 与 Telegram 集成,作为一个全功能对话机器人。连接后,您可以从任何设备与您的代理聊天,发送自动转写的语音备忘录,接收定时任务结果,并在群聊中使用代理。该集成基于 python-telegram-bot,支持文本、语音、图像和文件附件。
步骤 1:通过 BotFather 创建机器人
每个 Telegram 机器人需要一个由 @BotFather(Telegram 官方机器人管理工具)颁发的 API 令牌。
- 打开 Telegram 并搜索 @BotFather,或访问 t.me/BotFather
- 发送
/newbot - 选择一个显示名称(例如 "Hermes Agent")——可以是任何内容
- 选择一个用户名——必须唯一且以
bot结尾(例如my_hermes_bot) - BotFather 回复您的 API 令牌。它看起来像这样:
123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
警告
请保密您的机器人令牌。任何拥有此令牌的人都可以控制您的机器人。如果泄露,请立即通过 BotFather 的
/revoke命令撤销它。
步骤 2:自定义您的机器人(可选)
以下 BotFather 命令可改善用户体验。向 @BotFather 发送消息并使用:
| 命令 | 用途 |
|---|---|
/setdescription | 用户开始聊天前显示的“这个机器人能做什么?”文本 |
/setabouttext | 机器人个人资料页面上的简短文本 |
/setuserpic | 为您的机器人上传头像 |
/setcommands | 定义命令菜单(聊天中的 / 按钮) |
/setprivacy | 控制机器人是否能看到所有群组消息(参见步骤 3) |
提示
对于
/setcommands,一个有用的初始设置:texthelp - 显示帮助信息 new - 开始新对话 sethome - 将此聊天设为主频道
步骤 3:隐私模式(对群组至关重要)
Telegram 机器人有一个隐私模式,默认启用。这是在群组中使用机器人时最常见的困惑来源。
开启隐私模式时,您的机器人只能看到:
- 以
/命令开头的消息 - 直接回复机器人自己消息的消息
- 服务消息(成员加入/离开、置顶消息等)
- 机器人作为管理员的频道中的消息
关闭隐私模式时,机器人会收到群组中的每条消息。
如何关闭隐私模式
- 向 @BotFather 发送消息
- 发送
/mybots - 选择您的机器人
- 进入 Bot Settings → Group Privacy → Turn off
警告
更改隐私设置后,您必须将机器人从任何群组中移除并重新添加。 Telegram 在机器人加入群组时会缓存隐私状态,并且在机器人被移除并重新添加之前不会更新。
提示
关闭隐私模式的替代方案:将机器人提升为群组管理员。管理员机器人无论隐私设置如何,始终接收所有消息,这避免了切换全局隐私模式的需要。
观察群组聊天而不自动回复
对于 OpenClaw/Yuanbao 风格的群组行为,配置 Telegram 使机器人能够看到普通群组消息,但仅在直接触发时响应:
telegram:
allowed_chats:
- "-1001234567890"
group_allowed_chats:
- "-1001234567890"
require_mention: true
observe_unmentioned_group_messages: true启用此模式后,来自明确允许列表的聊天/主题的未提及群组消息会作为观察到的上下文附加到共享的聊天/主题会话记录中,但不会调度代理。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:/... 路径必须在运行网关的主机上可读。
常见陷阱:
- 代理在 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: 文件扩展名
网关从代理回复中提取 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、Feishu、Matrix 等)作为原生附件发送;在不支持原生附件的平台上,会回退为链接或纯文本指示。加粗类别是在最近几个版本中添加的——如果您之前依赖模型说“这是文件:/path/to/report.docx”,请改用 MEDIA:/path/to/report.docx 以实现原生发送。
Webhook 模式
默认情况下,Hermes 使用长轮询连接到 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 聊天(私聊或群组)中使用 /sethome 命令将其指定为主频道。定时任务(cron 作业)会将其结果发送到此频道。
您也可以在 ~/.hermes/.env 中手动设置:
TELEGRAM_HOME_CHANNEL=-1001234567890
TELEGRAM_HOME_CHANNEL_NAME="我的笔记"提示
群组聊天 ID 是负数(例如
-1001234567890)。您的个人私聊聊天 ID 与您的用户 ID 相同。
主题模式下的 Cron 投递
如果您在机器人私聊中启用了主题模式,发送到根聊天的 cron 消息会进入仅系统的大厅——在那里回复不会打开任何会话,您会看到“主聊天保留给系统命令”的通知。创建一个专门的论坛主题(例如 Cron)并设置:
TELEGRAM_CRON_THREAD_ID=<主题线程ID>TELEGRAM_CRON_THREAD_ID 会覆盖 TELEGRAM_HOME_CHANNEL_THREAD_ID,仅用于 cron 投递。该主题中的回复会继续该主题的现有会话。
语音消息
传入语音(语音转文字)
您在 Telegram 上发送的语音消息会自动由 Hermes 配置的 STT 提供商转写,并作为文本注入到对话中。
local使用运行 Hermes 的机器上的faster-whisper——无需 API 密钥groq使用 Groq Whisper,需要GROQ_API_KEYopenai使用 OpenAI Whisper,需要VOICE_TOOLS_OPENAI_KEY
跳过 STT:将原始音频文件传递给代理
如果您希望代理本身处理音频——用于说话人分离、自定义转写工具或仅归档录音——请在 ~/.hermes/config.yaml 中设置 stt.enabled: false:
stt:
enabled: false禁用 STT 后,网关仍会将语音/音频附件下载到 Hermes 的音频缓存中,但不会进行转写。代理会收到带有如下标记的消息:
[用户发送了一条语音消息:/home/<user>/.hermes/cache/audio/<hash>.ogg]
然后,您的工具或技能可以直接读取该路径(例如,将其交给本地说话人分离管道、更丰富的转写模型,或上传到长期存储)。文件扩展名反映了 Telegram 传递的原始格式(语音笔记为 .ogg,音频附件为 .mp3/.m4a/等)。
这与下面的本地 Bot API 服务器部分自然搭配,该部分将 Telegram 的 20MB getFile 上限提升到 2GB——当您要处理的录音超过几分钟时非常有用。
传出语音(文本转语音)
当代理通过 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警告 — 安全
本地 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 进程可读时才设置此项注意 — 使用
platforms.telegram.extra,而不是telegram.extra目前只有
platforms.<name>.extra形式会被深度合并到平台配置中。直接放在顶级telegram.extra块下的键会被静默丢弃。
当设置了 base_url 时,Hermes 会:
- 针对本地服务器构建 python-telegram-bot 客户端
- 自动将其内部文档/音频大小上限从 20 MB 提升到 2 GB
- 在“太大”错误消息中报告活动限制(
Maximum: 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 拥有。 - 不同的机器——机器人服务器在一台主机上运行(例如 NAS、单独的 VM),而 Hermes 在另一台上。服务器的数据目录必须与 Hermes 机器共享,且绝对路径相同(服务器报告的路径,通常是
/var/lib/telegram-bot-api)。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,原始音频文件的路径会进入代理的入站消息,供下游处理。
群聊使用
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,在这些群组中,显式提及不应覆盖回复和唤醒词触发器。
要操作多个配置文件,请为每个配置文件运行一次网关命令。例如:
## 默认配置文件
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>。这比假设一个单一的进程级命令可以在每个服务管理器上控制每个命名配置文件更可靠。
故障排除:在私聊中有效,但在群组中无效
如果机器人在私聊中响应,但在群组中保持静默,请按顺序检查这些关卡:
- 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启用,除非您有意想要旧版的共享触发器行为。
负聊天 ID 对于 Telegram 群组和超级群组是正常的。如果您使用聊天范围授权,请将这些 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 月)引入了私聊主题——机器人可以直接在 1 对 1 私聊中创建论坛风格的主题线程,无需超级群组。这使您可以在与 Hermes 的现有私聊中运行多个隔离的工作区。
使用场景
如果您从事多个长期项目,主题可以保持它们的上下文分离:
- 主题“网站”——处理您的生产 Web 服务
- 主题“研究”——文献综述和论文探索
- 主题“通用”——杂项任务和快速问题
每个主题都有自己的对话会话、历史记录和上下文——完全相互隔离。
配置
注意 — 先决条件
在将主题添加到配置之前,用户必须在机器人的私聊中启用主题模式:
- 在 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} - 每个主题中的消息都有自己的对话历史、内存刷新和上下文窗口
根私聊处理
默认情况下,发送到根私聊(在任何主题之外)的消息会被正常处理。设置 ignore_root_dm: true 将根私聊变为大厅——对于配置了私聊主题的用户,普通消息会被静默忽略,而系统命令(/start、/help、/status 等)仍然有效。
platforms:
telegram:
extra:
ignore_root_dm: true
dm_topics:
- chat_id: 123456789
topics:
- name: 通用检查是按聊天进行的:只有那些在 dm_topics 中至少有一个条目的用户,其根私聊才会受到影响。没有配置主题的用户不受影响。
技能绑定
带有 skill 字段的主题会在该主题中启动新会话时自动加载该技能。这就像在对话开始时输入 /skill-name 一样——技能内容被注入到第一条消息中,后续消息会在对话历史中看到它。
例如,一个带有 skill: arxiv 的主题,在其会话重置时(由于空闲超时、每日重置或手动 /reset),会预加载 arxiv 技能。
提示
在配置之外创建的主题(例如,通过手动调用 Telegram API)会在
forum_topic_created服务消息到达时自动发现。您也可以在网关运行时将主题添加到配置中——它们会在下一次缓存未命中时被拾取。
多会话私聊模式(/topic)
一个类似 ChatGPT 的多会话私聊——一个机器人,多个并行对话。与上面由操作员管理的 extra.dm_topics 不同,此模式是用户驱动的:无需配置,无需预先声明的主题名称。最终用户通过 /topic 开启它,然后点击 Telegram 的 + 按钮创建任意数量的主题,每个主题都是一个完全独立的 Hermes 会话。
/topic 子命令
| 形式 | 上下文 | 效果 |
|---|---|---|
/topic | 根私聊,尚未启用 | 检查 BotFather 能力,启用多会话模式,创建固定的系统主题 |
/topic | 根私聊,已启用 | 显示状态:可用于恢复的未链接会话 |
/topic | 在主题内 | 显示当前主题的会话绑定 |
/topic help | 任何 | 内联用法 |
/topic off | 根私聊 | 禁用多会话模式并清除此聊天的所有主题绑定 |
/topic <session-id> | 在主题内 | 将之前的 Telegram 会话恢复到当前主题 |
只有授权用户(通过 TELEGRAM_ALLOWED_USERS / 平台身份验证配置的允许列表)才能运行 /topic。未授权的发送者会收到拒绝,而不是激活。
私聊主题 vs 多会话私聊模式
extra.dm_topics(配置驱动) | /topic(用户驱动) | |
|---|---|---|
| 谁激活 | 操作员,在 config.yaml 中 | 最终用户,通过发送 /topic |
| 主题列表 | 配置中声明的固定集合 | 用户自由创建/删除主题 |
| 主题名称 | 由操作员选择 | 由用户选择;自动重命名以匹配 Hermes 会话标题 |
| 根私聊行为 | 正常聊天(如果 ignore_root_dm: true 则为大厅) | 成为系统大厅(非命令消息被拒绝) |
| 主要用例 | 带有可选技能绑定的永久工作区 | 临时并行会话 |
| 持久性 | 配置中的 extra.dm_topics | telegram_dm_topic_mode + telegram_dm_topic_bindings SQLite 表 |
这两个功能可以在同一个机器人上共存——您可以从用户的私聊中运行 /topic,而 extra.dm_topics 继续为其他聊天管理操作员声明的主题。
先决条件
在 @BotFather 中,打开您的机器人 → Bot Settings → Threads Settings:
- 打开线程模式(启用
has_topics_enabled) - 不要禁用用户创建主题(保持
allows_users_to_create_topics开启)
当用户首次运行 /topic 时,Hermes 会调用 getMe 来验证这两个标志。如果任何一个关闭,Hermes 会发送 BotFather 线程设置页面的截图,并解释要切换什么——在满足先决条件之前不会激活。
激活流程
从根私聊发送:
/topic
Hermes 将:
- 检查
getMe().has_topics_enabled和allows_users_to_create_topics - 如果两者都为真,则为此私聊启用多会话主题模式
- 创建并固定一个系统主题,用于状态/命令(尽力而为)
- 回复一个列表,列出用户可以恢复的之前未链接的 Telegram 会话
激活后,根私聊是一个大厅:普通提示会被拒绝,并给出指向所有消息的指导。系统命令(/status、/sessions、/usage、/help 等)在根私聊中仍然有效。
创建新主题(最终用户流程)
- 在 Telegram 中打开机器人私聊
- 点击机器人界面顶部的所有消息,然后发送任何消息
- Telegram 会为该消息创建一个新主题
- Hermes 在该主题内响应——该主题现在是一个独立的会话
每个主题都有自己的对话历史、模型状态、工具执行和会话 ID。隔离键是 agent:main:telegram:dm:{chat_id}:{thread_id}——与配置驱动的私聊主题隔离相同。
自动重命名主题
当 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,请在根私聊中发送 /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, ...),并在session_id上设置ON DELETE CASCADE——修剪会话会自动清除其主题绑定 - 主题模式 SQLite 迁移是选择加入的:它在第一次调用
/topic时运行,而不是在网关启动时。直到用户在此配置文件中运行/topic之前,state.db保持不变 - 每个入站私聊消息都会查找其
(chat_id, thread_id)绑定。如果存在,查找会通过SessionStore.switch_session()将消息路由到绑定的会话,以便会话键到会话 ID 的映射在磁盘上保持一致 - 主题内的
/new会重写绑定行,指向新的会话 ID,以便下一条消息保持在新的会话上 - 在
extra.dm_topics中声明的主题永远不会自动重命名——即使启用了多会话模式,操作员选择的名称也会保留 - 设置
extra.disable_topic_auto_rename: true可以关闭聊天中所有主题的自动重命名(包括通过线程模式创建的临时主题) - 在启用论坛的私聊中,固定的顶部通用主题被视为根大厅,无论 Telegram 是以
message_thread_id=1还是无 thread_id 传递其消息 - 根大厅提醒每聊天每 30 秒限速一次——忘记主题模式已开启并在根私聊中输入十个提示的用户不会收到十个回复
- BotFather 设置截图每聊天每 5 分钟限速一次——在线程设置仍然禁用时重复尝试
/topic不会重新上传同一张图片 - 在主题内启动的
/background <prompt>会将其结果投递回同一主题;后台会话不会触发所属主题的自动重命名 /topic本身受机器人用户授权检查的限制——未授权的私聊会收到拒绝,而不是激活
禁用多会话模式
在根私聊中发送 /topic off。Hermes 会关闭该行,清除聊天的 (thread_id → session_id) 绑定,根私聊恢复为正常的 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 中,但会被旧代码忽略。私聊会恢复为原生每线程隔离(每个 message_thread_id 仍然通过 build_session_key 获得自己的会话),因此您现有的 Telegram 主题会继续作为并行会话工作。根私聊不再是大厅——那里的消息会像以前一样进入代理。重新升级会精确地重新激活多会话模式。
群组论坛主题技能绑定
启用了主题模式的超级群组(也称为“论坛主题”)已经实现了每个主题的会话隔离——每个 thread_id 映射到自己的对话。但您可能希望在特定群组主题的消息到达时自动加载技能,就像私聊主题技能绑定一样。
使用场景
一个团队超级群组,包含不同工作流的论坛主题:
- 工程主题 → 自动加载
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字段,该技能会自动加载到会话中——与私聊主题技能绑定相同 - 没有
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——最后一个数字(5)就是thread_id。超级群组的chat_id是群组 ID 加上-100前缀(例如,群组1234567890变为-1001234567890)。
最近的 Bot API 功能
- Bot API 9.4(2026 年 2 月): 私聊主题——机器人可以通过
createForumTopic在 1 对 1 私聊中创建论坛主题。Hermes 使用此功能实现两个不同的特性:操作员管理的私聊主题(配置驱动,固定主题列表)和用户驱动的多会话私聊模式(通过/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 私聊)上使用原生草稿流式传输;否则使用传统的基于编辑的路径。如果草稿帧失败,会优雅回退。 |
draft | 强制使用原生草稿。如果聊天不支持草稿(例如群组/主题),会记录降级并回退到编辑。 |
edit | 对所有聊天类型使用传统的渐进式 editMessageText 轮询。 |
off | 完全禁用流式传输(仅最终回复,无渐进更新)。 |
在 ~/.hermes/config.yaml 中:
gateway:
streaming:
enabled: true
transport: auto # auto | draft | edit | off使用 edit(默认)时在私聊中看到的效果——网关会发送一条普通的预览消息,并通过 editMessageText 逐步更新它,避免了 Telegram 的草稿预览折叠/回滚效果。
使用 auto 或 draft 时在私聊中看到的效果——Telegram 会显示一个动画草稿预览,逐令牌更新。当回复完成时,它会作为普通消息投递,草稿预览会在客户端上自然清除。草稿没有消息 ID,因此最终答案会保留在您的聊天历史中。
群组、超级群组、论坛主题呢? Telegram 将 sendMessageDraft 限制为私聊。网关会透明地回退到基于编辑的路径来处理其他所有情况——与以前相同的用户体验。
如果草稿帧失败怎么办? 任何失败(临时网络错误、服务器端拒绝、较旧的 python-telegram-bot 安装)都会将该响应切换回基于编辑的路径,用于流的其余部分。下一次响应会重新尝试。
渲染:富消息、表格和链接预览
富消息(Bot API 10.1)。 包含传统 MarkdownV2 路径会降级的结构(表格、任务列表、可折叠的 <details> 和块级数学公式)的最终回复,会使用代理的原始 markdown 通过 Telegram 的原生 sendRichMessage 发送,因此它们会原生渲染,没有客户端扁平化。在流式传输期间,最终答案通过 editMessageText 的 rich_message 参数就地编辑现有预览来投递——没有第二条消息,没有删除,因此在一轮结束时没有重复投递的闪烁。在私聊中,实时流式传输预览也使用 sendRichMessageDraft,因此动画草稿与最终的富消息匹配。普通回复(纯散文、粗体/斜体、简单列表)会保留在 MarkdownV2 路径上,以保持跨客户端的字体粗细和间距一致。
当内容超过 32,768 字符的富文本限制时,富路径会自动跳过,任何来自 Telegram 的拒绝(不支持的端点、解析器错误、过大的块/列)都会透明地回退到 MarkdownV2 路径——您的消息永远不会丢失。临时/网络错误不会静默重新发送(没有重复的最终消息)。
MarkdownV2 回退。 当富路径不可用时,Hermes 会将 markdown 转换为 MarkdownV2。由于 MarkdownV2 没有原生表格语法,管道表格会被规范化:
- 小表格被扁平化为行组项目符号——每一行在列标题下变成一个可读的项目符号列表。适用于 2-4 列和短单元格。
- 较大或较宽的表格回退到带有对齐列的围栏代码块,这样不会折叠。
富消息默认启用。某些 Telegram 客户端接受 Bot API 负载但渲染效果不佳;要选择退出并强制每条回复使用传统的 MarkdownV2 路径:
gateway:
platforms:
telegram:
extra:
rich_messages: false此设置用于客户端渲染兼容性;当 Telegram 拒绝富 API 调用时,Hermes 已经自动回退。如果您只想要传统的“始终代码块”表格行为,同时保持富消息启用,请通过在 config.yaml 中设置 telegram.pretty_tables: false(默认:true)来禁用表格规范化。
链接预览。 Telegram 会自动为机器人消息中的 URL 生成链接预览。如果您想抑制这些(例如,长的 /tools 输出,代理回复中提到了十个链接等):
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(这也会授予他们私聊访问权限)时使用。 - 聊天 ID(
group_allowed_chats/TELEGRAM_GROUP_ALLOWED_CHATS)——聊天范围允许列表。这些群组/论坛的任何成员都可以与机器人交互。对于团队/支持机器人很有用,其中群组成员身份本身就是访问信号。
gateway:
platforms:
telegram:
extra:
## 全局访问(私聊 + 群组)。此处的用户始终可以调用机器人。
allow_from:
- "123456789"
## 仅在群组/论坛中允许的发送者 ID。不授予私聊访问权限。
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涵盖所有聊天类型(私聊、群组、论坛)。TELEGRAM_GROUP_ALLOWED_USERS仅在群组/论坛中授权列出的发送者。他们仍然不能向机器人发送私聊,除非也在TELEGRAM_ALLOWED_USERS中列出。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"访客 @提及绕过(guest_mode)
在典型设置中,group_allowed_chats 是一个硬性门控:来自列表外群组的消息会被静默丢弃,即使成员显式 @提及了机器人。这是支持/团队机器人的正确默认设置。
对于更随意的设置——朋友群聊中,您希望机器人大部分时间静默,但偶尔在显式 ping 时可用——启用 guest_mode:
gateway:
platforms:
telegram:
extra:
group_allowed_chats:
- "-1001234567890" # 您的主要允许列表群组
guest_mode: true # 非允许列表群组:仅在 @提及 时允许环境变量等效:
TELEGRAM_GUEST_MODE=true默认值:false。
使用 guest_mode: true 时,来自非允许列表群组的消息仅在显式 @提及机器人时才会被处理。每次交互都需要提及——访客交互没有会话粘性,因此机器人永远不会在没有被 ping 的情况下自动参与朋友群组的线程。
私聊和允许列表群组的行为与之前完全相同。
斜杠命令访问控制
默认情况下,每个允许的用户都可以运行每个斜杠命令。要将您的允许列表拆分为管理员(完全斜杠命令访问权限)和普通用户(仅限您显式启用的命令),请在平台的 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行为:
- 在某个范围(私聊或群组)的
allow_admin_from中列出的用户可以运行每个注册的斜杠命令——包括内置命令和插件注册的命令——通过实时注册表。 - 在
allow_from中但不在allow_admin_from中的用户只能运行user_allowed_commands中列出的命令,加上始终允许的基础命令:/help和/whoami。 - 普通聊天(非斜杠消息)不受影响。非管理员用户仍然可以正常与代理对话,只是不能触发任意命令。
- 向后兼容: 如果某个范围未设置
allow_admin_from,则该范围的斜杠命令门控被禁用。现有安装无需更改即可继续工作。 - 私聊管理员状态并不意味着群组管理员状态。每个范围都有自己的管理员列表。
- 如果只设置了
group_allow_admin_from,私聊范围保持不受限制(向后兼容)模式。
使用 /whoami 查看活动范围、您的层级(管理员/用户/不受限制)以及您可以运行的斜杠命令。
交互式模型选择器
当您在 Telegram 聊天中发送不带参数的 /model 时,Hermes 会显示一个交互式内联键盘,用于切换模型:
- 提供商选择——按钮显示每个可用提供商及其模型数量(例如,“OpenAI (15)”、“✓ Anthropic (12)”表示当前提供商)。
- 模型选择——分页模型列表,带有上一页/下一页导航、返回按钮返回提供商,以及取消。
当前模型和提供商显示在顶部。所有导航都通过就地编辑同一条消息完成(不会产生聊天混乱)。
提示
如果您知道确切的模型名称,请直接输入
/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 返回的与系统 DNS 结果不同的 IP 被用作回退。
- 如果 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"提示
您通常不需要手动配置此项。通过 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 群组或论坛主题分配临时系统提示。提示在每次交互时在运行时注入——永远不会持久化到对话记录中——因此更改会立即生效。
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。检查防火墙规则。 |
执行批准
当代理尝试运行可能危险的命令时,它会在聊天中请求您的批准:
⚠️ 此命令可能危险(递归删除)。回复“yes”以批准。
回复“yes”/“y”以批准,或“no”/“n”以拒绝。
交互式提示(clarify)
当代理调用 clarify 工具时——询问您更喜欢哪种方法、获取任务后反馈或在非平凡决策前检查——Telegram 会使用内联键盘按钮呈现问题:
❓ 我应该为仪表板使用哪个框架?
[1. Next.js] [2. Remix] [3. Astro] [✏️ 其他(输入答案)]
点击按钮回答,或点击其他输入自由格式的响应(您发送的下一条消息将成为答案)。开放式 clarify 调用(无预设选项)会跳过按钮,仅捕获您的下一条消息。
通过 ~/.hermes/config.yaml 中的 agent.clarify_timeout 配置响应超时(默认 600 秒)。如果您在超时内未响应,代理会使用哨兵消息解除阻塞并适应,而不是挂起。
推送通知音量
Telegram 会在机器人发送的每条消息上触发推送通知。对于发出工具进度气泡、流式更新和状态回调的长代理轮次,这会很快变得嘈杂。Telegram 适配器有两种通知模式:
| 模式 | 行为 |
|---|---|
important(默认) | 仅最终响应、批准提示和斜杠命令确认会响铃。工具进度、流式块和状态消息以 disable_notification=true 投递。 |
all | 每条出站消息都会触发推送通知。旧版行为;如果您真的想听到每个工具调用,请选择加入。 |
在 ~/.hermes/config.yaml 中配置:
display:
platforms:
telegram:
notifications: important # 或 "all"环境变量覆盖(方便快速 A/B 测试):
HERMES_TELEGRAM_NOTIFICATIONS=all未知值会记录警告并回退到 important。
状态消息就地编辑
Telegram 适配器通过 send_or_update_status() 路由重复的代理状态回调(例如“正在压缩上下文…”、“正在调用工具…”),该函数维护一个 {(chat_id, status_key) → message_id} 缓存,并在后续发送时编辑现有气泡,而不是每次追加一个新气泡。不同的 status_key 值获得自己的消息;不同的聊天永远不会冲突。如果编辑失败(例如用户删除了消息,或者消息早于 Telegram 允许编辑的时间),缓存条目会被丢弃,下一次发送会发布一条新消息并重新缓存其 ID。无需配置——这是默认的 Telegram 行为。其他未实现 send_or_update_status 的适配器会直接通过普通的 send() 传递。
在代理轮次期间固定传入用户消息
当用户发送一条触发代理轮次的消息时,Telegram 适配器会在轮次期间固定该传入消息,并在响应完成时取消固定——这是一个轻量级的视觉指示器,表明机器人正在积极处理该消息,而不是忽略它。固定使用 disable_notification=true 以避免额外的 ping。无需配置。
安全
警告
始终设置
TELEGRAM_ALLOWED_USERS以限制谁可以与您的机器人交互。没有它,网关会默认拒绝所有用户,作为一种安全措施。
切勿公开分享您的机器人令牌。如果泄露,请立即通过 BotFather 的 /revoke 命令撤销它。
有关更多详细信息,请参阅安全文档。您也可以使用私聊配对来实现更动态的用户授权方法。