@mastra/pg 1.18.0 → 1.18.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 +18 -0
- package/dist/docs/SKILL.md +3 -2
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-deployment-workers.md +137 -0
- package/dist/docs/references/docs-memory-semantic-recall.md +3 -3
- package/dist/docs/references/docs-memory-working-memory.md +8 -8
- package/dist/docs/references/docs-rag-overview.md +2 -2
- package/dist/docs/references/docs-rag-retrieval.md +18 -18
- package/dist/docs/references/docs-rag-vector-databases.md +2 -2
- package/dist/docs/references/docs-storage-overview.md +2 -2
- package/dist/docs/references/reference-memory-memory-class.md +4 -4
- package/dist/docs/references/reference-processors-message-history-processor.md +1 -1
- package/dist/docs/references/reference-processors-semantic-recall-processor.md +1 -1
- package/dist/docs/references/reference-processors-working-memory-processor.md +1 -1
- package/dist/docs/references/reference-rag-metadata-filters.md +2 -2
- package/dist/docs/references/reference-storage-dynamodb.md +7 -7
- package/dist/docs/references/reference-storage-postgresql.md +2 -2
- package/dist/docs/references/reference-storage-retention.md +33 -33
- package/dist/docs/references/reference-tools-vector-query-tool.md +5 -5
- package/dist/docs/references/reference-vectors-pg.md +5 -5
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @mastra/pg
|
|
2
2
|
|
|
3
|
+
## 1.18.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- dependencies updates: ([#19779](https://github.com/mastra-ai/mastra/pull/19779))
|
|
8
|
+
- Updated dependency [`pg@^8.22.0` ↗︎](https://www.npmjs.com/package/pg/v/8.22.0) (from `^8.21.0`, in `dependencies`)
|
|
9
|
+
- Updated dependencies [[`3f472b4`](https://github.com/mastra-ai/mastra/commit/3f472b468892a1ff14ccb43cc0343b86f7d8fd7d), [`ba369f2`](https://github.com/mastra-ai/mastra/commit/ba369f2a0aaf998da0d6aa033d26f64f96bef8ac), [`35b929b`](https://github.com/mastra-ai/mastra/commit/35b929b7abc3d20d85c7985880960ac2d04a6c86), [`55c9e24`](https://github.com/mastra-ai/mastra/commit/55c9e248c27c1d72b5bb7e94ea6b8a3999eee49f), [`dcfed93`](https://github.com/mastra-ai/mastra/commit/dcfed93e1e256c6abfa792cbb7ca836f5d0e8638), [`2876e15`](https://github.com/mastra-ai/mastra/commit/2876e15b4d2f616a3bc1ed3af57d546c268384ce), [`9b3626a`](https://github.com/mastra-ai/mastra/commit/9b3626aeb1d16fcd34b0a8e94c114ddb80a3b240), [`4696963`](https://github.com/mastra-ai/mastra/commit/469696312ac4c618bc8475b0c5ed7949b8a3455e), [`723aa54`](https://github.com/mastra-ai/mastra/commit/723aa5437106bdb708ae03c0ef6b77aa11291e73), [`07f5b4b`](https://github.com/mastra-ai/mastra/commit/07f5b4ba9d608d88865030732e580298296adf99), [`723aa54`](https://github.com/mastra-ai/mastra/commit/723aa5437106bdb708ae03c0ef6b77aa11291e73), [`723aa54`](https://github.com/mastra-ai/mastra/commit/723aa5437106bdb708ae03c0ef6b77aa11291e73), [`598080f`](https://github.com/mastra-ai/mastra/commit/598080f224edb3f0f5b801035b067fac50a56a03)]:
|
|
10
|
+
- @mastra/core@1.55.0
|
|
11
|
+
|
|
12
|
+
## 1.18.1-alpha.0
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- dependencies updates: ([#19779](https://github.com/mastra-ai/mastra/pull/19779))
|
|
17
|
+
- Updated dependency [`pg@^8.22.0` ↗︎](https://www.npmjs.com/package/pg/v/8.22.0) (from `^8.21.0`, in `dependencies`)
|
|
18
|
+
- Updated dependencies [[`723aa54`](https://github.com/mastra-ai/mastra/commit/723aa5437106bdb708ae03c0ef6b77aa11291e73), [`723aa54`](https://github.com/mastra-ai/mastra/commit/723aa5437106bdb708ae03c0ef6b77aa11291e73), [`723aa54`](https://github.com/mastra-ai/mastra/commit/723aa5437106bdb708ae03c0ef6b77aa11291e73)]:
|
|
19
|
+
- @mastra/core@1.55.0-alpha.3
|
|
20
|
+
|
|
3
21
|
## 1.18.0
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-pg
|
|
|
3
3
|
description: Documentation for @mastra/pg. Use when working with @mastra/pg APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/pg"
|
|
6
|
-
version: "1.18.
|
|
6
|
+
version: "1.18.1"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -16,6 +16,7 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
16
16
|
|
|
17
17
|
### Docs
|
|
18
18
|
|
|
19
|
+
- [Workers](references/docs-deployment-workers.md) - Separate background processing from the API layer by running workflow execution, cron schedules, and background tasks in dedicated worker processes.
|
|
19
20
|
- [Semantic recall](references/docs-memory-semantic-recall.md) - Learn how to use semantic recall in Mastra to retrieve relevant messages from past conversations using vector search and embeddings.
|
|
20
21
|
- [Working memory](references/docs-memory-working-memory.md) - Learn how to configure working memory in Mastra to store persistent user data, preferences.
|
|
21
22
|
- [RAG (Retrieval-Augmented Generation) in Mastra](references/docs-rag-overview.md) - Overview of Retrieval-Augmented Generation (RAG) in Mastra, detailing its capabilities for enhancing LLM outputs with relevant context.
|
|
@@ -25,7 +26,7 @@ Read the individual reference documents for detailed explanations and code examp
|
|
|
25
26
|
|
|
26
27
|
### Reference
|
|
27
28
|
|
|
28
|
-
- [Reference: Memory class](references/reference-memory-memory-class.md) - Documentation for the `Memory` class in Mastra, which provides a
|
|
29
|
+
- [Reference: Memory class](references/reference-memory-memory-class.md) - Documentation for the `Memory` class in Mastra, which provides a reliable system for managing conversation history and thread-based message storage.
|
|
29
30
|
- [Reference: MessageHistory](references/reference-processors-message-history-processor.md) - Documentation for the MessageHistory processor in Mastra, which handles retrieval and persistence of conversation history.
|
|
30
31
|
- [Reference: SemanticRecall](references/reference-processors-semantic-recall-processor.md) - Documentation for the SemanticRecall processor in Mastra, which enables semantic search over conversation history using vector embeddings.
|
|
31
32
|
- [Reference: WorkingMemory](references/reference-processors-working-memory-processor.md) - Documentation for the WorkingMemory processor in Mastra, which injects persistent user/context data as system instructions.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
+
|
|
3
|
+
# Workers
|
|
4
|
+
|
|
5
|
+
> **Beta:** This feature is in beta. The API is stable enough for production use, but some details may change. See [known limitations](#known-limitations) for current gaps.
|
|
6
|
+
|
|
7
|
+
Workers handle background processing outside the request-response cycle. Workflow step execution, cron-based scheduling, and long-running tool calls all run in workers, keeping the API responsive.
|
|
8
|
+
|
|
9
|
+
By default, workers run in the same process as the API. For production workloads, you can split them into separate processes or containers and scale each one independently.
|
|
10
|
+
|
|
11
|
+
## When to use workers
|
|
12
|
+
|
|
13
|
+
Workers matter when any of these apply:
|
|
14
|
+
|
|
15
|
+
- Workflow steps take more than a few seconds and shouldn't block API responses
|
|
16
|
+
- You need event durability so in-flight work survives process restarts
|
|
17
|
+
- Different parts of the system need to scale independently (e.g., more orchestration capacity without more API instances)
|
|
18
|
+
- Background tool calls should run on dedicated compute
|
|
19
|
+
|
|
20
|
+
If your application handles light traffic and workflows complete quickly, the default in-process setup works fine. Skip the worker infrastructure until you need it.
|
|
21
|
+
|
|
22
|
+
## Worker types
|
|
23
|
+
|
|
24
|
+
Mastra has three built-in worker types. Each handles a specific kind of background processing.
|
|
25
|
+
|
|
26
|
+
### Orchestration worker
|
|
27
|
+
|
|
28
|
+
Subscribes to workflow events on the [PubSub](https://mastra.ai/docs/server/pubsub) bus and executes workflow steps. Every `workflow.start`, step transition, and lifecycle event flows through this worker.
|
|
29
|
+
|
|
30
|
+
In a split deployment, the orchestration worker pulls events from a distributed PubSub backend and delegates step execution back to the API over HTTP. In-process, it runs steps directly.
|
|
31
|
+
|
|
32
|
+
The orchestration worker requires a PubSub backend that supports pull mode (e.g., [`RedisStreamsPubSub`](https://mastra.ai/reference/pubsub/redis-streams) or [`GoogleCloudPubSub`](https://mastra.ai/reference/pubsub/google-cloud-pubsub)).
|
|
33
|
+
|
|
34
|
+
### Scheduler worker
|
|
35
|
+
|
|
36
|
+
Polls storage for due cron schedules and publishes `workflow.start` events. It is a producer only, meaning it creates work for the orchestration worker to pick up.
|
|
37
|
+
|
|
38
|
+
The scheduler reads declarative `schedule` fields from your workflow definitions automatically. See [Scheduled workflows](https://mastra.ai/docs/workflows/scheduled-workflows) for how to declare schedules.
|
|
39
|
+
|
|
40
|
+
**Do not run more than one scheduler instance.** Multiple schedulers polling the same storage would fire duplicate events for the same schedule.
|
|
41
|
+
|
|
42
|
+
### Background task worker
|
|
43
|
+
|
|
44
|
+
Executes agent tool calls marked with `background: { enabled: true }`. When an agent invokes a background tool, the API dispatches the task to this worker instead of blocking the response stream.
|
|
45
|
+
|
|
46
|
+
The background task worker manages concurrency limits, task lifecycle, and result delivery through the PubSub bus.
|
|
47
|
+
|
|
48
|
+
## How workers run
|
|
49
|
+
|
|
50
|
+
### In-process (default)
|
|
51
|
+
|
|
52
|
+
With no configuration, Mastra creates and starts workers inside the API process. Events flow through an in-memory PubSub, and everything shares a single Node.js runtime.
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { Mastra } from '@mastra/core/mastra'
|
|
56
|
+
|
|
57
|
+
export const mastra = new Mastra({
|
|
58
|
+
// Workers run in-process by default.
|
|
59
|
+
// No pubsub or worker config needed.
|
|
60
|
+
})
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
This setup needs no external infrastructure beyond your storage adapter. It doesn't survive process crashes, and you can't scale individual components.
|
|
64
|
+
|
|
65
|
+
### Split processes
|
|
66
|
+
|
|
67
|
+
To run workers separately, configure a distributed [PubSub](https://mastra.ai/docs/server/pubsub) backend and use the `MASTRA_WORKERS` environment variable to control which workers start in each process.
|
|
68
|
+
|
|
69
|
+
**Redis Streams + PostgreSQL**:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { Mastra } from '@mastra/core/mastra'
|
|
73
|
+
import { RedisStreamsPubSub } from '@mastra/redis-streams'
|
|
74
|
+
import { PostgresStore } from '@mastra/pg'
|
|
75
|
+
|
|
76
|
+
export const mastra = new Mastra({
|
|
77
|
+
storage: new PostgresStore({
|
|
78
|
+
connectionString: process.env.DATABASE_URL!,
|
|
79
|
+
}),
|
|
80
|
+
pubsub: new RedisStreamsPubSub({
|
|
81
|
+
url: process.env.REDIS_URL!,
|
|
82
|
+
}),
|
|
83
|
+
})
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Google Cloud Pub/Sub + LibSQL**:
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { Mastra } from '@mastra/core/mastra'
|
|
90
|
+
import { GoogleCloudPubSub } from '@mastra/google-cloud-pubsub'
|
|
91
|
+
import { LibSQLStore } from '@mastra/libsql'
|
|
92
|
+
|
|
93
|
+
export const mastra = new Mastra({
|
|
94
|
+
storage: new LibSQLStore({
|
|
95
|
+
url: process.env.DATABASE_URL!,
|
|
96
|
+
}),
|
|
97
|
+
pubsub: new GoogleCloudPubSub({
|
|
98
|
+
projectId: process.env.GCP_PROJECT_ID!,
|
|
99
|
+
}),
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Any [supported storage backend](https://mastra.ai/reference/workers/overview) works — swap the storage adapter for your preferred database.
|
|
104
|
+
|
|
105
|
+
Run the same build artifact in multiple containers, each with a different [`MASTRA_WORKERS`](https://mastra.ai/reference/workers/overview) value to control which worker starts in each process.
|
|
106
|
+
|
|
107
|
+
Split deployments require a distributed PubSub backend ([`RedisStreamsPubSub`](https://mastra.ai/reference/pubsub/redis-streams) or [`GoogleCloudPubSub`](https://mastra.ai/reference/pubsub/google-cloud-pubsub)), a shared [storage backend](https://mastra.ai/reference/workers/overview), and network connectivity between the orchestration worker and the API.
|
|
108
|
+
|
|
109
|
+
The [worker deployment guide](https://mastra.ai/guides/deployment/mastra-workers) walks through this setup with a Docker Compose example.
|
|
110
|
+
|
|
111
|
+
## Network architecture
|
|
112
|
+
|
|
113
|
+
Workers are internal infrastructure. They are not exposed to end users and do not need their own subdomain, public URL, or inbound HTTP route.
|
|
114
|
+
|
|
115
|
+
In a split deployment:
|
|
116
|
+
|
|
117
|
+
- **The API server is the only public-facing process.** It serves all client HTTP requests — REST endpoints, agent interactions, workflow triggers, and any custom routes.
|
|
118
|
+
- **Workers connect outbound only.** They pull events from the distributed PubSub backend and read/write to the shared storage database. They do not accept inbound traffic from clients.
|
|
119
|
+
- **The orchestration worker calls the API internally.** It sends step execution requests to the API over the container network using `MASTRA_STEP_EXECUTION_URL`. This is internal service-to-service communication, not a public endpoint.
|
|
120
|
+
|
|
121
|
+
All three worker types (orchestration, scheduler, background task) sit behind the API on a private network. They share access to the PubSub backend and storage database but never receive traffic directly from clients. If a worker-related feature needs an HTTP route (for example, token minting for a voice integration), that route runs on the API server, not on the worker process.
|
|
122
|
+
|
|
123
|
+
## Known limitations
|
|
124
|
+
|
|
125
|
+
- **No dead-letter queue**: Failed events are nacked and retried, but there is no DLQ for events that repeatedly fail.
|
|
126
|
+
- **No built-in health endpoint**: Workers don't expose an HTTP health check. Use container-level liveness probes or process monitoring.
|
|
127
|
+
- **Scheduler is single-instance**: Running multiple scheduler processes causes duplicate schedule fires.
|
|
128
|
+
- **Runs stuck in "running" after API crash**: If the API process crashes while executing a workflow step, the run remains in `running` status with no automatic retry. For [durable agents](https://mastra.ai/docs/long-running-agents/durable-agents), set `recovery.durableAgents` to `'auto'` in the Mastra config to automatically re-drive orphaned runs on server restart. See [Crash recovery](https://mastra.ai/docs/long-running-agents/durable-agents) for details.
|
|
129
|
+
|
|
130
|
+
## Related
|
|
131
|
+
|
|
132
|
+
- [Worker deployment guide](https://mastra.ai/guides/deployment/mastra-workers): Docker Compose example and topology options
|
|
133
|
+
- [Worker authentication](https://mastra.ai/docs/server/auth/workers): Secure worker-to-API communication
|
|
134
|
+
- [Workers reference](https://mastra.ai/reference/workers/overview): Environment variables, worker types, and storage backends
|
|
135
|
+
- [CLI reference](https://mastra.ai/reference/cli/mastra): `mastra worker build` and `mastra worker start`
|
|
136
|
+
- [PubSub](https://mastra.ai/docs/server/pubsub): Event delivery backends
|
|
137
|
+
- [Scheduled workflows](https://mastra.ai/docs/workflows/scheduled-workflows): Declare cron schedules on workflows
|
|
@@ -10,7 +10,7 @@ If you ask your friend what they did last weekend, they will search in their mem
|
|
|
10
10
|
|
|
11
11
|
Semantic recall is RAG-based search that helps agents maintain context across longer interactions when messages are no longer within [recent message history](https://mastra.ai/docs/memory/message-history).
|
|
12
12
|
|
|
13
|
-
It uses vector embeddings of messages for similarity search
|
|
13
|
+
It uses vector embeddings of messages for similarity search and integrates with vector stores, plus has configurable context windows around retrieved messages.
|
|
14
14
|
|
|
15
15
|

|
|
16
16
|
|
|
@@ -34,7 +34,7 @@ const agent = new Agent({
|
|
|
34
34
|
id: 'support-agent',
|
|
35
35
|
name: 'SupportAgent',
|
|
36
36
|
instructions: 'You are a helpful support agent.',
|
|
37
|
-
model: 'openai/gpt-5.
|
|
37
|
+
model: 'openai/gpt-5.6-sol',
|
|
38
38
|
memory: new Memory({
|
|
39
39
|
storage: new LibSQLStore({
|
|
40
40
|
id: 'agent-storage',
|
|
@@ -64,7 +64,7 @@ const agent = new Agent({
|
|
|
64
64
|
id: 'support-agent',
|
|
65
65
|
name: 'SupportAgent',
|
|
66
66
|
instructions: 'You are a helpful support agent.',
|
|
67
|
-
model: 'openai/gpt-5.
|
|
67
|
+
model: 'openai/gpt-5.6-sol',
|
|
68
68
|
memory: new Memory({
|
|
69
69
|
storage: new MongoDBStore({
|
|
70
70
|
id: 'agent-storage',
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
While [message history](https://mastra.ai/docs/memory/message-history) and [semantic recall](https://mastra.ai/docs/memory/semantic-recall) help agents remember conversations, working memory allows them to maintain persistent information about users across interactions.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Working memory is the agent's active scratchpad: key information it keeps available about the user or task. It can retain a person's name, preferences, or other important details during a conversation.
|
|
8
8
|
|
|
9
9
|
This is useful for maintaining ongoing state that's always relevant and should always be available to the agent.
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ Working memory can persist at two different scopes:
|
|
|
17
17
|
- **Resource-scoped** (default): Memory persists across all conversation threads for the same user
|
|
18
18
|
- **Thread-scoped**: Memory is isolated per conversation thread
|
|
19
19
|
|
|
20
|
-
**
|
|
20
|
+
**Requirement:** Switching between scopes means the agent won't see memory from the other scope - thread-scoped memory is completely separate from resource-scoped memory.
|
|
21
21
|
|
|
22
22
|
## Quickstart
|
|
23
23
|
|
|
@@ -32,7 +32,7 @@ const agent = new Agent({
|
|
|
32
32
|
id: 'personal-assistant',
|
|
33
33
|
name: 'PersonalAssistant',
|
|
34
34
|
instructions: 'You are a helpful personal assistant.',
|
|
35
|
-
model: 'openai/gpt-5.
|
|
35
|
+
model: 'openai/gpt-5.6-sol',
|
|
36
36
|
memory: new Memory({
|
|
37
37
|
options: {
|
|
38
38
|
workingMemory: {
|
|
@@ -45,7 +45,7 @@ const agent = new Agent({
|
|
|
45
45
|
|
|
46
46
|
## How it works
|
|
47
47
|
|
|
48
|
-
Working memory is a block of Markdown text that the agent
|
|
48
|
+
Working memory is a block of Markdown text that the agent can update over time to store continuously relevant information.
|
|
49
49
|
|
|
50
50
|
## Memory persistence scopes
|
|
51
51
|
|
|
@@ -134,7 +134,7 @@ Resource-scoped working memory requires specific storage adapters that support t
|
|
|
134
134
|
|
|
135
135
|
## Custom templates
|
|
136
136
|
|
|
137
|
-
Templates guide the agent on what information to track and update in working memory.
|
|
137
|
+
Templates guide the agent on what information to track and update in working memory. Mastra uses a default template when you don't provide one. Define a custom template for your agent's use case so it remembers the most relevant information. For threads shared by multiple users, see [Multi-user threads](https://mastra.ai/docs/memory/multi-user-threads).
|
|
138
138
|
|
|
139
139
|
Here's an example of a custom template. In this example the agent will store the users name, location, timezone, etc as soon as the user sends a message containing any of the info:
|
|
140
140
|
|
|
@@ -214,7 +214,7 @@ const paragraphMemory = new Memory({
|
|
|
214
214
|
|
|
215
215
|
Working memory can also be defined using a structured schema instead of a Markdown template. This allows you to specify the exact fields and types that should be tracked, using a [Standard JSON Schema](https://standardschema.dev/json-schema) ([Zod](https://zod.dev/), [Valibot](https://valibot.dev/), [ArkType](https://arktype.io/), etc.). When using a schema, the agent will see and update working memory as a JSON object matching your schema.
|
|
216
216
|
|
|
217
|
-
**
|
|
217
|
+
**Requirement:** You must specify either `template` or `schema`, but not both.
|
|
218
218
|
|
|
219
219
|
### Example: Schema-Based Working Memory
|
|
220
220
|
|
|
@@ -271,8 +271,8 @@ Schema-based working memory uses **merge semantics**, meaning the agent only nee
|
|
|
271
271
|
|
|
272
272
|
## Choosing between template and schema
|
|
273
273
|
|
|
274
|
-
- 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
|
|
275
|
-
- Use a **schema** if you need structured, type-safe data that can be validated and programmatically accessed as JSON. The `workingMemory.schema` field accepts any `PublicSchema`-compatible schema (including Zod v3, Zod v4, JSON Schema, or already-standard schemas). Schemas use **merge semantics
|
|
274
|
+
- 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.
|
|
275
|
+
- Use a **schema** if you need structured, type-safe data that can be validated and programmatically accessed as JSON. The `workingMemory.schema` field accepts any `PublicSchema`-compatible schema (including Zod v3, Zod v4, JSON Schema, or already-standard schemas). Schemas use **merge semantics**: the agent only provides fields to update, and existing fields are preserved.
|
|
276
276
|
- Only one mode can be active at a time: setting both `template` and `schema` isn't supported.
|
|
277
277
|
|
|
278
278
|
## Example: Multi-step retention
|
|
@@ -59,11 +59,11 @@ const results = await pgVector.query({
|
|
|
59
59
|
console.log('Similar chunks:', results)
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
This example shows the essentials
|
|
62
|
+
This example shows the essentials. Initialize a document and create chunks, then generate and store embeddings before querying for similar content.
|
|
63
63
|
|
|
64
64
|
## Document processing
|
|
65
65
|
|
|
66
|
-
The basic building block of RAG is document processing. Documents can be chunked using
|
|
66
|
+
The basic building block of RAG is document processing. Documents can be chunked using strategies (recursive, sliding window, etc.) and enriched with metadata. See the [chunking and embedding doc](https://mastra.ai/docs/rag/chunking-and-embedding).
|
|
67
67
|
|
|
68
68
|
## Vector storage
|
|
69
69
|
|
|
@@ -160,15 +160,15 @@ When creating the tool, pay special attention to the tool's name and description
|
|
|
160
160
|
|
|
161
161
|
This is particularly useful when:
|
|
162
162
|
|
|
163
|
-
- Your agent needs to
|
|
163
|
+
- Your agent needs to decide at runtime what information to retrieve
|
|
164
164
|
- The retrieval process requires complex decision-making
|
|
165
165
|
- You want the agent to combine multiple retrieval strategies based on context
|
|
166
166
|
|
|
167
167
|
#### Database-Specific Configurations
|
|
168
168
|
|
|
169
|
-
The Vector Query Tool supports database-specific configurations that enable you to
|
|
169
|
+
The Vector Query Tool supports database-specific configurations that enable you to use unique features and optimizations of different vector stores.
|
|
170
170
|
|
|
171
|
-
> **Note:** These configurations are for **query-time options** like namespaces, performance tuning, and filtering
|
|
171
|
+
> **Note:** These configurations are for **query-time options** like namespaces, performance tuning, and filtering, not for database connection setup.
|
|
172
172
|
>
|
|
173
173
|
> Connection credentials (URLs, auth tokens) are configured when you instantiate the vector store class (e.g., `new LibSQLVector({ url: '...' })`).
|
|
174
174
|
|
|
@@ -235,7 +235,7 @@ const lanceQueryTool = createVectorQueryTool({
|
|
|
235
235
|
- **pgVector optimization**: Control search accuracy and speed with ef/probes parameters
|
|
236
236
|
- **Quality filtering**: Set minimum similarity thresholds to improve result relevance
|
|
237
237
|
- **LanceDB tables**: Separate data into tables for better organization and performance
|
|
238
|
-
- **Runtime flexibility**: Override configurations
|
|
238
|
+
- **Runtime flexibility**: Override configurations at runtime based on context
|
|
239
239
|
|
|
240
240
|
**Common Use Cases:**
|
|
241
241
|
|
|
@@ -274,7 +274,7 @@ import { PGVECTOR_PROMPT } from '@mastra/pg'
|
|
|
274
274
|
export const ragAgent = new Agent({
|
|
275
275
|
id: 'rag-agent',
|
|
276
276
|
name: 'RAG Agent',
|
|
277
|
-
model: 'openai/gpt-5.
|
|
277
|
+
model: 'openai/gpt-5.6-sol',
|
|
278
278
|
instructions: `
|
|
279
279
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
280
280
|
${PGVECTOR_PROMPT}
|
|
@@ -291,7 +291,7 @@ import { PINECONE_PROMPT } from '@mastra/pinecone'
|
|
|
291
291
|
export const ragAgent = new Agent({
|
|
292
292
|
id: 'rag-agent',
|
|
293
293
|
name: 'RAG Agent',
|
|
294
|
-
model: 'openai/gpt-5.
|
|
294
|
+
model: 'openai/gpt-5.6-sol',
|
|
295
295
|
instructions: `
|
|
296
296
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
297
297
|
${PINECONE_PROMPT}
|
|
@@ -308,7 +308,7 @@ import { QDRANT_PROMPT } from '@mastra/qdrant'
|
|
|
308
308
|
export const ragAgent = new Agent({
|
|
309
309
|
id: 'rag-agent',
|
|
310
310
|
name: 'RAG Agent',
|
|
311
|
-
model: 'openai/gpt-5.
|
|
311
|
+
model: 'openai/gpt-5.6-sol',
|
|
312
312
|
instructions: `
|
|
313
313
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
314
314
|
${QDRANT_PROMPT}
|
|
@@ -325,7 +325,7 @@ import { CHROMA_PROMPT } from '@mastra/chroma'
|
|
|
325
325
|
export const ragAgent = new Agent({
|
|
326
326
|
id: 'rag-agent',
|
|
327
327
|
name: 'RAG Agent',
|
|
328
|
-
model: 'openai/gpt-5.
|
|
328
|
+
model: 'openai/gpt-5.6-sol',
|
|
329
329
|
instructions: `
|
|
330
330
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
331
331
|
${CHROMA_PROMPT}
|
|
@@ -342,7 +342,7 @@ import { ASTRA_PROMPT } from '@mastra/astra'
|
|
|
342
342
|
export const ragAgent = new Agent({
|
|
343
343
|
id: 'rag-agent',
|
|
344
344
|
name: 'RAG Agent',
|
|
345
|
-
model: 'openai/gpt-5.
|
|
345
|
+
model: 'openai/gpt-5.6-sol',
|
|
346
346
|
instructions: `
|
|
347
347
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
348
348
|
${ASTRA_PROMPT}
|
|
@@ -359,7 +359,7 @@ import { LIBSQL_PROMPT } from '@mastra/libsql'
|
|
|
359
359
|
export const ragAgent = new Agent({
|
|
360
360
|
id: 'rag-agent',
|
|
361
361
|
name: 'RAG Agent',
|
|
362
|
-
model: 'openai/gpt-5.
|
|
362
|
+
model: 'openai/gpt-5.6-sol',
|
|
363
363
|
instructions: `
|
|
364
364
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
365
365
|
${LIBSQL_PROMPT}
|
|
@@ -376,7 +376,7 @@ import { UPSTASH_PROMPT } from '@mastra/upstash'
|
|
|
376
376
|
export const ragAgent = new Agent({
|
|
377
377
|
id: 'rag-agent',
|
|
378
378
|
name: 'RAG Agent',
|
|
379
|
-
model: 'openai/gpt-5.
|
|
379
|
+
model: 'openai/gpt-5.6-sol',
|
|
380
380
|
instructions: `
|
|
381
381
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
382
382
|
${UPSTASH_PROMPT}
|
|
@@ -393,7 +393,7 @@ import { VECTORIZE_PROMPT } from '@mastra/vectorize'
|
|
|
393
393
|
export const ragAgent = new Agent({
|
|
394
394
|
id: 'rag-agent',
|
|
395
395
|
name: 'RAG Agent',
|
|
396
|
-
model: 'openai/gpt-5.
|
|
396
|
+
model: 'openai/gpt-5.6-sol',
|
|
397
397
|
instructions: `
|
|
398
398
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
399
399
|
${VECTORIZE_PROMPT}
|
|
@@ -410,7 +410,7 @@ import { MONGODB_PROMPT } from '@mastra/mongodb'
|
|
|
410
410
|
export const ragAgent = new Agent({
|
|
411
411
|
id: 'rag-agent',
|
|
412
412
|
name: 'RAG Agent',
|
|
413
|
-
model: 'openai/gpt-5.
|
|
413
|
+
model: 'openai/gpt-5.6-sol',
|
|
414
414
|
instructions: `
|
|
415
415
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
416
416
|
${MONGODB_PROMPT}
|
|
@@ -427,7 +427,7 @@ import { OPENSEARCH_PROMPT } from '@mastra/opensearch'
|
|
|
427
427
|
export const ragAgent = new Agent({
|
|
428
428
|
id: 'rag-agent',
|
|
429
429
|
name: 'RAG Agent',
|
|
430
|
-
model: 'openai/gpt-5.
|
|
430
|
+
model: 'openai/gpt-5.6-sol',
|
|
431
431
|
instructions: `
|
|
432
432
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
433
433
|
${OPENSEARCH_PROMPT}
|
|
@@ -444,7 +444,7 @@ import { S3VECTORS_PROMPT } from '@mastra/s3vectors'
|
|
|
444
444
|
export const ragAgent = new Agent({
|
|
445
445
|
id: 'rag-agent',
|
|
446
446
|
name: 'RAG Agent',
|
|
447
|
-
model: 'openai/gpt-5.
|
|
447
|
+
model: 'openai/gpt-5.6-sol',
|
|
448
448
|
instructions: `
|
|
449
449
|
Process queries using the provided context. Structure responses to be concise and relevant.
|
|
450
450
|
${S3VECTORS_PROMPT}
|
|
@@ -455,10 +455,10 @@ export const ragAgent = new Agent({
|
|
|
455
455
|
|
|
456
456
|
### Re-ranking
|
|
457
457
|
|
|
458
|
-
Initial vector similarity search can sometimes miss
|
|
458
|
+
Initial vector similarity search can sometimes miss detailed relevance. Re-ranking is a more computationally expensive process, but more accurate algorithm that improves results by:
|
|
459
459
|
|
|
460
460
|
- Considering word order and exact matches
|
|
461
|
-
- Applying more
|
|
461
|
+
- Applying more advanced relevance scoring
|
|
462
462
|
- Using a method called cross-attention between query and documents
|
|
463
463
|
|
|
464
464
|
Here's how to use re-ranking:
|
|
@@ -476,7 +476,7 @@ const initialResults = await pgVector.query({
|
|
|
476
476
|
// Create a relevance scorer
|
|
477
477
|
const relevanceProvider = new MastraAgentRelevanceScorer(
|
|
478
478
|
'relevance-scorer',
|
|
479
|
-
'openai/gpt-5.
|
|
479
|
+
'openai/gpt-5.6-sol',
|
|
480
480
|
)
|
|
481
481
|
|
|
482
482
|
// Re-rank the results
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Storing embeddings in a vector database
|
|
4
4
|
|
|
5
|
-
After generating embeddings, you need to store them in a database that supports vector similarity search. Mastra provides a consistent interface for storing and querying embeddings across
|
|
5
|
+
After generating embeddings, you need to store them in a database that supports vector similarity search. Mastra provides a consistent interface for storing and querying embeddings across vector databases.
|
|
6
6
|
|
|
7
7
|
## Supported databases
|
|
8
8
|
|
|
@@ -571,7 +571,7 @@ The upsert operation:
|
|
|
571
571
|
|
|
572
572
|
Vector stores support rich metadata (any JSON-serializable fields) for filtering and organization. Since metadata is stored with no fixed schema, use consistent field naming to avoid unexpected query results.
|
|
573
573
|
|
|
574
|
-
> **Warning:** Metadata is
|
|
574
|
+
> **Warning:** Metadata is important for vector storage. Without it, you'd only have numerical embeddings with no way to return the original text or filter results. Always store at least the source text as metadata.
|
|
575
575
|
|
|
576
576
|
```ts
|
|
577
577
|
// Store embeddings with rich metadata for better organization and filtering
|
|
@@ -14,7 +14,7 @@ Storage powers:
|
|
|
14
14
|
|
|
15
15
|
## When to configure storage
|
|
16
16
|
|
|
17
|
-
Configure a persistent storage adapter when state must survive restarts
|
|
17
|
+
Configure a persistent storage adapter when state must survive restarts or be shared across processes. Persistent storage also keeps state visible in Studio across sessions. The default in-memory store is useful for tests and short local experiments, but it loses data when the process exits.
|
|
18
18
|
|
|
19
19
|
Use storage when your application needs any of these behaviors:
|
|
20
20
|
|
|
@@ -144,7 +144,7 @@ export const supportAgent = new Agent({
|
|
|
144
144
|
id: 'support-agent',
|
|
145
145
|
name: 'Support agent',
|
|
146
146
|
instructions: 'Answer customer support questions.',
|
|
147
|
-
model: 'openai/gpt-5.
|
|
147
|
+
model: 'openai/gpt-5.6-sol',
|
|
148
148
|
memory: new Memory({
|
|
149
149
|
storage: new PostgresStore({
|
|
150
150
|
id: 'support-agent-storage',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Memory class
|
|
4
4
|
|
|
5
|
-
The `Memory` class provides a
|
|
5
|
+
The `Memory` class provides a reliable system for managing conversation history and thread-based message storage in Mastra. It enables persistent storage of conversations, semantic search capabilities, and efficient message retrieval. You must configure a storage provider for conversation history, and if you enable semantic recall you will also need to provide a vector store and embedder.
|
|
6
6
|
|
|
7
7
|
## Usage example
|
|
8
8
|
|
|
@@ -14,7 +14,7 @@ export const agent = new Agent({
|
|
|
14
14
|
id: 'test-agent',
|
|
15
15
|
name: 'test-agent',
|
|
16
16
|
instructions: 'You are an agent with memory.',
|
|
17
|
-
model: 'openai/gpt-5.
|
|
17
|
+
model: 'openai/gpt-5.6-sol',
|
|
18
18
|
memory: new Memory({
|
|
19
19
|
options: {
|
|
20
20
|
workingMemory: {
|
|
@@ -63,7 +63,7 @@ import { LibSQLStore, LibSQLVector } from '@mastra/libsql'
|
|
|
63
63
|
export const agent = new Agent({
|
|
64
64
|
name: 'test-agent',
|
|
65
65
|
instructions: 'You are an agent with memory.',
|
|
66
|
-
model: 'openai/gpt-5.
|
|
66
|
+
model: 'openai/gpt-5.6-sol',
|
|
67
67
|
memory: new Memory({
|
|
68
68
|
storage: new LibSQLStore({
|
|
69
69
|
id: 'test-agent-storage',
|
|
@@ -100,7 +100,7 @@ import { PgStore, PgVector } from '@mastra/pg'
|
|
|
100
100
|
export const agent = new Agent({
|
|
101
101
|
name: 'pg-agent',
|
|
102
102
|
instructions: 'You are an agent with optimized PostgreSQL memory.',
|
|
103
|
-
model: 'openai/gpt-5.
|
|
103
|
+
model: 'openai/gpt-5.6-sol',
|
|
104
104
|
memory: new Memory({
|
|
105
105
|
storage: new PgStore({
|
|
106
106
|
id: 'pg-agent-storage',
|
|
@@ -48,7 +48,7 @@ export const agent = new Agent({
|
|
|
48
48
|
id: 'memory-agent',
|
|
49
49
|
name: 'memory-agent',
|
|
50
50
|
instructions: 'You are a helpful assistant with conversation memory',
|
|
51
|
-
model: 'openai/gpt-5.
|
|
51
|
+
model: 'openai/gpt-5.6-sol',
|
|
52
52
|
inputProcessors: [
|
|
53
53
|
new MessageHistory({
|
|
54
54
|
storage,
|
|
@@ -85,7 +85,7 @@ export const agent = new Agent({
|
|
|
85
85
|
id: 'semantic-memory-agent',
|
|
86
86
|
name: 'semantic-memory-agent',
|
|
87
87
|
instructions: 'You are a helpful assistant with semantic memory recall',
|
|
88
|
-
model: 'openai/gpt-5.
|
|
88
|
+
model: 'openai/gpt-5.6-sol',
|
|
89
89
|
inputProcessors: [semanticRecall, new MessageHistory({ storage, lastMessages: 50 })],
|
|
90
90
|
outputProcessors: [semanticRecall, new MessageHistory({ storage })],
|
|
91
91
|
})
|
|
@@ -70,7 +70,7 @@ export const agent = new Agent({
|
|
|
70
70
|
id: 'personalized-agent',
|
|
71
71
|
name: 'personalized-agent',
|
|
72
72
|
instructions: 'You are a helpful assistant that remembers user preferences',
|
|
73
|
-
model: 'openai/gpt-5.
|
|
73
|
+
model: 'openai/gpt-5.6-sol',
|
|
74
74
|
inputProcessors: [
|
|
75
75
|
new WorkingMemory({
|
|
76
76
|
storage,
|
|
@@ -194,8 +194,8 @@ const results = await store.query({
|
|
|
194
194
|
|
|
195
195
|
- Equality values must be primitives (string/number/boolean). `null`/`undefined`, arrays, objects, and Date aren't allowed for equality. Range operators accept numbers or Date (Dates are normalized to epoch ms).
|
|
196
196
|
- `$in`/`$nin` require **non-empty arrays of primitives**; Date elements are allowed and normalized to epoch ms. **Array equality** isn't supported.
|
|
197
|
-
- Implicit AND is canonicalized (`{a:1,b:2}` → `{$and:[{a:1},{b:2}]
|
|
198
|
-
- Keys listed in `nonFilterableMetadataKeys` at index creation are stored but not filterable
|
|
197
|
+
- Implicit AND is canonicalized (`{a:1,b:2}` → `{$and:[{a:1},{b:2}]`). Logical operators must contain field conditions and use non-empty arrays. They may appear only at the root or within other logical operators (not inside field values).
|
|
198
|
+
- Keys listed in `nonFilterableMetadataKeys` at index creation are stored but not filterable. This setting is immutable.
|
|
199
199
|
- $exists requires a boolean value.
|
|
200
200
|
- undefined/null/empty filters are treated as no filter.
|
|
201
201
|
- Each metadata key name limited to 63 characters.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# DynamoDB storage
|
|
4
4
|
|
|
5
|
-
The DynamoDB storage implementation provides a
|
|
5
|
+
The DynamoDB storage implementation provides a high-capacity and performant NoSQL database solution for Mastra, using a single-table design pattern with [ElectroDB](https://electrodb.dev/).
|
|
6
6
|
|
|
7
7
|
> **Observability Not Supported:** DynamoDB storage **doesn't support the observability domain**. Traces from the `MastraStorageExporter` can't be persisted to DynamoDB, and [Studio's](https://mastra.ai/docs/studio/overview) 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.
|
|
8
8
|
|
|
@@ -124,7 +124,7 @@ For local development, you can use [DynamoDB Local](https://docs.aws.amazon.com/
|
|
|
124
124
|
|
|
125
125
|
## TTL (time to live) configuration
|
|
126
126
|
|
|
127
|
-
DynamoDB TTL allows you to automatically delete items after a specified
|
|
127
|
+
DynamoDB TTL allows you to automatically delete items after a specified duration for these use cases:
|
|
128
128
|
|
|
129
129
|
- **Cost optimization**: Automatically remove old data to reduce storage costs
|
|
130
130
|
- **Data lifecycle management**: Implement retention policies for compliance
|
|
@@ -259,19 +259,19 @@ Before diving into the architectural details, keep these key points in mind when
|
|
|
259
259
|
|
|
260
260
|
## Architectural approach
|
|
261
261
|
|
|
262
|
-
This storage adapter utilizes a **single-table design pattern**
|
|
262
|
+
This storage adapter utilizes a **single-table design pattern** with [ElectroDB](https://electrodb.dev/), a common and recommended approach for DynamoDB. This differs architecturally from relational database adapters (like `@mastra/pg` or `@mastra/libsql`) that typically use multiple tables, each dedicated to a specific entity (threads, messages, etc.).
|
|
263
263
|
|
|
264
264
|
Key aspects of this approach:
|
|
265
265
|
|
|
266
|
-
- **DynamoDB Native:** The single-table design is optimized for DynamoDB's key-value and query capabilities, often leading to better performance and
|
|
266
|
+
- **DynamoDB Native:** The single-table design is optimized for DynamoDB's key-value and query capabilities, often leading to better performance and capacity compared to mimicking relational models.
|
|
267
267
|
- **External Table Management:** Unlike some adapters that might offer helper functions to create tables via code, this adapter **expects the DynamoDB table and its associated Global Secondary Indexes (GSIs) to be provisioned externally** before use. Please refer to [TABLE\_SETUP.md](https://github.com/mastra-ai/mastra/blob/main/stores/dynamodb/TABLE_SETUP.md) for detailed instructions using tools like AWS CloudFormation or CDK. The adapter focuses solely on interacting with the pre-existing table structure.
|
|
268
268
|
- **Consistency via Interface:** While the underlying storage model differs, this adapter adheres to the same `MastraStorage` interface as other adapters, ensuring it can be used interchangeably within the Mastra `Memory` component.
|
|
269
269
|
|
|
270
270
|
### Mastra Data in the Single Table
|
|
271
271
|
|
|
272
|
-
Within the single DynamoDB table, different Mastra data entities (such as Threads, Messages, Traces, Evals, and Workflows) are managed and distinguished using ElectroDB. ElectroDB defines specific models for each entity type, which include unique key structures and attributes.
|
|
272
|
+
Within the single DynamoDB table, different Mastra data entities (such as Threads, Messages, Traces, Evals, and Workflows) are managed and distinguished using ElectroDB. ElectroDB defines specific models for each entity type, which include unique key structures and attributes. It allows the adapter to store and retrieve diverse data types efficiently within the same table.
|
|
273
273
|
|
|
274
|
-
For example, a `Thread` item might have a primary key like `THREAD#<threadId>`, while a `Message` item belonging to that thread might use `THREAD#<threadId>` as a partition key and `MESSAGE#<messageId>` as a sort key. The Global Secondary Indexes (GSIs), detailed in `TABLE_SETUP.md`, are strategically designed to support common access patterns across these different entities, such as fetching all messages for a thread or querying traces associated with a
|
|
274
|
+
For example, a `Thread` item might have a primary key like `THREAD#<threadId>`, while a `Message` item belonging to that thread might use `THREAD#<threadId>` as a partition key and `MESSAGE#<messageId>` as a sort key. The Global Secondary Indexes (GSIs), detailed in `TABLE_SETUP.md`, are strategically designed to support common access patterns across these different entities, such as fetching all messages for a thread or querying traces associated with a workflow.
|
|
275
275
|
|
|
276
276
|
### Advantages of Single-Table Design
|
|
277
277
|
|
|
@@ -279,6 +279,6 @@ This implementation uses a single-table design pattern with ElectroDB, which off
|
|
|
279
279
|
|
|
280
280
|
1. **Lower cost (potentially):** Fewer tables can simplify Read/Write Capacity Unit (RCU/WCU) provisioning and management, especially with on-demand capacity.
|
|
281
281
|
2. **Better performance:** Related data can be co-located or accessed efficiently through GSIs, enabling fast lookups for common access patterns.
|
|
282
|
-
3. **Simplified administration:** Fewer distinct tables to monitor
|
|
282
|
+
3. **Simplified administration:** Fewer distinct tables to monitor and back up, with less to manage.
|
|
283
283
|
4. **Reduced complexity in access patterns:** ElectroDB helps manage the complexity of item types and access patterns on a single table.
|
|
284
284
|
5. **Transaction support:** DynamoDB transactions can be used across different "entity" types stored within the same table if needed.
|
|
@@ -317,7 +317,7 @@ export const mastra = new Mastra({
|
|
|
317
317
|
})
|
|
318
318
|
```
|
|
319
319
|
|
|
320
|
-
|
|
320
|
+
The pattern ensures only one `PostgresStore` instance is created regardless of how many times the module is reloaded during development. The same pattern can be applied to other storage providers like `LibSQLStore`.
|
|
321
321
|
|
|
322
322
|
> **Tip:** This singleton pattern is only necessary during local development with HMR. In production builds, modules are only loaded once.
|
|
323
323
|
|
|
@@ -337,7 +337,7 @@ export const pgAgent = new Agent({
|
|
|
337
337
|
name: 'PG Agent',
|
|
338
338
|
instructions:
|
|
339
339
|
'You are an AI agent with the ability to automatically recall memories from previous interactions.',
|
|
340
|
-
model: 'openai/gpt-5.
|
|
340
|
+
model: 'openai/gpt-5.6-sol',
|
|
341
341
|
memory: new Memory({
|
|
342
342
|
storage: new PostgresStore({
|
|
343
343
|
id: 'pg-agent-storage',
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
Storage grows without bound by default. Retention is an opt-in, age-based cleanup system: you declare per-table `maxAge` policies in the `retention` config, then call `storage.prune()` to delete rows older than their configured age. Anything you don't configure is kept forever, so there is no behavior change until you opt in.
|
|
6
6
|
|
|
7
|
-
`prune()` deletes rows. It caps growth and is safe to run against large tables (batched, bounded, resumable, cancellable). It never reclaims disk
|
|
7
|
+
`prune()` deletes rows. It caps growth and is safe to run against large tables (batched, bounded, resumable, cancellable). It never reclaims disk: on SQLite/libSQL the freed pages are reused by future writes so the file stops growing, but handing disk back to the OS (for example a `VACUUM`) is left to the underlying database and the operator to manage.
|
|
8
8
|
|
|
9
|
-
Retention covers **growth tables** only
|
|
9
|
+
Retention covers **growth tables** only: tables that accumulate rows unbounded as a side effect of normal operation (conversation history, telemetry, job and run records, schedule fire history, event feeds). User-authored artifacts and config (agents, skills, workspaces, prompt blocks, datasets, schedule definitions, channel installations, and so on) grow with user intent and are edited or deleted explicitly, so they're not valid retention keys.
|
|
10
10
|
|
|
11
11
|
The reference implementations are [libSQL](https://mastra.ai/reference/storage/libsql), [PostgreSQL](https://mastra.ai/reference/storage/postgresql), and [MongoDB](https://mastra.ai/reference/storage/mongodb). Other adapters keep rows forever until they implement retention.
|
|
12
12
|
|
|
@@ -31,7 +31,7 @@ const storage = new LibSQLStore({
|
|
|
31
31
|
},
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
-
// Wire this to your own cron/scheduler
|
|
34
|
+
// Wire this to your own cron/scheduler: Mastra never runs it for you.
|
|
35
35
|
const results = await storage.prune()
|
|
36
36
|
```
|
|
37
37
|
|
|
@@ -65,35 +65,35 @@ Set the `retention` field on the store config.
|
|
|
65
65
|
|
|
66
66
|
### Retention-eligible tables
|
|
67
67
|
|
|
68
|
-
Each domain declares which of its tables can be age-pruned and which timestamp column anchors the comparison. The anchor is chosen so `maxAge` means what you'd expect for that data
|
|
69
|
-
|
|
70
|
-
| Domain | Table key | Anchor column | `maxAge` measures
|
|
71
|
-
| ----------------- | ------------------ | ---------------- |
|
|
72
|
-
| `memory` | `threads` | `createdAt` | Thread age
|
|
73
|
-
| `memory` | `messages` | `createdAt` | Message age
|
|
74
|
-
| `memory` | `resources` | `createdAt` | Resource age
|
|
75
|
-
| `threadState` | `threadState` | `updatedAt` | Inactivity
|
|
76
|
-
| `observability` | `spans` | `startedAt` | Span age
|
|
77
|
-
| `observability` | `metrics` | `timestamp` | Metric event age (v-next only)
|
|
78
|
-
| `observability` | `logs` | `timestamp` | Log event age (v-next only)
|
|
79
|
-
| `observability` | `scores` | `timestamp` | Score event age (v-next only)
|
|
80
|
-
| `observability` | `feedback` | `timestamp` | Feedback event age (v-next only)
|
|
81
|
-
| `scores` | `scorers` | `createdAt` | Score record age
|
|
82
|
-
| `workflows` | `workflowSnapshot` | `updatedAt` | Inactivity
|
|
83
|
-
| `backgroundTasks` | `backgroundTasks` | `completedAt` | Time since completion
|
|
84
|
-
| `experiments` | `experiments` | `completedAt` | Time since completion
|
|
85
|
-
| `notifications` | `notifications` | `createdAt` | Notification age
|
|
86
|
-
| `harness` | `sessions` | `createdAt` | Session record age
|
|
87
|
-
| `schedules` | `triggers` | `actual_fire_at` | Fire-history age (epoch-ms column)
|
|
68
|
+
Each domain declares which of its tables can be age-pruned and which timestamp column anchors the comparison. The anchor is chosen so `maxAge` means what you'd expect for that data. Append-only logs use creation time, and live state uses last activity. Jobs and runs use completion time, so in-flight work is never pruned.
|
|
69
|
+
|
|
70
|
+
| Domain | Table key | Anchor column | `maxAge` measures |
|
|
71
|
+
| ----------------- | ------------------ | ---------------- | ---------------------------------------------------------------- |
|
|
72
|
+
| `memory` | `threads` | `createdAt` | Thread age |
|
|
73
|
+
| `memory` | `messages` | `createdAt` | Message age |
|
|
74
|
+
| `memory` | `resources` | `createdAt` | Resource age |
|
|
75
|
+
| `threadState` | `threadState` | `updatedAt` | Inactivity: state for still-active threads survives |
|
|
76
|
+
| `observability` | `spans` | `startedAt` | Span age |
|
|
77
|
+
| `observability` | `metrics` | `timestamp` | Metric event age (v-next only) |
|
|
78
|
+
| `observability` | `logs` | `timestamp` | Log event age (v-next only) |
|
|
79
|
+
| `observability` | `scores` | `timestamp` | Score event age (v-next only) |
|
|
80
|
+
| `observability` | `feedback` | `timestamp` | Feedback event age (v-next only) |
|
|
81
|
+
| `scores` | `scorers` | `createdAt` | Score record age |
|
|
82
|
+
| `workflows` | `workflowSnapshot` | `updatedAt` | Inactivity, suspended or long-running workflows survive |
|
|
83
|
+
| `backgroundTasks` | `backgroundTasks` | `completedAt` | Time since completion, in-flight tasks (`NULL`) are never pruned |
|
|
84
|
+
| `experiments` | `experiments` | `completedAt` | Time since completion, running experiments are never pruned |
|
|
85
|
+
| `notifications` | `notifications` | `createdAt` | Notification age |
|
|
86
|
+
| `harness` | `sessions` | `createdAt` | Session record age |
|
|
87
|
+
| `schedules` | `triggers` | `actual_fire_at` | Fire-history age (epoch-ms column) |
|
|
88
88
|
|
|
89
89
|
> **Note:**
|
|
90
90
|
>
|
|
91
91
|
> - The memory `observational_memory` table has no timestamp anchor, so it can't be age-pruned and isn't a valid retention key.
|
|
92
92
|
> - Experiments prune as whole units: an aged experiment's result rows are deleted together with it (results cascade with their parent), so a run is never left partially deleted. Retention doesn't have a separate `results` key.
|
|
93
|
-
> - For `schedules`, the growth table is the fire history (`schedule_triggers`, one row per fire)
|
|
93
|
+
> - For `schedules`, the growth table is the fire history (`schedule_triggers`, one row per fire): schedule definitions are config and aren't pruned.
|
|
94
94
|
> - On PostgreSQL, timestamp anchors use the timezone-aware mirror columns (for example `createdAtZ`, `completedAtZ`).
|
|
95
95
|
> - LibSQL supports all domains above; PostgreSQL and MongoDB support all except `threadState` and `harness`, which they don't implement.
|
|
96
|
-
> - The v-next PostgreSQL observability domain stores signal events in day-partitioned tables (`spans`, `metrics`, `logs`, `scores`, `feedback`). For it, `prune()` drops whole day partitions (or TimescaleDB chunks) that are entirely older than the cutoff instead of deleting rows
|
|
96
|
+
> - The v-next PostgreSQL observability domain stores signal events in day-partitioned tables (`spans`, `metrics`, `logs`, `scores`, `feedback`). For it, `prune()` drops whole day partitions (or TimescaleDB chunks) that are entirely older than the cutoff instead of deleting rows: effective level of detail is one day, and a partition is only dropped once its entire day is past `maxAge`. `PruneResult.deleted` reports the number of rows in the dropped partitions.
|
|
97
97
|
|
|
98
98
|
## Methods
|
|
99
99
|
|
|
@@ -103,11 +103,11 @@ Each domain declares which of its tables can be age-pruned and which timestamp c
|
|
|
103
103
|
|
|
104
104
|
Deletes rows older than their configured `maxAge` across every domain that has a policy in `retention`. Returns one `PruneResult` per table touched. With no `retention` configured it's a no-op returning `[]`.
|
|
105
105
|
|
|
106
|
-
`prune()` is designed to be safe on tables with millions of rows. It deletes in bounded, batched chunks
|
|
106
|
+
`prune()` is designed to be safe on tables with millions of rows. It deletes in bounded, batched chunks (each batch is its own transaction) so it never takes a long lock or bloats the transaction log. It never runs a `VACUUM`.
|
|
107
107
|
|
|
108
|
-
Pass `options.retention` to replace the configured policies for that call only
|
|
108
|
+
Pass `options.retention` to replace the configured policies for that call only: for example to skip a domain (keep chat history) or prune more aggressively than the standing config. The store's configured `retention` is unchanged.
|
|
109
109
|
|
|
110
|
-
Anchor-column indexes are created lazily on the first `prune()` call for each table with a policy
|
|
110
|
+
Anchor-column indexes are created lazily on the first `prune()` call for each table with a policy (never at `init()`) so deployments that don't configure retention pay no extra index write or disk overhead. The first prune of an existing large table pays a one-time index build. Subsequent prunes reuse the index.
|
|
111
111
|
|
|
112
112
|
```typescript
|
|
113
113
|
const results = await storage.prune({
|
|
@@ -156,7 +156,7 @@ interface PruneResult {
|
|
|
156
156
|
|
|
157
157
|
## Running prune on a schedule
|
|
158
158
|
|
|
159
|
-
`prune()` has no built-in scheduler
|
|
159
|
+
`prune()` has no built-in scheduler: you decide when it runs. Because it's bounded, a single call may not delete everything. When any result has `done: false`, eligible rows remain and you call again on the next tick. This keeps each invocation short and lets a large backlog drain over several runs.
|
|
160
160
|
|
|
161
161
|
```typescript
|
|
162
162
|
// Runs on your own cron (node-cron, a workflow schedule, an external job, etc.).
|
|
@@ -173,7 +173,7 @@ async function retentionTick() {
|
|
|
173
173
|
}
|
|
174
174
|
```
|
|
175
175
|
|
|
176
|
-
You can also cancel a long-running prune with an `AbortSignal
|
|
176
|
+
You can also cancel a long-running prune with an `AbortSignal`: the loop stops between batches and returns partial results with `done: false`, so the next run resumes cleanly.
|
|
177
177
|
|
|
178
178
|
## MongoDB TTL indexes (alternative to prune)
|
|
179
179
|
|
|
@@ -192,7 +192,7 @@ MongoDB offers native [TTL (Time-To-Live) indexes](https://www.mongodb.com/docs/
|
|
|
192
192
|
> - You need resumable, cancellable cleanup operations
|
|
193
193
|
> - You're using composite storage with multiple databases
|
|
194
194
|
>
|
|
195
|
-
> Both approaches are valid. TTL is simpler
|
|
195
|
+
> Both approaches are valid. TTL is simpler. `prune()` gives more control.
|
|
196
196
|
|
|
197
197
|
### Setting up TTL indexes on MongoDB
|
|
198
198
|
|
|
@@ -232,9 +232,9 @@ const storage = new MongoDBStore({
|
|
|
232
232
|
|
|
233
233
|
## Reclaiming disk
|
|
234
234
|
|
|
235
|
-
`prune()` deletes rows but doesn't shrink the database file. On SQLite/libSQL the freed pages go on a freelist and are reused by future writes, so the file stops growing
|
|
235
|
+
`prune()` deletes rows but doesn't shrink the database file. On SQLite/libSQL the freed pages go on a freelist and are reused by future writes, so the file stops growing: for most users this alone solves the unbounded-growth problem.
|
|
236
236
|
|
|
237
|
-
Handing that free space back to the OS is a separate concern that Mastra doesn't manage. If you specifically need to shrink the file, run the underlying database's compaction (for example `VACUUM` on self-hosted libSQL) yourself
|
|
237
|
+
Handing that free space back to the OS is a separate concern that Mastra doesn't manage. If you specifically need to shrink the file, run the underlying database's compaction (for example `VACUUM` on self-hosted libSQL) yourself in a maintenance window. A full `VACUUM` locks the file and needs roughly twice the file size in free disk. On PostgreSQL, autovacuum reclaims dead tuples for reuse automatically; a manual `VACUUM FULL` is only needed if you must return disk to the OS.
|
|
238
238
|
|
|
239
239
|
For MongoDB, deleted documents are reused by future insertions. To reclaim disk space, run [`db.runCommand({ compact: "collection_name" })`](https://www.mongodb.com/docs/manual/reference/command/compact/) during a maintenance window.
|
|
240
240
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# createVectorQueryTool()
|
|
4
4
|
|
|
5
|
-
The `createVectorQueryTool()` function creates a tool for semantic search over vector stores. It supports filtering, reranking, database-specific configurations, and integrates with
|
|
5
|
+
The `createVectorQueryTool()` function creates a tool for semantic search over vector stores. It supports filtering, reranking, database-specific configurations, and integrates with vector store backends.
|
|
6
6
|
|
|
7
7
|
## Basic usage
|
|
8
8
|
|
|
@@ -69,7 +69,7 @@ const queryTool = createVectorQueryTool({
|
|
|
69
69
|
|
|
70
70
|
**databaseConfig.chroma.whereDocument** (`Record<string, any>`): Document content filtering conditions
|
|
71
71
|
|
|
72
|
-
**providerOptions** (`Record<string, Record<string, any>>`): Provider-specific options for the embedding model (e.g., outputDimensionality).
|
|
72
|
+
**providerOptions** (`Record<string, Record<string, any>>`): Provider-specific options for the embedding model (e.g., outputDimensionality). Only works with AI SDK EmbeddingModelV2 models. For V1 models, configure options when creating the model itself.
|
|
73
73
|
|
|
74
74
|
**vectorStore** (`MastraVector | VectorStoreResolver`): Direct vector store instance or a resolver function for dynamic selection. Use a function for multi-tenant applications where the vector store is selected based on request context. When provided, vectorStoreName becomes optional.
|
|
75
75
|
|
|
@@ -144,7 +144,7 @@ const queryTool = createVectorQueryTool({
|
|
|
144
144
|
indexName: 'documentation',
|
|
145
145
|
model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
|
|
146
146
|
reranker: {
|
|
147
|
-
model: 'openai/gpt-5.
|
|
147
|
+
model: 'openai/gpt-5.6-sol',
|
|
148
148
|
options: {
|
|
149
149
|
weights: {
|
|
150
150
|
semantic: 0.5, // Semantic relevance weight
|
|
@@ -182,7 +182,7 @@ This example shows how to customize the tool description for a specific use case
|
|
|
182
182
|
|
|
183
183
|
## Database-specific configuration examples
|
|
184
184
|
|
|
185
|
-
The `databaseConfig` parameter allows you to
|
|
185
|
+
The `databaseConfig` parameter allows you to use features and optimizations specific to each vector database. These configurations are automatically applied during query execution.
|
|
186
186
|
|
|
187
187
|
**Pinecone**:
|
|
188
188
|
|
|
@@ -475,7 +475,7 @@ const result = await vectorQueryTool.execute(
|
|
|
475
475
|
)
|
|
476
476
|
```
|
|
477
477
|
|
|
478
|
-
This pattern is similar to how `Agent.memory` supports
|
|
478
|
+
This pattern is similar to how `Agent.memory` supports runtime-defined configuration and enables:
|
|
479
479
|
|
|
480
480
|
- **Schema isolation**: Each tenant's data in separate PostgreSQL schemas
|
|
481
481
|
- **Database isolation**: Route to different database instances per tenant
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# PG vector store
|
|
4
4
|
|
|
5
|
-
The PgVector class provides vector search using [PostgreSQL](https://www.postgresql.org/) with [pgvector](https://github.com/pgvector/pgvector) extension. It provides
|
|
5
|
+
The PgVector class provides vector search using [PostgreSQL](https://www.postgresql.org/) with [pgvector](https://github.com/pgvector/pgvector) extension. It provides reliable vector similarity search capabilities within your existing PostgreSQL database.
|
|
6
6
|
|
|
7
7
|
## Constructor options
|
|
8
8
|
|
|
@@ -110,13 +110,13 @@ const vectorStore = new PgVector({
|
|
|
110
110
|
|
|
111
111
|
#### Memory Requirements
|
|
112
112
|
|
|
113
|
-
HNSW indexes require
|
|
113
|
+
HNSW indexes require substantial shared memory during construction. For 100K vectors:
|
|
114
114
|
|
|
115
115
|
- Small dimensions (64d): \~60MB with default settings
|
|
116
116
|
- Medium dimensions (256d): \~180MB with default settings
|
|
117
117
|
- Large dimensions (384d+): \~250MB+ with default settings
|
|
118
118
|
|
|
119
|
-
Higher M values or efConstruction values will increase memory requirements
|
|
119
|
+
Higher M values or efConstruction values will increase memory requirements substantially. Adjust your system's shared memory limits if needed.
|
|
120
120
|
|
|
121
121
|
### `upsert()`
|
|
122
122
|
|
|
@@ -340,7 +340,7 @@ The system automatically detects configuration changes and only rebuilds indexes
|
|
|
340
340
|
- Regularly evaluate your index configuration to ensure optimal performance.
|
|
341
341
|
- Adjust parameters like `lists` and `m` based on dataset size and query requirements.
|
|
342
342
|
- **Monitor index performance** using `describeIndex()` to track usage
|
|
343
|
-
- Rebuild indexes periodically to maintain efficiency, especially after
|
|
343
|
+
- Rebuild indexes periodically to maintain efficiency, especially after substantial data changes
|
|
344
344
|
|
|
345
345
|
## Direct pool access
|
|
346
346
|
|
|
@@ -403,7 +403,7 @@ export const pgAgent = new Agent({
|
|
|
403
403
|
name: 'PG Agent',
|
|
404
404
|
instructions:
|
|
405
405
|
'You are an AI agent with the ability to automatically recall memories from previous interactions.',
|
|
406
|
-
model: 'openai/gpt-5.
|
|
406
|
+
model: 'openai/gpt-5.6-sol',
|
|
407
407
|
memory: new Memory({
|
|
408
408
|
storage: new PostgresStore({
|
|
409
409
|
id: 'pg-agent-storage',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/pg",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.1",
|
|
4
4
|
"description": "Postgres provider for Mastra - includes both vector and db storage capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
"license": "Apache-2.0",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"async-mutex": "^0.5.0",
|
|
24
|
-
"pg": "^8.
|
|
24
|
+
"pg": "^8.22.0",
|
|
25
25
|
"pg-connection-string": "^2.12.0",
|
|
26
26
|
"xxhash-wasm": "^1.1.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "22.20.1",
|
|
30
|
-
"@types/pg": "^8.
|
|
30
|
+
"@types/pg": "^8.20.0",
|
|
31
31
|
"@vitest/coverage-v8": "4.1.10",
|
|
32
32
|
"@vitest/ui": "4.1.10",
|
|
33
33
|
"eslint": "^10.7.0",
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"tsx": "^4.23.1",
|
|
36
36
|
"typescript": "^6.0.3",
|
|
37
37
|
"vitest": "4.1.10",
|
|
38
|
-
"@internal/lint": "0.0.
|
|
39
|
-
"@internal/storage-test-utils": "0.0.
|
|
40
|
-
"@
|
|
41
|
-
"@
|
|
38
|
+
"@internal/lint": "0.0.119",
|
|
39
|
+
"@internal/storage-test-utils": "0.0.115",
|
|
40
|
+
"@mastra/core": "1.55.0",
|
|
41
|
+
"@internal/types-builder": "0.0.94"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@mastra/core": ">=1.51.0-0 <2.0.0-0"
|