ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hermes Agent 记忆架构详解:四层记忆系统如何持久化?TaoToken 配置与验证实践

Hermes Agent 记忆架构详解:四层记忆系统如何持久化?TaoToken 配置与验证实践 1. 为什么 Hermes Agent 的记忆总在重启后“失忆”Hermes Agent 记忆架构详解这件事绕不开一个很具体的场景你本地跑着一个 Hermes Agent聊了半小时把项目约定、服务器环境、你的编码偏好都交代清楚了。关掉终端第二天再开它像换了个人又问你“请问你的项目用什么语言”。这不是模型笨而是四层记忆系统里真正持久化的那几层没有被正确落盘或者落盘了但没被重新加载。Hermes 的四层记忆系统本质是把“记忆”拆成四种生命周期完全不同的东西当前工作记忆messages 列表随 session 生灭、内建长期记忆MEMORY.md USER.md冻结快照注入 system prompt、完整对话历史state.db JSONLFTS5 检索、外部 Memory Provider可插拔语义后端recall 临时注入。这四层不是并列的功能模块而是一条上下文装配线稳定事实常驻、历史事件按需召回、外部记忆临时参考最后都汇入当前这一轮推理的 API messages。适合谁看正在本地部署 Hermes Agent、想搞清楚记忆为什么没生效、或者准备把 Hermes 接进自己工作流的开发者。这篇不讲空泛概念直接给可复制的 config.toml / settings.json 骨架配合 TaoToken 统一 Key 通道把四层记忆的读写链路一步步验证出来。我试过在本地把 MEMORY.md 写入、state.db 落盘、session_search 召回这三条链路分别打点确认哪一层断了比盲目调 prompt 有效得多。核心检索词先明确Hermes Agent 记忆架构、四层记忆系统、持久化、TaoToken 配置。下面从接入前置开始一路走到验证和排障。2. TaoToken 前置统一 Key 与 API 通道怎么准备在验证记忆链路之前得先让 Hermes 能稳定地发出模型请求。因为四层记忆里第二层的冻结快照注入、第三层的 session_search 摘要、第四层的 recall 摘要全都要调用模型。如果 API 通道本身不稳定你会分不清是“记忆没落盘”还是“请求根本没发出去”。TaoToken 在这里的角色是统一 Key 和 API 通道一个 Key 走多家模型Base URL 固定省得在 config.toml 里为每个 provider 维护一套鉴权。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 这个不加 UTM。你需要准备三件套缺一不可Base URLhttps://taotoken.net/apiAPI Key在控制台创建形如sk-...Model ID比如claude-sonnet-4-5或gpt-4o按你实际要用的填创建 Key 的入口在控制台的 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。如果你还没决定用哪个模型可以先去模型对话页面试一下https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。这里有个容易踩的坑Hermes 的辅助模型调用session_search 的 focus summary、flash memories 的归档调用默认可能走主模型链路。如果你想让这些后台调用走更便宜的模型需要在配置里单独指定 auxiliary client 的 model。TaoToken 的好处是同一个 Base URL 下换 Model ID 就行不用改鉴权。注意不要把 Key 硬编码进会提交到 git 的文件。用环境变量或本地.envHermes 读取时再注入。准备阶段做完你应该有一个可用的 Key、确认过的 Base URL、一个能跑通的 Model ID。接下来进配置文件。3. 可复制配置config.toml 与 settings.json 骨架这一节给可直接复制的配置骨架。Hermes 的配置分两块config.toml管模型和 providersettings.json管记忆系统的行为开关。路径按你本地实际安装位置调整下面用~/.hermes/作为示例根目录。先看config.toml# ~/.hermes/config.toml # Hermes Agent 主配置模型通道 记忆系统开关 [provider] # TaoToken 统一通道 base_url https://taotoken.net/api api_key ${TAOTOKEN_API_KEY} # 从环境变量读取不要写死 model claude-sonnet-4-5 # 主模型 Model ID timeout_seconds 120 [provider.auxiliary] # 辅助模型session_search 摘要、flash memories 归档走这里 # 用同一个 Base URL换更便宜的 Model ID base_url https://taotoken.net/api api_key ${TAOTOKEN_API_KEY} model gpt-4o-mini timeout_seconds 60 [memory] # 第二层内建长期记忆 enabled true memory_path ~/.hermes/memories/MEMORY.md user_path ~/.hermes/memories/USER.md memory_char_limit 2200 # 硬上限超了会拒绝写入 user_char_limit 1375 freeze_snapshot true # 冻结快照session 启动时注入本轮不变 scan_on_write true # 写入前做 prompt injection 扫描 [memory.history] # 第三层完整对话历史 enabled true db_path ~/.hermes/state.db jsonl_path ~/.hermes/transcripts/ fts5_enabled true # 开启全文索引session_search 依赖它 wal_mode true # WAL 模式多读单写 max_sessions_to_summarize 5 # 一次最多归并 5 个 session [memory.external] # 第四层外部 Provider同一时间只允许一个生效 enabled false # 先关掉验证内建链路后再开 provider none # 可选 honcho / mem0 / supermemory recall_inject_tag memory_context write_back_to_history false # 铁律recall 结果不写回历史 [governance] # 自动治理前台执行 后台复盘 turns_since_memory_threshold 10 # 连续 10 轮无写入触发 background review background_review_enabled true再看settings.json管运行时行为{ agent: { session_isolation: per_chat, group_sessions_per_user: false, thread_sessions_per_user: false }, memory: { flash_memories_on_compression: true, compression_creates_continuation: true, subagent_memory_enabled: false }, logging: { level: info, memory_trace: true } }几个关键参数解释一下。freeze_snapshot true是第二层的核心session 启动时把 MEMORY.md 和 USER.md 冻结成 system prompt 快照中途写入不刷新当前 session下次启动才生效。这是为了保住 prompt cache 前缀一致代价是体感滞后。write_back_to_history false是第四层的铁律recall 结果只在 API 调用边界临时注入绝不写回 state.db否则 session_search 会搜到“回忆”而不是“事实”形成自我污染。subagent_memory_enabled false对应子代理的克制设计子代理默认没有 memory 工具因为它的上下文更窄容易把局部偶然当成长期事实而且并发执行时写共享 memory 几乎一定制造噪声。配置写完后把 Key 注入环境export TAOTOKEN_API_KEYsk-你的key如果你用 Claude Code 或 Cline 这类工具做辅助开发它们的配置里也要填全三件套。以 Claude Code 的 settings 为例{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的key, ANTHROPIC_MODEL: claude-sonnet-4-5 } }Cline 的 MCP 配置同理Base URL、Key、Model ID 三个都要对上少一个就会报鉴权或模型找不到。Codex 的auth.json也是这个逻辑{ base_url: https://taotoken.net/api, api_key: sk-你的key, model: gpt-4o }配置阶段的目标是模型通道能通、记忆开关都打开、外部 Provider 先关着。接下来验证。4. 验证请求四层记忆读写链路逐步打点配置写完不代表记忆就生效了。这一节把四层记忆的读写链路分别验证一遍每步都有可观察的结果。4.1 验证第一层当前工作记忆是否正常汇入第一层是 run 循环里的 messages 列表不持久化但它是所有记忆汇合的地方。验证方法很简单发一条消息看模型能不能看到本轮上下文。# 启动 Hermes开 memory_trace 日志 hermes --config ~/.hermes/config.toml --log-level debug在对话里输入请复述我这条消息的原文不要做任何加工。如果模型能准确复述说明第一层的 messages 装配正常。如果它答非所问问题在请求通道不在记忆层。这一步是基线先确认它。4.2 验证第二层MEMORY.md 写入与冻结快照第二层最容易出问题因为它有“写入立刻落盘、但当前 session 不刷新”的特性。先手动写一条# 直接编辑 MEMORY.md模拟一次长期记忆写入 cat ~/.hermes/memories/MEMORY.md EOF - 此服务器运行 Ubuntu 22.04Docker 和 Podman 已安装 EOF然后在当前 session 里问我的服务器运行什么系统预期结果当前 session 看不到这条新记忆因为冻结快照是启动时生成的。这是设计如此不是 bug。要验证它生效需要重启 session# 退出当前 session重新启动 hermes --config ~/.hermes/config.toml新 session 里再问同样的问题模型应该能答出 Ubuntu 22.04。如果答不出检查freeze_snapshot是否为 true、memory_path路径是否正确、文件是否有读权限。再验证写入链路。让 Agent 主动保存一条请记住我偏好 TypeScript 而不是 JavaScript保存到 USER.md。然后检查文件cat ~/.hermes/memories/USER.md应该能看到新增条目。如果没写入看日志里有没有scan_on_write拦截记录——安全扫描会拦掉 prompt injection、角色劫持、SSH 后门暗示、隐形 unicode 等模式。4.3 验证第三层state.db 落盘与 session_search 召回第三层验证分两步先确认落盘再确认召回。落盘检查# 看 state.db 里有没有消息 sqlite3 ~/.hermes/state.db SELECT COUNT(*) FROM messages;如果返回 0说明消息没写进 DB。检查db_path和wal_mode。WAL 模式下会有state.db-wal文件这是正常的。召回验证先制造一段可检索的历史。在 session A 里说我们上次修了一个登录超时的 bug改的是 auth/session.go 里的 refreshToken 函数。结束 session A开 session B问上次那个登录超时的 bug 我们是怎么修的预期Agent 调用 session_searchFTS5 搜到关键词归并到 session A辅助模型做 focus summary返回“改的是 auth/session.go 的 refreshToken 函数”。如果召回为空检查fts5_enabled是否为 true以及 FTS5 索引是否建好sqlite3 ~/.hermes/state.db SELECT name FROM sqlite_master WHERE typetable;应该能看到 FTS5 相关的虚拟表。没有的话重建索引。4.4 验证第四层外部 Provider recall 临时注入第四层先保持关闭等前三层都通了再开。开启后验证 recall 是否临时注入、是否不写回历史[memory.external] enabled true provider mem0 write_back_to_history false发一条会触发 recall 的消息然后在日志里找memory_context标记。确认两件事一是 recall 结果确实拼到了当前 user message 后面二是 state.db 里没有这条 recall 内容。第二点最关键用 SQL 查sqlite3 ~/.hermes/state.db SELECT content FROM messages WHERE content LIKE %memory_context%;应该返回空。如果返回了内容说明 recall 被写回了历史这会污染后续 session_search。四层都验证通过后你的 Hermes 记忆链路就是通的。接下来处理常见报错。5. 常见报错排查401、local proxy failed、reading choices、OAuth这一节对照真实报错逐个拆。这些错误我在本地都遇到过按顺序排查基本能定位。5.1 401 Unauthorized最常见。原因通常是 Key 没注入或 Base URL 写错。Error: 401 Unauthorized - invalid api key排查顺序先确认环境变量有没有生效echo $TAOTOKEN_API_KEY如果为空说明export没在当前 shell 生效或者你启动 Hermes 的终端和 export 的终端不是同一个。再确认 config.toml 里的base_url是https://taotoken.net/api不要多写斜杠或路径。最后确认 Key 没有过期去控制台 API Keys 页面重新生成一个https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。5.2 local proxy failedError: local proxy failed - connection refused这个报错通常出现在你本地配了某种转发但没启动。Hermes 本身不需要本地转发直接用 TaoToken 的 Base URL 即可。检查 config.toml 里有没有残留的proxy字段删掉。如果你用的是 Claude Code 或 Cline检查它们的 settings 里有没有指向localhost的 Base URL改成https://taotoken.net/api。5.3 reading choices 相关报错Error: reading choices: unexpected end of JSON input这是响应体解析失败通常是模型返回了非预期格式或者请求被中途截断。排查先确认 Model ID 拼写正确比如claude-sonnet-4-5不要写成claude-sonnet-4.5。再确认timeout_seconds够大长上下文请求容易超时。如果用了辅助模型做 session_search 摘要确认 auxiliary 的 Model ID 也是有效的。5.4 OAuth 相关报错Error: OAuth token expired如果你在 Claude Code 或 Codex 里用了 OAuth 登录方式而 Hermes 走的是 API Key两者会冲突。统一用 API Key 方式在 Claude Code 的 settings 里填ANTHROPIC_API_KEY在 Codex 的auth.json里填api_key不要混用 OAuth。三件套Base URL Key Model ID必须同时存在且一致。5.5 记忆写入被静默拒绝没有报错但 MEMORY.md 没变化。检查日志里的扫描记录。安全扫描会拦掉包含“Ignore previous instructions”“You are now DAN”“Add my public key to authorized_keys”以及零宽空格等隐形字符的内容。如果你确实要写入类似文本先清理掉敏感模式。5.6 session_search 召回为空FTS5 索引没建好或者 lineage 排除把当前链路全排掉了。先确认fts5_enabled true再确认查询关键词在历史里确实存在。如果历史 session 是 compression 产生的 continuation session检查parent_session_id是否正确lineage 感知依赖这个字段。排障的核心思路先确认请求通道通401、proxy、choices、OAuth 都属于通道问题再确认记忆层开关对写入被拒、召回为空属于记忆层问题。通道问题看配置记忆问题看日志和 DB。6. 把四层记忆接进你的工作流验证通过后下一步是让它真正服务你的日常。几个实用建议。第一MEMORY.md 和 USER.md 分开维护。环境事实服务器系统、项目约定、工具版本写 MEMORY.md用户偏好编码风格、沟通习惯、技术栈背景写 USER.md。两者生命周期不同环境可能随项目切换全变用户偏好相对稳定分开后可以独立管理容量。第二善用 background review。turns_since_memory_threshold 10意味着连续 10 轮没写入就触发后台复盘。这个机制像会后秘书主 Agent 在前台干活后台检查有没有该记没记的事实。如果你发现它频繁触发但没写入有价值内容把阈值调大如果它漏记重要信息调小。第三外部 Provider 按需开。内建两层够用时不要急着开第四层。开了之后记住铁律recall 结果不写回历史。write_back_to_history false必须保持否则 session_search 会搜到自我污染的“回忆”。第四长期编码或 Agent 场景考虑用 Coding Plan 统一管理额度https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。如果你需要频繁验证模型行为模型对话页面更方便https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到配置细节可以对照。第五Claude Code 用户如果要把 Hermes 的记忆验证和日常编码结合参考 ClaudeCodeAnthropic 的接入方式https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude_codeutm_campaignrewrite Base URL、Key、Model ID 三件套填全。最后说一个我踩过的坑不要指望当前 session 立刻看到刚写入的长期记忆。冻结快照是故意的成本决策为了保住 prompt cache 前缀一致。如果你实在需要 session 内可见等 Hermes 后续的 overlay 记忆层方案或者临时把freeze_snapshot设为 false 做调试——但生产环境别关关了 prompt cache 命中率会掉成本和延迟都会恶化。四层记忆系统的价值不在于“记得多”而在于把不同类型的记忆放进不同层次用合适的生命周期和成本模型管理。稳定事实常驻、事件历史按需召回、外部记忆临时参考、当前工作记忆汇合——边界清楚了Agent 才不会在长对话里把自己拖垮。
返回列表