@mastra/mcp-docs-server 0.13.27 → 0.13.28-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.docs/organized/changelogs/%40internal%2Fplayground.md +3 -1
- package/.docs/organized/changelogs/%40internal%2Fstorage-test-utils.md +10 -10
- package/.docs/organized/changelogs/%40internal%2Ftypes-builder.md +4 -0
- package/.docs/organized/changelogs/%40mastra%2Fagent-builder.md +21 -21
- package/.docs/organized/changelogs/%40mastra%2Fai-sdk.md +20 -0
- package/.docs/organized/changelogs/%40mastra%2Fastra.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fchroma.md +11 -11
- package/.docs/organized/changelogs/%40mastra%2Fclickhouse.md +11 -11
- package/.docs/organized/changelogs/%40mastra%2Fclient-js.md +41 -41
- package/.docs/organized/changelogs/%40mastra%2Fcloud.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fcloudflare-d1.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fcloudflare.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fcore.md +97 -97
- package/.docs/organized/changelogs/%40mastra%2Fcouchbase.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-cloud.md +44 -44
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-cloudflare.md +31 -31
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-netlify.md +29 -29
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-vercel.md +31 -31
- package/.docs/organized/changelogs/%40mastra%2Fdeployer.md +75 -75
- package/.docs/organized/changelogs/%40mastra%2Fdynamodb.md +27 -27
- package/.docs/organized/changelogs/%40mastra%2Fevals.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Flance.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Flibsql.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Floggers.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fmcp-docs-server.md +33 -33
- package/.docs/organized/changelogs/%40mastra%2Fmcp-registry-registry.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fmcp.md +21 -21
- package/.docs/organized/changelogs/%40mastra%2Fmemory.md +19 -19
- package/.docs/organized/changelogs/%40mastra%2Fmongodb.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fmssql.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fopensearch.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fpg.md +19 -19
- package/.docs/organized/changelogs/%40mastra%2Fpinecone.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fplayground-ui.md +105 -105
- package/.docs/organized/changelogs/%40mastra%2Fqdrant.md +11 -11
- package/.docs/organized/changelogs/%40mastra%2Frag.md +13 -13
- package/.docs/organized/changelogs/%40mastra%2Freact.md +40 -0
- package/.docs/organized/changelogs/%40mastra%2Fs3vectors.md +21 -0
- package/.docs/organized/changelogs/%40mastra%2Fserver.md +41 -41
- package/.docs/organized/changelogs/%40mastra%2Fturbopuffer.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fupstash.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fvectorize.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fvoice-azure.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fvoice-cloudflare.md +11 -11
- package/.docs/organized/changelogs/%40mastra%2Fvoice-deepgram.md +11 -11
- package/.docs/organized/changelogs/%40mastra%2Fvoice-elevenlabs.md +11 -11
- package/.docs/organized/changelogs/%40mastra%2Fvoice-gladia.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fvoice-google-gemini-live.md +9 -0
- package/.docs/organized/changelogs/%40mastra%2Fvoice-google.md +13 -13
- package/.docs/organized/changelogs/%40mastra%2Fvoice-murf.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fvoice-openai-realtime.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fvoice-openai.md +10 -10
- package/.docs/organized/changelogs/%40mastra%2Fvoice-playai.md +11 -11
- package/.docs/organized/changelogs/%40mastra%2Fvoice-sarvam.md +11 -11
- package/.docs/organized/changelogs/%40mastra%2Fvoice-speechify.md +10 -10
- package/.docs/organized/changelogs/create-mastra.md +79 -79
- package/.docs/organized/changelogs/mastra.md +118 -118
- package/.docs/organized/code-examples/agent.md +2 -1
- package/.docs/organized/code-examples/heads-up-game.md +5 -5
- package/.docs/raw/agents/guardrails.mdx +335 -0
- package/.docs/raw/{networks-vnext/complex-task-execution.mdx → agents/networks.mdx} +29 -9
- package/.docs/raw/agents/overview.mdx +107 -63
- package/.docs/raw/agents/runtime-context.mdx +11 -16
- package/.docs/raw/agents/using-tools-and-mcp.mdx +1 -1
- package/.docs/raw/frameworks/agentic-uis/assistant-ui.mdx +9 -2
- package/.docs/raw/getting-started/mcp-docs-server.mdx +84 -179
- package/.docs/raw/getting-started/model-providers.mdx +5 -3
- package/.docs/raw/reference/agents/network.mdx +1 -1
- package/.docs/raw/reference/cli/create-mastra.mdx +61 -5
- package/.docs/raw/reference/cli/mastra.mdx +252 -0
- package/.docs/raw/reference/client-js/agents.mdx +1 -10
- package/.docs/raw/reference/processors/batch-parts-processor.mdx +111 -0
- package/.docs/raw/reference/processors/language-detector.mdx +154 -0
- package/.docs/raw/reference/processors/moderation-processor.mdx +145 -0
- package/.docs/raw/reference/processors/pii-detector.mdx +153 -0
- package/.docs/raw/reference/processors/prompt-injection-detector.mdx +130 -0
- package/.docs/raw/reference/processors/system-prompt-scrubber.mdx +145 -0
- package/.docs/raw/reference/processors/token-limiter-processor.mdx +136 -0
- package/.docs/raw/reference/processors/unicode-normalizer.mdx +114 -0
- package/.docs/raw/reference/streaming/ChunkType.mdx +2 -6
- package/.docs/raw/reference/streaming/agents/MastraModelOutput.mdx +1 -5
- package/.docs/raw/reference/streaming/workflows/resumeStreamVNext.mdx +1 -1
- package/.docs/raw/reference/streaming/workflows/stream.mdx +1 -1
- package/.docs/raw/reference/streaming/workflows/streamVNext.mdx +1 -1
- package/.docs/raw/reference/workflows/run-methods/resume.mdx +17 -1
- package/.docs/raw/reference/workflows/run-methods/start.mdx +17 -1
- package/.docs/raw/reference/workflows/step.mdx +11 -0
- package/.docs/raw/reference/workflows/workflow.mdx +7 -1
- package/.docs/raw/server-db/local-dev-playground.mdx +1 -1
- package/.docs/raw/workflows/overview.mdx +22 -5
- package/CHANGELOG.md +24 -0
- package/package.json +5 -5
- package/.docs/raw/agents/input-processors.mdx +0 -284
- package/.docs/raw/agents/output-processors.mdx +0 -328
- package/.docs/raw/networks-vnext/overview.mdx +0 -85
- package/.docs/raw/networks-vnext/single-task-execution.mdx +0 -135
- package/.docs/raw/reference/cli/build.mdx +0 -115
- package/.docs/raw/reference/cli/dev.mdx +0 -249
- package/.docs/raw/reference/cli/init.mdx +0 -97
- package/.docs/raw/reference/cli/lint.mdx +0 -56
- package/.docs/raw/reference/cli/mcp-docs-server.mdx +0 -82
- package/.docs/raw/reference/cli/scorers.mdx +0 -160
- package/.docs/raw/reference/cli/start.mdx +0 -50
|
@@ -1,328 +0,0 @@
|
|
|
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
|
-
|
|
86
|
-
### `BatchPartsProcessor`
|
|
87
|
-
|
|
88
|
-
This processor batches multiple stream parts together to reduce the frequency of emissions, useful for reducing network overhead or improving user experience.
|
|
89
|
-
|
|
90
|
-
```typescript copy showLineNumbers {5-12}
|
|
91
|
-
import { BatchPartsProcessor } from "@mastra/core/processors";
|
|
92
|
-
|
|
93
|
-
const agent = new Agent({
|
|
94
|
-
outputProcessors: [
|
|
95
|
-
new BatchPartsProcessor({
|
|
96
|
-
maxBatchSize: 5, // Maximum parts to batch together
|
|
97
|
-
maxWaitTime: 100, // Maximum time to wait before emitting (ms)
|
|
98
|
-
emitOnNonText: true, // Emit immediately on non-text parts
|
|
99
|
-
}),
|
|
100
|
-
],
|
|
101
|
-
});
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
Available options:
|
|
105
|
-
- `maxBatchSize`: Maximum number of parts to batch together (default: 3)
|
|
106
|
-
- `maxWaitTime`: Maximum time to wait before emitting batch (ms, default: 50)
|
|
107
|
-
- `emitOnNonText`: Whether to emit immediately when non-text parts are received (default: true)
|
|
108
|
-
|
|
109
|
-
### `TokenLimiterProcessor`
|
|
110
|
-
|
|
111
|
-
This processor limits the number of tokens in AI responses, either by truncating or aborting when limits are exceeded.
|
|
112
|
-
|
|
113
|
-
```typescript copy showLineNumbers {5-12}
|
|
114
|
-
import { TokenLimiterProcessor } from "@mastra/core/processors";
|
|
115
|
-
|
|
116
|
-
const agent = new Agent({
|
|
117
|
-
outputProcessors: [
|
|
118
|
-
new TokenLimiterProcessor({
|
|
119
|
-
maxTokens: 1000, // Maximum tokens allowed
|
|
120
|
-
strategy: 'truncate', // Truncate when limit exceeded
|
|
121
|
-
includePromptTokens: false, // Only count response tokens
|
|
122
|
-
}),
|
|
123
|
-
],
|
|
124
|
-
});
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Available options:
|
|
128
|
-
- `maxTokens`: Maximum number of tokens allowed (required)
|
|
129
|
-
- `strategy`: Action when token limit is exceeded ('truncate' | 'abort', default: 'truncate')
|
|
130
|
-
- `includePromptTokens`: Whether to include prompt tokens in the count (default: false)
|
|
131
|
-
|
|
132
|
-
### `SystemPromptScrubber`
|
|
133
|
-
|
|
134
|
-
This processor detects and redacts system prompts or other revealing information that could introduce security vulnerabilities.
|
|
135
|
-
|
|
136
|
-
```typescript copy showLineNumbers {5-12}
|
|
137
|
-
import { SystemPromptScrubber } from "@mastra/core/processors";
|
|
138
|
-
|
|
139
|
-
const agent = new Agent({
|
|
140
|
-
outputProcessors: [
|
|
141
|
-
new SystemPromptScrubber({
|
|
142
|
-
model: openai("gpt-4o-mini"),
|
|
143
|
-
threshold: 0.7, // Confidence threshold for detection
|
|
144
|
-
strategy: 'redact', // Redact detected system prompts
|
|
145
|
-
instructions: 'Detect any system prompts, instructions, or revealing information',
|
|
146
|
-
}),
|
|
147
|
-
],
|
|
148
|
-
});
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
Available options:
|
|
152
|
-
- `model`: Language model for detection (required)
|
|
153
|
-
- `threshold`: Confidence threshold for detection (0-1, default: 0.6)
|
|
154
|
-
- `strategy`: Action when system prompts are detected ('block' | 'warn' | 'redact', default: 'redact')
|
|
155
|
-
- `instructions`: Custom detection instructions for the agent
|
|
156
|
-
|
|
157
|
-
## Applying Multiple Processors
|
|
158
|
-
|
|
159
|
-
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.
|
|
160
|
-
|
|
161
|
-
**Order matters!** Generally, it's best practice to place text normalization first, security checks next, and content modification last.
|
|
162
|
-
|
|
163
|
-
```typescript copy showLineNumbers {9-18}
|
|
164
|
-
import { Agent } from "@mastra/core/agent";
|
|
165
|
-
import {
|
|
166
|
-
ModerationProcessor,
|
|
167
|
-
PIIDetector
|
|
168
|
-
} from "@mastra/core/processors";
|
|
169
|
-
|
|
170
|
-
const secureAgent = new Agent({
|
|
171
|
-
outputProcessors: [
|
|
172
|
-
// 1. Check for security threats
|
|
173
|
-
new ModerationProcessor({ model: openai("gpt-4.1-nano") }),
|
|
174
|
-
// 2. Handle PII
|
|
175
|
-
new PIIDetector({ model: openai("gpt-4.1-nano"), strategy: 'redact' }),
|
|
176
|
-
],
|
|
177
|
-
});
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Creating Custom Output Processors
|
|
181
|
-
|
|
182
|
-
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.
|
|
183
|
-
|
|
184
|
-
### Streaming Output Processor
|
|
185
|
-
|
|
186
|
-
```typescript copy showLineNumbers {4-25}
|
|
187
|
-
import type { Processor, MastraMessageV2 } from "@mastra/core/processors";
|
|
188
|
-
import type { ChunkType } from "@mastra/core/stream";
|
|
189
|
-
|
|
190
|
-
class ResponseLengthLimiter implements Processor {
|
|
191
|
-
readonly name = 'response-length-limiter';
|
|
192
|
-
|
|
193
|
-
constructor(private maxLength: number = 1000) {}
|
|
194
|
-
|
|
195
|
-
async processOutputStream({ part, streamParts, state, abort }: {
|
|
196
|
-
part: ChunkType;
|
|
197
|
-
streamParts: ChunkType[];
|
|
198
|
-
state: Record<string, any>;
|
|
199
|
-
abort: (reason?: string) => never;
|
|
200
|
-
}): Promise<ChunkType | null | undefined> {
|
|
201
|
-
// Track cumulative length in state, each processor gets its own state
|
|
202
|
-
if (!state.cumulativeLength) {
|
|
203
|
-
state.cumulativeLength = 0;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (part.type === 'text-delta') {
|
|
207
|
-
state.cumulativeLength += part.payload.text.length;
|
|
208
|
-
|
|
209
|
-
if (state.cumulativeLength > this.maxLength) {
|
|
210
|
-
abort(`Response too long: ${state.cumulativeLength} characters (max: ${this.maxLength})`);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return part; // Emit the part
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Final Result Processor
|
|
220
|
-
|
|
221
|
-
```typescript copy showLineNumbers {4-19}
|
|
222
|
-
import type { Processor, MastraMessageV2 } from "@mastra/core/processors";
|
|
223
|
-
|
|
224
|
-
class ResponseValidator implements Processor {
|
|
225
|
-
readonly name = 'response-validator';
|
|
226
|
-
|
|
227
|
-
constructor(private requiredKeywords: string[] = []) {}
|
|
228
|
-
|
|
229
|
-
processOutputResult({ messages, abort }: {
|
|
230
|
-
messages: MastraMessageV2[];
|
|
231
|
-
abort: (reason?: string) => never
|
|
232
|
-
}): MastraMessageV2[] {
|
|
233
|
-
const responseText = messages
|
|
234
|
-
.map(msg => msg.content.parts
|
|
235
|
-
.filter(part => part.type === 'text')
|
|
236
|
-
.map(part => (part as any).text)
|
|
237
|
-
.join('')
|
|
238
|
-
)
|
|
239
|
-
.join('');
|
|
240
|
-
|
|
241
|
-
// Check for required keywords
|
|
242
|
-
for (const keyword of this.requiredKeywords) {
|
|
243
|
-
if (!responseText.toLowerCase().includes(keyword.toLowerCase())) {
|
|
244
|
-
abort(`Response missing required keyword: ${keyword}`);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
return messages;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
When creating custom output processors:
|
|
254
|
-
- Always return the processed data (parts or messages)
|
|
255
|
-
- 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.
|
|
256
|
-
- For streaming processors, return `null` or `undefined` to skip emitting a part
|
|
257
|
-
- Keep processors focused on a single responsibility
|
|
258
|
-
- 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.
|
|
259
|
-
|
|
260
|
-
## Integration with Agent Methods
|
|
261
|
-
|
|
262
|
-
Output processors work with both `generate()` and `stream()` methods. The processor pipeline completes after the agent generates a response but before it's returned to the user.
|
|
263
|
-
|
|
264
|
-
```typescript copy showLineNumbers
|
|
265
|
-
// Processors run after generate() but before returning result
|
|
266
|
-
const result = await agent.generate('Hello');
|
|
267
|
-
console.log(result.text); // Processed text
|
|
268
|
-
console.log(result.object); // Structured data if applicable
|
|
269
|
-
|
|
270
|
-
// Processors also run during stream() for each part
|
|
271
|
-
const stream = await agent.stream('Hello');
|
|
272
|
-
for await (const part of stream) {
|
|
273
|
-
console.log(part); // Processed parts
|
|
274
|
-
}
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
### Per-Call Overrides
|
|
278
|
-
|
|
279
|
-
You can override output processors for individual calls:
|
|
280
|
-
|
|
281
|
-
```typescript copy showLineNumbers
|
|
282
|
-
// Override output processors for this specific call
|
|
283
|
-
const result = await agent.generate('Hello', {
|
|
284
|
-
outputProcessors: [
|
|
285
|
-
new ModerationProcessor({ model: openai("gpt-4.1-nano") }),
|
|
286
|
-
],
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
// Same for streaming
|
|
290
|
-
const stream = await agent.stream('Hello', {
|
|
291
|
-
outputProcessors: [
|
|
292
|
-
new TokenLimiterProcessor({ maxTokens: 500 }),
|
|
293
|
-
],
|
|
294
|
-
});
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
### Structured Output Processor
|
|
298
|
-
|
|
299
|
-
To use the StructuredOutputProcessor, you should use the `structuredOutput` option:
|
|
300
|
-
|
|
301
|
-
```typescript copy showLineNumbers
|
|
302
|
-
import { z } from "zod";
|
|
303
|
-
|
|
304
|
-
const result = await agent.generate('Analyze this text', {
|
|
305
|
-
structuredOutput: {
|
|
306
|
-
schema: z.object({
|
|
307
|
-
sentiment: z.enum(['positive', 'negative', 'neutral']),
|
|
308
|
-
confidence: z.number(),
|
|
309
|
-
}),
|
|
310
|
-
model: openai("gpt-4o-mini"),
|
|
311
|
-
errorStrategy: 'warn',
|
|
312
|
-
},
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
console.log(result.text); // Original text
|
|
316
|
-
console.log(result.object); // Typed structured data: { sentiment: 'positive', confidence: 0.8 }
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
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.
|
|
320
|
-
|
|
321
|
-
## Input vs Output Processors
|
|
322
|
-
|
|
323
|
-
- **Input Processors**: Handle user messages before they reach the language model
|
|
324
|
-
- **Output Processors**: Handle LLM responses after generation but before they're returned to the user
|
|
325
|
-
|
|
326
|
-
Use input processors for user input validation and security, and output processors for response validation and safety controls on LLM-generated content.
|
|
327
|
-
|
|
328
|
-
See the [Input Processors documentation](/docs/agents/input-processors) for details on processing user messages.
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Handling Complex LLM Operations | Networks | Mastra"
|
|
3
|
-
description: "Networks in Mastra help you execute individual or multiple Mastra primitives in a non-deterministic way using a single API."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Mastra vNext Agent Network
|
|
7
|
-
|
|
8
|
-
The vNext Agent Network module introduces a flexible, composable and non-deterministic way to orchestrate multiple specialized agents and workflows, enabling complex, reasoning and task completion.
|
|
9
|
-
|
|
10
|
-
There are two main problem areas that this system is designed to solve:
|
|
11
|
-
|
|
12
|
-
- Scenarios where a single agent is insufficient, and tasks require collaboration, routing, or sequential/parallel execution across multiple agents and workflows.
|
|
13
|
-
- Scenarios where the task is not fully defined and is initiated with unstructured input. The AgentNetwork can figure out which primitive to call and turn unstructured input into a structured task.
|
|
14
|
-
|
|
15
|
-
## Differences from Workflows
|
|
16
|
-
|
|
17
|
-
- Workflows are linear or branched sequences of steps. This creates a deterministic flow of execution.
|
|
18
|
-
- Agent Networks add a layer of non-deterministic LLM-based orchestration, allowing dynamic, multi-agent collaboration and routing. This creates a non-deterministic flow of execution.
|
|
19
|
-
|
|
20
|
-
## Differences from current experimental implementation
|
|
21
|
-
|
|
22
|
-
- The current implementation of AgentNetwork relies on tool calls to call other agents in the network. The vNext implementation is using Mastra workflows under the hood to break down the execution to individual tasks.
|
|
23
|
-
- New methods, `.generate()` for a one-off "playbook"-like execution of a single primitive in the network, more suitable for a chat-based interface where you iterate on a solution. The `.loop()` method is still available for more complex tasks and operates much like the current implementation.
|
|
24
|
-
|
|
25
|
-
## Important details
|
|
26
|
-
|
|
27
|
-
- Providing memory to the AgentNetwork is _not_ optional when using the `loop` method, as it is required to store the task history. Memory is the core primitive used for any decisions on which primitives to run, as well as determine task completion.
|
|
28
|
-
- Any available primitives (agents, workflows) are used based on their descriptions. The better the description, the better the routing agent will be able to select the right primitive. For workflows, the input schema is also used to determine which inputs to use when calling the workflow. More descriptive naming yields better results.
|
|
29
|
-
- When primitives with overlapping capabilities are available, the routing agent will use the most specific primitive. For example, if both an agent and a workflow can do research, it will use the input schema of the worklfow to determine
|
|
30
|
-
|
|
31
|
-
## Registering the network in Mastra
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
const mastra = new Mastra({
|
|
35
|
-
vnext_networks: {
|
|
36
|
-
'test-network': network,
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// using the network
|
|
41
|
-
const network = mastra.vnext_getNetwork('test-network');
|
|
42
|
-
|
|
43
|
-
if (!network) {
|
|
44
|
-
throw new Error('Network not found');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
console.log(await network.generate('What are the biggest cities in France?', { runtimeContext }));
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Using @mastra/client-js
|
|
51
|
-
|
|
52
|
-
You can use the `@mastra/client-js` package to run the network from the client side.
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
import { MastraClient } from '@mastra/client-js';
|
|
56
|
-
|
|
57
|
-
const client = new MastraClient();
|
|
58
|
-
|
|
59
|
-
const network = client.getVNextNetwork('test-network');
|
|
60
|
-
|
|
61
|
-
console.log(await network.generate('What are the biggest cities in France?', { runtimeContext }));
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
You can also stream the response
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
const stream = await network.stream('What are the biggest cities in France?', { runtimeContext });
|
|
68
|
-
|
|
69
|
-
for await (const chunk of stream) {
|
|
70
|
-
console.log(chunk);
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
And for loops
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
console.log(
|
|
78
|
-
// specifying the task, note that there is a mention here about using an agent for synthesis. This is because the routing agent can actually do some synthesis on results on its own, so this will force it to use agent2 instead
|
|
79
|
-
await network.loop(
|
|
80
|
-
'What are the biggest cities in France? Give me 3. How are they like? Find cities, then do thorough research on each city, and give me a final full report synthesizing all that information. Make sure to use an agent for synthesis.',
|
|
81
|
-
{ runtimeContext },
|
|
82
|
-
),
|
|
83
|
-
);
|
|
84
|
-
```
|
|
85
|
-
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Single Task Execution with AgentNetwork Generate Method"
|
|
3
|
-
description: "Learn how to use the AgentNetwork's generate method in Mastra vNext to convert unstructured input into structured tasks and route them to the most appropriate agent or workflow."
|
|
4
|
-
---
|
|
5
|
-
## Unstructured input to structured task
|
|
6
|
-
|
|
7
|
-
As an example, we have an AgentNetwork with 3 primitives at its disposal:
|
|
8
|
-
|
|
9
|
-
- `agent1`: A general research agent that can do research on a given topic.
|
|
10
|
-
- `agent2`: A general writing agent that can write a full report based on the researched material.
|
|
11
|
-
- `workflow1`: A workflow that can research a given city and write a full report based on the researched material (using both agent1 and agent2).
|
|
12
|
-
|
|
13
|
-
The AgentNetwork is able to route the task to the most appropriate primitive based on the task and the context.
|
|
14
|
-
To ask the AgentNetwork to act on unstructured (text) input, we can use the `generate` method.
|
|
15
|
-
|
|
16
|
-
```typescript
|
|
17
|
-
import { NewAgentNetwork } from '@mastra/core/network/vNext';
|
|
18
|
-
import { Agent } from '@mastra/core/agent';
|
|
19
|
-
import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
20
|
-
import { Memory } from '@mastra/memory';
|
|
21
|
-
import { openai } from '@ai-sdk/openai';
|
|
22
|
-
import { LibSQLStore } from '@mastra/libsql';
|
|
23
|
-
import { z } from 'zod';
|
|
24
|
-
import { RuntimeContext } from '@mastra/core/runtime-context';
|
|
25
|
-
|
|
26
|
-
const memory = new Memory({
|
|
27
|
-
storage: new LibSQLStore({
|
|
28
|
-
url: 'file:../mastra.db', // Or your database URL
|
|
29
|
-
}),
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
const agent1 = new Agent({
|
|
33
|
-
name: 'agent1',
|
|
34
|
-
instructions:
|
|
35
|
-
'This agent is used to do research, but not create full responses. Answer in bullet points only and be concise.',
|
|
36
|
-
description:
|
|
37
|
-
'This agent is used to do research, but not create full responses. Answer in bullet points only and be concise.',
|
|
38
|
-
model: openai('gpt-4o'),
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const agent2 = new Agent({
|
|
42
|
-
name: 'agent2',
|
|
43
|
-
description: 'This agent is used to do text synthesis on researched material. It writes articles in full paragraphs.',
|
|
44
|
-
instructions:
|
|
45
|
-
'This agent is used to do text synthesis on researched material. Write a full report based on the researched material. Do not use bullet points. Write full paragraphs. There should not be a single bullet point in the final report. You write articles.',
|
|
46
|
-
model: openai('gpt-4o'),
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const agentStep1 = createStep({
|
|
50
|
-
id: 'agent-step',
|
|
51
|
-
description: 'This step is used to do research and text synthesis.',
|
|
52
|
-
inputSchema: z.object({
|
|
53
|
-
city: z.string().describe('The city to research'),
|
|
54
|
-
}),
|
|
55
|
-
outputSchema: z.object({
|
|
56
|
-
text: z.string(),
|
|
57
|
-
}),
|
|
58
|
-
execute: async ({ inputData }) => {
|
|
59
|
-
const resp = await agent1.generate(inputData.city, {
|
|
60
|
-
output: z.object({
|
|
61
|
-
text: z.string(),
|
|
62
|
-
}),
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
return { text: resp.object.text };
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const agentStep2 = createStep({
|
|
70
|
-
id: 'agent-step-two',
|
|
71
|
-
description: 'This step is used to do research and text synthesis.',
|
|
72
|
-
inputSchema: z.object({
|
|
73
|
-
text: z.string().describe('The city to research'),
|
|
74
|
-
}),
|
|
75
|
-
outputSchema: z.object({
|
|
76
|
-
text: z.string(),
|
|
77
|
-
}),
|
|
78
|
-
execute: async ({ inputData }) => {
|
|
79
|
-
const resp = await agent2.generate(inputData.text, {
|
|
80
|
-
output: z.object({
|
|
81
|
-
text: z.string(),
|
|
82
|
-
}),
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
return { text: resp.object.text };
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const workflow1 = createWorkflow({
|
|
90
|
-
id: 'workflow1',
|
|
91
|
-
description: 'This workflow is perfect for researching a specific city.',
|
|
92
|
-
steps: [],
|
|
93
|
-
inputSchema: z.object({
|
|
94
|
-
city: z.string(),
|
|
95
|
-
}),
|
|
96
|
-
outputSchema: z.object({
|
|
97
|
-
text: z.string(),
|
|
98
|
-
}),
|
|
99
|
-
})
|
|
100
|
-
.then(agentStep1)
|
|
101
|
-
.then(agentStep2)
|
|
102
|
-
.commit();
|
|
103
|
-
|
|
104
|
-
const network = new NewAgentNetwork({
|
|
105
|
-
id: 'test-network',
|
|
106
|
-
name: 'Test Network',
|
|
107
|
-
instructions:
|
|
108
|
-
'You can research cities. You can also synthesize research material. You can also write a full report based on the researched material.',
|
|
109
|
-
model: openai('gpt-4o'),
|
|
110
|
-
agents: {
|
|
111
|
-
agent1,
|
|
112
|
-
agent2,
|
|
113
|
-
},
|
|
114
|
-
workflows: {
|
|
115
|
-
workflow1,
|
|
116
|
-
},
|
|
117
|
-
memory: memory,
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const runtimeContext = new RuntimeContext();
|
|
121
|
-
|
|
122
|
-
// This will call agent1, as the workflow is meant to be used with individual cities. The best primitive according to the routing agent is thus agent1 which is a general research primitive.
|
|
123
|
-
console.log(await network.generate('What are the biggest cities in France? How are they like?', { runtimeContext }));
|
|
124
|
-
// This will call workflow1, as it is the most suitable primitive according to the routing agent when researching individual cities.
|
|
125
|
-
console.log(await network.generate('Tell me more about Paris', { runtimeContext }));
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
The AgentNetwork will call the most appropriate primitive based on the task and the context. In the case of researching specific cities, it can figure out how to turn unstructured input into structured workflow inputs based on the workflow's input schema and description. It also knows, that for any other research topic, `agent1` is likely the most appropriate primitive.
|
|
129
|
-
|
|
130
|
-
### How It Works
|
|
131
|
-
|
|
132
|
-
- The underlying engine is a Mastra workflow.
|
|
133
|
-
- As a first step, the network uses a **routing agent** to decide which agent or workflow should handle each step.
|
|
134
|
-
- The routing agent will generate a prompt and or structured input for the selected primitive.
|
|
135
|
-
- The next step in the workflow is a `.branch()` that will select the right primitive, calling either an agent step or a workflow step with the input generated by the routing agent.
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "mastra build | Production Bundle | Mastra CLI"
|
|
3
|
-
description: "Build your Mastra project for production deployment"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# mastra build
|
|
7
|
-
|
|
8
|
-
The `mastra build` command bundles your Mastra project into a production-ready Hono server. Hono is a lightweight, type-safe web framework that makes it easy to deploy Mastra agents as HTTP endpoints with middleware support.
|
|
9
|
-
|
|
10
|
-
## Usage
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
mastra build [options]
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Options
|
|
17
|
-
|
|
18
|
-
<PropertiesTable
|
|
19
|
-
content={[
|
|
20
|
-
{
|
|
21
|
-
name: "--dir",
|
|
22
|
-
type: "string",
|
|
23
|
-
description: "Path to your Mastra Folder",
|
|
24
|
-
isOptional: true,
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
name: "--root",
|
|
28
|
-
type: "string",
|
|
29
|
-
description: "Path to your root folder",
|
|
30
|
-
isOptional: true,
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
name: "--tools",
|
|
34
|
-
type: "string",
|
|
35
|
-
description: "Comma-separated list of paths to tool files to include",
|
|
36
|
-
isOptional: true,
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
name: "--help",
|
|
40
|
-
type: "boolean",
|
|
41
|
-
description: "display help for command",
|
|
42
|
-
isOptional: true,
|
|
43
|
-
},
|
|
44
|
-
]}
|
|
45
|
-
/>
|
|
46
|
-
|
|
47
|
-
## Advanced usage
|
|
48
|
-
|
|
49
|
-
### Limit parallelism
|
|
50
|
-
|
|
51
|
-
For CI or when running in resource constrained environments you can cap
|
|
52
|
-
how many expensive tasks run at once by setting `MASTRA_CONCURRENCY`.
|
|
53
|
-
|
|
54
|
-
```bash copy
|
|
55
|
-
MASTRA_CONCURRENCY=2 mastra build
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Unset it to allow the CLI to base concurrency on the host capabilities.
|
|
59
|
-
|
|
60
|
-
### Disable telemetry
|
|
61
|
-
|
|
62
|
-
To opt out of anonymous build analytics set:
|
|
63
|
-
|
|
64
|
-
```bash copy
|
|
65
|
-
MASTRA_TELEMETRY_DISABLED=1 mastra build
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Custom provider endpoints
|
|
69
|
-
|
|
70
|
-
Build time respects the same `OPENAI_BASE_URL` and `ANTHROPIC_BASE_URL`
|
|
71
|
-
variables that `mastra dev` does. They are forwarded by the AI SDK to
|
|
72
|
-
any workflows or tools that call the providers.
|
|
73
|
-
|
|
74
|
-
## What It Does
|
|
75
|
-
|
|
76
|
-
1. Locates your Mastra entry file (either `src/mastra/index.ts` or `src/mastra/index.js`)
|
|
77
|
-
2. Creates a `.mastra` output directory
|
|
78
|
-
3. Bundles your code using Rollup with:
|
|
79
|
-
- Tree shaking for optimal bundle size
|
|
80
|
-
- Node.js environment targeting
|
|
81
|
-
- Source map generation for debugging
|
|
82
|
-
- Excluding test files (named `.test.`, `.spec.` or inside `__tests__` directory)
|
|
83
|
-
|
|
84
|
-
## Example
|
|
85
|
-
|
|
86
|
-
```bash copy
|
|
87
|
-
# Build from current directory
|
|
88
|
-
mastra build
|
|
89
|
-
|
|
90
|
-
# Build from specific directory
|
|
91
|
-
mastra build --dir ./my-mastra-project
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Output
|
|
95
|
-
|
|
96
|
-
The command generates a production bundle in the `.mastra` directory, which includes:
|
|
97
|
-
|
|
98
|
-
- A Hono-based HTTP server with your Mastra agents exposed as endpoints
|
|
99
|
-
- Bundled JavaScript files optimized for production
|
|
100
|
-
- Source maps for debugging
|
|
101
|
-
- Required dependencies
|
|
102
|
-
|
|
103
|
-
This output is suitable for:
|
|
104
|
-
|
|
105
|
-
- Deploying to cloud servers (EC2, Digital Ocean)
|
|
106
|
-
- Running in containerized environments
|
|
107
|
-
- Using with container orchestration systems
|
|
108
|
-
|
|
109
|
-
## Deployers
|
|
110
|
-
|
|
111
|
-
When a Deployer is used, the build output is automatically prepared for the target platform e.g
|
|
112
|
-
|
|
113
|
-
- [Vercel Deployer](/reference/deployer/vercel)
|
|
114
|
-
- [Netlify Deployer](/reference/deployer/netlify)
|
|
115
|
-
- [Cloudflare Deployer](/reference/deployer/cloudflare)
|