@mastra/memory 1.24.0 → 1.25.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/docs/SKILL.md +6 -6
  3. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  4. package/dist/docs/references/docs-agents-agent-approval.md +85 -11
  5. package/dist/docs/references/docs-agents-networks.md +2 -2
  6. package/dist/docs/references/docs-agents-supervisor-agents.md +19 -13
  7. package/dist/docs/references/docs-evals-evals-with-memory.md +4 -4
  8. package/dist/docs/references/docs-long-running-agents-background-tasks.md +10 -10
  9. package/dist/docs/references/docs-long-running-agents-goals.md +15 -11
  10. package/dist/docs/references/docs-memory-memory-processors.md +10 -10
  11. package/dist/docs/references/docs-memory-message-history.md +11 -5
  12. package/dist/docs/references/docs-memory-multi-user-threads.md +6 -6
  13. package/dist/docs/references/docs-memory-observational-memory.md +57 -38
  14. package/dist/docs/references/docs-memory-overview.md +24 -10
  15. package/dist/docs/references/docs-memory-semantic-recall.md +3 -3
  16. package/dist/docs/references/docs-memory-working-memory.md +8 -8
  17. package/dist/docs/references/docs-storage-overview.md +2 -2
  18. package/dist/docs/references/reference-memory-clone-utilities.md +1 -1
  19. package/dist/docs/references/reference-memory-cloneThread.md +3 -3
  20. package/dist/docs/references/reference-memory-listThreads.md +1 -1
  21. package/dist/docs/references/reference-memory-memory-class.md +4 -4
  22. package/dist/docs/references/reference-memory-observational-memory.md +88 -38
  23. package/dist/docs/references/reference-memory-summarizeConversation.md +3 -3
  24. package/dist/docs/references/reference-memory-summarizeThread.md +3 -3
  25. package/dist/docs/references/reference-processors-token-limiter-processor.md +4 -4
  26. package/dist/docs/references/reference-storage-dsql.md +3 -3
  27. package/dist/docs/references/reference-storage-dynamodb.md +7 -7
  28. package/dist/docs/references/reference-storage-mongodb.md +2 -2
  29. package/dist/docs/references/reference-storage-postgresql.md +2 -2
  30. package/dist/docs/references/reference-storage-redis.md +1 -1
  31. package/dist/docs/references/reference-storage-upstash.md +1 -1
  32. package/dist/docs/references/reference-vectors-libsql.md +2 -2
  33. package/dist/docs/references/reference-vectors-mongodb.md +3 -3
  34. package/dist/docs/references/reference-vectors-pg.md +5 -5
  35. package/dist/docs/references/reference-vectors-upstash.md +1 -1
  36. package/dist/index.cjs +1 -1
  37. package/dist/index.d.ts +1 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +1 -1
  40. package/dist/processors/index.cjs +1 -1
  41. package/dist/processors/index.js +1 -1
  42. package/dist/processors/observational-memory/index.d.ts +1 -1
  43. package/dist/processors/observational-memory/index.d.ts.map +1 -1
  44. package/dist/processors/observational-memory/observation-strategies/types.d.ts +6 -0
  45. package/dist/processors/observational-memory/observation-strategies/types.d.ts.map +1 -1
  46. package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
  47. package/dist/processors/observational-memory/observational-memory.d.ts +30 -1
  48. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  49. package/dist/processors/observational-memory/processor.d.ts.map +1 -1
  50. package/dist/processors/observational-memory/reflector-runner.d.ts.map +1 -1
  51. package/dist/processors/observational-memory/types.d.ts +50 -6
  52. package/dist/processors/observational-memory/types.d.ts.map +1 -1
  53. package/dist/{src-Ci_GvBVm.js → src-BYZh9IBv.js} +171 -27
  54. package/dist/{src-Ci_GvBVm.js.map → src-BYZh9IBv.js.map} +1 -1
  55. package/dist/{src-VD6qMn-H.cjs → src-naeQog_T.cjs} +171 -27
  56. package/dist/{src-VD6qMn-H.cjs.map → src-naeQog_T.cjs.map} +1 -1
  57. package/package.json +7 -7
@@ -2,9 +2,9 @@
2
2
 
3
3
  # Memory processors
4
4
 
5
- Memory processors transform and filter messages as they pass through an agent with memory enabled. They manage context window limits, remove unnecessary content, and optimize the information sent to the language model.
5
+ Memory processors transform and filter messages as they pass through an agent with memory enabled. They manage context window limits and remove unnecessary content, plus optimize the information sent to the language model.
6
6
 
7
- When memory is enabled on an agent, Mastra adds memory processors to the agent's processor pipeline. These processors retrieve message history, working memory, and semantically relevant messages, then persist new messages after the model responds.
7
+ When memory is enabled on an agent, Mastra adds memory processors to the agent's processor pipeline. These processors retrieve message history and working memory, plus semantically relevant messages, then persist new messages after the model responds.
8
8
 
9
9
  Memory processors are [processors](https://mastra.ai/docs/agents/processors) that operate specifically on memory-related messages and state.
10
10
 
@@ -47,7 +47,7 @@ const agent = new Agent({
47
47
  id: 'test-agent',
48
48
  name: 'Test Agent',
49
49
  instructions: 'You are a helpful assistant',
50
- model: 'openai/gpt-5.5',
50
+ model: 'openai/gpt-5.6-sol',
51
51
  memory: new Memory({
52
52
  storage: new LibSQLStore({
53
53
  id: 'memory-store',
@@ -97,7 +97,7 @@ import { openai } from '@ai-sdk/openai'
97
97
  const agent = new Agent({
98
98
  name: 'semantic-agent',
99
99
  instructions: 'You are a helpful assistant with semantic memory',
100
- model: 'openai/gpt-5.5',
100
+ model: 'openai/gpt-5.6-sol',
101
101
  memory: new Memory({
102
102
  storage: new LibSQLStore({
103
103
  id: 'memory-store',
@@ -150,7 +150,7 @@ import { openai } from '@ai-sdk/openai'
150
150
  const agent = new Agent({
151
151
  name: 'working-memory-agent',
152
152
  instructions: 'You are an assistant with working memory',
153
- model: 'openai/gpt-5.5',
153
+ model: 'openai/gpt-5.6-sol',
154
154
  memory: new Memory({
155
155
  storage: new LibSQLStore({
156
156
  id: 'memory-store',
@@ -182,7 +182,7 @@ const customMessageHistory = new MessageHistory({
182
182
  const agent = new Agent({
183
183
  name: 'custom-memory-agent',
184
184
  instructions: 'You are a helpful assistant',
185
- model: 'openai/gpt-5.5',
185
+ model: 'openai/gpt-5.6-sol',
186
186
  memory: new Memory({
187
187
  storage: new LibSQLStore({ id: 'memory-store', url: 'file:memory.db' }),
188
188
  lastMessages: 10, // This would normally add MessageHistory(10)
@@ -207,7 +207,7 @@ Understanding the execution order is important when combining guardrails with me
207
207
  1. **Memory processors run FIRST**: `WorkingMemory`, `MessageHistory`, `SemanticRecall`
208
208
  2. **Your input processors run AFTER**: guardrails, filters, validators
209
209
 
210
- This means memory loads message history before your processors can validate or filter the input.
210
+ As a result, memory loads message history before your processors can validate or filter the input.
211
211
 
212
212
  ### Output Processors
213
213
 
@@ -253,7 +253,7 @@ const agent = new Agent({
253
253
  id: 'safe-agent',
254
254
  name: 'safe-agent',
255
255
  instructions: 'You are a helpful assistant',
256
- model: 'openai/gpt-5.5',
256
+ model: 'openai/gpt-5.6-sol',
257
257
  memory: new Memory({ lastMessages: 10 }),
258
258
  // Your guardrail runs BEFORE memory saves
259
259
  outputProcessors: [contentBlocker],
@@ -293,7 +293,7 @@ const agent = new Agent({
293
293
  id: 'validated-agent',
294
294
  name: 'validated-agent',
295
295
  instructions: 'You are a helpful assistant',
296
- model: 'openai/gpt-5.5',
296
+ model: 'openai/gpt-5.6-sol',
297
297
  memory: new Memory({ lastMessages: 10 }),
298
298
  // Your guardrail runs AFTER memory loads history
299
299
  inputProcessors: [inputValidator],
@@ -370,7 +370,7 @@ export const supportAgent = new Agent({
370
370
  id: 'support-agent',
371
371
  name: 'Support agent',
372
372
  instructions: 'Answer customer support questions.',
373
- model: 'openai/gpt-5.5',
373
+ model: 'openai/gpt-5.6-sol',
374
374
  memory: new Memory({ lastMessages: 10 }),
375
375
  inputProcessors: [new AttachmentUploader()],
376
376
  })
@@ -134,7 +134,7 @@ export const supportAgent = new Agent({
134
134
  id: 'support-agent',
135
135
  name: 'Support agent',
136
136
  instructions: 'Answer customer support questions.',
137
- model: 'openai/gpt-5.5',
137
+ model: 'openai/gpt-5.6-sol',
138
138
  memory: new Memory({
139
139
  options: {
140
140
  generateTitle: true,
@@ -155,7 +155,7 @@ export const supportAgent = new Agent({
155
155
  id: 'support-agent',
156
156
  name: 'Support agent',
157
157
  instructions: 'Answer customer support questions.',
158
- model: 'openai/gpt-5.5',
158
+ model: 'openai/gpt-5.6-sol',
159
159
  memory: new Memory({
160
160
  options: {
161
161
  generateTitle: {
@@ -176,7 +176,7 @@ const agent = mastra.getAgentById('test-agent')
176
176
  const memory = await agent.getMemory()
177
177
  ```
178
178
 
179
- The `Memory` instance gives you access to functions for listing threads, recalling messages, cloning conversations, and more.
179
+ The `Memory` instance gives you access to functions for listing threads and recalling messages, plus cloning conversations, and more.
180
180
 
181
181
  ## Querying
182
182
 
@@ -279,7 +279,13 @@ const { messages } = await memory.recall({
279
279
  })
280
280
  ```
281
281
 
282
- Metadata filters match shallow scalar values only: `string`, finite `number`, `boolean`, and `null`. All specified metadata keys must match with AND semantics, and `null` matches an explicit `null` value, not a missing metadata key. Metadata keys must start with a letter or underscore, may contain only alphanumeric characters and underscores, must be 128 characters or fewer, and can't use reserved prototype keys such as `__proto__`, `constructor`, or `prototype`. Performance depends on the storage backend. Some backends can push parts of the filter into the database, while others scan candidate messages after thread, resource, and date constraints are applied but before pagination.
282
+ Metadata filters match shallow scalar values only: `string`, finite `number`, `boolean`, and `null`.
283
+
284
+ All specified metadata keys use AND semantics. A `null` filter matches only an explicit `null` value. A missing metadata key doesn't match.
285
+
286
+ Metadata keys must start with a letter or underscore and contain only alphanumeric characters. They must be 128 characters or fewer and can't use reserved prototype keys such as `__proto__`, `constructor`, or `prototype`.
287
+
288
+ Performance depends on the storage backend. Some backends can push parts of the filter into the database, while others scan candidate messages after thread, resource, and date constraints are applied but before pagination.
283
289
 
284
290
  Fetch a single message by ID:
285
291
 
@@ -324,7 +330,7 @@ Message queries return `MastraDBMessage[]` format. To display messages in a fron
324
330
 
325
331
  ## Thread cloning
326
332
 
327
- Thread cloning creates a copy of an existing thread with its messages. This is useful for branching conversations, creating checkpoints before a potentially destructive operation, or testing variations of a conversation.
333
+ Thread cloning creates a copy of an existing thread with its messages. This is useful for branching conversations or creating checkpoints before a potentially destructive operation, or alternatively testing variations of a conversation.
328
334
 
329
335
  ```typescript
330
336
  const { thread, clonedMessages } = await memory.cloneThread({
@@ -14,13 +14,13 @@ Use multi-user threads when several people collaborate on the same subject throu
14
14
 
15
15
  ## Share one `resourceId` across all participants
16
16
 
17
- A thread belongs to exactly one `resourceId`, so all participants on a shared thread need to pass the same value. Instead of using a user id (the default for single-user apps), key `resourceId` on the conversation itself for example `doc_${docId}` for a shared document, or `room_${roomId}` for a group chat. With everyone pointing at the same `resourceId`, they read and write the same history.
17
+ A thread belongs to exactly one `resourceId`, so all participants on a shared thread need to pass the same value. Instead of using a user id (the default for single-user apps), key `resourceId` on the conversation itself, for example `doc_${docId}` for a shared document, or `room_${roomId}` for a group chat. With everyone pointing at the same `resourceId`, they read and write the same history.
18
18
 
19
19
  ## Tag each user message with the speaker's identity
20
20
 
21
21
  The model needs to know who's talking on every turn. Since the message body is the one place that survives into history and back into context, wrap each user message in a small `<turn>` tag with the speaker's id, name, and role. The tag stays attached to the message, so when prior turns are recalled the model still sees who said what.
22
22
 
23
- Build the tag with a small helper. The example below is one way to do it copy it into your project and adapt it to your shape of user data:
23
+ Build the tag with a small helper. The example below is one way to do it, copy it into your project and adapt it to your shape of user data:
24
24
 
25
25
  ```typescript
26
26
  export type Speaker = {
@@ -113,11 +113,11 @@ The `<turn>` tag persists in the message body, so when history is recalled on la
113
113
 
114
114
  The user-tagging pattern composes with every memory layer. Pick the layer based on how long the conversation needs to remember per-user facts:
115
115
 
116
- - **Short conversations** (a single session, or a thread small enough to fit in `lastMessages`), or when you need a verbatim record of who said what: use [message history alone](#message-history-alone). The user tags in history are enough; no extra memory layer needed.
116
+ - **Short conversations** (a single session, or a thread small enough to fit in `lastMessages`), or when you need a verbatim record of who said what: use [message history alone](#message-history-alone). The user tags in history are enough. No extra memory layer needed.
117
117
  - **Long-running threads** (conversations that outgrow `lastMessages`, where you need per-user facts to survive history eviction): use [observational memory](#with-observational-memory-recommended).
118
118
  - **Need a structured participants list, or your storage adapter doesn't support OM** (OM requires LibSQL, PG, or MongoDB): use [working memory](#with-working-memory).
119
119
 
120
- We recommend using observational memory or working memory, not both — they cover overlapping needs, and running both at once adds latency and token cost without much benefit.
120
+ We recommend using either observational memory or working memory because they cover overlapping needs. Running both adds latency and token cost without much benefit.
121
121
 
122
122
  ### Message history alone
123
123
 
@@ -139,7 +139,7 @@ The model reads identity from the `<turn>` tag on the current message and from p
139
139
 
140
140
  ### With Observational Memory (recommended)
141
141
 
142
- [Observational Memory](https://mastra.ai/docs/memory/observational-memory) (OM) extracts per-user facts into a background log without burning the agent's tool budget. The default Observer model reads `<turn>` tags natively and produces named attribution like `Alice stated her favorite color is teal.` and `Bob asked for QA sign-off before publish.`
142
+ [Observational Memory](https://mastra.ai/docs/memory/observational-memory) (OM) extracts per-user facts into a background log without burning the agent's tool budget. The default Observer model reads `<turn>` tags natively and produces attribution like `Alice stated her favorite color is teal.` and `Bob asked for QA sign-off before publish.`
143
143
 
144
144
  Prefer OM over working memory for multi-user threads when your storage supports it. OM extracts facts automatically, scales to any number of participants, and doesn't need template upkeep. Enable it with no overrides:
145
145
 
@@ -162,7 +162,7 @@ OM requires a storage adapter that supports it: `@mastra/libsql`, `@mastra/pg`,
162
162
 
163
163
  ### With working memory
164
164
 
165
- Use working memory when OM isn't an option for example, when your storage adapter doesn't support OM, or when you need a structured, deterministic participants list the agent can read and write on every turn.
165
+ Use working memory when OM isn't an option, for example, when your storage adapter doesn't support OM, or when you need a structured, deterministic participants list the agent can read and write on every turn.
166
166
 
167
167
  The default [working memory](https://mastra.ai/docs/memory/working-memory) template assumes one user per thread ("First Name", "Last Name", etc.). For multi-user threads, provide a template with a participants list:
168
168
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  **Added in:** `@mastra/memory@1.1.0`
6
6
 
7
- Observational Memory (OM) is Mastra's memory system for long-context agentic memory. Two background agents an **Observer** and a **Reflector** watch your agent's conversations and maintain a dense observation log that replaces raw message history as it grows.
7
+ Observational Memory (OM) is Mastra's memory system for long-context agentic memory. Background agents, an **Observer** and a **Reflector**, watch your agent's conversations and maintain a dense observation log that replaces raw message history as it grows.
8
8
 
9
9
  ## Quickstart
10
10
 
@@ -94,11 +94,11 @@ See [configuration options](https://mastra.ai/reference/memory/observational-mem
94
94
  >
95
95
  > For an AI SDK example, see [Using Mastra Memory](https://mastra.ai/guides/build-your-ui/ai-sdk-ui).
96
96
 
97
- > **Note:** OM currently only supports `@mastra/pg`, `@mastra/libsql`, `@mastra/mongodb`, and `@mastra/convex` storage adapters. It uses background agents for managing memory. When no model is set, the default model is `google/gemini-2.5-flash`.
97
+ > **Note:** OM currently only supports `@mastra/pg`, `@mastra/libsql`, `@mastra/mysql`, `@mastra/mongodb`, and `@mastra/convex` storage adapters. It uses background agents for managing memory. When no model is set, the default model is `google/gemini-2.5-flash`.
98
98
 
99
99
  ## Temporal gap markers
100
100
 
101
- Temporal gap markers insert a short reminder before a new user message when enough time has passed since the previous message in the thread. They help the agent and the UI see that the conversation resumed after a meaningful pause.
101
+ Temporal gap markers insert a short reminder before a new user message when enough time has passed since the previous message in the thread. They help the agent and the UI see that the conversation resumed after a useful pause.
102
102
 
103
103
  Temporal gap markers are off by default. Enable them with `temporalMarkers: true` in the `observationalMemory` config:
104
104
 
@@ -191,15 +191,15 @@ See [the API reference](https://mastra.ai/reference/memory/observational-memory)
191
191
 
192
192
  ## Benefits
193
193
 
194
- - **Prompt caching**: OM's context is stable and observations append over time rather than being dynamically retrieved each turn. This keeps the prompt prefix cacheable, which reduces costs.
194
+ - **Prompt caching**: OM's context is stable and observations append over time rather than being retrieved at runtime each turn. This keeps the prompt prefix cacheable, which reduces costs.
195
195
  - **Compression**: Raw message history and tool results get compressed into a dense observation log. Smaller context means faster responses and longer coherent conversations.
196
196
  - **Zero context rot**: The agent sees relevant information instead of noisy tool calls and irrelevant tokens, so the agent stays on task over long sessions.
197
197
 
198
198
  ## How it works
199
199
 
200
- You don't remember every word of every conversation you've ever had. You observe what happened subconsciously, then your brain reflects reorganizing, combining, and condensing into long-term memory. OM works the same way.
200
+ You don't remember every word of every conversation you've ever had. You observe what happened subconsciously, then your brain reflects, reorganizing, combining, and condensing into long-term memory. OM works the same way.
201
201
 
202
- Every time an agent responds, it sees a context window containing its system prompt, recent message history, and any injected context. The context window is finite; even models with large token limits perform worse when the window is full. This causes two problems:
202
+ Every time an agent responds, it sees a context window containing its system prompt, recent message history, and any injected context. The context window is finite. Even models with large token limits perform worse when the window is full. This causes two problems:
203
203
 
204
204
  - **Context rot**: the more raw message history an agent carries, the worse it performs.
205
205
  - **Context waste**: most of that history contains tokens no longer needed to keep the agent on task.
@@ -274,7 +274,7 @@ new Extractor({
274
274
  })
275
275
  ```
276
276
 
277
- Use dynamic `instructions` or `schema` functions when an extractor needs runtime context, such as the active memory instance or request context:
277
+ Use runtime `instructions` or `schema` functions when an extractor needs runtime context, such as the active memory instance or request context:
278
278
 
279
279
  ```typescript
280
280
  new Extractor({
@@ -378,7 +378,7 @@ new Agent({
378
378
  })
379
379
  ```
380
380
 
381
- You can also pass an allowlist of mimeType globs (for example `['image/*']`) to forward only the kinds the Observer can handle.
381
+ You can also pass an allowlist of mimeType globs (for example `['image/*']`) to forward only the kinds the Observer can handle. Alternatively, set `observeAttachments: 'auto'` to let Mastra decide from the provider capabilities registry: attachments are forwarded when the Observer model supports multimodal input and dropped otherwise, falling back to `true` when no capability data is available for the model.
382
382
 
383
383
  ```md
384
384
  Date: 2026-01-15
@@ -389,7 +389,7 @@ Date: 2026-01-15
389
389
  - 🔴 12:15 User stated the app name is "Acme Dashboard"
390
390
  ```
391
391
 
392
- The compression is typically 5–40×. The Observer also tracks a **current task** and **suggested response** so the agent picks up where it left off.
392
+ The compression is typically between 5x and 40x. The Observer also tracks a **current task** and **suggested response** so the agent picks up where it left off.
393
393
 
394
394
  If you enable `observation.threadTitle`, the Observer can also suggest a short thread title when the conversation topic meaningfully changes. Thread title generation is opt-in and updates the thread metadata, so apps like Mastra Code can show the latest title in thread lists and status UI.
395
395
 
@@ -397,7 +397,9 @@ Example: An agent using Playwright MCP might see 50,000+ tokens per page snapsho
397
397
 
398
398
  ### Reflections
399
399
 
400
- When observations exceed their threshold (default: 40,000 tokens), the Reflector condenses them, combines related items, and reflects on patterns.
400
+ When observations exceed their threshold (default: 40,000 tokens), the Reflector condenses them and combines related items, plus reflects on patterns.
401
+
402
+ Reflections don't accumulate as a separate, ever-growing layer. Each reflection rewrites the entire observation log: the Reflector's output becomes the new log, and new observations append after it. When the log next hits the threshold, the Reflector re-processes everything — including earlier reflections — condensing older information more aggressively while keeping recent detail. Memory stays bounded around the reflection threshold no matter how long the conversation runs.
401
403
 
402
404
  The result is a three-tier system:
403
405
 
@@ -405,6 +407,21 @@ The result is a three-tier system:
405
407
  2. **Observations**: A log of what the Observer has seen
406
408
  3. **Reflections**: Condensed observations when memory becomes too long
407
409
 
410
+ ### Context over time
411
+
412
+ With default settings, the context window doesn't grow unbounded. It oscillates through an observe-and-shrink cycle:
413
+
414
+ ![Chart of context tokens over the course of a conversation with Observational Memory enabled: message history repeatedly grows toward the 30,000 token observation threshold, then shrinks back to around 6,000 tokens as observations activate, while the observation log steps up with each cycle until it reaches the 40,000 token reflection threshold and the Reflector condenses it into reflections](/img/memory/om-context-over-time-light.svg)
415
+
416
+ 1. **0 → 30k tokens**: Message history grows normally. In the background, the Observer buffers observations every \~6k tokens (`bufferTokens: 0.2`).
417
+ 2. **30k reached**: Buffered observations activate instantly. Observed messages are removed from the context window and only \~6k tokens of recent history remain (`bufferActivation: 0.8` retains 20% of the threshold). The \~24k tokens of removed messages become roughly 1-5k tokens of observations at typical 5-40x compression.
418
+ 3. **Repeat**: History grows from \~6k back toward 30k and shrinks again. Each cycle appends to the observation log, which grows much more slowly than raw history.
419
+ 4. **Observations reach 40k**: The Reflector condenses the observation log — including any earlier reflections — into a new, smaller log.
420
+
421
+ The result: in the normal buffered cycle, raw history oscillates between roughly 6k and 30k tokens and the observation log stays around 40k tokens, however long the conversation runs. These are activation thresholds rather than hard caps — if background buffering falls behind, history can grow past the threshold until `blockAfter` (default `1.2`) forces a synchronous observation at \~36k tokens (\~48k for reflection) as a safety ceiling.
422
+
423
+ With [`shareTokenBudget`](https://mastra.ai/reference/memory/observational-memory) enabled, the two budgets pool together: while the observation log is small, message history can expand into the unused observation space (up to \~70k tokens with the defaults) before observation triggers, then shrinks back as observations accumulate.
424
+
408
425
  ### Retrieval mode
409
426
 
410
427
  Normal OM compresses messages into observations, which is great for staying on task, but the original wording is gone. Retrieval mode fixes this by keeping each observation group linked to the raw messages that produced it. When the agent needs exact wording, tool output, or chronology that the summary compressed away, it can call a `recall` tool to page through the source messages.
@@ -446,7 +463,7 @@ When vector search is configured, new observation groups are automatically index
446
463
 
447
464
  #### Restricting to the current thread
448
465
 
449
- By default, the recall tool scope is `'resource'` the agent can list threads, browse other threads, and search across all conversations. Set `scope: 'thread'` to restrict the agent to only the current thread:
466
+ By default, the recall tool scope is `'resource'`, the agent can list threads and browse other threads, plus search across all conversations. Set `scope: 'thread'` to restrict the agent to only the current thread:
450
467
 
451
468
  ```typescript
452
469
  const memory = new Memory({
@@ -481,7 +498,9 @@ See the [recall tool reference](https://mastra.ai/reference/memory/observational
481
498
  To see how it works in practice, open [Studio](https://mastra.ai/docs/studio/overview) and navigate to an agent with OM enabled. The **Memory** tab displays:
482
499
 
483
500
  - **Token progress bars**: Current token counts for messages and observations, showing how close each is to its threshold. Hover over the info icon to see the model and threshold for the Observer and Reflector.
484
- - **Active observations**: The current observation log, rendered inline. When previous observation or reflection records exist, expand "Previous observations" to browse them.
501
+
502
+ - **Active observations**: The current observation log is shown inline. If earlier observation or reflection records exist, expand "Previous observations" to browse them.
503
+
485
504
  - **Background processing**: During a conversation, buffered observation chunks and reflection status appear as the agent processes in the background.
486
505
 
487
506
  The progress bars update live while the agent is observing or reflecting, showing elapsed time and a status badge.
@@ -490,7 +509,7 @@ The progress bars update live while the agent is observing or reflecting, showin
490
509
 
491
510
  The Observer and Reflector run in the background. Any model that works with Mastra's [model routing](https://mastra.ai/models) (`provider/model`) can be used. When no model is set, the default model is `google/gemini-2.5-flash`.
492
511
 
493
- Generally speaking, we recommend using a model that has a large context window (128K+ tokens) and is fast enough to run in the background without slowing down your actions.
512
+ Mastra recommends using a model that has a large context window (128K+ tokens) and is fast enough to run in the background without slowing down your actions.
494
513
 
495
514
  If you're unsure which model to use, start with the default `google/gemini-2.5-flash`. We've also successfully tested `openai/gpt-5-mini`, `anthropic/claude-haiku-4-5`, `deepseek/deepseek-reasoner`, `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`, `xai/grok-4-1-fast`, `qwen3`, and `glm-4.7`.
496
515
 
@@ -508,7 +527,7 @@ See [model configuration](https://mastra.ai/reference/memory/observational-memor
508
527
 
509
528
  > **Note:** `google/gemini-2.5-flash` is unusually good at preserving detail in long output. As a result, the Reflector can produce reflections that stay above the configured `reflection.observationTokens` threshold even after the maximum compression retry. When this happens, the Reflector returns the smallest non-degenerate candidate produced during retries so the loop terminates instead of running forever.
510
529
  >
511
- > If you'd rather have more aggressive compression on the Reflector, swap to a model that condenses more readily, such as `xai/grok-4-1-fast`, `deepseek/deepseek-v4-pro`, or `deepseek/deepseek-v4-flash`. You can keep `google/gemini-2.5-flash` for the Observer and use a different model for the Reflector see [different models per agent](https://mastra.ai/reference/memory/observational-memory).
530
+ > If you'd rather have more aggressive compression on the Reflector, swap to a model that condenses more readily, such as `xai/grok-4-1-fast`, `deepseek/deepseek-v4-pro`, or `deepseek/deepseek-v4-flash`. You can keep `google/gemini-2.5-flash` for the Observer and use a different model for the Reflector. See [different models per agent](https://mastra.ai/reference/memory/observational-memory).
512
531
 
513
532
  ### Token-tiered model selection
514
533
 
@@ -546,9 +565,9 @@ const memory = new Memory({
546
565
  })
547
566
  ```
548
567
 
549
- The `upTo` keys are inclusive upper bounds. OM computes the actual input token count for the Observer or Reflector call, resolves the matching tier directly, and uses that concrete model for the run.
568
+ The `upTo` keys are inclusive upper bounds. OM computes the actual input token count for the Observer or Reflector call and resolves the matching tier directly, plus uses that concrete model for the run.
550
569
 
551
- If the input exceeds the largest configured threshold, an error is thrown ensure your thresholds cover the full range of possible input sizes, or use a model with a sufficiently large context window at the highest tier.
570
+ If the input exceeds the largest configured threshold, an error is thrown, ensure your thresholds cover the full range of possible input sizes, or use a model with a sufficiently large context window at the highest tier.
552
571
 
553
572
  ## Scopes
554
573
 
@@ -651,10 +670,10 @@ const filePart = {
651
670
 
652
671
  The `tokenEstimate` object follows the same shape the Token Counter uses internally for cached estimates:
653
672
 
654
- - `v` cache schema version. Set to `0`. Caller-supplied entries are exempt from the framework's version check, so the value isn't read.
655
- - `source` cache lineage marker. Must be `'client'`. This is what tells the Token Counter the entry is authoritative and should be honored verbatim instead of being recomputed or overwritten.
656
- - `key` content fingerprint slot. Set to `'client'`. Framework entries use a content hash here so they invalidate when the payload changes; the `'client'` sentinel keeps caller estimates stable across writes.
657
- - `tokens` the token count to use. Must be a finite non-negative number.
673
+ - `v`: cache schema version. Set to `0`. Caller-supplied entries are exempt from the framework's version check, so the value isn't read.
674
+ - `source`: cache lineage marker. Must be `'client'`. This is what tells the Token Counter the entry is authoritative and should be honored verbatim instead of being recomputed or overwritten.
675
+ - `key`: content fingerprint slot. Set to `'client'`. Framework entries use a content hash here so they invalidate when the payload changes. The `'client'` sentinel keeps caller estimates stable across writes.
676
+ - `tokens`: the token count to use. Must be a finite non-negative number.
658
677
 
659
678
  Additional notes:
660
679
 
@@ -662,7 +681,7 @@ Additional notes:
662
681
 
663
682
  ## Async buffering
664
683
 
665
- Without async buffering, the Observer runs synchronously when the message threshold is reached the agent pauses mid-conversation while the Observer LLM call completes. With async buffering (enabled by default), observations are pre-computed in the background as the conversation grows. When the threshold is hit, buffered observations activate instantly with no pause.
684
+ Without async buffering, the Observer runs synchronously when the message threshold is reached, the agent pauses mid-conversation while the Observer LLM call completes. With async buffering (enabled by default), observations are pre-computed in the background as the conversation grows. When the threshold is hit, buffered observations activate instantly with no pause.
666
685
 
667
686
  ### How it works
668
687
 
@@ -670,19 +689,19 @@ As the agent converses, message tokens accumulate. At regular intervals (`buffer
670
689
 
671
690
  When message tokens reach the `messageTokens` threshold, buffered chunks activate: their observations move into the active observation log, and the corresponding raw messages are removed from the context window. The agent never pauses.
672
691
 
673
- Buffered observations also include continuation hints a suggested next response and the current task so the main agent maintains conversational continuity after activation shrinks the context window.
692
+ Buffered observations also include continuation hints, a suggested next response and the current task, so the main agent maintains conversational continuity after activation shrinks the context window.
674
693
 
675
694
  If the agent produces messages faster than the Observer can process them, a `blockAfter` safety threshold forces a synchronous observation as a last resort. Buffered activation still preserves a minimum remaining context (the smaller of \~1k tokens or the configured retention floor).
676
695
 
677
- Reflection works similarly the Reflector runs in the background when observations reach a fraction of the reflection threshold.
696
+ Reflection works similarly, the Reflector runs in the background when observations reach a fraction of the reflection threshold.
678
697
 
679
698
  ### Settings
680
699
 
681
700
  | Setting | Default | What it controls |
682
701
  | ------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
683
- | `observation.bufferTokens` | `0.2` | How often to buffer. `0.2` means every 20% of `messageTokens` with the default 30k threshold, that's roughly every 6k tokens. Can also be an absolute token count (e.g. `5000`). |
702
+ | `observation.bufferTokens` | `0.2` | How often to buffer. `0.2` means every 20% of `messageTokens`. With the default 30k threshold, that's roughly every 6k tokens. Can also be an absolute token count (e.g. `5000`). |
684
703
  | `observation.bufferActivation` | `0.8` | How aggressively to clear the message window on activation. `0.8` means remove enough messages to keep only 20% of `messageTokens` remaining. Lower values keep more message history. |
685
- | `observation.blockAfter` | `1.2` | Safety threshold as a multiplier of `messageTokens`. At `1.2`, synchronous observation is forced at 36k tokens (1.2 × 30k). Only matters if buffering can't keep up. |
704
+ | `observation.blockAfter` | `1.2` | Safety net if buffering can't keep up. Values from 1 up to (but not including) 100 multiply `messageTokens`: at `1.2`, synchronous observation is forced at 36k tokens (1.2 × 30k). Values of 100 or more are absolute token counts (e.g. `50_000`). |
686
705
  | `activateAfterIdle` | none | Forces buffered observations to activate after a period of inactivity, even before `observation.messageTokens` is reached. Accepts a numeric millisecond value such as `300_000`, duration strings like `"5m"` or `"1hr"`, or `"auto"` for a provider-aware prompt cache TTL. |
687
706
  | `activateOnProviderChange` | `false` | Forces buffered observations to activate when the next step uses a different `provider/model` than the one that produced the latest assistant step. Use this when switching providers or models would invalidate prompt cache reuse. |
688
707
  | `reflection.bufferActivation` | `0.5` | When to start background reflection. `0.5` means reflection begins when observations reach 50% of the `observationTokens` threshold. |
@@ -694,16 +713,16 @@ If you're relying on prompt caching, set `activateAfterIdle` to `"auto"` or to a
694
713
 
695
714
  With `"auto"`, Mastra chooses an idle activation TTL from the active model provider:
696
715
 
697
- | Provider | Auto TTL |
698
- | --------------------------------------------------------------------------------------- | --------- |
699
- | Anthropic, OpenRouter, unknown providers, xAI | 5 minutes |
700
- | DeepSeek | 1 hour |
701
- | Google Gemini | 24 hours |
702
- | Groq | 2 hours |
703
- | OpenAI with `providerOptions.openai.promptCacheRetention: "24h"` | 1 hour |
704
- | OpenAI with `providerOptions.openai.promptCacheRetention: "in_memory"` | 5 minutes |
705
- | OpenAI `gpt-4*`, `gpt-5`, `gpt-5-*`, `gpt-5.1*`, `gpt-5.2*`, `gpt-5.3*`, and `gpt-5.4*` | 5 minutes |
706
- | Other OpenAI models | 1 hour |
716
+ | Provider | Auto TTL |
717
+ | ------------------------------------------------------------------------------------------------------ | --------- |
718
+ | Anthropic, OpenRouter, unknown providers, xAI | 5 minutes |
719
+ | DeepSeek | 1 hour |
720
+ | Google Gemini | 24 hours |
721
+ | Groq | 2 hours |
722
+ | OpenAI with `providerOptions.openai.promptCacheRetention: "24h"` | 1 hour |
723
+ | OpenAI with `providerOptions.openai.promptCacheRetention: "in_memory"` | 5 minutes |
724
+ | OpenAI `gpt-4*`, `gpt-5`, `gpt-5-*`, and `gpt-5.1` through `gpt-5.4` (including `-` suffixed variants) | 5 minutes |
725
+ | Other OpenAI models | 1 hour |
707
726
 
708
727
  ```typescript
709
728
  const memory = new Memory({
@@ -761,7 +780,7 @@ const memory = new Memory({
761
780
  })
762
781
  ```
763
782
 
764
- - `previousObserverTokens: 2000` → default; keeps \~2k tokens of recent observations.
783
+ - `previousObserverTokens: 2000` → default. Keeps \~2k tokens of recent observations.
765
784
  - `previousObserverTokens: 0` → omit previous observations completely.
766
785
  - `previousObserverTokens: false` → disable truncation and keep full previous observations.
767
786
 
@@ -770,7 +789,7 @@ const memory = new Memory({
770
789
  No manual migration needed. OM reads existing messages and observes them lazily when thresholds are exceeded.
771
790
 
772
791
  - **Thread scope**: The first time a thread exceeds `observation.messageTokens`, the Observer processes the backlog.
773
- - **Resource scope**: All unobserved messages across all threads for a resource are processed together. For users with many existing threads, this could take significant time.
792
+ - **Resource scope**: All unobserved messages across all threads for a resource are processed together. For users with many existing threads, this could take substantial time.
774
793
 
775
794
  ## Comparing OM with other memory features
776
795
 
@@ -779,7 +798,7 @@ No manual migration needed. OM reads existing messages and observes them lazily
779
798
  - **[Semantic Recall](https://mastra.ai/docs/memory/semantic-recall)**: RAG-based retrieval of relevant past messages
780
799
  - **[Multi-user threads](https://mastra.ai/docs/memory/multi-user-threads)**: How OM attributes facts to individual users when several people share a single thread
781
800
 
782
- If you're using working memory to store conversation summaries or ongoing state that grows over time, OM is a better fit. Working memory is for small, structured data; OM is for long-running event logs. OM also manages message history automaticallythe `messageTokens` setting controls how much raw history remains before observation runs.
801
+ If you're using working memory to store conversation summaries or ongoing state that grows over time, OM is a better fit. Working memory is for small, structured data. OM is for long-running event logs. OM also manages message history automatically, the `messageTokens` setting controls how much raw history remains before observation runs.
783
802
 
784
803
  In practical terms, OM replaces both working memory and message history, and has greater accuracy (and lower cost) than Semantic Recall.
785
804
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Memory
4
4
 
5
- Memory enables your agent to remember user messages, agent replies, and tool results across interactions, giving it the context it needs to stay consistent, maintain conversation flow, and produce better answers over time.
5
+ Memory enables your agent to remember user messages and agent replies, and tool results across interactions, giving it the context it needs to stay consistent, maintain conversation flow, plus produce better answers over time.
6
6
 
7
7
  Mastra agents can be configured to store [message history](https://mastra.ai/docs/memory/message-history). Additionally, you can enable:
8
8
 
@@ -19,7 +19,7 @@ Memory results will be stored in one or more of your configured [storage provide
19
19
 
20
20
  ## When to use memory
21
21
 
22
- Use memory when your agent needs to maintain multi-turn conversations that reference prior exchanges, recall user preferences or facts from earlier in a session, or build context over time within a conversation thread. Skip memory for single-turn requests where each interaction is independent.
22
+ Use memory when your agent needs to maintain multi-turn conversations that reference prior exchanges or recall user preferences or facts from earlier in a session, or alternatively build context over time within a conversation thread. Skip memory for single-turn requests where each interaction is independent.
23
23
 
24
24
  ## Quickstart
25
25
 
@@ -172,6 +172,20 @@ export const memoryAgent = new Agent({
172
172
 
173
173
  See [Observational Memory](https://mastra.ai/docs/memory/observational-memory) for details on how observations and reflections work, and [the reference](https://mastra.ai/reference/memory/observational-memory) for all configuration options.
174
174
 
175
+ ## What the model sees
176
+
177
+ Each memory feature lands in one of two places in the request sent to the model: the system messages or the conversation messages. Which layers are present depends on which features you've enabled — working memory, semantic recall, and Observational Memory only appear when configured, while message history is on by default. The diagram shows where each enabled layer is placed in the request; the list below describes what each layer contributes:
178
+
179
+ ![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](/img/memory/memory-context-window-light.svg)
180
+
181
+ - [Working memory](https://mastra.ai/docs/memory/working-memory) is injected as a system message containing the template and the stored data. With `useStateSignals`, it's delivered as a state signal instead.
182
+ - [Semantic recall](https://mastra.ai/docs/memory/semantic-recall) matches from the current thread are inserted as regular messages and interleave with message history by timestamp. Matches from other threads are formatted into a system message instead.
183
+ - [Message history](https://mastra.ai/docs/memory/message-history) adds the last N messages in chronological order. Your new message always comes last.
184
+ - [Observational Memory](https://mastra.ai/docs/memory/observational-memory) replaces old raw history: reflections and observations live in a system message, and only messages that haven't been observed yet remain in the conversation. A short continuation reminder is placed at the start of the conversation messages.
185
+ - Context messages are the optional `context` array passed on a call, for example `agent.generate(msg, { context: [...] })`. Use them for one-off background such as app state or your own RAG results. They appear as regular conversation messages for that request only and are never saved to memory.
186
+
187
+ Conversation messages are ordered by timestamp and deduplicated by message ID, so recalled older messages appear before recent history. Context messages passed at call time are stamped with the current time, which places them after history and recall but before your new message. To inspect the exact context for a real request, use [Tracing](https://mastra.ai/docs/observability/tracing/overview) and open the LLM call spans, see [Observability](#observability) below.
188
+
175
189
  ## Memory in multi-agent systems
176
190
 
177
191
  When a [supervisor agent](https://mastra.ai/docs/agents/supervisor-agents) delegates to a subagent, Mastra isolates subagent memory automatically. No flag enables this as it happens on every delegation. Understanding how this scoping works lets you decide what stays private and what to share intentionally.
@@ -182,21 +196,21 @@ Each delegation creates a fresh `threadId` and a deterministic `resourceId` for
182
196
 
183
197
  - **Thread ID**: Unique per delegation. The subagent starts with a clean message history every time it's called.
184
198
  - **Resource ID**: Derived as `{parentResourceId}-{agentName}`. Because the resource ID is stable across delegations, resource-scoped memory persists between calls. A subagent remembers facts from previous delegations by the same user.
185
- - **Memory instance**: If a subagent has no memory configured, it inherits the supervisor's `Memory` instance, including all of its options. If the subagent defines its own, that takes precedence.
199
+ - **Memory instance**: A subagent without its own memory inherits the supervisor's `Memory` instance and all configured options. If the subagent defines its own, that takes precedence.
186
200
 
187
201
  > **Note:** Title generation (`generateTitle`) is a top-level thread concern and **isn't** applied to inherited subagent threads. Because each delegation creates an ephemeral thread that no one sees, running title generation for it would waste an LLM call per delegation. To generate titles for a subagent's own threads, give that subagent its own memory configuration.
188
202
 
189
- The supervisor forwards its conversation context to the subagent so it has enough background to complete the task. Only the delegation prompt and the subagent's response are saved the full parent conversation isn't stored. You can control which messages reach the subagent with the [`messageFilter`](https://mastra.ai/docs/agents/supervisor-agents) callback.
203
+ The supervisor forwards its conversation context to the subagent so it has enough background to complete the task. Only the delegation prompt and the subagent's response are saved, the full parent conversation isn't stored. You can control which messages reach the subagent with the [`messageFilter`](https://mastra.ai/docs/agents/supervisor-agents) callback.
190
204
 
191
- > **Note:** Subagent resource IDs are always suffixed with the agent name (`{parentResourceId}-{agentName}`). Two different subagents under the same supervisor never share a resource ID through delegation.
205
+ > **Note:** Subagent resource IDs are always suffixed with the agent name (`{parentResourceId}-{agentName}`). Different subagents under the same supervisor never share a resource ID through delegation.
192
206
 
193
207
  To go beyond this default isolation, you can share memory between agents by passing matching identifiers when you call them directly.
194
208
 
195
209
  ### Share memory between agents
196
210
 
197
- When you call agents directly (outside the delegation flow), memory sharing is controlled by two identifiers: `resourceId` and `threadId`. Agents that use the same values read and write to the same data. This is useful when agents collaborate on a shared context for example, a researcher that saves notes and a writer that reads them.
211
+ When you call agents directly (outside the delegation flow), memory sharing is controlled by two identifiers: `resourceId` and `threadId`. Agents that use the same values read and write to the same data. This is useful when agents collaborate on a shared context, for example, a researcher that saves notes and a writer that reads them.
198
212
 
199
- **Resource-scoped sharing** is the most common pattern. [Working memory](https://mastra.ai/docs/memory/working-memory) and [semantic recall](https://mastra.ai/docs/memory/semantic-recall) default to `scope: 'resource'`. If two agents share a `resourceId`, they share observations, working memory, and embeddings even across different threads:
213
+ **Resource-scoped sharing** is the most common pattern. [Working memory](https://mastra.ai/docs/memory/working-memory) and [semantic recall](https://mastra.ai/docs/memory/semantic-recall) default to `scope: 'resource'`. If two agents share a `resourceId`, they share observations, working memory, and embeddings, even across different threads:
200
214
 
201
215
  ```typescript
202
216
  // Both agents share the same resource-scoped memory
@@ -209,15 +223,15 @@ await writer.generate('Write a summary from the research notes.', {
209
223
  })
210
224
  ```
211
225
 
212
- Because both calls use `resource: 'project-42'`, the writer can access the researcher's observations, working memory, and semantic embeddings. Each agent still has its own thread, so message histories stay separate.
226
+ Because both calls use `resource: 'project-42'`, the writer can access the researcher's observations and working memory. Semantic embeddings are also shared through the resource. Each agent still has its own thread, so message histories stay separate.
213
227
 
214
- **Thread-scoped sharing** gives tighter coupling. [Observational Memory](https://mastra.ai/docs/memory/observational-memory) uses `scope: 'thread'` by default. If two agents use the same `resource` _and_ `thread`, they share the full message history. Each agent sees every message the other has written. This is useful when agents need to build on each other's exact outputs.
228
+ **Thread-scoped sharing** gives tighter coupling. [Observational Memory](https://mastra.ai/docs/memory/observational-memory) uses `scope: 'thread'` by default. If two agents use the same `resource` and `thread`, they share the full message history. Each agent sees every message the other has written. This is useful when agents need to build on each other's exact outputs.
215
229
 
216
230
  ## Observability
217
231
 
218
232
  Enable [Tracing](https://mastra.ai/docs/observability/tracing/overview) to monitor and debug memory in action. Traces show you exactly which messages and observations the agent included in its context for each request, helping you understand agent behavior and verify that memory retrieval is working as expected.
219
233
 
220
- Open [Studio](https://mastra.ai/docs/studio/overview) and select the **Observability** tab in the sidebar. Open the trace of a recent agent request, then look for spans of LLMs calls.
234
+ Open [Studio](https://mastra.ai/docs/studio/overview) and select the **Observability** tab in the sidebar. Open the trace of a recent agent request and look for its LLM call spans.
221
235
 
222
236
  ## Switch memory per request
223
237
 
@@ -10,7 +10,7 @@ If you ask your friend what they did last weekend, they will search in their mem
10
10
 
11
11
  Semantic recall is RAG-based search that helps agents maintain context across longer interactions when messages are no longer within [recent message history](https://mastra.ai/docs/memory/message-history).
12
12
 
13
- It uses vector embeddings of messages for similarity search, integrates with various vector stores, and has configurable context windows around retrieved messages.
13
+ It uses vector embeddings of messages for similarity search and integrates with vector stores, plus has configurable context windows around retrieved messages.
14
14
 
15
15
  ![Diagram showing Mastra Memory semantic recall](/assets/images/semantic-recall-fd7b9336a6d0d18019216cb6d3dbe710.png)
16
16
 
@@ -34,7 +34,7 @@ const agent = new Agent({
34
34
  id: 'support-agent',
35
35
  name: 'SupportAgent',
36
36
  instructions: 'You are a helpful support agent.',
37
- model: 'openai/gpt-5.5',
37
+ model: 'openai/gpt-5.6-sol',
38
38
  memory: new Memory({
39
39
  storage: new LibSQLStore({
40
40
  id: 'agent-storage',
@@ -64,7 +64,7 @@ const agent = new Agent({
64
64
  id: 'support-agent',
65
65
  name: 'SupportAgent',
66
66
  instructions: 'You are a helpful support agent.',
67
- model: 'openai/gpt-5.5',
67
+ model: 'openai/gpt-5.6-sol',
68
68
  memory: new Memory({
69
69
  storage: new MongoDBStore({
70
70
  id: 'agent-storage',