@mastra/mcp-docs-server 1.0.0-beta.5 → 1.0.0-beta.6

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 (132) hide show
  1. package/.docs/organized/changelogs/%40mastra%2Fagent-builder.md +9 -9
  2. package/.docs/organized/changelogs/%40mastra%2Fai-sdk.md +67 -67
  3. package/.docs/organized/changelogs/%40mastra%2Fclickhouse.md +26 -26
  4. package/.docs/organized/changelogs/%40mastra%2Fclient-js.md +53 -53
  5. package/.docs/organized/changelogs/%40mastra%2Fcloudflare-d1.md +26 -26
  6. package/.docs/organized/changelogs/%40mastra%2Fcloudflare.md +27 -27
  7. package/.docs/organized/changelogs/%40mastra%2Fconvex.md +29 -0
  8. package/.docs/organized/changelogs/%40mastra%2Fcore.md +274 -274
  9. package/.docs/organized/changelogs/%40mastra%2Fdeployer-cloud.md +15 -15
  10. package/.docs/organized/changelogs/%40mastra%2Fdeployer-netlify.md +12 -12
  11. package/.docs/organized/changelogs/%40mastra%2Fdeployer.md +65 -65
  12. package/.docs/organized/changelogs/%40mastra%2Fduckdb.md +42 -0
  13. package/.docs/organized/changelogs/%40mastra%2Fdynamodb.md +26 -26
  14. package/.docs/organized/changelogs/%40mastra%2Felasticsearch.md +52 -0
  15. package/.docs/organized/changelogs/%40mastra%2Fevals.md +12 -12
  16. package/.docs/organized/changelogs/%40mastra%2Flance.md +26 -26
  17. package/.docs/organized/changelogs/%40mastra%2Flibsql.md +24 -24
  18. package/.docs/organized/changelogs/%40mastra%2Fmcp-docs-server.md +9 -9
  19. package/.docs/organized/changelogs/%40mastra%2Fmcp.md +84 -84
  20. package/.docs/organized/changelogs/%40mastra%2Fmemory.md +36 -36
  21. package/.docs/organized/changelogs/%40mastra%2Fmongodb.md +26 -26
  22. package/.docs/organized/changelogs/%40mastra%2Fmssql.md +27 -27
  23. package/.docs/organized/changelogs/%40mastra%2Fpg.md +28 -28
  24. package/.docs/organized/changelogs/%40mastra%2Fplayground-ui.md +47 -47
  25. package/.docs/organized/changelogs/%40mastra%2Frag.md +43 -43
  26. package/.docs/organized/changelogs/%40mastra%2Freact.md +9 -0
  27. package/.docs/organized/changelogs/%40mastra%2Fschema-compat.md +6 -0
  28. package/.docs/organized/changelogs/%40mastra%2Fserver.md +56 -56
  29. package/.docs/organized/changelogs/%40mastra%2Fupstash.md +26 -26
  30. package/.docs/organized/changelogs/%40mastra%2Fvoice-google.md +19 -19
  31. package/.docs/organized/changelogs/create-mastra.md +9 -9
  32. package/.docs/organized/changelogs/mastra.md +17 -17
  33. package/.docs/organized/code-examples/agui.md +1 -0
  34. package/.docs/organized/code-examples/ai-sdk-v5.md +1 -0
  35. package/.docs/organized/code-examples/mcp-server-adapters.md +721 -0
  36. package/.docs/organized/code-examples/server-app-access.md +342 -0
  37. package/.docs/raw/agents/agent-approval.mdx +189 -0
  38. package/.docs/raw/agents/guardrails.mdx +13 -9
  39. package/.docs/raw/agents/networks.mdx +1 -0
  40. package/.docs/raw/agents/overview.mdx +23 -58
  41. package/.docs/raw/agents/processors.mdx +279 -0
  42. package/.docs/raw/deployment/cloud-providers/index.mdx +19 -26
  43. package/.docs/raw/deployment/cloud-providers/netlify-deployer.mdx +44 -13
  44. package/.docs/raw/evals/running-in-ci.mdx +0 -2
  45. package/.docs/raw/{guides/getting-started → getting-started}/manual-install.mdx +2 -2
  46. package/.docs/raw/getting-started/start.mdx +1 -1
  47. package/.docs/raw/guides/build-your-ui/ai-sdk-ui.mdx +8 -0
  48. package/.docs/raw/guides/getting-started/quickstart.mdx +1 -1
  49. package/.docs/raw/guides/guide/whatsapp-chat-bot.mdx +421 -0
  50. package/.docs/raw/guides/index.mdx +3 -35
  51. package/.docs/raw/guides/migrations/upgrade-to-v1/agent.mdx +11 -0
  52. package/.docs/raw/guides/migrations/upgrade-to-v1/workflows.mdx +29 -0
  53. package/.docs/raw/index.mdx +1 -1
  54. package/.docs/raw/memory/memory-processors.mdx +265 -79
  55. package/.docs/raw/memory/working-memory.mdx +10 -2
  56. package/.docs/raw/observability/overview.mdx +0 -1
  57. package/.docs/raw/observability/tracing/bridges/otel.mdx +176 -0
  58. package/.docs/raw/observability/tracing/exporters/arize.mdx +17 -0
  59. package/.docs/raw/observability/tracing/exporters/braintrust.mdx +19 -0
  60. package/.docs/raw/observability/tracing/exporters/langfuse.mdx +20 -0
  61. package/.docs/raw/observability/tracing/exporters/langsmith.mdx +12 -0
  62. package/.docs/raw/observability/tracing/exporters/otel.mdx +5 -4
  63. package/.docs/raw/observability/tracing/overview.mdx +71 -6
  64. package/.docs/raw/observability/tracing/processors/sensitive-data-filter.mdx +0 -1
  65. package/.docs/raw/rag/retrieval.mdx +23 -6
  66. package/.docs/raw/rag/vector-databases.mdx +93 -2
  67. package/.docs/raw/reference/agents/generate.mdx +55 -6
  68. package/.docs/raw/reference/agents/network.mdx +44 -0
  69. package/.docs/raw/reference/client-js/memory.mdx +43 -0
  70. package/.docs/raw/reference/client-js/workflows.mdx +92 -63
  71. package/.docs/raw/reference/deployer/netlify.mdx +1 -2
  72. package/.docs/raw/reference/evals/scorer-utils.mdx +362 -0
  73. package/.docs/raw/reference/index.mdx +1 -0
  74. package/.docs/raw/reference/observability/tracing/bridges/otel.mdx +150 -0
  75. package/.docs/raw/reference/observability/tracing/configuration.mdx +0 -4
  76. package/.docs/raw/reference/observability/tracing/exporters/arize.mdx +4 -0
  77. package/.docs/raw/reference/observability/tracing/exporters/langsmith.mdx +17 -1
  78. package/.docs/raw/reference/observability/tracing/exporters/otel.mdx +6 -0
  79. package/.docs/raw/reference/observability/tracing/instances.mdx +0 -4
  80. package/.docs/raw/reference/observability/tracing/interfaces.mdx +29 -4
  81. package/.docs/raw/reference/observability/tracing/spans.mdx +0 -4
  82. package/.docs/raw/reference/processors/language-detector.mdx +9 -2
  83. package/.docs/raw/reference/processors/message-history-processor.mdx +131 -0
  84. package/.docs/raw/reference/processors/moderation-processor.mdx +10 -3
  85. package/.docs/raw/reference/processors/pii-detector.mdx +10 -3
  86. package/.docs/raw/reference/processors/processor-interface.mdx +502 -0
  87. package/.docs/raw/reference/processors/prompt-injection-detector.mdx +9 -2
  88. package/.docs/raw/reference/processors/semantic-recall-processor.mdx +197 -0
  89. package/.docs/raw/reference/processors/system-prompt-scrubber.mdx +2 -2
  90. package/.docs/raw/reference/processors/tool-call-filter.mdx +125 -0
  91. package/.docs/raw/reference/processors/working-memory-processor.mdx +221 -0
  92. package/.docs/raw/reference/storage/cloudflare-d1.mdx +37 -0
  93. package/.docs/raw/reference/storage/convex.mdx +164 -0
  94. package/.docs/raw/reference/storage/lance.mdx +33 -0
  95. package/.docs/raw/reference/storage/libsql.mdx +37 -0
  96. package/.docs/raw/reference/storage/mongodb.mdx +39 -0
  97. package/.docs/raw/reference/storage/mssql.mdx +37 -0
  98. package/.docs/raw/reference/storage/postgresql.mdx +37 -0
  99. package/.docs/raw/reference/streaming/ChunkType.mdx +1 -1
  100. package/.docs/raw/reference/streaming/agents/stream.mdx +56 -1
  101. package/.docs/raw/reference/streaming/workflows/observeStream.mdx +7 -9
  102. package/.docs/raw/reference/streaming/workflows/{resumeStreamVNext.mdx → resumeStream.mdx} +51 -11
  103. package/.docs/raw/reference/streaming/workflows/stream.mdx +83 -24
  104. package/.docs/raw/reference/tools/mcp-client.mdx +74 -17
  105. package/.docs/raw/reference/vectors/convex.mdx +429 -0
  106. package/.docs/raw/reference/vectors/duckdb.mdx +462 -0
  107. package/.docs/raw/reference/vectors/elasticsearch.mdx +310 -0
  108. package/.docs/raw/reference/voice/google.mdx +159 -20
  109. package/.docs/raw/reference/workflows/run-methods/restart.mdx +142 -0
  110. package/.docs/raw/reference/workflows/run-methods/resume.mdx +44 -0
  111. package/.docs/raw/reference/workflows/run-methods/start.mdx +44 -0
  112. package/.docs/raw/reference/workflows/run.mdx +13 -5
  113. package/.docs/raw/reference/workflows/step.mdx +13 -0
  114. package/.docs/raw/reference/workflows/workflow.mdx +19 -0
  115. package/.docs/raw/server-db/mastra-server.mdx +30 -1
  116. package/.docs/raw/server-db/request-context.mdx +0 -1
  117. package/.docs/raw/server-db/storage.mdx +11 -0
  118. package/.docs/raw/streaming/overview.mdx +6 -6
  119. package/.docs/raw/streaming/tool-streaming.mdx +2 -2
  120. package/.docs/raw/streaming/workflow-streaming.mdx +5 -11
  121. package/.docs/raw/workflows/error-handling.mdx +1 -0
  122. package/.docs/raw/workflows/human-in-the-loop.mdx +4 -4
  123. package/.docs/raw/workflows/overview.mdx +56 -44
  124. package/.docs/raw/workflows/snapshots.mdx +1 -0
  125. package/.docs/raw/workflows/suspend-and-resume.mdx +85 -16
  126. package/.docs/raw/workflows/time-travel.mdx +313 -0
  127. package/.docs/raw/workflows/workflow-state.mdx +191 -0
  128. package/CHANGELOG.md +8 -0
  129. package/package.json +4 -4
  130. package/.docs/raw/agents/human-in-the-loop-with-tools.mdx +0 -91
  131. package/.docs/raw/reference/streaming/workflows/observeStreamVNext.mdx +0 -47
  132. package/.docs/raw/reference/streaming/workflows/streamVNext.mdx +0 -153
@@ -0,0 +1,342 @@
1
+ ### package.json
2
+ ```json
3
+ {
4
+ "name": "examples-server-app-access",
5
+ "dependencies": {
6
+ "@mastra/core": "latest",
7
+ "@mastra/hono": "latest",
8
+ "hono": "^4.10.4",
9
+ "zod": "^3.25.76"
10
+ },
11
+ "devDependencies": {
12
+ "@types/node": "22.13.17",
13
+ "tsx": "^4.19.3",
14
+ "typescript": "^5.8.3"
15
+ }
16
+ }
17
+ ```
18
+
19
+ ### demo-cli-batch.ts
20
+ ```typescript
21
+ /**
22
+ * Demo: Direct Server App Access
23
+ *
24
+ * This demonstrates how to use mastra.getServerApp() to call routes
25
+ * directly without running an HTTP server.
26
+ *
27
+ * Use case: CLI scripts, batch processing, testing, background jobs
28
+ *
29
+ * NOTE: The base URL (http://internal) is just a placeholder - Hono's app.fetch()
30
+ * processes requests in-memory and only uses the path. The hostname is ignored.
31
+ */
32
+
33
+ import { MastraServer } from '@mastra/hono';
34
+ import { Hono } from 'hono';
35
+ import type { Hono as HonoType } from 'hono';
36
+
37
+ import { mastra } from './mastra';
38
+
39
+ // Base URL is a placeholder - only the path matters for in-memory routing
40
+ const BASE_URL = 'http://internal';
41
+
42
+ async function main() {
43
+ // Create and initialize server (no port binding)
44
+ const app = new Hono();
45
+ const adapter = new MastraServer({ app: app as any, mastra });
46
+ await adapter.init();
47
+
48
+ // Get the server app - works because MastraServer auto-registers with mastra
49
+ const serverApp = mastra.getServerApp<HonoType>();
50
+ if (!serverApp) throw new Error('Server app not initialized');
51
+
52
+ // List tools
53
+ console.log('--- List Tools ---');
54
+ const toolsResponse = await serverApp.fetch(new Request(`${BASE_URL}/api/tools`));
55
+ const tools = (await toolsResponse.json()) as Record<string, unknown>;
56
+ console.log(`Tools: ${Object.keys(tools).join(', ') || '(none registered by key)'}`);
57
+
58
+ // Execute a tool
59
+ console.log('\n--- Execute Tool ---');
60
+ const calcResponse = await serverApp.fetch(
61
+ new Request(`${BASE_URL}/api/tools/calculator/execute`, {
62
+ method: 'POST',
63
+ headers: { 'Content-Type': 'application/json' },
64
+ body: JSON.stringify({ data: { operation: 'multiply', a: 7, b: 6 } }),
65
+ }),
66
+ );
67
+ console.log(`Result: ${JSON.stringify(await calcResponse.json())}`);
68
+
69
+ // List workflows
70
+ console.log('\n--- List Workflows ---');
71
+ const workflowsResponse = await serverApp.fetch(new Request(`${BASE_URL}/api/workflows`));
72
+ const workflows = (await workflowsResponse.json()) as Record<string, unknown>;
73
+ console.log(`Workflows: ${Object.keys(workflows).join(', ')}`);
74
+ }
75
+
76
+ main().catch(console.error);
77
+
78
+ ```
79
+
80
+ ### mastra/index.ts
81
+ ```typescript
82
+ import { Mastra } from '@mastra/core/mastra';
83
+
84
+ import { calculatorTool, timestampTool } from './tools';
85
+ import { dailyReportWorkflow, paymentProcessorWorkflow, processMessageWorkflow } from './workflows';
86
+
87
+ /**
88
+ * Main Mastra instance configured with tools and workflows
89
+ * for demonstrating server app access patterns.
90
+ */
91
+ export const mastra = new Mastra({
92
+ tools: {
93
+ calculatorTool,
94
+ timestampTool,
95
+ },
96
+ workflows: {
97
+ processMessageWorkflow,
98
+ dailyReportWorkflow,
99
+ paymentProcessorWorkflow,
100
+ },
101
+ });
102
+
103
+ ```
104
+
105
+ ### mastra/tools/index.ts
106
+ ```typescript
107
+ import { createTool } from '@mastra/core/tools';
108
+ import { z } from 'zod';
109
+
110
+ /**
111
+ * Calculator tool - performs basic arithmetic operations
112
+ */
113
+ export const calculatorTool = createTool({
114
+ id: 'calculator',
115
+ description: 'Performs basic arithmetic operations',
116
+ inputSchema: z.object({
117
+ operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
118
+ a: z.number(),
119
+ b: z.number(),
120
+ }),
121
+ execute: async ({ operation, a, b }) => {
122
+ if (operation === 'divide' && b === 0) {
123
+ throw new Error('Cannot divide by zero');
124
+ }
125
+
126
+ let result: number;
127
+ switch (operation) {
128
+ case 'add':
129
+ result = a + b;
130
+ break;
131
+ case 'subtract':
132
+ result = a - b;
133
+ break;
134
+ case 'multiply':
135
+ result = a * b;
136
+ break;
137
+ case 'divide':
138
+ result = a / b;
139
+ break;
140
+ default:
141
+ throw new Error(`Unsupported operation: ${operation}`);
142
+ }
143
+
144
+ return { result, operation, operands: { a, b } };
145
+ },
146
+ });
147
+
148
+ /**
149
+ * Timestamp tool - returns current timestamp in various formats
150
+ */
151
+ export const timestampTool = createTool({
152
+ id: 'timestamp',
153
+ description: 'Returns the current timestamp in various formats',
154
+ inputSchema: z.object({
155
+ format: z.enum(['iso', 'unix', 'readable']).default('iso'),
156
+ }),
157
+ execute: async ({ format }) => {
158
+ const now = new Date();
159
+
160
+ let timestamp: string;
161
+ switch (format) {
162
+ case 'unix':
163
+ timestamp = Math.floor(now.getTime() / 1000).toString();
164
+ break;
165
+ case 'readable':
166
+ timestamp = now.toLocaleString();
167
+ break;
168
+ case 'iso':
169
+ default:
170
+ timestamp = now.toISOString();
171
+ break;
172
+ }
173
+
174
+ return { timestamp, format };
175
+ },
176
+ });
177
+
178
+ ```
179
+
180
+ ### mastra/workflows/index.ts
181
+ ```typescript
182
+ import { createStep, createWorkflow } from '@mastra/core/workflows';
183
+ import { z } from 'zod';
184
+
185
+ // --- Process Message Workflow ---
186
+
187
+ const validateStep = createStep({
188
+ id: 'validate',
189
+ description: 'Validates the incoming message',
190
+ inputSchema: z.object({
191
+ message: z.string(),
192
+ priority: z.enum(['low', 'medium', 'high']).default('medium'),
193
+ }),
194
+ outputSchema: z.object({
195
+ valid: z.boolean(),
196
+ message: z.string(),
197
+ priority: z.enum(['low', 'medium', 'high']),
198
+ }),
199
+ execute: async ({ inputData }) => {
200
+ const valid = inputData.message.length > 0 && inputData.message.length < 1000;
201
+ return {
202
+ valid,
203
+ message: inputData.message,
204
+ priority: inputData.priority,
205
+ };
206
+ },
207
+ });
208
+
209
+ const processStep = createStep({
210
+ id: 'process',
211
+ description: 'Processes the validated message',
212
+ inputSchema: z.object({
213
+ valid: z.boolean(),
214
+ message: z.string(),
215
+ priority: z.enum(['low', 'medium', 'high']),
216
+ }),
217
+ outputSchema: z.object({
218
+ processed: z.boolean(),
219
+ result: z.string(),
220
+ timestamp: z.string(),
221
+ }),
222
+ execute: async ({ inputData }) => {
223
+ if (!inputData.valid) {
224
+ return {
225
+ processed: false,
226
+ result: 'Invalid message',
227
+ timestamp: new Date().toISOString(),
228
+ };
229
+ }
230
+
231
+ const result = `Processed [${inputData.priority}]: ${inputData.message.substring(0, 50)}...`;
232
+
233
+ return {
234
+ processed: true,
235
+ result,
236
+ timestamp: new Date().toISOString(),
237
+ };
238
+ },
239
+ });
240
+
241
+ export const processMessageWorkflow = createWorkflow({
242
+ id: 'process-message',
243
+ description: 'Validates and processes a message',
244
+ inputSchema: z.object({
245
+ message: z.string(),
246
+ priority: z.enum(['low', 'medium', 'high']).default('medium'),
247
+ }),
248
+ outputSchema: z.object({
249
+ processed: z.boolean(),
250
+ result: z.string(),
251
+ timestamp: z.string(),
252
+ }),
253
+ })
254
+ .then(validateStep)
255
+ .then(processStep)
256
+ .commit();
257
+
258
+ // --- Daily Report Workflow ---
259
+
260
+ const generateReportStep = createStep({
261
+ id: 'generate-report',
262
+ description: 'Generates a daily report',
263
+ inputSchema: z.object({
264
+ date: z.string(),
265
+ reportType: z.enum(['summary', 'detailed']).default('summary'),
266
+ }),
267
+ outputSchema: z.object({
268
+ reportId: z.string(),
269
+ status: z.string(),
270
+ generatedAt: z.string(),
271
+ }),
272
+ execute: async ({ inputData }) => {
273
+ const reportId = `RPT-${Date.now()}`;
274
+
275
+ return {
276
+ reportId,
277
+ status: `Generated ${inputData.reportType} report for ${inputData.date}`,
278
+ generatedAt: new Date().toISOString(),
279
+ };
280
+ },
281
+ });
282
+
283
+ export const dailyReportWorkflow = createWorkflow({
284
+ id: 'daily-report',
285
+ description: 'Generates daily reports',
286
+ inputSchema: z.object({
287
+ date: z.string(),
288
+ reportType: z.enum(['summary', 'detailed']).default('summary'),
289
+ }),
290
+ outputSchema: z.object({
291
+ reportId: z.string(),
292
+ status: z.string(),
293
+ generatedAt: z.string(),
294
+ }),
295
+ })
296
+ .then(generateReportStep)
297
+ .commit();
298
+
299
+ // --- Payment Processor Workflow ---
300
+
301
+ const processPaymentStep = createStep({
302
+ id: 'process-payment',
303
+ description: 'Processes a payment transaction',
304
+ inputSchema: z.object({
305
+ amount: z.number(),
306
+ currency: z.string(),
307
+ customerId: z.string(),
308
+ }),
309
+ outputSchema: z.object({
310
+ transactionId: z.string(),
311
+ status: z.string(),
312
+ processedAt: z.string(),
313
+ }),
314
+ execute: async ({ inputData }) => {
315
+ const transactionId = `TXN-${Date.now()}`;
316
+
317
+ return {
318
+ transactionId,
319
+ status: `Processed ${inputData.currency} ${inputData.amount} for customer ${inputData.customerId}`,
320
+ processedAt: new Date().toISOString(),
321
+ };
322
+ },
323
+ });
324
+
325
+ export const paymentProcessorWorkflow = createWorkflow({
326
+ id: 'payment-processor',
327
+ description: 'Processes payment transactions',
328
+ inputSchema: z.object({
329
+ amount: z.number(),
330
+ currency: z.string(),
331
+ customerId: z.string(),
332
+ }),
333
+ outputSchema: z.object({
334
+ transactionId: z.string(),
335
+ status: z.string(),
336
+ processedAt: z.string(),
337
+ }),
338
+ })
339
+ .then(processPaymentStep)
340
+ .commit();
341
+
342
+ ```
@@ -0,0 +1,189 @@
1
+ ---
2
+ title: "Agent Approval | Agents"
3
+ description: Learn how to require approvals and suspend tool execution while keeping humans in control of agent workflows.
4
+ ---
5
+
6
+ # Agent Approval
7
+
8
+ Agents sometimes require the same [human-in-the-loop](/docs/v1/workflows/human-in-the-loop) oversight used in workflows when calling tools that handle sensitive operations, like deleting resources or performing running long processes. With agent approval you can suspend a tool call and provide feedback to the user, or approve or decline a tool call based on targeted application conditions.
9
+
10
+ ## Tool call approval
11
+
12
+ Tool call approval can be enabled at the agent level and apply to every tool the agent uses, or at the tool level providing more granular control over individual tool calls.
13
+
14
+ ### Storage
15
+
16
+ Agent approval uses a snapshot to capture the state of the request. Ensure you've enabled a storage provider in your main Mastra instance. If storage isn't enabled you'll see an error relating to snapshot not found.
17
+
18
+ ```typescript title="src/mastra/index.ts"
19
+ import { Mastra } from "@mastra/core/mastra";
20
+ import { LibSQLStore } from "@mastra/libsql";
21
+
22
+ export const mastra = new Mastra({
23
+ // ...
24
+ storage: new LibSQLStore({
25
+ id: "mastra-storage",
26
+ url: ":memory:"
27
+ })
28
+ });
29
+ ```
30
+
31
+
32
+ ## Agent-level approval
33
+
34
+ When calling an agent using `.stream()` set `requireToolApproval` to `true` which will prevent the agent from calling any of the tools defined in its configuration.
35
+
36
+ ```typescript showLineNumbers
37
+ const stream = await agent.stream("What's the weather in London?", {
38
+ requireToolApproval: true
39
+ });
40
+ ```
41
+
42
+ ### Approving tool calls
43
+
44
+ To approve a tool call, access `approveToolCall` from the `agent`, passing in the `runId` of the stream. This will let the agent know its now OK to call its tools.
45
+
46
+ ```typescript showLineNumbers
47
+ const handleApproval = async () => {
48
+ const approvedStream = await agent.approveToolCall({ runId: stream.runId });
49
+
50
+ for await (const chunk of approvedStream.textStream) {
51
+ process.stdout.write(chunk);
52
+ }
53
+ process.stdout.write("\n");
54
+ };
55
+ ```
56
+
57
+ ### Declining tool calls
58
+
59
+ To decline a tool call, access the `declineToolCall` from the `agent`. You will see the streamed response from the agent, but it won't call its tools.
60
+
61
+ ```typescript showLineNumbers
62
+ const handleDecline = async () => {
63
+ const declinedStream = await agent.declineToolCall({ runId: stream.runId });
64
+
65
+ for await (const chunk of declinedStream.textStream) {
66
+ process.stdout.write(chunk);
67
+ }
68
+ process.stdout.write("\n");
69
+ };
70
+ ```
71
+
72
+ ## Tool-level approval
73
+
74
+ There are two types of tool call approval. The first uses `requireApproval`, which is a property on the tool definition, while `requireToolApproval` is a parameter passed to `agent.stream()`. The second uses `suspend` and lets the agent provide context or confirmation prompts so the user can decide whether the tool call should continue.
75
+
76
+ ### Tool approval using `requireToolApproval`
77
+
78
+ In this approach, `requireApproval` is configured on the tool definition (shown below) rather than on the agent.
79
+
80
+ ```typescript
81
+ export const testTool = createTool({
82
+ id: "test-tool",
83
+ description: "Fetches weather for a location",
84
+ inputSchema: z.object({
85
+ location: z.string()
86
+ }),
87
+ outputSchema: z.object({
88
+ weather: z.string()
89
+ }),
90
+ resumeSchema: z.object({
91
+ approved: z.boolean()
92
+ }),
93
+ execute: async ({ location }) => {
94
+ const response = await fetch(`https://wttr.in/${location}?format=3`);
95
+ const weather = await response.text();
96
+
97
+ return { weather };
98
+ },
99
+ requireApproval: true
100
+ });
101
+ ```
102
+
103
+ When `requireApproval` is true for a tool, the stream will include chunks of type `tool-call-approval` to indicate that the call is paused. To continue the call, invoke `resumeStream` with the required `resumeSchema` and the `runId`.
104
+
105
+ ```typescript
106
+ const stream = await agent.stream("What's the weather in London?");
107
+
108
+ for await (const chunk of stream.fullStream) {
109
+ if (chunk.type === "tool-call-approval") {
110
+ console.log("Approval required.");
111
+ }
112
+ }
113
+
114
+ const handleResume = async () => {
115
+ const resumedStream = await agent.resumeStream({ approved: true }, { runId: stream.runId });
116
+
117
+ for await (const chunk of resumedStream.textStream) {
118
+ process.stdout.write(chunk);
119
+ }
120
+ process.stdout.write("\n");
121
+ };
122
+ ```
123
+
124
+
125
+ ### Tool approval using `suspend`
126
+
127
+ With this approach, neither the agent nor the tool uses `requireApproval`. Instead, the tool implementation calls `suspend` to pause execution and return context or confirmation prompts to the user.
128
+
129
+ ```typescript
130
+
131
+ export const testToolB = createTool({
132
+ id: "test-tool-b",
133
+ description: "Fetches weather for a location",
134
+ inputSchema: z.object({
135
+ location: z.string()
136
+ }),
137
+ outputSchema: z.object({
138
+ weather: z.string()
139
+ }),
140
+ resumeSchema: z.object({
141
+ approved: z.boolean()
142
+ }),
143
+ suspendSchema: z.object({
144
+ reason: z.string()
145
+ }),
146
+ execute: async ({ location }, { agent } = {}) => {
147
+ const { resumeData: { approved } = {}, suspend } = agent ?? {};
148
+
149
+ if (!approved) {
150
+ return suspend?.({ reason: "Approval required." });
151
+ }
152
+
153
+ const response = await fetch(`https://wttr.in/${location}?format=3`);
154
+ const weather = await response.text();
155
+
156
+ return { weather };
157
+ }
158
+ });
159
+ ```
160
+
161
+ With this approach the stream will include a `tool-call-suspended` chunk, and the `suspendPayload` will contain the `reason` defined by the tool's `suspendSchema`. To continue the call, invoke `resumeStream` with the required `resumeSchema` and the `runId`.
162
+
163
+ ```typescript
164
+ const stream = await agent.stream("What's the weather in London?");
165
+
166
+ for await (const chunk of stream.fullStream) {
167
+ if (chunk.type === "tool-call-suspended") {
168
+ console.log(chunk.payload.suspendPayload);
169
+ }
170
+ }
171
+
172
+ const handleResume = async () => {
173
+ const resumedStream = await agent.resumeStream({ approved: true }, { runId: stream.runId });
174
+
175
+ for await (const chunk of resumedStream.textStream) {
176
+ process.stdout.write(chunk);
177
+ }
178
+ process.stdout.write("\n");
179
+ };
180
+
181
+ ```
182
+
183
+ ## Related
184
+
185
+ - [Using Tools](./using-tools)
186
+ - [Agent Overview](./overview)
187
+ - [Tools Overview](../mcp/overview)
188
+ - [Agent Memory](./agent-memory)
189
+ - [Request Context](/docs/v1/server-db/request-context)
@@ -33,7 +33,7 @@ export const moderatedAgent = new Agent({
33
33
  model: "openai/gpt-5.1",
34
34
  inputProcessors: [
35
35
  new ModerationProcessor({
36
- model: "openai/gpt-4.1-nano",
36
+ model: "openrouter/openai/gpt-oss-safeguard-20b",
37
37
  categories: ["hate", "harassment", "violence"],
38
38
  threshold: 0.7,
39
39
  strategy: "block",
@@ -82,7 +82,7 @@ export const secureAgent = new Agent({
82
82
  // ...
83
83
  inputProcessors: [
84
84
  new PromptInjectionDetector({
85
- model: "openai/gpt-4.1-nano",
85
+ model: "openrouter/openai/gpt-oss-safeguard-20b",
86
86
  threshold: 0.8,
87
87
  strategy: "rewrite",
88
88
  detectionTypes: ["injection", "jailbreak", "system-override"],
@@ -106,7 +106,7 @@ export const multilingualAgent = new Agent({
106
106
  // ...
107
107
  inputProcessors: [
108
108
  new LanguageDetector({
109
- model: "openai/gpt-4.1-nano",
109
+ model: "openrouter/openai/gpt-oss-safeguard-20b",
110
110
  targetLanguages: ["English", "en"],
111
111
  strategy: "translate",
112
112
  threshold: 0.8,
@@ -179,7 +179,7 @@ const scrubbedAgent = new Agent({
179
179
  name: "Scrubbed Agent",
180
180
  outputProcessors: [
181
181
  new SystemPromptScrubber({
182
- model: "openai/gpt-4.1-nano",
182
+ model: "openrouter/openai/gpt-oss-safeguard-20b",
183
183
  strategy: "redact",
184
184
  customPatterns: ["system prompt", "internal instructions"],
185
185
  includeDetections: true,
@@ -194,6 +194,10 @@ const scrubbedAgent = new Agent({
194
194
 
195
195
  > See [SystemPromptScrubber](/reference/v1/processors/system-prompt-scrubber) for a full list of configuration options.
196
196
 
197
+ :::note
198
+ When streaming responses over HTTP, Mastra redacts sensitive request data (system prompts, tool definitions, API keys) from stream chunks at the server level by default. See [Stream data redaction](/docs/v1/server-db/mastra-server#stream-data-redaction) for details.
199
+ :::
200
+
197
201
  ## Hybrid processors
198
202
 
199
203
  Hybrid processors can be applied either before messages are sent to the language model or before responses are returned to the user. They are useful for tasks like content moderation and PII redaction.
@@ -211,7 +215,7 @@ export const moderatedAgent = new Agent({
211
215
  // ...
212
216
  inputProcessors: [
213
217
  new ModerationProcessor({
214
- model: "openai/gpt-4.1-nano",
218
+ model: "openrouter/openai/gpt-oss-safeguard-20b",
215
219
  threshold: 0.7,
216
220
  strategy: "block",
217
221
  categories: ["hate", "harassment", "violence"],
@@ -240,7 +244,7 @@ export const privateAgent = new Agent({
240
244
  // ...
241
245
  inputProcessors: [
242
246
  new PIIDetector({
243
- model: "openai/gpt-4.1-nano",
247
+ model: "openrouter/openai/gpt-oss-safeguard-20b",
244
248
  threshold: 0.6,
245
249
  strategy: "redact",
246
250
  redactionMethod: "mask",
@@ -364,6 +368,6 @@ If the built-in processors don’t cover your needs, you can create your own by
364
368
 
365
369
  Available examples:
366
370
 
367
- - [Message Length Limiter](/examples/v1/processors/message-length-limiter)
368
- - [Response Length Limiter](/examples/v1/processors/response-length-limiter)
369
- - [Response Validator](/examples/v1/processors/response-validator)
371
+ - [Message Length Limiter](https://github.com/mastra-ai/mastra/tree/main/examples/processors-message-length-limiter)
372
+ - [Response Length Limiter](https://github.com/mastra-ai/mastra/tree/main/examples/processors-response-length-limiter)
373
+ - [Response Validator](https://github.com/mastra-ai/mastra/tree/main/examples/processors-response-validator)
@@ -240,3 +240,4 @@ network-execution-event-step-finish
240
240
  - [Agent Memory](./agent-memory)
241
241
  - [Workflows Overview](../workflows/overview)
242
242
  - [Request Context](/docs/v1/server-db/request-context)
243
+ - [Supervisor example](https://github.com/mastra-ai/mastra/tree/main/examples/supervisor-agent)