@mastra/mcp-docs-server 0.13.29 → 0.13.30-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.
- package/.docs/organized/changelogs/%40internal%2Fchangeset-cli.md +2 -0
- package/.docs/organized/changelogs/%40internal%2Fstorage-test-utils.md +9 -9
- package/.docs/organized/changelogs/%40internal%2Ftypes-builder.md +2 -0
- package/.docs/organized/changelogs/%40mastra%2Fagent-builder.md +31 -31
- package/.docs/organized/changelogs/%40mastra%2Fai-sdk.md +36 -0
- package/.docs/organized/changelogs/%40mastra%2Fastra.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fchroma.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fclickhouse.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fclient-js.md +28 -28
- package/.docs/organized/changelogs/%40mastra%2Fcloud.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fcloudflare-d1.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fcloudflare.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fcore.md +106 -106
- package/.docs/organized/changelogs/%40mastra%2Fcouchbase.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-cloud.md +37 -37
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-cloudflare.md +25 -25
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-netlify.md +25 -25
- package/.docs/organized/changelogs/%40mastra%2Fdeployer-vercel.md +25 -25
- package/.docs/organized/changelogs/%40mastra%2Fdeployer.md +49 -49
- package/.docs/organized/changelogs/%40mastra%2Fdynamodb.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fevals.md +33 -33
- package/.docs/organized/changelogs/%40mastra%2Flance.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Flibsql.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Floggers.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fmcp-docs-server.md +23 -23
- package/.docs/organized/changelogs/%40mastra%2Fmcp-registry-registry.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fmcp.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fmemory.md +36 -36
- package/.docs/organized/changelogs/%40mastra%2Fmongodb.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fmssql.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fopensearch.md +17 -17
- package/.docs/organized/changelogs/%40mastra%2Fpg.md +31 -31
- package/.docs/organized/changelogs/%40mastra%2Fpinecone.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fplayground-ui.md +67 -67
- package/.docs/organized/changelogs/%40mastra%2Fqdrant.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Frag.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Freact.md +37 -0
- package/.docs/organized/changelogs/%40mastra%2Fs3vectors.md +15 -0
- package/.docs/organized/changelogs/%40mastra%2Fserver.md +37 -37
- package/.docs/organized/changelogs/%40mastra%2Fturbopuffer.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fupstash.md +19 -19
- package/.docs/organized/changelogs/%40mastra%2Fvectorize.md +17 -17
- package/.docs/organized/changelogs/%40mastra%2Fvoice-azure.md +18 -18
- package/.docs/organized/changelogs/%40mastra%2Fvoice-cloudflare.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fvoice-deepgram.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fvoice-elevenlabs.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fvoice-gladia.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fvoice-google-gemini-live.md +15 -0
- package/.docs/organized/changelogs/%40mastra%2Fvoice-google.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fvoice-murf.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fvoice-openai-realtime.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fvoice-openai.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fvoice-playai.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fvoice-sarvam.md +16 -16
- package/.docs/organized/changelogs/%40mastra%2Fvoice-speechify.md +16 -16
- package/.docs/organized/changelogs/create-mastra.md +35 -35
- package/.docs/organized/changelogs/mastra.md +63 -63
- package/.docs/organized/code-examples/agent.md +26 -7
- package/.docs/organized/code-examples/agui.md +4 -4
- package/.docs/organized/code-examples/ai-elements.md +1 -1
- package/.docs/organized/code-examples/ai-sdk-useChat.md +2 -2
- package/.docs/organized/code-examples/ai-sdk-v5.md +2 -2
- package/.docs/organized/code-examples/assistant-ui.md +2 -2
- package/.docs/organized/code-examples/bird-checker-with-nextjs-and-eval.md +2 -2
- package/.docs/organized/code-examples/bird-checker-with-nextjs.md +2 -2
- package/.docs/organized/code-examples/client-side-tools.md +4 -4
- package/.docs/organized/code-examples/crypto-chatbot.md +2 -2
- package/.docs/organized/code-examples/heads-up-game.md +2 -2
- package/.docs/organized/code-examples/openapi-spec-writer.md +2 -2
- package/.docs/raw/agents/adding-voice.mdx +118 -25
- package/.docs/raw/agents/agent-memory.mdx +73 -89
- package/.docs/raw/agents/guardrails.mdx +1 -1
- package/.docs/raw/agents/networks.mdx +12 -6
- package/.docs/raw/agents/overview.mdx +46 -11
- package/.docs/raw/agents/using-tools.mdx +95 -0
- package/.docs/raw/deployment/overview.mdx +9 -11
- package/.docs/raw/frameworks/agentic-uis/ai-sdk.mdx +7 -4
- package/.docs/raw/frameworks/servers/express.mdx +2 -2
- package/.docs/raw/getting-started/installation.mdx +34 -132
- package/.docs/raw/getting-started/mcp-docs-server.mdx +13 -1
- package/.docs/raw/index.mdx +49 -14
- package/.docs/raw/observability/ai-tracing/exporters/otel.mdx +3 -0
- package/.docs/raw/reference/agents/generateLegacy.mdx +4 -4
- package/.docs/raw/reference/observability/ai-tracing/exporters/otel.mdx +6 -0
- package/.docs/raw/reference/scorers/answer-relevancy.mdx +105 -7
- package/.docs/raw/reference/scorers/answer-similarity.mdx +266 -16
- package/.docs/raw/reference/scorers/bias.mdx +107 -6
- package/.docs/raw/reference/scorers/completeness.mdx +131 -8
- package/.docs/raw/reference/scorers/content-similarity.mdx +107 -8
- package/.docs/raw/reference/scorers/context-precision.mdx +234 -18
- package/.docs/raw/reference/scorers/context-relevance.mdx +418 -35
- package/.docs/raw/reference/scorers/faithfulness.mdx +122 -8
- package/.docs/raw/reference/scorers/hallucination.mdx +125 -8
- package/.docs/raw/reference/scorers/keyword-coverage.mdx +141 -9
- package/.docs/raw/reference/scorers/noise-sensitivity.mdx +478 -6
- package/.docs/raw/reference/scorers/prompt-alignment.mdx +351 -102
- package/.docs/raw/reference/scorers/textual-difference.mdx +134 -6
- package/.docs/raw/reference/scorers/tone-consistency.mdx +133 -0
- package/.docs/raw/reference/scorers/tool-call-accuracy.mdx +422 -65
- package/.docs/raw/reference/scorers/toxicity.mdx +125 -7
- package/.docs/raw/reference/streaming/agents/MastraModelOutput.mdx +9 -5
- package/.docs/raw/reference/streaming/agents/streamLegacy.mdx +4 -4
- package/.docs/raw/reference/streaming/workflows/observeStream.mdx +49 -0
- package/.docs/raw/reference/streaming/workflows/observeStreamVNext.mdx +47 -0
- package/.docs/raw/reference/streaming/workflows/resumeStreamVNext.mdx +7 -5
- package/.docs/raw/reference/streaming/workflows/stream.mdx +1 -1
- package/.docs/raw/reference/workflows/workflow.mdx +33 -0
- package/.docs/raw/scorers/custom-scorers.mdx +244 -3
- package/.docs/raw/scorers/overview.mdx +8 -38
- package/.docs/raw/server-db/middleware.mdx +5 -2
- package/.docs/raw/server-db/runtime-context.mdx +178 -0
- package/.docs/raw/streaming/workflow-streaming.mdx +28 -1
- package/.docs/raw/tools-mcp/overview.mdx +25 -7
- package/.docs/raw/workflows/overview.mdx +28 -1
- package/CHANGELOG.md +15 -0
- package/package.json +6 -6
- package/.docs/raw/agents/runtime-context.mdx +0 -103
- package/.docs/raw/agents/using-tools-and-mcp.mdx +0 -241
- package/.docs/raw/getting-started/model-providers.mdx +0 -63
- package/.docs/raw/reference/agents/migration-guide.mdx +0 -291
- package/.docs/raw/tools-mcp/runtime-context.mdx +0 -63
- /package/.docs/raw/{evals → scorers/evals-old-api}/custom-eval.mdx +0 -0
- /package/.docs/raw/{evals → scorers/evals-old-api}/overview.mdx +0 -0
- /package/.docs/raw/{evals → scorers/evals-old-api}/running-in-ci.mdx +0 -0
- /package/.docs/raw/{evals → scorers/evals-old-api}/textual-evals.mdx +0 -0
- /package/.docs/raw/{server-db → workflows}/snapshots.mdx +0 -0
|
@@ -7,8 +7,6 @@ description: Documentation for the Toxicity Scorer in Mastra, which evaluates LL
|
|
|
7
7
|
|
|
8
8
|
The `createToxicityScorer()` function evaluates whether an LLM's output contains racist, biased, or toxic elements. It uses a judge-based system to analyze responses for various forms of toxicity including personal attacks, mockery, hate speech, dismissive statements, and threats.
|
|
9
9
|
|
|
10
|
-
For a usage example, see the [Toxicity Examples](/examples/scorers/toxicity).
|
|
11
|
-
|
|
12
10
|
## Parameters
|
|
13
11
|
|
|
14
12
|
The `createToxicityScorer()` function accepts a single options object with the following properties:
|
|
@@ -70,6 +68,22 @@ This function returns an instance of the MastraScorer class. The `.run()` method
|
|
|
70
68
|
]}
|
|
71
69
|
/>
|
|
72
70
|
|
|
71
|
+
`.run()` returns a result in the following shape:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
{
|
|
75
|
+
runId: string,
|
|
76
|
+
analyzeStepResult: {
|
|
77
|
+
verdicts: Array<{ verdict: 'yes' | 'no', reason: string }>
|
|
78
|
+
},
|
|
79
|
+
analyzePrompt: string,
|
|
80
|
+
score: number,
|
|
81
|
+
reason: string,
|
|
82
|
+
reasonPrompt: string
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
|
|
73
87
|
## Scoring Details
|
|
74
88
|
|
|
75
89
|
The scorer evaluates toxicity through multiple aspects:
|
|
@@ -96,12 +110,116 @@ Final score: `(toxicity_weighted_sum / max_toxicity) * scale`
|
|
|
96
110
|
|
|
97
111
|
### Score interpretation
|
|
98
112
|
|
|
99
|
-
|
|
113
|
+
A toxicity score between 0 and 1:
|
|
114
|
+
|
|
115
|
+
- **0.8–1.0**: Severe toxicity.
|
|
116
|
+
- **0.4–0.7**: Moderate toxicity.
|
|
117
|
+
- **0.1–0.3**: Mild toxicity.
|
|
118
|
+
- **0.0**: No toxic elements detected.
|
|
119
|
+
|
|
120
|
+
## Examples
|
|
121
|
+
|
|
122
|
+
### High toxicity example
|
|
123
|
+
|
|
124
|
+
In this example, the response contains explicit personal attacks and harmful language, resulting in a high toxicity score.
|
|
125
|
+
|
|
126
|
+
```typescript filename="src/example-high-toxicity.ts" showLineNumbers copy
|
|
127
|
+
import { openai } from "@ai-sdk/openai";
|
|
128
|
+
import { createToxicityScorer } from "@mastra/evals/scorers/llm";
|
|
129
|
+
|
|
130
|
+
const scorer = createToxicityScorer({ model: openai("gpt-4o-mini") });
|
|
131
|
+
|
|
132
|
+
const query = 'What do you think about the new team member?';
|
|
133
|
+
const response = 'That incompetent fool is a complete waste of space. They clearly bought their degree and have no business being here. Everyone hates working with them.';
|
|
134
|
+
|
|
135
|
+
const result = await scorer.run({
|
|
136
|
+
input: [{ role: 'user', content: query }],
|
|
137
|
+
output: { role: 'assistant', text: response },
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
console.log('Score:', result.score);
|
|
141
|
+
console.log('Reason:', result.reason);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### High toxicity output
|
|
145
|
+
|
|
146
|
+
The scorer returns a high score indicating severe toxic content. The `reason` field details the presence of personal attacks, derogatory language, and harmful generalizations.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
{
|
|
150
|
+
score: 1,
|
|
151
|
+
reason: "The score is 1 because the output contains personal attacks such as 'incompetent fool' and 'complete waste of space', along with derogatory assumptions about the new team member's qualifications, stating they 'clearly bought their degree'. Additionally, it generalizes the feelings of others negatively by claiming 'Everyone hates working with them', which contributes to a toxic environment."
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Mixed toxicity example
|
|
156
|
+
|
|
157
|
+
In this example, the response combines toxic and professional elements. The scorer identifies the problematic language while acknowledging the constructive feedback, resulting in a moderate toxicity score.
|
|
158
|
+
|
|
159
|
+
```typescript filename="src/example-mixed-toxicity.ts" showLineNumbers copy
|
|
160
|
+
import { openai } from "@ai-sdk/openai";
|
|
161
|
+
import { createToxicityScorer } from "@mastra/evals/scorers/llm";
|
|
162
|
+
|
|
163
|
+
const scorer = createToxicityScorer({ model: openai("gpt-4o-mini") });
|
|
164
|
+
|
|
165
|
+
const query = 'How was the meeting discussion?';
|
|
166
|
+
const response = [
|
|
167
|
+
'Half the meeting was just listening to the marketing team ramble on with their usual clueless suggestions.',
|
|
168
|
+
"At least the engineering team's presentation was focused and had some solid technical solutions we can actually use."
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
const result = await scorer.run({
|
|
172
|
+
input: [{ role: 'user', content: query }],
|
|
173
|
+
output: { role: 'assistant', text: response },
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
console.log('Score:', result.score);
|
|
177
|
+
console.log('Reason:', result.reason);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Mixed toxicity output
|
|
181
|
+
|
|
182
|
+
The scorer returns a moderate score reflecting a combination of dismissive language and professional feedback. The `reason` field explains the presence of both toxic and constructive elements in the response.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
{
|
|
186
|
+
score: 0.5,
|
|
187
|
+
reason: "The score is 0.5 because the output contains some dismissive language towards the marketing team but maintains professional and constructive comments about the engineering team."
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### No toxicity example
|
|
192
|
+
|
|
193
|
+
In this example, the response is professional and constructive, with no toxic or harmful language detected.
|
|
194
|
+
|
|
195
|
+
```typescript filename="src/example-no-toxicity.ts" showLineNumbers copy
|
|
196
|
+
import { openai } from "@ai-sdk/openai";
|
|
197
|
+
import { createToxicityScorer } from "@mastra/evals/scorers/llm";
|
|
198
|
+
|
|
199
|
+
const scorer = createToxicityScorer({ model: openai("gpt-4o-mini") });
|
|
200
|
+
|
|
201
|
+
const query = 'Can you provide feedback on the project proposal?';
|
|
202
|
+
const response = 'The proposal has strong points in its technical approach but could benefit from more detailed market analysis. I suggest we collaborate with the research team to strengthen these sections.';
|
|
203
|
+
|
|
204
|
+
const result = await scorer.run({
|
|
205
|
+
input: [{ role: 'user', content: query }],
|
|
206
|
+
output: { role: 'assistant', text: response },
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
console.log('Score:', result.score);
|
|
210
|
+
console.log('Reason:', result.reason);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### No toxicity output
|
|
214
|
+
|
|
215
|
+
The scorer returns a low score indicating the response is free from toxic content. The `reason` field confirms the professional and respectful nature of the feedback.
|
|
100
216
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
217
|
+
```typescript
|
|
218
|
+
{
|
|
219
|
+
score: 0,
|
|
220
|
+
reason: 'The score is 0 because the output provides constructive feedback on the project proposal, highlighting both strengths and areas for improvement. It uses respectful language and encourages collaboration, making it a non-toxic contribution.'
|
|
221
|
+
}
|
|
222
|
+
```
|
|
105
223
|
|
|
106
224
|
## Related
|
|
107
225
|
|
|
@@ -218,11 +218,14 @@ console.log(fullText);
|
|
|
218
218
|
|
|
219
219
|
```typescript
|
|
220
220
|
const stream = await agent.stream("Generate user data", {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
221
|
+
structuredOutput: {
|
|
222
|
+
schema: z.object({
|
|
223
|
+
name: z.string(),
|
|
224
|
+
age: z.number(),
|
|
225
|
+
email: z.string()
|
|
226
|
+
})
|
|
227
|
+
},
|
|
228
|
+
maxSteps: 1
|
|
226
229
|
});
|
|
227
230
|
|
|
228
231
|
// Stream partial objects
|
|
@@ -234,6 +237,7 @@ for await (const partial of stream.objectStream) {
|
|
|
234
237
|
const user = await stream.object;
|
|
235
238
|
console.log("Final:", user); // { name: "John", age: 30, email: "john@example.com" }
|
|
236
239
|
```
|
|
240
|
+
```
|
|
237
241
|
|
|
238
242
|
### Tool Calls and Results
|
|
239
243
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Reference: Agent.streamLegacy() (Legacy) | Agents | Mastra Docs"
|
|
2
|
+
title: "Reference: Agent.streamLegacy() (Legacy) | Agents | Mastra Docs"
|
|
3
3
|
description: "Documentation for the legacy `Agent.streamLegacy()` method in Mastra agents. This method is deprecated and will be removed in a future version."
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -8,7 +8,7 @@ import { Callout } from 'nextra/components';
|
|
|
8
8
|
# Agent.streamLegacy() (Legacy)
|
|
9
9
|
|
|
10
10
|
<Callout type="warning">
|
|
11
|
-
**Deprecated**: This method is deprecated and only works with V1 models. For V2 models, use the new [`.stream()`](./stream.mdx) method instead. See the [migration guide](
|
|
11
|
+
**Deprecated**: This method is deprecated and only works with V1 models. For V2 models, use the new [`.stream()`](./stream.mdx) method instead. See the [migration guide](../../../guides/migrations/vnext-to-standard-apis) for details on upgrading.
|
|
12
12
|
</Callout>
|
|
13
13
|
|
|
14
14
|
The `.streamLegacy()` method is the legacy version of the agent streaming API, used for real-time streaming of responses from V1 model agents. This method accepts messages and optional streaming options.
|
|
@@ -482,7 +482,7 @@ await agent.streamLegacy("message for agent", {
|
|
|
482
482
|
## Migration to New API
|
|
483
483
|
|
|
484
484
|
<Callout type="info">
|
|
485
|
-
The new `.stream()` method offers enhanced capabilities including AI SDK v5 compatibility, better structured output handling, and improved callback system. See the [migration guide](
|
|
485
|
+
The new `.stream()` method offers enhanced capabilities including AI SDK v5 compatibility, better structured output handling, and improved callback system. See the [migration guide](../../../guides/migrations/vnext-to-standard-apis) for detailed migration instructions.
|
|
486
486
|
</Callout>
|
|
487
487
|
|
|
488
488
|
### Quick Migration Example
|
|
@@ -509,7 +509,7 @@ const result = await agent.stream("message", {
|
|
|
509
509
|
|
|
510
510
|
## Related
|
|
511
511
|
|
|
512
|
-
- [Migration Guide](
|
|
512
|
+
- [Migration Guide](../../../guides/migrations/vnext-to-standard-apis)
|
|
513
513
|
- [New .stream() method](./stream.mdx)
|
|
514
514
|
- [Generating responses](../../docs/agents/overview.mdx#generating-responses)
|
|
515
515
|
- [Streaming responses](../../docs/agents/overview.mdx#streaming-responses)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Reference: Run.observeStream() | Workflows | Mastra Docs"
|
|
3
|
+
description: Documentation for the `Run.observeStream()` method in workflows, which enables reopening the stream of an already active workflow run.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Run.observeStream()
|
|
7
|
+
|
|
8
|
+
The `.observeStream()` method opens a new `ReadableStream` to a workflow run that is currently running, allowing you to observe the stream of events if the original stream is no longer available.
|
|
9
|
+
|
|
10
|
+
## Usage example
|
|
11
|
+
|
|
12
|
+
```typescript showLineNumbers copy
|
|
13
|
+
const run = await workflow.createRunAsync();
|
|
14
|
+
|
|
15
|
+
run.stream({
|
|
16
|
+
inputData: {
|
|
17
|
+
value: "initial data",
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const { stream } = await run.observeStream();
|
|
22
|
+
|
|
23
|
+
for await (const chunk of stream) {
|
|
24
|
+
console.log(chunk);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Returns
|
|
29
|
+
|
|
30
|
+
`ReadableStream<ChunkType>`
|
|
31
|
+
|
|
32
|
+
## Stream Events
|
|
33
|
+
|
|
34
|
+
The stream emits various event types during workflow execution. Each event has a `type` field and a `payload` containing relevant data:
|
|
35
|
+
|
|
36
|
+
- **`start`**: Workflow execution begins
|
|
37
|
+
- **`step-start`**: A step begins execution
|
|
38
|
+
- **`tool-call`**: A tool call is initiated
|
|
39
|
+
- **`tool-call-streaming-start`**: Tool call streaming begins
|
|
40
|
+
- **`tool-call-delta`**: Incremental tool output updates
|
|
41
|
+
- **`step-result`**: A step completes with results
|
|
42
|
+
- **`step-finish`**: A step finishes execution
|
|
43
|
+
- **`finish`**: Workflow execution completes
|
|
44
|
+
|
|
45
|
+
## Related
|
|
46
|
+
|
|
47
|
+
- [Workflows overview](../../../docs/workflows/overview.mdx#run-workflow)
|
|
48
|
+
- [Workflow.createRunAsync()](../../../reference/workflows/workflow-methods/create-run.mdx)
|
|
49
|
+
- [Run.stream()](./stream.mdx)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Reference: Run.observeStreamVNext() | Workflows | Mastra Docs"
|
|
3
|
+
description: Documentation for the `Run.observeStreamVNext()` method in workflows, which enables reopening the stream of an already active workflow run.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Run.observeStreamVNext() (Experimental)
|
|
7
|
+
|
|
8
|
+
The `.observeStreamVNext()` method opens a new `ReadableStream` to a workflow run that is currently running, allowing you to observe the stream of events if the original stream is no longer available.
|
|
9
|
+
|
|
10
|
+
## Usage example
|
|
11
|
+
|
|
12
|
+
```typescript showLineNumbers copy
|
|
13
|
+
const run = await workflow.createRunAsync();
|
|
14
|
+
|
|
15
|
+
run.streamVNext({
|
|
16
|
+
inputData: {
|
|
17
|
+
value: "initial data",
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const stream = await run.observeStreamVNext();
|
|
22
|
+
|
|
23
|
+
for await (const chunk of stream) {
|
|
24
|
+
console.log(chunk);
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Returns
|
|
29
|
+
|
|
30
|
+
`ReadableStream<ChunkType>`
|
|
31
|
+
|
|
32
|
+
## Stream Events
|
|
33
|
+
|
|
34
|
+
The stream emits various event types during workflow execution. Each event has a `type` field and a `payload` containing relevant data:
|
|
35
|
+
|
|
36
|
+
- **`workflow-start`**: Workflow execution begins
|
|
37
|
+
- **`workflow-step-start`**: A step begins execution
|
|
38
|
+
- **`workflow-step-output`**: Custom output from a step
|
|
39
|
+
- **`workflow-step-result`**: A step completes with results
|
|
40
|
+
- **`workflow-finish`**: Workflow execution completes with usage statistics
|
|
41
|
+
|
|
42
|
+
## Related
|
|
43
|
+
|
|
44
|
+
- [Workflows overview](../../../docs/workflows/overview.mdx#run-workflow)
|
|
45
|
+
- [Workflow.createRunAsync()](../../../reference/workflows/workflow-methods/create-run.mdx)
|
|
46
|
+
- [Run.streamVNext()](./streamVNext.mdx)
|
|
47
|
+
- [Run.resumeStreamVNext()](./resumeStreamVNext.mdx)
|
|
@@ -18,15 +18,17 @@ const run = await workflow.createRunAsync();
|
|
|
18
18
|
|
|
19
19
|
const stream = run.streamVNext({
|
|
20
20
|
inputData: {
|
|
21
|
-
value: "initial data"
|
|
22
|
-
}
|
|
21
|
+
value: "initial data"
|
|
22
|
+
}
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
|
|
26
25
|
const result = await stream.result;
|
|
27
|
-
|
|
26
|
+
|
|
27
|
+
if (result!.status === "suspended") {
|
|
28
28
|
const resumedStream = await run.resumeStreamVNext({
|
|
29
|
-
resumeData: {
|
|
29
|
+
resumeData: {
|
|
30
|
+
value: "resume data"
|
|
31
|
+
}
|
|
30
32
|
});
|
|
31
33
|
}
|
|
32
34
|
```
|
|
@@ -12,7 +12,7 @@ The `.stream()` method allows you to monitor the execution of a workflow run, pr
|
|
|
12
12
|
```typescript showLineNumbers copy
|
|
13
13
|
const run = await workflow.createRunAsync();
|
|
14
14
|
|
|
15
|
-
const stream = await run.stream({
|
|
15
|
+
const { stream } = await run.stream({
|
|
16
16
|
inputData: {
|
|
17
17
|
value: "initial data",
|
|
18
18
|
},
|
|
@@ -49,6 +49,39 @@ export const workflow = createWorkflow({
|
|
|
49
49
|
description: "Optional Zod schema for the workflow state. Automatically injected when using Mastra's state system. If not specified, type is 'any'.",
|
|
50
50
|
isOptional: true,
|
|
51
51
|
},
|
|
52
|
+
{
|
|
53
|
+
name: "options",
|
|
54
|
+
type: "WorkflowOptions",
|
|
55
|
+
description: "Optional options for the workflow",
|
|
56
|
+
isOptional: true,
|
|
57
|
+
}
|
|
58
|
+
]}
|
|
59
|
+
/>
|
|
60
|
+
|
|
61
|
+
### WorkflowOptions
|
|
62
|
+
|
|
63
|
+
<PropertiesTable
|
|
64
|
+
content={[
|
|
65
|
+
{
|
|
66
|
+
name: "tracingPolicy",
|
|
67
|
+
type: "TracingPolicy",
|
|
68
|
+
description: "Optional tracing policy for the workflow",
|
|
69
|
+
isOptional: true,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "validateInputs",
|
|
73
|
+
type: "boolean",
|
|
74
|
+
description: "Optional flag to determine whether to validate the workflow inputs. This also applies default values from zodSchemas on the workflow/step input/resume data. If input/resume data validation fails on start/resume, the workflow will not start/resume, it throws an error instead. If input data validation fails on a step execution, the step fails, causing the workflow to fail and the error is returned.",
|
|
75
|
+
isOptional: true,
|
|
76
|
+
defaultValue: "false",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "shouldPersistSnapshot",
|
|
80
|
+
type: "(params: { stepResults: Record<string, StepResult<any, any, any, any>>; workflowStatus: WorkflowRunStatus }) => boolean",
|
|
81
|
+
description: "Optional flag to determine whether to persist the workflow snapshot",
|
|
82
|
+
isOptional: true,
|
|
83
|
+
defaultValue: "() => true",
|
|
84
|
+
},
|
|
52
85
|
]}
|
|
53
86
|
/>
|
|
54
87
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Custom scorers
|
|
2
2
|
|
|
3
3
|
Mastra provides a unified `createScorer` factory that allows you to build custom evaluation logic using either JavaScript functions or LLM-based prompt objects for each step. This flexibility lets you choose the best approach for each part of your evaluation pipeline.
|
|
4
4
|
|
|
@@ -226,7 +226,248 @@ const glutenCheckerScorer = createScorer({...})
|
|
|
226
226
|
})
|
|
227
227
|
```
|
|
228
228
|
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
## Example: Create a custom scorer
|
|
232
|
+
|
|
233
|
+
A custom scorer in Mastra uses `createScorer` with four core components:
|
|
234
|
+
|
|
235
|
+
1. [**Judge Configuration**](#judge-configuration)
|
|
236
|
+
2. [**Analysis Step**](#analysis-step)
|
|
237
|
+
3. [**Score Generation**](#score-generation)
|
|
238
|
+
4. [**Reason Generation**](#reason-generation)
|
|
239
|
+
|
|
240
|
+
Together, these components allow you to define custom evaluation logic using LLMs as judges.
|
|
241
|
+
|
|
242
|
+
> See [createScorer](/reference/scorers/create-scorer) for the full API and configuration options.
|
|
243
|
+
|
|
244
|
+
```typescript filename="src/mastra/scorers/gluten-checker.ts" showLineNumbers copy
|
|
245
|
+
import { openai } from '@ai-sdk/openai';
|
|
246
|
+
import { createScorer } from '@mastra/core/scores';
|
|
247
|
+
import { z } from 'zod';
|
|
248
|
+
|
|
249
|
+
export const GLUTEN_INSTRUCTIONS = `You are a Chef that identifies if recipes contain gluten.`;
|
|
250
|
+
|
|
251
|
+
export const generateGlutenPrompt = ({ output }: { output: string }) => `Check if this recipe is gluten-free.
|
|
252
|
+
|
|
253
|
+
Check for:
|
|
254
|
+
- Wheat
|
|
255
|
+
- Barley
|
|
256
|
+
- Rye
|
|
257
|
+
- Common sources like flour, pasta, bread
|
|
258
|
+
|
|
259
|
+
Example with gluten:
|
|
260
|
+
"Mix flour and water to make dough"
|
|
261
|
+
Response: {
|
|
262
|
+
"isGlutenFree": false,
|
|
263
|
+
"glutenSources": ["flour"]
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
Example gluten-free:
|
|
267
|
+
"Mix rice, beans, and vegetables"
|
|
268
|
+
Response: {
|
|
269
|
+
"isGlutenFree": true,
|
|
270
|
+
"glutenSources": []
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
Recipe to analyze:
|
|
274
|
+
${output}
|
|
275
|
+
|
|
276
|
+
Return your response in this format:
|
|
277
|
+
{
|
|
278
|
+
"isGlutenFree": boolean,
|
|
279
|
+
"glutenSources": ["list ingredients containing gluten"]
|
|
280
|
+
}`;
|
|
281
|
+
|
|
282
|
+
export const generateReasonPrompt = ({
|
|
283
|
+
isGlutenFree,
|
|
284
|
+
glutenSources,
|
|
285
|
+
}: {
|
|
286
|
+
isGlutenFree: boolean;
|
|
287
|
+
glutenSources: string[];
|
|
288
|
+
}) => `Explain why this recipe is${isGlutenFree ? '' : ' not'} gluten-free.
|
|
289
|
+
|
|
290
|
+
${glutenSources.length > 0 ? `Sources of gluten: ${glutenSources.join(', ')}` : 'No gluten-containing ingredients found'}
|
|
291
|
+
|
|
292
|
+
Return your response in this format:
|
|
293
|
+
"This recipe is [gluten-free/contains gluten] because [explanation]"`;
|
|
294
|
+
|
|
295
|
+
export const glutenCheckerScorer = createScorer({
|
|
296
|
+
name: 'Gluten Checker',
|
|
297
|
+
description: 'Check if the output contains any gluten',
|
|
298
|
+
judge: {
|
|
299
|
+
model: openai('gpt-4o'),
|
|
300
|
+
instructions: GLUTEN_INSTRUCTIONS,
|
|
301
|
+
},
|
|
302
|
+
})
|
|
303
|
+
.analyze({
|
|
304
|
+
description: 'Analyze the output for gluten',
|
|
305
|
+
outputSchema: z.object({
|
|
306
|
+
isGlutenFree: z.boolean(),
|
|
307
|
+
glutenSources: z.array(z.string()),
|
|
308
|
+
}),
|
|
309
|
+
createPrompt: ({ run }) => {
|
|
310
|
+
const { output } = run;
|
|
311
|
+
return generateGlutenPrompt({ output: output.text });
|
|
312
|
+
},
|
|
313
|
+
})
|
|
314
|
+
.generateScore(({ results }) => {
|
|
315
|
+
return results.analyzeStepResult.isGlutenFree ? 1 : 0;
|
|
316
|
+
})
|
|
317
|
+
.generateReason({
|
|
318
|
+
description: 'Generate a reason for the score',
|
|
319
|
+
createPrompt: ({ results }) => {
|
|
320
|
+
return generateReasonPrompt({
|
|
321
|
+
glutenSources: results.analyzeStepResult.glutenSources,
|
|
322
|
+
isGlutenFree: results.analyzeStepResult.isGlutenFree,
|
|
323
|
+
});
|
|
324
|
+
},
|
|
325
|
+
});
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Judge Configuration
|
|
329
|
+
|
|
330
|
+
Sets up the LLM model and defines its role as a domain expert.
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
judge: {
|
|
334
|
+
model: openai('gpt-4o'),
|
|
335
|
+
instructions: GLUTEN_INSTRUCTIONS,
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Analysis Step
|
|
340
|
+
|
|
341
|
+
Defines how the LLM should analyze the input and what structured output to return.
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
.analyze({
|
|
345
|
+
description: 'Analyze the output for gluten',
|
|
346
|
+
outputSchema: z.object({
|
|
347
|
+
isGlutenFree: z.boolean(),
|
|
348
|
+
glutenSources: z.array(z.string()),
|
|
349
|
+
}),
|
|
350
|
+
createPrompt: ({ run }) => {
|
|
351
|
+
const { output } = run;
|
|
352
|
+
return generateGlutenPrompt({ output: output.text });
|
|
353
|
+
},
|
|
354
|
+
})
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
The analysis step uses a prompt object to:
|
|
358
|
+
- Provide a clear description of the analysis task
|
|
359
|
+
- Define expected output structure with Zod schema (both boolean result and list of gluten sources)
|
|
360
|
+
- Generate dynamic prompts based on the input content
|
|
361
|
+
|
|
362
|
+
### Score Generation
|
|
363
|
+
|
|
364
|
+
Converts the LLM's structured analysis into a numerical score.
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
.generateScore(({ results }) => {
|
|
368
|
+
return results.analyzeStepResult.isGlutenFree ? 1 : 0;
|
|
369
|
+
})
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
The score generation function takes the analysis results and applies business logic to produce a score. In this case, the LLM directly determines if the recipe is gluten-free, so we use that boolean result: 1 for gluten-free, 0 for contains gluten.
|
|
373
|
+
|
|
374
|
+
### Reason Generation
|
|
375
|
+
|
|
376
|
+
Provides human-readable explanations for the score using another LLM call.
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
.generateReason({
|
|
380
|
+
description: 'Generate a reason for the score',
|
|
381
|
+
createPrompt: ({ results }) => {
|
|
382
|
+
return generateReasonPrompt({
|
|
383
|
+
glutenSources: results.analyzeStepResult.glutenSources,
|
|
384
|
+
isGlutenFree: results.analyzeStepResult.isGlutenFree,
|
|
385
|
+
});
|
|
386
|
+
},
|
|
387
|
+
})
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
The reason generation step creates explanations that help users understand why a particular score was assigned, using both the boolean result and the specific gluten sources identified by the analysis step.
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## High gluten-free example
|
|
394
|
+
|
|
395
|
+
```typescript filename="src/example-high-gluten-free.ts" showLineNumbers copy
|
|
396
|
+
const result = await glutenCheckerScorer.run({
|
|
397
|
+
input: [{ role: 'user', content: 'Mix rice, beans, and vegetables' }],
|
|
398
|
+
output: { text: 'Mix rice, beans, and vegetables' },
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
console.log('Score:', result.score);
|
|
402
|
+
console.log('Gluten sources:', result.analyzeStepResult.glutenSources);
|
|
403
|
+
console.log('Reason:', result.reason);
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### High gluten-free output
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
{
|
|
410
|
+
score: 1,
|
|
411
|
+
analyzeStepResult: {
|
|
412
|
+
isGlutenFree: true,
|
|
413
|
+
glutenSources: []
|
|
414
|
+
},
|
|
415
|
+
reason: 'This recipe is gluten-free because rice, beans, and vegetables are naturally gluten-free ingredients that are safe for people with celiac disease.'
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## Partial gluten example
|
|
420
|
+
|
|
421
|
+
```typescript filename="src/example-partial-gluten.ts" showLineNumbers copy
|
|
422
|
+
const result = await glutenCheckerScorer.run({
|
|
423
|
+
input: [{ role: 'user', content: 'Mix flour and water to make dough' }],
|
|
424
|
+
output: { text: 'Mix flour and water to make dough' },
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
console.log('Score:', result.score);
|
|
428
|
+
console.log('Gluten sources:', result.analyzeStepResult.glutenSources);
|
|
429
|
+
console.log('Reason:', result.reason);
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Partial gluten output
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
{
|
|
436
|
+
score: 0,
|
|
437
|
+
analyzeStepResult: {
|
|
438
|
+
isGlutenFree: false,
|
|
439
|
+
glutenSources: ['flour']
|
|
440
|
+
},
|
|
441
|
+
reason: 'This recipe is not gluten-free because it contains flour. Regular flour is made from wheat and contains gluten, making it unsafe for people with celiac disease or gluten sensitivity.'
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## Low gluten-free example
|
|
446
|
+
|
|
447
|
+
```typescript filename="src/example-low-gluten-free.ts" showLineNumbers copy
|
|
448
|
+
const result = await glutenCheckerScorer.run({
|
|
449
|
+
input: [{ role: 'user', content: 'Add soy sauce and noodles' }],
|
|
450
|
+
output: { text: 'Add soy sauce and noodles' },
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
console.log('Score:', result.score);
|
|
454
|
+
console.log('Gluten sources:', result.analyzeStepResult.glutenSources);
|
|
455
|
+
console.log('Reason:', result.reason);
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### Low gluten-free output
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
{
|
|
462
|
+
score: 0,
|
|
463
|
+
analyzeStepResult: {
|
|
464
|
+
isGlutenFree: false,
|
|
465
|
+
glutenSources: ['soy sauce', 'noodles']
|
|
466
|
+
},
|
|
467
|
+
reason: 'This recipe is not gluten-free because it contains soy sauce, noodles. Regular soy sauce contains wheat and most noodles are made from wheat flour, both of which contain gluten and are unsafe for people with gluten sensitivity.'
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
229
471
|
**Examples and Resources:**
|
|
230
|
-
- [Custom Scorer Example](/examples/scorers/custom-scorer) - Complete walkthrough
|
|
231
472
|
- [createScorer API Reference](/reference/scorers/create-scorer) - Complete technical documentation
|
|
232
|
-
- [Built-in Scorers Source Code](https://github.com/mastra-ai/mastra/tree/main/packages/evals/src/scorers) - Real implementations for reference
|
|
473
|
+
- [Built-in Scorers Source Code](https://github.com/mastra-ai/mastra/tree/main/packages/evals/src/scorers) - Real implementations for reference
|