字节笔记本
2026年6月21日
hermes教程-会话
会话如何工作
每次对话——无论是来自 CLI、Telegram、Discord、Slack、WhatsApp、Signal、Matrix、Teams 还是任何其他消息平台——都会作为包含完整消息历史的会话存储。会话在以下位置进行跟踪:
- SQLite 数据库 (
~/.hermes/state.db) — 结构化的会话元数据,支持 FTS5 全文搜索,以及完整的消息历史
SQLite 数据库存储:
- 会话 ID、来源平台、用户 ID
- 会话标题(唯一的、人类可读的名称)
- 模型名称和配置
- 系统提示快照
- 完整消息历史(角色、内容、工具调用、工具结果)
- Token 计数(输入/输出)
- 时间戳(started_at、ended_at)
- 父会话 ID(用于压缩触发的会话拆分)
哪些内容计入上下文
Hermes 会存储会话历史以便恢复对话,但不会重复发送它处理过的每一个字节。在每一轮中,模型看到的是选定的系统提示、当前对话窗口以及 Hermes 为该轮显式注入的任何内容。
媒体附件作为轮次范围内的输入处理:
- 图像可以原生附加到下一个模型调用,或者在当前模型不支持原生视觉时预先分析为文本描述。
- 音频在配置了语音转文本时会被转录为文本。
- 文本文档可以包含其提取的文本;其他文档类型通常通过保存的本地路径和简短注释来表示。
- 附件路径和提取/派生的文本可以出现在记录中,但原始图像、音频或二进制文件字节不会重复复制到未来的提示中。
例如,如果用户发送一张图片并要求 Hermes 用它制作一个表情包,Hermes 可能会用视觉功能检查该图片一次,并运行一个图像处理脚本。未来的轮次不会自动携带原始 JPEG 到上下文中。它们只携带写入对话的内容,例如用户的请求、简短的图像描述、本地缓存路径或最终的助手响应。
上下文增长的最常见原因不是媒体文件本身,而是冗长的文本:粘贴的记录、完整的日志、大型工具输出、长差异、重复的状态报告以及详细的证明转储。优先使用摘要、文件路径、重点摘录和工具支持的查找,而不是将大型工件复制到聊天中。
提示
当会话变长时使用
/compress,需要新线程时使用/new,只有在你想从存储中删除旧的已结束会话时才使用hermes sessions prune。压缩会减少活动上下文;它不是隐私删除。向/new传递一个名称(例如/new payments-refactor)可以预先设置新会话的初始标题——方便以后用/resume <name>或在/sessions选择器中找到它。
会话来源
每个会话都标记有其来源平台:
| 来源 | 描述 |
|---|---|
cli | 交互式 CLI(hermes 或 hermes chat) |
telegram | Telegram 信使 |
discord | Discord 服务器/私信 |
slack | Slack 工作区 |
whatsapp | WhatsApp 信使 |
signal | Signal 信使 |
matrix | Matrix 房间和私信 |
mattermost | Mattermost 频道 |
email | 电子邮件(IMAP/SMTP) |
sms | 通过 Twilio 的短信 |
dingtalk | 钉钉信使 |
feishu | 飞书/Lark 信使 |
wecom | 企业微信 |
weixin | 微信(个人微信) |
bluebubbles | 通过 BlueBubbles macOS 服务器的 Apple iMessage |
qqbot | QQ 机器人(腾讯 QQ)通过官方 API v2 |
homeassistant | Home Assistant 对话 |
webhook | 传入的 Webhook |
api-server | API 服务器请求 |
acp | ACP 编辑器集成 |
cron | 计划任务 |
batch | 批处理运行 |
CLI 会话恢复
使用 --continue 或 --resume 从 CLI 恢复之前的对话:
继续上一个会话
## 恢复最近的 CLI 会话
hermes --continue
hermes -c
## 或者使用 chat 子命令
hermes chat --continue
hermes chat -c这会从 SQLite 数据库中查找最近的 cli 会话,并加载其完整的对话历史。
按名称恢复
如果你已经为会话设置了标题(参见下面的 会话命名),你可以按名称恢复它:
## 恢复一个命名的会话
hermes -c "my project"
## 如果有衍生变体(my project, my project #2, my project #3),
## 这会自动恢复最近的一个
hermes -c "my project" # → 恢复 "my project #3"恢复特定会话
## 按 ID 恢复特定会话
hermes --resume 20250305_091523_a1b2c3d4
hermes -r 20250305_091523_a1b2c3d4
## 按标题恢复
hermes --resume "refactoring auth"
## 或者使用 chat 子命令
hermes chat --resume 20250305_091523_a1b2c3d4会话 ID 在退出 CLI 会话时显示,也可以通过 hermes sessions list 找到。
恢复时的对话回顾
当你恢复一个会话时,Hermes 会在输入提示之前显示一个紧凑的回顾面板,展示之前的对话:
回顾内容:
- 显示用户消息(金色
●)和助手响应(绿色◆) - 截断长消息(用户消息 300 字符,助手消息 200 字符 / 3 行)
- 折叠工具调用为带有工具名称的计数(例如
[3 个工具调用: terminal, web_search]) - 隐藏系统消息、工具结果和内部推理
- 限制在最后 10 轮对话,并带有 "... N 条更早的消息 ..." 指示器
- 使用暗淡样式以区别于活动对话
要禁用回顾并保持最小的一行行为,在 ~/.hermes/config.yaml 中设置:
display:
resume_display: minimal # 默认: full提示
会话 ID 的格式为
YYYYMMDD_HHMMSS_<hex>— CLI/TUI 会话使用 6 字符十六进制后缀(例如20250305_091523_a1b2c3),网关会话使用 8 字符后缀(例如20250305_091523_a1b2c3d4)。你可以按 ID(完整或唯一前缀)或按标题恢复 — 两者都适用于-c和-r。
跨平台交接
使用 /handoff <platform> 从 CLI 会话将实时对话转移到消息平台的主频道。代理会从 CLI 离开的地方精确继续——相同的会话 ID、完整的角色感知记录、工具调用等。
## 在 CLI 会话内部
/handoff telegram发生的情况:
-
CLI 验证
<platform>已启用并设置了主频道(在目标聊天中运行/sethome一次进行配置)。 -
CLI 将会话标记为待处理并阻塞轮询网关。如果代理正在处理中则拒绝——先等待当前响应完成。
-
网关监视器认领交接,并要求目标适配器创建一个新线程:
- Telegram — 打开一个新的论坛主题(如果聊天中启用了 Bot API 9.4+ 主题模式,则为私信主题;否则为论坛超级组主题)。
- Discord — 在主文本频道下创建一个 1440 分钟自动归档的线程。
- Slack — 发布一条种子消息,并将其
ts作为线程锚点。 - WhatsApp / Signal / Matrix / SMS — 没有原生线程,直接回退到主频道。
-
网关将目标键重新绑定到你现有的 CLI 会话 ID,然后伪造一个合成用户轮次,要求代理确认并总结。回复会出现在新线程中。
-
当网关确认成功时,CLI 打印一个
/resume提示并干净退出:text↻ 交接完成。会话现在在 telegram 上活跃。 稍后在此 CLI 上恢复它:/resume my-session-title -
从那时起,对话在平台上进行。在新线程中回复——该频道中任何授权用户共享同一个会话,并且线程中任何后续的真实用户消息都会无缝加入,因为线程会话不依赖
user_id。
回到 CLI: 当你想要回到桌面时,只需运行 /resume <title>(或从 shell 运行 hermes -r "<title>"),从平台离开的地方继续。
失败模式:
- 未配置主频道 → CLI 拒绝并提示
/sethome。 - 平台未启用 / 网关未运行 → CLI 在 60 秒后超时,显示清晰消息,你的 CLI 会话保持完整。
- 线程创建失败(权限、主题模式关闭)→ 直接回退到主频道并仍然完成;没有线程隔离但交接本身有效。
adapter.send失败(速率限制、临时 API 错误)→ 交接标记为失败并显示原因;记录被清除,你可以重试。
值得注意的限制: 对于不支持线程的平台,如果有多用户群组主频道,合成轮次会作为私信风格的会话键。这对于自私信主频道(典型设置)有效,但对于真正的共享群聊并不理想。线程覆盖了 Telegram / Discord / Slack——这是最常见的情况——所以大多数设置不会遇到这个问题。
会话命名
为会话设置人类可读的标题,以便轻松找到和恢复它们。
自动生成的标题
Hermes 会在第一次交流后自动为每个会话生成一个简短的描述性标题(3-7 个单词)。这会在后台线程中使用快速辅助模型运行,因此不会增加延迟。当你使用 hermes sessions list 或 hermes sessions browse 浏览会话时,会看到自动生成的标题。
自动标题只会在每个会话中触发一次,如果你已经手动设置了标题,则会跳过。
手动设置标题
在任何聊天会话(CLI 或网关)中使用 /title 斜杠命令:
/title my research project
标题会立即应用。如果会话尚未在数据库中创建(例如,你在发送第一条消息之前运行 /title),它会被排队并在会话开始时应用。
你也可以从命令行重命名现有会话:
hermes sessions rename 20250305_091523_a1b2c3d4 "refactoring auth module"标题规则
- 唯一 — 没有两个会话可以共享相同的标题
- 最多 100 个字符 — 保持列表输出整洁
- 清理 — 控制字符、零宽字符和 RTL 覆盖符会被自动去除
- 普通 Unicode 没问题 — 表情符号、中日韩文字、重音字符都可以
压缩时的自动衍生
当会话的上下文被压缩时(手动通过 /compress 或自动),Hermes 会创建一个新的延续会话。如果原始会话有标题,新会话会自动获得一个编号标题:
"my project" → "my project #2" → "my project #3"
当你按名称恢复时(hermes -c "my project"),它会自动选择衍生链中最新的会话。
消息平台中的 /title
/title 命令在所有网关平台(Telegram、Discord、Slack、WhatsApp)中工作:
/title My Research— 设置会话标题/title— 显示当前标题
会话管理命令
Hermes 通过 hermes sessions 提供一整套会话管理命令:
列出会话
## 列出最近的会话(默认:最后 20 个)
hermes sessions list
## 按平台过滤
hermes sessions list --source telegram
## 显示更多会话
hermes sessions list --limit 50当会话有标题时,输出显示标题、预览和相对时间戳:
Title Preview Last Active ID
────────────────────────────────────────────────────────────────────────────────────────────────
refactoring auth Help me refactor the auth module please 2h ago 20250305_091523_a
my project #3 Can you check the test failures? yesterday 20250304_143022_e
— What's the weather in Las Vegas? 3d ago 20250303_101500_f当没有会话有标题时,使用更简单的格式:
Preview Last Active Src ID
──────────────────────────────────────────────────────────────────────────────────────
Help me refactor the auth module please 2h ago cli 20250305_091523_a
What's the weather in Las Vegas? 3d ago tele 20250303_101500_f导出会话
## 将所有会话导出到 JSONL 文件
hermes sessions export backup.jsonl
## 导出特定平台的会话
hermes sessions export telegram-history.jsonl --source telegram
## 导出单个会话
hermes sessions export session.jsonl --session-id 20250305_091523_a1b2c3d4导出的文件每行包含一个 JSON 对象,包含完整的会话元数据和所有消息。
删除会话
## 删除特定会话(需要确认)
hermes sessions delete 20250305_091523_a1b2c3d4
## 无需确认删除
hermes sessions delete 20250305_091523_a1b2c3d4 --yes重命名会话
## 设置或更改会话标题
hermes sessions rename 20250305_091523_a1b2c3d4 "debugging auth flow"
## 多词标题在 CLI 中不需要引号
hermes sessions rename 20250305_091523_a1b2c3d4 debugging auth flow如果标题已被其他会话使用,会显示错误。
清理旧会话
## 删除超过 90 天的已结束会话(默认)
hermes sessions prune
## 自定义时间阈值
hermes sessions prune --older-than 30
## 仅清理特定平台的会话
hermes sessions prune --source telegram --older-than 60
## 跳过确认
hermes sessions prune --older-than 30 --yes信息
清理只删除已结束的会话(已明确结束或自动重置的会话)。活动会话永远不会被清理。
会话统计
hermes sessions stats输出:
Total sessions: 142
Total messages: 3847
cli: 89 sessions
telegram: 38 sessions
discord: 15 sessions
Database size: 12.4 MB要进行更深入的分析——Token 使用、成本估算、工具分解和活动模式——请使用 hermes insights。
会话搜索工具
代理内置了一个 session_search 工具,它使用 SQLite 的 FTS5 引擎对所有过去的对话执行全文搜索——并允许代理滚动浏览它找到的任何会话。没有 LLM 调用,没有摘要,没有截断。每种形状都从数据库返回实际消息。
三种调用形状
该工具根据你设置的参数推断你想要什么。没有 mode 参数。
1. 发现 — 传递 query:
session_search(query="auth refactor", limit=3)运行 FTS5,按会话衍生链去重,返回前 N 个会话。每个结果包含:
session_id、title、when、sourcesnippet— FTS5 高亮的匹配摘录bookend_start— 会话的前 3 条用户+助手消息(目标/启动)messages— FTS5 匹配前后各 5 条消息,锚点消息被标记(上下文中的命中)bookend_end— 会话的最后 3 条用户+助手消息(结论/决策)match_message_id、messages_before、messages_after
书签 + 窗口一起重建目标 → 匹配 → 结论,而无需支付整个记录的成本。典型耗时:在真实会话数据库上为 15–50 毫秒。
2. 滚动 — 传递 session_id + around_message_id:
session_search(session_id="20260510_174648_805cc2", around_message_id=590803, window=10)返回以锚点为中心的 ±window 条消息窗口。没有 FTS5,没有书签——只有切片。在发现调用后,当你需要比默认 ±5 窗口更多的上下文时使用。
- 要向前滚动:将
messages[-1].id作为around_message_id传回 - 要向后滚动:将
messages[0].id作为around_message_id传回 - 边界消息会出现在两个窗口中,作为方向标记
- 当
messages_before或messages_after小于window时,你已到达会话的开始或结束
典型耗时:每次滚动调用 1–2 毫秒。
3. 浏览 — 无参数:
session_search()按时间顺序返回最近的会话(标题、预览、时间戳)。当用户问“我之前在做什么”但没有指定主题时很有用。
FTS5 查询语法
关键词模式支持标准的 FTS5 查询语法:
- 简单关键词:
docker deployment(FTS5 默认为 AND) - 短语:
"exact phrase" - 布尔:
docker OR kubernetes、python NOT java - 前缀:
deploy*
可选参数
sort—newest或oldest,在 FTS5 排名之上。省略则仅按相关性排序(默认;适用于探索性回忆)。使用newest回答“我们在哪里留下了 X”的问题,使用oldest回答“X 是如何开始的”的问题。role_filter— 逗号分隔的角色,用于包含。发现默认为user,assistant(工具输出通常是噪音)。传递user,assistant,tool以包含工具输出(调试工具行为)或tool仅搜索工具输出。
何时使用
代理被提示自动使用会话搜索:
“当用户引用过去对话中的内容,或者你怀疑存在相关的先前上下文时,使用 session_search 来回忆它,而不是要求他们重复自己。”
典型触发词:“我们之前做过这个”、“还记得什么时候”、“上次”、“正如我提到的”,或者任何对当前窗口中不存在的项目/人/概念的引用。
按平台会话跟踪
网关会话
在消息平台上,会话通过从消息源构建的确定性会话键进行键控:
| 聊天类型 | 默认键格式 | 行为 |
|---|---|---|
| Telegram 私信 | agent:main:telegram:dm:<chat_id> | 每个私信聊天一个会话 |
| Discord 私信 | agent:main:discord:dm:<chat_id> | 每个私信聊天一个会话 |
| WhatsApp 私信 | agent:main:whatsapp:dm:<canonical_identifier> | 每个私信用户一个会话(当映射存在时,LID/电话别名合并为一个身份) |
| 群组聊天 | agent:main:<platform>:group:<chat_id>:<user_id> | 群组内每个用户一个会话(当平台暴露用户 ID 时) |
| 群组线程/主题 | agent:main:<platform>:group:<chat_id>:<thread_id> | 所有线程参与者共享的会话(默认)。使用 thread_sessions_per_user: true 时为每个用户一个会话。 |
| 频道 | agent:main:<platform>:channel:<chat_id>:<user_id> | 频道内每个用户一个会话(当平台暴露用户 ID 时) |
当 Hermes 无法获取共享聊天的参与者标识符时,它会回退到该房间的一个共享会话。
共享与隔离的群组会话
默认情况下,Hermes 在 config.yaml 中使用 group_sessions_per_user: true。这意味着:
- Alice 和 Bob 可以在同一个 Discord 频道中与 Hermes 对话,而不会共享记录历史
- 一个用户长时间的工具密集型任务不会污染另一个用户的上下文窗口
- 中断处理也保持每个用户独立,因为运行代理键与隔离的会话键匹配
如果你想要一个共享的“房间大脑”,请设置:
group_sessions_per_user: false这将群组/频道恢复为每个房间一个共享会话,这保留了共享的对话上下文,但也共享了 Token 成本、中断状态和上下文增长。
会话重置策略
网关会话根据可配置的策略自动重置:
- idle — 在 N 分钟不活动后重置
- daily — 在每天的特定小时重置
- both — 以先到者为准(空闲或每日)
- none — 从不自动重置
在自动重置会话之前,代理会获得一个轮次来保存对话中的任何重要记忆或技能。
具有活动后台进程的会话永远不会自动重置,无论策略如何。
存储位置
| 内容 | 路径 | 描述 |
|---|---|---|
| SQLite 数据库 | ~/.hermes/state.db | 所有会话元数据 + 消息,带 FTS5 |
| 网关消息 | ~/.hermes/state.db | SQLite — 所有会话消息的规范存储 |
| 网关路由索引 | ~/.hermes/sessions/sessions.json | 将会话键映射到活动会话 ID(原始元数据、过期标志) |
SQLite 数据库使用 WAL 模式支持并发读取和单个写入,这很好地适应了网关的多平台架构。
注意 — 遗留 JSONL 记录
在 state.db 成为规范存储之前创建的会话可能在
~/.hermes/sessions/中留有*.jsonl文件。Hermes 不再写入或读取它们。在验证 state.db 中存在相应会话后,可以安全删除。
数据库模式
state.db 中的关键表:
- sessions — 会话元数据(id、source、user_id、model、title、timestamps、token counts)。标题有唯一索引(允许 NULL 标题,只有非 NULL 必须唯一)。
- messages — 完整消息历史(role、content、tool_calls、tool_name、token_count)
- messages_fts — 用于跨消息内容全文搜索的 FTS5 虚拟表
会话过期与清理
自动清理
- 网关会话根据配置的重置策略自动重置
- 在重置之前,代理会保存过期会话中的记忆和技能
- 可选自动清理:当
sessions.auto_prune为true时,在 CLI/网关启动时清理超过sessions.retention_days(默认 90 天)的已结束会话 - 在真正删除行之后,
state.db会执行VACUUM以回收磁盘空间(SQLite 在普通 DELETE 后不会缩小文件) - 清理最多每
sessions.min_interval_hours(默认 24)运行一次;最后运行时间戳存储在state.db本身中,因此它在同一HERMES_HOME中的所有 Hermes 进程之间共享
默认是关闭的——会话历史对于 session_search 回忆很有价值,静默删除可能会让用户感到惊讶。在 ~/.hermes/config.yaml 中启用:
sessions:
auto_prune: true # 选择加入 — 默认为 false
retention_days: 90 # 保留已结束会话的天数
vacuum_after_prune: true # 清理后回收磁盘空间
min_interval_hours: 24 # 不要比这个更频繁地运行清理活动会话永远不会被自动清理,无论其年龄如何。
手动清理
## 清理超过 90 天的会话
hermes sessions prune
## 删除特定会话
hermes sessions delete <session_id>
## 在清理前导出(备份)
hermes sessions export backup.jsonl
hermes sessions prune --older-than 30 --yes提示
数据库增长缓慢(典型:数百个会话 10-15 MB),会话历史为跨过去对话的
session_search回忆提供支持,因此自动清理默认是禁用的。如果你正在运行高负载的网关/定时任务工作负载,其中state.db显著影响性能(观察到的失败模式:384 MB 的 state.db 包含约 1000 个会话,导致 FTS5 插入和/resume列表变慢),请启用它。使用hermes sessions prune进行一次性清理,而无需打开自动清理。