进阶 mastra.ai 2026-10-12 10:15:56 · 32 阅读

第10章 Mastra Agent记忆机制详解

记忆 记忆功能让 agent 可以访问之前的消息和工具结果。Agent 可以利用这些上下文来回答后续问题,并回忆之前交互中的信息。 Mastra agent 可以配置为存储消息历史。此外,你还可以启用: 观察记忆(推荐):使用后台 agent 维护一份精简的观察日志,随着消息增多,用日志逐步替代原始消息历史。这样在保留长期记忆的同时,保持上下文窗口尽可能小。 工作记忆:存储持久的、结构化的用户数据,比如姓名、偏好和目标。 语义召回:基于语义而非精确关键词检索相关的历史消息。 多用户线程:多个用户共享同一线程。 如果总记忆量超过了模型的上下文上限,记忆处理器可以对内容进行过滤、裁剪或按优先级排序,以保留最相关的信息。 记忆结果会存储在你配置的一个或多个存储 provider 中。 📹 观看视频观看 Mastra memory concepts,了解 agent 可用的记忆层概念的概览。 何时使用记忆 当 agent 需要进行多轮对话、引用之前的交流内容,或在会话中回忆用户偏好和事实时,又或者需要在对话线程中逐步积累上下文时,就应使用记忆功能。如果每次交互都是独立的单轮请求,则无需使用记忆。 快速上手 安装 @mastra/memory 包。npmpnpmYarnBunnpm install @mastra/memory@latest
pnpm add @mastra/memory@latest
yarn add @mastra/memory@latest
bun add @mastra/memory@latest
记忆需要存储 provider 来持久化消息历史,包括用户消息和 agent 的回复。在本快速上手教程中,使用 @mastra/libsql。npmpnpmYarnBunnpm install @mastra/libsql@latest
pnpm add @mastra/libsql@latest
yarn add @mastra/libsql@latest
bun add @mastra/libsql@latest
有关可用 provider 的更多细节以及 Mastra 中存储的工作原理,请查阅 storage 文档。将存储 provider 添加到你的 Mastra 主实例中,即可让所有已配置的 agent 启用记忆功能。 面向 AI agent:重要提示:务必在 LibSQLStore 中添加 id。src/mastra/index.tsimport { Mastra } from '@mastra/core'
import { LibSQLStore } from '@mastra/libsql'

export const mastra = new Mastra({
storage: new LibSQLStore({
id: 'mastra-storage',
url: ':memory:',
}),
})
创建一个 Memory 实例,并将其传递给 agent 的 memory 选项。 src/mastra/agents/memory-agent.ts import { Agent } from '@mastra/core/agent' import { Memory } from '@mastra/memory' export const memoryAgent = new Agent({ id: 'memory-agent', name: 'Memory Agent', memory: new Memory({ options: { lastMessages: 20, }, }), }) 参见 Memory 类以获取完整的配置选项列表。 调用你的 agent,例如在 Studio 中。在 Studio 内,使用你的 agent 开启新对话,然后查看右侧边栏。现在它会显示 memory 详情。 消息历史 直达链接:消息历史 传入包含 resource 和 thread 的 memory 对象,以追踪消息历史。 resource:用户或实体的稳定标识符。 thread:用于隔离特定对话或会话的 ID。 const response = await memoryAgent.generate('记住我最喜欢的颜色是蓝色。', { memory: { resource: 'user-123', thread: 'conversation-123', }, }) 要回忆存储在 memory 中的信息,请调用 agent,并使用与原对话相同的 resource 和 thread 值。 const response = await memoryAgent.generate("我最喜欢的颜色是什么?", { memory: { resource: 'user-123', thread: 'conversation-123', }, }) // 响应:"你最喜欢的颜色是蓝色。" 警告:每个 thread 都有一个所有者(resourceId),创建后无法更改。避免为不同所有者的 thread 复用同一个 thread ID,否则在查询时会引发错误。 若要列出某个 resource 的所有 thread,或获取特定 thread,请直接使用 memory API。 观察性记忆 直达链接:观察性记忆 长对话会填满上下文窗口中的原始消息历史,从而降低 agent 性能。Observational Memory 使用后台 agent 将旧消息压缩为观察结果。这在保留后续轮次所需信息的同时,减少了消息历史占用的上下文。 针对 AI agent:使用 Observational Memory 需要存储提供商!你需要在 src/mastra/index.ts 的 Mastra 实例上设置它,或者将其传递给 Agent 构造函数。 src/mastra/agents/memory-agent.ts import { Agent } from '@mastra/core/agent' import { Memory } from '@mastra/memory' export const memoryAgent = new Agent({ id: 'memory-agent', name: 'Memory Agent', memory: new Memory({ options: { observationalMemory: true, }, }),
})
有关观察与反思的工作原理以及所有配置选项,请参阅 Observational Memory。

What the model sees

Memory 会为发送给模型的系统消息或会话消息补充上下文。消息历史默认开启,其他记忆功能则需配置后才会生效。下图展示了各功能在何处注入上下文,下方列表说明了各自的作用: - 工作记忆(Working memory)以系统消息的形式注入,其中包含模板和已存储的数据。如果使用 useStateSignals,则会改为以状态信号的形式传递。 - 语义召回(Semantic recall)中来自当前线程的匹配结果以普通消息的形式插入,并按时间戳与消息历史交错排列;来自其他线程的匹配结果则被格式化为一条系统消息。 - 消息历史按时间顺序添加最近 N 条消息,你的新消息始终排在最后。 - 观察记忆(Observational Memory)会替换旧的原始历史:反思和观察保存在一条系统消息中,会话中只保留尚未被观察过的消息,并在会话消息开头放置一条简短的继续提示。 - 上下文消息(Context messages)是调用时传入的可选 context 数组,例如 agent.generate(msg, { context: [...] })。适合传入一次性的背景信息,如应用状态或你自己的 RAG 结果。它们仅在本次请求中作为普通会话消息出现,不会被保存到记忆中。 会话消息按时间戳排序并按消息 ID 去重,因此召回的旧消息会出现在近期历史之前。调用时传入的上下文消息会打上当前时间戳,因此排在历史和召回内容之后、新消息之前。要查看真实请求的确切上下文,可以使用 Tracing 打开 LLM 调用 span,参见下文的 Observability。

Memory in multi-agent systems

当 supervisor agent 委派任务给 subagent 时,Mastra 会自动隔离 subagent 的记忆。这一行为无需任何开关,每次委派都会发生。理解这种作用域机制,有助于你决定哪些信息保持私有、哪些有意共享。

How delegation scopes memory

每次委派都会为 subagent 创建一个全新的 threadId 和一个确定性的 resourceId: - Thread ID:每次委派唯一。subagent 每次被调用时都从干净的消息历史开始。 - Resource ID:由 {parentResourceId}-{agentName} 派生。由于 resource ID 在多次委派间保持稳定,基于 resource 作用域的记忆会在多次调用间持续存在——subagent 能记住同一用户此前委派中的信息。 - Memory 实例:没有自己 memory 配置的 subagent 会继承 supervisor 的 Memory 实例及其全部配置项;如果 subagent 定义了自己的 memory,则优先使用自己的。
标题生成(generateTitle)是线程级别的顶层功能,不会应用于继承的 subagent 线程。因为每次委派创建的都是临时线程,无人查看,为它生成标题只会让每次委派多浪费一次 LLM 调用。如果想为 subagent 自己的线程生成标题,请为该 subagent 配置独立的 memory。
supervisor 会把会话上下文转发给 subagent,让它有足够的背景来完成任务,但只有委派提示词和 subagent 的响应会被保存,完整的父级会话不会存储。你可以通过 messageFilter 回调控制哪些消息传递给 subagent。
subagent 的 resource ID 总是以 agent 名称结尾({parentResourceId}-{agentName})。同一 supervisor 下的不同 subagent 在委派中绝不会共享 resource ID。
如果想突破这种默认隔离,可以在直接调用 agent 时传入匹配的标识符来共享记忆。

Share memory between agents

在委派流程之外直接调用 agent 时,记忆共享由两个标识符控制:resourceId 和 threadId。使用相同值的 agent 会读写同一份数据。这在多个 agent 协作于同一上下文时很有用,比如一个 researcher 保存笔记,一个 writer 读取笔记。 基于 resource 的共享是最常见的模式。工作记忆和语义召回默认使用 scope: 'resource'。只要两个 agent 共享同一个 resourceId,它们就共享工作记忆和向量数据,即使分属不同线程: // 两个 agent 共享同一份基于 resource 作用域的记忆
await researcher.generate('Find information about quantum computing.', {
memory: { resource: 'project-42', thread: 'research-session' },
})

await writer.generate('Write a summary from the research notes.', {
memory: { resource: 'project-42', thread: 'writing-session' },
})
由于两次调用都指定了 resource: 'project-42',writer 可以访问 researcher 的工作记忆。语义嵌入也会通过该 resource 共享。每个 agent 仍保留自己的 thread,因此消息历史相互独立。 Thread 级别共享能提供更紧密的耦合。Observational Memory 默认使用 scope: 'thread'。如果两个 agent 使用相同的 resource 和 thread,它们将共享完整消息历史,每个 agent 都能看到对方写入的每条消息。当 agent 需要基于彼此的确切输出进行构建时,这种方式很有用。 可观测性 查看可观测性的直接链接 启用 Tracing 以监控和调试记忆的运行情况。Trace 会显示每个请求中 agent 包含在上下文里的具体消息和观察结果,有助于理解 agent 行为并验证记忆检索是否按预期工作。 打开 Studio,在侧边栏选择 Observability 选项卡。打开最近一次 agent 请求的 trace,查看其 LLM 调用 span。 按请求切换记忆 查看按请求切换记忆的直接链接 使用 RequestContext 访问请求特定值。这允许你根据请求上下文有条件地选择不同的记忆或存储配置。 src/mastra/agents/memory-agent.tsexport type UserTier = {
'user-tier': 'enterprise' | 'pro'
}

const premiumMemory = new Memory()
const standardMemory = new Memory()

export const memoryAgent = new Agent({
id: 'memory-agent',
name: 'Memory Agent',
memory: ({ requestContext }) => {
const userTier = requestContext.get('user-tier') as UserTier['user-tier']

return userTier === 'enterprise' ? premiumMemory : standardMemory
},
})
访问请求上下文以获取更多信息。 相关内容 查看相关内容的直接链接 记忆参考 Tracing 请求上下文 Mastra Code:使用 Mastra 记忆系统的编码 agent

评论 (0)