AI Agent(能够调用工具、规划任务并持续执行的人工智能程序)如果没有记忆,每次对话都像第一次见到用户。
用户已经说过自己的职业、偏好、常用工具、项目背景,Agent 下一轮仍然需要重新询问;一个长任务执行到一半,如果上下文太长,还会不断把历史消息塞回提示词里,token 成本越来越高,模型也更容易忽略关键状态。
TencentDB Agent Memory 解决的就是这个问题:给 AI Agent 增加独立的记忆层,让它能保存、检索、更新用户事实和任务上下文。
项目地址:
https://github.com/TencentCloud/TencentDB-Agent-Memory
这个项目由腾讯云数据库团队开源,目标很明确:为 Agent 提供长期记忆和短期记忆能力。公开评测数据里,长期记忆整体准确率从 47.85% 提高到 76.10%,用户事实召回从不到 30% 提高到 79%;短期记忆在长任务中最高节省 61% token。
这组结果说明,Agent Memory 不是简单地把聊天记录存起来,而是把“该记住什么、什么时候取出来、怎么塞回上下文”做成了一套可复用的记忆机制。
图中的核心信息可以拆成两部分看:长期记忆主要改善事实召回和回答准确率,短期记忆主要降低长任务中的上下文消耗。前者影响“AI 是否记得住你”,后者影响“AI 执行复杂任务时会不会越跑越贵、越跑越乱”。
上下文窗口不是记忆
大语言模型(LLM,Large Language Model)的上下文窗口只能保存当前请求里传进去的内容。它看起来像记忆,实际上只是临时输入。
假设用户告诉 Agent:
我负责一个 Go 后端项目,数据库用 PostgreSQL,部署在 Kubernetes 上。
如果下一轮请求仍然包含这句话,模型就能利用它;如果请求里不再包含,模型就不知道。上下文窗口不会主动把这条信息保存到某个长期位置,也不会在下一次对话中自动取出来。
单纯依赖上下文窗口会遇到三个问题:
| 问题 | 表现 | 后果 |
|---|---|---|
| 会话结束即丢失 | 新会话无法继承旧信息 | 用户反复补充背景 |
| 长上下文成本高 | 每轮都带上大量历史消息 | token 消耗上升,响应变慢 |
| 关键信息容易淹没 | 历史消息越多,噪声越多 | 模型忽略重要事实或任务状态 |
Agent Memory 的核心思路是把记忆从提示词里拆出来,放到一个独立模块中管理。模型需要时再检索相关内容,而不是把全部历史都塞进去。
长期记忆和短期记忆分别负责什么
Agent 记忆通常分成两类:长期记忆和短期记忆。
| 记忆类型 | 生命周期 | 保存内容 | 主要作用 | 典型例子 |
|---|---|---|---|---|
| 短期记忆 | 当前任务或当前会话 | 最近对话、任务步骤、临时状态 | 保持任务连续性,减少重复上下文 | “已经完成需求分析,正在生成接口设计” |
| 长期记忆 | 跨会话长期存在 | 用户事实、偏好、稳定背景 | 让 Agent 认识用户,减少重复询问 | “用户常用 Go 和 PostgreSQL” |
短期记忆更像工作台上的便签,用来记录当前正在做什么;长期记忆更像用户档案,用来保存长期有效的信息。
一个完整的 Agent 记忆系统通常会同时使用这两类记忆:
flowchart LR
U[用户输入] --> A[Agent 运行时]
A --> S[短期记忆检索]
A --> L[长期记忆检索]
S --> C[上下文组装]
L --> C
C --> M[大语言模型]
M --> R[生成回复 / 调用工具]
R --> W[记忆写入与更新]
W --> S
W --> L
关键点在于,记忆不是只写不读,也不是只读不管更新。每轮交互后,系统都要判断哪些内容需要进入短期记忆,哪些内容值得沉淀成长期记忆,哪些旧记忆需要合并、覆盖或删除。
长期记忆:记住用户事实和偏好
长期记忆的目标不是保存完整聊天记录,而是提炼出对未来有用的稳定信息。
例如用户说:
以后帮我写代码示例时,尽量用 Python,不要用 Java。
这句话适合进入长期记忆,因为它表达的是用户偏好,而且会影响未来多次交互。
可以抽取成结构化记忆:
{
"user_id": "u_123",
"type": "preference",
"content": "用户希望代码示例优先使用 Python,避免使用 Java。",
"source": "conversation",
"created_at": "2026-06-07T10:30:00+08:00",
"confidence": 0.95
}
后续用户问“帮我写一个文件上传接口示例”时,Agent 可以检索到这条偏好,并自动使用 Python 示例,而不需要用户重复说明。
长期记忆的写入流程一般包含几个步骤:
flowchart TD
A[对话内容] --> B[候选记忆抽取]
B --> C{是否值得长期保存}
C -- 否 --> D[丢弃]
C -- 是 --> E[分类:事实 / 偏好 / 关系 / 目标]
E --> F[去重与冲突检测]
F --> G[写入长期记忆库]
这里最容易出问题的是“是否值得长期保存”。不是每句话都应该进入长期记忆,否则记忆库会迅速变脏。
适合长期保存的内容通常有这些特征:
| 内容类型 | 是否适合长期记忆 | 说明 |
|---|---|---|
| 用户稳定偏好 | 是 | 会持续影响后续输出 |
| 用户职业、技术栈、项目背景 | 是 | 能减少重复沟通 |
| 临时闲聊 | 否 | 对未来任务价值低 |
| 一次性任务参数 | 视情况而定 | 当前任务需要,长期不一定需要 |
| 模型猜测出的信息 | 谨慎 | 没有用户确认时容易污染记忆 |
长期记忆检索也不能只做关键词匹配。用户问“给我一个适合当前项目的部署方案”,并没有直接出现“Go”“PostgreSQL”“Kubernetes”,但这些旧事实都和当前问题有关。更合理的做法是结合语义检索、标签过滤和相关性排序,只把最有用的几条记忆放进提示词。
短期记忆:让长任务不用反复携带完整历史
短期记忆主要服务长任务。
例如让 Agent 完成一个需求分析、数据库设计、接口设计、代码生成、测试用例生成的连续任务,如果每一步都把前面所有对话完整塞进上下文,token 会持续增长。
短期记忆会把“当前任务状态”压缩成更小的结构:
{
"session_id": "s_456",
"task": "设计一个文件管理系统后端",
"progress": [
"已确定核心实体:User、File、Folder、Permission",
"已选择 PostgreSQL 作为关系数据库",
"正在设计文件上传和权限校验接口"
],
"constraints": [
"接口示例使用 Python",
"返回 REST API 设计"
]
}
这样下一轮不需要携带完整历史,只需要携带短期记忆摘要和最近几轮关键消息。
短期记忆的工作流可以画成这样:
flowchart TD
A[当前用户请求] --> B[读取最近消息]
B --> C[读取任务摘要]
C --> D[组装精简上下文]
D --> E[模型生成结果]
E --> F[更新任务摘要]
F --> G[保留必要最近消息]
G --> H[丢弃低价值历史]
短期记忆省 token 的原因很直接:它把“完整历史”变成“任务摘要 + 必要片段”。如果摘要质量足够好,模型仍然知道任务进展,却不用读取大量重复内容。
Agent Memory 在 Agent 链路里的位置
记忆模块通常不直接替代 LLM,也不替代工具调用框架。它更像 Agent Runtime 旁边的一层中间件,负责在模型调用前后做两件事:
- 模型调用前:根据用户输入检索相关记忆,组装进提示词。
- 模型调用后:根据用户输入和模型回复,更新短期记忆与长期记忆。
整体链路如下:
sequenceDiagram
participant User as 用户
participant Agent as Agent 运行时
participant Memory as Agent Memory
participant LLM as 大语言模型
participant Tool as 外部工具
User->>Agent: 发送请求
Agent->>Memory: 检索短期记忆和长期记忆
Memory-->>Agent: 返回相关记忆
Agent->>LLM: 携带记忆生成计划
LLM-->>Agent: 返回回复或工具调用意图
Agent->>Tool: 执行工具调用
Tool-->>Agent: 返回工具结果
Agent->>Memory: 更新任务状态和用户记忆
Agent-->>User: 返回最终结果
这个设计的好处是解耦。Agent 可以继续使用原来的模型、工具和业务逻辑,只需要在输入输出两端加上记忆读写。
一个简化版接入示例
实际项目要以 TencentDB Agent Memory 仓库中的接口为准。为了说明接入位置,可以用一个简化版伪代码表达核心流程:
class AgentMemory:
def get_short_term(self, session_id: str, max_tokens: int):
"""读取当前会话的任务摘要和必要历史"""
pass
def search_long_term(self, user_id: str, query: str, top_k: int):
"""根据当前问题检索用户长期记忆"""
pass
def update_short_term(self, session_id: str, user_message: str, agent_reply: str):
"""更新当前任务状态"""
pass
def extract_and_upsert_long_term(self, user_id: str, user_message: str, agent_reply: str):
"""抽取长期有效的信息,并进行新增或更新"""
pass
def handle_message(user_id: str, session_id: str, message: str):
memory = AgentMemory()
short_memory = memory.get_short_term(
session_id=session_id,
max_tokens=2000
)
long_memory = memory.search_long_term(
user_id=user_id,
query=message,
top_k=5
)
prompt = build_prompt(
user_message=message,
short_memory=short_memory,
long_memory=long_memory
)
agent_reply = call_llm(prompt)
memory.update_short_term(
session_id=session_id,
user_message=message,
agent_reply=agent_reply
)
memory.extract_and_upsert_long_term(
user_id=user_id,
user_message=message,
agent_reply=agent_reply
)
return agent_reply
提示词里可以把记忆放到单独区域,避免和用户当前请求混在一起:
你是一个编程助手。
【长期记忆】
- 用户偏好:代码示例优先使用 Python。
- 用户背景:用户负责 Go 后端服务,数据库常用 PostgreSQL。
【短期记忆】
- 当前任务:设计文件管理系统后端。
- 已完成:实体设计、数据库选型。
- 当前步骤:生成文件上传接口。
【用户请求】
请继续给出上传接口的参数校验逻辑。
这种格式有两个好处:模型能清楚区分“历史记忆”和“当前问题”,系统也更容易控制注入到提示词里的记忆数量。
记忆检索不能越多越好
很多 Agent 记忆系统会陷入一个误区:既然记忆有用,那就多取一些。
这会带来两个问题。
一是 token 又涨回去了。长期记忆如果一次取几十条,和塞完整历史没有本质区别。
二是噪声会影响模型判断。无关记忆越多,模型越可能把过期信息、弱相关信息当成重要约束。
更稳妥的策略是给记忆检索设置预算:
| 控制项 | 建议做法 |
|---|---|
| top_k | 长期记忆通常只取最相关的几条 |
| token 上限 | 为短期记忆和长期记忆分别设置最大 token |
| 相关性阈值 | 低于阈值的记忆不注入提示词 |
| 时间衰减 | 太旧且很少被使用的记忆降低权重 |
| 类型过滤 | 当前任务只取相关类型,比如偏好、项目背景、约束 |
记忆模块的目标不是“记住所有东西”,而是“在正确的时候拿出正确的内容”。
适合和不适合的场景
Agent Memory 对跨会话、长任务、个性化场景帮助明显,但不是所有 AI 应用都需要它。
| 场景 | 是否适合 | 原因 |
|---|---|---|
| 个人助理 | 适合 | 需要长期记住用户习惯、日程偏好、常用信息 |
| 编程 Agent | 适合 | 需要记住项目背景、技术栈、代码风格和任务进度 |
| 客服 Agent | 适合 | 需要关联用户历史问题、偏好和服务记录 |
| 数据分析 Agent | 适合 | 需要记住数据口径、指标定义和分析上下文 |
| 一次性问答 | 不一定 | 单轮问题直接回答即可,记忆成本可能大于收益 |
| 高敏感临时咨询 | 谨慎 | 需要严格控制保存范围和删除机制 |
| 纯检索问答 | 不一定 | 如果只需要检索知识库,RAG(检索增强生成)可能已经足够 |
RAG 解决的是“从知识库找资料”,Agent Memory 解决的是“记住用户和任务”。两者可以结合,但不是同一个东西。
落地时最容易踩的坑
1. 把模型猜测当成用户事实
如果用户说“帮我写一个 Java 示例”,不能直接写入“用户偏好 Java”。这可能只是当前任务要求,不代表长期偏好。
更安全的写入策略是区分事实来源:
{
"content": "用户本次请求使用 Java 示例。",
"scope": "session",
"confidence": 0.8
}
只有用户明确表达长期偏好时,才进入长期记忆。
2. 旧记忆和新记忆冲突
用户偏好会变化。比如长期记忆里已有:
用户希望代码示例使用 Python。
后来用户说:
以后示例都改成 TypeScript。
这时不能简单追加一条新记忆,否则检索时可能同时取出 Python 和 TypeScript,模型不知道该听谁的。
冲突处理一般有三种方式:
| 策略 | 适用情况 |
|---|---|
| 覆盖旧记忆 | 用户明确表达新偏好 |
| 标记过期 | 旧信息仍需审计但不再参与检索 |
| 同时保留并加条件 | 偏好与场景相关,比如后端用 Go,前端用 TypeScript |
3. 隐私和删除机制不完整
记忆越强,隐私责任越重。用户事实、工作背景、偏好、任务内容都可能包含敏感信息。
一个可上线的记忆系统至少要支持:
- 用户可查看已保存记忆;
- 用户可删除指定记忆;
- 敏感字段可配置不保存;
- 不同用户和租户之间严格隔离;
- 记忆写入、读取、删除都有审计记录。
4. 短期摘要丢失关键细节
短期记忆通常依赖摘要压缩,但摘要不是无损压缩。如果摘要阶段漏掉约束,后续模型会偏离任务。
例如“不要引入 Redis”这样的限制,一旦没进入短期记忆,后面生成架构时可能又把 Redis 加回来。
短期记忆摘要最好保留几类信息:
| 信息类型 | 示例 |
|---|---|
| 当前目标 | 生成文件管理系统后端设计 |
| 已完成步骤 | 已完成实体设计和数据库设计 |
| 强约束 | 不引入 Redis,接口使用 REST |
| 待办事项 | 继续生成上传接口 |
| 用户确认结果 | 用户已确认 PostgreSQL 方案 |
评测指标应该怎么理解
TencentDB Agent Memory 公布的几个数字可以放在不同维度理解:
| 指标 | 含义 | 说明 |
|---|---|---|
| 长期记忆整体准确率 47.85% → 76.10% | Agent 利用长期记忆回答问题的正确率提高 | 相对提升约 59.04% |
| 用户事实召回 <30% → 79% | 系统更容易找回用户相关事实 | 直接影响个性化回答质量 |
| 长任务最高节省 61% token | 短期记忆减少重复上下文 | 影响成本、延迟和上下文稳定性 |
长期记忆指标更关注“记得准不准”,短期记忆指标更关注“任务跑得省不省”。两个方向都重要,因为一个 Agent 既要理解用户,也要能稳定完成多轮任务。
Agent 记忆模块的价值边界
TencentDB Agent Memory 把 Agent 记忆做成了独立能力,这对应用开发很关键。没有记忆层时,开发者只能在提示词、数据库表、会话历史里各自拼凑;有了统一记忆模块后,长期用户事实、短期任务状态、检索和更新逻辑都可以收敛到一个清晰位置。
它最适合用在需要持续交互的 Agent 系统中,例如个人助理、编程助手、客服助手、数据分析助手。对于只做单轮问答的应用,接入记忆模块未必能带来明显收益,反而会增加存储、检索、隐私管理和调试成本。
真正可用的 AI Agent 不只是会调用工具,还要能在多次交互中保持连续性。长期记忆让它认识用户,短期记忆让它记住当前任务,这两者组合起来,Agent 才能从“每轮重新开始”变成“持续协作”。
