@mastra/memory 1.6.1 → 1.6.2-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 (49) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/{chunk-GBBQIJQF.js → chunk-3CM4XQJO.js} +1940 -463
  3. package/dist/chunk-3CM4XQJO.js.map +1 -0
  4. package/dist/{chunk-D6II7EP4.cjs → chunk-5W5463NI.cjs} +1939 -461
  5. package/dist/chunk-5W5463NI.cjs.map +1 -0
  6. package/dist/docs/SKILL.md +1 -1
  7. package/dist/docs/assets/SOURCE_MAP.json +25 -25
  8. package/dist/docs/references/docs-agents-agent-memory.md +2 -2
  9. package/dist/docs/references/docs-agents-network-approval.md +4 -1
  10. package/dist/docs/references/docs-agents-networks.md +1 -1
  11. package/dist/docs/references/docs-memory-memory-processors.md +1 -1
  12. package/dist/docs/references/docs-memory-message-history.md +2 -2
  13. package/dist/docs/references/docs-memory-observational-memory.md +6 -2
  14. package/dist/docs/references/docs-memory-semantic-recall.md +2 -2
  15. package/dist/docs/references/docs-memory-storage.md +1 -1
  16. package/dist/docs/references/docs-memory-working-memory.md +6 -6
  17. package/dist/docs/references/reference-memory-cloneThread.md +1 -1
  18. package/dist/docs/references/reference-memory-observational-memory.md +7 -5
  19. package/dist/docs/references/reference-processors-token-limiter-processor.md +2 -2
  20. package/dist/docs/references/reference-storage-dynamodb.md +2 -2
  21. package/dist/docs/references/reference-storage-mongodb.md +1 -1
  22. package/dist/docs/references/reference-storage-postgresql.md +2 -2
  23. package/dist/docs/references/reference-storage-upstash.md +1 -1
  24. package/dist/docs/references/reference-vectors-pg.md +2 -0
  25. package/dist/index.cjs +48 -25
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.ts +14 -14
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +44 -21
  30. package/dist/index.js.map +1 -1
  31. package/dist/{observational-memory-AHVELJX4.cjs → observational-memory-C5LO7RBR.cjs} +17 -17
  32. package/dist/{observational-memory-AHVELJX4.cjs.map → observational-memory-C5LO7RBR.cjs.map} +1 -1
  33. package/dist/{observational-memory-QFQUF5EY.js → observational-memory-OYK4MEUD.js} +3 -3
  34. package/dist/{observational-memory-QFQUF5EY.js.map → observational-memory-OYK4MEUD.js.map} +1 -1
  35. package/dist/processors/index.cjs +15 -15
  36. package/dist/processors/index.js +1 -1
  37. package/dist/processors/observational-memory/observational-memory.d.ts +33 -2
  38. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  39. package/dist/processors/observational-memory/observer-agent.d.ts +7 -4
  40. package/dist/processors/observational-memory/observer-agent.d.ts.map +1 -1
  41. package/dist/processors/observational-memory/repro-capture.d.ts +23 -0
  42. package/dist/processors/observational-memory/repro-capture.d.ts.map +1 -0
  43. package/dist/processors/observational-memory/token-counter.d.ts +28 -3
  44. package/dist/processors/observational-memory/token-counter.d.ts.map +1 -1
  45. package/dist/tools/working-memory.d.ts +6 -10
  46. package/dist/tools/working-memory.d.ts.map +1 -1
  47. package/package.json +13 -8
  48. package/dist/chunk-D6II7EP4.cjs.map +0 -1
  49. package/dist/chunk-GBBQIJQF.js.map +0 -1
@@ -3,7 +3,7 @@ name: mastra-memory
3
3
  description: Documentation for @mastra/memory. Use when working with @mastra/memory APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/memory"
6
- version: "1.6.1"
6
+ version: "1.6.2-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,71 +1,71 @@
1
1
  {
2
- "version": "1.6.1",
2
+ "version": "1.6.2-alpha.0",
3
3
  "package": "@mastra/memory",
4
4
  "exports": {
5
5
  "OBSERVATIONAL_MEMORY_DEFAULTS": {
6
6
  "types": "dist/processors/index.d.ts",
7
- "implementation": "dist/chunk-GBBQIJQF.js"
7
+ "implementation": "dist/chunk-3CM4XQJO.js"
8
8
  },
9
9
  "OBSERVATION_CONTEXT_INSTRUCTIONS": {
10
10
  "types": "dist/processors/index.d.ts",
11
- "implementation": "dist/chunk-GBBQIJQF.js"
11
+ "implementation": "dist/chunk-3CM4XQJO.js"
12
12
  },
13
13
  "OBSERVATION_CONTEXT_PROMPT": {
14
14
  "types": "dist/processors/index.d.ts",
15
- "implementation": "dist/chunk-GBBQIJQF.js"
15
+ "implementation": "dist/chunk-3CM4XQJO.js"
16
16
  },
17
17
  "OBSERVATION_CONTINUATION_HINT": {
18
18
  "types": "dist/processors/index.d.ts",
19
- "implementation": "dist/chunk-GBBQIJQF.js"
19
+ "implementation": "dist/chunk-3CM4XQJO.js"
20
20
  },
21
21
  "OBSERVER_SYSTEM_PROMPT": {
22
22
  "types": "dist/processors/index.d.ts",
23
- "implementation": "dist/chunk-GBBQIJQF.js"
23
+ "implementation": "dist/chunk-3CM4XQJO.js"
24
24
  },
25
25
  "ObservationalMemory": {
26
26
  "types": "dist/processors/index.d.ts",
27
- "implementation": "dist/chunk-GBBQIJQF.js",
28
- "line": 1642
27
+ "implementation": "dist/chunk-3CM4XQJO.js",
28
+ "line": 2907
29
29
  },
30
30
  "TokenCounter": {
31
31
  "types": "dist/processors/index.d.ts",
32
- "implementation": "dist/chunk-GBBQIJQF.js",
33
- "line": 1401
32
+ "implementation": "dist/chunk-3CM4XQJO.js",
33
+ "line": 2385
34
34
  },
35
35
  "buildObserverPrompt": {
36
36
  "types": "dist/processors/index.d.ts",
37
- "implementation": "dist/chunk-GBBQIJQF.js",
38
- "line": 822
37
+ "implementation": "dist/chunk-3CM4XQJO.js",
38
+ "line": 993
39
39
  },
40
40
  "buildObserverSystemPrompt": {
41
41
  "types": "dist/processors/index.d.ts",
42
- "implementation": "dist/chunk-GBBQIJQF.js",
43
- "line": 570
42
+ "implementation": "dist/chunk-3CM4XQJO.js",
43
+ "line": 573
44
44
  },
45
45
  "extractCurrentTask": {
46
46
  "types": "dist/processors/index.d.ts",
47
- "implementation": "dist/chunk-GBBQIJQF.js",
48
- "line": 951
47
+ "implementation": "dist/chunk-3CM4XQJO.js",
48
+ "line": 1101
49
49
  },
50
50
  "formatMessagesForObserver": {
51
51
  "types": "dist/processors/index.d.ts",
52
- "implementation": "dist/chunk-GBBQIJQF.js",
53
- "line": 665
52
+ "implementation": "dist/chunk-3CM4XQJO.js",
53
+ "line": 820
54
54
  },
55
55
  "hasCurrentTaskSection": {
56
56
  "types": "dist/processors/index.d.ts",
57
- "implementation": "dist/chunk-GBBQIJQF.js",
58
- "line": 939
57
+ "implementation": "dist/chunk-3CM4XQJO.js",
58
+ "line": 1089
59
59
  },
60
60
  "optimizeObservationsForContext": {
61
61
  "types": "dist/processors/index.d.ts",
62
- "implementation": "dist/chunk-GBBQIJQF.js",
63
- "line": 962
62
+ "implementation": "dist/chunk-3CM4XQJO.js",
63
+ "line": 1112
64
64
  },
65
65
  "parseObserverOutput": {
66
66
  "types": "dist/processors/index.d.ts",
67
- "implementation": "dist/chunk-GBBQIJQF.js",
68
- "line": 853
67
+ "implementation": "dist/chunk-3CM4XQJO.js",
68
+ "line": 1003
69
69
  },
70
70
  "extractWorkingMemoryContent": {
71
71
  "types": "dist/index.d.ts",
@@ -96,7 +96,7 @@
96
96
  "processors": {
97
97
  "index": "dist/processors/index.js",
98
98
  "chunks": [
99
- "chunk-GBBQIJQF.js"
99
+ "chunk-3CM4XQJO.js"
100
100
  ]
101
101
  }
102
102
  }
@@ -96,7 +96,7 @@ export const memoryAgent = new Agent({
96
96
  })
97
97
  ```
98
98
 
99
- > **Mastra Cloud Store limitation:** Agent-level storage is not supported when using [Mastra Cloud Store](https://mastra.ai/docs/mastra-cloud/deployment). If you use Mastra Cloud Store, configure storage on the Mastra instance instead. This limitation does not apply if you bring your own database.
99
+ > **Mastra Cloud Store limitation:** Agent-level storage isn't supported when using [Mastra Cloud Store](https://mastra.ai/docs/mastra-cloud/deployment). If you use Mastra Cloud Store, configure storage on the Mastra instance instead. This limitation doesn't apply if you bring your own database.
100
100
 
101
101
  ## Message history
102
102
 
@@ -127,7 +127,7 @@ const response = await memoryAgent.generate("What's my favorite color?", {
127
127
  })
128
128
  ```
129
129
 
130
- > **Warning:** Each thread has an owner (`resourceId`) that cannot be changed after creation. Avoid reusing the same thread ID for threads with different owners, as this will cause errors when querying.
130
+ > **Warning:** Each thread has an owner (`resourceId`) that can't be changed after creation. Avoid reusing the same thread ID for threads with different owners, as this will cause errors when querying.
131
131
 
132
132
  To learn more about memory see the [Memory](https://mastra.ai/docs/memory/overview) documentation.
133
133
 
@@ -1,5 +1,7 @@
1
1
  # Network Approval
2
2
 
3
+ > **Deprecated:** Agent networks are deprecated and will be removed in a future release. Use the [supervisor pattern](https://mastra.ai/docs/agents/supervisor-agents) instead. See the [migration guide](https://mastra.ai/guides/migrations/network-to-supervisor) to upgrade.
4
+
3
5
  Agent networks can require the same [human-in-the-loop](https://mastra.ai/docs/workflows/human-in-the-loop) oversight used in individual agents and workflows. When a tool, subagent, or workflow within a network requires approval or suspends execution, the network pauses and emits events that allow your application to collect user input before resuming.
4
6
 
5
7
  ## Storage
@@ -269,7 +271,8 @@ Both approaches work with the same tool definitions. Automatic resumption trigge
269
271
 
270
272
  ## Related
271
273
 
272
- - [Agent Networks](https://mastra.ai/docs/agents/networks)
274
+ - [Supervisor Agents](https://mastra.ai/docs/agents/supervisor-agents)
275
+ - [Migration: .network() to Supervisor Pattern](https://mastra.ai/guides/migrations/network-to-supervisor)
273
276
  - [Agent Approval](https://mastra.ai/docs/agents/agent-approval)
274
277
  - [Human-in-the-Loop](https://mastra.ai/docs/workflows/human-in-the-loop)
275
278
  - [Agent Memory](https://mastra.ai/docs/agents/agent-memory)
@@ -1,6 +1,6 @@
1
1
  # Agent Networks
2
2
 
3
- > **Supervisor Pattern Recommended:** The [supervisor pattern](https://mastra.ai/docs/agents/supervisor-agents) using `agent.stream()` or `agent.generate()` is now the recommended approach for coordinating multiple agents. It provides the same multi-agent coordination capabilities as `.network()` with significant improvements:
3
+ > **Agent Network Deprecated — Supervisor Pattern Recommended:** Agent networks are deprecated and will be removed in a future release. The [supervisor pattern](https://mastra.ai/docs/agents/supervisor-agents) using `agent.stream()` or `agent.generate()` is now the recommended approach for coordinating multiple agents. It provides the same multi-agent coordination capabilities as `.network()` with significant improvements:
4
4
  >
5
5
  > - **Better control**: Iteration hooks, delegation hooks, and task completion scoring give you fine-grained control over execution
6
6
  > - **Simpler API**: Uses familiar `stream()` and `generate()` methods instead of a separate `.network()` API
@@ -161,7 +161,7 @@ const agent = new Agent({
161
161
 
162
162
  ## Manual Control and Deduplication
163
163
 
164
- If you manually add a memory processor to `inputProcessors` or `outputProcessors`, Mastra will **not** automatically add it. This gives you full control over processor ordering:
164
+ If you manually add a memory processor to `inputProcessors` or `outputProcessors`, Mastra **won't** automatically add it. This gives you full control over processor ordering:
165
165
 
166
166
  ```typescript
167
167
  import { Agent } from '@mastra/core/agent'
@@ -98,7 +98,7 @@ await agent.stream('Hello', {
98
98
 
99
99
  > **Info:** Threads and messages are created automatically when you call `agent.generate()` or `agent.stream()`, but you can also create them manually with [`createThread()`](https://mastra.ai/reference/memory/createThread) and [`saveMessages()`](https://mastra.ai/reference/memory/memory-class).
100
100
 
101
- There are two ways to use this history:
101
+ You can use this history in two ways:
102
102
 
103
103
  - **Automatic inclusion** - Mastra automatically fetches and includes recent messages in the context window. By default, it includes the last 10 messages, keeping agents grounded in the conversation. You can adjust this number with `lastMessages`, but in most cases you don't need to think about it.
104
104
  - [**Manual querying**](#querying) - For more control, use the `recall()` function to query threads and messages directly. This lets you choose exactly which memories are included in the context window, or fetch messages to render conversation history in your UI.
@@ -118,7 +118,7 @@ The `Memory` instance gives you access to functions for listing threads, recalli
118
118
 
119
119
  Use these methods to fetch threads and messages for displaying conversation history in your UI or for custom memory retrieval logic.
120
120
 
121
- > **Warning:** The memory system does not enforce access control. Before running any query, verify in your application logic that the current user is authorized to access the `resourceId` being queried.
121
+ > **Warning:** The memory system doesn't enforce access control. Before running any query, verify in your application logic that the current user is authorized to access the `resourceId` being queried.
122
122
 
123
123
  ### Threads
124
124
 
@@ -61,6 +61,10 @@ OM solves both problems by compressing old context into dense observations.
61
61
 
62
62
  When message history tokens exceed a threshold (default: 30,000), the Observer creates observations — concise notes about what happened:
63
63
 
64
+ Image parts contribute to this threshold with model-aware estimates, so multimodal conversations trigger observation at the right time. The same applies to image-like `file` parts when a transport normalizes an uploaded image as a file instead of an image part. For example, OpenAI image detail settings can materially change when OM decides to observe.
65
+
66
+ The Observer can also see attachments in the history it reviews. OM keeps readable placeholders like `[Image #1: reference-board.png]` or `[File #1: floorplan.pdf]` in the transcript for readability, and forwards the actual attachment parts alongside the text. Image-like `file` parts are upgraded to image inputs for the Observer when possible, while non-image attachments are forwarded as file parts with normalized token counting. This applies to both normal thread observation and batched resource-scope observation.
67
+
64
68
  ```text
65
69
  Date: 2026-01-15
66
70
  - 🔴 12:10 User is building a Next.js app with Supabase auth, due in 1 week (meaning January 22nd 2026)
@@ -177,7 +181,7 @@ OM caches tiktoken part estimates in message metadata to reduce repeat counting
177
181
  - Per-part estimates are stored on `part.providerMetadata.mastra` and reused on subsequent passes when the cache version/tokenizer source matches.
178
182
  - For string-only message content (without parts), OM uses a message-level metadata fallback cache.
179
183
  - Message and conversation overhead are still recalculated on every pass. The cache only stores payload estimates, so counting semantics stay the same.
180
- - `data-*` and `reasoning` parts are still skipped and are not cached.
184
+ - `data-*` and `reasoning` parts are still skipped and aren't cached.
181
185
 
182
186
  ## Async Buffering
183
187
 
@@ -224,7 +228,7 @@ const memory = new Memory({
224
228
 
225
229
  Setting `bufferTokens: false` disables both observation and reflection async buffering. See [async buffering configuration](https://mastra.ai/reference/memory/observational-memory) for the full API.
226
230
 
227
- > **Note:** Async buffering is not supported with `scope: 'resource'`. It is automatically disabled in resource scope.
231
+ > **Note:** Async buffering isn't supported with `scope: 'resource'`. It's automatically disabled in resource scope.
228
232
 
229
233
  ## Migrating existing threads
230
234
 
@@ -35,7 +35,7 @@ const agent = new Agent({
35
35
 
36
36
  ## Using the recall() Method
37
37
 
38
- While `listMessages` retrieves messages by thread ID with basic pagination, [`recall()`](https://mastra.ai/reference/memory/recall) adds support for **semantic search**. When you need to find messages by meaning rather than just recency, use `recall()` with a `vectorSearchString`:
38
+ While `listMessages` retrieves messages by thread ID with basic pagination, [`recall()`](https://mastra.ai/reference/memory/recall) adds support for **semantic search**. When you need to find messages by meaning rather than recency, use `recall()` with a `vectorSearchString`:
39
39
 
40
40
  ```typescript
41
41
  const memory = await agent.getMemory()
@@ -264,7 +264,7 @@ For detailed information about index configuration options and performance tunin
264
264
 
265
265
  ## Disabling
266
266
 
267
- There is a performance impact to using semantic recall. New messages are converted into embeddings and used to query a vector database before new messages are sent to the LLM.
267
+ Semantic recall has a performance impact. New messages are converted into embeddings and used to query a vector database before new messages are sent to the LLM.
268
268
 
269
269
  Semantic recall is enabled by default but can be disabled when not needed:
270
270
 
@@ -170,7 +170,7 @@ export const agent = new Agent({
170
170
  })
171
171
  ```
172
172
 
173
- Title generation runs asynchronously after the agent responds and does not affect response time.
173
+ Title generation runs asynchronously after the agent responds and doesn't affect response time.
174
174
 
175
175
  To optimize cost or behavior, provide a smaller [`model`](https://mastra.ai/models) and custom `instructions`:
176
176
 
@@ -170,11 +170,11 @@ const memory = new Memory({
170
170
 
171
171
  ## Designing Effective Templates
172
172
 
173
- A well-structured template keeps the information easy for the agent to parse and update. Treat the template as a short form that you want the assistant to keep up to date.
173
+ A well-structured template keeps the information straightforward for the agent to parse and update. Treat the template as a short form that you want the assistant to keep up to date.
174
174
 
175
- - **Short, focused labels.** Avoid paragraphs or very long headings. Keep labels brief (for example `## Personal Info` or `- Name:`) so updates are easy to read and less likely to be truncated.
175
+ - **Short, focused labels.** Avoid paragraphs or very long headings. Keep labels brief (for example `## Personal Info` or `- Name:`) so updates are readable and less likely to be truncated.
176
176
  - **Use consistent casing.** Inconsistent capitalization (`Timezone:` vs `timezone:`) can cause messy updates. Stick to Title Case or lower case for headings and bullet labels.
177
- - **Keep placeholder text simple.** Use hints such as `[e.g., Formal]` or `[Date]` to help the LLM fill in the correct spots.
177
+ - **Keep placeholder text minimal.** Use hints such as `[e.g., Formal]` or `[Date]` to help the LLM fill in the correct spots.
178
178
  - **Abbreviate very long values.** If you only need a short form, include guidance like `- Name: [First name or nickname]` or `- Address (short):` rather than the full legal text.
179
179
  - **Mention update rules in `instructions`.** You can instruct how and when to fill or clear parts of the template directly in the agent's `instructions` field.
180
180
 
@@ -263,13 +263,13 @@ Schema-based working memory uses **merge semantics**, meaning the agent only nee
263
263
 
264
264
  - **Object fields are deep merged:** Only provided fields are updated; others remain unchanged
265
265
  - **Set a field to `null` to delete it:** This explicitly removes the field from memory
266
- - **Arrays are replaced entirely:** When an array field is provided, it replaces the existing array (arrays are not merged element-by-element)
266
+ - **Arrays are replaced entirely:** When an array field is provided, it replaces the existing array (arrays aren't merged element-by-element)
267
267
 
268
268
  ## Choosing Between Template and Schema
269
269
 
270
270
  - Use a **template** (Markdown) if you want the agent to maintain memory as a free-form text block, such as a user profile or scratchpad. Templates use **replace semantics** — the agent must provide the complete memory content on each update.
271
271
  - Use a **schema** if you need structured, type-safe data that can be validated and programmatically accessed as JSON. Schemas use **merge semantics** — the agent only provides fields to update, and existing fields are preserved.
272
- - Only one mode can be active at a time: setting both `template` and `schema` is not supported.
272
+ - Only one mode can be active at a time: setting both `template` and `schema` isn't supported.
273
273
 
274
274
  ## Example: Multi-step Retention
275
275
 
@@ -301,7 +301,7 @@ Below is a simplified view of how the `User Profile` template updates across a s
301
301
 
302
302
  The agent can now refer to `Sam` or `Berlin` in later responses without requesting the information again because it has been stored in working memory.
303
303
 
304
- If your agent is not properly updating working memory when you expect it to, you can add system instructions on _how_ and _when_ to use this template in your agent's `instructions` setting.
304
+ If your agent isn't properly updating working memory when you expect it to, you can add system instructions on _how_ and _when_ to use this template in your agent's `instructions` setting.
305
305
 
306
306
  ## Setting Initial Working Memory
307
307
 
@@ -135,4 +135,4 @@ When [Observational Memory](https://mastra.ai/docs/memory/observational-memory)
135
135
  - **Resource-scoped OM (same `resourceId`)**: The OM record is shared between the source and cloned threads since they belong to the same resource. No duplication occurs.
136
136
  - **Resource-scoped OM (different `resourceId`)**: The OM record is cloned to the new resource. Message IDs are remapped and any thread-identifying tags within observations are updated to reference the cloned thread.
137
137
 
138
- Only the current (most recent) OM generation is cloned — older history generations are not copied. Transient processing state (observation/reflection in-progress flags) is reset on the cloned record.
138
+ Only the current (most recent) OM generation is cloned — older history generations aren't copied. Transient processing state (observation/reflection in-progress flags) is reset on the cloned record.
@@ -26,6 +26,8 @@ export const agent = new Agent({
26
26
 
27
27
  The `observationalMemory` option accepts `true`, a configuration object, or `false`. Setting `true` enables OM with `google/gemini-2.5-flash` as the default model. When passing a config object, a `model` must be explicitly set — either at the top level, or on `observation.model` and/or `reflection.model`.
28
28
 
29
+ Observer input is multimodal-aware. OM keeps text placeholders like `[Image #1: screenshot.png]` in the transcript it builds for the Observer, and also sends the underlying image parts when possible. This applies to both single-thread observation and batched multi-thread observation. Non-image files appear as placeholders only.
30
+
29
31
  **enabled** (`boolean`): Enable or disable Observational Memory. When omitted from a config object, defaults to \`true\`. Only \`enabled: false\` explicitly disables it. (Default: `true`)
30
32
 
31
33
  **model** (`string | LanguageModel | DynamicModel | ModelWithRetries[]`): Model for both the Observer and Reflector agents. Sets the model for both at once. Cannot be used together with \`observation.model\` or \`reflection.model\` — an error will be thrown if both are set. When using \`observationalMemory: true\`, defaults to \`google/gemini-2.5-flash\`. When passing a config object, this or \`observation.model\`/\`reflection.model\` must be set. Use \`"default"\` to explicitly use the default model (\`google/gemini-2.5-flash\`). (Default: `'google/gemini-2.5-flash' (when using observationalMemory: true)`)
@@ -40,7 +42,7 @@ The `observationalMemory` option accepts `true`, a configuration object, or `fal
40
42
 
41
43
  **observation.instruction** (`string`): Custom instruction appended to the Observer's system prompt. Use this to customize what the Observer focuses on, such as domain-specific preferences or priorities.
42
44
 
43
- **observation.messageTokens** (`number`): Token count of unobserved messages that triggers observation. When unobserved message tokens exceed this threshold, the Observer agent is called.
45
+ **observation.messageTokens** (`number`): Token count of unobserved messages that triggers observation. When unobserved message tokens exceed this threshold, the Observer agent is called. Image parts are included with model-aware estimates when possible, with deterministic fallbacks when image metadata is incomplete. Image-like \`file\` parts are counted the same way when uploads are normalized as files.
44
46
 
45
47
  **observation.maxTokensPerBatch** (`number`): Maximum tokens per batch when observing multiple threads in resource scope. Threads are chunked into batches of this size and processed in parallel. Lower values mean more parallelism but more API calls.
46
48
 
@@ -80,9 +82,9 @@ OM persists token payload estimates so repeated counting can reuse prior tiktoke
80
82
 
81
83
  - Part-level cache: `part.providerMetadata.mastra`.
82
84
  - String-content fallback cache: message-level metadata when no parts exist.
83
- - Cache entries are ignored and recomputed if cache version/tokenizer source does not match.
84
- - Per-message and per-conversation overhead are always recomputed at runtime and are not cached.
85
- - `data-*` and `reasoning` parts are skipped and do not receive cache entries.
85
+ - Cache entries are ignored and recomputed if cache version/tokenizer source doesn't match.
86
+ - Per-message and per-conversation overhead are always recomputed at runtime and aren't cached.
87
+ - `data-*` and `reasoning` parts are skipped and don't receive cache entries.
86
88
 
87
89
  ## Examples
88
90
 
@@ -283,7 +285,7 @@ observationalMemory: {
283
285
 
284
286
  Setting `bufferTokens: false` disables both observation and reflection async buffering. Observations and reflections will run synchronously when their thresholds are reached.
285
287
 
286
- > **Note:** Async buffering is not supported with `scope: 'resource'` and is automatically disabled in resource scope.
288
+ > **Note:** Async buffering isn't supported with `scope: 'resource'` and is automatically disabled in resource scope.
287
289
 
288
290
  ## Streaming data parts
289
291
 
@@ -47,8 +47,8 @@ const processor = new TokenLimiterProcessor({
47
47
 
48
48
  When used as an input processor, `TokenLimiterProcessor` throws a `TripWire` error in the following cases:
49
49
 
50
- - **Empty messages**: If there are no messages to process, a TripWire is thrown because you cannot send an LLM request with no messages.
51
- - **System messages exceed limit**: If system messages alone exceed the token limit, a TripWire is thrown because you cannot send an LLM request with only system messages and no user/assistant messages.
50
+ - **Empty messages**: If there are no messages to process, a TripWire is thrown because you can't send an LLM request with no messages.
51
+ - **System messages exceed limit**: If system messages alone exceed the token limit, a TripWire is thrown because you can't send an LLM request with only system messages and no user/assistant messages.
52
52
 
53
53
  ```typescript
54
54
  import { TripWire } from '@mastra/core/agent'
@@ -2,7 +2,7 @@
2
2
 
3
3
  The DynamoDB storage implementation provides a scalable and performant NoSQL database solution for Mastra, leveraging a single-table design pattern with [ElectroDB](https://electrodb.dev/).
4
4
 
5
- > **Observability Not Supported:** DynamoDB storage **does not support the observability domain**. Traces from the `DefaultExporter` cannot be persisted to DynamoDB, and Mastra Studio's observability features won't work with DynamoDB as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to a supported provider like ClickHouse or PostgreSQL.
5
+ > **Observability Not Supported:** DynamoDB storage **doesn't support the observability domain**. Traces from the `DefaultExporter` can't be persisted to DynamoDB, and Mastra Studio's observability features won't work with DynamoDB as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to a supported provider like ClickHouse or PostgreSQL.
6
6
 
7
7
  > **Item Size Limit:** DynamoDB enforces a **400 KB maximum item size**. This limit can be exceeded when storing messages with base64-encoded attachments such as images. See [Handling large attachments](https://mastra.ai/docs/memory/storage) for workarounds including uploading attachments to external storage.
8
8
 
@@ -211,7 +211,7 @@ aws dynamodb update-time-to-live \
211
211
  1. Go to the DynamoDB console
212
212
  2. Select your table
213
213
  3. Go to "Additional settings" tab
214
- 4. Under "Time to Live (TTL)", click "Manage TTL"
214
+ 4. Under "Time to Live (TTL)", select "Manage TTL"
215
215
  5. Enable TTL and specify the attribute name (default: `ttl`)
216
216
 
217
217
  > **Note:** DynamoDB deletes expired items within 48 hours after expiration. Items remain queryable until actually deleted.
@@ -136,7 +136,7 @@ const memoryStore = await storage.getStore('memory')
136
136
  const thread = await memoryStore?.getThreadById({ threadId: '...' })
137
137
  ```
138
138
 
139
- > **Warning:** If `init()` is not called, collections won't be created and storage operations will fail silently or throw errors.
139
+ > **Warning:** If `init()` isn't called, collections won't be created and storage operations will fail silently or throw errors.
140
140
 
141
141
  ## Vector Search Capabilities
142
142
 
@@ -177,7 +177,7 @@ const memoryStore = await storage.getStore('memory')
177
177
  const thread = await memoryStore?.getThreadById({ threadId: '...' })
178
178
  ```
179
179
 
180
- > **Warning:** If `init()` is not called, tables won't be created and storage operations will fail silently or throw errors.
180
+ > **Warning:** If `init()` isn't called, tables won't be created and storage operations will fail silently or throw errors.
181
181
 
182
182
  ### Using an Existing Pool
183
183
 
@@ -201,7 +201,7 @@ const storage = new PostgresStore({
201
201
 
202
202
  **Pool lifecycle behavior:**
203
203
 
204
- - When you **provide a pool**: Mastra uses your pool but does **not** close it when `store.close()` is called. You manage the pool lifecycle.
204
+ - When you **provide a pool**: Mastra uses your pool but **doesn't** close it when `store.close()` is called. You manage the pool lifecycle.
205
205
  - When Mastra **creates a pool**: Mastra owns the pool and will close it when `store.close()` is called.
206
206
 
207
207
  ### Direct Database and Pool Access
@@ -4,7 +4,7 @@ The Upstash storage implementation provides a serverless-friendly storage soluti
4
4
 
5
5
  > **Pricing:** When using Mastra with Upstash, the pay-as-you-go model can result in unexpectedly high costs due to the high volume of Redis commands generated during agent conversations. We strongly recommend using a **fixed pricing plan** for predictable costs. See [Upstash pricing](https://upstash.com/pricing/redis) for details and [GitHub issue #5850](https://github.com/mastra-ai/mastra/issues/5850) for context.
6
6
 
7
- > **Observability Not Supported:** Upstash storage **does not support the observability domain**. Traces from the `DefaultExporter` cannot be persisted to Upstash, and Mastra Studio's observability features won't work with Upstash as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to a supported provider like ClickHouse or PostgreSQL.
7
+ > **Observability Not Supported:** Upstash storage **doesn't support the observability domain**. Traces from the `DefaultExporter` can't be persisted to Upstash, and Mastra Studio's observability features won't work with Upstash as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to a supported provider like ClickHouse or PostgreSQL.
8
8
 
9
9
  ## Installation
10
10
 
@@ -82,6 +82,8 @@ const vectorStore = new PgVector({
82
82
 
83
83
  **buildIndex** (`boolean`): Whether to build the index (Default: `true`)
84
84
 
85
+ **metadataIndexes** (`string[]`): Array of metadata field names to create btree indexes on. Improves query performance when filtering by these metadata fields.
86
+
85
87
  #### IndexConfig
86
88
 
87
89
  **type** (`'flat' | 'hnsw' | 'ivfflat'`): Index type (Default: `ivfflat`)
package/dist/index.cjs CHANGED
@@ -9,11 +9,11 @@ var agent = require('@mastra/core/agent');
9
9
  var features = require('@mastra/core/features');
10
10
  var memory = require('@mastra/core/memory');
11
11
  var utils = require('@mastra/core/utils');
12
- var zodToJson = require('@mastra/schema-compat/zod-to-json');
12
+ var schema = require('@mastra/schema-compat/schema');
13
13
  var asyncMutex = require('async-mutex');
14
14
  var xxhash = require('xxhash-wasm');
15
+ var schema$1 = require('@mastra/core/schema');
15
16
  var tools = require('@mastra/core/tools');
16
- var schemaCompat = require('@mastra/schema-compat');
17
17
  var processors = require('@mastra/core/processors');
18
18
 
19
19
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -15147,19 +15147,26 @@ function deepMergeWorkingMemory(existing, update) {
15147
15147
  return result;
15148
15148
  }
15149
15149
  var updateWorkingMemoryTool = (memoryConfig) => {
15150
- const schema = memoryConfig?.workingMemory?.schema;
15150
+ const schema$2 = memoryConfig?.workingMemory?.schema;
15151
15151
  let inputSchema = zod.z.object({
15152
15152
  memory: zod.z.string().describe(`The Markdown formatted working memory content to store. This MUST be a string. Never pass an object.`)
15153
15153
  });
15154
- if (schema) {
15155
- inputSchema = zod.z.object({
15156
- memory: schema instanceof zod.ZodObject ? schema : schemaCompat.convertSchemaToZod({ jsonSchema: schema }).describe(
15157
- `The JSON formatted working memory content to store.`
15158
- )
15154
+ if (schema$2) {
15155
+ const standardSchema2 = schema$1.isStandardSchemaWithJSON(schema$2) ? schema$2 : schema$1.toStandardSchema(schema$2);
15156
+ const jsonSchema4 = schema.standardSchemaToJSONSchema(standardSchema2, { io: "input" });
15157
+ delete jsonSchema4.$schema;
15158
+ inputSchema = schema$1.toStandardSchema({
15159
+ $schema: "http://json-schema.org/draft-07/schema#",
15160
+ type: "object",
15161
+ description: "The JSON formatted working memory content to store.",
15162
+ properties: {
15163
+ memory: jsonSchema4
15164
+ },
15165
+ required: ["memory"]
15159
15166
  });
15160
15167
  }
15161
- const usesMergeSemantics = Boolean(schema);
15162
- const description = schema ? `Update the working memory with new information. Data is merged with existing memory - you only need to include fields you want to add or update. Set a field to null to remove it. Arrays are replaced entirely when provided.` : `Update the working memory with new information. Any data not included will be overwritten. Always pass data as string to the memory field. Never pass an object.`;
15168
+ const usesMergeSemantics = Boolean(schema$2);
15169
+ const description = schema$2 ? `Update the working memory with new information. Data is merged with existing memory - you only need to include fields you want to add or update. Set a field to null to remove it. Arrays are replaced entirely when provided.` : `Update the working memory with new information. Any data not included will be overwritten. Always pass data as string to the memory field. Never pass an object.`;
15163
15170
  return tools.createTool({
15164
15171
  id: "update-working-memory",
15165
15172
  description,
@@ -15206,26 +15213,28 @@ var updateWorkingMemoryTool = (memoryConfig) => {
15206
15213
  existingData = null;
15207
15214
  }
15208
15215
  }
15209
- if (inputData.memory === void 0 || inputData.memory === null) {
15216
+ const memoryInput = inputData.memory;
15217
+ if (memoryInput === void 0 || memoryInput === null) {
15210
15218
  return { success: true, message: "No memory data provided, existing memory unchanged." };
15211
15219
  }
15212
15220
  let newData;
15213
- if (typeof inputData.memory === "string") {
15221
+ if (typeof memoryInput === "string") {
15214
15222
  try {
15215
- newData = JSON.parse(inputData.memory);
15223
+ newData = JSON.parse(memoryInput);
15216
15224
  } catch (parseError) {
15217
15225
  const errorMessage = parseError instanceof Error ? parseError.message : String(parseError);
15218
15226
  throw new Error(
15219
- `Failed to parse working memory input as JSON: ${errorMessage}. Raw input: ${inputData.memory.length > 500 ? inputData.memory.slice(0, 500) + "..." : inputData.memory}`
15227
+ `Failed to parse working memory input as JSON: ${errorMessage}. Raw input: ${memoryInput.length > 500 ? memoryInput.slice(0, 500) + "..." : memoryInput}`
15220
15228
  );
15221
15229
  }
15222
15230
  } else {
15223
- newData = inputData.memory;
15231
+ newData = memoryInput;
15224
15232
  }
15225
15233
  const mergedData = deepMergeWorkingMemory(existingData, newData);
15226
15234
  workingMemory = JSON.stringify(mergedData);
15227
15235
  } else {
15228
- workingMemory = typeof inputData.memory === "string" ? inputData.memory : JSON.stringify(inputData.memory);
15236
+ const memoryInput = inputData.memory;
15237
+ workingMemory = typeof memoryInput === "string" ? memoryInput : JSON.stringify(memoryInput);
15229
15238
  const existingRaw = await memory.getWorkingMemory({
15230
15239
  threadId,
15231
15240
  resourceId,
@@ -15336,7 +15345,6 @@ var CHARS_PER_TOKEN = 4;
15336
15345
  var DEFAULT_MESSAGE_RANGE = { before: 1, after: 1 };
15337
15346
  var DEFAULT_TOP_K = 4;
15338
15347
  var VECTOR_DELETE_BATCH_SIZE = 100;
15339
- var isZodObject = (v) => v instanceof zod.ZodObject;
15340
15348
  var Memory = class extends memory.MastraMemory {
15341
15349
  constructor(config = {}) {
15342
15350
  super({ name: "Memory", ...config });
@@ -15383,6 +15391,7 @@ var Memory = class extends memory.MastraMemory {
15383
15391
  const config = this.getMergedThreadConfig(threadConfig || {});
15384
15392
  if (resourceId) await this.validateThreadIsOwnedByResource(threadId, resourceId, config);
15385
15393
  const perPage = perPageArg !== void 0 ? perPageArg : config.lastMessages;
15394
+ const historyDisabledByConfig = config.lastMessages === false && perPageArg === void 0;
15386
15395
  const shouldGetNewestAndReverse = !orderBy && perPage !== false;
15387
15396
  const effectiveOrderBy = shouldGetNewestAndReverse ? { field: "createdAt", direction: "DESC" } : orderBy;
15388
15397
  const vectorResults = [];
@@ -15393,7 +15402,8 @@ var Memory = class extends memory.MastraMemory {
15393
15402
  orderBy: effectiveOrderBy,
15394
15403
  hasWorkingMemorySchema: Boolean(config.workingMemory?.schema),
15395
15404
  workingMemoryEnabled: config.workingMemory?.enabled,
15396
- semanticRecallEnabled: Boolean(config.semanticRecall)
15405
+ semanticRecallEnabled: Boolean(config.semanticRecall),
15406
+ historyDisabledByConfig
15397
15407
  });
15398
15408
  const defaultRange = DEFAULT_MESSAGE_RANGE;
15399
15409
  const defaultTopK = DEFAULT_TOP_K;
@@ -15411,6 +15421,9 @@ var Memory = class extends memory.MastraMemory {
15411
15421
  );
15412
15422
  }
15413
15423
  let usage;
15424
+ if (historyDisabledByConfig && (!config.semanticRecall || !vectorSearchString || !this.vector)) {
15425
+ return { messages: [], usage: void 0, total: 0, page: page ?? 0, perPage: 0, hasMore: false };
15426
+ }
15414
15427
  if (config?.semanticRecall && vectorSearchString && this.vector) {
15415
15428
  const result = await this.embedMessageContent(vectorSearchString);
15416
15429
  usage = result.usage;
@@ -15439,10 +15452,11 @@ var Memory = class extends memory.MastraMemory {
15439
15452
  );
15440
15453
  }
15441
15454
  const memoryStore = await this.getMemoryStore();
15455
+ const effectivePerPage = historyDisabledByConfig ? 0 : perPage;
15442
15456
  const paginatedResult = await memoryStore.listMessages({
15443
15457
  threadId,
15444
15458
  resourceId,
15445
- perPage,
15459
+ perPage: effectivePerPage,
15446
15460
  page,
15447
15461
  orderBy: effectiveOrderBy,
15448
15462
  filter: filter3,
@@ -15868,7 +15882,10 @@ ${workingMemory}`;
15868
15882
  return part;
15869
15883
  });
15870
15884
  if (newMessage.content.parts.length === 0) {
15871
- return null;
15885
+ const hasContentText = typeof newMessage.content.content === "string" && newMessage.content.content.trim().length > 0;
15886
+ if (!hasContentText) {
15887
+ return null;
15888
+ }
15872
15889
  }
15873
15890
  }
15874
15891
  return newMessage;
@@ -15923,12 +15940,13 @@ ${workingMemory}`;
15923
15940
  }
15924
15941
  if (config.workingMemory?.schema) {
15925
15942
  try {
15926
- const schema = config.workingMemory.schema;
15943
+ const schema$1 = config.workingMemory.schema;
15927
15944
  let convertedSchema;
15928
- if (isZodObject(schema)) {
15929
- convertedSchema = zodToJson.zodToJsonSchema(schema);
15945
+ if (schema.isStandardSchemaWithJSON(schema$1)) {
15946
+ convertedSchema = schema$1["~standard"].jsonSchema.output({ target: "draft-07" });
15930
15947
  } else {
15931
- convertedSchema = schema;
15948
+ const standardSchema2 = schema.toStandardSchema(schema$1);
15949
+ convertedSchema = standardSchema2["~standard"].jsonSchema.output({ target: "draft-07" });
15932
15950
  }
15933
15951
  return { format: "json", content: JSON.stringify(convertedSchema) };
15934
15952
  } catch (error) {
@@ -16665,7 +16683,12 @@ Notes:
16665
16683
  "Observational memory async buffering is enabled by default but the installed version of @mastra/core does not support it. Either upgrade @mastra/core, @mastra/memory, and your storage adapter (@mastra/libsql, @mastra/pg, or @mastra/mongodb) to the latest version, or explicitly disable async buffering by setting `observation: { bufferTokens: false }` in your observationalMemory config."
16666
16684
  );
16667
16685
  }
16668
- const { ObservationalMemory } = await import('./observational-memory-AHVELJX4.cjs');
16686
+ if (!features.coreFeatures.has("request-response-id-rotation")) {
16687
+ throw new Error(
16688
+ "Observational memory requires @mastra/core support for request-response-id-rotation. Please bump @mastra/core to a newer version."
16689
+ );
16690
+ }
16691
+ const { ObservationalMemory } = await import('./observational-memory-C5LO7RBR.cjs');
16669
16692
  return new ObservationalMemory({
16670
16693
  storage: memoryStore,
16671
16694
  scope: omConfig.scope,