云计算百科
云计算领域专业知识百科平台

Hermes 记忆革命:四层记忆架构

Hermes 记忆革命:四层记忆架构如何让 Agent 从"金鱼"变成"知己"

说在前面

想象一个场景:你花了整个下午教 AI 助手学会了你的项目部署流程——哪个分支对应哪个环境、构建前要跑哪些检查、出错了怎么回滚。它完成得很好。你关掉终端,下班回家。

第二天早上,你打开电脑,对 AI 助手说:“帮我把昨天的改动部署到 staging。”

它问:“请问你的项目是用什么构建工具?”

这一刻的挫败感,所有用过传统 AI Agent 的人都不会陌生。Agent 的"失忆症"——每次会话结束,经验清零——是阻碍 Agent 从玩具走向工具的第一道墙。

Hermes 用了一套四层记忆架构来拆这面墙。这不是"多加一个向量库"那么简单,而是一套完整的认知记忆体系——从人类记忆模型中获得启发,通过工程化的手段落地,让 Agent 真正拥有"过去"。

本文逐层拆解这套记忆系统的设计。读完你会理解:

  • 四层记忆各自的定位、存储方案和工程实现
  • 四层之间的数据流转和协同机制
  • 这套设计与 LangChain Memory 的本质区别

  • 一、传统 Agent 为什么记不住:单层记忆的死胡同

    1.1 上下文窗口 ≠ 记忆

    传统 Agent 的"记忆"只有一种形式:把历史消息塞进模型的上下文窗口。

    这天然受限于两个硬约束:

    窗口有上限。不管是 200K 还是 1M tokens,总有装满的时候。旧的对话被截断、丢失,跟没发生过一样。

    线性排列,没有结构。上下文窗口里的消息是按时间顺序平铺的。Agent 无法区分"上周那个非常重要的部署流程"和"前天那两句无聊的寒暄"——在它看来,它们都是同等权重的文本片段。

    1.2 三种失败的补救方案

    方案做法为什么失败
    摘要法 每次对话结束让 LLM 写一段摘要,下次注入 摘要丢失细节;多次摘要后信息退化;摘要本身也占 token
    向量库法 把所有对话 embedding 后存向量库,检索相关片段注入 语义检索不可靠——“部署"能匹配到"部署”,匹配不到"上线"
    规则法 开发者手写规则决定记住什么、记多久 维护成本随规则数量指数增长;没有规则能覆盖所有场景

    这些方案共同的根本问题:它们把记忆当作"存数据"的问题,而不是"知识沉淀"的问题。存数据容易——加个向量库就行。但把数据变成能在未来被有效使用的知识——需要一套完整的工程架构。


    二、四层记忆的认知模型

    2.1 为什么是四层

    Hermes 的四层记忆模型直接借鉴了人类认知心理学中对记忆的分类:

    人类记忆定义Hermes 对应
    工作记忆 你正在有意识地思考的内容 Working Memory
    情景记忆 你记得发生在你身上的具体事件 Episodic Memory
    语义记忆 你知道的事实和概念 Semantic Memory
    程序性记忆 你会做的技能(骑车、游泳) Procedural Memory (Skills)

    这个分类不是拍脑袋的学术炫技。每一层解决一个工程上真实存在的问题,而且每一层需要完全不同的存储方案和检索策略。

    2.2 四层全景

    #mermaid-svg-N4qnE4wHTknKssmo{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-N4qnE4wHTknKssmo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-N4qnE4wHTknKssmo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-N4qnE4wHTknKssmo .error-icon{fill:#552222;}#mermaid-svg-N4qnE4wHTknKssmo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-N4qnE4wHTknKssmo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-N4qnE4wHTknKssmo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-N4qnE4wHTknKssmo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-N4qnE4wHTknKssmo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-N4qnE4wHTknKssmo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-N4qnE4wHTknKssmo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-N4qnE4wHTknKssmo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-N4qnE4wHTknKssmo .marker.cross{stroke:#333333;}#mermaid-svg-N4qnE4wHTknKssmo svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-N4qnE4wHTknKssmo p{margin:0;}#mermaid-svg-N4qnE4wHTknKssmo .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-N4qnE4wHTknKssmo .cluster-label text{fill:#333;}#mermaid-svg-N4qnE4wHTknKssmo .cluster-label span{color:#333;}#mermaid-svg-N4qnE4wHTknKssmo .cluster-label span p{background-color:transparent;}#mermaid-svg-N4qnE4wHTknKssmo .label text,#mermaid-svg-N4qnE4wHTknKssmo span{fill:#333;color:#333;}#mermaid-svg-N4qnE4wHTknKssmo .node rect,#mermaid-svg-N4qnE4wHTknKssmo .node circle,#mermaid-svg-N4qnE4wHTknKssmo .node ellipse,#mermaid-svg-N4qnE4wHTknKssmo .node polygon,#mermaid-svg-N4qnE4wHTknKssmo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-N4qnE4wHTknKssmo .rough-node .label text,#mermaid-svg-N4qnE4wHTknKssmo .node .label text,#mermaid-svg-N4qnE4wHTknKssmo .image-shape .label,#mermaid-svg-N4qnE4wHTknKssmo .icon-shape .label{text-anchor:middle;}#mermaid-svg-N4qnE4wHTknKssmo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-N4qnE4wHTknKssmo .rough-node .label,#mermaid-svg-N4qnE4wHTknKssmo .node .label,#mermaid-svg-N4qnE4wHTknKssmo .image-shape .label,#mermaid-svg-N4qnE4wHTknKssmo .icon-shape .label{text-align:center;}#mermaid-svg-N4qnE4wHTknKssmo .node.clickable{cursor:pointer;}#mermaid-svg-N4qnE4wHTknKssmo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-N4qnE4wHTknKssmo .arrowheadPath{fill:#333333;}#mermaid-svg-N4qnE4wHTknKssmo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-N4qnE4wHTknKssmo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-N4qnE4wHTknKssmo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-N4qnE4wHTknKssmo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-N4qnE4wHTknKssmo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-N4qnE4wHTknKssmo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-N4qnE4wHTknKssmo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-N4qnE4wHTknKssmo .cluster text{fill:#333;}#mermaid-svg-N4qnE4wHTknKssmo .cluster span{color:#333;}#mermaid-svg-N4qnE4wHTknKssmo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-N4qnE4wHTknKssmo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-N4qnE4wHTknKssmo rect.text{fill:none;stroke-width:0;}#mermaid-svg-N4qnE4wHTknKssmo .icon-shape,#mermaid-svg-N4qnE4wHTknKssmo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-N4qnE4wHTknKssmo .icon-shape p,#mermaid-svg-N4qnE4wHTknKssmo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-N4qnE4wHTknKssmo .icon-shape .label rect,#mermaid-svg-N4qnE4wHTknKssmo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-N4qnE4wHTknKssmo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-N4qnE4wHTknKssmo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-N4qnE4wHTknKssmo :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    会话结束压缩归档

    定期提炼事实提取

    经验固化流程抽象

    L4: 技能专用记忆 (Procedural Memory)

    存储: Markdown 文件.hermes/skills/

    生命周期: 永久存储,持续迭代

    内容: 自动提炼的Skill、工作流、操作步骤

    职责: 可执行经验的直接复用

    L3: 语义记忆 (Semantic Memory)

    存储: 向量数据库Chroma / Pinecone / Qdrant

    生命周期: 永久存储,自动更新

    内容: 用户偏好、项目事实、行业规则

    职责: 知识检索与推理增强

    L2: 情景记忆 (Episodic Memory)

    存储: SQLite + FTS5 全文索引

    生命周期: 长期存储

    内容: 历史对话摘要、任务记录、时间线

    职责: 跨会话事件回溯

    L1: 工作记忆 (Working Memory)

    存储: 模型上下文窗口

    生命周期: 当前会话

    内容: 本轮对话的全部上下文

    职责: 支撑实时推理

    核心洞察:四层之间不是"四个独立的数据库",而是数据的抽象层次逐级升高。工作记忆是原始交互数据,情景记忆是结构化事件,语义记忆是提炼后的事实,技能记忆是可执行的流程。每一层都在前一层的基础上做了压缩与升维。


    三、L1 工作记忆:不止是"把历史消息塞进上下文"

    3.1 上下文不是越大越好

    直觉上,上下文窗口越大,Agent 记得越多。但工程实践表明,上下文窗口变大带来了两个新问题:

    "中间丢失"效应。研究表明,LLM 对上下文窗口中间部分的信息注意力最低。你把一长串对话历史塞进去,Agent 可能准确地回忆开头和结尾,但中间的关键信息(比如某个重要的配置参数)可能被忽略。

    成本线性增长。API 调用的计费基于 token 数。200K token 的上下文窗口如果每次都装满,每轮对话的成本是 2K token 的 100 倍。

    3.2 Hermes 的策略:动态压缩 + 缓存复用

    Hermes 的工作记忆管理有三层优化:

    第一层:分层 Prompt 构建。 不是把所有东西揉成一个巨大的 System Prompt,而是分层组装:

    #mermaid-svg-d3CyH0h8yTfygJ5L{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-d3CyH0h8yTfygJ5L .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-d3CyH0h8yTfygJ5L .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-d3CyH0h8yTfygJ5L .error-icon{fill:#552222;}#mermaid-svg-d3CyH0h8yTfygJ5L .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-d3CyH0h8yTfygJ5L .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-d3CyH0h8yTfygJ5L .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-d3CyH0h8yTfygJ5L .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-d3CyH0h8yTfygJ5L .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-d3CyH0h8yTfygJ5L .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-d3CyH0h8yTfygJ5L .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-d3CyH0h8yTfygJ5L .marker{fill:#333333;stroke:#333333;}#mermaid-svg-d3CyH0h8yTfygJ5L .marker.cross{stroke:#333333;}#mermaid-svg-d3CyH0h8yTfygJ5L svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-d3CyH0h8yTfygJ5L p{margin:0;}#mermaid-svg-d3CyH0h8yTfygJ5L .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-d3CyH0h8yTfygJ5L .cluster-label text{fill:#333;}#mermaid-svg-d3CyH0h8yTfygJ5L .cluster-label span{color:#333;}#mermaid-svg-d3CyH0h8yTfygJ5L .cluster-label span p{background-color:transparent;}#mermaid-svg-d3CyH0h8yTfygJ5L .label text,#mermaid-svg-d3CyH0h8yTfygJ5L span{fill:#333;color:#333;}#mermaid-svg-d3CyH0h8yTfygJ5L .node rect,#mermaid-svg-d3CyH0h8yTfygJ5L .node circle,#mermaid-svg-d3CyH0h8yTfygJ5L .node ellipse,#mermaid-svg-d3CyH0h8yTfygJ5L .node polygon,#mermaid-svg-d3CyH0h8yTfygJ5L .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-d3CyH0h8yTfygJ5L .rough-node .label text,#mermaid-svg-d3CyH0h8yTfygJ5L .node .label text,#mermaid-svg-d3CyH0h8yTfygJ5L .image-shape .label,#mermaid-svg-d3CyH0h8yTfygJ5L .icon-shape .label{text-anchor:middle;}#mermaid-svg-d3CyH0h8yTfygJ5L .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-d3CyH0h8yTfygJ5L .rough-node .label,#mermaid-svg-d3CyH0h8yTfygJ5L .node .label,#mermaid-svg-d3CyH0h8yTfygJ5L .image-shape .label,#mermaid-svg-d3CyH0h8yTfygJ5L .icon-shape .label{text-align:center;}#mermaid-svg-d3CyH0h8yTfygJ5L .node.clickable{cursor:pointer;}#mermaid-svg-d3CyH0h8yTfygJ5L .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-d3CyH0h8yTfygJ5L .arrowheadPath{fill:#333333;}#mermaid-svg-d3CyH0h8yTfygJ5L .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-d3CyH0h8yTfygJ5L .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-d3CyH0h8yTfygJ5L .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d3CyH0h8yTfygJ5L .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-d3CyH0h8yTfygJ5L .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d3CyH0h8yTfygJ5L .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-d3CyH0h8yTfygJ5L .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-d3CyH0h8yTfygJ5L .cluster text{fill:#333;}#mermaid-svg-d3CyH0h8yTfygJ5L .cluster span{color:#333;}#mermaid-svg-d3CyH0h8yTfygJ5L div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-d3CyH0h8yTfygJ5L .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-d3CyH0h8yTfygJ5L rect.text{fill:none;stroke-width:0;}#mermaid-svg-d3CyH0h8yTfygJ5L .icon-shape,#mermaid-svg-d3CyH0h8yTfygJ5L .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d3CyH0h8yTfygJ5L .icon-shape p,#mermaid-svg-d3CyH0h8yTfygJ5L .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-d3CyH0h8yTfygJ5L .icon-shape .label rect,#mermaid-svg-d3CyH0h8yTfygJ5L .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d3CyH0h8yTfygJ5L .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-d3CyH0h8yTfygJ5L .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-d3CyH0h8yTfygJ5L :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    分层 Prompt 结构

    SOUL.mdAgent 人格定义固定,永远在上下文开头

    MEMORY.md记忆索引会话开始时注入,内容精简

    USER.md用户偏好固定,跨会话不变

    当前会话加载的 Skills按需加载,匹配当前任务

    本期对话历史随对话增长,动态压缩

    检索到的相关记忆片段按需注入,只带最相关的

    这个分层结构的好处是:前面几层是固定的或很少变化的——它们可以完美命中 API 的前缀缓存(Prompt Caching),几乎零成本。

    第二层:上下文压缩。 当对话历史增长到接近窗口上限时,Hermes 不简单地截断旧消息,而是对较早的对话进行摘要压缩。摘要保留了关键决策点和结果(“用户选择了方案 A,部署到 staging 环境,遇到了端口冲突的报错,已通过修改 docker-compose.yml 解决”),丢弃了冗余的来回确认和中间输出。

    第三层:Anthropic Prompt Caching 适配。 在 Claude API 调用时,Hermes 固化 session_start 和 session_id 两个参数——即使 Prompt Builder 的某些路径可能会重新渲染部分内容,这些固化参数保证了字节级一致性,从而稳定命中缓存。

    3.3 工作记忆的边界:当"现在"变成"过去"

    会话结束时,工作记忆面临一个决策:怎么处理刚才的对话?

    Hermes 的做法不是"存全部"或"全部丢弃",而是选择性归档:

    • 简单的问答(“今天天气怎么样”)——归档为一条简短的摘要记录
    • 包含工具调用的任务(“帮我部署项目”)——归档为结构化的情景记忆条目,包含任务目标、执行步骤、结果和踩过的坑
    • 失败的任务——同样归档,失败的经验往往比成功的更有价值(但只记录"怎么修复的",不记录"什么坏了"的临时状态)

    判断标准不是对话长度,而是工具迭代次数。迭代次数少 = 简单交互,不需要深度归档;迭代次数多 = 复杂任务,需要完整保留执行轨迹。


    四、L2 情景记忆:把"发生过的事"变成可检索的资产

    4.1 为什么选 SQLite + FTS5

    情景记忆需要回答的问题是:“上次类似的情况发生了什么?” 这类查询的特点是:

    • 关键词匹配 > 语义匹配。"部署 staging"和"上线到预发布环境"语义上说的是同一件事,但用户更可能用固定的术语搜索。关键词索引能精准命中用户自己的用词习惯。
    • 时间线很重要。“上周那次部署”——需要按时间范围过滤。
    • 结构化字段。任务类型、成功/失败、涉及的工具——这些维度需要结构化查询。

    SQLite + FTS5 全文索引恰好满足这三个需求:FTS5 提供高效的关键词搜索,SQL 提供结构化过滤,而且 SQLite 是嵌入式数据库——零配置、零运维,数据以单个文件存储,天然适合个人 Agent 的部署场景。

    4.2 情景记忆的数据结构

    每条情景记忆记录的简化结构:

    CREATE TABLE episodes (
    id TEXT PRIMARY KEY,
    session_id TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    task_type TEXT, — 'deployment', 'debugging', 'code_review'
    summary TEXT, — 任务摘要(自然语言)
    tools_used TEXT, — JSON array: ["git_clone", "run_terminal"]
    outcome TEXT, — 'success', 'failure', 'partial'
    key_learnings TEXT, — 提取的关键经验
    user_feedback TEXT, — 用户对任务结果的反馈
    compressed_log TEXT — 压缩后的完整执行轨迹
    );

    几个设计决策值得展开:

    task_type 是枚举而非自由文本。Agent 在归档时从预定义的分类中选择(deployment, debugging, code_review, data_analysis, …),确保同一类任务能被聚合查询。分类不够用时通过技能系统的伞状合并来扩展。

    key_learnings 和 compressed_log 共存。前者是提炼后的要点的,用于快速注入上下文(几十个 token);后者是完整的执行轨迹,在需要详细回溯时使用(几千个 token)。Agent 默认只检索 key_learnings,只有在匹配度很高时才加载 compressed_log。

    user_feedback 是慢反馈信号。用户说"干得好"和沉默不语,都是信号。Hermes 追踪这些信号,用于后续的技能迭代决策——被用户赞过的任务模式,更可能在复盘时被提炼为 Skill。

    4.3 检索策略:精确匹配优先,语义兜底

    面对一个新的用户请求,情景记忆的检索逻辑是:

    #mermaid-svg-dyn3dsqPRrSP8oRE{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dyn3dsqPRrSP8oRE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dyn3dsqPRrSP8oRE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dyn3dsqPRrSP8oRE .error-icon{fill:#552222;}#mermaid-svg-dyn3dsqPRrSP8oRE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dyn3dsqPRrSP8oRE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dyn3dsqPRrSP8oRE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dyn3dsqPRrSP8oRE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dyn3dsqPRrSP8oRE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dyn3dsqPRrSP8oRE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dyn3dsqPRrSP8oRE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dyn3dsqPRrSP8oRE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dyn3dsqPRrSP8oRE .marker.cross{stroke:#333333;}#mermaid-svg-dyn3dsqPRrSP8oRE svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dyn3dsqPRrSP8oRE p{margin:0;}#mermaid-svg-dyn3dsqPRrSP8oRE .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-dyn3dsqPRrSP8oRE .cluster-label text{fill:#333;}#mermaid-svg-dyn3dsqPRrSP8oRE .cluster-label span{color:#333;}#mermaid-svg-dyn3dsqPRrSP8oRE .cluster-label span p{background-color:transparent;}#mermaid-svg-dyn3dsqPRrSP8oRE .label text,#mermaid-svg-dyn3dsqPRrSP8oRE span{fill:#333;color:#333;}#mermaid-svg-dyn3dsqPRrSP8oRE .node rect,#mermaid-svg-dyn3dsqPRrSP8oRE .node circle,#mermaid-svg-dyn3dsqPRrSP8oRE .node ellipse,#mermaid-svg-dyn3dsqPRrSP8oRE .node polygon,#mermaid-svg-dyn3dsqPRrSP8oRE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dyn3dsqPRrSP8oRE .rough-node .label text,#mermaid-svg-dyn3dsqPRrSP8oRE .node .label text,#mermaid-svg-dyn3dsqPRrSP8oRE .image-shape .label,#mermaid-svg-dyn3dsqPRrSP8oRE .icon-shape .label{text-anchor:middle;}#mermaid-svg-dyn3dsqPRrSP8oRE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dyn3dsqPRrSP8oRE .rough-node .label,#mermaid-svg-dyn3dsqPRrSP8oRE .node .label,#mermaid-svg-dyn3dsqPRrSP8oRE .image-shape .label,#mermaid-svg-dyn3dsqPRrSP8oRE .icon-shape .label{text-align:center;}#mermaid-svg-dyn3dsqPRrSP8oRE .node.clickable{cursor:pointer;}#mermaid-svg-dyn3dsqPRrSP8oRE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dyn3dsqPRrSP8oRE .arrowheadPath{fill:#333333;}#mermaid-svg-dyn3dsqPRrSP8oRE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dyn3dsqPRrSP8oRE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dyn3dsqPRrSP8oRE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dyn3dsqPRrSP8oRE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dyn3dsqPRrSP8oRE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dyn3dsqPRrSP8oRE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dyn3dsqPRrSP8oRE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dyn3dsqPRrSP8oRE .cluster text{fill:#333;}#mermaid-svg-dyn3dsqPRrSP8oRE .cluster span{color:#333;}#mermaid-svg-dyn3dsqPRrSP8oRE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dyn3dsqPRrSP8oRE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dyn3dsqPRrSP8oRE rect.text{fill:none;stroke-width:0;}#mermaid-svg-dyn3dsqPRrSP8oRE .icon-shape,#mermaid-svg-dyn3dsqPRrSP8oRE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dyn3dsqPRrSP8oRE .icon-shape p,#mermaid-svg-dyn3dsqPRrSP8oRE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dyn3dsqPRrSP8oRE .icon-shape .label rect,#mermaid-svg-dyn3dsqPRrSP8oRE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dyn3dsqPRrSP8oRE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dyn3dsqPRrSP8oRE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dyn3dsqPRrSP8oRE :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    提取请求中的关键词

    FTS5 全文搜索按时间衰减加权排序

    结果 >= 阈值?

    向量语义搜索可选启用

    按 task_type 过滤按时间衰减排序取 top-5

    结果 >= 阈值?

    返回空不硬塞无关记忆

    注入上下文:仅注入 key_learnings 字段

    匹配度 > 阈值?

    额外注入compressed_log

    完成

    "宁缺毋滥"是这个策略的核心。Agent 宁可少带一些记忆,也不应该带着无关的历史片段来干扰当前推理。一个做着部署任务的 Agent 如果被硬塞了一段上周的代码审计记录,只会被混淆——这跟人类回忆无关往事干扰当前决策的道理完全一样。


    五、L3 语义记忆:从"记得什么事件"到"知道什么事实"

    5.1 情景 vs 语义:一个关键区分

    情景记忆记录的是事件:“2026 年 4 月 15 日,用户让我分析了 facebook/react 的代码质量,发现了 23 个 anti-patterns,用户对我的报告格式提出了三点修改意见。”

    语义记忆记录的是事实:“用户偏好代码分析报告使用 Markdown 表格而非纯文本段落;用户关注的安全问题优先级为:凭证泄露 > 依赖过期 > 注入风险;用户的 React 项目使用 TypeScript 和 ESLint。”

    前者是时间线上的一个点,后者是跨越多个事件的规律。分层存储的意义在于:语义记忆是情景记忆经过提炼的产物,它的数据量小得多,但信息密度高得多。

    5.2 向量数据库选型

    语义记忆需要语义搜索——"用户偏好什么"不应该依赖关键词匹配。因此选用向量数据库:

    选项适用场景特点
    Chroma 本地开发、单用户 嵌入式,零配置,和 SQLite 一样简单
    Pinecone 多用户、生产环境 全托管,高可用,按量付费
    Qdrant 自托管、高性能 Rust 实现,支持量化压缩,过滤能力强

    Hermes 的设计是可选插件式——默认使用 Chroma(开箱即用),需要扩展时可以切换到 Pinecone 或 Qdrant。抽象接口层保证了切换向量库不影响其他模块。

    5.3 自动提取:从事件到事实

    语义记忆最关键的技术挑战是:如何从情景记忆中自动提取事实,而不需要用户手动整理?

    Hermes 的做法是在后台 Curator 巡检时运行一个提炼流程:

    #mermaid-svg-9r7JR3tCU1lflSqq{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9r7JR3tCU1lflSqq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9r7JR3tCU1lflSqq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9r7JR3tCU1lflSqq .error-icon{fill:#552222;}#mermaid-svg-9r7JR3tCU1lflSqq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9r7JR3tCU1lflSqq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9r7JR3tCU1lflSqq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9r7JR3tCU1lflSqq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9r7JR3tCU1lflSqq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9r7JR3tCU1lflSqq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9r7JR3tCU1lflSqq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9r7JR3tCU1lflSqq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9r7JR3tCU1lflSqq .marker.cross{stroke:#333333;}#mermaid-svg-9r7JR3tCU1lflSqq svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9r7JR3tCU1lflSqq p{margin:0;}#mermaid-svg-9r7JR3tCU1lflSqq .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-9r7JR3tCU1lflSqq .cluster-label text{fill:#333;}#mermaid-svg-9r7JR3tCU1lflSqq .cluster-label span{color:#333;}#mermaid-svg-9r7JR3tCU1lflSqq .cluster-label span p{background-color:transparent;}#mermaid-svg-9r7JR3tCU1lflSqq .label text,#mermaid-svg-9r7JR3tCU1lflSqq span{fill:#333;color:#333;}#mermaid-svg-9r7JR3tCU1lflSqq .node rect,#mermaid-svg-9r7JR3tCU1lflSqq .node circle,#mermaid-svg-9r7JR3tCU1lflSqq .node ellipse,#mermaid-svg-9r7JR3tCU1lflSqq .node polygon,#mermaid-svg-9r7JR3tCU1lflSqq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9r7JR3tCU1lflSqq .rough-node .label text,#mermaid-svg-9r7JR3tCU1lflSqq .node .label text,#mermaid-svg-9r7JR3tCU1lflSqq .image-shape .label,#mermaid-svg-9r7JR3tCU1lflSqq .icon-shape .label{text-anchor:middle;}#mermaid-svg-9r7JR3tCU1lflSqq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-9r7JR3tCU1lflSqq .rough-node .label,#mermaid-svg-9r7JR3tCU1lflSqq .node .label,#mermaid-svg-9r7JR3tCU1lflSqq .image-shape .label,#mermaid-svg-9r7JR3tCU1lflSqq .icon-shape .label{text-align:center;}#mermaid-svg-9r7JR3tCU1lflSqq .node.clickable{cursor:pointer;}#mermaid-svg-9r7JR3tCU1lflSqq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-9r7JR3tCU1lflSqq .arrowheadPath{fill:#333333;}#mermaid-svg-9r7JR3tCU1lflSqq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9r7JR3tCU1lflSqq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9r7JR3tCU1lflSqq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9r7JR3tCU1lflSqq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-9r7JR3tCU1lflSqq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9r7JR3tCU1lflSqq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-9r7JR3tCU1lflSqq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9r7JR3tCU1lflSqq .cluster text{fill:#333;}#mermaid-svg-9r7JR3tCU1lflSqq .cluster span{color:#333;}#mermaid-svg-9r7JR3tCU1lflSqq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9r7JR3tCU1lflSqq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-9r7JR3tCU1lflSqq rect.text{fill:none;stroke-width:0;}#mermaid-svg-9r7JR3tCU1lflSqq .icon-shape,#mermaid-svg-9r7JR3tCU1lflSqq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9r7JR3tCU1lflSqq .icon-shape p,#mermaid-svg-9r7JR3tCU1lflSqq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-9r7JR3tCU1lflSqq .icon-shape .label rect,#mermaid-svg-9r7JR3tCU1lflSqq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9r7JR3tCU1lflSqq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-9r7JR3tCU1lflSqq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-9r7JR3tCU1lflSqq :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    新事实补充旧事实

    新事实与旧事实矛盾

    与旧事实完全一致

    情景记忆最近7天的episodes

    按 task_type 分组

    对每组:LLM批次分析提取跨事件的模式

    候选事实列表

    与已有语义记忆去重比对

    冲突检测

    更新

    标记为待确认下次出现时再更新

    跳过

    更新语义记忆库

    冲突检测是其中最关键的一步。用户的偏好可能变化——上半年偏好 React,下半年转向 Vue。语义记忆需要敏感于这种变化,但不能在一次变化后就覆盖旧事实(可能只是临时项目需要)。Hermes 选择了保守策略:矛盾需要两次以上的确认才会覆盖。这避免了"一个临时项目把你的技能偏好永久改偏"的问题。


    六、L4 技能专用记忆:从"知道什么"到"会做什么"

    6.1 为什么 Skills 是记忆的一层

    你可能会问:技能不应该是独立的"功能"吗?为什么放在记忆系统里?

    因为在 Hermes 的架构哲学中,技能就是最高层级的记忆——它是工作记忆、情景记忆、语义记忆经过 Learning Loop 的反思提炼后,固化的最终产物。

    #mermaid-svg-wdcfoskeibBYWvvv{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wdcfoskeibBYWvvv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wdcfoskeibBYWvvv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wdcfoskeibBYWvvv .error-icon{fill:#552222;}#mermaid-svg-wdcfoskeibBYWvvv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wdcfoskeibBYWvvv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wdcfoskeibBYWvvv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wdcfoskeibBYWvvv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wdcfoskeibBYWvvv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wdcfoskeibBYWvvv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wdcfoskeibBYWvvv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wdcfoskeibBYWvvv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wdcfoskeibBYWvvv .marker.cross{stroke:#333333;}#mermaid-svg-wdcfoskeibBYWvvv svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wdcfoskeibBYWvvv p{margin:0;}#mermaid-svg-wdcfoskeibBYWvvv .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-wdcfoskeibBYWvvv .cluster-label text{fill:#333;}#mermaid-svg-wdcfoskeibBYWvvv .cluster-label span{color:#333;}#mermaid-svg-wdcfoskeibBYWvvv .cluster-label span p{background-color:transparent;}#mermaid-svg-wdcfoskeibBYWvvv .label text,#mermaid-svg-wdcfoskeibBYWvvv span{fill:#333;color:#333;}#mermaid-svg-wdcfoskeibBYWvvv .node rect,#mermaid-svg-wdcfoskeibBYWvvv .node circle,#mermaid-svg-wdcfoskeibBYWvvv .node ellipse,#mermaid-svg-wdcfoskeibBYWvvv .node polygon,#mermaid-svg-wdcfoskeibBYWvvv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wdcfoskeibBYWvvv .rough-node .label text,#mermaid-svg-wdcfoskeibBYWvvv .node .label text,#mermaid-svg-wdcfoskeibBYWvvv .image-shape .label,#mermaid-svg-wdcfoskeibBYWvvv .icon-shape .label{text-anchor:middle;}#mermaid-svg-wdcfoskeibBYWvvv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wdcfoskeibBYWvvv .rough-node .label,#mermaid-svg-wdcfoskeibBYWvvv .node .label,#mermaid-svg-wdcfoskeibBYWvvv .image-shape .label,#mermaid-svg-wdcfoskeibBYWvvv .icon-shape .label{text-align:center;}#mermaid-svg-wdcfoskeibBYWvvv .node.clickable{cursor:pointer;}#mermaid-svg-wdcfoskeibBYWvvv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wdcfoskeibBYWvvv .arrowheadPath{fill:#333333;}#mermaid-svg-wdcfoskeibBYWvvv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wdcfoskeibBYWvvv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wdcfoskeibBYWvvv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wdcfoskeibBYWvvv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wdcfoskeibBYWvvv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wdcfoskeibBYWvvv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wdcfoskeibBYWvvv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wdcfoskeibBYWvvv .cluster text{fill:#333;}#mermaid-svg-wdcfoskeibBYWvvv .cluster span{color:#333;}#mermaid-svg-wdcfoskeibBYWvvv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wdcfoskeibBYWvvv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wdcfoskeibBYWvvv rect.text{fill:none;stroke-width:0;}#mermaid-svg-wdcfoskeibBYWvvv .icon-shape,#mermaid-svg-wdcfoskeibBYWvvv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wdcfoskeibBYWvvv .icon-shape p,#mermaid-svg-wdcfoskeibBYWvvv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wdcfoskeibBYWvvv .icon-shape .label rect,#mermaid-svg-wdcfoskeibBYWvvv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wdcfoskeibBYWvvv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wdcfoskeibBYWvvv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wdcfoskeibBYWvvv :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    工作记忆中的成功执行轨迹

    情景记忆中归档的结构化事件

    语义记忆中提炼的偏好和事实

    Learning Loop 的反思与抽象

    技能专用记忆可执行的Skill文件

    一个 Skill 文件不只是一个"操作手册"。它包含了:

    • 触发条件(什么时候该用这个技能)——来自情景记忆中的模式识别
    • 执行步骤(怎么操作)——来自工作记忆中的成功轨迹
    • 已知限制(什么时候不该用)——来自情景记忆中的失败案例
    • 用户偏好(怎么适配你的习惯)——来自语义记忆中的事实提取

    6.2 Markdown 作为技能载体

    Skills 以 Markdown 文件存储在 .hermes/skills/ 目录下。选择 Markdown 的理由:

  • LLM 原生擅长读写 Markdown。不需要特殊的解析器,不需要训练。
  • 人类可读、可编辑。你可以随时打开 Skill 文件修改执行步骤。
  • 自然语言的灵活性 > 代码的结构性。一个部署步骤的描述(“先在 staging 环境测试,确认没问题后再推到 production”)比等价的代码逻辑(try-catch、环境变量判断、回滚逻辑)更容易让 LLM 理解和执行。
  • 版本控制友好。Markdown 文件的 diff 清晰可读,方便追踪技能的演进。
  • 6.3 技能的生命周期

    技能不是创建后就一劳永逸的静态文件。每个 Skill 有完整的生命周期:

    #mermaid-svg-HJ7ZB68DIcHYSOs3{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .error-icon{fill:#552222;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .marker.cross{stroke:#333333;}#mermaid-svg-HJ7ZB68DIcHYSOs3 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 p{margin:0;}#mermaid-svg-HJ7ZB68DIcHYSOs3 defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-HJ7ZB68DIcHYSOs3 g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-HJ7ZB68DIcHYSOs3 g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-HJ7ZB68DIcHYSOs3 g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HJ7ZB68DIcHYSOs3 .edgeLabel .label text{fill:#333;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .label div .edgeLabel{color:#333;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 #statediagram-barbEnd{fill:#333333;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .cluster-label,#mermaid-svg-HJ7ZB68DIcHYSOs3 .nodeLabel{color:#131300;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .note-edge{stroke-dasharray:5;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-note text{fill:black;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram-note .nodeLabel{color:black;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagram .edgeLabel{color:red;}#mermaid-svg-HJ7ZB68DIcHYSOs3 #dependencyStart,#mermaid-svg-HJ7ZB68DIcHYSOs3 #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-HJ7ZB68DIcHYSOs3 .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HJ7ZB68DIcHYSOs3 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    Agent从经验中生成

    2-3次使用后统计成功率和耗时

    成功率>80%用户确认持久化

    每次使用后可能被patch优化

    高频使用

    30天未使用

    被复用自动复活

    持续90天未使用

    成功率<50%

    被伞状合并知识升维到父技能

    创建

    验证

    激活

    迭代

    stale

    archived

    需要改进

    absorbed_into

    这个状态机是双向可逆的。状态可以从 active 到 stale 到 archived,也可以从 stale 回到 active(当技能被复用后自动复活)。这是 Hermes 区别于其他单向降级系统(用过期的技能就直接删除)的关键设计——你偶尔需要的技能不会因为"用得不够勤"而消失。

    纯规则引擎驱动。30 天 / 90 天的双阈值判断不需要 LLM 参与——它是 SQL 查询 + 时间戳比较。这保证了技能治理的成本是零(零 API 调用、零 GPU 消耗),而且结果完全可预测。


    七、四层协同:记忆系统的数据流转全景

    拆完四层后,最关键的问题是:它们如何协同工作?

    7.1 一次任务中的记忆流转

    以一个完整的用户任务为例,追踪记忆数据的流动:

    #mermaid-svg-x2b2E1qO1aiEvXXB{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-x2b2E1qO1aiEvXXB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-x2b2E1qO1aiEvXXB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-x2b2E1qO1aiEvXXB .error-icon{fill:#552222;}#mermaid-svg-x2b2E1qO1aiEvXXB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-x2b2E1qO1aiEvXXB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-x2b2E1qO1aiEvXXB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-x2b2E1qO1aiEvXXB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-x2b2E1qO1aiEvXXB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-x2b2E1qO1aiEvXXB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-x2b2E1qO1aiEvXXB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-x2b2E1qO1aiEvXXB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-x2b2E1qO1aiEvXXB .marker.cross{stroke:#333333;}#mermaid-svg-x2b2E1qO1aiEvXXB svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-x2b2E1qO1aiEvXXB p{margin:0;}#mermaid-svg-x2b2E1qO1aiEvXXB .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-x2b2E1qO1aiEvXXB .cluster-label text{fill:#333;}#mermaid-svg-x2b2E1qO1aiEvXXB .cluster-label span{color:#333;}#mermaid-svg-x2b2E1qO1aiEvXXB .cluster-label span p{background-color:transparent;}#mermaid-svg-x2b2E1qO1aiEvXXB .label text,#mermaid-svg-x2b2E1qO1aiEvXXB span{fill:#333;color:#333;}#mermaid-svg-x2b2E1qO1aiEvXXB .node rect,#mermaid-svg-x2b2E1qO1aiEvXXB .node circle,#mermaid-svg-x2b2E1qO1aiEvXXB .node ellipse,#mermaid-svg-x2b2E1qO1aiEvXXB .node polygon,#mermaid-svg-x2b2E1qO1aiEvXXB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-x2b2E1qO1aiEvXXB .rough-node .label text,#mermaid-svg-x2b2E1qO1aiEvXXB .node .label text,#mermaid-svg-x2b2E1qO1aiEvXXB .image-shape .label,#mermaid-svg-x2b2E1qO1aiEvXXB .icon-shape .label{text-anchor:middle;}#mermaid-svg-x2b2E1qO1aiEvXXB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-x2b2E1qO1aiEvXXB .rough-node .label,#mermaid-svg-x2b2E1qO1aiEvXXB .node .label,#mermaid-svg-x2b2E1qO1aiEvXXB .image-shape .label,#mermaid-svg-x2b2E1qO1aiEvXXB .icon-shape .label{text-align:center;}#mermaid-svg-x2b2E1qO1aiEvXXB .node.clickable{cursor:pointer;}#mermaid-svg-x2b2E1qO1aiEvXXB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-x2b2E1qO1aiEvXXB .arrowheadPath{fill:#333333;}#mermaid-svg-x2b2E1qO1aiEvXXB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-x2b2E1qO1aiEvXXB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-x2b2E1qO1aiEvXXB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x2b2E1qO1aiEvXXB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-x2b2E1qO1aiEvXXB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x2b2E1qO1aiEvXXB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-x2b2E1qO1aiEvXXB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-x2b2E1qO1aiEvXXB .cluster text{fill:#333;}#mermaid-svg-x2b2E1qO1aiEvXXB .cluster span{color:#333;}#mermaid-svg-x2b2E1qO1aiEvXXB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-x2b2E1qO1aiEvXXB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-x2b2E1qO1aiEvXXB rect.text{fill:none;stroke-width:0;}#mermaid-svg-x2b2E1qO1aiEvXXB .icon-shape,#mermaid-svg-x2b2E1qO1aiEvXXB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x2b2E1qO1aiEvXXB .icon-shape p,#mermaid-svg-x2b2E1qO1aiEvXXB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-x2b2E1qO1aiEvXXB .icon-shape .label rect,#mermaid-svg-x2b2E1qO1aiEvXXB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x2b2E1qO1aiEvXXB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-x2b2E1qO1aiEvXXB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-x2b2E1qO1aiEvXXB :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    执行后:知识沉淀

    L2 新episode:端口冲突通过修改8080-8081解决

    L3 可能更新:该项目staging环境端口已变更为8081

    L4 可能更新:deploy-app Skill增加部署前检查端口映射是否冲突

    执行中:AIAgent Loop

    1. 切换到staging分支语义记忆提供的映射

    2. 运行测试语义记忆提供的偏好

    3. 构建并部署技能记忆提供的流程

    4. 遇到端口冲突新踩的坑

    5. 修复后成功部署

    执行前:记忆检索

    用户请求:帮我把最近一周的改动部署到 staging

    L2 情景记忆检索FTS5全文搜索最近一周+部署+staging找到3条相关episodes

    L3 语义记忆检索语义搜索staging对应分支部署前需跑test

    L4 技能记忆加载匹配到 deploy-app Skill触发条件命中

    7.2 协同原则

    写时分层,读时汇聚。写入时,数据按抽象层次分别进入不同层。读取时,四层数据汇聚为一个统一的上下文,注入当前会话。

    下层主动向上层提炼。工作记忆归档时提取情景记忆,情景记忆批量分析时提取语义记忆,语义记忆结合执行轨迹固化为技能记忆。向上提炼的过程是自动的、异步的、后台执行的。

    上层可以反向查询下层。如果技能记忆中的某个步骤需要更多上下文(“为什么部署前要检查端口映射?”),可以反向从情景记忆中找到原始事件(“2026-08-10 部署 staging,端口冲突”)。


    八、与其他记忆方案的对比定位

    8.1 vs LangChain Memory

    LangChain 提供了多种 Memory 实现(ConversationBufferMemory、ConversationSummaryMemory、VectorStoreRetrieverMemory 等),核心思路是"把记忆串在 Chain 上"——每次调用时从 Memory 取数据,拼到 Prompt 里。

    关键区别:LangChain Memory 是被动存储——它存什么由开发者定义(存最近 K 轮对话、存摘要、存实体),Agent 不会主动决定"这个经验值得记住"。Hermes 的记忆系统是主动学习——Agent 自己判断什么值得记、怎么记、记在哪一层。

    另一个区别:LangChain 的 Memory 各类型之间是并列可选的(你选 Buffer 或 Summary 或 VectorStore),而 Hermes 的四层是分层递进的——从数据到信息到知识到技能,每层有不同的抽象等级。

    8.2 一张对比表

    维度LangChain MemoryHermes Memory
    记忆层数 单层(可选类型) 四层(工作→情景→语义→技能)
    存储方式 多种可选 SQLite + 向量库 + Markdown
    学习方式 被动(开发者定义存什么) 主动(Agent 自己判断 + 自动归档)
    跨会话 支持 支持(且自动提炼)
    技能/流程复用 不支持 支持(L4 技能专用记忆)
    运维复杂度 中(多存储后端)

    总结

    回到开篇的场景:为什么 Hermes 的 Agent 不会在第二天早上问"你的项目用什么构建工具"?

    因为它有四层记忆在工作:

    • 情景记忆记得昨天你们做了一次部署,其中涉及了 docker-compose、staging 分支、端口冲突和修复过程
    • 语义记忆知道这个项目用 Docker 构建、staging 对应 dev 分支、部署前需要跑测试
    • 技能记忆存了一份 deploy-app 技能,里面有完整的部署流程
    • 工作记忆在新会话开始时,自动加载了这三层记忆中最相关的部分

    用户说"帮我把昨天的改动部署到 staging"。Agent 已经准备好了——不是因为它记住了这一句话,而是因为它记住了你。

    架构层面的启示:记忆系统的设计,核心不是"存多大"或"存多久",而是 “信息如何逐层升维”。工作记忆是原始数据,情景记忆是结构化事件,语义记忆是抽象事实,技能记忆是可执行流程。这四层代表了信息从"发生过"到"学会了"的完整进化路径。

    一个只有工作记忆的 Agent 是"金鱼"。一个有情景记忆的 Agent 是"日记本"。一个有语义记忆的 Agent 是"百科全书"。而四层齐备的 Agent,才是"知己"。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Hermes 记忆革命:四层记忆架构
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!