Working Memory
消息历史和 Semantic Recall 可帮助 Agent 记住对话,而 Working Memory 则让它们可以跨多次交互维护有关用户的持久信息。
Working Memory 是 Agent 的活动便笺:它会随时保留与用户或任务有关的关键信息。在对话期间,它可以记住用户的姓名、偏好或其他重要细节。
这适合维护始终相关、应当始终可供 Agent 使用的持续状态。
如果使用 Observational Memory,observationalMemory.observation.manageWorkingMemory 可以让 OM 为 Agent 更新 Working Memory。
观看 Mastra Working Memory,了解 Agent 如何跨多次交互持续保留用户上下文。
Working Memory 可以在两种不同的作用域中持久化:
- Resource 作用域(默认):Memory 会在同一用户的所有对话 Thread 间持久化
- Thread 作用域:每个对话 Thread 的 Memory 相互隔离
**要求:**切换作用域后,Agent 将无法看到另一个作用域中的 Memory——Thread 作用域 Memory 与 Resource 作用域 Memory 完全分离。
快速开始快速开始的直接链接
下面是为 Agent 设置 Working Memory 的最小示例:
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'
// Create agent with working memory enabled
const agent = new Agent({
id: 'personal-assistant',
name: 'PersonalAssistant',
instructions: 'You are a helpful personal assistant.',
model: 'openai/gpt-5.6-sol',
memory: new Memory({
options: {
workingMemory: {
enabled: true,
},
},
}),
})
工作原理工作原理的直接链接
Working Memory 是一段 Markdown 文本,Agent 可以不断更新它,以存储持续相关的信息。
Memory 持久化作用域Memory 持久化作用域的直接链接
Working Memory 可以在两种不同的作用域中运行,你可以选择 Memory 如何跨对话持久化:
Resource 作用域 Memory(默认)Resource 作用域 Memory(默认)的直接链接
默认情况下,Working Memory 会在同一用户(resourceId)的所有对话 Thread 间持久化,从而实现持久化的用户 Memory:
const memory = new Memory({
storage,
options: {
workingMemory: {
enabled: true,
scope: 'resource', // Memory persists across all user threads
template: `# User Profile
- **Name**:
- **Location**:
- **Interests**:
- **Preferences**:
- **Long-term Goals**:
`,
},
},
})
使用场景:
- 记住用户偏好的个人助手
- 维护客户上下文的客服机器人
- 跟踪学生进度的教育应用
与 Agent 一起使用与 Agent 一起使用的直接链接
使用 Resource 作用域 Memory 时,请确保在 Memory 选项中传入 resource 参数:
// Resource-scoped memory requires resource
const response = await agent.generate('Hello!', {
memory: {
thread: 'conversation-123',
resource: 'user-alice-456', // Same user across different threads
},
})
Thread 作用域 MemoryThread 作用域 Memory的直接链接
Thread 作用域 Memory 会将 Working Memory 隔离到各个对话 Thread。每个 Thread 都维护自己独立的 Memory:
const memory = new Memory({
storage,
options: {
workingMemory: {
enabled: true,
scope: 'thread', // Memory is isolated per thread
template: `# User Profile
- **Name**:
- **Interests**:
- **Current Goal**:
`,
},
},
})
使用场景:
- 围绕不同主题进行的不同对话
- 临时或特定于会话的信息
- 每个 Thread 都需要 Working Memory,但各 Thread 都是临时且彼此无关的 Workflow
Storage Adapter 支持Storage Adapter 支持的直接链接
Resource 作用域 Working Memory 需要支持 mastra_resources 表的特定 Storage Adapter:
支持的 Storage Adapter支持的 Storage Adapter的直接链接
- libSQL(
@mastra/libsql) - PostgreSQL(
@mastra/pg) - OracleDB(
@mastra/oracledb) - Upstash(
@mastra/upstash) - MongoDB(
@mastra/mongodb)
自定义模板自定义模板的直接链接
模板会引导 Agent 决定在 Working Memory 中跟踪和更新哪些信息。未提供模板时,Mastra 会使用默认模板。请针对 Agent 的使用场景定义自定义模板,使其记住最相关的信息。对于多个用户共享的 Thread,请参阅多用户 Thread。
以下是一个自定义模板示例。在该示例中,只要用户发送的消息包含姓名、位置、时区等任一信息,Agent 就会立即存储它:
const memory = new Memory({
options: {
workingMemory: {
enabled: true,
template: `
# User Profile
## Personal info
- Name:
- Location:
- Timezone:
## Preferences
- Communication Style: [e.g., Formal, Casual]
- Project Goal:
- Key Deadlines:
- [Deadline 1]: [Date]
- [Deadline 2]: [Date]
## Session state
- Last Task Discussed:
- Open Questions:
- [Question 1]
- [Question 2]
`,
},
},
})
设计有效的模板设计有效的模板的直接链接
结构良好的模板可以让信息直观易懂,便于 Agent 解析和更新。请将模板视为一个需要助手持续维护的简短表单。
- **使用简短且聚焦的标签。**避免段落或过长的标题。保持标签简短(例如
## Personal Info或- Name:),这样更新内容更易读,也不容易被截断。 - **保持大小写一致。**大小写不一致(
Timezone:与timezone:)会导致更新杂乱。标题和项目符号标签应统一使用 Title Case 或小写。 - **尽量减少占位文本。**使用
[e.g., Formal]或[Date]等提示,帮助 LLM 填写正确位置。 - **缩写非常长的值。**如果只需要简短形式,请加入类似
- Name: [First name or nickname]或- Address (short):的指导,而不是要求完整的法律文本。 - **在
instructions中说明更新规则。**你可以直接在 Agent 的instructions字段中说明如何以及何时填写或清除模板的各个部分。
其他模板样式其他模板样式的直接链接
如果只需要少量条目,可以使用更短的单一区块:
const basicMemory = new Memory({
options: {
workingMemory: {
enabled: true,
template: `User Facts:\n- Name:\n- Favorite Color:\n- Current Topic:`,
},
},
})
如果更喜欢叙述风格,也可以使用简短段落格式存储关键事实:
const paragraphMemory = new Memory({
options: {
workingMemory: {
enabled: true,
template: `Important Details:\n\nKeep a short paragraph capturing the user's important facts (name, main goal, current task).`,
},
},
})
结构化 Working Memory结构化 Working Memory的直接链接
Working Memory 还可以使用结构化 Schema 定义,而不是 Markdown 模板。你可以通过 Standard JSON Schema(Zod、Valibot、ArkType 等)指定需要跟踪的确切字段和类型。使用 Schema 时,Agent 会以与该 Schema 匹配的 JSON 对象查看和更新 Working Memory。
**要求:**必须指定 template 或 schema,但不能同时指定两者。
示例:基于 Schema 的 Working Memory示例:基于 Schema 的 Working Memory的直接链接
import { z } from 'zod'
import { Memory } from '@mastra/memory'
const userProfileSchema = z.object({
name: z.string().optional(),
location: z.string().optional(),
timezone: z.string().optional(),
preferences: z
.object({
communicationStyle: z.string().optional(),
projectGoal: z.string().optional(),
deadlines: z.array(z.string()).optional(),
})
.optional(),
})
const memory = new Memory({
options: {
workingMemory: {
enabled: true,
schema: userProfileSchema,
// template: ... (do not set)
},
},
})
提供 Schema 后,Agent 会以 JSON 对象形式接收 Working Memory。例如:
{
"name": "Sam",
"location": "Berlin",
"timezone": "CET",
"preferences": {
"communicationStyle": "Formal",
"projectGoal": "Launch MVP",
"deadlines": ["2025-07-01"]
}
}
基于 Schema 的 Memory 合并语义基于 Schema 的 Memory 合并语义的直接链接
基于 Schema 的 Working Memory 使用合并语义,也就是说 Agent 只需包含希望添加或更新的字段。现有字段会自动保留。
- **对象字段会深度合并:**只更新提供的字段,其他字段保持不变
- **将字段设为
null即可删除:**这会从 Memory 中显式移除该字段 - **数组会被完全替换:**提供数组字段后,它会替换现有数组(不会逐元素合并数组)
在模板与 Schema 之间选择在模板与 Schema 之间选择的直接链接
- 如果希望 Agent 将 Memory 维护为用户资料或便笺等自由格式的文本块,请使用 模板(Markdown)。模板采用替换语义:Agent 每次更新都必须提供完整的 Memory 内容。
- 如果需要可以验证并以 JSON 形式通过编程方式访问的结构化、类型安全数据,请使用 Schema。
workingMemory.schema字段接受任何与PublicSchema兼容的 Schema(包括 Zod v3、Zod v4、JSON Schema 或已符合标准的 Schema)。Schema 采用合并语义:Agent 只需提供要更新的字段,现有字段会保留。 - 每次只能启用一种模式:不支持同时设置
template和schema。
示例:多步保留示例:多步保留的直接链接
以下简化示例展示 User Profile 模板如何在一段简短的用户对话中更新:
# User Profile
## Personal info
- Name:
- Location:
- Timezone:
--- After user says "My name is **Sam** and I'm from **Berlin**" ---
# User Profile
- Name: Sam
- Location: Berlin
- Timezone:
--- After user adds "By the way I'm normally in **CET**" ---
# User Profile
- Name: Sam
- Location: Berlin
- Timezone: CET
由于这些信息已存入 Working Memory,Agent 在后续响应中可以直接提及 Sam 或 Berlin,无需再次询问。
如果 Agent 没有按预期正确更新 Working Memory,可以在 Agent 的 instructions 设置中添加系统指令,说明应_如何_以及_何时_使用该模板。
设置初始 Working Memory设置初始 Working Memory的直接链接
Agent 通常通过 updateWorkingMemory Tool 更新 Working Memory;此外,你也可以在创建或更新 Thread 时以编程方式设置初始 Working Memory。如果希望 Agent 能使用姓名、偏好或其他用户数据,而无需每次请求都传入这些数据,此功能很有用。
通过 Thread 元数据设置 Working Memory通过 Thread 元数据设置 Working Memory的直接链接
创建 Thread 时,可以通过元数据的 workingMemory 键提供初始 Working Memory:
// Create a thread with initial working memory
const thread = await memory.createThread({
threadId: 'thread-123',
resourceId: 'user-456',
title: 'Medical Consultation',
metadata: {
workingMemory: `# Patient Profile
- Name: John Doe
- Blood Type: O+
- Allergies: Penicillin
- Current Medications: None
- Medical History: Hypertension (controlled)
`,
},
})
// The agent will now have access to this information in all messages
await agent.generate("What's my blood type?", {
memory: {
thread: thread.id,
resource: 'user-456',
},
})
// Response: "Your blood type is O+."
以编程方式更新 Working Memory以编程方式更新 Working Memory的直接链接
你也可以更新现有 Thread 的 Working Memory:
// Update thread metadata to add/modify working memory
await memory.updateThread({
id: 'thread-123',
title: thread.title,
metadata: {
...thread.metadata,
workingMemory: `# Patient Profile
- Name: John Doe
- Blood Type: O+
- Allergies: Penicillin, Ibuprofen // Updated
- Current Medications: Lisinopril 10mg daily // Added
- Medical History: Hypertension (controlled)
`,
},
})
直接更新 Memory直接更新 Memory的直接链接
也可以直接使用 updateWorkingMemory 方法:
await memory.updateWorkingMemory({
threadId: 'thread-123',
resourceId: 'user-456', // Required for resource-scoped memory
workingMemory: 'Updated memory content...',
})
只读 Working Memory只读 Working Memory的直接链接
在某些场景中,你可能希望 Agent 能访问 Working Memory 数据,但不能修改它。这适用于:
- 需要上下文但不应更新用户资料的路由 Agent
- 多 Agent 系统中应当引用而非拥有 Memory 的子 Agent
要启用只读模式,请在 Memory 选项中设置 readOnly: true:
const response = await agent.generate('What do you know about me?', {
memory: {
thread: 'conversation-123',
resource: 'user-alice-456',
options: {
readOnly: true, // Working memory is provided but cannot be updated
},
},
})
选择启用状态信号(实验性)选择启用状态信号(实验性)的直接链接
默认情况下,Working Memory 会作为系统消息的一部分传给模型。设置 useStateSignals: true 后,可以改为通过状态信号传递:
const memory = new Memory({
storage: new LibSQLStore({ id: 'mastra-storage', url: 'file:./mastra.db' }),
options: {
workingMemory: {
enabled: true,
template: '# User\n- name:\n- location:',
useStateSignals: true, // experimental: deliver as state signal
},
},
})
变化如下:
- **Storage 完全相同。**读取和写入的仍是相同的 Resource/Thread
workingMemory字段。 - **Tool 结构相同,但以新名称公开。**写入仍通过同一个底层 Tool;在此路径中,它注册为
setWorkingMemory(而非updateWorkingMemory)。重命名可以防止旧版剥离筛选器移除 Tool 调用部分,使其作为正常审计记录持久化,并让模型下一步自动获取新值。 - 只改变传递方式。
Memory不再将其合并到系统提示词,而会自动附加一个WorkingMemoryStateProcessor,将当前 Working Memory 作为stateId: 'working-memory'的state信号发出。
你会继承标准状态信号的优势:Thread 作用域跟踪元数据;通过 cacheKey 去重,使相同快照只发出一次;以及在旧快照移出窗口后通过 contextWindow.hasSnapshot 重新注入。
默认值(useStateSignals: false)会保持现有系统消息行为不变。模板 Working Memory 的 version: 'vnext' 不支持 useStateSignals。
示例示例的直接链接
- 使用模板的 Working Memory
- 使用 Schema 的 Working Memory
- 每个 Resource 独立的 Working Memory:展示 Resource 作用域 Memory 持久化的完整示例