@mastra/mcp-docs-server 1.2.15-alpha.3 → 1.2.15-alpha.7
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/docs/agents/a2a.md +39 -0
- package/.docs/docs/agents/skills.md +15 -1
- package/.docs/docs/capabilities/channels/overview.md +19 -0
- package/.docs/docs/evals/overview.md +16 -4
- package/.docs/docs/index.md +1 -1
- package/.docs/docs/observability/feedback.md +16 -0
- package/.docs/guides/getting-started/quickstart.md +1 -1
- package/.docs/guides/voice/realtime-voice.md +28 -2
- package/.docs/models/gateways/neon.md +4 -1
- package/.docs/models/gateways/netlify.md +1 -2
- package/.docs/models/gateways/openrouter.md +1 -1
- package/.docs/models/gateways/vercel.md +8 -2
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/cortecs.md +2 -1
- package/.docs/models/providers/deepinfra.md +2 -2
- package/.docs/models/providers/digitalocean.md +3 -2
- package/.docs/models/providers/empiriolabs.md +6 -4
- package/.docs/models/providers/hyper.md +4 -5
- package/.docs/models/providers/kilo.md +3 -3
- package/.docs/models/providers/llmgateway.md +2 -2
- package/.docs/models/providers/nano-gpt.md +3 -2
- package/.docs/models/providers/neuralwatt.md +2 -1
- package/.docs/models/providers/ofox.md +74 -16
- package/.docs/models/providers/opencode-go.md +1 -1
- package/.docs/models/providers/opencode.md +2 -2
- package/.docs/models/providers/vivgrid.md +4 -2
- package/.docs/models/providers/wandb.md +1 -1
- package/.docs/reference/agents/channels.md +22 -1
- package/.docs/reference/channels/slack-provider.md +2 -0
- package/.docs/reference/client-js/workflows.md +13 -0
- package/.docs/reference/configuration.md +25 -0
- package/.docs/reference/file-based-agents/config.md +22 -21
- package/.docs/reference/file-based-agents/instructions.md +42 -17
- package/.docs/reference/index.md +1 -0
- package/.docs/reference/observability/metrics/automatic-metrics.md +10 -8
- package/.docs/reference/server/routes.md +25 -11
- package/.docs/reference/storage/composite.md +58 -0
- package/.docs/reference/tools/bedrock-kb-tool.md +117 -0
- package/.docs/reference/voice/google.md +19 -3
- package/.docs/reference/workflows/step.md +40 -0
- package/CHANGELOG.md +22 -0
- package/package.json +4 -4
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Ofox
|
|
4
4
|
|
|
5
|
-
Access
|
|
5
|
+
Access 71 Ofox models through Mastra's model router. Authentication is handled automatically using the `OFOX_API_KEY` environment variable.
|
|
6
6
|
|
|
7
7
|
Learn more in the [Ofox documentation](https://ofox.ai/docs).
|
|
8
8
|
|
|
@@ -34,21 +34,79 @@ for await (const chunk of stream) {
|
|
|
34
34
|
|
|
35
35
|
## Models
|
|
36
36
|
|
|
37
|
-
| Model
|
|
38
|
-
|
|
|
39
|
-
| `ofox/anthropic/claude-fable-5`
|
|
40
|
-
| `ofox/anthropic/claude-
|
|
41
|
-
| `ofox/anthropic/claude-
|
|
42
|
-
| `ofox/
|
|
43
|
-
| `ofox/
|
|
44
|
-
| `ofox/
|
|
45
|
-
| `ofox/
|
|
46
|
-
| `ofox/
|
|
47
|
-
| `ofox/
|
|
48
|
-
| `ofox/
|
|
49
|
-
| `ofox/
|
|
50
|
-
| `ofox/
|
|
51
|
-
| `ofox/
|
|
37
|
+
| Model | Context | Tools | Reasoning | Image | Audio | Video | Input $/1M | Output $/1M |
|
|
38
|
+
| ------------------------------------------ | ------- | ----- | --------- | ----- | ----- | ----- | ---------- | ----------- |
|
|
39
|
+
| `ofox/anthropic/claude-fable-5` | 1.0M | | | | | | $10 | $50 |
|
|
40
|
+
| `ofox/anthropic/claude-haiku-4.5` | 200K | | | | | | $1 | $5 |
|
|
41
|
+
| `ofox/anthropic/claude-opus-4.5` | 200K | | | | | | $5 | $25 |
|
|
42
|
+
| `ofox/anthropic/claude-opus-4.6` | 1.0M | | | | | | $5 | $25 |
|
|
43
|
+
| `ofox/anthropic/claude-opus-4.7` | 1.0M | | | | | | $5 | $25 |
|
|
44
|
+
| `ofox/anthropic/claude-opus-4.8` | 1.0M | | | | | | $5 | $25 |
|
|
45
|
+
| `ofox/anthropic/claude-opus-5` | 1.0M | | | | | | $5 | $25 |
|
|
46
|
+
| `ofox/anthropic/claude-sonnet-4.6` | 1.0M | | | | | | $3 | $15 |
|
|
47
|
+
| `ofox/anthropic/claude-sonnet-5` | 1.0M | | | | | | $2 | $10 |
|
|
48
|
+
| `ofox/bailian/qwen-flash` | 1.0M | | | | | | $0.02 | $0.22 |
|
|
49
|
+
| `ofox/bailian/qwen-max` | 33K | | | | | | $0.35 | $1 |
|
|
50
|
+
| `ofox/bailian/qwen-turbo` | 128K | | | | | | $0.05 | $0.09 |
|
|
51
|
+
| `ofox/bailian/qwen-vl-max` | 131K | | | | | | $0.23 | $0.58 |
|
|
52
|
+
| `ofox/bailian/qwen3-coder-flash` | 1.0M | | | | | | $0.50 | $3 |
|
|
53
|
+
| `ofox/bailian/qwen3-coder-next` | 262K | | | | | | $0.20 | $2 |
|
|
54
|
+
| `ofox/bailian/qwen3-coder-plus` | 1.0M | | | | | | $2 | $9 |
|
|
55
|
+
| `ofox/bailian/qwen3-max` | 262K | | | | | | $0.36 | $1 |
|
|
56
|
+
| `ofox/bailian/qwen3.5-122b-a10b` | 256K | | | | | | $0.29 | $2 |
|
|
57
|
+
| `ofox/bailian/qwen3.5-27b` | 262K | | | | | | $0.29 | $2 |
|
|
58
|
+
| `ofox/bailian/qwen3.5-397b-a17b` | 256K | | | | | | $0.55 | $4 |
|
|
59
|
+
| `ofox/bailian/qwen3.5-flash` | 1.0M | | | | | | $0.10 | $0.40 |
|
|
60
|
+
| `ofox/bailian/qwen3.5-plus` | 1.0M | | | | | | $0.40 | $2 |
|
|
61
|
+
| `ofox/bailian/qwen3.6-27b` | 256K | | | | | | $0.60 | $4 |
|
|
62
|
+
| `ofox/bailian/qwen3.6-flash` | 1.0M | | | | | | $0.25 | $2 |
|
|
63
|
+
| `ofox/bailian/qwen3.6-max-preview` | 262K | | | | | | $2 | $12 |
|
|
64
|
+
| `ofox/bailian/qwen3.6-plus` | 1.0M | | | | | | $0.50 | $3 |
|
|
65
|
+
| `ofox/bailian/qwen3.7-max` | 1.0M | | | | | | $3 | $8 |
|
|
66
|
+
| `ofox/bailian/qwen3.7-plus` | 1.0M | | | | | | $0.40 | $2 |
|
|
67
|
+
| `ofox/bailian/qwen3.8-max` | 1.0M | | | | | | $2 | $6 |
|
|
68
|
+
| `ofox/deepseek/deepseek-v3.2` | 128K | | | | | | $0.29 | $0.43 |
|
|
69
|
+
| `ofox/deepseek/deepseek-v4-flash` | 1.0M | | | | | | $0.14 | $0.28 |
|
|
70
|
+
| `ofox/deepseek/deepseek-v4-pro` | 1.0M | | | | | | $0.45 | $0.88 |
|
|
71
|
+
| `ofox/google/gemini-2.5-flash` | 1.0M | | | | | | $0.30 | $3 |
|
|
72
|
+
| `ofox/google/gemini-2.5-flash-lite` | 1.0M | | | | | | $0.10 | $0.40 |
|
|
73
|
+
| `ofox/google/gemini-2.5-pro` | 1.0M | | | | | | $1 | $10 |
|
|
74
|
+
| `ofox/google/gemini-3-flash-preview` | 1.0M | | | | | | $0.50 | $3 |
|
|
75
|
+
| `ofox/google/gemini-3.1-flash-lite` | 1.0M | | | | | | $0.25 | $2 |
|
|
76
|
+
| `ofox/google/gemini-3.1-pro-preview` | 1.0M | | | | | | $2 | $12 |
|
|
77
|
+
| `ofox/google/gemini-3.5-flash` | 1.0M | | | | | | $2 | $9 |
|
|
78
|
+
| `ofox/google/gemini-3.6-flash` | 1.0M | | | | | | $2 | $8 |
|
|
79
|
+
| `ofox/moonshotai/kimi-k2.5` | 262K | | | | | | $0.60 | $3 |
|
|
80
|
+
| `ofox/moonshotai/kimi-k2.6` | 262K | | | | | | $0.95 | $4 |
|
|
81
|
+
| `ofox/moonshotai/kimi-k2.7-code-highspeed` | 262K | | | | | | $2 | $8 |
|
|
82
|
+
| `ofox/moonshotai/kimi-k3` | 1.0M | | | | | | $3 | $15 |
|
|
83
|
+
| `ofox/openai/gpt-4.1` | 1.0M | | | | | | $2 | $8 |
|
|
84
|
+
| `ofox/openai/gpt-4.1-mini` | 1.0M | | | | | | $0.40 | $2 |
|
|
85
|
+
| `ofox/openai/gpt-4o` | 128K | | | | | | $3 | $10 |
|
|
86
|
+
| `ofox/openai/gpt-4o-mini` | 128K | | | | | | $0.15 | $0.60 |
|
|
87
|
+
| `ofox/openai/gpt-5` | 400K | | | | | | $1 | $10 |
|
|
88
|
+
| `ofox/openai/gpt-5-mini` | 256K | | | | | | $0.25 | $2 |
|
|
89
|
+
| `ofox/openai/gpt-5.1` | 400K | | | | | | $1 | $10 |
|
|
90
|
+
| `ofox/openai/gpt-5.1-codex-max` | 256K | | | | | | $1 | $10 |
|
|
91
|
+
| `ofox/openai/gpt-5.1-codex-mini` | 256K | | | | | | $0.25 | $2 |
|
|
92
|
+
| `ofox/openai/gpt-5.2` | 400K | | | | | | $2 | $14 |
|
|
93
|
+
| `ofox/openai/gpt-5.2-codex` | 400K | | | | | | $2 | $14 |
|
|
94
|
+
| `ofox/openai/gpt-5.4-mini` | 400K | | | | | | $0.75 | $5 |
|
|
95
|
+
| `ofox/openai/gpt-5.4-nano` | 400K | | | | | | $0.20 | $1 |
|
|
96
|
+
| `ofox/openai/gpt-5.5` | 1.1M | | | | | | $5 | $30 |
|
|
97
|
+
| `ofox/openai/gpt-5.6-luna` | 1.1M | | | | | | $0.20 | $1 |
|
|
98
|
+
| `ofox/openai/gpt-5.6-sol` | 1.1M | | | | | | $5 | $30 |
|
|
99
|
+
| `ofox/openai/gpt-5.6-terra` | 1.1M | | | | | | $2 | $12 |
|
|
100
|
+
| `ofox/x-ai/grok-4.1-fast` | 2.0M | | | | | | $0.20 | $0.50 |
|
|
101
|
+
| `ofox/x-ai/grok-4.20` | 2.0M | | | | | | $4 | $12 |
|
|
102
|
+
| `ofox/x-ai/grok-4.3` | 1.0M | | | | | | $1 | $3 |
|
|
103
|
+
| `ofox/z-ai/glm-4.6` | 205K | | | | | | $0.40 | $2 |
|
|
104
|
+
| `ofox/z-ai/glm-4.7` | 205K | | | | | | $0.40 | $2 |
|
|
105
|
+
| `ofox/z-ai/glm-4.7-flashx` | 200K | | | | | | $0.07 | $0.43 |
|
|
106
|
+
| `ofox/z-ai/glm-5` | 205K | | | | | | $1 | $3 |
|
|
107
|
+
| `ofox/z-ai/glm-5-turbo` | 200K | | | | | | $1 | $4 |
|
|
108
|
+
| `ofox/z-ai/glm-5.1` | 200K | | | | | | $1 | $4 |
|
|
109
|
+
| `ofox/z-ai/glm-5.2` | 1.0M | | | | | | $1 | $4 |
|
|
52
110
|
|
|
53
111
|
## Advanced configuration
|
|
54
112
|
|
|
@@ -36,7 +36,7 @@ for await (const chunk of stream) {
|
|
|
36
36
|
|
|
37
37
|
| Model | Context | Tools | Reasoning | Image | Audio | Video | Input $/1M | Output $/1M |
|
|
38
38
|
| ------------------------------- | ------- | ----- | --------- | ----- | ----- | ----- | ---------- | ----------- |
|
|
39
|
-
| `opencode-go/deepseek-v4-flash` | 1.0M | | | | | | $0.
|
|
39
|
+
| `opencode-go/deepseek-v4-flash` | 1.0M | | | | | | $0.07 | $0.14 |
|
|
40
40
|
| `opencode-go/deepseek-v4-pro` | 1.0M | | | | | | $0.43 | $0.87 |
|
|
41
41
|
| `opencode-go/glm-5.1` | 203K | | | | | | $1 | $4 |
|
|
42
42
|
| `opencode-go/glm-5.2` | 1.0M | | | | | | $1 | $4 |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# OpenCode Zen
|
|
4
4
|
|
|
5
|
-
Access
|
|
5
|
+
Access 87 OpenCode Zen models through Mastra's model router. Authentication is handled automatically using the `OPENCODE_API_KEY` environment variable.
|
|
6
6
|
|
|
7
7
|
Learn more in the [OpenCode Zen documentation](https://opencode.ai/docs/zen).
|
|
8
8
|
|
|
@@ -86,7 +86,7 @@ for await (const chunk of stream) {
|
|
|
86
86
|
| `opencode/kimi-k2.7-code` | 262K | | | | | | $0.95 | $4 |
|
|
87
87
|
| `opencode/kimi-k3` | 1.0M | | | | | | $3 | $15 |
|
|
88
88
|
| `opencode/laguna-s-2.1-free` | 256K | | | | | | — | — |
|
|
89
|
-
| `opencode/ling-3.0-
|
|
89
|
+
| `opencode/ling-3.0-tiny-free` | 262K | | | | | | — | — |
|
|
90
90
|
| `opencode/longcat-2.0-free` | 1.0M | | | | | | — | — |
|
|
91
91
|
| `opencode/mimo-v2.5-free` | 200K | | | | | | — | — |
|
|
92
92
|
| `opencode/minimax-m2.5` | 205K | | | | | | $0.30 | $1 |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Vivgrid
|
|
4
4
|
|
|
5
|
-
Access
|
|
5
|
+
Access 19 Vivgrid models through Mastra's model router. Authentication is handled automatically using the `VIVGRID_API_KEY` environment variable.
|
|
6
6
|
|
|
7
7
|
Learn more in the [Vivgrid documentation](https://docs.vivgrid.com/models).
|
|
8
8
|
|
|
@@ -37,6 +37,7 @@ for await (const chunk of stream) {
|
|
|
37
37
|
| Model | Context | Tools | Reasoning | Image | Audio | Video | Input $/1M | Output $/1M |
|
|
38
38
|
| --------------------------------------- | ------- | ----- | --------- | ----- | ----- | ----- | ---------- | ----------- |
|
|
39
39
|
| `vivgrid/deepseek-v3.2` | 128K | | | | | | $0.28 | $0.42 |
|
|
40
|
+
| `vivgrid/deepseek-v4-flash` | 1.0M | | | | | | $0.15 | $0.30 |
|
|
40
41
|
| `vivgrid/deepseek-v4-pro` | 1.0M | | | | | | $0.43 | $0.87 |
|
|
41
42
|
| `vivgrid/gemini-3.1-flash-lite-preview` | 1.0M | | | | | | $0.25 | $2 |
|
|
42
43
|
| `vivgrid/gemini-3.1-pro-preview` | 1.0M | | | | | | $2 | $12 |
|
|
@@ -53,6 +54,7 @@ for await (const chunk of stream) {
|
|
|
53
54
|
| `vivgrid/gpt-5.6-luna` | 1.1M | | | | | | $1 | $6 |
|
|
54
55
|
| `vivgrid/gpt-5.6-sol` | 1.1M | | | | | | $5 | $30 |
|
|
55
56
|
| `vivgrid/gpt-5.6-terra` | 1.1M | | | | | | $3 | $15 |
|
|
57
|
+
| `vivgrid/kimi-k3` | 1.0M | | | | | | $3 | $15 |
|
|
56
58
|
|
|
57
59
|
## Advanced configuration
|
|
58
60
|
|
|
@@ -82,7 +84,7 @@ const agent = new Agent({
|
|
|
82
84
|
model: ({ requestContext }) => {
|
|
83
85
|
const useAdvanced = requestContext.task === "complex";
|
|
84
86
|
return useAdvanced
|
|
85
|
-
? "vivgrid/
|
|
87
|
+
? "vivgrid/kimi-k3"
|
|
86
88
|
: "vivgrid/deepseek-v3.2";
|
|
87
89
|
}
|
|
88
90
|
});
|
|
@@ -39,7 +39,7 @@ for await (const chunk of stream) {
|
|
|
39
39
|
| `wandb/deepseek-ai/DeepSeek-V3.1` | 161K | | | | | | $0.55 | $2 |
|
|
40
40
|
| `wandb/deepseek-ai/DeepSeek-V4-Flash` | 1.0M | | | | | | $0.14 | $0.28 |
|
|
41
41
|
| `wandb/deepseek-ai/DeepSeek-V4-Flash-0731` | 262K | | | | | | $0.13 | $0.28 |
|
|
42
|
-
| `wandb/deepseek-ai/DeepSeek-V4-Pro` | 1.0M | | | | | | $
|
|
42
|
+
| `wandb/deepseek-ai/DeepSeek-V4-Pro` | 1.0M | | | | | | $1 | $3 |
|
|
43
43
|
| `wandb/google/gemma-4-31B-it` | 262K | | | | | | $0.10 | $0.34 |
|
|
44
44
|
| `wandb/ibm-granite/granite-4.1-8b` | 131K | | | | | | $0.05 | $0.10 |
|
|
45
45
|
| `wandb/JetBrains/Mellum2-12B-A2.5B-Instruct` | 131K | | | | | | $0.05 | $0.10 |
|
|
@@ -102,7 +102,9 @@ const agent = new Agent({
|
|
|
102
102
|
|
|
103
103
|
**streaming** (`boolean | { updateIntervalMs?: number }`): Stream agent text deltas to the channel as the agent generates them instead of buffering and posting once per step. Requires the underlying adapter to support post-and-edit streaming. Slack defaults to true; other adapters default to false. (Default: `false (true for Slack)`)
|
|
104
104
|
|
|
105
|
-
**
|
|
105
|
+
**textFormat** (`'markdown' | 'plain'`): Dialect for the agent's final reply text. 'markdown' (the default) posts replies as markdown: adapters with native markdown rendering (Slack) render it directly, others convert it to their platform format. 'plain' posts replies as literal plain text, restoring the pre-markdown behavior for agents prompted to emit a platform dialect such as Slack mrkdwn. Applies to final reply text only; tool cards, error messages, and tripwire notices are unaffected. Native streaming is always markdown regardless of this setting. (Default: `'markdown'`)
|
|
106
|
+
|
|
107
|
+
**toolDisplay** (`'cards' | 'text' | 'timeline' | 'grouped' | 'hidden' | ToolDisplayFn`): How tool calls are rendered in the channel. "cards" posts per-tool running/result cards as rich Block Kit. "text" posts the same lifecycle as plain text (no Block Kit). "timeline" and "grouped" stream tool state as inline task\_update chunks (requires streaming: true; Slack only today — other adapters may render a placeholder). "hidden" executes tools silently. Pass a function to render tool events yourself; return { kind: "post", message } for a discrete post/edit, { kind: "stream", chunk } to push into the streaming widget, or undefined to skip rendering that event. Add openIfEmpty: false to a stream result when its chunk should only apply to an active streaming session. Approve/deny prompts always render as a separate card regardless of mode. (Default: `'cards' ('grouped' for Slack)`)
|
|
106
108
|
|
|
107
109
|
**typingStatus** (`boolean | ((chunk: AgentChunkType, ctx: TypingStatusContext) => string | false | null | undefined | void)`): Control the platform typing indicator. true uses built-in defaults (is typing… on text, is calling {tool}… on tool-call, is waiting for approval… on tool-call-approval). false suppresses typing entirely — useful when a live streaming widget (e.g. toolDisplay: "grouped" in Slack) already conveys progress. Pass a function to set custom status copy per chunk; return a string to set the status, or false/null/undefined to leave it unchanged. Compose with defaultTypingStatus (exported from @mastra/core/channels) to fall back to defaults for chunks you don't handle. (Default: `true`)
|
|
108
110
|
|
|
@@ -116,6 +118,25 @@ const agent = new Agent({
|
|
|
116
118
|
|
|
117
119
|
Pass a function to `toolDisplay` for fully custom rendering. The function receives a `ToolDisplayEvent` (`running` / `result` / `error` / `approval`) and a `ToolDisplayContext` (`{ mode, platform }`); return `{ kind: 'post', message }` for a discrete post/edit, `{ kind: 'stream', chunk }` to push into the active streaming widget, or `undefined` to skip rendering that event.
|
|
118
120
|
|
|
121
|
+
By default, a stream result opens a streaming session when none is active. Set `openIfEmpty: false` when the chunk only applies to an existing session. Mastra skips the chunk when no session is active. Static channels ignore this option and keep their existing plain-text fallback behavior.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
toolDisplay: event => {
|
|
125
|
+
if (event.kind !== 'running') return undefined
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
kind: 'stream',
|
|
129
|
+
chunk: {
|
|
130
|
+
type: 'task_update',
|
|
131
|
+
id: event.toolCallId,
|
|
132
|
+
title: event.displayName,
|
|
133
|
+
status: 'in_progress',
|
|
134
|
+
},
|
|
135
|
+
openIfEmpty: false,
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
119
140
|
Approve/deny prompts (`requireApproval`) always render as a separate card regardless of mode, because inline task entries can't carry interactive buttons.
|
|
120
141
|
|
|
121
142
|
```typescript
|
|
@@ -53,6 +53,8 @@ await slack.configure({
|
|
|
53
53
|
|
|
54
54
|
**streaming** (`StreamingConfig | false`): Stream agent text deltas to Slack as they're generated. Pass { updateIntervalMs } to customize the post-and-edit interval, or false to buffer text until step-finish. Disabling streaming restricts toolDisplay to static modes. (Default: `true`)
|
|
55
55
|
|
|
56
|
+
**textFormat** (`'markdown' | 'plain'`): Dialect for the agent's final reply text, forwarded to the Slack adapter. 'markdown' (the default) posts replies as markdown so Slack renders bold text, links, and tables natively. 'plain' posts literal plain text, the escape hatch for agents prompted to emit Slack mrkdwn. Applies to buffered replies (streaming: false) and the streaming fallback; native streaming is always markdown. (Default: `'markdown'`)
|
|
57
|
+
|
|
56
58
|
**toolDisplay** (`ToolDisplay`): How tool calls are rendered in Slack: 'cards', 'text', 'timeline', 'grouped', 'hidden', or a function. 'hidden' suppresses tool call/result rendering entirely. 'timeline' and 'grouped' require streaming. With streaming: false, only static modes are available and the default is 'cards'. (Default: `'grouped'`)
|
|
57
59
|
|
|
58
60
|
**typingStatus** (`boolean | TypingStatusFn`): Show a typing indicator while the agent works. Set false to disable, or pass a function to return custom status text per stream chunk (return undefined to fall back to the default for that chunk). (Default: `true`)
|
|
@@ -12,6 +12,19 @@ Retrieve a list of all available workflows:
|
|
|
12
12
|
const workflows = await mastraClient.listWorkflows()
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
## Getting workflow run counts
|
|
16
|
+
|
|
17
|
+
Retrieve per-workflow counts of `running` and [`suspended`](https://mastra.ai/docs/workflows/suspend-and-resume) runs in a single request. The counts are computed on the server and keyed by the workflow's registry key — the key used when registering the workflow in the Mastra config, which can differ from the workflow's own `id`:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
const runCounts = await mastraClient.listWorkflowRunCounts()
|
|
21
|
+
// { "cityWorkflow": { running: 2, suspended: 1 }, ... }
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Returns: `Record<string, { running: number; suspended: number }>`
|
|
25
|
+
|
|
26
|
+
The server may cache the counts for a few seconds between requests. Servers that predate this endpoint respond with `404 Not Found` — handle the error when the client can talk to older deployments.
|
|
27
|
+
|
|
15
28
|
## Working with a specific workflow
|
|
16
29
|
|
|
17
30
|
Get an instance of a specific workflow by its ID:
|
|
@@ -500,6 +500,31 @@ const mastra = new Mastra({
|
|
|
500
500
|
|
|
501
501
|
## Bundler options
|
|
502
502
|
|
|
503
|
+
### bundler.entries
|
|
504
|
+
|
|
505
|
+
**Type:** `Record<string, string>`\
|
|
506
|
+
**Default:** `{}`
|
|
507
|
+
|
|
508
|
+
Additional process entries to emit alongside the server bundle, as a map of output name to source path relative to your Mastra directory. Each entry becomes its own `<name>.mjs` in `.mastra/output`.
|
|
509
|
+
|
|
510
|
+
Use this for long-running processes that run beside your Mastra server rather than inside it, such as a [LiveKit voice worker](https://mastra.ai/guides/voice/realtime-voice). The entry shares the output directory, `package.json`, and installed dependencies with the server, so one `mastra build` produces one deployable artifact you can start with different commands.
|
|
511
|
+
|
|
512
|
+
```typescript
|
|
513
|
+
import { Mastra } from '@mastra/core'
|
|
514
|
+
|
|
515
|
+
export const mastra = new Mastra({
|
|
516
|
+
bundler: {
|
|
517
|
+
entries: { 'voice-worker': './voice-worker.ts' },
|
|
518
|
+
},
|
|
519
|
+
})
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
This emits `.mastra/output/voice-worker.mjs` next to `.mastra/output/index.mjs`. Dependencies imported only by the extra entry are analyzed too, so they're installed into the output.
|
|
523
|
+
|
|
524
|
+
Entry names can contain `/` to nest the output. They can't be `index`, which is the server bundle, `tools`, which is the tool aggregator, or start with `tools/`, which is reserved for tool bundles.
|
|
525
|
+
|
|
526
|
+
> **Note:** `mastra build` applies the [`bundler.externals`](#bundlerexternals) default of `true` only when you set no bundler options at all. Once you set `entries`, set `externals` explicitly as well if your extra entry depends on packages that can't be bundled, such as native modules.
|
|
527
|
+
|
|
503
528
|
### bundler.externals
|
|
504
529
|
|
|
505
530
|
**Type:** `boolean | string[]`\
|
|
@@ -69,32 +69,33 @@ Please note:
|
|
|
69
69
|
|
|
70
70
|
Keep `config.ts` focused on runtime options. Use sibling files for concerns that benefit from their own location.
|
|
71
71
|
|
|
72
|
-
| Setting | File or folder
|
|
73
|
-
| ------------ |
|
|
74
|
-
| Instructions | [`instructions.md`](https://mastra.ai/reference/file-based-agents/instructions) | Keeps the always-on prompt readable as markdown
|
|
75
|
-
| Tools | [`tools/`](https://mastra.ai/reference/file-based-agents/tools)
|
|
76
|
-
| Skills | [`skills/`](https://mastra.ai/reference/file-based-agents/skills)
|
|
77
|
-
| Memory | [`memory.ts`](https://mastra.ai/reference/file-based-agents/memory)
|
|
78
|
-
| Workspace | [`workspace.ts`](https://mastra.ai/reference/file-based-agents/workspace)
|
|
79
|
-
| Processors | [`processors/`](https://mastra.ai/reference/file-based-agents/processors)
|
|
80
|
-
| Subagents | [`subagents/`](https://mastra.ai/reference/file-based-agents/subagents)
|
|
72
|
+
| Setting | File or folder | Why it lives there |
|
|
73
|
+
| ------------ | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
74
|
+
| Instructions | [`instructions.md` or `instructions.ts`](https://mastra.ai/reference/file-based-agents/instructions) | Keeps the always-on prompt readable as markdown, or computed in TypeScript |
|
|
75
|
+
| Tools | [`tools/`](https://mastra.ai/reference/file-based-agents/tools) | Gives each callable action its own typed module |
|
|
76
|
+
| Skills | [`skills/`](https://mastra.ai/reference/file-based-agents/skills) | Keeps load-on-demand procedures separate from always-on instructions |
|
|
77
|
+
| Memory | [`memory.ts`](https://mastra.ai/reference/file-based-agents/memory) | Configures persistent memory without crowding runtime options |
|
|
78
|
+
| Workspace | [`workspace.ts`](https://mastra.ai/reference/file-based-agents/workspace) | Configures files and sandbox behavior separately from model settings |
|
|
79
|
+
| Processors | [`processors/`](https://mastra.ai/reference/file-based-agents/processors) | Separates input and output processing pipelines |
|
|
80
|
+
| Subagents | [`subagents/`](https://mastra.ai/reference/file-based-agents/subagents) | Gives each specialist child agent its own directory |
|
|
81
81
|
|
|
82
82
|
## Precedence
|
|
83
83
|
|
|
84
84
|
`config.ts` merges with the agent's other files according to these rules:
|
|
85
85
|
|
|
86
|
-
| Domain | Source A
|
|
87
|
-
| ------------ |
|
|
88
|
-
| Instructions | Dynamic `config.instructions`
|
|
89
|
-
| Instructions | Static `config.instructions`
|
|
90
|
-
|
|
|
91
|
-
| Tools |
|
|
92
|
-
|
|
|
93
|
-
| Skills |
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
97
|
-
|
|
86
|
+
| Domain | Source A | Source B | Winner |
|
|
87
|
+
| ------------ | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
|
|
88
|
+
| Instructions | Dynamic `config.instructions` | [`instructions.ts` or `instructions.md`](https://mastra.ai/reference/file-based-agents/instructions) | Dynamic `config.instructions` |
|
|
89
|
+
| Instructions | Static `config.instructions` | [`instructions.ts` or `instructions.md`](https://mastra.ai/reference/file-based-agents/instructions) | The instructions file |
|
|
90
|
+
| Instructions | [`instructions.ts`](https://mastra.ai/reference/file-based-agents/instructions) | [`instructions.md`](https://mastra.ai/reference/file-based-agents/instructions) | `instructions.ts` |
|
|
91
|
+
| Tools | `config.tools` | [`tools/`](https://mastra.ai/reference/file-based-agents/tools) | Both merge; `config.tools` wins on key collisions |
|
|
92
|
+
| Tools | Function `config.tools` | [`tools/`](https://mastra.ai/reference/file-based-agents/tools) | Function `config.tools`; discovered tools are ignored |
|
|
93
|
+
| Skills | `config.skills` | [`skills/`](https://mastra.ai/reference/file-based-agents/skills) | Both merge; `config.skills` wins on name collisions |
|
|
94
|
+
| Skills | Function `config.skills` | [`skills/`](https://mastra.ai/reference/file-based-agents/skills) | Function `config.skills`; discovered skills are ignored |
|
|
95
|
+
| Memory | `config.memory` | [`memory.ts`](https://mastra.ai/reference/file-based-agents/memory) | `config.memory` |
|
|
96
|
+
| Workspace | `config.workspace` | [`workspace.ts`](https://mastra.ai/reference/file-based-agents/workspace) | `config.workspace` |
|
|
97
|
+
|
|
98
|
+
Missing `instructions.md`, `instructions.ts`, and `config.instructions` fails the build. Missing both `config.memory` and `memory.ts` leaves the agent without memory.
|
|
98
99
|
|
|
99
100
|
## Discovery lifecycle
|
|
100
101
|
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
# Instructions
|
|
4
4
|
|
|
5
|
-
An agent's
|
|
5
|
+
An agent's instructions hold its always-on system prompt: the model reads it on every turn. Use them to define the agent's identity, tone, role, and standing rules.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Write them in one of two files at the agent root. Use `instructions.md` when the prompt is fixed text. Use `instructions.ts` when the prompt needs code, for example when it's built from shared constants or resolved per request.
|
|
8
|
+
|
|
9
|
+
Instructions are always in context, so keep them for stable behavior that applies to every request. Move anything conditional, large, or action-oriented into [`tools/`](https://mastra.ai/reference/file-based-agents/tools) or [`skills/`](https://mastra.ai/reference/file-based-agents/skills), which the model uses only when relevant.
|
|
8
10
|
|
|
9
11
|
## Quickstart
|
|
10
12
|
|
|
@@ -25,30 +27,53 @@ Effective instructions cover the parts of an agent's behavior that don't change
|
|
|
25
27
|
|
|
26
28
|
Move conditional, large, or action-oriented guidance into [`tools/`](https://mastra.ai/reference/file-based-agents/tools) or [`skills/`](https://mastra.ai/reference/file-based-agents/skills), which the model uses only when relevant.
|
|
27
29
|
|
|
28
|
-
##
|
|
30
|
+
## Instructions in TypeScript
|
|
31
|
+
|
|
32
|
+
Use `instructions.ts` when markdown can't express the prompt. The file default-exports a string, a system message, or a function returning one, and `agentInstructions()` types the export without changing it.
|
|
33
|
+
|
|
34
|
+
Export a string when the prompt is assembled in code, for example from constants shared with the rest of your app:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { agentInstructions } from '@mastra/core/agent'
|
|
38
|
+
import { SUPPORTED_UNITS } from '../../constants'
|
|
39
|
+
|
|
40
|
+
export default agentInstructions(`
|
|
41
|
+
You are a helpful weather assistant.
|
|
42
|
+
Report conditions using one of these units: ${SUPPORTED_UNITS.join(', ')}.
|
|
43
|
+
`)
|
|
44
|
+
```
|
|
29
45
|
|
|
30
|
-
|
|
46
|
+
Export a function when the prompt depends on the request. Mastra calls it on every turn and passes the request context:
|
|
31
47
|
|
|
32
48
|
```typescript
|
|
33
|
-
import {
|
|
34
|
-
|
|
35
|
-
export default
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const tier = runtimeContext.get('tier') ?? 'standard'
|
|
39
|
-
return `You are a support agent. Treat this as a ${tier}-tier customer.`
|
|
40
|
-
},
|
|
49
|
+
import { agentInstructions } from '@mastra/core/agent'
|
|
50
|
+
|
|
51
|
+
export default agentInstructions(({ requestContext }) => {
|
|
52
|
+
const tier = requestContext.get('tier') ?? 'standard'
|
|
53
|
+
return `You are a support agent. Treat this as a ${tier}-tier customer.`
|
|
41
54
|
})
|
|
42
55
|
```
|
|
43
56
|
|
|
57
|
+
The function can be `async` and receives `mastra` alongside `requestContext`, so it can read from storage or another registered primitive before returning the prompt.
|
|
58
|
+
|
|
59
|
+
Both files can also live in a [subagent](https://mastra.ai/reference/file-based-agents/subagents) directory, which follows the same rules.
|
|
60
|
+
|
|
44
61
|
## Build-time behavior
|
|
45
62
|
|
|
46
|
-
|
|
63
|
+
`instructions.md` and `instructions.ts` reach the deployed agent differently:
|
|
64
|
+
|
|
65
|
+
- `instructions.md`: Mastra reads the file and inlines its contents into the generated code at build time.
|
|
66
|
+
- `instructions.ts`: The generated code imports the module, so it's bundled like any other TypeScript file and can import from the rest of your project.
|
|
67
|
+
|
|
68
|
+
Under `mastra dev`, editing either file triggers a rebuild. In a deployed app neither file is read from disk at runtime, so changes take effect after the next build.
|
|
47
69
|
|
|
48
70
|
## Precedence with config
|
|
49
71
|
|
|
50
|
-
Instructions can come from `instructions.md
|
|
72
|
+
Instructions can come from `instructions.ts`, `instructions.md`, or the `instructions` field in [`config.ts`](https://mastra.ai/reference/file-based-agents/config):
|
|
73
|
+
|
|
74
|
+
- A runtime-defined (function) `instructions` in `config.ts` wins over both files.
|
|
75
|
+
- Otherwise `instructions.ts` wins over `instructions.md`.
|
|
76
|
+
- `instructions.md` wins over a static `instructions` string in `config.ts`.
|
|
77
|
+
- If none is present, the build fails and names the agent directory.
|
|
51
78
|
|
|
52
|
-
|
|
53
|
-
- Otherwise `instructions.md` wins over a static `instructions` string.
|
|
54
|
-
- If neither is present, the build fails and names the agent directory.
|
|
79
|
+
Defining instructions in more than one place logs a warning that names both sources and which one wins. Keep one source per agent.
|
package/.docs/reference/index.md
CHANGED
|
@@ -302,6 +302,7 @@ The Reference section provides documentation of Mastra's API, including paramete
|
|
|
302
302
|
- [Overview](https://mastra.ai/reference/templates/overview)
|
|
303
303
|
- [askUserTool](https://mastra.ai/reference/tools/ask-user-tool)
|
|
304
304
|
- [Bright Data Tools](https://mastra.ai/reference/tools/brightdata)
|
|
305
|
+
- [createBedrockKBTool()](https://mastra.ai/reference/tools/bedrock-kb-tool)
|
|
305
306
|
- [createCodeMode()](https://mastra.ai/reference/tools/create-code-mode)
|
|
306
307
|
- [createDocumentChunkerTool()](https://mastra.ai/reference/tools/document-chunker-tool)
|
|
307
308
|
- [createGraphRAGTool()](https://mastra.ai/reference/tools/graph-rag-tool)
|
|
@@ -64,17 +64,19 @@ The detailed breakdown metrics (everything except `total_input` and `total_outpu
|
|
|
64
64
|
|
|
65
65
|
### When cost context is attached
|
|
66
66
|
|
|
67
|
-
Cost context is attached to token metrics when the embedded pricing registry has a matching entry for the provider and model. Mastra
|
|
67
|
+
Cost context is attached to token metrics when the provider reports a valid cost for every completed model step or when the embedded pricing registry has a matching entry for the provider and model. Mastra sums the per-step provider costs into one query total. If any completed step lacks a valid reported cost, Mastra uses the pricing registry instead of reporting a partial total. If neither source is available, token metrics are still emitted without cost fields.
|
|
68
|
+
|
|
69
|
+
A caller-supplied `costContext` takes precedence over provider-reported costs and pricing registry estimates. Provider-reported totals use `costMetadata.source: 'provider_reported'`, `costMetadata.scope: 'query_total'`, and `costMetadata.reportedStepCount` to identify the source, scope, and number of completed steps included in the total.
|
|
68
70
|
|
|
69
71
|
### What cost fields may be included
|
|
70
72
|
|
|
71
|
-
| Field | Description
|
|
72
|
-
| --------------- |
|
|
73
|
-
| `provider` | Provider name (e.g. `openai`, `anthropic`)
|
|
74
|
-
| `model` | Model identifier (e.g. `gpt-4o`, `claude-sonnet-4-20250514`)
|
|
75
|
-
| `estimatedCost` | Estimated cost
|
|
76
|
-
| `costUnit` | Currency unit (e.g. `USD`)
|
|
77
|
-
| `costMetadata` | Additional pricing context
|
|
73
|
+
| Field | Description |
|
|
74
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
75
|
+
| `provider` | Provider name (e.g. `openai`, `anthropic`) |
|
|
76
|
+
| `model` | Model identifier (e.g. `gpt-4o`, `claude-sonnet-4-20250514`) |
|
|
77
|
+
| `estimatedCost` | Estimated cost from token count and pricing tier, or a total reported by the provider |
|
|
78
|
+
| `costUnit` | Currency unit (e.g. `USD`) |
|
|
79
|
+
| `costMetadata` | Additional pricing context, including tier information, error details, and provider-reported cost source and scope |
|
|
78
80
|
|
|
79
81
|
## Correlation with traces
|
|
80
82
|
|
|
@@ -171,17 +171,31 @@ The route returns:
|
|
|
171
171
|
|
|
172
172
|
## Workflows
|
|
173
173
|
|
|
174
|
-
| Method | Path | Description
|
|
175
|
-
| ------ | ----------------------------------------- |
|
|
176
|
-
| `GET` | `/api/workflows` | List all workflows
|
|
177
|
-
| `GET` | `/api/workflows
|
|
178
|
-
| `
|
|
179
|
-
| `POST` | `/api/workflows/:workflowId/
|
|
180
|
-
| `POST` | `/api/workflows/:workflowId/
|
|
181
|
-
| `POST` | `/api/workflows/:workflowId/
|
|
182
|
-
| `POST` | `/api/workflows/:workflowId/resume
|
|
183
|
-
| `
|
|
184
|
-
| `GET` | `/api/workflows/:workflowId/runs
|
|
174
|
+
| Method | Path | Description |
|
|
175
|
+
| ------ | ----------------------------------------- | ----------------------------------------------------- |
|
|
176
|
+
| `GET` | `/api/workflows` | List all workflows |
|
|
177
|
+
| `GET` | `/api/workflows/run-counts` | Get per-workflow counts of running and suspended runs |
|
|
178
|
+
| `GET` | `/api/workflows/:workflowId` | Get workflow by ID |
|
|
179
|
+
| `POST` | `/api/workflows/:workflowId/create-run` | Create a new workflow run |
|
|
180
|
+
| `POST` | `/api/workflows/:workflowId/start-async` | Start workflow and await result |
|
|
181
|
+
| `POST` | `/api/workflows/:workflowId/stream` | Stream workflow execution |
|
|
182
|
+
| `POST` | `/api/workflows/:workflowId/resume` | Resume suspended workflow |
|
|
183
|
+
| `POST` | `/api/workflows/:workflowId/resume-async` | Resume asynchronously |
|
|
184
|
+
| `GET` | `/api/workflows/:workflowId/runs` | List workflow runs |
|
|
185
|
+
| `GET` | `/api/workflows/:workflowId/runs/:runId` | Get specific run |
|
|
186
|
+
|
|
187
|
+
### Run counts response
|
|
188
|
+
|
|
189
|
+
The `/api/workflows/run-counts` endpoint returns counts of `running` and [`suspended`](https://mastra.ai/docs/workflows/suspend-and-resume) runs for every registered workflow. The record is keyed by the workflow's registry key from the Mastra config, and the server may cache the response for a few seconds:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
{
|
|
193
|
+
[workflowRegistryKey: string]: {
|
|
194
|
+
running: number;
|
|
195
|
+
suspended: number;
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
```
|
|
185
199
|
|
|
186
200
|
### Stored workflows
|
|
187
201
|
|
|
@@ -251,6 +251,64 @@ const memoryStore = await storage.getStore('memory')
|
|
|
251
251
|
const thread = await memoryStore?.getThreadById({ threadId: '...' })
|
|
252
252
|
```
|
|
253
253
|
|
|
254
|
+
## Closing connections
|
|
255
|
+
|
|
256
|
+
`close()` releases the connections of the stores a composite was built from: the `default` and `editor` stores, plus any domain that owns its own client. Each store is closed once, even when it backs several domains. When passed to the Mastra class, `close()` is called by `shutdown()`:
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
import { MastraCompositeStore } from '@mastra/core/storage'
|
|
260
|
+
import { PostgresStore } from '@mastra/pg'
|
|
261
|
+
import { Mastra } from '@mastra/core'
|
|
262
|
+
|
|
263
|
+
const pgStore = new PostgresStore({
|
|
264
|
+
id: 'pg-storage',
|
|
265
|
+
connectionString: process.env.DATABASE_URL,
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
export const mastra = new Mastra({
|
|
269
|
+
storage: new MastraCompositeStore({ id: 'composite', default: pgStore }),
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
process.on('SIGTERM', async () => {
|
|
273
|
+
// Releases the Postgres pool, so the process can exit
|
|
274
|
+
await mastra.shutdown()
|
|
275
|
+
})
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
A store you construct only to supply a domain isn't reachable through the composite. Keep a reference to it and close it yourself:
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
import { MastraCompositeStore } from '@mastra/core/storage'
|
|
282
|
+
import { ClickhouseStore } from '@mastra/clickhouse'
|
|
283
|
+
import { PostgresStore } from '@mastra/pg'
|
|
284
|
+
import { Mastra } from '@mastra/core'
|
|
285
|
+
|
|
286
|
+
const pgStore = new PostgresStore({
|
|
287
|
+
id: 'pg-storage',
|
|
288
|
+
connectionString: process.env.DATABASE_URL,
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
const clickhouseStore = new ClickhouseStore({
|
|
292
|
+
id: 'clickhouse-storage',
|
|
293
|
+
url: process.env.CLICKHOUSE_URL,
|
|
294
|
+
username: process.env.CLICKHOUSE_USERNAME,
|
|
295
|
+
password: process.env.CLICKHOUSE_PASSWORD,
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
export const mastra = new Mastra({
|
|
299
|
+
storage: new MastraCompositeStore({
|
|
300
|
+
id: 'composite',
|
|
301
|
+
default: pgStore,
|
|
302
|
+
domains: { observability: clickhouseStore.stores?.observability },
|
|
303
|
+
}),
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
process.on('SIGTERM', async () => {
|
|
307
|
+
await mastra.shutdown()
|
|
308
|
+
await clickhouseStore.close()
|
|
309
|
+
})
|
|
310
|
+
```
|
|
311
|
+
|
|
254
312
|
## Use cases
|
|
255
313
|
|
|
256
314
|
### Separate databases for different workloads
|