@mastra/libsql 1.18.0 → 1.19.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.
Files changed (34) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/dist/docs/SKILL.md +4 -3
  3. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  4. package/dist/docs/references/docs-agent-builder-deploying.md +2 -2
  5. package/dist/docs/references/docs-agent-builder-overview.md +1 -1
  6. package/dist/docs/references/docs-agents-agent-approval.md +85 -11
  7. package/dist/docs/references/docs-agents-networks.md +2 -2
  8. package/dist/docs/references/docs-deployment-workers.md +137 -0
  9. package/dist/docs/references/docs-memory-memory-processors.md +10 -10
  10. package/dist/docs/references/docs-memory-message-history.md +11 -5
  11. package/dist/docs/references/docs-memory-multi-user-threads.md +6 -6
  12. package/dist/docs/references/docs-memory-overview.md +24 -10
  13. package/dist/docs/references/docs-memory-semantic-recall.md +3 -3
  14. package/dist/docs/references/docs-memory-working-memory.md +8 -8
  15. package/dist/docs/references/docs-rag-retrieval.md +18 -18
  16. package/dist/docs/references/docs-storage-overview.md +2 -2
  17. package/dist/docs/references/docs-workflows-snapshots.md +3 -3
  18. package/dist/docs/references/reference-core-mastra-class.md +48 -1
  19. package/dist/docs/references/reference-file-based-agents-storage.md +1 -1
  20. package/dist/docs/references/reference-memory-memory-class.md +4 -4
  21. package/dist/docs/references/reference-storage-dynamodb.md +7 -7
  22. package/dist/docs/references/reference-storage-retention.md +33 -33
  23. package/dist/docs/references/reference-vectors-libsql.md +2 -2
  24. package/dist/index.cjs +193 -19
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.js +194 -21
  27. package/dist/index.js.map +1 -1
  28. package/dist/storage/domains/datasets/index.d.ts.map +1 -1
  29. package/dist/storage/domains/experiments/index.d.ts.map +1 -1
  30. package/dist/storage/domains/workflow-definitions/index.d.ts +14 -0
  31. package/dist/storage/domains/workflow-definitions/index.d.ts.map +1 -0
  32. package/dist/storage/index.d.ts +2 -1
  33. package/dist/storage/index.d.ts.map +1 -1
  34. package/package.json +5 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,67 @@
1
1
  # @mastra/libsql
2
2
 
3
+ ## 1.19.0-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Stored workflow definitions now persist across restarts on every major database backend. ([#20471](https://github.com/mastra-ai/mastra/pull/20471))
8
+
9
+ Implement the `workflowDefinitions` storage domain for libsql, pg, mysql, mssql, mongodb, and spanner. Previously the stored-workflow persistence path (`POST /stored/workflows`, `Mastra.addStoredWorkflow`) only worked against `@mastra/core`'s in-memory store. Persistent adapters returned `undefined` from `storage.getStore('workflowDefinitions')` and threw when the HTTP handler tried to read/write a workflow.
10
+
11
+ ```ts
12
+ const workflowDefinitions = await storage.getStore('workflowDefinitions');
13
+ if (!workflowDefinitions) {
14
+ throw new Error('This storage adapter does not support the workflowDefinitions domain');
15
+ }
16
+
17
+ await workflowDefinitions.upsert({
18
+ id: 'greeting-workflow',
19
+ inputSchema: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] },
20
+ outputSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
21
+ graph: [{ type: 'agent', id: 'greet', agentId: 'greeter-agent' }],
22
+ });
23
+
24
+ const { definitions, total } = await workflowDefinitions.list({ status: 'active' });
25
+ const definition = await workflowDefinitions.get('greeting-workflow');
26
+ await workflowDefinitions.delete('greeting-workflow');
27
+ ```
28
+
29
+ Each adapter now ships a `WorkflowDefinitions*` domain that:
30
+
31
+ - Creates the shared `mastra_workflow_definitions` table (or Mongo collection) from `WORKFLOW_DEFINITIONS_SCHEMA` during `init()`, plus a default index on `status`.
32
+ - Implements `upsert` / `get` / `list` / `delete` matching `WorkflowDefinitionsStorage` semantics (`list` supports `status` and `authorId` filters and orders by `updatedAt` desc). Partial upserts preserve unspecified fields, including `authorId` updates and `createdAt` / `updatedAt` semantics.
33
+ - Handles concurrent first-writes race-safely: if two callers upsert the same new id simultaneously, the losing insert detects the duplicate key, re-reads the row, and applies the partial-update path instead of failing.
34
+ - Round-trips the JSON columns (`inputSchema`, `outputSchema`, `stateSchema`, `requestContextSchema`, `metadata`, `graph`) through each adapter's JSON handling, so declarative workflow graphs rehydrate identically no matter which backend they were stored in. Malformed persisted JSON surfaces as an actionable error naming the row and column instead of hydrating raw strings.
35
+
36
+ Exported class names by adapter: `WorkflowDefinitionsLibSQL`, `WorkflowDefinitionsPG`, `WorkflowDefinitionsMySQL`, `WorkflowDefinitionsMSSQL`, `MongoDBWorkflowDefinitionsStore`, `WorkflowDefinitionsSpanner`. The composite stores (`LibSQLStore`, `PostgresStore`, `MySQLStore`, `MSSQLStore`, `MongoDBStore`, `SpannerStore`) auto-wire the new domain, so callers do not need to construct it manually — `storage.getStore('workflowDefinitions')` now returns a live handle.
37
+
38
+ The pg adapter reads `createdAt` / `updatedAt` from the auto-added `createdAtZ` / `updatedAtZ` `timestamptz` companion columns to avoid the naive-timestamp / local-TZ drift that a plain `TIMESTAMP` read exhibits under node-pg.
39
+
40
+ `@mastra/clickhouse` and `@mastra/cloudflare` register the new `mastra_workflow_definitions` table in their table/type maps so shared table constants stay exhaustive (no workflow-definitions domain implementation yet).
41
+
42
+ - Updated dependencies [[`4844167`](https://github.com/mastra-ai/mastra/commit/4844167cff2d5ec5004e94edd34970833040fa3f), [`5faf93f`](https://github.com/mastra-ai/mastra/commit/5faf93f03e19daea394b9e2a923f2e4f833407f2), [`80ad891`](https://github.com/mastra-ai/mastra/commit/80ad891f8cd10379aa5b5af7510c763783b2ab56), [`a1cb98d`](https://github.com/mastra-ai/mastra/commit/a1cb98d11990b560b98482292a1f34aa1a2d9092), [`598ad82`](https://github.com/mastra-ai/mastra/commit/598ad82d41c41389a686338a1d0e50b7400e1938), [`1fd6aad`](https://github.com/mastra-ai/mastra/commit/1fd6aad1ea4a9d32f65efa832307c35e981a4c0a)]:
43
+ - @mastra/core@1.56.0-alpha.4
44
+
45
+ ## 1.19.0-alpha.0
46
+
47
+ ### Minor Changes
48
+
49
+ - Added persistence for dataset item undeclared tool policies. ([#19643](https://github.com/mastra-ai/mastra/pull/19643))
50
+
51
+ ```typescript
52
+ await dataset.addItem({
53
+ input: 'What is the weather?',
54
+ unmockedToolPolicy: 'deny',
55
+ });
56
+ ```
57
+
58
+ ### Patch Changes
59
+
60
+ - Added a comment column to experiment results so review comments persist. The column is added automatically and non-destructively on startup for existing databases (https://github.com/mastra-ai/mastra/issues/19857). ([#19865](https://github.com/mastra-ai/mastra/pull/19865))
61
+
62
+ - Updated dependencies [[`c5e56ff`](https://github.com/mastra-ai/mastra/commit/c5e56ff3bcabdf062708f2d48744fec304df6792), [`4e35a56`](https://github.com/mastra-ai/mastra/commit/4e35a56cdf8d74a5ff6d5eda01f2c1deaf6cc7be)]:
63
+ - @mastra/core@1.56.0-alpha.1
64
+
3
65
  ## 1.18.0
4
66
 
5
67
  ### Minor Changes
@@ -3,7 +3,7 @@ name: mastra-libsql
3
3
  description: Documentation for @mastra/libsql. Use when working with @mastra/libsql APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/libsql"
6
- version: "1.18.0"
6
+ version: "1.19.0-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -18,8 +18,9 @@ Read the individual reference documents for detailed explanations and code examp
18
18
 
19
19
  - [Deploying](references/docs-agent-builder-deploying.md) - Swap local Agent Builder primitives for cloud-backed storage, filesystems, sandboxes, an EE license, auth, and a public channel URL for production.
20
20
  - [Agent Builder overview](references/docs-agent-builder-overview.md) - Let teammates create, configure, and operate Mastra agents from a browser, with admin-pinned defaults, RBAC, and channel integrations.
21
- - [Agent approval](references/docs-agents-agent-approval.md) - Learn how to require approvals, suspend tool execution, and automatically resume suspended tools while keeping humans in control of agent workflows.
21
+ - [Agent approval](references/docs-agents-agent-approval.md) - Learn how to require approvals and suspend tool execution, plus automatically resume suspended tools while keeping humans in control of agent workflows.
22
22
  - [Agent networks](references/docs-agents-networks.md) - Coordinate multiple agents, workflows, and tools using agent networks for complex, non-deterministic task execution.
23
+ - [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.
23
24
  - [Memory processors](references/docs-memory-memory-processors.md) - Learn how to use memory processors in Mastra to filter, trim, and transform messages before they're sent to the language model to manage context window limits.
24
25
  - [Message history](references/docs-memory-message-history.md) - Learn how to configure message history in Mastra to store recent messages from the current conversation.
25
26
  - [Multi-user threads](references/docs-memory-multi-user-threads.md) - Share one Mastra thread between multiple users by carrying speaker identity in the message body.
@@ -41,7 +42,7 @@ Read the individual reference documents for detailed explanations and code examp
41
42
  - [Reference: Mastra class](references/reference-core-mastra-class.md) - Documentation for the `Mastra` class in Mastra, the core entry point for managing agents, workflows, MCP servers, and server endpoints.
42
43
  - [Memory](references/reference-file-based-agents-memory.md) - Give a file-based agent persistent memory with a memory.ts module.
43
44
  - [Storage](references/reference-file-based-agents-storage.md) - Set the default Mastra store by file convention with storage.ts.
44
- - [Reference: Memory class](references/reference-memory-memory-class.md) - Documentation for the `Memory` class in Mastra, which provides a robust system for managing conversation history and thread-based message storage.
45
+ - [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.
45
46
  - [Reference: Composite storage](references/reference-storage-composite.md) - Documentation for combining multiple storage backends in Mastra.
46
47
  - [Reference: DynamoDB storage](references/reference-storage-dynamodb.md) - Documentation for the DynamoDB storage implementation in Mastra, using a single-table design with ElectroDB.
47
48
  - [Reference: libSQL storage](references/reference-storage-libsql.md) - Documentation for the libSQL storage implementation in Mastra.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.18.0",
2
+ "version": "1.19.0-alpha.1",
3
3
  "package": "@mastra/libsql",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -10,8 +10,8 @@ Production deployments swap the local primitives in the Quickstart for cloud-bac
10
10
 
11
11
  1. **EE license**: A valid `MASTRA_EE_LICENSE` so the server will start with the Builder enabled.
12
12
  2. **Hosted storage**: A shared store for agents, skills, runs, and memory.
13
- 3. **Shared workspace filesystem**: Survives across instances; `local` is single-node only.
14
- 4. **Cloud sandbox**: Runs agent commands safely; `local` is unsafe in shared environments.
13
+ 3. **Shared workspace filesystem**: Survives across instances. `local` is single-node only.
14
+ 4. **Cloud sandbox**: Runs agent commands safely. `local` is unsafe in shared environments.
15
15
  5. **Auth and RBAC**: Gates the Builder UI and `/agent-builder/*` routes.
16
16
  6. **Public base URL for channels**: Slack and other channel providers need a reachable URL.
17
17
 
@@ -58,7 +58,7 @@ yarn add @mastra/editor @mastra/libsql
58
58
  bun add @mastra/editor @mastra/libsql
59
59
  ```
60
60
 
61
- The example below defines a storage adapter, registers a builder agent, and enables the editor as explained in the prerequisites:
61
+ The example below defines a storage adapter and registers a builder agent, plus enables the editor as explained in the prerequisites:
62
62
 
63
63
  ```typescript
64
64
  import { Mastra } from '@mastra/core/mastra'
@@ -6,7 +6,7 @@ Agents sometimes require the same [human-in-the-loop](https://mastra.ai/docs/wor
6
6
 
7
7
  ## When to use agent approval
8
8
 
9
- - **Destructive or irreversible actions** such as deleting records, sending emails, or processing payments.
9
+ - **Destructive or irreversible actions** such as deleting records or sending emails, or alternatively processing payments.
10
10
  - **Cost-heavy operations** like calling expensive third-party APIs where you want to verify arguments first.
11
11
  - **Conditional confirmation** where a tool starts executing and then discovers it needs the user to confirm or supply extra data before finishing.
12
12
 
@@ -60,7 +60,7 @@ Mastra offers two distinct mechanisms for pausing tool calls: **pre-execution ap
60
60
 
61
61
  Pre-execution approval pauses a tool call _before_ its `execute` function runs. The LLM still decides which tool to call and provides arguments, but `execute` doesn't run until you explicitly approve.
62
62
 
63
- Two flags control this, combined with OR logic. If _either_ is `true`, the call pauses:
63
+ The flags control this, combined with OR logic. If _either_ is `true`, the call pauses:
64
64
 
65
65
  | Flag | Where to set it | Scope |
66
66
  | --------------------------- | --------------------------------- | ------------------------------------------- |
@@ -92,7 +92,7 @@ for await (const chunk of stream.fullStream) {
92
92
 
93
93
  #### Conditional approval with a function
94
94
 
95
- Instead of a boolean, `requireToolApproval` accepts a function that decides per tool call. It receives the `toolName`, the `args` the model passed, the `requestContext`, and the `workspace`. Return `true` to require approval for that call, or `false` to allow it. This lets you gate approval dynamically for example, only for tools whose name matches a pattern:
95
+ Instead of a boolean, `requireToolApproval` accepts a function that decides per tool call. It receives the `toolName`, the `args` the model passed, the `requestContext`, and the `workspace`. Return `true` to require approval for that call, or `false` to allow it. This lets you gate approval at runtime, for example, only for tools whose name matches a pattern:
96
96
 
97
97
  ```typescript
98
98
  const stream = await agent.stream('Clean up old records', {
@@ -100,10 +100,82 @@ const stream = await agent.stream('Clean up old records', {
100
100
  })
101
101
  ```
102
102
 
103
- A tool's own `requireApproval` setting still takes precedence: if a tool defines its own approval rule, that rule decides for that tool and the function above doesn't override it. If the function throws, the call requires approval (fail-safe).
103
+ A tool's own `requireApproval` setting takes precedence over the function above. Its rule decides whether that tool needs approval. If the function throws, the call requires approval as a fail-safe.
104
104
 
105
105
  > **Note:** Function-based `requireToolApproval` is only available on regular `stream()` / `generate()` calls. Durable agents and stored agents persist their options, and a function can't be serialized, so they accept only a boolean. If you pass a function in those contexts it falls back to requiring approval for every tool call.
106
106
 
107
+ #### Bind approval to the exact tool arguments
108
+
109
+ For sensitive tools, bind the approval to the exact tool name and arguments that were shown to the reviewer. If those arguments drift before execution, the tool shouldn't run under the old approval.
110
+
111
+ The `tool-call-approval` chunk already includes `toolName`, `toolCallId`, and `args`. You can fingerprint those fields when the approval request is shown. The example below uses a JSON string as the fingerprint, but in production you should use a stable hash of the tool name and arguments:
112
+
113
+ ```typescript
114
+ import { Agent } from '@mastra/core/agent'
115
+
116
+ // For your production usecase, build a stable hash of the tool name and args
117
+ function actionFingerprint(toolName: string, args: unknown) {
118
+ const payload = JSON.stringify({ toolName, args })
119
+ return `fingerprint-${payload}`
120
+ }
121
+
122
+ const sensitiveTools = new Set(['issue_refund', 'delete_record'])
123
+ const approvedFingerprints = new Set<string>()
124
+
125
+ export const approvalBoundAgent = new Agent({
126
+ id: 'approval-bound-agent',
127
+ name: 'Approval Bound Agent',
128
+ model: 'openai/gpt-5.6-sol',
129
+ tools: { issueRefundTool, deleteRecordTool },
130
+ hooks: {
131
+ beforeToolCall: ({ toolName, input }) => {
132
+ if (!sensitiveTools.has(toolName)) return
133
+
134
+ const fingerprint = actionFingerprint(toolName, input)
135
+ if (!approvedFingerprints.delete(fingerprint)) {
136
+ return {
137
+ proceed: false,
138
+ output: `Tool call blocked: approval did not match ${toolName} arguments.`,
139
+ }
140
+ }
141
+ },
142
+ },
143
+ })
144
+ ```
145
+
146
+ ```typescript
147
+ const stream = await approvalBoundAgent.stream('Refund order ord-1042', {
148
+ requireToolApproval: ({ toolName }) => sensitiveTools.has(toolName),
149
+ })
150
+
151
+ async function consumeApprovalStream(currentStream: typeof stream) {
152
+ for await (const chunk of currentStream.fullStream) {
153
+ if (chunk.type === 'tool-call-approval') {
154
+ const { toolName, toolCallId, args } = chunk.payload
155
+ const fingerprint = actionFingerprint(toolName, args)
156
+
157
+ // Present toolName, args, and fingerprint to your approval UI.
158
+ const approved = await showApprovalDialog({ toolName, args, fingerprint })
159
+
160
+ const nextStream = approved
161
+ ? await approveReviewedToolCall(currentStream.runId, toolCallId, fingerprint)
162
+ : await approvalBoundAgent.declineToolCall({ runId: currentStream.runId, toolCallId })
163
+
164
+ await consumeApprovalStream(nextStream)
165
+ }
166
+ }
167
+ }
168
+
169
+ async function approveReviewedToolCall(runId: string, toolCallId: string, fingerprint: string) {
170
+ approvedFingerprints.add(fingerprint)
171
+ return approvalBoundAgent.approveToolCall({ runId, toolCallId })
172
+ }
173
+
174
+ await consumeApprovalStream(stream)
175
+ ```
176
+
177
+ In production, store the approved fingerprint in durable storage scoped to the user, run, tool call, and policy version. The `Set` above is intentionally small so the boundary is clear: the approval is consumed once, and only for the same canonical tool arguments that were reviewed.
178
+
107
179
  ### Runtime suspension with `suspend()`
108
180
 
109
181
  A tool can also pause _during_ its `execute` function by calling `suspend()`. This is useful when the tool starts running and then discovers it needs additional user input or confirmation before it can finish.
@@ -133,7 +205,7 @@ const weatherTool = createTool({
133
205
  })
134
206
  ```
135
207
 
136
- > **Note:** `suspend()` doesn't throw return immediately after calling it (e.g. `return await suspend({ ... })`). Code after `await suspend(...)` still runs before the tool pauses.
208
+ > **Note:** `suspend()` doesn't throw, return immediately after calling it (e.g. `return await suspend({ ... })`). Code after `await suspend(...)` still runs before the tool pauses.
137
209
 
138
210
  ## Tool approval with `generate()`
139
211
 
@@ -172,11 +244,11 @@ if (output.finishReason === 'suspended') {
172
244
  | Decline method | `declineToolCall({ runId })` | `declineToolCallGenerate({ runId, toolCallId })` |
173
245
  | Result | Stream to iterate | Full output object |
174
246
 
175
- > **Note:** `toolCallId` is optional on all four methods. Pass it when multiple tool calls may be pending at the same time (common in supervisor agents). When omitted, the agent resumes the most recent suspended tool call.
247
+ > **Note:** `toolCallId` is optional on all four methods. Pass it when multiple tool calls may be pending (common in supervisor agents). When omitted, the agent resumes the most recent suspended tool call.
176
248
 
177
249
  ## Tool-level approval
178
250
 
179
- Instead of pausing every tool call at the agent level, you can mark individual tools as requiring approval. This gives you granular control: only specific tools pause, while others execute immediately.
251
+ Instead of pausing every tool call at the agent level, you can mark individual tools as requiring approval. You get fine-grained control: only specific tools pause, while others execute immediately.
180
252
 
181
253
  ### Approval using `requireApproval`
182
254
 
@@ -303,7 +375,9 @@ const agent = new Agent({
303
375
  })
304
376
  ```
305
377
 
306
- When enabled, the agent detects suspended tools from message history on the next user message, extracts `resumeData` based on the tool's `resumeSchema`, and automatically resumes the tool. The following example shows a complete conversational flow:
378
+ When enabled, the agent detects suspended tools from message history on the next user message. It extracts `resumeData` based on the tool's `resumeSchema`, then automatically resumes the tool.
379
+
380
+ The following example shows a complete conversational flow:
307
381
 
308
382
  ```typescript
309
383
  import { createTool } from '@mastra/core/tools'
@@ -386,7 +460,7 @@ Both approaches work with the same tool definitions. Automatic resumption trigge
386
460
 
387
461
  ## Resuming after a restart
388
462
 
389
- The examples above hold on to `stream.runId` between suspension and approval. That works while the process stays alive, but in production the approval often arrives later after a page refresh, a server restart, or on a different server instance behind a load balancer.
463
+ The examples above hold on to `stream.runId` between suspension and approval. That works while the process stays alive, but in production the approval often arrives later, after a page refresh, a server restart, or on a different server instance behind a load balancer.
390
464
 
391
465
  Use [`listSuspendedRuns()`](https://mastra.ai/reference/agents/listSuspendedRuns) to rediscover the pending run for a conversation from storage:
392
466
 
@@ -414,7 +488,7 @@ if (run && toolCall) {
414
488
  }
415
489
  ```
416
490
 
417
- Each returned run includes the suspended tool calls (`toolCallId`, `toolName`, `args`, and `requiresApproval`). Approval suspensions (`requiresApproval: true`) are answered with `approveToolCall()` / `declineToolCall()`, while `suspend()`-based suspensions carry their `suspendPayload` and expect `resumeStream()` with resume data so you can rebuild the right UI for either flow without keeping any state in memory.
491
+ Each returned run includes the suspended tool calls (`toolCallId`, `toolName`, `args`, and `requiresApproval`). Approval suspensions (`requiresApproval: true`) are answered with `approveToolCall()` / `declineToolCall()`, while `suspend()`-based suspensions carry their `suspendPayload` and expect `resumeStream()` with resume data, so you can rebuild the right UI for either flow without keeping any state in memory.
418
492
 
419
493
  `sendToolApproval()` uses the same storage-backed discovery automatically: when no active run is found in memory for the thread, it looks up the suspended run in storage before failing. If several suspended runs match the thread, pass a `toolCallId` to disambiguate.
420
494
 
@@ -477,7 +551,7 @@ const supervisorAgent = new Agent({
477
551
  name: 'Supervisor Agent',
478
552
  instructions: `You coordinate data retrieval tasks.
479
553
  Delegate to data-agent for user lookups.`,
480
- model: 'openai/gpt-5.5',
554
+ model: 'openai/gpt-5.6-sol',
481
555
  agents: { dataAgent },
482
556
  memory: new Memory(),
483
557
  })
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Agent networks
4
4
 
5
- > **Deprecated — Use supervisor agents:** Agent networks are deprecated and will be removed in a future major release. [Supervisor agents](https://mastra.ai/docs/agents/supervisor-agents) using `agent.stream()` or `agent.generate()` are now the recommended approach. It provides the same multi-agent coordination with better control, a simpler API, and easier debugging.
5
+ > **Deprecated:** Agent networks are deprecated and will be removed in a future major release. [Supervisor agents](https://mastra.ai/docs/agents/supervisor-agents) using `agent.stream()` or `agent.generate()` are now the recommended approach. It provides the same multi-agent coordination with better control, a simpler API, and easier debugging.
6
6
  >
7
7
  > See the [migration guide](https://mastra.ai/guides/migrations/network-to-supervisor) to upgrade.
8
8
 
@@ -29,7 +29,7 @@ export const routingAgent = new Agent({
29
29
  name: 'Routing Agent',
30
30
  instructions: `
31
31
  You are a network of writers and researchers. The user will ask you to research a topic. Always respond with a complete report—no bullet points. Write in full paragraphs, like a blog post. Do not answer with incomplete or uncertain information.`,
32
- model: 'openai/gpt-5.5',
32
+ model: 'openai/gpt-5.6-sol',
33
33
  agents: {
34
34
  researchAgent,
35
35
  writingAgent,
@@ -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 fast, 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's 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
+ **Don't 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 mode (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 in their own processes, 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 Docker Compose and Kubernetes examples.
110
+
111
+ ## Network architecture
112
+
113
+ Workers are internal infrastructure. They're not exposed to end users and don't 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, including 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 don't 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's no DLQ for events that fail after all retries.
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 and Kubernetes examples
133
+ - [Worker authentication](https://mastra.ai/docs/server/auth/workers): Secure worker-to-API communication
134
+ - [Workers reference](https://mastra.ai/reference/workers/overview): Details about worker environment variables and types, with a list of supported 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
@@ -2,9 +2,9 @@
2
2
 
3
3
  # Memory processors
4
4
 
5
- Memory processors transform and filter messages as they pass through an agent with memory enabled. They manage context window limits, remove unnecessary content, and optimize the information sent to the language model.
5
+ Memory processors transform and filter messages as they pass through an agent with memory enabled. They manage context window limits and remove unnecessary content, plus optimize the information sent to the language model.
6
6
 
7
- When memory is enabled on an agent, Mastra adds memory processors to the agent's processor pipeline. These processors retrieve message history, working memory, and semantically relevant messages, then persist new messages after the model responds.
7
+ When memory is enabled on an agent, Mastra adds memory processors to the agent's processor pipeline. These processors retrieve message history and working memory, plus semantically relevant messages, then persist new messages after the model responds.
8
8
 
9
9
  Memory processors are [processors](https://mastra.ai/docs/agents/processors) that operate specifically on memory-related messages and state.
10
10
 
@@ -47,7 +47,7 @@ const agent = new Agent({
47
47
  id: 'test-agent',
48
48
  name: 'Test Agent',
49
49
  instructions: 'You are a helpful assistant',
50
- model: 'openai/gpt-5.5',
50
+ model: 'openai/gpt-5.6-sol',
51
51
  memory: new Memory({
52
52
  storage: new LibSQLStore({
53
53
  id: 'memory-store',
@@ -97,7 +97,7 @@ import { openai } from '@ai-sdk/openai'
97
97
  const agent = new Agent({
98
98
  name: 'semantic-agent',
99
99
  instructions: 'You are a helpful assistant with semantic memory',
100
- model: 'openai/gpt-5.5',
100
+ model: 'openai/gpt-5.6-sol',
101
101
  memory: new Memory({
102
102
  storage: new LibSQLStore({
103
103
  id: 'memory-store',
@@ -150,7 +150,7 @@ import { openai } from '@ai-sdk/openai'
150
150
  const agent = new Agent({
151
151
  name: 'working-memory-agent',
152
152
  instructions: 'You are an assistant with working memory',
153
- model: 'openai/gpt-5.5',
153
+ model: 'openai/gpt-5.6-sol',
154
154
  memory: new Memory({
155
155
  storage: new LibSQLStore({
156
156
  id: 'memory-store',
@@ -182,7 +182,7 @@ const customMessageHistory = new MessageHistory({
182
182
  const agent = new Agent({
183
183
  name: 'custom-memory-agent',
184
184
  instructions: 'You are a helpful assistant',
185
- model: 'openai/gpt-5.5',
185
+ model: 'openai/gpt-5.6-sol',
186
186
  memory: new Memory({
187
187
  storage: new LibSQLStore({ id: 'memory-store', url: 'file:memory.db' }),
188
188
  lastMessages: 10, // This would normally add MessageHistory(10)
@@ -207,7 +207,7 @@ Understanding the execution order is important when combining guardrails with me
207
207
  1. **Memory processors run FIRST**: `WorkingMemory`, `MessageHistory`, `SemanticRecall`
208
208
  2. **Your input processors run AFTER**: guardrails, filters, validators
209
209
 
210
- This means memory loads message history before your processors can validate or filter the input.
210
+ As a result, memory loads message history before your processors can validate or filter the input.
211
211
 
212
212
  ### Output Processors
213
213
 
@@ -253,7 +253,7 @@ const agent = new Agent({
253
253
  id: 'safe-agent',
254
254
  name: 'safe-agent',
255
255
  instructions: 'You are a helpful assistant',
256
- model: 'openai/gpt-5.5',
256
+ model: 'openai/gpt-5.6-sol',
257
257
  memory: new Memory({ lastMessages: 10 }),
258
258
  // Your guardrail runs BEFORE memory saves
259
259
  outputProcessors: [contentBlocker],
@@ -293,7 +293,7 @@ const agent = new Agent({
293
293
  id: 'validated-agent',
294
294
  name: 'validated-agent',
295
295
  instructions: 'You are a helpful assistant',
296
- model: 'openai/gpt-5.5',
296
+ model: 'openai/gpt-5.6-sol',
297
297
  memory: new Memory({ lastMessages: 10 }),
298
298
  // Your guardrail runs AFTER memory loads history
299
299
  inputProcessors: [inputValidator],
@@ -370,7 +370,7 @@ export const supportAgent = new Agent({
370
370
  id: 'support-agent',
371
371
  name: 'Support agent',
372
372
  instructions: 'Answer customer support questions.',
373
- model: 'openai/gpt-5.5',
373
+ model: 'openai/gpt-5.6-sol',
374
374
  memory: new Memory({ lastMessages: 10 }),
375
375
  inputProcessors: [new AttachmentUploader()],
376
376
  })
@@ -134,7 +134,7 @@ export const supportAgent = new Agent({
134
134
  id: 'support-agent',
135
135
  name: 'Support agent',
136
136
  instructions: 'Answer customer support questions.',
137
- model: 'openai/gpt-5.5',
137
+ model: 'openai/gpt-5.6-sol',
138
138
  memory: new Memory({
139
139
  options: {
140
140
  generateTitle: true,
@@ -155,7 +155,7 @@ export const supportAgent = new Agent({
155
155
  id: 'support-agent',
156
156
  name: 'Support agent',
157
157
  instructions: 'Answer customer support questions.',
158
- model: 'openai/gpt-5.5',
158
+ model: 'openai/gpt-5.6-sol',
159
159
  memory: new Memory({
160
160
  options: {
161
161
  generateTitle: {
@@ -176,7 +176,7 @@ const agent = mastra.getAgentById('test-agent')
176
176
  const memory = await agent.getMemory()
177
177
  ```
178
178
 
179
- The `Memory` instance gives you access to functions for listing threads, recalling messages, cloning conversations, and more.
179
+ The `Memory` instance gives you access to functions for listing threads and recalling messages, plus cloning conversations, and more.
180
180
 
181
181
  ## Querying
182
182
 
@@ -279,7 +279,13 @@ const { messages } = await memory.recall({
279
279
  })
280
280
  ```
281
281
 
282
- Metadata filters match shallow scalar values only: `string`, finite `number`, `boolean`, and `null`. All specified metadata keys must match with AND semantics, and `null` matches an explicit `null` value, not a missing metadata key. Metadata keys must start with a letter or underscore, may contain only alphanumeric characters and underscores, must be 128 characters or fewer, and can't use reserved prototype keys such as `__proto__`, `constructor`, or `prototype`. Performance depends on the storage backend. Some backends can push parts of the filter into the database, while others scan candidate messages after thread, resource, and date constraints are applied but before pagination.
282
+ Metadata filters match shallow scalar values only: `string`, finite `number`, `boolean`, and `null`.
283
+
284
+ All specified metadata keys use AND semantics. A `null` filter matches only an explicit `null` value. A missing metadata key doesn't match.
285
+
286
+ Metadata keys must start with a letter or underscore and contain only alphanumeric characters. They must be 128 characters or fewer and can't use reserved prototype keys such as `__proto__`, `constructor`, or `prototype`.
287
+
288
+ Performance depends on the storage backend. Some backends can push parts of the filter into the database, while others scan candidate messages after thread, resource, and date constraints are applied but before pagination.
283
289
 
284
290
  Fetch a single message by ID:
285
291
 
@@ -324,7 +330,7 @@ Message queries return `MastraDBMessage[]` format. To display messages in a fron
324
330
 
325
331
  ## Thread cloning
326
332
 
327
- Thread cloning creates a copy of an existing thread with its messages. This is useful for branching conversations, creating checkpoints before a potentially destructive operation, or testing variations of a conversation.
333
+ Thread cloning creates a copy of an existing thread with its messages. This is useful for branching conversations or creating checkpoints before a potentially destructive operation, or alternatively testing variations of a conversation.
328
334
 
329
335
  ```typescript
330
336
  const { thread, clonedMessages } = await memory.cloneThread({