Agent 记忆机制没什么神秘的,一篇文章给你讲懂

阅读指南:时间有限的话,重点看 Section 3(进化四层)和 Section 5(记忆归属权)。前者让你从零理解记忆系统的每一层为什么存在,后者告诉你为什么这件事比你想象的更重要。

---

1. 你的 AI 助手为什么今天又忘记你的名字

你跟 ChatGPT 聊了二十分钟,告诉它你叫什么、做什么工作、最近在折腾什么项目。聊得挺投机。你觉得它"认识"你了。

第二天你打开新对话,满怀期待地问了一句:"我们昨天聊的那个方案怎么样了?"

它完全不知道你在说什么。

这不是 ChatGPT 的 bug,也不是你用的模型不够贵。大语言模型在设计上就是无状态的——每次你发一条消息,它收到的都是一整段从开头到现在的完整对话历史。它不"记得"你,它只是在每次请求时重新读了一遍聊天记录。就像一个人每说一句话都要从头把之前的对话默念一遍,念完就忘。

你感受到的"记忆",是一种精心设计的幻觉。你以为的"它记住了我的名字",实际上只是因为你的名字在当前的上下文窗口里。一旦对话太长,最早的内容被截掉,它就"忘"了。一旦你开了新对话,一切清零。

这个无状态特性意味着:如果你关掉对话窗口,开一个新的,之前的一切都不存在了。模型不认识你,不知道你说过什么,不了解你的偏好。你在上一个对话里精心调教好的 Agent 人设,在新对话里全部失效。

这就是 Agent 开发者面对的核心问题之一:怎么让 AI 在不同的对话、不同的会话、甚至不同的工具之间保持记忆。

我们来看一个最简单的 Agent 长什么样——一个没有任何记忆的 Agent:

class MemoryAgent:
"""一个完全无状态的 Agent"""

def __init__(self):
self.model = "gpt-4"

def chat(self, user_input: str) -> str:
"""每次调用都是全新对话,
不保留任何历史信息"""
messages = {"role": "user", "content": user_input}
" class="hb-emoji hb-emoji-
{"role": "system", "content": "你是一个助手"},
{"role": "user", "content": user hb-emoji-
{"role": "system", "content": "你是一个助手"},
{"role": "user", "content": user_input}
">

return call_llm(self.model, messages)

def reset(self):
"""无状态 Agent 不需要重置,
因为本来就没状态"""
pass

这个 Agent 的记忆存在哪里?在 API 调用的间隙——不存在。

怎么让它记住?你可能会想,存个变量不就行了?存个文件?用数据库?这些方案都对,但又都不够。原因我们慢慢拆。先搞清楚一个前提:人类记忆是怎么工作的,因为 Agent 记忆的设计几乎完全照搬了认知科学的框架。

---

2. 给 Agent 装个大脑——记忆的三层模型

心理学家把人类记忆分成三层,这个模型从 1968 年 Atkinson 和 Shiffrin 提出到现在,基本框架没变过。

短时记忆(short-term memory):这是刚才看到的东西,刚才听到的音调,刚才做出的动作。也就是刚刚经过感官的输入,正在大脑某个部位停留几秒钟的东西。在 Agent 的世界里,这对应就工具返回的原始输出——一大坨 JSON、一段网页文本、一条命令行输出。这些信息在当前轮次可能有用,但下一轮就被新的输入覆盖了。

工作记忆(working memory):它容量有限,但它能持续维持。心理学家 George Miller 在 1956 年发表了一篇超级经典的论文,论述并提出了一个很有名的数字:7±2。也就是说人类同时能在脑子里维持下面的信息单元数量是大约 5 到 9 个。这个论文有很多后续研究修改和演绎,比如 Cowan 在 2001 年修正为 4±1,但核心结论没变:工作记忆的容量是非常有限的。对应到 Agent 就是上下文窗口。GPT-4 的窗口是 128K token,听上去这么多数量还挺多的,但是稍微复杂点的项目聊天,代码、日志、文档引用几千字很容易就填满了。

长时记忆(long-term memory):这一块我认为是最复杂的也是最有用的一部分。长时记忆按照认知科学的定义,又被细分成三种:

- 情景记忆(episodic memory):你上周三去开会,听老板讲了一件事。你去年去旅游,中午吃了个烤全羊。具体的带时间戳的记忆。

- 语义记忆(semantic memory):北京是中国的首都。Python 是一种编程语言。从各种各样具体记忆中抽象出来的知识体系。时间无关的、一般化的知识。

- 程序性记忆(procedural memory):肌肉记忆,打球的都懂。

映射到 Agent 的世界的话就是:

  • 情景记忆 = 对话历史、任务执行日志、用户反馈记录。信息加时间戳。比如“用户上周二问了怎么退款,我告诉他联系售后”

  • 语义记忆 = 知识库、向量数据库、文档索引。语言模型本身也是一种语义记忆。比如“公司的退款政策是 7 天无理由退货”——这条语句的知识可能不是某个具体回答用户来自的,而是你在大量互动经验中提炼总结出来的

  • 程序性记忆 = 提示词模板、工具调用规范、工作流定义。比如”用户提问涉及到退款,那就先调用查询订单状态工具,然后确认退货期限,最后执行退款动作”

简单来说:情景记忆就是经历了什么你就记住什么。但是如果某些相似的模式反复出现(比如用户每次问你退款都需要走同样的流程),那么你的情景记忆就会抽象为语义记忆(”退款流程是这样的”)和程序性记忆(”用户反问有关退款的问题,就自动触发这个流程”)。

这三层搞清楚了,从下一节开始我们以一个完整代码示例为基准,从最简单的方案一层层进化,完善一个混合架构的Agent。每层代码基于之前的内容改造和添加,每一层都解决一个实际问题。

接下来我们定义了一张表格,用来追踪每一层方案解决了什么问题:

解决方案 | 多轮对话 | 持久化 | 语义检索 | 关系推理 | 归属权

Agent(无状态) | — | — | — | — | 你

这个表目前还只有一个最简单的无状态Agent,下面我们开始一步步升级。

---

3. Agent 记忆进化

---

3.1:对话历史

最容易想到的方法,也是最简单的方法:既然我们的模型要看到历史消息才能记住之前发生过什么,我们就把历史消息存下来,每次请求都发到模型那边去。

class MemoryAgent:
"""一个用列表来存储对话历史的 Agent"""

def __init__(self):
self.model = "gpt-4"
self.messages = [
{"role": "system",
"content": "你是一个有帮助的助手"}
]

def chat(self, user_input: str) -> str:
"""存储消息的函数并且每次发完整的对话"""
self.messages.append(
{"role": "user", "content": user_input})
response = call_llm(self.model, self.messages)
self.messages.append(
{"role": "assistant", "content": response})
return response

def get_history_length(self) -> int:
"""查询对话历史长度"""
return len(self.messages)

现在你的 Agent 可以记住对话上下文啦。你问它名字,下一秒她就记得。多轮对话的基本能力有了。

但是马上又会面临两个问题:

第一个问题:上下文长度是有限的。 4.7 opus和刚出的deepseek-4-pro可以达到1M的上下文,你可能感觉很多,但是如果你让你的 Agent 去做一个稍微复杂点的任务,比如分析一个大型代码库、读取一份长报告,那你的对话历史就会迅速积累到上限。超过一定阈值之后,Agent就会压缩,丢失部分信息,那记忆本质上也丢失了。

第二个问题:进程重启,内存清零。 这个 self.messages 变量就存储在 Python 的内存里。你关闭了终端、服务器重启了、又或者你的 Python 进程崩溃了一下,信息就全没了。这在实际部署场景中非常常见,一旦 重启,积累在内存中的大量上下文信息就会丢失。

简单粗暴的列表记忆方案解决了“多轮对话”的问题,但是引入了“记忆持久化”的新问题。

解决方案 | 多轮对话 | 持久化 | 语义检索 | 关系推理 | 归属权

Agent(无状态) | — | — | — | — | 你

+ 对话历史 | ✓ | — | — | — | 内存(进程死=记忆灭)

存储在内存里。进程挂了,内存也没了。

那怎么解决呢?将内存中的记忆做持久化存储。

---

3.2:文件 I/O — 记忆写成你能看懂的 markdown 文本

解决记忆持久化的最自然方式:把东西写进文件。重启Agent再读回来。

但是我们可以稍微变通一点点,我们让 Agent 做一些额外的工作,把重要信息提炼成一个个记忆笔记,并且存储为 markdown 格式。每次启动我们读取这些记忆笔记,作为我们发给模型的上下文内容的一部分。

如果你用过 Claude Code 的话,它的 MEMORY.md 和 CLAUDE.md 文件就是这套方案的体现:用 markdown 格式记录项目约定、用户偏好、长期决策等内容,Agent 每次启动时自动读取内容。

OpenClaw 和 Hermes 这两个 Agent 框架,都把这种文件记忆模式作为底层默认特性。

class MemoryAgent:
"""一个用 markdown 文件持久化记忆的 Agent"""

def __init__(self, memory_file="memory.md"):
self.model = "gpt-4"
self.messages = []
self.memory_file = memory_file
self.memory = self._load_memory()

def _load_memory(self) -> str:
"""从文件读取记忆"""
try:
with open(self.memory_file) as f:
return f.read()
except FileNotFoundError:
return ""

def _save_memory(self, new_info: str):
"""向文件写入新增信息"""
with open(self.memory_file, "a") as f:
f.write(f"\n- {new_info}")
self.memory = self._load_memory()

def chat(self, user_input: str) -> str:
"""带文件记忆读取的交互"""
context = ""
if self.memory:
context = f"已知信息:\n{self.memory}\n\n"
self.messages.append(
{"role": "user",
"content": context + user_input})
response = call_llm(self.model, self.messages)
self.messages.append(
{"role": "assistant", "content": response})
return response

现在我们的 Agent 可以把记忆写入文件了。注意这里我们用到的 markdown 格式,天然的可读。你随便用什么编辑器都能打开这个文件,随意修改内容,用Git管理版本。

但是它有一个致命的缺陷,不怎么好搜索。

假设你在记忆文件里写下了:我们将产品数据库迁移到新 AWS 区域。而过了几天你问 Agent:“我们的云端迁移进展得如何了?”它搜索不到。文件里头没有“云端”这三个字。你说的话和文件里的内容语义上是一个意思,但不是字面上的意思。

再比如你写下了:Alice 负责 Project Atlas。你现在搜索笔记文件,“谁负责数据库项目?”搜索不到结果。记忆文件里面没有“数据库项目”这几个字,虽然你知道 Atlas 就是用数据库做的项目。

Obsidian、Notion 这类笔记软件都有这个问题。全文检索可以根据输入的关键词来匹配内容,但无法找到“意思相近”的内容。随着你的笔记越来越多,这个问题会越来越严重。

问题来了:你的记忆存在哪里?

解决方案 | 多轮对话 | 持久化 | 语义检索 | 关系推理 | 归属权

Agent(无状态) | — | — | — | — | 你

+ 对话历史 | ✓ | — | — | — | 内存(进程死=记忆灭)

+ 文件 I/O | ✓ | ✓ | — | — | 你的文件(可打包带走)

现在我们可以把记忆永久地记录在本地了,但是检索能力比较差。

---

3.3:向量检索

前面提到过,关键词搜不到“意思相近”的内容,根本原因就是因为文字对人有意义,对计算机只是一串字符串。

如何解决这个问题?就是需要让计算机理解文字的意思。

这个方法就是 embedding(向量嵌入)。文本经过了 embedding 后,变成了一串数字坐标。比如“数据库”和“PostgreSQL”它们的字符串完全不一样,但是在 embedding 后的向量表示空间里,两者是邻居。当你搜索数据库的时候,PostgreSQL 自然会被检索出来。

向量检索就是用向量空间里相似来检索,而不是直接字符串匹配。

class VectorStore:
"""一个超简单版的向量存储——用硬编码距离来演示基本概念"""

def __init__(self):
# 预先计算好的向量距离,纯粹为了演示做了硬编码
# 实际中这里会用 embedding 模型计算出来
self.distances = {
("数据库", "PostgreSQL"): 0.15,
("数据库", "MySQL"): 0.18,
("云迁移", "将生产数据库迁移到AWS"): 0.12,
("Alice", "PostgreSQL"): 0.35,
("Alice", "Project Atlas"): 0.25,
}

def search(self, query: str, top_k=3) -> list:
"""返回距离 query 最近的 k 个结果"""
results = []
for (a, b), dist in self.distances.items():
if query.lower() in a.lower() or query.lower() in b.lower():
results.append(
(a if query in b else b, dist))
return sorted(results, key=lambda x: x[1])

def add(self, text: str, embedding: list):
"""添加新文本(超简化了,不涉及实际计算嵌入)"""
pass

class MemoryAgent:
"""加上向量检索的 Agent"""

def __init__(self, memory_file="memory.md"):
self.model = "gpt-4"
self.messages = []
self.memory_file = memory_file
self.memory = self._load_memory()
self.vectors = VectorStore()

def _load_memory(self) -> str:
try:
with open(self.memory_file) as f:
return f.read()
except FileNotFoundError:
return ""

def chat(self, user_input: str) -> str:
"""先向量检索相关记忆,然后再聊天"""
related = self.vectors.search(user_input)
context = ""
if related:
context += f"相关记忆: {related}\n"
if self.memory:
context += f"已知信息:\n{self.memory}\n"
self.messages.append(
{"role": "user",
"content": context + user_input})
response = call_llm(self.model, self.messages)
self.messages.append(
{"role": "assistant", "content": response})
return response

这样搜索“云迁移”可以匹配到我们记录的“将生产数据库迁移到 AWS 区域”的记忆。向量检索彻底打破了关键词匹配的局限性。

ChatGPT 在今年年初发布的记忆功能就是建立在向量检索上面的。ChatGPT 会把用户输入的东西和长期记忆里的内容计算语义距离,选取距离最近的几个内容,并且把它们注入到聊天上下文之中。这样即使你换了种说法,也能找到相关内容。

但向量检索也有缺点,假设你的记忆库里有以下三条内容:

  1. Alice 是 Project Atlas 的负责人

  2. Project Atlas 使用的数据库是 PostgreSQL

  3. PostgreSQL 昨天挂掉了一次,影响了部分用户

然后你问你的 Agent:“Alice 的项目最近出现了什么问题吗?”

为了正确答复这个问题,Agent 必须要连接起上面三条内容:Alice → Project Atlas → PostgreSQL → 故障。

而向量检索做了什么?计算“跟 Alice 关系密切的”内容,找到了 Alice 和 Project Atlas 的关系。计算“跟问题相关的内容”,找到了 PostgreSQL 出故障这条记录。它看不到 Alice → Project Atlas → PostgreSQL 这条三连。

究其根本原因,还是因为你写进去的内容是一堆孤立的字符串,而不是一个知识图谱。

如果你换一种问法:"PostgreSQL 最近有什么问题?

向量搜索能完美回答,因为"PostgreSQL"和"故障"在向量空间里确实很近。问题出在多级上:从 Alice 到 Atlas 是一级,从 Atlas 到 PostgreSQL 是另一级,从 PostgreSQL 到故障是第三级。每一级都需要沿着一条明确的关系边走过去,而不是在向量空间里直线测量距离。

为什么呢?因为向量空间里,每个事实是一个孤立的点。"Alice 管理 Atlas"是一条边,"Atlas 使用 PostgreSQL"是另一条边,"PostgreSQL 有故障"是第三条边。

这三条边可以在向量空间表示成三个独立的向量。向量距离只能度量两个点之间的相似度,并不能沿着”管理→使用→有故障“的链路一路走到底。

这三个实体之间的关系对向量搜索来说是不可见的。

这就是多级推理无法实现的原因。也是纯粹依赖关键词匹配和向量搜索都不完美的原因。

让我们回到能力矩阵。

方案 | 多轮对话 | 持久化 | 语义检索 | 关系推理 | 归属权

Agent(无状态) | — | — | — | — | 你

+ 对话历史 | ✓ | — | — | — | 内存(进程死=内存丢失)

+ 文件 I/O | ✓ | ✓ | — | — | 你的文件(可存档)

+ 向量搜索 | ✓ | ✓ | ✓ | — | 向量数据库(格式绑定)

语义检索搞定了,但关系推理还不行。最后一层。

---

4.知识图谱 + 混合架构

想要完成多级推理,我们需要引入一种可以显示存储“关系”的数据结构:知识图谱(knowledge graph,用节点存储实体、用边存储关系,像张网一样把所有东西都连在一起)。

但知识图谱搜索不是搜索数据库……知识图谱也不擅长语义检索。在图谱里,”数据库“和”PostgreSQL“是两个完全不同的节点。如果我搜索”数据库“是不一定能找到 PostgreSQL 的。

所以最终的解决方案是混合架构。

  • **关键词精确匹配**:BM25,精确的词面匹配。”PostgreSQL”搜索”PostgreSQL”一定能命中。

  • **向量搜索** :语义相关,“数据库”可以找到”PostgreSQL“。

  • **图谱遍历** :知识图谱搜索,“管理”的女儿就是 Alice 使用过的所有数据库。

这三种结果如何融合到一起呢?你可以使用一种叫做 RRF 的技术(Reciprocal Rank Fusion),简单来说就是让三个“人”各自为候选项排序,之后用”排名越前越高权重越大“的规则将排序融合在一起(就像每个人对一个结果投一张选票,票越靠前投的人排名越靠前越重)。最终的得分就是按分数排序的倒数之和。

class KnowledgeGraph:
"""简化版知识图谱——用字典存储实体关系"""

def __init__(self):
self.edges = {
("Alice", "manages"): ["Project Atlas"],
("Project Atlas", "uses"): ["PostgreSQL"],
("PostgreSQL", "had_outage"): ["2024-03-15"],
("Alice", "role"): ["Tech Lead"],
}

def traverse(self, start: str, max_hops=3) -> list:
"""从起点出发,沿着关系链路走"""
visited, found = set(), []
queue = [start]
for _ in range(max_hops):
next_q = []
for node in queue:
if node in visited:
continue
visited.add(node)
for (s, rel), targets in self.edges.items():
if s == node:
found.extend(targets)
next_q.extend(targets)
queue = next_q
return found

def reciprocal_rank_fusion(
bm25_hits, vec_hits, graph_hits, k=60):
"""RRF 融合:三路检索结果合并排序。
每个结果从三路各获得一个排名,
最终分数 = 各路 1/(k+排名) 之和。
排名越靠前,分数越高。"""
scores = {}
for results in [bm25_hits, vec_hits, graph_hits]:
for rank, item in enumerate(results):
scores[item] = scores.get(
item, 0) + 1.0 / (k + rank + 1)
return sorted(scores.items(),
key=lambda x: -x[1])

class MemoryAgent:
"""完整混合架构——三路检索 + RRF 融合"""

def __init__(self, memory_file="memory.md"):
self.model = "gpt-4"
self.messages = []
self.memory_file = memory_file
self.memory = self._load_memory()
self.vectors = VectorStore()
self.graph = KnowledgeGraph()

def _load_memory(self) -> str:
try:
with open(self.memory_file) as f:
return f.read()
except FileNotFoundError:
return ""

def chat(self, user_input: str) -> str:
"""三路并行检索,RRF 融合,然后对话"""
bm25_hits = keyword_search(
self.memory, user_input)
vec_hits = self.vectors.search(user_input)
graph_hits = self.graph.traverse(
extract_entity(user_input))
merged = reciprocal_rank_fusion(
bm25_hits, vec_hits, graph_hits)
context = f"综合检索: {merged[:5]}\n"
if self.memory:
context += f"已知信息:\n{self.memory}\n"
self.messages.append(
{"role": "user",
"content": context + user_input})
response = call_llm(self.model, self.messages)
self.messages.append(
{"role": "assistant", "content": response})
return response

开源项目 Cognee 把这整套架构封装成了 4 个 API:add() 存数据、cognify() 自动构建图谱和向量索引、memify() 优化权重(后面会讲)、search() 做混合检索。底层自动管理三种数据库——SQLite 做关系存储、LanceDB 做向量、Kuzu 做图查询。

Hindsight 走了另一条路:不需要你手动搭建三种数据库,而是提供了一个仿生记忆系统,2 行代码就能快速接入。底层用 PostgreSQL 统一管理,同时支持语义检索、关键词匹配、图谱遍历和时间维度检索四路并行。

agentmemory 则专注于跨 Agent 可移植性。它的记忆层不绑定任何特定 Agent——你在 Cursor 里积累的记忆,可以无缝迁移到 Windsurf 或 Claude Code 里继续用。在 LongMemEval 基准测试上,它的召回准确率达到了 92% 以上。

一些智能客服产品,背后就是这种混合架构。它沿着"用户 → 订单 → 商品 → 库存状态"的链路一步步找答案,最后把几路结果融合起来给你一个准确的回复。

三种数据库意味着三个供应商。谁来保证数据一致性?谁真正拥有你的 Agent 的完整记忆?

方案 | 多轮对话 | 持久化 | 语义检索 | 关系推理 | 归属权

Agent(无状态) | — | — | — | — | 你

+ 对话历史 | ✓ | — | — | — | 内存(进程死=内存丢失)

+ 文件 I/O | ✓ | ✓ | — | — | 你的文件(可存档)

+ 向量搜索 | ✓ | ✓ | ✓ | — | 向量数据库(格式绑定)

+ 图谱混合 | ✓ | ✓ | ✓ | ✓ | 三个供应商(谁拥有完整记忆?)

能力矩阵填满了。但代价不只是技术复杂度——还有运维成本。你需要维护三种数据库(关系型、向量、图谱),需要保证它们之间的数据一致性,需要处理索引更新、图谱重建、向量重新嵌入等定时任务。在生产环境中,Cognee 建议的配置是 PostgreSQL 做关系存储、Qdrant 做向量检索、Neo4j 做图谱查询——三个独立的服务需要监控、备份和故障恢复。

值不值得?取决于你的场景。如果你的 Agent 只需要回答"这个用户喜欢什么"这类简单问题,文件 + 向量就够了。但如果它需要回答"Alice 的项目最近有什么问题"这类需要链路推理的问题,混合架构不是奢侈,是必需。

---

6. 记忆会遗忘才健康——衰减与自我优化

到这一层你可能以为,存储多、检索准确,才是完美的记忆系统。实际上,完美的记忆系统是会主动遗忘的。

Cognee 的 memify() 函数做了一个看似违反常理的事情:主动地对知识图谱的边做一些弱化操作。意思是说,在知识图谱里有的节点 A 和 B 之间的关系,会被逐渐弱化,如果不经过强化(查询),它的权重会越来越低。

原理很简单:对于每条边(即表示两个实体之间的关系)都设置一个权重(weight),表示这条边的优先级。每当有查询经过这条路径时,会被强化(加大权重)——类似于森林里的小路,被人走的越多,越宽。而长期无人走的路径,它的强化权重会被按一定的比例进行衰减,直到忘记。

这背后的理论来自强化学习。以"用户 → 订单 → 商品 → 库存状态"为例,Cognee 的系统每当有人问 AI 客服"最近有哪些库存卖光的商品",这条路径的强化权重就会被加大一些。

越经常被查询的路径,越容易被检索到。

还是拿刚刚那个例子:你有一个 AI 的客服 agent。每天被问一次 "退款怎么办",然后用户需要去"商品 → 规格"看具体退款说明的路径,每天会被搜索引擎加强调查 300 次。而 3 年前某个已经被废弃的功能点,几乎不会有用户查询,权重会慢慢衰减到 0。

比如说同时为销售和 HR 内部部门做知识图谱搜索的 Agent。销售团队每天都会通过"产品 → 文档 → 解决方案"这条路径查询知识,这条边的强化权重会被加大。HR 管理员偶尔也会搜索员工的培训记录——通过"员工 → 培训记录"这条路径。因为后者使用频率低,前者使用频率高,系统会自动优化图谱,使搜索的频繁路径权重加大。

你的大脑也是这么实现记忆重要性的:你每天都会走从家到公司的路线。你闭着眼睛都能找到对应的路。因为你每天走这条路,这条路径被反复强化了。

19 世纪的心理学家 Hermann Ebbinghaus 通过实验总结出了人脑记忆衰减的规律:遵循指数曲线衰减。学习了一个完全新鲜的知识点,一小时后你只记住了它的 44%;一天后你只记住 33%。但如果你在这知识快被你完全遗忘时,去复习这个知识点一次。那么你的记忆就会被延长。

Cognee 的图谱衰减机制其实和 Hermann Ebbinghaus 概括的记忆衰减规律差不多:不常查的路径会被逐渐淘汰,经常查的路径会被强化。当用户的查询模式真实反映了系统被使用的场景时,系统其实已经帮你配置好了重要程度。

永不遗忘的记忆系统是噪音放大器。 购买了 3 年前的那些功能点和刚发布的核心功能,在检索时都有一样的优先级——搜索结果每次都会被各种无关紧要的噪音干扰。

Hindsight 框架的作者也意识到了这一点。他们实现了一个名叫 reflect 的操作:定期从当前的记忆中自动提取出新的知识点。就像你去睡觉,白天的很多记忆都被整理成了生物钟能记住的 episodic memory 一样。你跟 Agent 说了一百遍:『 我喜欢深色主题 』——Hindsight 的深度学习模型会自动生成一个 semantic rule:『 用户喜欢深色的界面主题 』。

好的记忆系统会记住重要的,主动遗忘过时的,从重复查询中提炼规律。

综上四层,加上这层衰减和遗忘机制,才能完整描述一个 AI Agent 的记忆架构。

但是还有最后一个问题没有解决:这些记忆到底归属于谁?

---

7. 你的记忆,属于谁?

归属权是我觉得 Agent 时代最容易被忽视的问题之一:很多人在发现记忆被丢失或者锁死以后,才意识到归属问题的存在。

它有三个级别,也可以叫锁定级别。从轻到重:

轻度锁定:有状态 API 。 有的 AI 服务商提供了类似"自动上下文压缩"的功能,你的对话历史存在他们的服务器上,按照特定压缩格式保留。效果确实不错,省去了你自己去管理上下文窗口的麻烦。但代价就是:换个模型商,你的记忆就丢失了。这些压缩好的上下文格式基本不具备可迁移性。比如说 Anthropic 家的 Claude ,虽然他们有服务端记忆的功能,但压缩后的对话上下文是无法导出的,你只能看到"Claude 记住了你喜欢吃辣"这个事实,而看不到压缩前的原始数据。Google Gemini 也类似,他们的"记忆"也是存在在 Google 的服务器上的。

中度锁定:封闭的 Agent 框架。 因为他们内置的记忆格式是自家专有的、压缩格式的摘要。用户看不到里面原始的内容,更无从迁移、导出。一篇叫"Your Harness, Your Memory"的文章,指出:你选择了什么样的 harness(框架),你的 agent 就会有怎么样的记忆系统。

为什么这么说呢?因为有的框架开发者在设计记忆系统时,并不考虑跨框架使用的兼容性。他们考虑的是和自家产品的无缝对接,以提升整体用户体验。如果你要从一个框架迁移到另一个,你的记忆是带不走的。框架不一定差:他们可能很强大、开发体验很好用。但你需要知道,用了这套框架多久,离换框架的痛苦值就会翻倍。

重度锁定:平台级记忆。 这个是归属权问题的最严重的情况,因为涉及到你整个数字化办公体系。有用户在论坛上分享过自己的经历:他使用了一家 AI 邮件助手,来帮助他整理半年的工作邮件。邮件助手 AI 了解他的沟通风格,给领导的邮件正式简练、给用户提问题时贴心周全。AI 慢慢学会了这个用户所有重要联系人的喜好、每个项目的重要节点、每个沟通中产生的待解决问题。

经过半年的积累,这个 AI 助手变成了这个用户的日常工作流的一部分。可后来这个产品调整了新的计费模式,比他之前预算的高。于是他找了其他的产品对比,并最终下了决定要换一个替代产品。但这位用户发现,自己积累半年的"记忆"全部被锁在了原来的平台里,无法导出。改用新的平台以后,新产品的表现一落千丈。

换个角度说:新助手缺少的是半年积累下来的系统了解这个用户工作习惯的能力。

你或许会认为这是极端情况。但这时你请问自己:你用 AI 助手有多久了?它积累了多少关于你工作习惯、项目细节以及偏好的信息?如果明天因为某种原因,这个平台被关停了,或者提价到你无法接受的价格?你能不能带走你和它积累下来的"记忆"?

随着工具的发展和成熟,Agent 的记忆会越来越具备复利作用:使用的时间长,AI 理解你的越透彻,帮你的越省力。而归属权问题也变得越来越重要。

我非常赞同开源精神:开源工具 + 开源格式 = 可迁移

你的Agent的记忆,理论上应该是一个可以下载的文件夹。文件夹里面只有你可以用记事本编辑的纯文本文件。

比如我们项目里面用到的 MEMORY.md、.SOUL.md、.USER.md 就是一个开放格式的体现。所有的内容都是纯文本,完全是人类可读的。任何编辑器都能打开、编辑。任何 Agent 都能读取。甚至可以用 Git 追踪版本变更历史。你不需要向任何公司申请就能查看、编辑你 Agent 的记忆。

Deep Agents 项目有一个很好的实践:他们设计了一个可以无缝换底层数据库引擎的记忆系统。换句话说,你可以选择 MongoDB、Postgres、Redis 作为你的记忆后端;而当你迁移时,也可以随意更换,因为他们的接口是开放的、可插拔的。

你现在可能正在用的工具里也有。如果你用过 Claude Code ,你自己搭建 Agent 的项目根目录里那些 .md 文件其实就是你 Agent 在本地硬盘上存储的文件。你不依赖任何 API、任何云服务商、任何平台,完全自建。换一个 Agent SDK?文件还在。换个工具读取它们就好。

即便 Claude Code 明天倒闭了,你随时可以用另外一个文本编辑器,直接查看其中的内容。

这就是开源格式的好处:控制权在你手上,而不是锁定在某一家公司的服务器上。

在选型记忆系统的时候,不仅要衡量它的技术能力(能不能检索准确、能不能做多级推理),还需要考虑记忆的可移植性:

如果明天我要换工具,我的记忆能带走吗?

如果你的答案不能,那么你可能需要找一套更开放的解决方案。

---

记忆选型决策树

说这么多方案,落地时到底该怎么选?

你可以用下面这张图:

你的 Agent 需要记住多少事实?

├─ 几个到几十个 → Markdown 文件就够了
│ 不用引入任何数据库。
│ MEMORY.md + Git 版本管理,简单可靠。

├─ 需要语义搜索吗("意思相近"能找到)?
│ ├─ 不需要 → 关键词 + 文件,到此为止
│ │ 适合项目文档、API 文档等结构明确的内容
│ └─ 需要 → 加向量数据库
│ 用 embedding 模型建立索引
│ 搜索从"字面匹配"升级为"语义匹配"

├─ 需要关系查询吗("A 通过 B 关联到 C")?
│ ├─ 不需要 → 向量 + 文件就够了
│ │ 大多数聊天机器人和知识库场景到此为止
│ └─ 需要 → 混合架构(向量 + 图谱 + BM25)
│ 用 RRF 融合三路检索结果
│ Cognee、Hindsight 可以帮你搭好

└─ 不确定?从 Markdown 开始,遇到瓶颈再升级
这是最务实的路径。每一层代码改动都不大,
而且你会清楚地知道"我为什么需要更复杂的方案"——因为简单方案在某个具体场景下失败了

工具 | 一句话特色 | 适合谁

Markdown 文件 | 零依赖,人类可读,Git 管理 | 个人开发者、轻量级 Agent ,不想引入额外基础设施

Hindsight | 仿生记忆、2 行代码接入、内置衰减 | 快速原型,想先跑起来再说

agentmemory | 跨 Agent 可移植记忆层,LongMemEval 92%+ | 多工具协同(Cursor + Claude + Windsurf 同时用)

Cognee | 四个 API 搭好三重存储、自动图谱构建 | 需要完整混合架构的生产项目

Hermes / OpenClaw | 内置 MEMORY.md 模式,Agent 策展记忆、开放格式 | 日常开发 Agent ,偏好开放格式和可移植性

如果我可以再给你一点建议的话,那就是从 Markdown 文本文件开始。用一个月的时间,把遇到的所有问题写下来。写到你发现哪些问题,关键词搜索无法解决。用一个月时间,集中解决关键词搜索无法解决的问题。再等关键词搜索跑得满地都是 bug 的时候,再考虑引入向量检索。用向量检索又过一个月,看看那些问题是因为"找不到相关关系"造成的。再引入一整套混合检索系统,去解决链路推理无法解决的问题。

逐步升级,以实用为主。

同时,不管你用哪种工具。都记住一个道理:选择开源的、开放的。

你的记忆是你工作中最能反映个人习惯、偏好的底层数据资产之一。甚至可以说是数据资产里面最能反映你个人的那一份。把它锁定在别人无法提供的格式里,那就等于把自己所有的数字化积累工作都交给了别人。

你的项目里用了哪些记忆方案?有遇到记忆丢失或者记忆被锁死的问题吗?评论区聊聊 ❤

更多游戏资讯请关注:电玩帮游戏资讯专区

电玩帮图文攻略 www.vgover.com