06 - 记忆系统:让 Agent 真正”认识”用户
一句话总结:用 MemoryManager 让 Agent 跨越所有会话记住用户的偏好和信息,从”有记性”进化到”有记忆”。
先搞清楚:Storage 和 Memory 是两回事
上一篇我们让 Agent 学会了在同一个 session 里”记住”上下文。但你可能已经发现问题了 – 换一个 session,Agent 又变成了陌生人。
这就好比你跟一个人聊了三天微信,换个聊天窗口他就不认识你了。这说不过去。
Agno 把”记性”分成了两个层次:
- Storage(存储) – 保存对话历史和 session 状态。它是单个 session 内的东西,就像你的聊天记录。你可以翻看某次对话说了什么,但每个聊天窗口是独立的。
- Memory(记忆) – 保存关于用户的长期信息。它跨越所有 session,就像你大脑中对一个人的印象。不管在哪个聊天窗口,你都知道他叫什么、喜欢什么、做什么工作。
上一篇的 db、add_history_to_context、session_state 都属于 Storage。今天我们来搞 Memory。
MemoryManager:给 Agent 装上长期记忆
核心思路很简单:有一个专门的 MemoryManager 负责从对话中提取关键信息,存到数据库里。下次不管开哪个 session,Agent 都能把这些信息捞出来。
来看最基本的用法:
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.db.sqlite import SqliteDb
from agno.memory import MemoryManager
db = SqliteDb(db_file="tmp/agents.db")
memory_manager = MemoryManager(
model=OpenAIChat(id="gpt-4o-mini"),
db=db,
)
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
db=db,
memory_manager=memory_manager,
enable_agentic_memory=True, # Agent 自己决定什么时候存记忆
instructions="你是一个贴心的助手,会记住用户的偏好和信息",
markdown=True,
)
# 告诉 Agent 一些关于自己的信息
agent.print_response(
"我叫小明,我是一个Python开发者,喜欢用FastAPI",
user_id="xiaoming",
)
# 开一个全新的 session -- 它依然记得你
agent.print_response(
"你还记得我吗?我擅长什么?",
user_id="xiaoming",
session_id="new-session",
)
运行一下,你会发现 Agent 在新 session 里依然知道你叫小明、是 Python 开发者、喜欢 FastAPI。这不是靠对话历史,而是靠 MemoryManager 提取并存储的”记忆”。
记忆捕获的两种模式
Agno 提供了两种方式来捕获用户信息:
1. Agentic 模式:Agent 自己决定
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
db=db,
memory_manager=memory_manager,
enable_agentic_memory=True, # Agent 通过工具调用来存储记忆
)
这种模式下,MemoryManager 会给 Agent 注入一些记忆相关的工具(add_memory、update_memory 等)。Agent 在对话过程中自己判断”这条信息值得记下来”,然后主动调用工具存储。
优点:高效,只在需要的时候触发,不浪费 token。 缺点:Agent 可能会”忘记”调用工具,漏掉一些信息。
2. Always 模式:每次都跑一遍
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
db=db,
memory_manager=memory_manager,
update_memory_on_run=True, # 每次回复后都自动提取记忆
)
这种模式下,Agent 每次回复之后,MemoryManager 都会在后台跑一遍,分析对话内容,决定要不要创建或更新记忆。
优点:不会漏掉信息,捕获更全面。 缺点:每次都多一轮模型调用,延迟更高、费用更多。
怎么选?如果你的场景对信息完整性要求高(比如客服系统、健康助手),用 update_memory_on_run=True。如果对话比较随意、偶尔记一下就行,用 enable_agentic_memory=True 更省钱。
自定义记忆捕获规则
默认情况下,MemoryManager 会捕获用户的姓名、职业、偏好这些常规信息。但你可以通过 additional_instructions 告诉它重点关注什么:
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.db.sqlite import SqliteDb
from agno.memory import MemoryManager
db = SqliteDb(db_file="tmp/agents.db")
memory_manager = MemoryManager(
model=OpenAIChat(id="gpt-4o-mini"),
db=db,
additional_instructions="重点记录用户的技术栈偏好、项目经验和工作习惯。忽略闲聊内容。",
)
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
db=db,
memory_manager=memory_manager,
enable_agentic_memory=True,
instructions="你是一个技术助手",
markdown=True,
)
agent.print_response(
"我最近在用FastAPI和SQLAlchemy做一个微服务项目,"
"团队用的是GitLab CI做持续集成,部署在AWS ECS上。"
"对了昨天天气真不错。",
user_id="xiaoming",
)
在这个例子里,MemoryManager 会重点记录技术栈相关的信息(FastAPI、SQLAlchemy、GitLab CI、AWS ECS),而”天气不错”这种闲聊大概率会被忽略。
你也可以用 memory_capture_instructions 完全替换默认的捕获规则:
memory_manager = MemoryManager(
model=OpenAIChat(id="gpt-4o-mini"),
db=db,
memory_capture_instructions="""\
只记录以下类型的信息:
- 用户的编程语言偏好
- 用户正在做的项目
- 用户明确表达的技术观点
其他信息一律不记录。
""",
)
查看已存储的记忆
想知道 Agent 到底记住了什么?用 get_user_memories:
memories = agent.get_user_memories(user_id="xiaoming")
if memories:
for m in memories:
print(f"[{m.memory_id}] {m.memory}")
if m.topics:
print(f" topics: {m.topics}")
else:
print("暂无记忆")
输出可能是这样的:
[abc-123] 用户名叫小明,是一个Python开发者
topics: ['name', 'occupation']
[def-456] 小明喜欢用FastAPI框架
topics: ['preferences', 'technology']
[ghi-789] 小明的团队使用GitLab CI和AWS ECS
topics: ['technology', 'infrastructure']
每条记忆都有一个唯一的 memory_id,还可能带有 topics 标签。这些都是 MemoryManager 自动生成的。
user_id 是关键
你可能注意到了,每次调用 print_response 的时候我们都传了 user_id="xiaoming"。这个参数决定了记忆归属于谁。
规则很简单:
- 相同的
user_id-> 共享记忆,不管在哪个 session - 不同的
user_id-> 记忆完全隔离
# 小明的记忆
agent.print_response("我喜欢Python", user_id="xiaoming")
# 小红的记忆 -- 跟小明完全隔离
agent.print_response("我喜欢Rust", user_id="xiaohong")
# 新 session 里问小明 -- 只知道 Python,不知道 Rust
agent.print_response("我喜欢什么语言?", user_id="xiaoming", session_id="new")
如果你不传 user_id,Agno 会用一个默认值。但在实际应用中,你几乎一定要传 – 否则所有用户的记忆会混在一起,那就乱套了。
一个完整的例子
把前面说的串起来,写一个记得住用户的技术助手:
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.db.sqlite import SqliteDb
from agno.memory import MemoryManager
db = SqliteDb(db_file="tmp/agents.db")
memory_manager = MemoryManager(
model=OpenAIChat(id="gpt-4o-mini"),
db=db,
additional_instructions="记录用户的技术偏好、工作角色和项目信息",
)
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
db=db,
memory_manager=memory_manager,
enable_agentic_memory=True,
add_history_to_context=True, # session 内也带上历史
num_history_runs=5,
instructions="你是一个技术助手,会记住用户的背景和偏好,给出个性化的建议",
markdown=True,
)
user_id = "dev-xiaoming"
# 第一次对话:自我介绍
agent.print_response(
"你好,我是小明,后端开发,主要用Python和Go。最近在学Rust。",
user_id=user_id,
session_id="session-1",
)
# 第二次对话:聊项目
agent.print_response(
"我们团队在做一个实时数据处理管道,现在用的是Kafka加Flink。",
user_id=user_id,
session_id="session-1",
)
# 看看 Agent 记住了什么
print("\n--- 已存储的记忆 ---")
memories = agent.get_user_memories(user_id=user_id)
if memories:
for m in memories:
print(f" - {m.memory}")
# 全新的 session -- Agent 依然认识你
print("\n--- 新 session ---")
agent.print_response(
"帮我推荐一个适合我们项目的消息队列方案?",
user_id=user_id,
session_id="session-2",
)
在最后一次调用中,虽然是全新的 session(没有对话历史),但 Agent 知道你用 Python 和 Go、在做实时数据处理、用了 Kafka 和 Flink,所以它能给出有针对性的建议,而不是泛泛而谈。
Storage vs Memory vs State:三者对比
到现在为止,我们已经接触了 Agno 中三种”记住东西”的机制。来做个清晰的对比:
| 特性 | Storage (对话历史) | Session State | Memory (记忆) |
|---|---|---|---|
| 范围 | 单个 session | 单个 session | 跨所有 session |
| 内容 | 原始聊天记录 | 结构化键值对 | 提取的用户信息 |
| 写入方式 | 自动(每次对话) | 工具调用修改 | MemoryManager 提取 |
| 读取方式 | add_history_to_context |
指令中 {变量} |
自动注入上下文 |
| 典型用途 | 多轮对话连贯性 | 追踪表单状态、计数 | 用户偏好、背景 |
| 需要 db | 持久化才需要 | 持久化才需要 | 必须 |
怎么选?
- 只需要多轮对话?用 Storage 就够了
- 需要追踪结构化的会话数据?加上 Session State
- 需要跨会话认识用户?上 Memory
三者不冲突,可以同时使用。实际项目中最常见的组合是 Storage + Memory:session 内靠历史记录保持连贯,跨 session 靠记忆保持个性化。
今天学了什么
回顾一下关键概念:
- MemoryManager 是独立于 Agent 的记忆管理器,负责从对话中提取、存储、更新用户信息
- enable_agentic_memory=True 让 Agent 自己决定何时存记忆(高效但可能遗漏)
- update_memory_on_run=True 每次回复后自动提取记忆(全面但延迟更高)
- additional_instructions 可以告诉 MemoryManager 重点关注哪些信息
- user_id 是记忆的归属标识,相同 user_id 跨 session 共享记忆
- get_user_memories() 可以查看已存储的记忆内容
- Storage、Session State、Memory 三者各有分工,按需组合
生产环境建议用 PostgreSQL 替代 SQLite,换一下连接就行,API 完全一样。
下一篇预告
07 - 知识库与 RAG:让 Agent 拥有专属知识
Memory 让 Agent 认识用户,但 Agent 自己的知识呢?如果你想让它理解你的产品文档、API 手册、内部 wiki,光靠模型训练数据可不够。下一篇我们聊知识库和 RAG – 把你的数据喂给 Agent,让它变成你的领域专家。