Telegram 设置#
Hermes Agent 与 Telegram 集成,作为功能完整的对话机器人。连接后,你可以从任何设备与 Agent 聊天、发送自动转录的语音备忘录、接收定时任务结果,并在群聊中使用 Agent。该集成基于 python-telegram-bot 构建,支持文本、语音、图片和文件附件。第一步:通过 BotFather 创建机器人#
每个 Telegram 机器人都需要由 @BotFather(Telegram 官方机器人管理工具)颁发的 API token(令牌)。3.
选择一个显示名称(例如 "Hermes Agent")——可以是任意名称
4.
选择一个用户名——必须唯一且以 bot 结尾(例如 my_hermes_bot)
5.
BotFather 会回复你的 API token,格式如下:
123456789:ABCdefGHIjklMNOpqrSTUvwxYZ
请妥善保管你的机器人 token。任何持有该 token 的人都可以控制你的机器人。如果泄露,请立即通过 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 机器人有一个隐私模式,默认启用。这是在群组中使用机器人时最常见的困惑来源。如何关闭隐私模式#
4.
进入 Bot Settings → Group Privacy → Turn off
更改隐私设置后,必须将机器人从所有群组中移除并重新添加。 Telegram 在机器人加入群组时会缓存隐私状态,在机器人被移除并重新添加之前不会更新。
禁用隐私模式的替代方案:将机器人提升为群组管理员。管理员机器人无论隐私设置如何都能接收所有消息,这样就无需切换全局隐私模式。
观察群组消息但不自动回复#
对于 OpenClaw/Yuanbao 风格的群组行为,可配置 Telegram 使机器人能看到普通群组消息,但只在被直接触发时响应:启用此模式后,来自明确白名单聊天/话题的未提及群组消息会作为观察上下文追加到共享聊天/话题会话记录中,但不会触发 Agent。allowed_chats 控制机器人在哪里响应;group_allowed_chats 授权用于观察上下文的共享群组会话,因此在此模式下使用相同的聊天 ID。同一白名单聊天/话题中后续的 @botname 提及、对机器人的回复或配置的提及模式可以使用该观察上下文。触发消息还会标记 [nickname|user_id],并获得每轮安全 prompt(提示词),使模型将之前观察到的内容视为上下文而非发给机器人的指令。这需要 Telegram 将普通群组消息传递给 gateway,因此请按上述说明禁用 BotFather 隐私模式或将机器人提升为群组管理员。第四步:获取你的用户 ID#
Hermes Agent 使用 Telegram 数字用户 ID 来控制访问权限。你的用户 ID 不是你的用户名——它是一个类似 123456789 的数字。第五步:配置 Hermes#
方式 A:交互式设置(推荐)#
在提示时选择 Telegram。向导会询问你的机器人 token 和允许的用户 ID,然后为你写入配置。方式 B:手动配置#
启动 Gateway#
机器人应在几秒内上线。在 Telegram 上向它发送消息以验证。从 Docker 后端终端发送生成的文件#
如果你的终端后端是 docker,请注意 Telegram 附件由 gateway 进程发送,而非从容器内部发送。这意味着最终的 MEDIA:/... 路径必须在运行 gateway 的宿主机上可读。Agent 在 Docker 内将文件写入 /workspace/report.txt
模型发出 MEDIA:/workspace/report.txt
Telegram 投递失败,因为 /workspace/report.txt 只存在于容器内,而非宿主机上
在 Docker 内将文件写入 /output/...
在 MEDIA: 中使用宿主机可见的路径,例如:
MEDIA:/home/user/.hermes/cache/documents/report.txt
如果你已有 docker_volumes: 部分,将新挂载添加到同一列表中。YAML 重复键会静默覆盖之前的值。支持的 MEDIA: 文件扩展名#
gateway 从 Agent 回复中提取 MEDIA:/path/to/file 标签,并将引用的文件作为平台原生附件发送。所有 gateway 平台支持的扩展名:| 类别 | 扩展名 |
|---|
| 图片 | 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 |
| Office | docx, xlsx, pptx, odt, ods, odp |
| 压缩包 | zip, rar, 7z, tar, gz, bz2 |
| 书籍/安装包 | epub, apk, ipa |
此列表中的任何内容都会在支持原生附件的平台(Telegram、Discord、Signal、Slack、WhatsApp、飞书、Matrix 等)上作为原生附件投递;在不支持原生附件的平台上,会回退为链接或纯文本指示。加粗类别是最近几个版本新增的——如果你之前依赖模型输出 here is the file: /path/to/report.docx,请改用 MEDIA:/path/to/report.docx 以实现原生投递。Webhook 模式#
默认情况下,Hermes 使用长轮询连接 Telegram——gateway 向 Telegram 服务器发出出站请求以获取新更新。这对本地和常驻部署效果良好。对于云部署(Fly.io、Railway、Render 等),webhook 模式更具成本效益。这些平台可以在入站 HTTP 流量时自动唤醒休眠的机器,但无法通过出站连接唤醒。由于轮询是出站的,轮询机器人永远无法休眠。Webhook 模式反转了方向——Telegram 将更新推送到你的机器人 HTTPS URL,从而实现空闲时休眠的部署。 | 轮询(默认) | Webhook |
|---|
| 方向 | Gateway → Telegram(出站) | Telegram → Gateway(入站) |
| 适用场景 | 本地、常驻服务器 | 支持自动唤醒的云平台 |
| 设置 | 无需额外配置 | 设置 TELEGRAM_WEBHOOK_URL |
| 空闲成本 | 机器必须保持运行 | 机器可在消息间隙休眠 |
| 变量 | 是否必填 | 说明 |
|---|
TELEGRAM_WEBHOOK_URL | 是 | Telegram 发送更新的公开 HTTPS URL。URL 路径会自动提取(例如上例中的 /telegram)。 |
TELEGRAM_WEBHOOK_SECRET | 是(设置 TELEGRAM_WEBHOOK_URL 时) | Telegram 在每个 webhook 请求中回显的密钥 token,用于验证。gateway 在没有该密钥时拒绝启动——参见 GHSA-3vpc-7q5r-276h。使用 openssl rand -hex 32 生成。 |
TELEGRAM_WEBHOOK_PORT | 否 | webhook 服务器监听的本地端口(默认:8443)。 |
设置 TELEGRAM_WEBHOOK_URL 后,gateway 会启动 HTTP webhook 服务器而非轮询。未设置时使用轮询模式——与之前版本行为无变化。云部署示例(Fly.io)#
2.
在 fly.toml 中暴露 webhook 端口:
[[services]]
internal_port = 8443
protocol = "tcp"
[[services.ports]]
handlers = ["tls", "http"]
port = 443
gateway 日志应显示:[telegram] Connected to Telegram (webhook mode)。代理支持#
如果 Telegram 的 API 被封锁,或你需要通过代理路由流量,可设置 Telegram 专用代理 URL。此设置优先于通用的 HTTPS_PROXY / HTTP_PROXY 环境变量。支持的协议:http://、https://、socks5://。代理同时适用于主 Telegram 连接和备用 IP 传输。如果未设置 Telegram 专用代理,gateway 会回退到 HTTPS_PROXY / HTTP_PROXY / ALL_PROXY(或 macOS 系统代理自动检测)。主频道#
在任意 Telegram 聊天(私聊或群组)中使用 /sethome 命令,将其指定为主频道。定时任务(cron 任务)的结果会投递到此频道。也可以在 ~/.hermes/.env 中手动设置:群聊 ID 是负数(例如 -1001234567890)。你的个人私聊 ID 与你的用户 ID 相同。
话题模式下的 Cron 投递#
如果你在机器人私聊中启用了话题模式,投递到根聊天的 cron 消息会落入仅限系统的大厅——在那里回复不会开启会话,你会看到"主聊天保留给系统命令"的提示。创建一个专用论坛话题(例如 Cron)并设置:TELEGRAM_CRON_THREAD_ID 仅针对 cron 投递覆盖 TELEGRAM_HOME_CHANNEL_THREAD_ID。在该话题中的回复会继续该话题的现有会话。语音消息#
接收语音(语音转文字)#
你在 Telegram 上发送的语音消息会由 Hermes 配置的 STT(语音转文字)提供商自动转录,并作为文本注入对话。local 在运行 Hermes 的机器上使用 faster-whisper——无需 API 密钥
groq 使用 Groq Whisper,需要 GROQ_API_KEY
openai 使用 OpenAI Whisper,需要 VOICE_TOOLS_OPENAI_KEY
跳过 STT:将原始音频文件传递给 Agent#
如果你希望由 Agent 本身处理音频——用于说话人分离、自定义转录工具或仅存档录音——请在 ~/.hermes/config.yaml 中设置 stt.enabled: false:禁用 STT 后,gateway 仍会将语音/音频附件下载到 Hermes 的音频缓存中,但不进行转录。Agent 收到的消息带有如下标记:[The user sent a voice message: /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:
没有 ffmpeg,Edge TTS 音频会作为普通音频文件发送(仍可播放,但使用矩形播放器而非语音气泡)。在 config.yaml 的 tts.provider 键下配置 TTS 提供商。通过本地 Bot API 服务器处理大文件(>20MB)#
Telegram 的公共 Bot API 将 getFile 下载限制为 20 MB,因此任何超过该大小的语音备忘录、音频文件、视频或文档都会被 Hermes 静默拒绝并回复"文件过大"。官方解决方案是运行本地 telegram-bot-api 守护进程——与 Telegram 使用的相同服务器软件,但运行在你的网络上。本地服务器将文件上限提升至 2 GB,Hermes 在检测到自定义 base_url 配置时会自动解除自身内部限制。存档原始音频用于离线管道,如说话人分离、对齐或训练数据
第一步:获取 Telegram API 凭据#
本地服务器直接与 Telegram 的 MTProto 层通信(而非公共 Bot API),因此需要 MTProto 凭据:3.
复制 api_id 和 api_hash——两者都是必需的。
第二步:运行 telegram-bot-api 服务器#
本地 Bot API 服务器在 URL 路径中接受你的机器人 token(例如 /bot<TOKEN>/getMe),无额外认证。任何能访问该端口的人都可以完全控制你的机器人——读取它能看到的每条消息、以它的身份发送消息等。将容器绑定到 127.0.0.1,并/或在私有网络上用反向代理保护。切勿将 8081 端口暴露到公网。
第三步:将机器人从公共 API 登出(一次性操作)#
一个机器人在同一时间只能在一个 Bot API 服务器上活跃。如果你的机器人之前已在 api.telegram.org 上运行(几乎可以肯定),你必须先在那里明确登出,本地服务器才会接受它:这是一次性迁移步骤——不需要在每次重启时重复。logOut 后收到的消息会通过新服务器投递。验证本地服务器能代表机器人与 Telegram 通信:第四步:将 Hermes 指向本地服务器#
在 ~/.hermes/config.yaml 的 platforms.telegram.extra 下添加 URL::::caution 使用 platforms.telegram.extra,而非 telegram.extra
目前只有 platforms.<name>.extra 形式会深度合并到平台配置中。直接放在顶层 telegram.extra 块下的键会被静默丢弃。
:::基于本地服务器构建 python-telegram-bot 客户端
自动将内部文档/音频大小上限从 20 MB 提升至 2 GB
在"文件过大"错误消息中报告当前限制(Maximum: 2048 MB.),以便清楚了解所处模式
第五步:local_mode——磁盘上的文件访问#
1.
不使用 --local(默认):文件通过 HTTP 在 /file/bot<TOKEN>/<path> 提供,与公共 Bot API 相同。20MB 上限仍然有效。仅作为网络修复使用(例如 api.telegram.org 不可达但你可以自托管);这不是你想要的大小提升方式。
2.
使用 --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、独立虚拟机),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
如果你看到这个,说明大小提升正在工作,但文件共享没有。以 gateway 运行用户的身份从 Hermes 宿主机执行 ls -la /var/lib/telegram-bot-api/<TOKEN>/voice/,并确认单个文件可以 cat 而不出现权限错误。第六步:测试#
向机器人发送一个超过 20 MB 的语音备忘录或音频文件。查看 gateway 日志:你应该看到 [Telegram] Cached user voice at /home/<user>/.hermes/cache/audio/... 行,且没有"文件过大"拒绝。结合上方的 stt.enabled: false,原始音频文件的路径会出现在 Agent 的入站消息中,供下游处理使用。群聊使用#
Hermes Agent 在 Telegram 群聊中工作时有几点注意事项:TELEGRAM_ALLOWED_USERS 仍然适用——即使在群组中,也只有授权用户才能触发机器人
你可以通过 telegram.require_mention: true 阻止机器人响应普通群组消息
设置 telegram.require_mention: true 时,以下情况的群组消息会被接受:/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 机器人 token,并为每个配置文件启动一个 gateway。不要在多个运行中的 gateway 中重用同一个机器人 token;Telegram 会拒绝对同一 token 的并发轮询。使用此设置,群组消息如 @research_bot @ops_bot summarize this 只由 research_bot 和 ops_bot 处理。群组中的其他 Hermes 机器人保持沉默,即使该消息是对其早期消息的回复或与共享唤醒词匹配。仅在旧版群组中(明确提及不应覆盖回复和唤醒词触发)才将 exclusive_bot_mentions: false。要运行多个配置文件,每个配置文件运行一次 gateway 命令。例如:对于小型固定机器人集群,使用 shell 循环或脚本,对默认配置文件调用 hermes gateway <action>,对每个命名配置文件调用 hermes -p <profile> gateway <action>。这比假设单个进程级命令在每个服务管理器上控制所有命名配置文件更可靠。故障排除:私聊正常 但群组无响应#
如果机器人在私聊中响应但在群组中保持沉默,请按顺序检查以下关卡:1.
Telegram 投递: 关闭 BotFather 隐私模式、将机器人提升为管理员,或直接提及机器人。Hermes 无法响应 Telegram 从未投递给机器人的群组消息。
2.
更改隐私后重新加入: 更改 BotFather 隐私设置后,将机器人从群组中移除并重新添加。Telegram 可能对现有成员保留旧的投递行为。
3.
Hermes 授权: 确保发送者在 TELEGRAM_ALLOWED_USERS 或 TELEGRAM_GROUP_ALLOWED_USERS 中,或通过 TELEGRAM_GROUP_ALLOWED_CHATS 允许该群聊。
4.
提及过滤器: 如果设置了 telegram.require_mention: true,普通群组消息会被忽略,除非消息是斜杠命令、对机器人的回复、@botusername 提及或配置的 mention_patterns 匹配。
5.
多机器人路由: 如果群组包含多个机器人,确保每个 Hermes 配置文件使用唯一的机器人 token,并保持 exclusive_bot_mentions 启用,除非你有意使用旧版共享触发行为。
Telegram 群组和超级群组的负数聊天 ID 是正常的。如果你使用聊天范围的授权,请将这些 ID 放在 TELEGRAM_GROUP_ALLOWED_CHATS 中,而非发送者用户白名单中。群组触发配置示例#
将以下内容添加到 ~/.hermes/config.yaml:此示例允许所有常规直接触发,以及以 chompy 开头的消息,即使它们不使用 @mention。
Telegram 话题 31 和 42 中的消息在提及和自由响应检查运行之前始终被忽略。mention_patterns 说明#
无效的正则表达式模式会在 gateway 日志中记录警告并被忽略,而不会导致机器人崩溃
私聊话题(Bot API 9.4)#
Telegram Bot API 9.4(2026 年 2 月)引入了私聊话题——机器人可以直接在一对一私聊中创建论坛风格的话题线程,无需超级群 组。这让你可以在与 Hermes 的现有私聊中运行多个隔离的工作区。使用场景#
如果你同时处理多个长期项目,话题可以保持各自上下文独立:话题"Website" — 处理你的生产 Web 服务
每个话题都有自己的对话会话、历史记录和上下文——完全相互隔离。在配置中添加话题之前,用户必须在与机器人的私聊中启用话题模式:1.
在 Telegram 中打开与 Hermes 机器人的私聊
没有此设置,Hermes 会在启动时记录 The chat is not a forum 并跳过话题创建。这是 Telegram 客户端设置——机器人无法以编程方式启用它。 在 ~/.hermes/config.yaml 的 platforms.telegram.extra.dm_topics 下添加话题:| 字段 | 是否必填 | 说明 |
|---|
name | 是 | 话题显示名称 |
icon_color | 否 | Telegram 图标颜色代码(整数) |
icon_custom_emoji_id | 否 | 话题图标的自定义 emoji ID |
skill | 否 | 在此话题的新会话中自动加载的技能 |
thread_id | 否 | 话题创建后自动填充——请勿手动设置 |
工作原理#
1.
gateway 启动时,Hermes 为每个尚未有 thread_id 的话题调用 createForumTopic
2.
thread_id 会自动保存回 config.yaml——后续重启会跳过 API 调用
3.
每个话题映射到一个隔离的会话键:agent:main:telegram:dm:{chat_id}:{thread_id}
4.
每个话题中的消息都有自己的对话历史、内存刷新和上下文窗口
根私聊处理#
默认情况下,发送到根私聊(任何话题之外)的消息会正常处理。设置 ignore_root_dm: true 可将根私聊变为大厅——对于已配置私聊话题的用户,普通消息会被静默忽略,而系统命令(/start、/help、/status 等)仍然有效。该检查是按聊天进行的:只有在 dm_topics 中至少有一个条目的用户的根私聊才会受到影响。没有配置话题的用户不受影响。技能绑定#
带有 skill 字段的话题会在该话题中新会话开始时自动加载该技能。这与在对话开始时输入 /skill-name 完全相同——技能内容会注入到第一条消息中,后续消息在对话历史中可以看到它。例如,带有 skill: arxiv 的话题会在其会话重置时(由于空闲超时、每日重置或手动 /reset)预加载 arxiv 技能。在配置之外创建的话题(例如通过手动调用 Telegram API)会在 forum_topic_created 服务消息到达时自动被发现。你也可以在 gateway 运行时向配置中添加话题——它们会在下次缓存未命中时被拾取。
多会话私聊模式(/topic)#
ChatGPT 风格的多会话私聊——一个机器人,多个并行对话。 与上方运营商策划的 extra.dm_topics 不同,此模式是用户驱动的:无需配置,无需预先声明话题名称。终端用户通过 /topic 开启,然后点击 Telegram 的 + 按钮创建任意数量的话题,每个话题都是完全独立的 Hermes 会话。/topic 子命令#
| 形式 | 上下文 | 效果 |
|---|
/topic | 根私聊,尚未启用 | 检查 BotFather 功能,启用多会话模式,创建置顶 System 话题 |
/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:1.
开启 Threaded Mode(启用 has_topics_enabled)
2.
不要禁用用户创建话题(保持 allows_users_to_create_topics 开启)
当用户首次运行 /topic 时,Hermes 调用 getMe 验证两个标志。如果任一标志关闭,Hermes 会发送 BotFather Threads Settings 页面的截图并说明需要切换什么——在满足前提条件之前不会激活。激活流程#
1.
检查 getMe().has_topics_enabled 和 allows_users_to_create_topics
2.
如果两者都为 true,为此私聊启用多会话话题模式
3.
创建并置顶一个 System 话题用于状态/命令(尽力而为)
4.
回复用户可以恢复的之前未链接 Telegram 会话列表
激活后,根私聊变为大厅:普通 prompt 会被拒绝,并引导用户前往 All Messages。系统命令(/status、/sessions、/usage、/help 等)在根目录仍然有效。创建新话题(终端用户流程)#
2.
点击机器人界面顶部的 All Messages,然后发送任意消息
4.
Hermes 在该话题内响应——该话题现在是一个独立会话
每个话题都有自己的对话历史、模型状态、工具执行和会话 ID。隔离键为 agent:main:telegram:dm:{chat_id}:{thread_id}——与配置驱动的私聊话题隔离相同。自动重命名话题#
当 Hermes 为话题生成会话标题时(通过自动标题管道,在第一次交换后),Telegram 话题本身会被重命名以匹配——例如"New Topic"变为"Database migration plan"。重命名是尽力而为的:失败会被记录但不会中断会话。启用此标志后,Hermes 仍会生成内部会话标题(供 hermes sessions、TUI 等使用),但永远不会编辑 Telegram 话题名称。当你在 BotFather Threaded Mode 下手动整理话题,且不希望每次第一次回复都覆盖标题时,此功能很有用。话题内的 /new#
重置当前话题的会话(新会话 ID,全新历史记录),而不影响其他话题。Hermes 回复提醒,对于并行工作,创建另一个话题(通过 All Messages)通常才是你想要的。恢复之前的会话#
这会将当前话题绑定到现有 Hermes 会话,而非重新开始。适用于继续在启用话题模式之前开始的对话。限制: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 调用时运行,而非在 gateway 启动时。在用户在此配置文件中运行 /topic 之前,state.db 保持不变
每条入站私聊消息都会查找其 (chat_id, thread_id) 绑定。如果存在,查找会通过 SessionStore.switch_session() 将消息路由到绑定的会话,以保持磁盘上会话键到会话 ID 映射的一致性
话题内的 /new 会重写绑定行以指向新会话 ID,因此下一条消息保持在新会话上
extra.dm_topics 中声明的话题永远不会自动重命名——即使启用了多会话模式,运营商选择的名称也会被保留
设置 extra.disable_topic_auto_rename: true 可关闭聊天中所有话题的自动重命名(包括通过 Threaded Mode 创建的临时话题)
论坛启用私聊中的 General(置顶顶部)话题被视为根大厅,无论 Telegram 是以 message_thread_id=1 还是无 thread_id 投递其消息
根大厅提醒每个聊天每 30 秒限速一条——忘记话题模式已开启并在根目录输入十条 prompt 的用户不会收到十条回复
BotFather 设置截图每个聊天每 5 分钟限速一次发送——在 Threads Settings 仍然禁用时重复尝试 /topic 不会重复上传同一张图片
在话题内启动的 /background <prompt> 会将结果投递回同一话题;后台会话不会触发所属话题的自动重命名
/topic 本身受机器人用户授权检查限制——未授权的私聊会收到拒绝而非激活
禁用多会话模式#
在根私聊发送 /topic off。Hermes 将该行翻转为关闭,清除聊天的 (thread_id → session_id) 绑定,根私聊恢复为正常 Hermes 聊天。Telegram 中现有的话题不会被删除——它们只是不再作为独立会话被管控。之后重新运行 /topic 可重新开启。如果你需要手动清理(例如跨多个聊天的批量重置),直接删除行:降级 Hermes#
如果你降级到早于 /topic 的 Hermes 版本,该功能会停止工作——telegram_dm_topic_mode 和 telegram_dm_topic_bindings 表保留在 state.db 中,但被旧代码忽略。私聊恢复为原生的每线程隔离(每个 message_thread_id 仍通过 build_session_key 获得自己的会话),因此你现有的 Telegram 话题继续作为并行会话工作。根私聊不再是大厅——消息像以前一样进入 Agent。重新升级会在原来的位置精确恢复多会话模式。群组论坛话题技能绑定#
启用了话题模式(也称为"论坛话题")的超级群组已经按话题进行会话隔离——每个 thread_id 映射到自己的对话。但你可能希望在特定群组话题中有消息到达时自动加载技能,就像私聊话题技能绑定的工作方式一样。使用场景#
Engineering 话题 → 自动加载 software-development 技能
Research 话题 → 自动加载 arxiv 技能
在 ~/.hermes/config.yaml 的 platforms.telegram.extra.group_topics 下添加话题绑定:| 字段 | 是否必填 | 说明 |
|---|
chat_id | 是 | 超级群组的数字 ID(以 -100 开头的负数) |
name | 否 | 话题的人类可读标签(仅供参考) |
thread_id | 是 | Telegram 论坛话题 ID——在 t.me/c/<group_id>/<thread_id> 链接中可见 |
skill | 否 | 在此话题的新会话中自动加载的技能 |
工作原理#
1.
当消息到达已映射的群组话题时,Hermes 在 group_topics 配置中查找 chat_id 和 thread_id
2.
如果匹配条目有 skill 字段,该技能会为会话自动加载——与私聊话题技能绑定完全相同
3.
没有 skill 键的话题只获得会话隔离(现有行为,不变)
4.
未映射的 thread_id 值或 chat_id 值会静默通过——无错误,无技能
与私聊话题的区别#
| 私聊话题 | 群组话题 |
|---|
| 配置键 | extra.dm_topics | extra.group_topics |
| 话题创建 | 如果缺少 thread_id,Hermes 通过 API 创建话题 | 管理员在 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 在一对一私聊中创建论坛话题。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 中:使用 edit(默认)时私聊中的效果 — gateway 发送一条普通预览消息,并通过 editMessageText 渐进更新,避免 Telegram 草稿预览折叠/回滚效果。使用 auto 或 draft 时私聊中的效果 — Telegram 显示逐 token 更新的动画草稿预览。回复完成后,它作为普通消息投递,草稿预览在客户端自然清除。草稿没有消息 ID,因此最终答案才是保留在聊天历史中的内容。群组、超级群组、论坛话题怎么办? Telegram 将 sendMessageDraft 限制为私聊(私信)。gateway 对其他所有内容透明地回退到基于编辑的路径——与之前的用户体验相同。如果草稿帧失败怎么办? 任何失败(瞬时网络错误、服务器端拒绝、旧版 python-telegram-bot 安装)都会将该响应的剩余流切换回基于编辑的路径。下一个响应会重新尝试。渲染:表格和链接预览#
Telegram 的 MarkdownV2 没有原生表格语法——如果直接传递管道表格,会渲染为反斜杠转义的噪音。Hermes 自动规范化 markdown 表格:小表格被展平为行组项目符号——每行在列标题下变为可读的项目符号列表。适合 2-4 列和短单元格。
较大或较宽的表格回退为带对齐列的围栏代 码块,以防内容折叠。还会添加一行 prompt 提示,让 Agent 知道在 Telegram 上优先使用散文而非更多表格。
无需配置——适配器会为每条消息选择正确的回退方式。如果你想要旧版"始终使用代码块"行为,可在 config.yaml 中设置 telegram.pretty_tables: false 禁用表格规范化(默认:true)。链接预览。 Telegram 会为机器人消息中的 URL 自动生成链接预览。如果你希望抑制这些预览(长 /tools 输出、提及十个链接的 Agent 回复等):启用后,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)——聊天范围白名单。这些群组/论坛的任何成员都可以与机器人交互。适用于群组成员身份本身就是访问信号的团队/支持机器人。
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,并记录一次弃用警告。迁移方式:访客 @mention 绕过(guest_mode)#
在典型设置中,group_allowed_chats 是硬性关卡:来自列表之外群组的消息会被静默丢弃,即使成员明确 @mention 了机器人。这是支持/团队机器人的正确默认值。对于更随意的设置——朋友群聊,你希望机器人大部分时间保持沉默,但在被明确 ping 时偶尔可用——启用 guest_mode:启用 guest_mode: true 后,来自非白名单群组的消息仅在明确 @mention 机器人时才被处理。每轮都需要提及——访客交互没有会话粘性,因此机器人永远不会在未被 ping 的朋友群组线程中自动参与。斜杠命令访问控制#
默认情况下,每个允许的用户都可以运行每个斜杠命令。要将你的白名单分为管理员(完整斜杠命令访问)和普通用户(仅你明确启用的命令),请在平台的 extra 块中添加 allow_admin_from 和 user_allowed_commands:在某个范围(私聊或群组)的 allow_admin_from 中列出的用户可以运行每个已注册的斜杠命令——内置命令和插件注册的命令——通过实时注册表。
在 allow_from 中但不在 allow_admin_from 中的用户只能运行 user_allowed_commands 中列出的命令,加上始终允许的底线:/help 和 /whoami。
普通聊天(非斜杠消息)不受影响。非管理员用户仍然可以正常与 Agent 对话,只是无法触发任意命令。
向后兼容: 如果某个范围未设置 allow_admin_from,该范围的斜杠命令限制被禁用。现有安装无需任何更改即可继续工作。
私聊管理员状态不意味着群组管理员状态。每个范围都有自己的管理员列表。
如果只设置了 group_allow_admin_from,私聊范围保持不受限制(向后兼容)模式。
使用 /whoami 查看当前范围、你的级别(管理员/用户/不受限制)以及你可以运行的斜杠命令。