@mastra/pg 1.0.0 → 1.1.0-alpha.1

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 CHANGED
@@ -1,5 +1,107 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 1.1.0-alpha.1
4
+
5
+ ### Minor Changes
6
+
7
+ - Restructured stored agents to use a thin metadata record with versioned configuration snapshots. ([#12488](https://github.com/mastra-ai/mastra/pull/12488))
8
+
9
+ The agent record now only stores metadata fields (id, status, activeVersionId, authorId, metadata, timestamps). All configuration fields (name, instructions, model, tools, etc.) live exclusively in version snapshot rows, enabling full version history and rollback.
10
+
11
+ **Key changes:**
12
+ - Stored Agent records are now thin metadata-only (StorageAgentType)
13
+ - All config lives in version snapshots (StorageAgentSnapshotType)
14
+ - New resolved type (StorageResolvedAgentType) merges agent record + active version config
15
+ - Renamed `ownerId` to `authorId` for multi-tenant filtering
16
+ - Changed `memory` field type from `string` to `Record<string, unknown>`
17
+ - Added `status` field ('draft' | 'published') to agent records
18
+ - Flattened CreateAgent/UpdateAgent input types (config fields at top level, no nested snapshot)
19
+ - Version config columns are top-level in the agent_versions table (no single snapshot jsonb column)
20
+ - List endpoints return resolved agents (thin record + active version config)
21
+ - Auto-versioning on update with retention limits and race condition handling
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies [[`b99ceac`](https://github.com/mastra-ai/mastra/commit/b99ceace2c830dbdef47c8692d56a91954aefea2), [`deea43e`](https://github.com/mastra-ai/mastra/commit/deea43eb1366d03a864c5e597d16a48592b9893f), [`ac9ec66`](https://github.com/mastra-ai/mastra/commit/ac9ec6672779b2e6d4344e415481d1a6a7d4911a)]:
26
+ - @mastra/core@1.1.0-alpha.1
27
+
28
+ ## 1.1.0-alpha.0
29
+
30
+ ### Minor Changes
31
+
32
+ - Added dynamic agent management with CRUD operations and version tracking ([#12038](https://github.com/mastra-ai/mastra/pull/12038))
33
+
34
+ **New Features:**
35
+ - Create, edit, and delete agents directly from the Mastra Studio UI
36
+ - Full version history for agents with compare and restore capabilities
37
+ - Visual diff viewer to compare agent configurations across versions
38
+ - Agent creation modal with comprehensive configuration options (model selection, instructions, tools, workflows, sub-agents, memory)
39
+ - AI-powered instruction enhancement
40
+
41
+ **Storage:**
42
+ - New storage interfaces for stored agents and agent versions
43
+ - PostgreSQL, LibSQL, and MongoDB implementations included
44
+ - In-memory storage for development and testing
45
+
46
+ **API:**
47
+ - RESTful endpoints for agent CRUD operations
48
+ - Version management endpoints (create, list, activate, restore, delete, compare)
49
+ - Automatic versioning on agent updates when enabled
50
+
51
+ **Client SDK:**
52
+ - JavaScript client with full support for stored agents and versions
53
+ - Type-safe methods for all CRUD and version operations
54
+
55
+ **Usage Example:**
56
+
57
+ ```typescript
58
+ // Server-side: Configure storage
59
+ import { Mastra } from '@mastra/core';
60
+ import { PgAgentsStorage } from '@mastra/pg';
61
+
62
+ const mastra = new Mastra({
63
+ agents: { agentOne },
64
+ storage: {
65
+ agents: new PgAgentsStorage({
66
+ connectionString: process.env.DATABASE_URL,
67
+ }),
68
+ },
69
+ });
70
+
71
+ // Client-side: Use the SDK
72
+ import { MastraClient } from '@mastra/client-js';
73
+
74
+ const client = new MastraClient({ baseUrl: 'http://localhost:3000' });
75
+
76
+ // Create a stored agent
77
+ const agent = await client.createStoredAgent({
78
+ name: 'Customer Support Agent',
79
+ description: 'Handles customer inquiries',
80
+ model: { provider: 'ANTHROPIC', name: 'claude-sonnet-4-5' },
81
+ instructions: 'You are a helpful customer support agent...',
82
+ tools: ['search', 'email'],
83
+ });
84
+
85
+ // Create a version snapshot
86
+ await client.storedAgent(agent.id).createVersion({
87
+ name: 'v1.0 - Initial release',
88
+ changeMessage: 'First production version',
89
+ });
90
+
91
+ // Compare versions
92
+ const diff = await client.storedAgent(agent.id).compareVersions('version-1', 'version-2');
93
+ ```
94
+
95
+ **Why:**
96
+ This feature enables teams to manage agents dynamically without code changes, making it easier to iterate on agent configurations and maintain a complete audit trail of changes.
97
+
98
+ - Added `status` field to `listTraces` response. The status field indicates the trace state: `success` (completed without error), `error` (has error), or `running` (still in progress). This makes it easier to filter and display traces by their current state without having to derive it from the `error` and `endedAt` fields. ([#12213](https://github.com/mastra-ai/mastra/pull/12213))
99
+
100
+ ### Patch Changes
101
+
102
+ - Updated dependencies [[`90fc0e5`](https://github.com/mastra-ai/mastra/commit/90fc0e5717cb280c2d4acf4f0410b510bb4c0a72), [`1cf5d2e`](https://github.com/mastra-ai/mastra/commit/1cf5d2ea1b085be23e34fb506c80c80a4e6d9c2b), [`833ae96`](https://github.com/mastra-ai/mastra/commit/833ae96c3e34370e58a1e979571c41f39a720592), [`943772b`](https://github.com/mastra-ai/mastra/commit/943772b4378f625f0f4e19ea2b7c392bd8e71786), [`b5c711b`](https://github.com/mastra-ai/mastra/commit/b5c711b281dd1fb81a399a766bc9f86c55efc13e), [`3efbe5a`](https://github.com/mastra-ai/mastra/commit/3efbe5ae20864c4f3143457f4f3ee7dc2fa5ca76), [`1e49e7a`](https://github.com/mastra-ai/mastra/commit/1e49e7ab5f173582154cb26b29d424de67d09aef), [`751eaab`](https://github.com/mastra-ai/mastra/commit/751eaab4e0d3820a94e4c3d39a2ff2663ded3d91), [`69d8156`](https://github.com/mastra-ai/mastra/commit/69d81568bcf062557c24471ce26812446bec465d), [`60d9d89`](https://github.com/mastra-ai/mastra/commit/60d9d899e44b35bc43f1bcd967a74e0ce010b1af), [`5c544c8`](https://github.com/mastra-ai/mastra/commit/5c544c8d12b08ab40d64d8f37b3c4215bee95b87), [`771ad96`](https://github.com/mastra-ai/mastra/commit/771ad962441996b5c43549391a3e6a02c6ddedc2), [`2b0936b`](https://github.com/mastra-ai/mastra/commit/2b0936b0c9a43eeed9bef63e614d7e02ee803f7e), [`3b04f30`](https://github.com/mastra-ai/mastra/commit/3b04f3010604f3cdfc8a0674731700ad66471cee), [`97e26de`](https://github.com/mastra-ai/mastra/commit/97e26deaebd9836647a67b96423281d66421ca07), [`10523f4`](https://github.com/mastra-ai/mastra/commit/10523f4882d9b874b40ce6e3715f66dbcd4947d2), [`cb72d20`](https://github.com/mastra-ai/mastra/commit/cb72d2069d7339bda8a0e76d4f35615debb07b84), [`42856b1`](https://github.com/mastra-ai/mastra/commit/42856b1c8aeea6371c9ee77ae2f5f5fe34400933), [`66f33ff`](https://github.com/mastra-ai/mastra/commit/66f33ff68620018513e499c394411d1d39b3aa5c), [`ab3c190`](https://github.com/mastra-ai/mastra/commit/ab3c1901980a99910ca9b96a7090c22e24060113), [`d4f06c8`](https://github.com/mastra-ai/mastra/commit/d4f06c85ffa5bb0da38fb82ebf3b040cc6b4ec4e), [`0350626`](https://github.com/mastra-ai/mastra/commit/03506267ec41b67add80d994c0c0fcce93bbc75f), [`bc9fa00`](https://github.com/mastra-ai/mastra/commit/bc9fa00859c5c4a796d53a0a5cae46ab4a3072e4), [`f46a478`](https://github.com/mastra-ai/mastra/commit/f46a4782f595949c696569e891f81c8d26338508), [`90fc0e5`](https://github.com/mastra-ai/mastra/commit/90fc0e5717cb280c2d4acf4f0410b510bb4c0a72), [`f05a3a5`](https://github.com/mastra-ai/mastra/commit/f05a3a5cf2b9a9c2d40c09cb8c762a4b6cd5d565), [`a291da9`](https://github.com/mastra-ai/mastra/commit/a291da9363efd92dafd8775dccb4f2d0511ece7a), [`c5d71da`](https://github.com/mastra-ai/mastra/commit/c5d71da1c680ce5640b1a7f8ca0e024a4ab1cfed), [`07042f9`](https://github.com/mastra-ai/mastra/commit/07042f9f89080f38b8f72713ba1c972d5b1905b8), [`0423442`](https://github.com/mastra-ai/mastra/commit/0423442b7be2dfacba95890bea8f4a810db4d603)]:
103
+ - @mastra/core@1.1.0-alpha.0
104
+
3
105
  ## 1.0.0
4
106
 
5
107
  ### Major Changes
@@ -33,4 +33,4 @@ docs/
33
33
  ## Version
34
34
 
35
35
  Package: @mastra/pg
36
- Version: 1.0.0
36
+ Version: 1.1.0-alpha.1
@@ -5,7 +5,7 @@ description: Documentation for @mastra/pg. Includes links to type definitions an
5
5
 
6
6
  # @mastra/pg Documentation
7
7
 
8
- > **Version**: 1.0.0
8
+ > **Version**: 1.1.0-alpha.1
9
9
  > **Package**: @mastra/pg
10
10
 
11
11
  ## Quick Navigation
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.0",
2
+ "version": "1.1.0-alpha.1",
3
3
  "package": "@mastra/pg",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Storage
4
4
 
5
- For Mastra to remember previous interactions, you must configure a storage adapter. Mastra is designed to work with your preferred database provider - choose from the [supported providers](#supported-providers) and pass it to your Mastra instance.
5
+ For agents to remember previous interactions, Mastra needs a database. Use a storage adapter for one of the [supported databases](#supported-providers) and pass it to your Mastra instance.
6
6
 
7
7
  ```typescript title="src/mastra/index.ts"
8
8
  import { Mastra } from "@mastra/core";
@@ -15,35 +15,37 @@ export const mastra = new Mastra({
15
15
  }),
16
16
  });
17
17
  ```
18
- On first interaction, Mastra automatically creates the necessary tables following the [core schema](https://mastra.ai/reference/v1/storage/overview#core-schema). This includes tables for messages, threads, resources, workflows, traces, and evaluation datasets.
18
+ This configures instance-level storage, which all agents share by default. You can also configure [agent-level storage](#agent-level-storage) for isolated data boundaries.
19
+
20
+ Mastra automatically creates the necessary tables on first interaction. See the [core schema](https://mastra.ai/reference/storage/overview#core-schema) for details on what gets created, including tables for messages, threads, resources, workflows, traces, and evaluation datasets.
19
21
 
20
22
  ## Supported providers
21
23
 
22
24
  Each provider page includes installation instructions, configuration parameters, and usage examples:
23
25
 
24
- - [libSQL Storage](https://mastra.ai/reference/v1/storage/libsql)
25
- - [PostgreSQL Storage](https://mastra.ai/reference/v1/storage/postgresql)
26
- - [MongoDB Storage](https://mastra.ai/reference/v1/storage/mongodb)
27
- - [Upstash Storage](https://mastra.ai/reference/v1/storage/upstash)
28
- - [Cloudflare D1](https://mastra.ai/reference/v1/storage/cloudflare-d1)
29
- - [Cloudflare Durable Objects](https://mastra.ai/reference/v1/storage/cloudflare)
30
- - [Convex](https://mastra.ai/reference/v1/storage/convex)
31
- - [DynamoDB](https://mastra.ai/reference/v1/storage/dynamodb)
32
- - [LanceDB](https://mastra.ai/reference/v1/storage/lance)
33
- - [Microsoft SQL Server](https://mastra.ai/reference/v1/storage/mssql)
26
+ - [libSQL](https://mastra.ai/reference/storage/libsql)
27
+ - [PostgreSQL](https://mastra.ai/reference/storage/postgresql)
28
+ - [MongoDB](https://mastra.ai/reference/storage/mongodb)
29
+ - [Upstash](https://mastra.ai/reference/storage/upstash)
30
+ - [Cloudflare D1](https://mastra.ai/reference/storage/cloudflare-d1)
31
+ - [Cloudflare Durable Objects](https://mastra.ai/reference/storage/cloudflare)
32
+ - [Convex](https://mastra.ai/reference/storage/convex)
33
+ - [DynamoDB](https://mastra.ai/reference/storage/dynamodb)
34
+ - [LanceDB](https://mastra.ai/reference/storage/lance)
35
+ - [Microsoft SQL Server](https://mastra.ai/reference/storage/mssql)
34
36
 
35
37
  > **Note:**
36
- libSQL is the easiest way to get started because it doesn’t require running a separate database server
38
+ libSQL is the easiest way to get started because it doesn’t require running a separate database server.
37
39
 
38
40
  ## Configuration scope
39
41
 
40
- You can configure storage at two different scopes:
42
+ Storage can be configured at the instance level (shared by all agents) or at the agent level (isolated to a specific agent).
41
43
 
42
44
  ### Instance-level storage
43
45
 
44
46
  Add storage to your Mastra instance so all agents, workflows, observability traces and scores share the same memory provider:
45
47
 
46
- ```typescript
48
+ ```typescript title="src/mastra/index.ts"
47
49
  import { Mastra } from "@mastra/core";
48
50
  import { PostgresStore } from "@mastra/pg";
49
51
 
@@ -54,7 +56,7 @@ export const mastra = new Mastra({
54
56
  }),
55
57
  });
56
58
 
57
- // All agents automatically use this storage
59
+ // Both agents inherit storage from the Mastra instance above
58
60
  const agent1 = new Agent({ id: "agent-1", memory: new Memory() });
59
61
  const agent2 = new Agent({ id: "agent-2", memory: new Memory() });
60
62
  ```
@@ -63,7 +65,7 @@ This is useful when all primitives share the same storage backend and have simil
63
65
 
64
66
  #### Composite storage
65
67
 
66
- Add storage to your Mastra instance using `MastraCompositeStore` and configure individual storage domains to use different storage providers.
68
+ [Composite storage](https://mastra.ai/reference/storage/composite) is an alternative way to configure instance-level storage. Use `MastraCompositeStore` to set the `memory` domain (and any other [domains](https://mastra.ai/reference/storage/composite#storage-domains) you need) to different storage providers.
67
69
 
68
70
  ```typescript title="src/mastra/index.ts"
69
71
  import { Mastra } from "@mastra/core";
@@ -76,6 +78,7 @@ export const mastra = new Mastra({
76
78
  storage: new MastraCompositeStore({
77
79
  id: "composite",
78
80
  domains: {
81
+ // highlight-next-line
79
82
  memory: new MemoryLibSQL({ url: "file:./memory.db" }),
80
83
  workflows: new WorkflowsPG({ connectionString: process.env.DATABASE_URL }),
81
84
  observability: new ObservabilityStorageClickhouse({
@@ -90,14 +93,11 @@ export const mastra = new Mastra({
90
93
 
91
94
  This is useful when different types of data have different performance or operational requirements, such as low-latency storage for memory, durable storage for workflows, and high-throughput storage for observability.
92
95
 
93
- > **Note:**
94
- See [Storage Domains](https://mastra.ai/reference/v1/storage/composite#storage-domains) for more information.
95
-
96
96
  ### Agent-level storage
97
97
 
98
- Agent-level storage overrides storage configured at the instance-level. Add storage to a specific agent when you need data boundaries or compliance requirements:
98
+ Agent-level storage overrides storage configured at the instance level. Add storage to a specific agent when you need data boundaries or compliance requirements:
99
99
 
100
- ```typescript title="src/mastra/agents/memory-agent.ts"
100
+ ```typescript title="src/mastra/agents/your-agent.ts"
101
101
  import { Agent } from "@mastra/core/agent";
102
102
  import { Memory } from "@mastra/memory";
103
103
  import { PostgresStore } from "@mastra/pg";
@@ -113,56 +113,55 @@ export const agent = new Agent({
113
113
  });
114
114
  ```
115
115
 
116
- This is useful when different agents need to store data in separate databases for security, compliance, or organizational reasons.
117
-
118
- > **Mastra Cloud Store limitation**
119
- Agent-level storage is not supported when using [Mastra Cloud Store](https://mastra.ai/docs/v1/mastra-cloud/deployment#using-mastra-cloud-store). If you use Mastra Cloud Store, configure storage on the Mastra instance instead. This limitation does not apply if you bring your own database.
116
+ > **Note:**
117
+ [Mastra Cloud Store](https://mastra.ai/docs/mastra-cloud/deployment#using-mastra-cloud-store) doesn't support agent-level storage.
120
118
 
121
119
  ## Threads and resources
122
120
 
123
- Mastra organizes memory into threads using two identifiers:
121
+ Mastra organizes conversations using two identifiers:
122
+
123
+ - **Thread** - a conversation session containing a sequence of messages.
124
+ - **Resource** - the entity that owns the thread, such as a user, organization, project, or any other domain entity in your application.
124
125
 
125
- - **Thread**: A conversation session containing a sequence of messages (e.g., `convo_123`)
126
- - **Resource**: An identifier for the entity the thread belongs to, typically a user (e.g., `user_123`)
126
+ Both identifiers are required for agents to store information:
127
127
 
128
- Both identifiers are required for agents to store and recall information:
128
+ **generate:**
129
129
 
130
130
  ```typescript
131
- const stream = await agent.stream("message for agent", {
131
+ const response = await agent.generate("hello", {
132
132
  memory: {
133
- thread: "convo_123",
133
+ thread: "conversation-abc-123",
134
134
  resource: "user_123",
135
135
  },
136
136
  });
137
137
  ```
138
138
 
139
- > **Note:**
140
- [Studio](https://mastra.ai/docs/v1/getting-started/studio) automatically generates a thread and resource ID for you. Remember to to pass these explicitly when calling `stream` or `generate` yourself.
141
-
142
- ### Thread and resource relationship
139
+
140
+ **stream:**
143
141
 
144
- Each thread has an owner (its `resourceId`) that is set when the thread is created and cannot be changed. When you query a thread, you must use the correct owner's resource ID. Attempting to query a thread with a different resource ID will result in an error:
145
-
146
- ```text
147
- Thread with id <thread_id> is for resource with id <resource_a>
148
- but resource <resource_b> was queried
142
+ ```typescript
143
+ const stream = await agent.stream("hello", {
144
+ memory: {
145
+ thread: "conversation-abc-123",
146
+ resource: "user_123",
147
+ },
148
+ });
149
149
  ```
150
150
 
151
- Note that while each thread has one owner, messages within that thread can have different `resourceId` values. This is used for message attribution and filtering (e.g., distinguishing between different agents in a multi-agent system, or filtering messages for analytics).
152
-
153
- **Security:** Memory is a storage layer, not an authorization layer. Your application must implement access control before calling memory APIs. The `resourceId` parameter controls both validation and filtering - provide it to validate ownership and filter messages, or omit it for server-side access without validation.
151
+
154
152
 
155
- To avoid accidentally reusing thread IDs across different owners, use UUIDs: `crypto.randomUUID()`
153
+ > **Note:**
154
+ [Studio](https://mastra.ai/docs/getting-started/studio) automatically generates a thread and resource ID for you. When calling `stream()` or `generate()` yourself, remember to provide these identifiers explicitly.
156
155
 
157
156
  ### Thread title generation
158
157
 
159
- Mastra can automatically generate descriptive thread titles based on the user's first message.
158
+ Mastra can automatically generate descriptive thread titles based on the user's first message when `generateTitle` is enabled.
160
159
 
161
160
  Use this option when implementing a ChatGPT-style chat interface to render a title alongside each thread in the conversation list (for example, in a sidebar) derived from the thread’s initial user message.
162
161
 
163
- ```typescript
164
- export const testAgent = new Agent({
165
- id: "test-agent",
162
+ ```typescript title="src/mastra/agents/my-agent.ts"
163
+ export const agent = new Agent({
164
+ id: "agent",
166
165
  memory: new Memory({
167
166
  options: {
168
167
  generateTitle: true,
@@ -173,16 +172,16 @@ export const testAgent = new Agent({
173
172
 
174
173
  Title generation runs asynchronously after the agent responds and does not affect response time.
175
174
 
176
- To optimize cost or behavior, provide a smaller `model` and custom `instructions`:
175
+ To optimize cost or behavior, provide a smaller [`model`](/models) and custom `instructions`:
177
176
 
178
- ```typescript
179
- export const testAgent = new Agent({
180
- id: "test-agent",
177
+ ```typescript title="src/mastra/agents/my-agent.ts"
178
+ export const agent = new Agent({
179
+ id: "agent",
181
180
  memory: new Memory({
182
181
  options: {
183
182
  generateTitle: {
184
183
  model: "openai/gpt-4o-mini",
185
- instructions: "Generate a concise title based on the user's first message",
184
+ instructions: "Generate a 1 word title",
186
185
  },
187
186
  },
188
187
  }),
@@ -191,43 +190,72 @@ export const testAgent = new Agent({
191
190
 
192
191
  ## Semantic recall
193
192
 
194
- Semantic recall uses vector embeddings to retrieve relevant past messages based on meaning rather than recency. This requires a vector database instance, which can be configured at the instance or agent level.
193
+ Semantic recall has different storage requirements - it needs a vector database in addition to the standard storage adapter. See [Semantic recall](https://mastra.ai/docs/memory/semantic-recall) for setup and supported vector providers.
195
194
 
196
- The vector database doesn't have to be the same as your storage provider. For example, you might use PostgreSQL for storage and Pinecone for vectors:
195
+ ## Handling large attachments
197
196
 
198
- ```typescript
199
- import { Mastra } from "@mastra/core";
200
- import { Agent } from "@mastra/core/agent";
201
- import { Memory } from "@mastra/memory";
202
- import { PostgresStore } from "@mastra/pg";
203
- import { PineconeVector } from "@mastra/pinecone";
197
+ Some storage providers enforce record size limits that base64-encoded file attachments (such as images) can exceed:
204
198
 
205
- // Instance-level vector configuration
206
- export const mastra = new Mastra({
207
- storage: new PostgresStore({
208
- id: 'mastra-storage',
209
- connectionString: process.env.DATABASE_URL,
210
- }),
211
- });
199
+ | Provider | Record size limit |
200
+ | -------- | ----------------- |
201
+ | [DynamoDB](https://mastra.ai/reference/storage/dynamodb) | 400 KB |
202
+ | [Convex](https://mastra.ai/reference/storage/convex) | 1 MiB |
203
+ | [Cloudflare D1](https://mastra.ai/reference/storage/cloudflare-d1) | 1 MiB |
212
204
 
213
- // Agent-level vector configuration
214
- export const agent = new Agent({
215
- id: "agent",
216
- memory: new Memory({
217
- vector: new PineconeVector({
218
- id: 'agent-vector',
219
- apiKey: process.env.PINECONE_API_KEY,
220
- }),
221
- options: {
222
- semanticRecall: {
223
- topK: 5,
224
- messageRange: 2,
225
- },
226
- },
227
- }),
228
- });
205
+ PostgreSQL, MongoDB, and libSQL have higher limits and are generally unaffected.
206
+
207
+ To avoid this, use an input processor to upload attachments to external storage (S3, R2, GCS, [Convex file storage](https://docs.convex.dev/file-storage), etc.) and replace them with URL references before persistence.
208
+
209
+ ```typescript title="src/mastra/processors/attachment-uploader.ts"
210
+ import type { Processor } from "@mastra/core/processors";
211
+ import type { MastraDBMessage } from "@mastra/core/memory";
212
+
213
+ export class AttachmentUploader implements Processor {
214
+ id = "attachment-uploader";
215
+
216
+ async processInput({ messages }: { messages: MastraDBMessage[] }) {
217
+ return Promise.all(messages.map((msg) => this.processMessage(msg)));
218
+ }
219
+
220
+ async processMessage(msg: MastraDBMessage) {
221
+ const attachments = msg.content.experimental_attachments;
222
+ if (!attachments?.length) return msg;
223
+
224
+ const uploaded = await Promise.all(
225
+ attachments.map(async (att) => {
226
+ // Skip if already a URL
227
+ if (!att.url?.startsWith("data:")) return att;
228
+
229
+ // Upload base64 data and replace with URL
230
+ const url = await this.upload(att.url, att.contentType);
231
+ return { ...att, url };
232
+ })
233
+ );
234
+
235
+ return { ...msg, content: { ...msg.content, experimental_attachments: uploaded } };
236
+ }
237
+
238
+ async upload(dataUri: string, contentType?: string): Promise<string> {
239
+ const base64 = dataUri.split(",")[1];
240
+ const buffer = Buffer.from(base64, "base64");
241
+
242
+ // Replace with your storage provider (S3, R2, GCS, Convex, etc.)
243
+ // return await s3.upload(buffer, contentType);
244
+ throw new Error("Implement upload() with your storage provider");
245
+ }
246
+ }
229
247
  ```
230
248
 
231
- We support all popular vector providers including [Pinecone](https://mastra.ai/reference/v1/vectors/pinecone), [Chroma](https://mastra.ai/reference/v1/vectors/chroma), [Qdrant](https://mastra.ai/reference/v1/vectors/qdrant), and many more.
249
+ Use the processor with your agent:
232
250
 
233
- For more information on configuring semantic recall, see the [Semantic Recall](./semantic-recall) documentation.
251
+ ```typescript
252
+ import { Agent } from "@mastra/core/agent";
253
+ import { Memory } from "@mastra/memory";
254
+ import { AttachmentUploader } from "./processors/attachment-uploader";
255
+
256
+ const agent = new Agent({
257
+ id: "my-agent",
258
+ memory: new Memory({ storage: yourStorage }),
259
+ inputProcessors: [new AttachmentUploader()],
260
+ });
261
+ ```
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Working Memory
4
4
 
5
- While [message history](https://mastra.ai/docs/v1/memory/message-history) and [semantic recall](./semantic-recall) help agents remember conversations, working memory allows them to maintain persistent information about users across interactions.
5
+ While [message history](https://mastra.ai/docs/memory/message-history) and [semantic recall](./semantic-recall) help agents remember conversations, working memory allows them to maintain persistent information about users across interactions.
6
6
 
7
7
  Think of it as the agent's active thoughts or scratchpad – the key information they keep available about the user or task. It's similar to how a person would naturally remember someone's name, preferences, or important details during a conversation.
8
8
 
@@ -383,6 +383,27 @@ await memory.updateWorkingMemory({
383
383
  });
384
384
  ```
385
385
 
386
+ ## Read-Only Working Memory
387
+
388
+ In some scenarios, you may want an agent to have access to working memory data without the ability to modify it. This is useful for:
389
+
390
+ - **Routing agents** that need context but shouldn't update user profiles
391
+ - **Sub agents** in a multi-agent system that should reference but not own the memory
392
+
393
+ To enable read-only mode, set `readOnly: true` in the memory options:
394
+
395
+ ```typescript
396
+ const response = await agent.generate("What do you know about me?", {
397
+ memory: {
398
+ thread: "conversation-123",
399
+ resource: "user-alice-456",
400
+ options: {
401
+ readOnly: true, // Working memory is provided but cannot be updated
402
+ },
403
+ },
404
+ });
405
+ ```
406
+
386
407
  ## Examples
387
408
 
388
409
  - [Working memory with template](https://github.com/mastra-ai/mastra/tree/main/examples/memory-with-template)
@@ -37,9 +37,32 @@ const agent = new Agent({
37
37
  });
38
38
  ```
39
39
 
40
+ ## Using the recall() Method
41
+
42
+ 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`:
43
+
44
+ ```typescript
45
+ const memory = await agent.getMemory();
46
+
47
+ // Basic recall - similar to listMessages
48
+ const { messages } = await memory!.recall({
49
+ threadId: "thread-123",
50
+ perPage: 50,
51
+ });
52
+
53
+ // Semantic recall - find messages by meaning
54
+ const { messages: relevantMessages } = await memory!.recall({
55
+ threadId: "thread-123",
56
+ vectorSearchString: "What did we discuss about the project deadline?",
57
+ threadConfig: {
58
+ semanticRecall: true,
59
+ },
60
+ });
61
+ ```
62
+
40
63
  ## Storage configuration
41
64
 
42
- Semantic recall relies on a [storage and vector db](https://mastra.ai/reference/v1/memory/memory-class) to store messages and their embeddings.
65
+ Semantic recall relies on a [storage and vector db](https://mastra.ai/reference/memory/memory-class) to store messages and their embeddings.
43
66
 
44
67
  ```ts {8-16}
45
68
  import { Memory } from "@mastra/memory";
@@ -64,23 +87,23 @@ const agent = new Agent({
64
87
 
65
88
  Each vector store page below includes installation instructions, configuration parameters, and usage examples:
66
89
 
67
- - [Astra](https://mastra.ai/reference/v1/vectors/astra)
68
- - [Chroma](https://mastra.ai/reference/v1/vectors/chroma)
69
- - [Cloudflare Vectorize](https://mastra.ai/reference/v1/vectors/vectorize)
70
- - [Convex](https://mastra.ai/reference/v1/vectors/convex)
71
- - [Couchbase](https://mastra.ai/reference/v1/vectors/couchbase)
72
- - [DuckDB](https://mastra.ai/reference/v1/vectors/duckdb)
73
- - [Elasticsearch](https://mastra.ai/reference/v1/vectors/elasticsearch)
74
- - [LanceDB](https://mastra.ai/reference/v1/vectors/lance)
75
- - [libSQL](https://mastra.ai/reference/v1/vectors/libsql)
76
- - [MongoDB](https://mastra.ai/reference/v1/vectors/mongodb)
77
- - [OpenSearch](https://mastra.ai/reference/v1/vectors/opensearch)
78
- - [Pinecone](https://mastra.ai/reference/v1/vectors/pinecone)
79
- - [PostgreSQL](https://mastra.ai/reference/v1/vectors/pg)
80
- - [Qdrant](https://mastra.ai/reference/v1/vectors/qdrant)
81
- - [S3 Vectors](https://mastra.ai/reference/v1/vectors/s3vectors)
82
- - [Turbopuffer](https://mastra.ai/reference/v1/vectors/turbopuffer)
83
- - [Upstash](https://mastra.ai/reference/v1/vectors/upstash)
90
+ - [Astra](https://mastra.ai/reference/vectors/astra)
91
+ - [Chroma](https://mastra.ai/reference/vectors/chroma)
92
+ - [Cloudflare Vectorize](https://mastra.ai/reference/vectors/vectorize)
93
+ - [Convex](https://mastra.ai/reference/vectors/convex)
94
+ - [Couchbase](https://mastra.ai/reference/vectors/couchbase)
95
+ - [DuckDB](https://mastra.ai/reference/vectors/duckdb)
96
+ - [Elasticsearch](https://mastra.ai/reference/vectors/elasticsearch)
97
+ - [LanceDB](https://mastra.ai/reference/vectors/lance)
98
+ - [libSQL](https://mastra.ai/reference/vectors/libsql)
99
+ - [MongoDB](https://mastra.ai/reference/vectors/mongodb)
100
+ - [OpenSearch](https://mastra.ai/reference/vectors/opensearch)
101
+ - [Pinecone](https://mastra.ai/reference/vectors/pinecone)
102
+ - [PostgreSQL](https://mastra.ai/reference/vectors/pg)
103
+ - [Qdrant](https://mastra.ai/reference/vectors/qdrant)
104
+ - [S3 Vectors](https://mastra.ai/reference/vectors/s3vectors)
105
+ - [Turbopuffer](https://mastra.ai/reference/vectors/turbopuffer)
106
+ - [Upstash](https://mastra.ai/reference/vectors/upstash)
84
107
 
85
108
  ## Recall configuration
86
109
 
@@ -106,7 +129,7 @@ const agent = new Agent({
106
129
 
107
130
  ## Embedder configuration
108
131
 
109
- Semantic recall relies on an [embedding model](https://mastra.ai/reference/v1/memory/memory-class) to convert messages into embeddings. Mastra supports embedding models through the model router using `provider/model` strings, or you can use any [embedding model](https://sdk.vercel.ai/docs/ai-sdk-core/embeddings) compatible with the AI SDK.
132
+ Semantic recall relies on an [embedding model](https://mastra.ai/reference/memory/memory-class) to convert messages into embeddings. Mastra supports embedding models through the model router using `provider/model` strings, or you can use any [embedding model](https://sdk.vercel.ai/docs/ai-sdk-core/embeddings) compatible with the AI SDK.
110
133
 
111
134
  #### Using the Model Router (Recommended)
112
135
 
@@ -127,7 +150,7 @@ const agent = new Agent({
127
150
  Supported embedding models:
128
151
 
129
152
  - **OpenAI**: `text-embedding-3-small`, `text-embedding-3-large`, `text-embedding-ada-002`
130
- - **Google**: `gemini-embedding-001`, `text-embedding-004`
153
+ - **Google**: `gemini-embedding-001`
131
154
 
132
155
  The model router automatically handles API key detection from environment variables (`OPENAI_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`).
133
156
 
@@ -152,7 +175,7 @@ const agent = new Agent({
152
175
  To use FastEmbed (a local embedding model), install `@mastra/fastembed`:
153
176
 
154
177
  ```bash npm2yarn
155
- npm install @mastra/fastembed@beta
178
+ npm install @mastra/fastembed@latest
156
179
  ```
157
180
 
158
181
  Then configure it in your memory:
@@ -205,7 +228,7 @@ const agent = new Agent({
205
228
  });
206
229
  ```
207
230
 
208
- For detailed information about index configuration options and performance tuning, see the [PgVector configuration guide](https://mastra.ai/reference/v1/vectors/pg#index-configuration-guide).
231
+ For detailed information about index configuration options and performance tuning, see the [PgVector configuration guide](https://mastra.ai/reference/vectors/pg#index-configuration-guide).
209
232
 
210
233
  ## Disabling
211
234
 
@@ -120,14 +120,14 @@ export const agent = new Agent({
120
120
 
121
121
  ### Related
122
122
 
123
- - [Getting Started with Memory](https://mastra.ai/docs/v1/memory/overview)
124
- - [Semantic Recall](https://mastra.ai/docs/v1/memory/semantic-recall)
125
- - [Working Memory](https://mastra.ai/docs/v1/memory/working-memory)
126
- - [Memory Processors](https://mastra.ai/docs/v1/memory/memory-processors)
127
- - [createThread](https://mastra.ai/reference/v1/memory/createThread)
128
- - [recall](https://mastra.ai/reference/v1/memory/recall)
129
- - [getThreadById](https://mastra.ai/reference/v1/memory/getThreadById)
130
- - [listThreads](https://mastra.ai/reference/v1/memory/listThreads)
131
- - [deleteMessages](https://mastra.ai/reference/v1/memory/deleteMessages)
132
- - [cloneThread](https://mastra.ai/reference/v1/memory/cloneThread)
133
- - [Clone Utility Methods](https://mastra.ai/reference/v1/memory/clone-utilities)
123
+ - [Getting Started with Memory](https://mastra.ai/docs/memory/overview)
124
+ - [Semantic Recall](https://mastra.ai/docs/memory/semantic-recall)
125
+ - [Working Memory](https://mastra.ai/docs/memory/working-memory)
126
+ - [Memory Processors](https://mastra.ai/docs/memory/memory-processors)
127
+ - [createThread](https://mastra.ai/reference/memory/createThread)
128
+ - [recall](https://mastra.ai/reference/memory/recall)
129
+ - [getThreadById](https://mastra.ai/reference/memory/getThreadById)
130
+ - [listThreads](https://mastra.ai/reference/memory/listThreads)
131
+ - [deleteMessages](https://mastra.ai/reference/memory/deleteMessages)
132
+ - [cloneThread](https://mastra.ai/reference/memory/cloneThread)
133
+ - [Clone Utility Methods](https://mastra.ai/reference/memory/clone-utilities)