跳到主要内容

Memory

Memory 让 Agent 能够记住用户消息、Agent 回复以及多次交互中的 Tool 结果,从而获得保持一致性、维持对话连贯性以及逐步生成更好回答所需的上下文。

Mastra Agent 可以配置为存储消息历史。此外,你还可以启用:

  • Observational Memory(推荐):使用后台 Agent 维护一份密集的观察日志,随着原始消息历史不断增长,该日志会取代原始历史。这样既能缩小上下文窗口,又能保留长期 Memory。
  • Working Memory:存储姓名、偏好和目标等持久化的结构化用户数据。
  • Semantic Recall:根据语义而非完全匹配的关键词检索相关历史消息。
  • 多用户 Thread:让多个用户共享同一个 Thread。

如果合并后的 Memory 超出模型上下文限制,Memory Processor 可以筛选、裁剪内容或调整其优先级,从而保留最相关的信息。

Memory 结果会存储在你配置的一个或多个 Storage Provider 中。

📹 观看视频

观看 Mastra Memory 概念,从概念层面了解 Agent 可以使用的各个 Memory 层。

何时使用 Memory
何时使用 Memory的直接链接

当 Agent 需要维持多轮对话、引用先前交流内容、回忆用户在当前会话早些时候提供的偏好或事实,或者需要在某个对话 Thread 中逐步积累上下文时,请使用 Memory。对于每次交互都相互独立的单轮请求,则无需使用 Memory。

快速开始
快速开始的直接链接

  1. 安装 @mastra/memory 包。

    npm install @mastra/memory@latest
  2. Memory 需要 Storage Provider 来持久化消息历史,包括用户消息和 Agent 响应。

    本快速入门使用 @mastra/libsql

    npm install @mastra/libsql@latest

    如需详细了解可用的 Provider 以及 Storage 在 Mastra 中的工作方式,请参阅 Storage 文档。

  3. 将 Storage Provider 添加到 Mastra 主实例,为所有已配置的 Agent 启用 Memory。

    src/mastra/index.ts
    import { Mastra } from '@mastra/core'
    import { LibSQLStore } from '@mastra/libsql'

    export const mastra = new Mastra({
    storage: new LibSQLStore({
    id: 'mastra-storage',
    url: ':memory:',
    }),
    })
  4. 创建 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 类

  5. 调用你的 Agent,例如在 Studio 中调用。在 Studio 里与 Agent 开始新对话,并查看右侧边栏。现在其中会显示各类 Memory 相关信息。

消息历史
消息历史的直接链接

传入包含 resourcethreadmemory 对象来跟踪消息历史。

  • resource:用户或实体的稳定标识符。
  • thread:用于隔离特定对话或会话的 ID。
const response = await memoryAgent.generate('Remember my favorite color is blue.', {
memory: {
resource: 'user-123',
thread: 'conversation-123',
},
})

要回忆 Memory 中存储的信息,请使用原始对话所用的相同 resourcethread 值调用 Agent。

const response = await memoryAgent.generate("What's my favorite color?", {
memory: {
resource: 'user-123',
thread: 'conversation-123',
},
})

// Response: "Your favorite color is blue."
注意

每个 Thread 都有一个所有者(resourceId),创建后无法更改。请避免为不同所有者的 Thread 重复使用同一个 Thread ID,否则查询时会出错。

要列出某个 Resource 的所有 Thread 或检索特定 Thread,请直接使用 Memory API

Observational Memory
Observational Memory的直接链接

在长时间运行的对话中,原始消息历史会持续增长,直至填满上下文窗口,从而降低 Agent 性能。Observational 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: {
observationalMemory: true,
},
}),
})

有关观察和反思的工作方式,请参阅 Observational Memory;有关全部配置选项,请参阅参考文档

模型会看到什么
模型会看到什么的直接链接

每项 Memory 功能都会被添加到发送给模型的请求中的系统消息或对话消息。具体包含哪些层取决于你启用了哪些功能。Working Memory 和 Semantic Recall 仅在配置后才会出现;Observational Memory 同样如此,而消息历史则默认启用。下图展示每个已启用层在请求中的位置。其后的列表说明各层提供的内容:

Diagram showing how Mastra assembles the model context: system messages containing agent instructions, call-time system messages, working memory, cross-thread semantic recall, and Observational Memory, followed by conversation messages where message history and same-thread semantic recall interleave by timestamp, then call-time context messages, and finally the new user message
  • Working Memory 会作为一条包含模板和已存储数据的系统消息注入。启用 useStateSignals 后,它会改为通过状态信号传递。
  • Semantic Recall 从当前 Thread 找到的匹配项会作为普通消息插入,并按时间戳与消息历史交错排列。来自其他 Thread 的匹配项则会被格式化到系统消息中。
  • 消息历史按时间顺序添加最近 N 条消息。你的新消息始终排在最后。
  • Observational Memory 会替换旧的原始历史:反思和观察结果位于系统消息中,只有尚未观察的消息会保留在对话中。对话消息的开头还会放置一条简短的续接提醒。
  • 上下文消息是调用时传入的可选 context 数组,例如 agent.generate(msg, { context: [...] })。可用它提供一次性的背景信息,例如应用状态或你自己的 RAG 结果。它们只会作为普通对话消息出现在该次请求中,绝不会保存到 Memory。

对话消息按时间戳排序,并根据消息 ID 去重,因此召回的旧消息会出现在近期历史之前。调用时传入的上下文消息会使用当前时间作为时间戳,因此位于历史和召回内容之后、你的新消息之前。要检查真实请求的确切上下文,请使用 Tracing 并打开 LLM 调用 span,详见下方的可观测性

多 Agent 系统中的 Memory
多 Agent 系统中的 Memory的直接链接

Supervisor Agent 将任务委派给子 Agent 时,Mastra 会自动隔离子 Agent 的 Memory。这一行为会在每次委派时发生,无需通过任何标志启用。了解其作用域规则后,你就能判断哪些内容保持私有,以及哪些内容需要有意共享。

委派如何限定 Memory 作用域
委派如何限定 Memory 作用域的直接链接

每次委派都会为子 Agent 创建一个全新的 threadId 和一个确定性的 resourceId

  • Thread ID:每次委派都唯一。每次调用子 Agent 时,它都会从空白的消息历史开始。
  • Resource ID:派生格式为 {parentResourceId}-{agentName}。由于 Resource ID 在多次委派之间保持稳定,Resource 作用域的 Memory 会跨调用持久存在。同一用户先前委派时提供的事实,子 Agent 仍能记住。
  • Memory 实例:没有自有 Memory 的子 Agent 会继承 Supervisor 的 Memory 实例及所有配置选项。如果子 Agent 定义了自己的 Memory,则优先使用它。
备注

标题生成(generateTitle)属于顶层 Thread,不会应用于继承的子 Agent Thread。每次委派都会创建一个用户不可见的临时 Thread,如果为它运行标题生成,每次委派都会浪费一次 LLM 调用。要为子 Agent 自己的 Thread 生成标题,请为该子 Agent 提供独立的 Memory 配置。

Supervisor 会将自身的对话上下文转发给子 Agent,使其拥有完成任务所需的背景。只会保存委派提示词和子 Agent 的响应,不会存储完整的父级对话。你可以使用 messageFilter 回调控制哪些消息会传给子 Agent。

备注

子 Agent 的 Resource ID 始终带有 Agent 名称后缀({parentResourceId}-{agentName})。同一 Supervisor 下的不同子 Agent 绝不会通过委派共享 Resource ID。

如果需要突破这种默认隔离,可以在直接调用多个 Agent 时传入匹配的标识符,让它们共享 Memory。

在 Agent 之间共享 Memory
在 Agent 之间共享 Memory的直接链接

直接调用 Agent(不经过委派流程)时,Memory 共享由两个标识符控制:resourceIdthreadId。使用相同值的 Agent 会读写同一份数据。这适合多个 Agent 围绕共享上下文协作的场景,例如研究者保存笔记,再由写作者读取笔记。

Resource 作用域共享是最常见的模式。Working MemorySemantic Recall 默认使用 scope: 'resource'。如果两个 Agent 共享一个 resourceId,即使它们处于不同 Thread,也会共享观察结果、Working Memory 和嵌入:

// Both agents share the same resource-scoped memory
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',写作者可以访问研究者的观察结果和 Working Memory。语义嵌入也会通过该 Resource 共享。每个 Agent 仍有自己的 Thread,因此消息历史彼此独立。

Thread 作用域共享提供更紧密的耦合。Observational Memory 默认使用 scope: 'thread'。如果两个 Agent 使用相同的 resourcethread,它们会共享完整的消息历史。每个 Agent 都能看到另一个 Agent 写入的所有消息。这适合需要基于彼此确切输出继续工作的 Agent。

可观测性
可观测性的直接链接

启用 Tracing 可以监控和调试 Memory 的实际运行。Trace 会准确显示 Agent 在每次请求的上下文中包含了哪些消息和观察结果,帮助你理解 Agent 的行为,并确认 Memory 检索是否按预期工作。

打开 Studio,在侧边栏中选择 Observability 选项卡。打开近期 Agent 请求的 Trace,然后查看其中的 LLM 调用 span。

按请求切换 Memory
按请求切换 Memory的直接链接

使用 RequestContext 访问特定于请求的值。这样可以根据请求上下文有条件地选择不同的 Memory 或 Storage 配置。

src/mastra/agents/memory-agent.ts
export 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
},
})

更多信息请参阅 Request Context