Hermes Agent 完整记忆架构分析

Summary

Hermes 的记忆系统不是单一的 2200 chars 限制,而是一个多层、多模态的记忆架构,包含 5 个层级,总容量远超表面限制。2200 chars 只是”工作记忆”层,还有”长期记忆”、“程序记忆”、“情景记忆”和”外部记忆”层。


1. 记忆架构全景(5 层模型)

┌─────────────────────────────────────────────────────────────────┐
│                    HERMES 记忆架构 5 层模型                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  L1: 工作记忆 (Working Memory)                                   │
│  ├── MEMORY.md: 2200 chars (Agent 个人笔记)                      │
│  ├── USER.md: 1375 chars (用户画像)                              │
│  └── 注入方式:系统提示词,每次对话都携带                           │
│                                                                 │
│  L2: 程序记忆 (Procedural Memory)                                │
│  ├── Skills: 145+ 个技能文件                                     │
│  ├── 每个 SKILL.md: 无硬性限制 (通常 2-10KB)                     │
│  └── 注入方式:按需加载 (LLM 自主决定或用户触发)                   │
│                                                                 │
│  L3: 情景记忆 (Episodic Memory)                                  │
│  ├── SQLite 数据库 (state.db): 所有对话历史                       │
│  ├── FTS5 全文索引: 快速搜索                                     │
│  └── 检索方式:session_search 工具 (LLM 按需调用)                 │
│                                                                 │
│  L4: 语义记忆 (Semantic Memory)                                  │
│  ├── 外部 Memory Provider (可选):                                 │
│  │   ├── Honcho: AI 原生用户建模                                  │
│  │   ├── Mem0: 向量数据库记忆                                     │
│  │   ├── Hindsight: 对话洞察提取                                  │
│  │   └── 其他: Supermemory, ByteRover, OpenViking, RetainDB      │
│  └── 注入方式:prefetch 预取 + 按需检索                           │
│                                                                 │
│  L5: 知识库 (Knowledge Base)                                     │
│  ├── Obsidian Vault: ~/record/wyb-study/                         │
│  ├── 结构化目录: knowledge/20_study/, 05_references/ 等          │
│  └── 访问方式:文件工具直接读取                                   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

2. 各层详细分析

L1: 工作记忆 (Working Memory)

文件: ~/.hermes/memories/MEMORY.md + USER.md

容量:

  • MEMORY.md: 2200 chars
  • USER.md: 1375 chars
  • 总计: 3575 chars

特性:

  • 每次对话强制注入到系统提示词
  • 使用 § 作为条目分隔符
  • 采用冻结快照模式:会话开始时加载,会话中写入不影响当前对话(保持 prefix cache 稳定)
  • 文件锁保护并发安全

设计原则:

# memory_tool.py:118
def __init__(self, memory_char_limit: int = 2200, user_char_limit: int = 1375):

为什么限制这么小?

  • 系统提示词需要保持精简,避免占用过多 context window
  • 只存储最核心、最频繁使用的信息
  • 类似于人类的”工作记忆”(7±2 个组块)

L2: 程序记忆 (Procedural Memory)

文件: ~/.hermes/skills/**/*.md

容量:

  • 145+ 个 skills
  • 每个通常 2-10KB
  • 总计: 约 500KB-1MB

特性:

  • 按需加载(不全部注入系统提示)
  • 系统提示中只有分类索引(skill 名称 + 简短描述)
  • LLM 自主决定何时加载(skill_view(name))
  • 支持条件激活(fallback_for_*, requires_*)

发现机制:

# skill_utils.py:440-451
def iter_skill_index_files(skills_dir: Path, filename: str):
    for root, dirs, files in os.walk(skills_dir, followlinks=True):
        dirs[:] = [d for d in dirs if d not in EXCLUDED_SKILL_DIRS]
        if filename in files:
            matches.append(Path(root) / filename)

注入方式:

系统提示词中的 skill 索引格式:
## Skills (mandatory)
<available_skills>
  category:
    - skill-name: brief description
</available_skills>

Only proceed without loading a skill if genuinely none are relevant.

L3: 情景记忆 (Episodic Memory)

文件: ~/.hermes/state.db (SQLite)

容量:

  • 无硬性限制(受磁盘空间限制)
  • FTS5 全文索引支持快速搜索
  • 实际可存储: 数万条对话记录

表结构:

-- sessions 表:会话元数据
CREATE TABLE sessions (
    id TEXT PRIMARY KEY,
    source TEXT NOT NULL,          -- 'cli', 'telegram', 'feishu' 等
    user_id TEXT,
    model TEXT,
    started_at REAL NOT NULL,
    ended_at REAL,
    message_count INTEGER DEFAULT 0,
    tool_call_count INTEGER DEFAULT 0,
    input_tokens INTEGER DEFAULT 0,
    output_tokens INTEGER DEFAULT 0,
    ...
);
 
-- messages 表:完整对话历史
CREATE TABLE messages (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    session_id TEXT NOT NULL,
    role TEXT NOT NULL,            -- 'system', 'user', 'assistant', 'tool'
    content TEXT,
    tool_calls TEXT,
    reasoning TEXT,
    timestamp REAL NOT NULL,
    ...
);
 
-- FTS5 虚拟表:全文搜索
CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(
    content,
    content='messages',
    content_rowid='id'
);

检索机制:

# session_search_tool.py:325-420
def session_search(query: str, role_filter: str = None, limit: int = 3):
    # 1. FTS5 搜索匹配消息
    raw_results = db.search_messages(query=query, limit=50)
    
    # 2. 解析子会话到父会话(压缩/委派链)
    resolved_sid = _resolve_to_parent(raw_sid)
    
    # 3. 并行摘要匹配会话(使用辅助 LLM)
    results = _run_async(_summarize_all())
    
    # 4. 返回结构化摘要
    return json.dumps({"results": summaries})

典型工作流:

用户: "我们上次讨论的 PX4 日志清理路径是什么?"
  ↓
Agent 调用 session_search(query="PX4 日志清理")
  ↓
FTS5 搜索 → 找到匹配会话 → 并行摘要 → 返回结果
  ↓
Agent: "上次我们讨论的路径是 ~/code/PX4-Autopilot/build/px4_sitl_default/instance_*/log/*"

L4: 语义记忆 (Semantic Memory)

外部 Memory Providers(可选,只能启用一个):

Provider类型特点容量
HonchoAI 原生用户建模语义搜索 + 用户画像 + 辩证问答无限(云端)
Mem0向量数据库语义相似度检索取决于向量库
Hindsight对话洞察提取自动提取模式/教训无限
Supermemory知识图谱实体关系建模无限
ByteRover长期记忆对话压缩 + 检索无限

架构:

# memory_manager.py:203-247
def add_provider(self, provider: MemoryProvider):
    # 只允许一个外部 provider
    if not is_builtin:
        if self._has_external:
            logger.warning("Rejected... Only one external memory provider is allowed")
            return
        self._has_external = True

生命周期:

# memory_provider.py:15-31
initialize()          # 会话启动时初始化
system_prompt_block()  # 静态文本注入系统提示
prefetch(query)        # 每次对话前预取相关上下文
sync_turn(user, asst)  # 每轮对话后异步写入
shutdown()             # 会话结束时清理

Honcho 示例:

# plugins/memory/honcho/__init__.py:36-80
PROFILE_SCHEMA = {
    "name": "honcho_profile",
    "description": "Retrieve or update a peer card..."
}
 
SEARCH_SCHEMA = {
    "name": "honcho_search",
    "description": "Semantic search over Honcho's stored context..."
}

L5: 知识库 (Knowledge Base)

文件: ~/record/wyb-study/ (Obsidian Vault)

容量:

  • 无限制(文件系统)
  • 结构化目录组织
  • Git 同步

目录结构:

knowledge/
├── 00_tutorials/        # 教程和配置指南
├── 05_references/       # 参考资料
│   ├── books/           # 书籍
│   ├── papers/          # 论文笔记
│   ├── courses/         # 课程
│   └── tools_websites/  # 工具网站
├── 10_seminar/          # 研讨会笔记
├── 20_study/            # 系统学习材料
│   ├── llm/             # LLM 基础
│   ├── agent/           # Agent 技能/工具
│   ├── agent_memory/    # 记忆机制
│   └── algorithms/      # 算法
└── 30_projects/         # 项目设计
    └── swarm_drone/     # 多无人机系统

访问方式: 文件工具直接读取(read_file, search_files)


3. 记忆系统协作机制

3.1 对话流程中的记忆注入

┌─────────────────────────────────────────────────────────────────┐
│                     单次对话记忆注入流程                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. 会话启动                                                     │
│     ├── 加载 L1: MEMORY.md + USER.md → 冻结快照                  │
│     ├── 加载 L4: 外部 Provider initialize()                     │
│     └── 构建系统提示词:                                          │
│         ├── 基础指令                                             │
│         ├── L1 工作记忆 (冻结)                                   │
│         ├── L4 系统提示块 (如有)                                 │
│         ├── Skills 索引 (分类列表)                               │
│         └── 其他指导 (MEMORY_GUIDANCE, SKILLS_GUIDANCE 等)       │
│                                                                 │
│  2. 用户输入                                                     │
│     ├── L4: prefetch(query) → 预取相关上下文                     │
│     └── 注入 <memory-context> 标签包裹的检索结果                  │
│                                                                 │
│  3. LLM 响应                                                     │
│     ├── 根据系统提示中的 Skills 索引判断是否需要加载 skill        │
│     ├── 如需 → 调用 skill_view(name) → 加载完整 skill 内容       │
│     ├── 如需历史 → 调用 session_search(query) → 检索对话历史     │
│     └── 如需知识 → 使用文件工具读取知识库                        │
│                                                                 │
│  4. 对话结束                                                     │
│     ├── L1: sync_turn(user, asst) → 异步写入 MEMORY.md/USER.md  │
│     ├── L4: sync_turn(user, asst) → 异步写入外部 Provider        │
│     └── L3: 自动保存到 state.db                                  │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

3.2 记忆分层决策树

需要保存信息时:
│
├─ 这是用户偏好/身份/沟通风格?
│   └─ 是 → 保存到 USER.md (L1)
│
├─ 这是环境配置/工具特性/项目约定?
│   └─ 是 → 保存到 MEMORY.md (L1)
│
├─ 这是程序性知识/工作流/最佳实践?
│   └─ 是 → 创建/更新 Skill (L2)
│
├─ 这是对话历史/任务结果/临时状态?
│   └─ 是 → 自动保存到 state.db (L3)
│   └─     需要时通过 session_search 检索
│
├─ 这是用户画像/长期模式/语义关系?
│   └─ 是 → 保存到外部 Provider (L4)
│
└─ 这是系统化知识/学习笔记/参考资料?
    └─ 是 → 保存到知识库 (L5)

4. 2200 chars 真的够用吗?

答案:作为工作记忆,够用;作为唯一记忆,不够。

关键设计哲学:

  • 2200 chars 不是”总记忆”,而是”工作记忆”
  • 类似于人类的”短期记忆”(7±2 个组块)
  • 更多信息存储在 L2-L5 层,按需检索

实际容量对比:

层级容量访问频率延迟
L1: 工作记忆3,575 chars每次对话0ms (已注入)
L2: 程序记忆~1MB按需加载~100ms (tool call)
L3: 情景记忆无限FTS5 搜索~500ms (搜索 + 摘要)
L4: 语义记忆无限语义检索~1s (向量搜索)
L5: 知识库无限文件读取~50ms (本地文件)

优化策略:

  1. 分层存储:核心原则在 L1,详细信息在 L2-L5
  2. 按需加载:不把所有信息都塞进系统提示
  3. 冻结快照:保持 prefix cache 稳定,提升性能
  4. 外部扩展:通过 Provider 插件无限扩展

5. 关键陷阱与最佳实践

5.1 常见陷阱

陷阱现象解决方案
记忆体溢出2200 chars 满了无法添加先 remove 旧条目,再 add 新条目
写入不生效会话中写入的记忆当前对话看不到这是设计:冻结快照模式,下次会话生效
重复保存相同信息保存到多个层级遵循决策树,每类信息只存一处
Skill 未触发LLM 不知道有相关 skill在 description 中包含关键词

5.2 最佳实践

  1. L1 只存核心:用户偏好、关键配置、不可变规则
  2. L2 存程序:工作流、最佳实践、陷阱记录
  3. L3 自动管理:对话历史自动保存,无需手动操作
  4. L4 按需启用:复杂用户建模场景启用 Honcho/Mem0
  5. L5 结构化:按主题分类,便于检索

6. 配置示例

启用 Honcho 记忆 Provider

# ~/.hermes/config.yaml
memory:
  provider: honcho
 
# ~/.hermes/honcho.json
{
  "api_key": "your-api-key",
  "app_id": "your-app-id"
}

查看记忆状态

hermes memory status

手动管理记忆

# 添加记忆
memory(action='add', target='memory', content='用户偏好中文交互')
 
# 替换记忆
memory(action='replace', target='memory', 
       old_text='旧内容', new_content='新内容')
 
# 搜索历史对话
session_search(query='PX4 日志清理')

References

  • 源码路径:
    • agent/memory_manager.py - 记忆管理器
    • agent/memory_provider.py - Provider 基类
    • tools/memory_tool.py - 工作记忆工具
    • tools/session_search_tool.py - 情景记忆检索
    • plugins/memory/honcho/__init__.py - Honcho 实现
  • 用户记忆文件:
    • ~/.hermes/memories/MEMORY.md
    • ~/.hermes/memories/USER.md
    • ~/.hermes/state.db


● main|UTF-8|Markdown金乌意 v1.0