@mastra/mcp-docs-server 0.13.11 → 0.13.12-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 (73) hide show
  1. package/.docs/organized/changelogs/%40internal%2Fstorage-test-utils.md +19 -19
  2. package/.docs/organized/changelogs/%40internal%2Ftypes-builder.md +2 -0
  3. package/.docs/organized/changelogs/%40mastra%2Fchroma.md +14 -14
  4. package/.docs/organized/changelogs/%40mastra%2Fclickhouse.md +14 -14
  5. package/.docs/organized/changelogs/%40mastra%2Fclient-js.md +42 -42
  6. package/.docs/organized/changelogs/%40mastra%2Fcloudflare-d1.md +14 -14
  7. package/.docs/organized/changelogs/%40mastra%2Fcore.md +45 -45
  8. package/.docs/organized/changelogs/%40mastra%2Fdeployer-cloudflare.md +53 -53
  9. package/.docs/organized/changelogs/%40mastra%2Fdeployer-netlify.md +49 -49
  10. package/.docs/organized/changelogs/%40mastra%2Fdeployer-vercel.md +49 -49
  11. package/.docs/organized/changelogs/%40mastra%2Fdeployer.md +54 -54
  12. package/.docs/organized/changelogs/%40mastra%2Fdynamodb.md +20 -20
  13. package/.docs/organized/changelogs/%40mastra%2Fevals.md +14 -14
  14. package/.docs/organized/changelogs/%40mastra%2Ffirecrawl.md +21 -21
  15. package/.docs/organized/changelogs/%40mastra%2Flance.md +22 -22
  16. package/.docs/organized/changelogs/%40mastra%2Flibsql.md +34 -34
  17. package/.docs/organized/changelogs/%40mastra%2Fmcp-docs-server.md +41 -41
  18. package/.docs/organized/changelogs/%40mastra%2Fmcp.md +33 -33
  19. package/.docs/organized/changelogs/%40mastra%2Fmemory.md +23 -23
  20. package/.docs/organized/changelogs/%40mastra%2Fmongodb.md +20 -20
  21. package/.docs/organized/changelogs/%40mastra%2Fpg.md +37 -37
  22. package/.docs/organized/changelogs/%40mastra%2Fplayground-ui.md +49 -49
  23. package/.docs/organized/changelogs/%40mastra%2Fqdrant.md +21 -21
  24. package/.docs/organized/changelogs/%40mastra%2Frag.md +20 -20
  25. package/.docs/organized/changelogs/%40mastra%2Fschema-compat.md +8 -0
  26. package/.docs/organized/changelogs/%40mastra%2Fserver.md +44 -44
  27. package/.docs/organized/changelogs/%40mastra%2Fvoice-google-gemini-live.md +14 -0
  28. package/.docs/organized/changelogs/create-mastra.md +26 -26
  29. package/.docs/organized/changelogs/mastra.md +63 -63
  30. package/.docs/organized/code-examples/agent.md +292 -275
  31. package/.docs/raw/agents/input-processors.mdx +25 -19
  32. package/.docs/raw/agents/output-processors.mdx +376 -0
  33. package/.docs/raw/agents/overview.mdx +165 -188
  34. package/.docs/raw/agents/streaming.mdx +11 -5
  35. package/.docs/raw/community/contributing-templates.mdx +1 -1
  36. package/.docs/raw/deployment/cloud-providers/amazon-ec2.mdx +9 -9
  37. package/.docs/raw/deployment/cloud-providers/aws-lambda.mdx +27 -33
  38. package/.docs/raw/deployment/cloud-providers/azure-app-services.mdx +12 -12
  39. package/.docs/raw/deployment/cloud-providers/digital-ocean.mdx +17 -17
  40. package/.docs/raw/getting-started/templates.mdx +1 -1
  41. package/.docs/raw/rag/vector-databases.mdx +9 -1
  42. package/.docs/raw/reference/agents/agent.mdx +9 -3
  43. package/.docs/raw/reference/agents/generate.mdx +80 -3
  44. package/.docs/raw/reference/agents/getDefaultGenerateOptions.mdx +1 -1
  45. package/.docs/raw/reference/agents/getDefaultStreamOptions.mdx +1 -1
  46. package/.docs/raw/reference/agents/getDefaultVNextStreamOptions.mdx +1 -1
  47. package/.docs/raw/reference/agents/getLLM.mdx +1 -1
  48. package/.docs/raw/reference/agents/streamVNext.mdx +88 -5
  49. package/.docs/raw/reference/cli/scorers.mdx +160 -0
  50. package/.docs/raw/reference/rag/chroma.mdx +158 -17
  51. package/.docs/raw/reference/templates.mdx +3 -3
  52. package/.docs/raw/reference/tools/create-tool.mdx +2 -2
  53. package/.docs/raw/reference/tools/mcp-client.mdx +9 -9
  54. package/.docs/raw/reference/tools/mcp-server.mdx +5 -5
  55. package/.docs/raw/reference/workflows/branch.mdx +1 -1
  56. package/.docs/raw/reference/workflows/create-run.mdx +4 -4
  57. package/.docs/raw/reference/workflows/execute.mdx +2 -2
  58. package/.docs/raw/reference/workflows/foreach.mdx +1 -1
  59. package/.docs/raw/reference/workflows/run-methods/cancel.mdx +58 -0
  60. package/.docs/raw/reference/workflows/{resume.mdx → run-methods/resume.mdx} +7 -5
  61. package/.docs/raw/reference/workflows/{start.mdx → run-methods/start.mdx} +5 -5
  62. package/.docs/raw/reference/workflows/{stream.mdx → run-methods/stream.mdx} +6 -3
  63. package/.docs/raw/reference/workflows/{streamVNext.mdx → run-methods/streamVNext.mdx} +14 -9
  64. package/.docs/raw/reference/workflows/{watch.mdx → run-methods/watch.mdx} +12 -12
  65. package/.docs/raw/reference/workflows/run.mdx +104 -0
  66. package/.docs/raw/reference/workflows/step.mdx +0 -1
  67. package/.docs/raw/reference/workflows/workflow.mdx +3 -2
  68. package/.docs/raw/{reference/workflows → server-db}/snapshots.mdx +2 -2
  69. package/.docs/raw/voice/overview.mdx +81 -2
  70. package/.docs/raw/voice/speech-to-speech.mdx +45 -0
  71. package/.docs/raw/workflows/overview.mdx +11 -4
  72. package/.docs/raw/workflows-legacy/overview.mdx +8 -8
  73. package/package.json +4 -4
@@ -19,7 +19,7 @@ This processor normalizes Unicode text to ensure consistent formatting and remov
19
19
 
20
20
  ```typescript copy showLineNumbers {9-11}
21
21
  import { Agent } from "@mastra/core/agent";
22
- import { UnicodeNormalizer } from "@mastra/core/agent/input-processor/processors";
22
+ import { UnicodeNormalizer } from "@mastra/core/processors";
23
23
  import { openai } from "@ai-sdk/openai";
24
24
 
25
25
  const agent = new Agent({
@@ -41,16 +41,16 @@ Available options:
41
41
  - `collapseWhitespace`: Collapse multiple spaces/newlines (default: true)
42
42
  - `trim`: Remove leading/trailing whitespace (default: true)
43
43
 
44
- ### `ModerationInputProcessor`
44
+ ### `ModerationProcessor`
45
45
 
46
46
  This processor provides content moderation using an LLM to detect inappropriate content across multiple categories.
47
47
 
48
48
  ```typescript copy showLineNumbers {5-13}
49
- import { ModerationInputProcessor } from "@mastra/core/agent/input-processor/processors";
49
+ import { ModerationProcessor } from "@mastra/core/processors";
50
50
 
51
51
  const agent = new Agent({
52
52
  inputProcessors: [
53
- new ModerationInputProcessor({
53
+ new ModerationProcessor({
54
54
  model: openai("gpt-4.1-nano"), // Use a fast, cost-effective model
55
55
  threshold: 0.7, // Confidence threshold for flagging
56
56
  strategy: 'block', // Block flagged content
@@ -77,7 +77,7 @@ Strategies available:
77
77
  This processor detects and prevents prompt injection attacks, jailbreaks, and system manipulation attempts.
78
78
 
79
79
  ```typescript copy showLineNumbers {5-12}
80
- import { PromptInjectionDetector } from "@mastra/core/agent/input-processor/processors";
80
+ import { PromptInjectionDetector } from "@mastra/core/processors";
81
81
 
82
82
  const agent = new Agent({
83
83
  inputProcessors: [
@@ -110,7 +110,7 @@ Strategies available:
110
110
  This processor detects and optionally redacts personally identifiable information (PII) from messages.
111
111
 
112
112
  ```typescript copy showLineNumbers {5-14}
113
- import { PIIDetector } from "@mastra/core/agent/input-processor/processors";
113
+ import { PIIDetector } from "@mastra/core/processors";
114
114
 
115
115
  const agent = new Agent({
116
116
  inputProcessors: [
@@ -148,7 +148,7 @@ Strategies available:
148
148
  This processor detects the language of incoming messages and can automatically translate them to a target language.
149
149
 
150
150
  ```typescript copy showLineNumbers {5-12}
151
- import { LanguageDetector } from "@mastra/core/agent/input-processor/processors";
151
+ import { LanguageDetector } from "@mastra/core/processors";
152
152
 
153
153
  const agent = new Agent({
154
154
  inputProcessors: [
@@ -186,10 +186,10 @@ You can chain multiple processors. They execute sequentially in the order they a
186
186
  import { Agent } from "@mastra/core/agent";
187
187
  import {
188
188
  UnicodeNormalizer,
189
- ModerationInputProcessor,
189
+ ModerationProcessor,
190
190
  PromptInjectionDetector,
191
191
  PIIDetector
192
- } from "@mastra/core/agent/input-processor/processors";
192
+ } from "@mastra/core/processors";
193
193
 
194
194
  const secureAgent = new Agent({
195
195
  inputProcessors: [
@@ -198,7 +198,7 @@ const secureAgent = new Agent({
198
198
  // 2. Check for security threats
199
199
  new PromptInjectionDetector({ model: openai("gpt-4.1-nano") }),
200
200
  // 3. Moderate content
201
- new ModerationInputProcessor({ model: openai("gpt-4.1-nano") }),
201
+ new ModerationProcessor({ model: openai("gpt-4.1-nano") }),
202
202
  // 4. Handle PII last
203
203
  new PIIDetector({ model: openai("gpt-4.1-nano"), strategy: 'redact' }),
204
204
  ],
@@ -207,17 +207,17 @@ const secureAgent = new Agent({
207
207
 
208
208
  ## Creating Custom Processors
209
209
 
210
- You can create custom processors by implementing the `InputProcessor` interface.
210
+ You can create custom processors by implementing the `Processor` interface. A Processor can be used for input processing when it implements the `processInput` method.
211
211
 
212
212
  ```typescript copy showLineNumbers {4-19,23-26}
213
- import type { InputProcessor, MastraMessageV2, TripWire } from "@mastra/core/agent";
213
+ import type { Processor, MastraMessageV2, TripWire } from "@mastra/core/processors";
214
214
 
215
- class MessageLengthLimiter implements InputProcessor {
215
+ class MessageLengthLimiter implements Processor {
216
216
  readonly name = 'message-length-limiter';
217
217
 
218
218
  constructor(private maxLength: number = 1000) {}
219
219
 
220
- process({ messages, abort }: {
220
+ processInput({ messages, abort }: {
221
221
  messages: MastraMessageV2[];
222
222
  abort: (reason?: string) => never
223
223
  }): MastraMessageV2[] {
@@ -260,17 +260,23 @@ When creating custom processors:
260
260
 
261
261
  ## Integration with Agent Methods
262
262
 
263
- Input processors work with both `generate()` and `stream()` methods. The entire processor pipeline completes before the agent begins generating or streaming a response.
263
+ Input processors work with the `generate()`, `stream()`, and `streamVNext()` methods. The entire processor pipeline completes before the agent begins generating or streaming a response.
264
264
 
265
265
  ```typescript copy showLineNumbers
266
266
  // Processors run before generate()
267
267
  const result = await agent.generate('Hello');
268
268
 
269
- // Processors also run before stream()
270
- const stream = await agent.stream('Hello');
271
- for await (const chunk of stream.textStream) {
269
+ // Processors also run before streamVNext()
270
+ const stream = await agent.streamVNext('Hello');
271
+ for await (const chunk of stream) {
272
272
  console.log(chunk);
273
273
  }
274
274
  ```
275
275
 
276
- If any processor calls `abort()`, the request terminates immediately and subsequent processors are not executed. The agent returns a 200 response with details (`result.tripwireReason`) about why the request was blocked.
276
+ If any processor calls `abort()`, the request terminates immediately and subsequent processors are not executed. The agent returns a 200 response with details (`result.tripwireReason`) about why the request was blocked.
277
+
278
+ ## Output Processors
279
+
280
+ While input processors handle user messages before they reach the language model, **output processors** handle the LLM's responses after generation but before they're returned to the user. This is useful for response validation, content filtering, and safety controls on LLM-generated content.
281
+
282
+ See the [Output Processors documentation](/docs/agents/output-processors) for details on processing LLM responses.
@@ -0,0 +1,376 @@
1
+ ---
2
+ title: "Output Processors"
3
+ description: "Learn how to use output processors to intercept and modify AI responses before they are returned to users."
4
+ ---
5
+
6
+ # Output Processors
7
+
8
+ Output Processors allow you to intercept, modify, validate, or filter AI responses _after_ they are generated by the language model but _before_ they are returned to users. This is useful for implementing response validation, content moderation, response transformation, and safety controls on AI-generated content.
9
+
10
+ Processors operate on the AI's response messages in your conversation thread. They can modify, filter, or validate content, and even abort the response entirely if certain conditions are met.
11
+
12
+ ## Built-in Processors
13
+
14
+ Mastra provides several built-in output processors for common use cases:
15
+
16
+ ### `ModerationProcessor`
17
+
18
+ This processor provides content moderation using an LLM to detect inappropriate content across multiple categories.
19
+
20
+ ```typescript copy showLineNumbers {5-13}
21
+ import { ModerationProcessor } from "@mastra/core/processors";
22
+
23
+ const agent = new Agent({
24
+ outputProcessors: [
25
+ new ModerationProcessor({
26
+ model: openai("gpt-4.1-nano"), // Use a fast, cost-effective model
27
+ threshold: 0.7, // Confidence threshold for flagging
28
+ strategy: 'block', // Block flagged content
29
+ categories: ['hate', 'harassment', 'violence'], // Custom categories
30
+ }),
31
+ ],
32
+ });
33
+ ```
34
+
35
+ Available options:
36
+ - `model`: Language model for moderation analysis (required)
37
+ - `categories`: Array of categories to check (default: ['hate','hate/threatening','harassment','harassment/threatening','self-harm','self-harm/intent','self-harm/instructions','sexual','sexual/minors','violence','violence/graphic'])
38
+ - `threshold`: Confidence threshold for flagging (0-1, default: 0.5)
39
+ - `strategy`: Action when content is flagged (default: 'block')
40
+ - `customInstructions`: Custom instructions for the moderation agent
41
+
42
+ Strategies available:
43
+ - `block`: Reject the response with an error (default)
44
+ - `warn`: Log warning but allow content through
45
+ - `filter`: Remove flagged messages but continue processing
46
+
47
+ ### `PIIDetector`
48
+
49
+ This processor detects and optionally redacts personally identifiable information (PII) from AI responses.
50
+
51
+ ```typescript copy showLineNumbers {5-14}
52
+ import { PIIDetector } from "@mastra/core/processors";
53
+
54
+ const agent = new Agent({
55
+ outputProcessors: [
56
+ new PIIDetector({
57
+ model: openai("gpt-4.1-nano"),
58
+ threshold: 0.6,
59
+ strategy: 'redact', // Automatically redact detected PII
60
+ detectionTypes: ['email', 'phone', 'credit-card', 'ssn', 'api-key', 'crypto-wallet', 'iban'],
61
+ redactionMethod: 'mask', // Preserve format while masking
62
+ preserveFormat: true, // Keep original structure in redacted values
63
+ includeDetections: true, // Log details for compliance auditing
64
+ }),
65
+ ],
66
+ });
67
+ ```
68
+
69
+ Available options:
70
+ - `model`: Language model for PII detection (required)
71
+ - `detectionTypes`: Array of PII types to detect (default: ['email', 'phone', 'credit-card', 'ssn', 'api-key', 'ip-address', 'name', 'address', 'date-of-birth', 'url', 'uuid', 'crypto-wallet', 'iban'])
72
+ - `threshold`: Confidence threshold for flagging (0-1, default: 0.6)
73
+ - `strategy`: Action when PII is detected (default: 'block')
74
+ - `redactionMethod`: How to redact PII ('mask', 'hash', 'remove', 'placeholder', default: 'mask')
75
+ - `preserveFormat`: Maintain PII structure during redaction (default: true)
76
+ - `includeDetections`: Include detection details in logs for compliance (default: false)
77
+ - `instructions`: Custom detection instructions for the agent
78
+
79
+ Strategies available:
80
+ - `block`: Reject responses containing PII (default)
81
+ - `warn`: Log warning but allow through
82
+ - `filter`: Remove messages containing PII
83
+ - `redact`: Replace PII with placeholder values
84
+
85
+ ### `StructuredOutputProcessor`
86
+
87
+ This processor converts unstructured LLM text responses into structured data using an internal agent. It preserves the original text while adding structured data to the response metadata as well as to result.object.
88
+
89
+ ```typescript copy showLineNumbers {5-15}
90
+ import { StructuredOutputProcessor } from "@mastra/core/processors";
91
+ import { z } from "zod";
92
+
93
+ const agent = new Agent({
94
+ outputProcessors: [
95
+ new StructuredOutputProcessor({
96
+ schema: z.object({
97
+ sentiment: z.enum(['positive', 'negative', 'neutral']),
98
+ confidence: z.number().min(0).max(1),
99
+ topics: z.array(z.string()),
100
+ }),
101
+ model: openai("gpt-4o-mini"),
102
+ errorStrategy: 'warn', // Log warnings but continue on errors
103
+ instructions: 'Analyze the sentiment and extract key topics from the response',
104
+ }),
105
+ ],
106
+ });
107
+
108
+ const result = await agent.generate("Some conversational text")
109
+
110
+ console.log(result.object) // { sentiment: "positive", confidence: 0.6, topics: ["foo", "bar"] }
111
+ ```
112
+
113
+ Available options:
114
+ - `schema`: Zod schema defining the expected structured output (required)
115
+ - `model`: Language model for the internal structuring agent (required)
116
+ - `errorStrategy`: Strategy when parsing or validation fails ('strict' | 'warn' | 'fallback', default: 'strict')
117
+ - `fallbackValue`: Fallback value when errorStrategy is 'fallback'
118
+ - `instructions`: Custom instructions for the structuring agent
119
+
120
+ The structured data is stored in `result.object` and the original text is preserved in `result.text`.
121
+
122
+ ### `BatchPartsProcessor`
123
+
124
+ This processor batches multiple stream parts together to reduce the frequency of emissions, useful for reducing network overhead or improving user experience.
125
+
126
+ ```typescript copy showLineNumbers {5-12}
127
+ import { BatchPartsProcessor } from "@mastra/core/processors";
128
+
129
+ const agent = new Agent({
130
+ outputProcessors: [
131
+ new BatchPartsProcessor({
132
+ maxBatchSize: 5, // Maximum parts to batch together
133
+ maxWaitTime: 100, // Maximum time to wait before emitting (ms)
134
+ emitOnNonText: true, // Emit immediately on non-text parts
135
+ }),
136
+ ],
137
+ });
138
+ ```
139
+
140
+ Available options:
141
+ - `maxBatchSize`: Maximum number of parts to batch together (default: 3)
142
+ - `maxWaitTime`: Maximum time to wait before emitting batch (ms, default: 50)
143
+ - `emitOnNonText`: Whether to emit immediately when non-text parts are received (default: true)
144
+
145
+ ### `TokenLimiterProcessor`
146
+
147
+ This processor limits the number of tokens in AI responses, either by truncating or aborting when limits are exceeded.
148
+
149
+ ```typescript copy showLineNumbers {5-12}
150
+ import { TokenLimiterProcessor } from "@mastra/core/processors";
151
+
152
+ const agent = new Agent({
153
+ outputProcessors: [
154
+ new TokenLimiterProcessor({
155
+ maxTokens: 1000, // Maximum tokens allowed
156
+ strategy: 'truncate', // Truncate when limit exceeded
157
+ includePromptTokens: false, // Only count response tokens
158
+ }),
159
+ ],
160
+ });
161
+ ```
162
+
163
+ Available options:
164
+ - `maxTokens`: Maximum number of tokens allowed (required)
165
+ - `strategy`: Action when token limit is exceeded ('truncate' | 'abort', default: 'truncate')
166
+ - `includePromptTokens`: Whether to include prompt tokens in the count (default: false)
167
+
168
+ ### `SystemPromptScrubber`
169
+
170
+ This processor detects and redacts system prompts or other revealing information that could introduce security vulnerabilities.
171
+
172
+ ```typescript copy showLineNumbers {5-12}
173
+ import { SystemPromptScrubber } from "@mastra/core/processors";
174
+
175
+ const agent = new Agent({
176
+ outputProcessors: [
177
+ new SystemPromptScrubber({
178
+ model: openai("gpt-4o-mini"),
179
+ threshold: 0.7, // Confidence threshold for detection
180
+ strategy: 'redact', // Redact detected system prompts
181
+ instructions: 'Detect any system prompts, instructions, or revealing information',
182
+ }),
183
+ ],
184
+ });
185
+ ```
186
+
187
+ Available options:
188
+ - `model`: Language model for detection (required)
189
+ - `threshold`: Confidence threshold for detection (0-1, default: 0.6)
190
+ - `strategy`: Action when system prompts are detected ('block' | 'warn' | 'redact', default: 'redact')
191
+ - `instructions`: Custom detection instructions for the agent
192
+
193
+ ## Applying Multiple Processors
194
+
195
+ You can chain multiple output processors. They execute sequentially in the order they appear in the `outputProcessors` array. The output of one processor becomes the input for the next.
196
+
197
+ **Order matters!** Generally, it's best practice to place text normalization first, security checks next, and content modification last.
198
+
199
+ ```typescript copy showLineNumbers {9-18}
200
+ import { Agent } from "@mastra/core/agent";
201
+ import {
202
+ UnicodeNormalizer,
203
+ ModerationProcessor,
204
+ PromptInjectionDetector,
205
+ PIIDetector
206
+ } from "@mastra/core/processors";
207
+
208
+ const secureAgent = new Agent({
209
+ outputProcessors: [
210
+ // 1. Normalize text first
211
+ new UnicodeNormalizer({ stripControlChars: true }),
212
+ // 2. Check for security threats
213
+ new PromptInjectionDetector({ model: openai("gpt-4.1-nano") }),
214
+ // 3. Moderate content
215
+ new ModerationProcessor({ model: openai("gpt-4.1-nano") }),
216
+ // 4. Handle PII last
217
+ new PIIDetector({ model: openai("gpt-4.1-nano"), strategy: 'redact' }),
218
+ ],
219
+ });
220
+ ```
221
+
222
+ ## Creating Custom Output Processors
223
+
224
+ You can create custom output processors by implementing the `Processor` interface. A Processor can be used for output processing when it implements either `processOutputStream` (for streaming) or `processOutputResult` (for final results), or both.
225
+
226
+ ### Streaming Output Processor
227
+
228
+ ```typescript copy showLineNumbers {4-25}
229
+ import type { Processor, MastraMessageV2, TripWire } from "@mastra/core/processors";
230
+ import type { TextStreamPart, ObjectStreamPart } from 'ai';
231
+
232
+ class ResponseLengthLimiter implements Processor {
233
+ readonly name = 'response-length-limiter-and-lower-case-results';
234
+
235
+ constructor(private maxLength: number = 1000) {}
236
+
237
+ async processOutputStream({ chunk, streamParts, state, abort }: { // will run on every stream part emitted from the LLM
238
+ chunk: TextStreamPart<any> | ObjectStreamPart<any>;
239
+ streamParts: (TextStreamPart<any> | ObjectStreamPart<any>)[];
240
+ state: Record<string, any>;
241
+ abort: (reason?: string) => never;
242
+ }): Promise<TextStreamPart<any> | ObjectStreamPart<any> | null> {
243
+ // Track cumulative length in state, each processor gets its own state
244
+ if (!state.cumulativeLength) {
245
+ state.cumulativeLength = 0;
246
+ }
247
+
248
+ const shouldEmitChunk = chunk?.textDelta?.includes('foo');
249
+
250
+ if (chunk.type === 'text-delta') {
251
+ state.cumulativeLength += chunk.textDelta.length;
252
+
253
+ if (state.cumulativeLength > this.maxLength) {
254
+ abort(`Response too long: ${state.cumulativeLength} characters (max: ${this.maxLength})`);
255
+ }
256
+ }
257
+
258
+ if (shouldEmitChunk) {
259
+ return chunk; // Emit the chunk
260
+ } else {
261
+ return null; // Emit nothing
262
+ }
263
+ }
264
+ }
265
+ ```
266
+
267
+ ### Final Result Processor
268
+
269
+ ```typescript copy showLineNumbers {4-19}
270
+ import type { Processor, MastraMessageV2, TripWire } from "@mastra/core/processors";
271
+
272
+ class ResponseValidator implements Processor {
273
+ readonly name = 'response-validator';
274
+
275
+ constructor(private requiredKeywords: string[] = []) {}
276
+
277
+ processOutputResult({ messages, abort }: {
278
+ messages: MastraMessageV2[];
279
+ abort: (reason?: string) => never
280
+ }): MastraMessageV2[] {
281
+ const responseText = messages
282
+ .map(msg => msg.content.parts
283
+ .filter(part => part.type === 'text')
284
+ .map(part => (part as any).text)
285
+ .join('')
286
+ )
287
+ .join('');
288
+
289
+ // Check for required keywords
290
+ for (const keyword of this.requiredKeywords) {
291
+ if (!responseText.toLowerCase().includes(keyword.toLowerCase())) {
292
+ abort(`Response missing required keyword: ${keyword}`);
293
+ }
294
+ }
295
+
296
+ return messages;
297
+ }
298
+ }
299
+ ```
300
+
301
+ When creating custom output processors:
302
+ - Always return the processed data (chunks or messages)
303
+ - Use `abort(reason)` to terminate processing early. Abort is used to simulate blocking a response. Errors thrown with `abort` will be an instance of TripWire.
304
+ - For streaming processors, return `null` or `undefined` to skip emitting a chunk
305
+ - Keep processors focused on a single responsibility
306
+ - If using an agent inside your processor, use a fast model, limit the size of the response from it as much as possible, and make the system prompt as concise as possible.
307
+
308
+ ## Integration with Agent Methods
309
+
310
+ Output processors work with both `generate()` and `streamVNext()` methods. The processor pipeline completes after the agent generates a response but before it's returned to the user.
311
+
312
+ ```typescript copy showLineNumbers
313
+ // Processors run after generate() but before returning result
314
+ const result = await agent.generate('Hello');
315
+ console.log(result.text); // Processed text
316
+ console.log(result.object); // Structured data if applicable
317
+
318
+ // Processors also run during streamVNext() for each chunk
319
+ const stream = await agent.streamVNext('Hello');
320
+ for await (const chunk of stream) {
321
+ console.log(chunk); // Processed chunks
322
+ }
323
+ ```
324
+
325
+ ### Per-Call Overrides
326
+
327
+ You can override output processors for individual calls:
328
+
329
+ ```typescript copy showLineNumbers
330
+ // Override output processors for this specific call
331
+ const result = await agent.generate('Hello', {
332
+ outputProcessors: [
333
+ new ModerationProcessor({ model: openai("gpt-4.1-nano") }),
334
+ ],
335
+ });
336
+
337
+ // Same for streaming
338
+ const stream = await agent.streamVNext('Hello', {
339
+ outputProcessors: [
340
+ new TokenLimiterProcessor({ maxTokens: 500 }),
341
+ ],
342
+ });
343
+ ```
344
+
345
+ ### Structured Output with Better DX
346
+
347
+ For better developer experience with structured output, you can use the `structuredOutput` option:
348
+
349
+ ```typescript copy showLineNumbers
350
+ import { z } from "zod";
351
+
352
+ const result = await agent.generate('Analyze this text', {
353
+ structuredOutput: {
354
+ schema: z.object({
355
+ sentiment: z.enum(['positive', 'negative', 'neutral']),
356
+ confidence: z.number(),
357
+ }),
358
+ model: openai("gpt-4o-mini"),
359
+ errorStrategy: 'warn',
360
+ },
361
+ });
362
+
363
+ console.log(result.text); // Original text
364
+ console.log(result.object); // Typed structured data: { sentiment: 'positive', confidence: 0.8 }
365
+ ```
366
+
367
+ If any processor calls `abort()`, the request terminates immediately and subsequent processors are not executed. The agent returns a 200 response with details (`result.tripwireReason`) about why the response was blocked.
368
+
369
+ ## Input vs Output Processors
370
+
371
+ - **Input Processors**: Handle user messages before they reach the language model
372
+ - **Output Processors**: Handle LLM responses after generation but before they're returned to the user
373
+
374
+ Use input processors for user input validation and security, and output processors for response validation and safety controls on LLM-generated content.
375
+
376
+ See the [Input Processors documentation](/docs/agents/input-processors) for details on processing user messages.