@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.
- package/CHANGELOG.md +26 -0
- package/dist/{chunk-GBBQIJQF.js → chunk-3CM4XQJO.js} +1940 -463
- package/dist/chunk-3CM4XQJO.js.map +1 -0
- package/dist/{chunk-D6II7EP4.cjs → chunk-5W5463NI.cjs} +1939 -461
- package/dist/chunk-5W5463NI.cjs.map +1 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +25 -25
- package/dist/docs/references/docs-agents-agent-memory.md +2 -2
- package/dist/docs/references/docs-agents-network-approval.md +4 -1
- package/dist/docs/references/docs-agents-networks.md +1 -1
- package/dist/docs/references/docs-memory-memory-processors.md +1 -1
- package/dist/docs/references/docs-memory-message-history.md +2 -2
- package/dist/docs/references/docs-memory-observational-memory.md +6 -2
- package/dist/docs/references/docs-memory-semantic-recall.md +2 -2
- package/dist/docs/references/docs-memory-storage.md +1 -1
- package/dist/docs/references/docs-memory-working-memory.md +6 -6
- package/dist/docs/references/reference-memory-cloneThread.md +1 -1
- package/dist/docs/references/reference-memory-observational-memory.md +7 -5
- package/dist/docs/references/reference-processors-token-limiter-processor.md +2 -2
- package/dist/docs/references/reference-storage-dynamodb.md +2 -2
- package/dist/docs/references/reference-storage-mongodb.md +1 -1
- package/dist/docs/references/reference-storage-postgresql.md +2 -2
- package/dist/docs/references/reference-storage-upstash.md +1 -1
- package/dist/docs/references/reference-vectors-pg.md +2 -0
- package/dist/index.cjs +48 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -21
- package/dist/index.js.map +1 -1
- package/dist/{observational-memory-AHVELJX4.cjs → observational-memory-C5LO7RBR.cjs} +17 -17
- package/dist/{observational-memory-AHVELJX4.cjs.map → observational-memory-C5LO7RBR.cjs.map} +1 -1
- package/dist/{observational-memory-QFQUF5EY.js → observational-memory-OYK4MEUD.js} +3 -3
- package/dist/{observational-memory-QFQUF5EY.js.map → observational-memory-OYK4MEUD.js.map} +1 -1
- package/dist/processors/index.cjs +15 -15
- package/dist/processors/index.js +1 -1
- package/dist/processors/observational-memory/observational-memory.d.ts +33 -2
- package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
- package/dist/processors/observational-memory/observer-agent.d.ts +7 -4
- package/dist/processors/observational-memory/observer-agent.d.ts.map +1 -1
- package/dist/processors/observational-memory/repro-capture.d.ts +23 -0
- package/dist/processors/observational-memory/repro-capture.d.ts.map +1 -0
- package/dist/processors/observational-memory/token-counter.d.ts +28 -3
- package/dist/processors/observational-memory/token-counter.d.ts.map +1 -1
- package/dist/tools/working-memory.d.ts +6 -10
- package/dist/tools/working-memory.d.ts.map +1 -1
- package/package.json +13 -8
- package/dist/chunk-D6II7EP4.cjs.map +0 -1
- package/dist/chunk-GBBQIJQF.js.map +0 -1
package/dist/docs/SKILL.md
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.6.
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
23
|
+
"implementation": "dist/chunk-3CM4XQJO.js"
|
|
24
24
|
},
|
|
25
25
|
"ObservationalMemory": {
|
|
26
26
|
"types": "dist/processors/index.d.ts",
|
|
27
|
-
"implementation": "dist/chunk-
|
|
28
|
-
"line":
|
|
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-
|
|
33
|
-
"line":
|
|
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-
|
|
38
|
-
"line":
|
|
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-
|
|
43
|
-
"line":
|
|
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-
|
|
48
|
-
"line":
|
|
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-
|
|
53
|
-
"line":
|
|
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-
|
|
58
|
-
"line":
|
|
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-
|
|
63
|
-
"line":
|
|
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-
|
|
68
|
-
"line":
|
|
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-
|
|
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
|
|
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
|
|
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
|
-
- [
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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`
|
|
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
|
|
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
|
|
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
|
|
84
|
-
- Per-message and per-conversation overhead are always recomputed at runtime and
|
|
85
|
-
- `data-*` and `reasoning` parts are skipped and
|
|
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
|
|
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
|
|
51
|
-
- **System messages exceed limit**: If system messages alone exceed the token limit, a TripWire is thrown because you
|
|
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 **
|
|
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)",
|
|
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()`
|
|
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()`
|
|
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
|
|
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 **
|
|
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
|
|
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
|
-
|
|
15156
|
-
|
|
15157
|
-
|
|
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
|
-
|
|
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
|
|
15221
|
+
if (typeof memoryInput === "string") {
|
|
15214
15222
|
try {
|
|
15215
|
-
newData = JSON.parse(
|
|
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: ${
|
|
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 =
|
|
15231
|
+
newData = memoryInput;
|
|
15224
15232
|
}
|
|
15225
15233
|
const mergedData = deepMergeWorkingMemory(existingData, newData);
|
|
15226
15234
|
workingMemory = JSON.stringify(mergedData);
|
|
15227
15235
|
} else {
|
|
15228
|
-
|
|
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
|
-
|
|
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 (
|
|
15929
|
-
convertedSchema =
|
|
15945
|
+
if (schema.isStandardSchemaWithJSON(schema$1)) {
|
|
15946
|
+
convertedSchema = schema$1["~standard"].jsonSchema.output({ target: "draft-07" });
|
|
15930
15947
|
} else {
|
|
15931
|
-
|
|
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
|
-
|
|
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,
|