进阶教程
Agent持久化内存
Hermes Agent持久化内存评测:2文件3级扫描告别重启失忆
摘要
HermesAgent采用双文件持久化内存,字符上限3575(约1300tokens),固定预算避免成本失控。通
Hermes Agent 持久化内存:双文件三级扫描,1300 Tokens 固定预算实现跨会话记忆
在操作复杂AI Agent时,一个高频痛点是被迫应对会话中断后的记忆空白。你花大量时间向Agent解释项目架构、编码约定与个人偏好,一旦终端会话关闭,所有上下文归零。即便在同一会话内,随着对话深入,早期关键信息也会因上下文窗口溢出而被自动截断。 传统方案依赖向量数据库存储历史对话,在需要时检索并注入上下文。但这引入了严重的成本不确定性——注入多少数据、检索多少内容、每次Prompt消耗多少Token,完全取决于随机变动的对话长度。 Hermes Agent采取了一套截然不同的策略:为Agent配备一本固定大小的笔记本,仅包含2个Markdown文件,总字符上限为3575。容量耗尽时,自动执行合并旧条目;新会话启动时,自动加载最新版本。该方案的核心不在于记忆更多,而是在限定预算内,优先保留最具价值的信息。1. 双文件存储,3575字符上限:极简内存模型
Hermes的持久化内存由两个Markdown文件构成,存放于`~/.hermes/memories/`目录: | 文件 | 用途 | 字符上限 | 约等价Token数 | |------|------|----------|----------------| | `MEMORY.md` | Agent的个人笔记:环境配置、项目约定、工具特性、经验总结 | 2200 | ~800 tokens | | `USER.md` | 用户画像:偏好、沟通风格、期望、工作习惯 | 1375 | ~500 tokens | 每个会话的固定开销约1300 Tokens,与对话内容长度无关。 **为何采用字符限制而非Token限制?** 源码注释(`memory_tool.py`)阐释了设计决策:不同模型的Tokenizer存在差异,同一文本在GPT与Claude上的Token计数可能显著不同。但字符计数是统一的——2200字符在任何模型上均保持一致。这种设计确保预算控制在模型切换时依然有效。 **条目分隔与操作机制** 内存条目使用`§`(段落标记)分隔,支持多行内容。Agent通过单一`memory`工具进行操作,`action`参数区分三种操作: - `add`:新增条目,触发字符预算检查 - `replace`:基于短子串匹配替换现有条目 - `remove`:基于短子串匹配删除现有条目 `replace`与`remove`无需提供完整条目原文,仅需一个能唯一定位目标条目的短子串。若子串匹配到多个不同条目,工具会报错并提示提供更具体的信息。  *图1:双文件存储模型——MEMORY.md与USER.md的字符预算分配与操作方式* **内存满载时的处理策略** 这是设计中最具巧思的部分。当`add`操作超出字符限制时,工具不会自动覆盖旧条目。它会返回一个错误,并附带当前使用量及现有条目列表: ```python # memory_tool.py 预算检查逻辑(简化) new_entries = entries + [content] new_total = len(ENTRY_DELIMITER.join(new_entries)) if new_total > limit: return { "success": False, "error": f"Memory at {current:,}/{limit:,} chars. " f"Adding this entry ({len(content)} chars) " f"would exceed the limit. " f"Replace or remove existing entries first.", "current_entries": entries, "usage": f"{current:,}/{limit:,}", } ``` Agent被引导执行一条策展路径:读取现有条目→识别可合并或删除的冗余信息→使用`replace`合并→再执行`add`操作。这一过程实际上强制Agent定期整理记忆,维持信息密度。2. 冻结快照:为何内存更新不影响KV缓存?
Hermes内存系统最精巧的设计是冻结快照模式。 **会话生命周期中的快照机制** ```markdown 会话启动 ├── load_from_disk() │ ├── 读取 MEMORY.md → live state │ ├── 读取 USER.md → live state │ ├── 安全扫描 → sanitized entries │ └── 生成 _system_prompt_snapshot(冻结,不可变) │ System Prompt注入 format_for_system_prompt() → 返回 frozen snapshot │ 会话中途写入 add/replace/remove → 更新 live state + 写入磁盘 但 system prompt 中的 snapshot 不变 │ 下一个会话 load_from_disk() → 新的 frozen snapshot ``` **冻结的必要性** 源码注释(`memory_tool.py` 第11-14行)给出了明确解释: 背景知识:大模型推理时,system prompt部分(前缀)会被缓存为KV Cache。若前缀不变,后续每个Prompt均可复用该缓存,节省重复计算。一旦前缀有任何修改,整个缓存失效。 如果每次内存更新都同步修改system prompt,Agent每记住一个新信息,就等同于废弃之前所有缓存。Token成本将随着会话推进不断攀升。冻结快照从根本上解决了这一问题——在整个会话期间,前缀始终保持不变。  *图2:冻结快照模式的完整生命周期——从加载到冻结到下一会话* **系统提示中的内存注入格式** 内存注入到system prompt时,格式如下: ```markdown ══════════════════════════════════════════════ MEMORY (your personal notes) [67% — 1,474/2,200 chars] ══════════════════════════════════════════════ User's project is a Rust web service at ~/code/myapi using Axum + SQLx § This machine runs Ubuntu 22.04, has Docker and Podman installed § User prefers concise responses, dislikes verbose explanations ``` Header中包含使用率百分比与字符计数。Agent能够感知当前已占用67%的空间,在做出写入决策时拥有更充分的判断依据。 这比无限制地向上下文填充信息更为高效——Agent清楚预算有限,会更有选择性地进行记忆。3. 三级安全扫描 + 外部漂移检测
持久化内存天然存在安全隐患:存储的内容在每个新会话中都会被加载到system prompt里。若有人在`MEMORY.md`中植入了恶意指令,等于在每个会话中都埋下后门。 Hermes采用双重防御机制应对该问题。 **三级威胁扫描** 威胁模式定义在`tools/threat_patterns.py`中,分为三个范围: | 范围 | 适用场景 | 检测内容 | |------|----------|----------| | `all` | 所有文本 | 经典注入、数据泄露 | | `context` | 上下文文件、内存、工具结果 | C2/promptware/角色劫持 | | `strict` | 内存写入、Skill安装 | 持久化攻击/SSH后门/URL泄露 | 内存写入使用最严格的`strict`级别。扫描发生在两个时间点: - 写入时:每次`add`/`replace`操作前执行扫描 - 加载时:`load_from_disk()`时执行扫描,命中条目在快照中替换为`[BLOCKED: ...]`占位符 注意:加载时扫描不会删除原始条目,仅在新会话的快照中进行屏蔽。用户仍可查看并手动清理被标记的条目。这一设计相对克制——误报时不会造成数据丢失。 **外部漂移检测** 这是一项独特的安全机制,用于检测`MEMORY.md`/`USER.md`是否被Hermes之外的进程修改过,例如patch工具、shell追加、手动编辑或另一个并发会话。 检测逻辑(`memory_tool.py` → `_detect_external_drift()`)基于两个信号: - 往返不一致性:将文件内容解析为条目再序列化还原,与原始文件进行比对。不一致表明有人绕过Hermes的格式规范修改了文件 - 条目大小溢出:单个条目超过整个存储的字符限制。正常操作不会出现这种情况 检测到漂移时,Hermes会: - 备份当前文件为`.bak.{timestamp}` - 拒绝修改操作,返回错误 - 要求用户手动解决漂移后重试 在并发场景下,这一机制尤为重要。两个会话同时向`MEMORY.md`写入数据,若没有漂移检测,后写入的会覆盖先写入的,且两个会话的live state与磁盘状态将出现不一致。  *图3:三级威胁扫描 + 外部漂移检测——Hermes内存的双层安全防御体系*4. 跨会话召回:持久化内存 + FTS5全文搜索
持久化内存与会话搜索是互补关系,而非替代关系。 | 维度 | Persistent Memory | Session Search | |------|-------------------|----------------| | 容量 | ~1300 tokens(固定) | 无限(所有历史会话) | | 速度 | 即时(在system prompt中) | ~20ms FTS5查询 | | Token成本 | 每个prompt固定 | 按需(仅搜索时消耗) | | 管理方式 | Agent手动策展 | 自动(所有会话存入SQLite) | | 信息类型 | 精炼的关键事实 | 原始对话全文 | **Session Search的三种模式** 所有CLI及消息会话自动存入`~/.hermes/state.db`(SQLite + FTS5索引)。Agent通过`session_search`工具调用: | 模式 | 参数 | 用途 | |------|------|------| | Discovery | `query` | FTS5搜索 + 会话lineage去重 + top N结果 | | Scroll | `session_id` + `around_message_id` | 按锚点上下滚动浏览 | | Browse | 无参数 | 返回最近会话列表 | 两个值得关注的细节: - 零LLM成本:搜索结果直接返回数据库中的原始消息,不经过LLM摘要处理。节省了一次模型调用 - Lineage去重:通过`parent_session_id`链追踪到根会话,排除当前会话链路中已有的消息。避免搜索到自身的历史发言 **Memory Nudge:强制Agent定期回顾** Hermes还包含一个不易察觉的机制——Memory Nudge。当连续N个用户回合未使用`memory`工具时,系统会注入一个提醒,引导Agent检查是否有值得持久化的事实。 ```python # conversation_loop.py(简化) if (agent._memory_nudge_interval > 0 and "memory" in agent.valid_tool_names and agent._memory_store): agent._turns_since_memory += 1 if agent._turns_since_memory >= agent._memory_nudge_interval: _should_review_memory = True agent._turns_since_memory = 0 ``` 会话恢复时,通过取模运算保持原始节奏(`prior_user_turns % nudge_interval`),避免在边界处重复触发。这一细节体现了设计者在用户体验上的深思熟虑。5. 实战配置:从安装到生产环境
**安装与初始化** ```bash # 安装Hermes Agent curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash # 启动交互式CLI hermes # 配置模型(按提示操作) hermes model # 配置工具 hermes tools # 完整设置向导(推荐新手使用) hermes setup # 环境诊断 hermes doctor ``` **内存目录结构** ```markdown ~/.hermes/ ├── memories/ │ ├── MEMORY.md # Agent个人笔记 │ ├── USER.md # 用户画像 │ ├── MEMORY.md.lock # 文件锁 │ └── USER.md.lock # 文件锁 ├── state.db # SQLite会话数据库(FTS5) ├── config.yaml # 全局配置 ├── SOUL.md # Agent人格定义 └── plugins/ # 用户安装的插件 ``` **关键配置项** ```yaml # ~/.hermes/config.yaml memory: memory_enabled: true # 启用MEMORY.md user_profile_enabled: true # 启用USER.md memory_char_limit: 2200 # MEMORY.md字符上限 user_char_limit: 1375 # USER.md字符上限 provider: "" # 外部memory provider,空字符串表示仅内置 ``` 默认值无需修改即可运行。可以调高`memory_char_limit`和`user_char_limit`,但需要权衡:字符预算越大,每个prompt的固定Token开销就越高。 **外部Memory Provider** Hermes支持8种外部Memory Provider作为内置内存的补充: | Provider | 特点 | |----------|------| | Honcho | 方言式用户建模、知识图谱 | | OpenViking | 语义搜索 | | Mem0 | 自动事实提取 | | Hindsight | 跨会话用户建模 | | Holographic | — | | RetainDB | — | | ByteRover | — | | Supermemory | Cloudflare Workers上的长期记忆 | 几点注意事项: - 同一时间仅允许激活一个外部Provider(`MemoryManager`强制执行) - 外部Provider不会替代内置内存,而是作为补充 - 配置方式:`hermes memory setup`(交互式选择)或直接修改`config.yaml` 如果你仅需跨会话记住关键事实,内置内存已足够。若需要语义搜索或更复杂的用户建模能力,再考虑外接Provider。6. 生产级最佳实践
**多项目环境下的隔离策略** Hermes支持通过profile覆盖内存目录路径(`hermes_constants.get_hermes_home()`动态解析)。在多个项目间切换时,建议为每个项目设置独立的profile,避免不同项目的记忆相互干扰。 记忆污染是真实存在的:Agent在项目A中记住的用户偏好简洁回复,可能影响其在项目B中的行为。若项目A是Rust后端、项目B是前端,两者的代码规范、工具链、测试习惯均不同,混用只会导致Agent记忆失效。 **防记忆污染** 几点实用建议: - 定期审查内存条目:直接查看`~/.hermes/memories/MEMORY.md`,确认其中没有过时或矛盾的信息 - 利用字符预算约束:2200字符的限制是特性而非缺陷。它天然阻止了内存无限膨胀 - 关注使用率百分比:system prompt header中的百分比是Agent策展行为的信号。超过80%时主动合并条目 - 善用漂移检测:若发现`.bak.{timestamp}`备份文件出现,说明有外部程序修改过内存文件,需排查原因 **容量管理的实操建议** 当内存接近上限时,Agent的策展路径是:读取→评估→合并/删除→再添加。你可以通过以下方式辅助该过程: - 在对话中明确告知Agent:帮我整理一下MEMORY.md,把过时的条目清理掉 - 定期检查`MEMORY.md`,手动合并相关条目 - 若发现Agent频繁因预算不足无法添加新条目,说明可能需要提高`memory_char_limit` **系统提示的三层缓存结构** Hermes的system prompt分为三层组装,与内存的冻结快照紧密配合: | 层 | 内容 | 缓存行为 | |------|------|----------| | stable | Agent身份、工具指南、Skill索引 | 跨会话稳定 | | context | 上下文文件(AGENTS.md等) | 会话级稳定 | | volatile | Memory + USER profile + 时间戳 | 每次会话可能变化 | 内存属于volatile层,但由于在会话期间冻结,因此在该会话内依然是稳定的。三层结构从稳定到不稳定排列,最大化KV Cache的复用率。7. 与传统方案对比:字符预算 vs 向量注入
将Hermes的方案与传统向量数据库+上下文注入进行对比,差异明显: | 维度 | 传统向量注入 | Hermes字符预算 | |------|--------------|-----------------| | Token开销 | 不确定(检索量可变) | 固定~1300 tokens/会话 | | 成本可预测性 | 难以预算 | 精确到字符 | | 遗忘风险 | 高(上下文膨胀后被截断) | 低(冻结快照,每会话始终可见) | | 信息质量 | 取决于检索质量 | Agent手动策展,密度高 | | 跨会话搜索 | 需要额外向量搜索 | 内置FTS5 session search | | 安全防护 | 通常无注入防护 | 三级威胁扫描+外部漂移检测 | | 并发安全 | 通常无保护 | 原子写入+文件锁+漂移检测 |  *图4:字符预算 vs 向量注入——两种Agent记忆方案的核心差异* 两种方案并非简单的优劣之分。 向量注入适合记忆量大、无需精确预算的场景。例如客服Agent,历史对话可能有数千条,检索top-k注入即可,无需对每条数据进行精确管理。 Hermes的字符预算适合需要精确控制成本的场景。例如长时间运行的个人Agent,你可以精确计算每个prompt的Token消耗,精准规划月度开销。由于预算有限,Agent被迫只保留高价值信息,记忆质量反而更高。总结
Hermes Agent的持久化内存系统,核心思路可概括为三条: 用固定预算替代无限制增长。2个文件、3575字符上限,每个会话固定~1300 Tokens。成本可控,预算可预测。 用冻结快照保持缓存稳定。会话期间内存只读不改,KV Cache从头到尾有效。新会话再加载新快照。 用安全机制保护持久化入口。三级威胁扫描防止注入攻击,外部漂移检测防止并发冲突,原子写入保证数据完整性。 36氪报道中的一个社区比喻流传颇广:OpenClaw负责干活,Hermes负责动脑。这个说法虽简化了两个项目的能力边界,但确实点出了Hermes的差异化——它不仅能干活,还能学会干活。 GitHub上两个月获得7.1万Star,峰值单日增长6400颗星。社区对“越用越聪明”这一特性的认可度很高。不过也需要客观看待:企业用户普遍还在观望,稳定性与中文支持是主要顾虑。项目目前版本为v0.14.0,距离生产级成熟仍有距离。 如果你的场景是个人开发或小团队协作,想尝试一个能记住事情的AI Agent,Hermes值得花一个下午研究。建议先将内置内存运行起来,理解字符预算与冻结快照的工作方式,再决定是否外接Memory Provider。 **相关资源** 官方文档:https://hermes-agent.nousresearch.com/docs/user-guide/features/memory GitHub仓库:https://github.com/NousResearch/hermes-agent来源:互联网
免责声明
本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。