Agno 02_agents 示例详解:用 MemoryManager 与 LearningMachine 为 Agent 构建跨会话持久记忆
本文围绕 Agno 仓库 cookbook/02_agents/06_memory_and_learning 目录中的两个官方示例展开:memory_manager.py 演示如何为 Agent 提供跨会话的持久记忆(MemoryManager),learning_machine.py 演示如何基于 LearningMachine 实现 agentic 模式的用户画像学习。读完本文,你将理解两种记忆机制的适用边界、关键参数(enable_agentic_memory、LearningMode.AGENTIC、记忆数据库注入等)的作用方式,并能按文档给出的环境配置直接复现这两个可运行的完整示例。
一、文档定位与示例文件清单
cookbook/02_agents/06_memory_and_learning 是 Agent 章节(02_agents)下专门演示"持久记忆与学习行为"(persistent memory and learning behavior)的示例目录。目录中的 README.md 列出了两个核心文件:
| 文件 | 作用 |
|---|---|
| learning_machine.py | 演示基于 LearningMachine 的学习能力(以 agentic 模式维护用户画像) |
| memory_manager.py | 使用 MemoryManager 为 Agent 提供跨会话的持久记忆 |
两个示例的共同思路是:在两次独立的交互之间,Agent 能把第一次交互中获得的信息(姓名、偏好)沉淀下来,并在第二次交互中被主动调用。区别在于沉淀的载体与机制:MemoryManager 走"记忆捕获 + 记忆检索"路线,LearningMachine 则走"结构化学习类型(用户画像、实体记忆、决策日志等)"路线。
二、前置条件与环境准备
README 给出的运行前置条件(原文完整继承):
- 使用
direnv allow加载环境变量(其中必须包含OPENAI_API_KEY); - 通过
./scripts/demo_setup.sh创建演示环境(对应仓库根目录的 scripts/demo_setup.sh),随后使用.venvs/demo/bin/python运行 cookbook; - 部分示例依赖可选的本地服务(例如 pgvector)或特定服务商的 API Key。
运行命令统一为:
.venvs/demo/bin/python cookbook/02_agents/06_memory_and_learning/<file>.py
两个示例都使用 OpenAIResponses 模型,因此 OPENAI_API_KEY 是硬性依赖;而记忆/学习数据的落盘在本示例中使用 SQLite,不需要额外数据库服务。
三、示例一:MemoryManager 跨会话持久记忆
3.1 完整示例代码
cookbook/02_agents/06_memory_and_learning/memory_manager.py 的完整内容如下:
"""
Memory Manager
=============================
Use a MemoryManager to give agents persistent memory across sessions.
"""
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.memory.manager import MemoryManager
from agno.models.openai import OpenAIResponses
# ---------------------------------------------------------------------------
# Create Agent
# ---------------------------------------------------------------------------
db = SqliteDb(db_file="tmp/memory_demo.db")
agent = Agent(
model=OpenAIResponses(id="gpt-5.2"),
db=db,
# Enable agentic memory so the agent can store and retrieve memories
enable_agentic_memory=True,
# Provide a MemoryManager for structured memory operations
memory_manager=MemoryManager(
db=db,
model=OpenAIResponses(id="gpt-5-mini"),
),
markdown=True,
)
# ---------------------------------------------------------------------------
# Run Agent
# ---------------------------------------------------------------------------
if __name__ == "__main__":
# First interaction: tell the agent something to remember
agent.print_response(
"My name is Alice and I prefer Python over JavaScript.",
stream=True,
)
print("\n--- Second interaction ---\n")
# Second interaction: the agent should recall the preference
agent.print_response(
"What programming language do I prefer?",
stream=True,
)
示例的验证逻辑非常直接:第一次交互向 Agent 陈述"My name is Alice and I prefer Python over JavaScript.",第二次交互提问"What programming language do I prefer?"。如果 Agent 能回答出 Python,说明记忆已成功持久化并在会话间被召回。
3.2 关键参数解读
db = SqliteDb(db_file="tmp/memory_demo.db"):记忆与运行状态的落盘位置。同一个db实例同时传给Agent和MemoryManager,保证记忆读取/写入与 Agent 会话数据使用同一个存储后端。SqliteDb来自agno.db.sqlite,是本地零依赖的默认选择;生产环境可替换为其他实现(仓库 libs/agno/agno/db 下还有 PostgreSQL、Mongo、Redis 等后端)。enable_agentic_memory=True:开启 agentic memory,使 Agent 自身具备存储与检索记忆的工具能力(源码注释即"Enable agentic memory so the agent can store and retrieve memories")。memory_manager=MemoryManager(db=db, model=OpenAIResponses(id="gpt-5-mini")):提供结构化的记忆管理操作。注意这里使用了一个更小、更廉价的模型(gpt-5-mini)来执行记忆管理,而不是与主 Agent 相同的gpt-5.2——记忆捕获本质上是辅助任务,用轻量模型控制成本是合理的工程做法。- 两次
print_response调用未显式传user_id:默认用户下两次交互共享同一记忆命名空间,因此偏好可以跨"会话"召回。
3.3 源码级实现:MemoryManager 到底做了什么
MemoryManager 定义在 libs/agno/agno/memory/manager.py。从源码结构看,它是一个 dataclass,核心字段包括:
model:执行记忆管理(记忆捕获、去重、更新)所用的模型。若未提供,get_model()会回退到OpenAIChat(id="gpt-4o")(见 manager.py#L112-L123),并在缺少openai包时打印明确的安装提示后退出。system_message/memory_capture_instructions/additional_instructions:分别用于覆盖默认的 Manager 系统消息、默认的记忆捕获指令,以及追加附加指令。这三个参数是让记忆行为"可定制"的入口,默认值即可满足示例场景。- 四个数据库工具开关:
delete_memories、clear_memories、update_memories、add_memories,决定 Manager 向 Agent 暴露哪些记忆操作工具。注意__init__签名中的默认值为delete_memories=False、clear_memories=False、update_memories=True、add_memories=True(见 manager.py#L77-L93),即默认只开放"增、改",不开放"删、清",这与示例中不做删除操作的行为一致。 db:类型标注为Optional[Union[BaseDb, AsyncBaseDb]](见 manager.py#L73),即同步/异步数据库基类均可。示例中读取记忆走read_from_db():当未指定user_id时调用db.get_user_memories()读取全部记忆,并按user_id分组成字典(见 manager.py#L125-L139)。这解释了为什么示例中同一个user_id空间内的两次交互能互相"记住"对方。debug_mode:置为True可打开 Manager 内部的调试日志,排查"为什么这条记忆没有被捕获"时很有用。
另外,Manager 内部定义了一个 MemorySearchResponse 模型(字段为 memory_ids),用于按语义相似度返回与查询最匹配的记忆 ID(见 manager.py#L36-L42),说明记忆召回支持基于相似度的检索路径。
四、示例二:LearningMachine 的 Agentic 学习
4.1 完整示例代码
cookbook/02_agents/06_memory_and_learning/learning_machine.py 的完整内容如下:
"""
Learning Machine
=============================
Learning Machine.
"""
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.learn import LearningMachine, LearningMode, UserProfileConfig
from agno.models.openai import OpenAIResponses
# ---------------------------------------------------------------------------
# Setup
# ---------------------------------------------------------------------------
agent_db = SqliteDb(db_file="tmp/agents.db")
# ---------------------------------------------------------------------------
# Create Agent
# ---------------------------------------------------------------------------
agent = Agent(
name="Learning Agent",
model=OpenAIResponses(id="gpt-5.2"),
db=agent_db,
learning=LearningMachine(
user_profile=UserProfileConfig(mode=LearningMode.AGENTIC),
),
markdown=True,
)
# ---------------------------------------------------------------------------
# Run Agent
# ---------------------------------------------------------------------------
if __name__ == "__main__":
user_id = "learning-demo-user"
agent.print_response(
"My name is Alex, and I prefer concise responses.",
user_id=user_id,
session_id="learning_session_1",
stream=True,
)
agent.print_response(
"What do you remember about me?",
user_id=user_id,
session_id="learning_session_2",
stream=True,
)
与 MemoryManager 示例相比,这个示例刻意强调了跨会话(cross-session):两次 print_response 使用同一个 user_id(learning-demo-user)但不同的 session_id(learning_session_1 / learning_session_2)。第一次会话陈述姓名与偏好("My name is Alex, and I prefer concise responses."),第二次会话直接提问"What do you remember about me?"——如果学习成果按用户(而非会话)维度持久化,第二次会话应当能复述出这两条信息。
4.2 关键参数解读
learning=LearningMachine(...):Agent通过learning参数挂载学习系统。LearningMachine是学习模块的统一入口,模块文档字符串(libs/agno/agno/learn/init.py)将其描述为"Unified learning system",与 Config(学习类型配置)、Schemas(学习类型数据结构)、Stores(存储后端)四大组件共同构成agno.learn包。UserProfileConfig(mode=LearningMode.AGENTIC):只启用"用户画像"这一种学习类型,并指定其模式为AGENTIC。LearningMode是定义在 libs/agno/agno/learn/config.py 中的枚举,UserProfileConfig在 config.py#L57。从命名与枚举设计可以推断,AGENTIC 模式意味着由模型自主决定何时提取/更新画像字段,而不是按固定规则硬编码捕获。agent_db = SqliteDb(db_file="tmp/agents.db"):学习数据同样依赖db落盘,且文件与 MemoryManager 示例(tmp/memory_demo.db)相互独立,避免两个演示互相污染。
4.3 源码级实现:learn 模块的结构
libs/agno/agno/learn 包的 __init__.py 导出了完整的组件面(见 learn/init.py#L41-L67):
- 主类:
LearningMachine(实现位于 learn/machine.py#L82); - 六种学习类型的 Config:
UserProfileConfig(用户画像)、UserMemoryConfig(用户记忆)、EntityMemoryConfig(实体记忆)、SessionContextConfig(会话上下文)、LearnedKnowledgeConfig(习得知识)、DecisionLogConfig(决策日志); - 对应的 Schemas:
UserProfile、Memories、EntityMemory、SessionContext、LearnedKnowledge、DecisionLog; - 对应的 Stores:
UserProfileStore、UserMemoryStore、EntityMemoryStore、SessionContextStore、LearnedKnowledgeStore、DecisionLogStore,以及通用基类LearningStore。
也就是说,示例中只开了 UserProfileConfig 一项,但同一套机制还可以按需叠加实体记忆、决策日志等其它学习类型——每种类型都有独立的 Config / Schema / Store 三元组,彼此正交。此外 learn 包还包含 curate.py(学习成果的整理/精炼)与 migrations.py(存储迁移)等支撑模块,说明学习数据在持久化层面有版本演进能力。
五、两种机制的对比与选型
| 维度 | MemoryManager(memory_manager.py) | LearningMachine(learning_machine.py) |
|---|---|---|
| 启用方式 | Agent(enable_agentic_memory=True, memory_manager=MemoryManager(...)) |
Agent(learning=LearningMachine(user_profile=UserProfileConfig(...))) |
| 记忆载体 | 非结构化记忆条目,存于 db.get_user_memories() 可读取的用户记忆表 |
结构化学习类型(用户画像等),按类型分 Store |
| 辅助模型 | 示例中显式指定 gpt-5-mini 降低记忆管理成本 |
由学习模式(如 AGENTIC)驱动,未单独指定 |
| 用户隔离 | 示例未显式传 user_id,使用默认用户 |
显式传 user_id 并跨两个 session_id 验证 |
| 典型问题 | "我偏好什么语言?"(单点事实召回) | "你记得我什么?"(画像式复述) |
选型建议:如果只需要"记住用户说过的事实并能在后续会话中召回",MemoryManager 方案更直接;如果需要把用户信息沉淀为可管理、可演进的画像/实体/决策日志等结构化资产(配合 libs/agno/agno/learn 中六种学习类型),则应使用 LearningMachine。两者都要求为 Agent 与记忆/学习组件注入同一个 db 实例,这是示例中最容易被忽略的"隐性契约"。
六、测试记录与复现
cookbook/02_agents/06_memory_and_learning/TEST_LOG.md 记录了 2026-02-13 的验证结果:
- learning_machine.py:PASS,5 秒内完成,"Ran successfully and produced expected output";
- memory_manager.py:PASS,9 秒内完成,同样成功产出预期输出;
- 测试环境为
.venvs/demo/bin/python,pgvector 服务处于运行状态。
复现步骤(与 README 一致):
# 1. 允许 direnv 加载 .env(需包含 OPENAI_API_KEY)
direnv allow
# 2. 创建 demo 虚拟环境
./scripts/demo_setup.sh
# 3. 分别运行两个示例
.venvs/demo/bin/python cookbook/02_agents/06_memory_and_learning/memory_manager.py
.venvs/demo/bin/python cookbook/02_agents/06_memory_and_learning/learning_machine.py
运行后可检查 tmp/memory_demo.db 与 tmp/agents.db 两个 SQLite 文件,确认记忆/学习数据确实被持久化。
七、小结
06_memory_and_learning 目录虽然只有两个示例脚本,但完整覆盖了 Agno Agent 的两条记忆/学习技术路线:
- MemoryManager 路线:
enable_agentic_memory+MemoryManager(db=..., model=...),通过 libs/agno/agno/memory/manager.py 中的可定制系统消息、记忆捕获指令与增/改/删/清四个工具开关,实现跨会话的事实记忆; - LearningMachine 路线:
learning=LearningMachine(user_profile=UserProfileConfig(mode=LearningMode.AGENTIC)),依托 libs/agno/agno/learn 中"Config—Schema—Store"三件套,把用户画像等学习成果结构化地按用户维度持久化,并用不同session_id验证跨会话生效。
两条路线都以显式注入共享 db 为前提,都可用仓库自带的 scripts/demo_setup.sh 环境直接复现,适合作为在生产 Agent 中引入长期记忆前的最小可行验证方案。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00