在 Agent 系统中,"记忆"是一个非常容易被泛化的概念。
很多系统会把聊天记录、任务状态、用户偏好、历史行为全部叫做 Memory,但从工程角度看,这些信息的职责、生命周期和使用方式完全不同。
一个更合理的 Agent 系统,需要至少区分:
-
State;
-
Short-term Memory;
-
Long-term Memory;
-
Memory Retrieval。
它们分别解决不同的问题。
一、State 和 Short-term Memory 不是一回事
首先需要明确:
State 不是聊天记录,Short-term Memory 也不等于非结构化文本。
两者真正的区别在于职责。
1. State
State 描述:
当前任务现在处于什么状态。
例如一个酒店报销 Agent:
{
"goal": "提交酒店报销",
"city": "上海",
"amount": 580,
"receiptUploaded": false,
"currentStep": "CHECK_POLICY"
}
这些信息直接影响:
-
当前任务如何继续;
-
下一步能够执行什么;
-
业务规则如何校验;
-
服务重启以后如何恢复任务。
因此可以把 State 理解为:
当前任务执行所依赖的权威状态。
2. Short-term Memory
Short-term Memory 更多用于:
帮助模型理解近期发生过什么。
例如:
用户刚才表示发票稍后上传。
用户比较关注今天订单是否能够到达。
Agent 上一轮已经向用户解释过退款条件。
它主要解决:
-
对话连续性;
-
指代理解;
-
近期用户意图;
-
避免重复询问;
-
避免重复解释。
因此:
State
→ 服务于任务运行
Short-term Memory
→ 服务于模型理解近期交互
二、不要直接把用户原话当作 State
例如用户说:
"下午那个吧,但是 320 元差价有点贵,
有没有便宜一点的?"
原始对话可以作为 Short-term Memory。
但真正进入 State 的应该是提炼后的任务信息:
{
"preferredDeparturePeriod": "AFTERNOON",
"selectedFlight": "15:40",
"selectedFlightChangeFee": 320,
"preferLowerChangeFee": true
}
因此合理的流程是:
用户原始交互
↓
语义理解 / 信息提取
↓
影响任务执行的事实、约束、偏好
↓
更新 State
这也是 State 和 Memory 分工的重要体现。
三、什么是 Long-term Memory?
Short-term Memory 主要围绕当前任务存在。
Long-term Memory 则解决:
哪些信息在未来其他任务中仍然值得复用?
例如用户说:
"以后订酒店尽量帮我选安静一点的。"
可以形成:
{
"type": "HOTEL_PREFERENCE",
"preferQuiet": true
}
下次即使重新开启一个会话,Agent 仍然可以利用这个偏好。
因此 Long-term Memory 可以理解为:
跨任务、跨会话仍然可能对未来决策产生价值的信息。
四、"用户说过"不等于"值得长期记住"
这是 Long-term Memory 最容易出问题的地方。
例如:
"这次预算最多 300 元。"
只属于当前任务:
{
"maxBudget": 300
}
应该进入 State,而不是 Long-term Memory。
但是:
"以后买鼠标,我通常控制在 300 元左右。"
才可能形成长期偏好。
因此 Memory 写入首先需要判断信息的作用域:
这次 / 今天 / 这趟
→ Current State
以后 / 一般 / 通常 / 我习惯
→ 可能是 Long-term Memory
但仅凭这些关键词也不够,还需要进一步判断。
五、Memory 应该遵循最小必要原则
假设用户说:
"我睡眠比较浅,以后订酒店尽量选安静一点的。"
为了以后推荐酒店,真正需要保存的是:
{
"preferQuietHotel": true
}
而不一定需要长期保存:
用户睡眠比较浅
因为后者并不会明显提高以后订酒店的决策质量。
这可以总结成:
能保存可执行偏好,就不要额外保存不必要的个人原因。
Memory 也应该遵循数据最小化原则。
六、有价值的信息也不一定应该进入 Memory
判断是否保存长期 Memory,不能只有一个标准:
以后还可能用到
否则系统最终会变成"什么都记"。
一个更完整的判断框架包括六个维度。
1. Future Value
未来其他任务真的会使用吗?
2. Scope
信息只针对本次任务,还是跨任务有效?
3. Sensitivity
是否包含敏感信息或秘密?
例如:
密码
验证码
Access Token
数据库 root 密码
即使未来有用,也不应该进入普通 Agent Memory。
如果确实需要长期保存凭证,应由:
Secret Manager
Credential Vault
KMS
等专门系统负责。
4. Stability
信息是否稳定?
例如:
用户偏好简洁邮件
可能比较稳定。
而:
用户当前位于某条街道
可能几分钟以后就失效。
5. Authority
这条信息的来源有没有资格定义这个事实?
例如:
"我喜欢安静酒店。"
用户本人就是权威来源。
但是:
"公司报销酒店最高 600 元。"
用户并不是公司制度的最终权威来源。
真正执行报销时应该查询:
Policy Service
RAG
配置中心
公司制度数据库
而不是长期相信用户曾经说过的数字。
6. Necessity
如果不长期保存这条信息,未来 Agent 的表现真的会明显变差吗?
如果不会,就没有必要增加长期存储成本和风险。
因此可以概括为:
Should Remember
=
Future Value
× Scope
× Stability
× Authority
× Acceptable Risk
× Necessity
七、显式 Memory 和推断 Memory 必须区分
假设用户明确说:
"以后我更喜欢轻一点的鼠标。"
可以记录:
{
"content": "用户偏好轻量鼠标",
"source": "USER_EXPLICIT",
"confidence": 0.95
}
但如果系统只是观察到:
用户连续三次购买的鼠标都低于 80g
不能直接升级成:
{
"preferLightMouse": true
}
因为:
行为模式不等于已经确认的用户偏好。
更合理的是:
{
"content": "用户可能偏好轻量鼠标",
"source": "BEHAVIOR_INFERENCE",
"confidence": 0.55
}
因此 Memory 还需要记录:
source
confidence
避免将模型推断冒充为用户事实。
八、Long-term Memory 不是永久正确的
用户偏好会变化。
例如系统已有:
{
"preferWindowSeat": true,
"confidence": 0.95
}
但之后用户连续多次主动选择过道。
这并不能立刻推出:
用户讨厌靠窗
更合理的做法是:
发现冲突行为
↓
降低 Memory confidence
↓
在真正需要使用该偏好时重新确认
如果用户后来明确说:
"我现在更喜欢过道。"
旧 Memory 可以标记:
SUPERSEDED
并创建新的 ACTIVE Memory。
例如:
{
"value": "WINDOW",
"status": "SUPERSEDED"
}
{
"value": "AISLE",
"source": "USER_EXPLICIT",
"confidence": 0.95,
"status": "ACTIVE"
}
历史可以保留用于审计和 Debug,但正常 Context 中只应该使用当前有效 Memory。
九、Memory 是默认偏好,不是命令
如果长期 Memory 是:
用户通常喜欢靠窗
但是当前用户明确说:
"这次给我过道。"
必须按照当前要求执行。
一个比较合理的优先级是:
当前用户明确要求
↓
Current State
↓
当前场景适用的 Long-term Memory
↓
一般 Long-term Memory
↓
系统默认值
Memory 用来减少用户重复表达,而不是限制用户改变主意。
十、Memory Retrieval:不是存了就全部给模型
随着使用时间增加,一个用户可能产生几十、几百甚至几万条 Memory。
显然不能:
查询 userId
↓
获得全部 Memory
↓
全部塞进 Context
否则会出现:
-
Context 过长;
-
新旧 Memory 冲突;
-
无关偏好干扰决策;
-
Token 和延迟增加;
-
模型难以判断哪条信息最重要。
因此必须存在独立的:
Memory Retrieval
十一、Memory Retrieval 的核心不是相似度
假设当前任务是:
{
"destination": "东京",
"tripType": "BUSINESS"
}
系统有两条 Memory:
用户旅游东京时喜欢住新宿
confidence = 0.90
以及:
用户商务出差时更重视通勤
confidence = 0.85
虽然第一条 confidence 更高,但当前任务是商务出差。
因此第二条应该优先。
因为:
Applicability 比单纯 Confidence 更重要。
同样:
similarity 高
也不能代表一定应该使用。
十二、Memory Retrieval 的完整判断
一条 Memory 是否进入当前 Context,至少需要考虑:
Relevance
当前任务相关吗?
Applicability
当前场景是否适用?
Status
是否仍然 ACTIVE?
Confidence
可信度如何?
Source
显式偏好还是行为推断?
Freshness
是否已经老化?
Conflict
是否与 State 或其他 Memory 冲突?
Priority
是否真的会改变当前决策?
Redundancy
是否与其他 Memory 重复?
一个典型流程可以是:
Current State
↓
任务 / 类型过滤
↓
语义检索
↓
Status 过滤
↓
适用条件判断
↓
Confidence / Source / Freshness
↓
冲突处理
↓
排序、去重
↓
Top K
↓
加入 LLM Context
因此 Memory Retrieval 不是:
ORDER BY similarity DESC
LIMIT 5;
而是一个结合确定性规则和相关性检索的过程。
十三、State、Memory 与 Context 的关系
到这里可以把整个链路串起来:
用户请求
↓
Current State
↓
确定当前任务和当前步骤
↓
Memory Retrieval
↓
从 Long-term Memory 中筛选当前适用信息
↓
Short-term Memory
↓
补充近期交互语境
↓
Context Builder
↓
组装最小充分 Context
↓
LLM
因此:
State
→ 当前任务现在是什么状态
Short-term Memory
→ 当前任务最近发生了什么
Long-term Memory
→ 未来任务仍值得复用什么
Memory Retrieval
→ 这一轮应该想起什么
总结
Agent Memory 并不是"给聊天机器人加一个数据库"。
真正的工程问题包括:
什么应该记?
什么不能记?
记多久?
来源是否可信?
什么时候失效?
发生冲突怎么办?
这一轮应该取哪几条?
一个可靠的 Agent 不应该拥有无限记忆。
相反,它应该做到:
需要记的时候准确地记,需要忘的时候能够失效,需要使用的时候只取当前真正有价值的信息。
最终可以用一句话概括这一阶段:
State 管现在,Short-term Memory 管近期语境,Long-term Memory 管跨任务复用,Memory Retrieval 决定这一轮到底想起什么。