@mastra/libsql 0.0.0-error-handler-fix-20251020202607 → 0.0.0-everlasting-joggers-20260331153923

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 (73) hide show
  1. package/CHANGELOG.md +3120 -3
  2. package/LICENSE.md +15 -0
  3. package/README.md +30 -20
  4. package/dist/docs/SKILL.md +46 -0
  5. package/dist/docs/assets/SOURCE_MAP.json +6 -0
  6. package/dist/docs/references/docs-agents-agent-approval.md +509 -0
  7. package/dist/docs/references/docs-agents-networks.md +182 -0
  8. package/dist/docs/references/docs-memory-memory-processors.md +314 -0
  9. package/dist/docs/references/docs-memory-message-history.md +262 -0
  10. package/dist/docs/references/docs-memory-overview.md +240 -0
  11. package/dist/docs/references/docs-memory-semantic-recall.md +297 -0
  12. package/dist/docs/references/docs-memory-storage.md +261 -0
  13. package/dist/docs/references/docs-memory-working-memory.md +400 -0
  14. package/dist/docs/references/docs-rag-retrieval.md +515 -0
  15. package/dist/docs/references/docs-workflows-snapshots.md +238 -0
  16. package/dist/docs/references/guides-agent-frameworks-ai-sdk.md +140 -0
  17. package/dist/docs/references/reference-core-getMemory.md +49 -0
  18. package/dist/docs/references/reference-core-listMemory.md +55 -0
  19. package/dist/docs/references/reference-core-mastra-class.md +66 -0
  20. package/dist/docs/references/reference-memory-memory-class.md +145 -0
  21. package/dist/docs/references/reference-storage-composite.md +243 -0
  22. package/dist/docs/references/reference-storage-dynamodb.md +282 -0
  23. package/dist/docs/references/reference-storage-libsql.md +135 -0
  24. package/dist/docs/references/reference-vectors-libsql.md +305 -0
  25. package/dist/index.cjs +9006 -1972
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.js +8993 -1973
  28. package/dist/index.js.map +1 -1
  29. package/dist/storage/db/index.d.ts +318 -0
  30. package/dist/storage/db/index.d.ts.map +1 -0
  31. package/dist/storage/{domains → db}/utils.d.ts +21 -13
  32. package/dist/storage/db/utils.d.ts.map +1 -0
  33. package/dist/storage/domains/agents/index.d.ts +30 -0
  34. package/dist/storage/domains/agents/index.d.ts.map +1 -0
  35. package/dist/storage/domains/blobs/index.d.ts +17 -0
  36. package/dist/storage/domains/blobs/index.d.ts.map +1 -0
  37. package/dist/storage/domains/datasets/index.d.ts +43 -0
  38. package/dist/storage/domains/datasets/index.d.ts.map +1 -0
  39. package/dist/storage/domains/experiments/index.d.ts +31 -0
  40. package/dist/storage/domains/experiments/index.d.ts.map +1 -0
  41. package/dist/storage/domains/mcp-clients/index.d.ts +26 -0
  42. package/dist/storage/domains/mcp-clients/index.d.ts.map +1 -0
  43. package/dist/storage/domains/mcp-servers/index.d.ts +26 -0
  44. package/dist/storage/domains/mcp-servers/index.d.ts.map +1 -0
  45. package/dist/storage/domains/memory/index.d.ts +41 -53
  46. package/dist/storage/domains/memory/index.d.ts.map +1 -1
  47. package/dist/storage/domains/observability/index.d.ts +41 -29
  48. package/dist/storage/domains/observability/index.d.ts.map +1 -1
  49. package/dist/storage/domains/prompt-blocks/index.d.ts +25 -0
  50. package/dist/storage/domains/prompt-blocks/index.d.ts.map +1 -0
  51. package/dist/storage/domains/scorer-definitions/index.d.ts +26 -0
  52. package/dist/storage/domains/scorer-definitions/index.d.ts.map +1 -0
  53. package/dist/storage/domains/scores/index.d.ts +19 -31
  54. package/dist/storage/domains/scores/index.d.ts.map +1 -1
  55. package/dist/storage/domains/skills/index.d.ts +26 -0
  56. package/dist/storage/domains/skills/index.d.ts.map +1 -0
  57. package/dist/storage/domains/workflows/index.d.ts +20 -32
  58. package/dist/storage/domains/workflows/index.d.ts.map +1 -1
  59. package/dist/storage/domains/workspaces/index.d.ts +26 -0
  60. package/dist/storage/domains/workspaces/index.d.ts.map +1 -0
  61. package/dist/storage/index.d.ts +68 -259
  62. package/dist/storage/index.d.ts.map +1 -1
  63. package/dist/vector/index.d.ts +12 -4
  64. package/dist/vector/index.d.ts.map +1 -1
  65. package/dist/vector/sql-builder.d.ts.map +1 -1
  66. package/package.json +17 -13
  67. package/dist/storage/domains/legacy-evals/index.d.ts +0 -18
  68. package/dist/storage/domains/legacy-evals/index.d.ts.map +0 -1
  69. package/dist/storage/domains/operations/index.d.ts +0 -110
  70. package/dist/storage/domains/operations/index.d.ts.map +0 -1
  71. package/dist/storage/domains/traces/index.d.ts +0 -21
  72. package/dist/storage/domains/traces/index.d.ts.map +0 -1
  73. package/dist/storage/domains/utils.d.ts.map +0 -1
package/LICENSE.md CHANGED
@@ -1,3 +1,18 @@
1
+ Portions of this software are licensed as follows:
2
+
3
+ - All content that resides under any directory named "ee/" within this
4
+ repository, including but not limited to:
5
+ - `packages/core/src/auth/ee/`
6
+ - `packages/server/src/server/auth/ee/`
7
+ is licensed under the license defined in `ee/LICENSE`.
8
+
9
+ - All third-party components incorporated into the Mastra Software are
10
+ licensed under the original license provided by the owner of the
11
+ applicable component.
12
+
13
+ - Content outside of the above-mentioned directories or restrictions is
14
+ available under the "Apache License 2.0" as defined below.
15
+
1
16
  # Apache License 2.0
2
17
 
3
18
  Copyright (c) 2025 Kepler Software, Inc.
package/README.md CHANGED
@@ -50,31 +50,38 @@ const results = await vectorStore.query({
50
50
  import { LibSQLStore } from '@mastra/libsql';
51
51
 
52
52
  const store = new LibSQLStore({
53
+ id: 'libsql-storage',
53
54
  url: 'file:./my-db.db',
54
55
  });
55
56
 
56
57
  // Create a thread
57
58
  await store.saveThread({
58
- id: 'thread-123',
59
- resourceId: 'resource-456',
60
- title: 'My Thread',
61
- metadata: { key: 'value' },
59
+ thread: {
60
+ id: 'thread-123',
61
+ resourceId: 'resource-456',
62
+ title: 'My Thread',
63
+ metadata: { key: 'value' },
64
+ createdAt: new Date(),
65
+ },
62
66
  });
63
67
 
64
68
  // Add messages to thread
65
- await store.saveMessages([
66
- {
67
- id: 'msg-789',
68
- threadId: 'thread-123',
69
- role: 'user',
70
- type: 'text',
71
- content: [{ type: 'text', text: 'Hello' }],
72
- },
73
- ]);
69
+ await store.saveMessages({
70
+ messages: [
71
+ {
72
+ id: 'msg-789',
73
+ threadId: 'thread-123',
74
+ role: 'user',
75
+ content: { content: 'Hello' },
76
+ resourceId: 'resource-456',
77
+ createdAt: new Date(),
78
+ },
79
+ ],
80
+ });
74
81
 
75
82
  // Query threads and messages
76
- const savedThread = await store.getThread('thread-123');
77
- const messages = await store.getMessages('thread-123');
83
+ const savedThread = await store.getThreadById({ threadId: 'thread-123' });
84
+ const messages = await store.listMessages({ threadId: 'thread-123' });
78
85
  ```
79
86
 
80
87
  ## Configuration
@@ -124,6 +131,9 @@ Example filter:
124
131
  - `createIndex({indexName, dimension, metric?, indexConfig?, defineIndex?})`: Create a new table with vector support
125
132
  - `upsert({indexName, vectors, metadata?, ids?})`: Add or update vectors
126
133
  - `query({indexName, queryVector, topK?, filter?, includeVector?, minScore?})`: Search for similar vectors
134
+ - `updateVector({ indexName, id?, filter?, update })`: Update a single vector by ID or metadata filter
135
+ - `deleteVector({ indexName, id })`: Delete a single vector by ID
136
+ - `deleteVectors({ indexName, ids?, filter? })`: Delete multiple vectors by IDs or metadata filter
127
137
  - `defineIndex({indexName, metric?, indexConfig?})`: Define an index
128
138
  - `listIndexes()`: List all vector-enabled tables
129
139
  - `describeIndex(indexName)`: Get table statistics
@@ -132,11 +142,11 @@ Example filter:
132
142
 
133
143
  ## Storage Methods
134
144
 
135
- - `saveThread(thread)`: Create or update a thread
136
- - `getThread(threadId)`: Get a thread by ID
137
- - `deleteThread(threadId)`: Delete a thread and its messages
138
- - `saveMessages(messages)`: Save multiple messages in a transaction
139
- - `getMessages(threadId)`: Get all messages for a thread
145
+ - `saveThread({ thread })`: Create or update a thread
146
+ - `getThreadById({ threadId })`: Get a thread by ID
147
+ - `deleteThread({ threadId })`: Delete a thread and its messages
148
+ - `saveMessages({ messages })`: Save multiple messages in a transaction
149
+ - `listMessages({ threadId, perPage?, page? })`: Get messages for a thread with pagination
140
150
  - `deleteMessages(messageIds)`: Delete specific messages
141
151
 
142
152
  ## Related Links
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: mastra-libsql
3
+ description: Documentation for @mastra/libsql. Use when working with @mastra/libsql APIs, configuration, or implementation.
4
+ metadata:
5
+ package: "@mastra/libsql"
6
+ version: "0.0.0-everlasting-joggers-20260331153923"
7
+ ---
8
+
9
+ ## When to use
10
+
11
+ Use this skill whenever you are working with @mastra/libsql to obtain the domain-specific knowledge.
12
+
13
+ ## How to use
14
+
15
+ Read the individual reference documents for detailed explanations and code examples.
16
+
17
+ ### Docs
18
+
19
+ - [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.
20
+ - [Agent networks](references/docs-agents-networks.md) - Coordinate multiple agents, workflows, and tools using agent networks for complex, non-deterministic task execution.
21
+ - [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.
22
+ - [Message history](references/docs-memory-message-history.md) - Learn how to configure message history in Mastra to store recent messages from the current conversation.
23
+ - [Memory overview](references/docs-memory-overview.md) - Learn how Mastra's memory system works with working memory, message history, semantic recall, and observational memory.
24
+ - [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.
25
+ - [Storage](references/docs-memory-storage.md) - Configure storage for Mastra to persist conversations and other runtime state.
26
+ - [Working memory](references/docs-memory-working-memory.md) - Learn how to configure working memory in Mastra to store persistent user data, preferences.
27
+ - [Retrieval, semantic search, reranking](references/docs-rag-retrieval.md) - Guide on retrieval processes in Mastra's RAG systems, including semantic search, filtering, and re-ranking.
28
+ - [Snapshots](references/docs-workflows-snapshots.md) - Learn how to save and resume workflow execution state with snapshots in Mastra
29
+
30
+ ### Guides
31
+
32
+ - [AI SDK](references/guides-agent-frameworks-ai-sdk.md) - Use Mastra processors and memory with the Vercel AI SDK
33
+
34
+ ### Reference
35
+
36
+ - [Reference: Mastra.getMemory()](references/reference-core-getMemory.md) - Documentation for the `Mastra.getMemory()` method in Mastra, which retrieves a registered memory instance by its registry key.
37
+ - [Reference: Mastra.listMemory()](references/reference-core-listMemory.md) - Documentation for the `Mastra.listMemory()` method in Mastra, which returns all registered memory instances.
38
+ - [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.
39
+ - [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.
40
+ - [Reference: Composite storage](references/reference-storage-composite.md) - Documentation for combining multiple storage backends in Mastra.
41
+ - [Reference: DynamoDB storage](references/reference-storage-dynamodb.md) - Documentation for the DynamoDB storage implementation in Mastra, using a single-table design with ElectroDB.
42
+ - [Reference: libSQL storage](references/reference-storage-libsql.md) - Documentation for the libSQL storage implementation in Mastra.
43
+ - [Reference: libSQL vector store](references/reference-vectors-libsql.md) - Documentation for the LibSQLVector class in Mastra, which provides vector search using libSQL with vector extensions.
44
+
45
+
46
+ Read [assets/SOURCE_MAP.json](assets/SOURCE_MAP.json) for source code references.
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": "0.0.0-everlasting-joggers-20260331153923",
3
+ "package": "@mastra/libsql",
4
+ "exports": {},
5
+ "modules": {}
6
+ }
@@ -0,0 +1,509 @@
1
+ # Agent approval
2
+
3
+ Agents sometimes require the same [human-in-the-loop](https://mastra.ai/docs/workflows/human-in-the-loop) oversight used in workflows when calling tools that handle sensitive operations, like deleting resources or running long processes. With agent approval you can suspend a tool call before it executes so a human can approve or decline it, or let tools suspend themselves to request additional context from the user.
4
+
5
+ ## When to use agent approval
6
+
7
+ - **Destructive or irreversible actions** such as deleting records, sending emails, or processing payments.
8
+ - **Cost-heavy operations** like calling expensive third-party APIs where you want to verify arguments first.
9
+ - **Conditional confirmation** where a tool starts executing and then discovers it needs the user to confirm or supply extra data before finishing.
10
+
11
+ ## Quickstart
12
+
13
+ Mark a tool with `requireApproval: true`, then check for the `tool-call-approval` chunk in the stream to approve or decline:
14
+
15
+ ```typescript
16
+ import { Agent } from '@mastra/core/agent'
17
+ import { createTool } from '@mastra/core/tools'
18
+ import { z } from 'zod'
19
+
20
+ const deleteTool = createTool({
21
+ id: 'delete-record',
22
+ description: 'Delete a record by ID',
23
+ inputSchema: z.object({ id: z.string() }),
24
+ outputSchema: z.object({ deleted: z.boolean() }),
25
+ requireApproval: true,
26
+ execute: async ({ id }) => {
27
+ await db.delete(id)
28
+ return { deleted: true }
29
+ },
30
+ })
31
+
32
+ const agent = new Agent({
33
+ id: 'my-agent',
34
+ name: 'My Agent',
35
+ model: 'openai/gpt-5-mini',
36
+ tools: { deleteTool },
37
+ })
38
+
39
+ const stream = await agent.stream('Delete record abc-123')
40
+
41
+ for await (const chunk of stream.fullStream) {
42
+ if (chunk.type === 'tool-call-approval') {
43
+ const approved = await agent.approveToolCall({ runId: stream.runId })
44
+ for await (const c of approved.textStream) process.stdout.write(c)
45
+ }
46
+ }
47
+ ```
48
+
49
+ > **Note:** Agent approval uses snapshots to capture request state. Configure a [storage provider](https://mastra.ai/docs/memory/storage) on your Mastra instance or you'll see a "snapshot not found" error.
50
+
51
+ ## How approval works
52
+
53
+ Mastra offers two distinct mechanisms for pausing tool calls: **pre-execution approval** and **runtime suspension**.
54
+
55
+ ### Pre-execution approval
56
+
57
+ 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.
58
+
59
+ Two flags control this, combined with OR logic. If _either_ is `true`, the call pauses:
60
+
61
+ | Flag | Where to set it | Scope |
62
+ | --------------------------- | --------------------------------- | ------------------------------------------- |
63
+ | `requireToolApproval: true` | `stream()` / `generate()` options | Pauses **every** tool call for that request |
64
+ | `requireApproval: true` | `createTool()` definition | Pauses calls to **that specific tool** |
65
+
66
+ The stream emits a `tool-call-approval` chunk containing the `toolCallId`, `toolName`, and `args`. Call `approveToolCall()` or `declineToolCall()` with the stream's `runId` to continue:
67
+
68
+ ```typescript
69
+ const stream = await agent.stream("What's the weather in London?", {
70
+ requireToolApproval: true,
71
+ })
72
+
73
+ for await (const chunk of stream.fullStream) {
74
+ if (chunk.type === 'tool-call-approval') {
75
+ console.log('Tool:', chunk.payload.toolName)
76
+ console.log('Args:', chunk.payload.args)
77
+
78
+ // Approve
79
+ const approved = await agent.approveToolCall({ runId: stream.runId })
80
+ for await (const c of approved.textStream) process.stdout.write(c)
81
+
82
+ // Or decline
83
+ const declined = await agent.declineToolCall({ runId: stream.runId })
84
+ for await (const c of declined.textStream) process.stdout.write(c)
85
+ }
86
+ }
87
+ ```
88
+
89
+ ### Runtime suspension with `suspend()`
90
+
91
+ 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.
92
+
93
+ The stream emits a `tool-call-suspended` chunk with a custom payload defined by the tool's `suspendSchema`. You resume by calling `resumeStream()` with data matching the tool's `resumeSchema`.
94
+
95
+ ## Tool approval with `generate()`
96
+
97
+ Tool approval also works with `generate()` for non-streaming use cases. When a tool requires approval, `generate()` returns immediately with `finishReason: 'suspended'`, a `suspendPayload` containing the tool call details (`toolCallId`, `toolName`, `args`), and a `runId`:
98
+
99
+ ```typescript
100
+ const output = await agent.generate('Find user John', {
101
+ requireToolApproval: true,
102
+ })
103
+
104
+ if (output.finishReason === 'suspended') {
105
+ console.log('Tool requires approval:', output.suspendPayload.toolName)
106
+
107
+ // Approve
108
+ const result = await agent.approveToolCallGenerate({
109
+ runId: output.runId,
110
+ toolCallId: output.suspendPayload.toolCallId,
111
+ })
112
+ console.log('Final result:', result.text)
113
+
114
+ // Or decline
115
+ const result = await agent.declineToolCallGenerate({
116
+ runId: output.runId,
117
+ toolCallId: output.suspendPayload.toolCallId,
118
+ })
119
+ }
120
+ ```
121
+
122
+ ### Stream vs generate comparison
123
+
124
+ | Aspect | `stream()` | `generate()` |
125
+ | ------------------ | ---------------------------- | ------------------------------------------------ |
126
+ | Response type | Streaming chunks | Complete response |
127
+ | Approval detection | `tool-call-approval` chunk | `finishReason: 'suspended'` |
128
+ | Approve method | `approveToolCall({ runId })` | `approveToolCallGenerate({ runId, toolCallId })` |
129
+ | Decline method | `declineToolCall({ runId })` | `declineToolCallGenerate({ runId, toolCallId })` |
130
+ | Result | Stream to iterate | Full output object |
131
+
132
+ > **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.
133
+
134
+ ## Tool-level approval
135
+
136
+ 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.
137
+
138
+ ### Approval using `requireApproval`
139
+
140
+ Set `requireApproval: true` on a tool definition. The tool pauses before execution regardless of whether `requireToolApproval` is set on the agent:
141
+
142
+ ```typescript
143
+ export const testTool = createTool({
144
+ id: 'test-tool',
145
+ description: 'Fetches weather for a location',
146
+ inputSchema: z.object({
147
+ location: z.string(),
148
+ }),
149
+ outputSchema: z.object({
150
+ weather: z.string(),
151
+ }),
152
+ resumeSchema: z.object({
153
+ approved: z.boolean(),
154
+ }),
155
+ execute: async inputData => {
156
+ const response = await fetch(`https://wttr.in/${inputData.location}?format=3`)
157
+ const weather = await response.text()
158
+
159
+ return { weather }
160
+ },
161
+ requireApproval: true,
162
+ })
163
+ ```
164
+
165
+ When `requireApproval` is `true`, the stream emits `tool-call-approval` chunks the same way agent-level approval does. Use `approveToolCall()` or `declineToolCall()` to continue:
166
+
167
+ ```typescript
168
+ const stream = await agent.stream("What's the weather in London?")
169
+
170
+ for await (const chunk of stream.fullStream) {
171
+ if (chunk.type === 'tool-call-approval') {
172
+ console.log('Approval required for:', chunk.payload.toolName)
173
+ }
174
+ }
175
+
176
+ const handleApproval = async () => {
177
+ const approvedStream = await agent.approveToolCall({ runId: stream.runId })
178
+
179
+ for await (const chunk of approvedStream.textStream) {
180
+ process.stdout.write(chunk)
181
+ }
182
+ process.stdout.write('\n')
183
+ }
184
+ ```
185
+
186
+ ### Approval using `suspend()`
187
+
188
+ With this approach, neither the agent nor the tool uses `requireApproval`. Instead, the tool's `execute` function calls `suspend()` to pause at a specific point and return context or confirmation prompts to the user. This is useful when approval depends on runtime conditions rather than being unconditional.
189
+
190
+ ```typescript
191
+ export const testToolB = createTool({
192
+ id: 'test-tool-b',
193
+ description: 'Fetches weather for a location',
194
+ inputSchema: z.object({
195
+ location: z.string(),
196
+ }),
197
+ outputSchema: z.object({
198
+ weather: z.string(),
199
+ }),
200
+ resumeSchema: z.object({
201
+ approved: z.boolean(),
202
+ }),
203
+ suspendSchema: z.object({
204
+ reason: z.string(),
205
+ }),
206
+ execute: async (inputData, context) => {
207
+ const { resumeData: { approved } = {}, suspend } = context?.agent ?? {}
208
+
209
+ if (!approved) {
210
+ return suspend?.({ reason: 'Approval required.' })
211
+ }
212
+
213
+ const response = await fetch(`https://wttr.in/${inputData.location}?format=3`)
214
+ const weather = await response.text()
215
+
216
+ return { weather }
217
+ },
218
+ })
219
+ ```
220
+
221
+ With this approach the stream includes a `tool-call-suspended` chunk, and the `suspendPayload` contains the `reason` defined by the tool's `suspendSchema`. Call `resumeStream` with the `resumeSchema` data and `runId` to continue:
222
+
223
+ ```typescript
224
+ const stream = await agent.stream("What's the weather in London?")
225
+
226
+ for await (const chunk of stream.fullStream) {
227
+ if (chunk.type === 'tool-call-suspended') {
228
+ console.log(chunk.payload.suspendPayload)
229
+ }
230
+ }
231
+
232
+ const handleResume = async () => {
233
+ const resumedStream = await agent.resumeStream({ approved: true }, { runId: stream.runId })
234
+
235
+ for await (const chunk of resumedStream.textStream) {
236
+ process.stdout.write(chunk)
237
+ }
238
+ process.stdout.write('\n')
239
+ }
240
+ ```
241
+
242
+ ## Automatic tool resumption
243
+
244
+ When using tools that call `suspend()`, you can enable automatic resumption so the agent resumes suspended tools based on the user's next message. Set `autoResumeSuspendedTools` to `true` in the agent's default options or per-request:
245
+
246
+ ```typescript
247
+ import { Agent } from '@mastra/core/agent'
248
+ import { Memory } from '@mastra/memory'
249
+
250
+ const agent = new Agent({
251
+ id: 'my-agent',
252
+ name: 'My Agent',
253
+ instructions: 'You are a helpful assistant',
254
+ model: 'openai/gpt-5-mini',
255
+ tools: { weatherTool },
256
+ memory: new Memory(),
257
+ defaultOptions: {
258
+ autoResumeSuspendedTools: true,
259
+ },
260
+ })
261
+ ```
262
+
263
+ 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:
264
+
265
+ ```typescript
266
+ import { createTool } from '@mastra/core/tools'
267
+ import { z } from 'zod'
268
+
269
+ const weatherTool = createTool({
270
+ id: 'weather-tool',
271
+ description: 'Fetches weather for a city',
272
+ inputSchema: z.object({
273
+ city: z.string(),
274
+ }),
275
+ outputSchema: z.object({
276
+ weather: z.string(),
277
+ }),
278
+ suspendSchema: z.object({
279
+ message: z.string(),
280
+ }),
281
+ resumeSchema: z.object({
282
+ city: z.string(),
283
+ }),
284
+ execute: async (inputData, context) => {
285
+ const { resumeData, suspend } = context?.agent ?? {}
286
+
287
+ // If no city provided, ask the user
288
+ if (!inputData.city && !resumeData?.city) {
289
+ return suspend?.({ message: 'What city do you want to know the weather for?' })
290
+ }
291
+
292
+ const city = resumeData?.city ?? inputData.city
293
+ const response = await fetch(`https://wttr.in/${city}?format=3`)
294
+ const weather = await response.text()
295
+
296
+ return { weather: `${city}: ${weather}` }
297
+ },
298
+ })
299
+ ```
300
+
301
+ ```typescript
302
+ const stream = await agent.stream("What's the weather like?")
303
+
304
+ for await (const chunk of stream.fullStream) {
305
+ if (chunk.type === 'tool-call-suspended') {
306
+ console.log(chunk.payload.suspendPayload)
307
+ }
308
+ }
309
+
310
+ // User sends follow-up on the same thread
311
+ const resumedStream = await agent.stream('San Francisco')
312
+ for await (const chunk of resumedStream.textStream) {
313
+ process.stdout.write(chunk)
314
+ }
315
+ ```
316
+
317
+ ```text
318
+ User: "What's the weather like?"
319
+ Agent: "What city do you want to know the weather for?"
320
+
321
+ User: "San Francisco"
322
+ Agent: "The weather in San Francisco is: San Francisco: ☀️ +72°F"
323
+ ```
324
+
325
+ The second message automatically resumes the suspended tool. The agent extracts `{ city: "San Francisco" }` from the user's message and passes it as `resumeData`.
326
+
327
+ ### Requirements
328
+
329
+ For automatic tool resumption to work:
330
+
331
+ - **Memory configured**: The agent needs memory to track suspended tools across messages
332
+ - **Same thread**: The follow-up message must use the same memory thread and resource identifiers
333
+ - **`resumeSchema` defined**: The tool must define a `resumeSchema` so the agent knows what data structure to extract from the user's message
334
+
335
+ ### Manual vs automatic resumption
336
+
337
+ | Approach | Use case |
338
+ | -------------------------------------- | ------------------------------------------------------------------------ |
339
+ | Manual (`resumeStream()`) | Programmatic control, webhooks, button clicks, external triggers |
340
+ | Automatic (`autoResumeSuspendedTools`) | Conversational flows where users provide resume data in natural language |
341
+
342
+ Both approaches work with the same tool definitions. Automatic resumption triggers only when suspended tools exist in the message history and the user sends a new message on the same thread.
343
+
344
+ ## Tool approval: Supervisor agents
345
+
346
+ A [supervisor agent](https://mastra.ai/docs/agents/supervisor-agents) coordinates multiple subagents using `.stream()` or `.generate()`. When a subagent calls a tool that requires approval, the request propagates up through the delegation chain and surfaces at the supervisor level:
347
+
348
+ 1. The supervisor delegates a task to a subagent.
349
+ 2. The subagent calls a tool that has `requireApproval: true` or uses `suspend()`.
350
+ 3. The approval request bubbles up to the supervisor.
351
+ 4. You approve or decline at the supervisor level.
352
+ 5. The decision propagates back down to the subagent.
353
+
354
+ Tool approvals also propagate through multiple levels of delegation. If a supervisor delegates to subagent A, which delegates to subagent B that has a tool with `requireApproval: true`, the approval request still surfaces at the top-level supervisor.
355
+
356
+ ### Approve and decline in supervisor agents
357
+
358
+ The example below creates a subagent with a tool requiring approval. When the tool triggers an approval request, it surfaces in the supervisor's stream as a `tool-call-approval` chunk:
359
+
360
+ ```typescript
361
+ import { Agent } from '@mastra/core/agent'
362
+ import { createTool } from '@mastra/core/tools'
363
+ import { Memory } from '@mastra/memory'
364
+ import { z } from 'zod'
365
+
366
+ const findUserTool = createTool({
367
+ id: 'find-user',
368
+ description: 'Finds user by ID in the database',
369
+ inputSchema: z.object({
370
+ userId: z.string(),
371
+ }),
372
+ outputSchema: z.object({
373
+ user: z.object({
374
+ id: z.string(),
375
+ name: z.string(),
376
+ email: z.string(),
377
+ }),
378
+ }),
379
+ requireApproval: true,
380
+ execute: async input => {
381
+ const user = await database.findUser(input.userId)
382
+ return { user }
383
+ },
384
+ })
385
+
386
+ const dataAgent = new Agent({
387
+ id: 'data-agent',
388
+ name: 'Data Agent',
389
+ description: 'Handles database queries and user data retrieval',
390
+ model: 'openai/gpt-5-mini',
391
+ tools: { findUserTool },
392
+ })
393
+
394
+ const supervisorAgent = new Agent({
395
+ id: 'supervisor',
396
+ name: 'Supervisor Agent',
397
+ instructions: `You coordinate data retrieval tasks.
398
+ Delegate to data-agent for user lookups.`,
399
+ model: 'openai/gpt-5.4',
400
+ agents: { dataAgent },
401
+ memory: new Memory(),
402
+ })
403
+
404
+ const stream = await supervisorAgent.stream('Find user with ID 12345')
405
+
406
+ for await (const chunk of stream.fullStream) {
407
+ if (chunk.type === 'tool-call-approval') {
408
+ console.log('Tool requires approval:', chunk.payload.toolName)
409
+ console.log('Arguments:', chunk.payload.args)
410
+
411
+ // Approve the tool call
412
+ const resumeStream = await supervisorAgent.approveToolCall({
413
+ runId: stream.runId,
414
+ toolCallId: chunk.payload.toolCallId,
415
+ })
416
+
417
+ for await (const resumeChunk of resumeStream.textStream) {
418
+ process.stdout.write(resumeChunk)
419
+ }
420
+
421
+ // To decline instead, use:
422
+ const declineStream = await supervisorAgent.declineToolCall({
423
+ runId: stream.runId,
424
+ toolCallId: chunk.payload.toolCallId,
425
+ })
426
+ }
427
+ }
428
+ ```
429
+
430
+ ### Use `suspend()` in supervisor agents
431
+
432
+ Tools can also use [`suspend()`](#approval-using-suspend) to pause execution and return context to the user. This approach works through the supervisor delegation chain the same way `requireApproval` does: the suspension surfaces at the supervisor level:
433
+
434
+ ```typescript
435
+ const conditionalTool = createTool({
436
+ id: 'conditional-operation',
437
+ description: 'Performs an operation that may require confirmation',
438
+ inputSchema: z.object({
439
+ operation: z.string(),
440
+ }),
441
+ suspendSchema: z.object({
442
+ message: z.string(),
443
+ }),
444
+ resumeSchema: z.object({
445
+ confirmed: z.boolean(),
446
+ }),
447
+ execute: async (input, context) => {
448
+ const { resumeData } = context?.agent ?? {}
449
+
450
+ if (!resumeData?.confirmed) {
451
+ return context?.agent?.suspend({
452
+ message: `Confirm: ${input.operation}?`,
453
+ })
454
+ }
455
+
456
+ // Proceed with operation
457
+ return await performOperation(input.operation)
458
+ },
459
+ })
460
+ ```
461
+
462
+ ```typescript
463
+ // When using this tool through a subagent in supervisor agents
464
+ for await (const chunk of stream.fullStream) {
465
+ if (chunk.type === 'tool-call-suspended') {
466
+ console.log('Tool suspended:', chunk.payload.suspendPayload.message)
467
+
468
+ // Resume with confirmation
469
+ const resumeStream = await supervisorAgent.resumeStream(
470
+ { confirmed: true },
471
+ { runId: stream.runId },
472
+ )
473
+
474
+ for await (const resumeChunk of resumeStream.textStream) {
475
+ process.stdout.write(resumeChunk)
476
+ }
477
+ }
478
+ }
479
+ ```
480
+
481
+ ### Supervisor approval with `generate()`
482
+
483
+ Tool approval propagation also works with `generate()` in supervisor agents:
484
+
485
+ ```typescript
486
+ const output = await supervisorAgent.generate('Find user with ID 12345', {
487
+ maxSteps: 10,
488
+ })
489
+
490
+ if (output.finishReason === 'suspended') {
491
+ console.log('Tool requires approval:', output.suspendPayload.toolName)
492
+
493
+ // Approve
494
+ const result = await supervisorAgent.approveToolCallGenerate({
495
+ runId: output.runId,
496
+ toolCallId: output.suspendPayload.toolCallId,
497
+ })
498
+
499
+ console.log('Final result:', result.text)
500
+ }
501
+ ```
502
+
503
+ ## Related
504
+
505
+ - [Tools](https://mastra.ai/docs/agents/using-tools)
506
+ - [Agent overview](https://mastra.ai/docs/agents/overview)
507
+ - [MCP overview](https://mastra.ai/docs/mcp/overview)
508
+ - [Memory](https://mastra.ai/docs/memory/overview)
509
+ - [Request context](https://mastra.ai/docs/server/request-context)