@mastra/mcp-docs-server 1.2.14 → 1.2.15-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/.docs/docs/agents/a2a.md +75 -2
  2. package/.docs/docs/agents/processors.md +2 -0
  3. package/.docs/docs/agents/skills.md +15 -1
  4. package/.docs/docs/capabilities/channels/overview.md +19 -0
  5. package/.docs/docs/capabilities/subagents.md +23 -5
  6. package/.docs/docs/connections/overview.md +94 -0
  7. package/.docs/docs/datasets/running-experiments.md +18 -0
  8. package/.docs/docs/evals/overview.md +16 -4
  9. package/.docs/docs/harness/agent-controller.md +6 -0
  10. package/.docs/docs/harness/overview.md +26 -0
  11. package/.docs/docs/index.md +1 -1
  12. package/.docs/docs/mcp/overview.md +10 -0
  13. package/.docs/docs/memory/multi-user-threads.md +1 -1
  14. package/.docs/docs/memory/observational-memory.md +1 -1
  15. package/.docs/docs/memory/semantic-recall.md +2 -1
  16. package/.docs/docs/memory/working-memory.md +1 -0
  17. package/.docs/docs/observability/feedback.md +16 -0
  18. package/.docs/docs/observability/integrations/exporters/mastra-storage.md +1 -0
  19. package/.docs/docs/server/auth.md +2 -0
  20. package/.docs/docs/server/mastra-client.md +11 -11
  21. package/.docs/docs/storage/overview.md +1 -0
  22. package/.docs/docs/workflows/agents-and-tools.md +2 -2
  23. package/.docs/docs/workflows/{stored-workflows.md → dynamic-workflows.md} +23 -23
  24. package/.docs/docs/workflows/snapshots.md +3 -1
  25. package/.docs/guides/build-your-ui/ai-sdk-ui.md +25 -14
  26. package/.docs/guides/getting-started/quickstart.md +1 -1
  27. package/.docs/guides/rag/overview.md +1 -1
  28. package/.docs/guides/rag/retrieval.md +17 -0
  29. package/.docs/guides/rag/vector-databases.md +41 -0
  30. package/.docs/guides/voice/realtime-voice.md +28 -2
  31. package/.docs/models/gateways/neon.md +20 -14
  32. package/.docs/models/gateways/netlify.md +1 -2
  33. package/.docs/models/gateways/openrouter.md +4 -2
  34. package/.docs/models/gateways/vercel.md +10 -3
  35. package/.docs/models/index.md +1 -1
  36. package/.docs/models/providers/anthropic.md +2 -2
  37. package/.docs/models/providers/cortecs.md +2 -1
  38. package/.docs/models/providers/deepinfra.md +6 -3
  39. package/.docs/models/providers/digitalocean.md +6 -5
  40. package/.docs/models/providers/empiriolabs.md +6 -4
  41. package/.docs/models/providers/friendli.md +8 -9
  42. package/.docs/models/providers/huggingface.md +4 -1
  43. package/.docs/models/providers/hyper.md +5 -6
  44. package/.docs/models/providers/kilo.md +11 -9
  45. package/.docs/models/providers/llmgateway.md +3 -3
  46. package/.docs/models/providers/meta.md +7 -5
  47. package/.docs/models/providers/minimax.md +25 -23
  48. package/.docs/models/providers/nano-gpt.md +7 -4
  49. package/.docs/models/providers/neuralwatt.md +2 -1
  50. package/.docs/models/providers/ofox.md +74 -16
  51. package/.docs/models/providers/openai.md +28 -26
  52. package/.docs/models/providers/opencode-go.md +1 -1
  53. package/.docs/models/providers/opencode.md +2 -3
  54. package/.docs/models/providers/perplexity-agent.md +24 -24
  55. package/.docs/models/providers/pioneer.md +27 -1
  56. package/.docs/models/providers/regolo-ai.md +25 -20
  57. package/.docs/models/providers/upstage.md +3 -2
  58. package/.docs/models/providers/vivgrid.md +4 -2
  59. package/.docs/models/providers/wandb.md +1 -1
  60. package/.docs/reference/agents/channels.md +22 -1
  61. package/.docs/reference/agents/generate.md +1 -1
  62. package/.docs/reference/ai-sdk/chat-route.md +2 -0
  63. package/.docs/reference/browser/agent-browser.md +1 -1
  64. package/.docs/reference/browser/mastra-browser.md +1 -1
  65. package/.docs/reference/browser/stagehand-browser.md +1 -1
  66. package/.docs/reference/channels/slack-provider.md +2 -0
  67. package/.docs/reference/client-js/observability.md +22 -0
  68. package/.docs/reference/client-js/workflows.md +32 -19
  69. package/.docs/reference/configuration.md +26 -1
  70. package/.docs/reference/core/{addStoredWorkflow.md → addDynamicWorkflow.md} +10 -10
  71. package/.docs/reference/core/{addStoredWorkflows.md → addDynamicWorkflows.md} +9 -9
  72. package/.docs/reference/editor/tool-provider.md +26 -1
  73. package/.docs/reference/file-based-agents/config.md +22 -21
  74. package/.docs/reference/file-based-agents/instructions.md +42 -17
  75. package/.docs/reference/file-based-agents/schedules.md +232 -0
  76. package/.docs/reference/index.md +7 -3
  77. package/.docs/reference/observability/metrics/automatic-metrics.md +10 -8
  78. package/.docs/reference/rag/metadata-filters.md +13 -4
  79. package/.docs/reference/server/register-api-route.md +2 -0
  80. package/.docs/reference/server/routes.md +38 -24
  81. package/.docs/reference/storage/composite.md +58 -0
  82. package/.docs/reference/storage/oracledb.md +239 -0
  83. package/.docs/reference/storage/overview.md +9 -9
  84. package/.docs/reference/storage/retention.md +1 -1
  85. package/.docs/reference/streaming/agents/stream.md +1 -1
  86. package/.docs/reference/tools/bedrock-kb-tool.md +117 -0
  87. package/.docs/reference/tools/mcp-client.md +54 -0
  88. package/.docs/reference/vectors/oracledb.md +347 -0
  89. package/.docs/reference/voice/google.md +19 -3
  90. package/.docs/reference/workflows/{stored-workflow-definition.md → dynamic-workflow-definition.md} +7 -7
  91. package/.docs/reference/workflows/step.md +40 -0
  92. package/.docs/reference/workflows/workflow-methods/agent.md +3 -3
  93. package/.docs/reference/workflows/workflow-methods/tool.md +3 -3
  94. package/.docs/reference/workspace/daytona-sandbox.md +21 -0
  95. package/.docs/reference/workspace/workspace-class.md +2 -0
  96. package/CHANGELOG.md +51 -0
  97. package/package.json +6 -6
@@ -2,7 +2,7 @@
2
2
 
3
3
  # A2A (Agent-to-Agent)
4
4
 
5
- Mastra supports the [Agent-to-Agent (A2A) protocol](https://a2a-protocol.org/latest/) for cross-platform multi-agent systems. Use A2A to expose Mastra agents as remote agents, consume remote A2A agents as Mastra subagents, or call A2A endpoints with the JavaScript client SDK.
5
+ Mastra supports version 0.3.0 of the [Agent-to-Agent (A2A) protocol](https://a2a-protocol.org/latest/) for cross-platform multi-agent systems. Use A2A to expose Mastra agents as remote agents, consume remote A2A agents as Mastra subagents, or call A2A endpoints with the JavaScript client SDK.
6
6
 
7
7
  A2A is an open protocol for delegating work to agents across network, framework, vendor, and language boundaries. A remote agent keeps its own tools, prompts, memory, workflows, and infrastructure private while exposing a protocol endpoint that other systems can discover and call.
8
8
 
@@ -57,6 +57,18 @@ A2A represents work as messages and tasks. Messages carry text, file, or structu
57
57
 
58
58
  Tasks are stateful units of work with IDs and lifecycle states. Clients can follow long-running work and send follow-up turns. They can also cancel work or resubscribe after a disconnect.
59
59
 
60
+ ## Protocol versions
61
+
62
+ Mastra supports A2A Protocol v0.3 and v1.0 on the same agent card and execution URLs. The `A2A-Version` request header selects the wire protocol:
63
+
64
+ - Missing, empty, or `0.3`: Uses the existing v0.3 API.
65
+ - `1.0`: Uses the v1.0 API.
66
+ - Any other value: Returns a `VersionNotSupported` protocol error.
67
+
68
+ Existing `A2AAgent` and `MastraClient.getA2A()` integrations continue to use v0.3. Use `MastraClient.getA2AV1()` for v1.0 requests. The v1 client sends `A2A-Version: 1.0` automatically and adds the `tasks/list` operation.
69
+
70
+ Import v1.0 protocol types and codecs from `@mastra/core/a2a/v1`. The existing `@mastra/core/a2a/client` export remains on v0.3.
71
+
60
72
  ## Get started
61
73
 
62
74
  A2A has two common paths in Mastra:
@@ -155,6 +167,33 @@ for await (const event of updates) {
155
167
  }
156
168
  ```
157
169
 
170
+ ### Use the v1.0 client
171
+
172
+ Use `getA2AV1()` to opt into the A2A v1.0 wire protocol. The protocol package provides codecs for creating v1 request values from JSON-shaped input:
173
+
174
+ ```typescript
175
+ import { ListTasksRequest } from '@mastra/core/a2a/v1'
176
+ import { MastraClient } from '@mastra/client-js'
177
+
178
+ const client = new MastraClient({
179
+ baseUrl: 'https://agent.example.com',
180
+ })
181
+
182
+ const a2a = client.getA2AV1('weather-agent')
183
+ const response = await a2a.listTasks(
184
+ ListTasksRequest.fromJSON({
185
+ contextId: 'customer-support',
186
+ pageSize: 20,
187
+ }),
188
+ )
189
+
190
+ for (const task of response.tasks) {
191
+ console.log(task.id, task.status)
192
+ }
193
+ ```
194
+
195
+ The v1.0 client supports `getAgentCard()`, `sendMessage()`, `sendMessageStream()`, `getTask()`, `listTasks()`, `cancelTask()`, and `resubscribeTask()`.
196
+
158
197
  ## Configure subagent calls
159
198
 
160
199
  `A2AAgent` accepts request options for authenticated or constrained environments:
@@ -176,6 +215,38 @@ const remoteWeatherAgent = new A2AAgent({
176
215
 
177
216
  You can also pass `credentials`, `fetch`, and `abortSignal` when the runtime needs custom fetch behavior or request cancellation.
178
217
 
218
+ ## Human-in-the-loop
219
+
220
+ A2A models human-in-the-loop (HITL) work with the `input-required` task state. When a task pauses for input, the client provides the missing input by sending a follow-up message with the same `taskId`, and the server continues the task.
221
+
222
+ Mastra maps its agent suspension model to this state in both directions:
223
+
224
+ - **As a server**: when an exposed agent suspends, the task transitions to `input-required`. This includes suspensions caused by [tool approval](https://mastra.ai/docs/agents/agent-approval) or a tool that calls `suspend()`. The task status message includes a text prompt and a data part with the structured `suspendPayload` and `resumeSchema`. A follow-up `message/send` or `message/stream` request with the same `taskId` resumes the suspended run with the provided input.
225
+ - **As a client**: when a remote task reaches `input-required` or `auth-required`, `A2AAgent` returns a suspended result with `finishReason: 'suspended'` and a `suspendPayload`. Calling `resumeGenerate()` or `resumeStream()` sends the input or credentials back to the remote task with the original `taskId`.
226
+
227
+ ```typescript
228
+ import { A2AAgent } from '@mastra/core/a2a'
229
+
230
+ const agent = new A2AAgent({
231
+ url: 'https://agent.example.com/api/.well-known/booking-agent/agent-card.json',
232
+ })
233
+
234
+ const result = await agent.generate('Book a flight to Paris', { runId: 'run-1' })
235
+
236
+ if (result.finishReason === 'suspended') {
237
+ // Inspect result.suspendPayload, collect input from a human,
238
+ // then resume the remote task.
239
+ const resumed = await agent.resumeGenerate({ approved: true }, { runId: 'run-1' })
240
+ console.log(resumed.text)
241
+ }
242
+ ```
243
+
244
+ Follow-up messages for an `input-required` task can carry the resume data as a structured data part, or as JSON or plain text in a text part.
245
+
246
+ When a resumed run requires additional input, the task returns to `input-required` and the flow repeats. Resuming a suspended run requires storage configured on the Mastra server so the suspended run state can be restored across requests.
247
+
248
+ > **Note:** A2A task records live in an in-memory store, so a paused task can only be resumed by the same server process that suspended it. A server restart or a horizontally scaled deployment without sticky routing loses the task record, and a follow-up message fails with a task-not-found error.
249
+
179
250
  ## Push notifications
180
251
 
181
252
  Mastra supports A2A push notifications for remote agents that advertise `capabilities.pushNotifications`. Use push notifications when a client can't keep a stream open, or when a long-running task should update a callback URL after the original request ends.
@@ -192,7 +263,9 @@ await a2a.setTaskPushNotificationConfig({
192
263
  })
193
264
  ```
194
265
 
195
- Mastra Server sends the current task snapshot to registered callbacks when the task reaches `completed`, `failed`, `canceled`, or `input-required`. Push notification delivery is best-effort. Protect callback URLs, validate notification tokens, and avoid exposing internal network targets as push notification destinations.
266
+ Mastra Server sends the current task snapshot to registered callbacks when the task reaches `completed`, `failed`, `canceled`, `rejected`, `input-required`, or `auth-required`. Push notification delivery is best-effort. Protect callback URLs, validate notification tokens, and avoid exposing internal network targets as push notification destinations.
267
+
268
+ Push notification configurations are stored in memory and must be registered again after a server restart.
196
269
 
197
270
  ## Sign and verify agent cards
198
271
 
@@ -544,6 +544,8 @@ This means the cache key is derived from the resolved `LanguageModelV2Prompt` Ma
544
544
 
545
545
  When you don't supply `key`, the processor derives one deterministically from the inputs that change the LLM's response at this step: `agentId`, `stepNumber` (so each step in a tool loop has its own cache entry), `scope`, model identity (`provider`, `modelId`, spec version), and the resolved `prompt` (post-memory + post-processors). Any change to these inputs automatically invalidates the cache.
546
546
 
547
+ Multimodal prompts are included too. Image and file parts reach the key by value: a URL contributes its full href, and inline binary data (`Uint8Array`, `ArrayBuffer`) contributes a digest of its bytes. Two requests that differ only in which image they reference therefore get different cache entries.
548
+
547
549
  #### Customize the cache key
548
550
 
549
551
  Pass `key` as a function on the constructor or per-call to derive your own cache key from any subset of those inputs. The function receives the same inputs the deterministic hash would have consumed and returns a string (or a `Promise<string>`):
@@ -123,7 +123,21 @@ export const agent = new Agent({
123
123
  })
124
124
  ```
125
125
 
126
- The resolver function receives `{ requestContext }` and returns a `SkillInput[]` array or a `Promise<SkillInput[]>`.
126
+ The resolver function receives `{ requestContext, tracingContext }` and returns a `SkillInput[]` array or a `Promise<SkillInput[]>`.
127
+
128
+ The resolver runs once per `RequestContext`. During an agent execution it runs inside a `resolve-skills` span, and `tracingContext.currentSpan` lets you create child spans for your own work, the same way tools do. The resolver also runs on metadata reads such as `agent.listSkills()` and the server's agent endpoints, where no span exists and `tracingContext.currentSpan` is `undefined`, so keep it fast and guard any span usage:
129
+
130
+ ```typescript
131
+ skills: async ({ requestContext, tracingContext }) => {
132
+ const span = tracingContext?.currentSpan?.createChildSpan({
133
+ type: 'generic',
134
+ name: 'entitlements-lookup',
135
+ })
136
+ const skills = await fetchSkillsFor(requestContext.get('userId'))
137
+ span?.end()
138
+ return skills
139
+ }
140
+ ```
127
141
 
128
142
  See [Request Context](https://mastra.ai/docs/server/request-context) for more on using request context with agents and workflows.
129
143
 
@@ -153,6 +153,25 @@ When the agent calls this tool, users see a card with the tool name, arguments,
153
153
 
154
154
  Set `toolDisplay: 'text'` on an adapter to render tool calls as plain text instead of interactive cards. In `'hidden'` mode, `autoResumeSuspendedTools` can resume suspended tools when a later user message arrives on the same thread. This requires memory. Hidden mode only suppresses the approval buttons.
155
155
 
156
+ ## Reply formatting
157
+
158
+ Agent replies post as markdown by default. Platforms with native markdown rendering, such as Slack, render bold text, links, and tables directly. Other platforms convert the markdown to their own format. Agents write standard markdown and it renders correctly everywhere, matching how the same reply renders in Studio.
159
+
160
+ Set `textFormat: 'plain'` on an adapter to post replies as literal plain text instead:
161
+
162
+ ```typescript
163
+ channels: {
164
+ adapters: {
165
+ slack: {
166
+ adapter: createSlackAdapter(),
167
+ textFormat: 'plain',
168
+ },
169
+ },
170
+ },
171
+ ```
172
+
173
+ Use this escape hatch if your agent is prompted to emit a platform-specific dialect, such as Slack mrkdwn, instead of standard markdown. If you added such prompt instructions to work around markdown rendering literally, remove them instead. The default now renders standard markdown natively. `textFormat` affects final reply text only. Tool cards, error messages, and natively streamed text are unaffected.
174
+
156
175
  ## Multi-user awareness
157
176
 
158
177
  In group conversations, Mastra prefixes each message with the sender's name and platform ID so the agent can distinguish between speakers:
@@ -104,11 +104,29 @@ const stream = await parentAgent.stream('Research AI trends', {
104
104
 
105
105
  The `context` object includes:
106
106
 
107
- | Property | Description |
108
- | ------------- | ----------------------------------------- |
109
- | `primitiveId` | The ID of the subagent being delegated to |
110
- | `prompt` | The prompt the parent agent is sending |
111
- | `iteration` | Current iteration number |
107
+ | Property | Description |
108
+ | ---------------- | ------------------------------------------------- |
109
+ | `primitiveId` | The ID of the subagent being delegated to |
110
+ | `prompt` | The prompt the parent agent is sending |
111
+ | `iteration` | Current iteration number |
112
+ | `requestContext` | The request context the subagent run will receive |
113
+
114
+ ### Request context at the delegation boundary
115
+
116
+ Each delegation receives a request context whose entries are shallowly copied from the parent run, excluding run-scoped identity keys. Setting or deleting entries during the subagent run does not affect the parent's context. Set entries on `context.requestContext` in `onDelegationStart` to pass values to the delegated run:
117
+
118
+ ```typescript
119
+ const stream = await parentAgent.stream('Research AI trends', {
120
+ maxSteps: 10,
121
+ delegation: {
122
+ onDelegationStart: async context => {
123
+ context.requestContext.set('audience', 'technical')
124
+ },
125
+ },
126
+ })
127
+ ```
128
+
129
+ The subagent reads these entries in its tools and dynamic configuration, such as `instructions: ({ requestContext }) => ...`. See [Request Context](https://mastra.ai/docs/server/request-context) for details. Values must be JSON-serializable to work with durable agents.
112
130
 
113
131
  ### `onDelegationComplete`
114
132
 
@@ -0,0 +1,94 @@
1
+ > Discover all available pages from the documentation index: https://mastra.ai/llms.txt
2
+
3
+ # Connections overview
4
+
5
+ Connections let Mastra work with remote agents, coding agents, provider software development kit (SDK) runtimes, and external tools and resources. Choose a connection type based on which system owns the agent runtime and what you need to exchange.
6
+
7
+ - [**Agent-to-Agent (A2A)**](https://mastra.ai/docs/agents/a2a): Expose or consume remote agents across service, framework, vendor, and language boundaries.
8
+ - [**Agent Client Protocol (ACP)**](https://mastra.ai/docs/agents/acp): Run compatible coding-agent processes as Mastra tools or subagents.
9
+ - [**SDK agents**](https://mastra.ai/docs/agents/sdk-agents): Register Claude, Cursor, or OpenAI SDK-backed agents while the provider SDK retains control of the runtime, tools, permissions, and agent loop.
10
+ - [**Model Context Protocol (MCP)**](https://mastra.ai/docs/mcp/overview): Connect agents to external tools and resources, or expose Mastra agents, tools, workflows, prompts, and resources to MCP-compatible systems.
11
+
12
+ ## When to use connections
13
+
14
+ Use connections when you need to:
15
+
16
+ - Delegate work to an agent running in another service or runtime.
17
+ - Run a coding agent against a project workspace.
18
+ - Add a provider-native agent without replacing its SDK runtime or agent loop.
19
+ - Connect agents to external tools and resources or publish Mastra capabilities to other systems.
20
+
21
+ ## Get started
22
+
23
+ Start with the boundary you need to cross. Use [A2A](https://mastra.ai/docs/agents/a2a) for remote agent endpoints, [ACP](https://mastra.ai/docs/agents/acp) for coding-agent processes, [SDK agents](https://mastra.ai/docs/agents/sdk-agents) for provider-owned runtimes, or [MCP](https://mastra.ai/docs/mcp/overview) for tools and resources.
24
+
25
+ **A2A**:
26
+
27
+ ```typescript
28
+ import { A2AAgent } from '@mastra/core/a2a'
29
+
30
+ const agent = new A2AAgent({
31
+ url: 'https://agent.example.com/.well-known/agent-card.json',
32
+ })
33
+
34
+ const result = await agent.generate('Summarize the latest report')
35
+ console.log(result.text)
36
+ ```
37
+
38
+ **ACP**:
39
+
40
+ ```typescript
41
+ import { AcpAgent } from '@mastra/acp'
42
+
43
+ const agent = new AcpAgent({
44
+ id: 'coding-agent',
45
+ description: 'Inspects and edits code',
46
+ command: 'claude',
47
+ args: ['--acp'],
48
+ persistSession: false,
49
+ })
50
+
51
+ const result = await agent.generate('Review this project')
52
+ console.log(result.text)
53
+ ```
54
+
55
+ **SDK agents**:
56
+
57
+ ```typescript
58
+ import { OpenAISDKAgent } from '@mastra/openai'
59
+
60
+ const agent = new OpenAISDKAgent({
61
+ id: 'openai-agent',
62
+ description: 'Answers project questions',
63
+ sdkOptions: {
64
+ name: 'Project assistant',
65
+ model: 'gpt-5',
66
+ },
67
+ })
68
+
69
+ const result = await agent.generate('Explain agent loops in one sentence')
70
+ console.log(result.text)
71
+ ```
72
+
73
+ **MCP**:
74
+
75
+ ```typescript
76
+ import { MCPClient } from '@mastra/mcp'
77
+
78
+ const client = new MCPClient({
79
+ id: 'wikipedia-client',
80
+ servers: {
81
+ wikipedia: {
82
+ command: 'npx',
83
+ args: ['-y', 'wikipedia-mcp'],
84
+ },
85
+ },
86
+ })
87
+
88
+ try {
89
+ const tools = await client.listTools()
90
+ console.log(Object.keys(tools))
91
+ } finally {
92
+ await client.disconnect()
93
+ }
94
+ ```
@@ -58,6 +58,24 @@ const summary = await dataset.startExperiment({
58
58
 
59
59
  Each item's `input` is passed directly to `agent.generate()`, so it must be a `string`, `string[]`, or `CoreMessage[]`.
60
60
 
61
+ #### Memory-enabled agents
62
+
63
+ When the target agent has its own memory and the request context carries a resource id (`MASTRA_RESOURCE_ID_KEY`, set by auth middleware, the experiment or item `requestContext`, or the Studio **Run Experiment** form), the experiment runner injects a fresh memory thread for each item. A resource id in the request context means "run as this resource": each item's conversation persists as a thread under that resource, and retried items get a new thread per attempt so earlier failed attempts can't leak into the retry's context.
64
+
65
+ Injected threads are tagged so you can map them back to the run: thread metadata carries the `experimentId` and the dataset item's id as `experimentItemId`. No thread title is generated for them.
66
+
67
+ Because the threads belong to the caller's resource, resource-scoped memory features both read and write that resource's state during the run:
68
+
69
+ - Resource-scoped working memory updates persist to the resource, and later items in the run see updates made by earlier items.
70
+ - Resource-scoped semantic recall can surface the resource's prior conversations to the experiment, and experiment transcripts become recallable in that resource's later conversations.
71
+
72
+ This is useful when you want to evaluate an agent against a real user's accumulated context. If you don't want experiment runs touching real user state, run the experiment with a dedicated evaluation resource id instead.
73
+
74
+ Thread injection is skipped in the following cases:
75
+
76
+ - If the request context also sets `MASTRA_THREAD_ID_KEY`, the runner uses that thread as-is, so every item (and retry) shares the same conversation.
77
+ - If the agent has no memory, or the request context has no resource id, the run is memoryless and nothing is persisted.
78
+
61
79
  ### Registered workflow
62
80
 
63
81
  Point to a workflow registered on your Mastra instance:
@@ -75,7 +75,7 @@ export const evaluatedAgent = new Agent({
75
75
 
76
76
  ### Adding scorers to workflow steps
77
77
 
78
- You can also add scorers to individual workflow steps to evaluate outputs at specific points in your process:
78
+ You can also add scorers to individual workflow steps to evaluate outputs at specific points in your process. Each scorer receives that step's own input and output, so you can measure quality at each step instead of only scoring the final answer:
79
79
 
80
80
  ```typescript
81
81
  import { createWorkflow, createStep } from "@mastra/core/workflows";
@@ -83,22 +83,34 @@ import { z } from "zod";
83
83
  import { customStepScorer } from "../scorers/custom-step-scorer";
84
84
 
85
85
  const contentStep = createStep({
86
+ id: "content-step",
87
+ inputSchema: z.object({ topic: z.string() }),
88
+ outputSchema: z.object({ content: z.string() }),
86
89
  scorers: {
87
90
  customStepScorer: {
88
91
  scorer: customStepScorer(),
89
92
  sampling: {
90
93
  type: "ratio",
91
94
  rate: 1, // Score every step execution
92
- }
93
- }
95
+ },
96
+ },
97
+ },
98
+ execute: async ({ inputData }) => {
99
+ return { content: await generateContent(inputData.topic) };
94
100
  },
95
101
  });
96
102
 
97
- export const contentWorkflow = createWorkflow({ ... })
103
+ export const contentWorkflow = createWorkflow({
104
+ id: "content-workflow",
105
+ inputSchema: z.object({ topic: z.string() }),
106
+ outputSchema: z.object({ content: z.string() }),
107
+ })
98
108
  .then(contentStep)
99
109
  .commit();
100
110
  ```
101
111
 
112
+ For the step-level `scorers` API, see the [Step class reference](https://mastra.ai/reference/workflows/step).
113
+
102
114
  ### How live evaluations work
103
115
 
104
116
  **Asynchronous execution**: Live evaluations run in the background without blocking your agent responses or workflow execution. This ensures your AI systems maintain their performance while still being monitored.
@@ -322,6 +322,10 @@ const controller = new AgentController({
322
322
  if (thread.isDM) return message.author.userId
323
323
  return defaultResourceId
324
324
  },
325
+ onSessionStart: async ({ session, thread }) => {
326
+ const plan = await billing.planFor(thread.resourceId)
327
+ await session.model.switch({ modelId: plan.modelId })
328
+ },
325
329
  },
326
330
  })
327
331
 
@@ -339,6 +343,8 @@ Point each platform webhook at the controller-specific route:
339
343
 
340
344
  Each external chat thread maps to one controller Session and Mastra thread. By default, new sessions use a resource ID derived from the adapter's chat-thread ID, prefixed with `channel:`. Use `resolveResourceId` to map direct messages to an existing application user or choose another memory owner. The callback only affects new threads; an existing thread keeps its stored resource ID.
341
345
 
346
+ Channel sessions are created by the controller rather than by your code, so `onSessionStart` is where you configure them. It runs once per session, after the session is bound to its mapped thread and before the first message is handled. Use it to apply a model, memory settings, or session state that a channel session would otherwise miss. Later messages in the same thread reuse the session and don't call it again. Errors are logged and swallowed so a session that can't be configured still answers the message.
347
+
342
348
  Controller channel sessions and auto-approval state are held in memory, so use a long-lived server. Pending approvals and live Session state don't survive process restarts. Adapters that can't render approval controls automatically run tools without an approval prompt so the run doesn't remain suspended.
343
349
 
344
350
  See [Channels](https://mastra.ai/docs/capabilities/channels/overview) for adapter setup and platform-specific webhook configuration.
@@ -0,0 +1,26 @@
1
+ > Discover all available pages from the documentation index: https://mastra.ai/llms.txt
2
+
3
+ # Harness overview
4
+
5
+ A harness lets an agent pursue long-running, complex goals while keeping its work durable, visible, and steerable. It preserves progress across retries and interruptions, while giving people and other systems a way to inspect progress, add context, approve actions, redirect the agent, or stop it.
6
+
7
+ In Mastra, harness refers to a set of capabilities for managing an agent beyond a single uninterrupted run. You can adopt these capabilities individually or combine them as needed.
8
+
9
+ [`AgentController`](https://mastra.ai/docs/harness/agent-controller) is a harness designed for interactive agent applications. It extends the base [`Agent`](https://mastra.ai/docs/agents/overview) loop with isolated sessions for each user or task, persistent threads and state, switchable modes and models, tool permissions and approvals, subagent orchestration, and streams for events and display state.
10
+
11
+ Agent harnesses are useful wherever work continues over time. Common examples include coding agents that carry changes through CI and review, software factories that coordinate many tasks in parallel, SRE agents that adapt as incidents evolve, and go-to-market agents that respond as accounts, signals, and conversations change.
12
+
13
+ ## When to use a harness
14
+
15
+ Choose a starting point based on what the agent needs. You may use one capability or several.
16
+
17
+ | If you want to | Start here | Why |
18
+ | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
19
+ | Keep a run available through client disconnects or server restarts | [Durable Agents](https://mastra.ai/docs/long-running-agents/durable-agents) | Persist run state and let clients reconnect to its stream. |
20
+ | Run slow tools, workflows, or subagents without blocking | [Background Tasks](https://mastra.ai/docs/long-running-agents/background-tasks) | Finish work asynchronously and return its result to the agent. |
21
+ | Keep an agent working until it reaches an objective | [Goals](https://mastra.ai/docs/long-running-agents/goals) | Evaluate a thread-scoped objective until it's complete or reaches its run budget. |
22
+ | Start work automatically at recurring times | [Schedules](https://mastra.ai/docs/long-running-agents/schedules) | Start isolated runs or send prompts into an existing thread on a cron schedule. |
23
+ | Add context, redirect active work, or wake an idle thread | [Signals](https://mastra.ai/docs/long-running-agents/signals) | Deliver input now or hold it for the next turn. |
24
+ | React to changes in GitHub, Slack, continuous integration, or another external system | [Signal Providers](https://mastra.ai/docs/long-running-agents/signal-providers) | Track subscriptions and forward matching events to agent threads. |
25
+ | Build an interactive product with sessions, modes, state, approvals, and events | [AgentController](https://mastra.ai/docs/harness/agent-controller) | Host isolated sessions around a shared agent runtime. |
26
+ | Let users steer, queue follow-up work, or stop an interactive run | [AgentController](https://mastra.ai/docs/harness/agent-controller) | Expose run controls through each session. |
@@ -132,7 +132,7 @@ npm create mastra@latest
132
132
  **pnpm**:
133
133
 
134
134
  ```bash
135
- pnpm create mastra
135
+ pnpm create mastra@latest
136
136
  ```
137
137
 
138
138
  **Yarn**:
@@ -142,6 +142,16 @@ requireToolApproval: ({ toolName }) => toolName.startsWith('delete_')
142
142
 
143
143
  Treat tool annotations from servers you don't control as untrusted hints. Visit [tool approval](https://mastra.ai/reference/tools/mcp-client) for the callback context and security guidance.
144
144
 
145
+ ### Security
146
+
147
+ MCP servers run code and return content on your agent's behalf, so configure them with the same care as any other external dependency:
148
+
149
+ - **Stdio subprocess environment**: subprocesses inherit only the MCP SDK's curated environment whitelist (for example `PATH` and `HOME` on POSIX), not the full parent environment. Set `inheritDefaultEnv: false` on a server to pass only the variables you list in `env`.
150
+ - **Outbound host restriction**: when HTTP server URLs come from untrusted configuration, set `allowedHosts` to restrict which hosts the client will contact. On the default fetch path this also blocks redirect hops before they're sent; a custom `fetch` gets its final response URL validated after the request runs, so it must enforce redirect policy itself when preventing outbound contact is required.
151
+ - **Tool response trust**: tool results are untrusted model input. Use [input and output processors](https://mastra.ai/docs/agents/processors) to inspect or sanitize content before it reaches the model, and `requireToolApproval` to gate sensitive tools.
152
+
153
+ Visit the [MCPClient security reference](https://mastra.ai/reference/tools/mcp-client) for enforcement details of each option.
154
+
145
155
  ### MCP registries
146
156
 
147
157
  Registries provide hosted or packaged MCP servers. The client configuration above works with registry endpoints and commands.
@@ -156,7 +156,7 @@ const memory = new Memory({
156
156
  })
157
157
  ```
158
158
 
159
- OM requires a storage adapter that supports it: `@mastra/libsql`, `@mastra/pg`, or `@mastra/mongodb`.
159
+ OM requires a storage adapter that supports it: `@mastra/libsql`, `@mastra/pg`, `@mastra/mongodb`, or `@mastra/oracledb`.
160
160
 
161
161
  > **Note:** If you switch the Observer to a weaker model and see facts collapse to a generic `User`, use [`observation.instruction`](https://mastra.ai/reference/memory/observational-memory) to teach the Observer how to read the `<turn>` tag.
162
162
 
@@ -94,7 +94,7 @@ See [configuration options](https://mastra.ai/reference/memory/observational-mem
94
94
  >
95
95
  > For an AI SDK example, see [Using Mastra Memory](https://mastra.ai/guides/build-your-ui/ai-sdk-ui).
96
96
 
97
- > **Note:** OM currently only supports `@mastra/pg`, `@mastra/libsql`, `@mastra/mysql`, `@mastra/mongodb`, and `@mastra/convex` storage adapters. It uses background agents for managing memory. When no model is set, the default model is `google/gemini-2.5-flash`.
97
+ > **Note:** OM currently only supports `@mastra/pg`, `@mastra/libsql`, `@mastra/mysql`, `@mastra/mongodb`, `@mastra/convex`, and `@mastra/oracledb` storage adapters. It uses background agents for managing memory. When no model is set, the default model is `google/gemini-2.5-flash`.
98
98
 
99
99
  ## Temporal gap markers
100
100
 
@@ -148,6 +148,7 @@ Each vector store page below includes installation instructions, configuration p
148
148
  - [libSQL](https://mastra.ai/reference/vectors/libsql)
149
149
  - [MongoDB](https://mastra.ai/reference/vectors/mongodb)
150
150
  - [OpenSearch](https://mastra.ai/reference/vectors/opensearch)
151
+ - [OracleDB](https://mastra.ai/reference/vectors/oracledb)
151
152
  - [Pinecone](https://mastra.ai/reference/vectors/pinecone)
152
153
  - [PostgreSQL](https://mastra.ai/reference/vectors/pg)
153
154
  - [Qdrant](https://mastra.ai/reference/vectors/qdrant)
@@ -180,7 +181,7 @@ const agent = new Agent({
180
181
  })
181
182
  ```
182
183
 
183
- > **Note:** `scope: 'resource'` is supported by the LibSQL, PostgreSQL, MongoDB, and Upstash storage adapters.
184
+ > **Note:** `scope: 'resource'` is supported by the LibSQL, OracleDB, PostgreSQL, MongoDB, and Upstash storage adapters.
184
185
 
185
186
  ### Metadata filtering
186
187
 
@@ -129,6 +129,7 @@ Resource-scoped working memory requires specific storage adapters that support t
129
129
 
130
130
  - **libSQL** (`@mastra/libsql`)
131
131
  - **PostgreSQL** (`@mastra/pg`)
132
+ - **OracleDB** (`@mastra/oracledb`)
132
133
  - **Upstash** (`@mastra/upstash`)
133
134
  - **MongoDB** (`@mastra/mongodb`)
134
135
 
@@ -33,6 +33,22 @@ await mastra.observability.addFeedback({
33
33
  })
34
34
  ```
35
35
 
36
+ ## Find the trace for a message
37
+
38
+ Feedback is usually collected against a message a user has already read, so you need the `traceId` for that message. Assistant messages carry it in `content.metadata`, both in the stream result and when the message is recalled later from memory:
39
+
40
+ ```typescript
41
+ const agent = mastra.getAgent('weatherAgent')
42
+ const memory = await agent.getMemory()
43
+
44
+ const { messages } = await memory!.recall({ threadId, perPage: false })
45
+
46
+ const message = messages.find(m => m.id === messageId)
47
+ const traceId = message?.content.metadata?.traceId
48
+ ```
49
+
50
+ The value is the same trace the run reports as `traceId` on its result, so feedback collected at generation time and feedback collected later against a stored message anchor to the same trace. Messages produced while tracing is disabled have no `traceId`.
51
+
36
52
  ## Create feedback
37
53
 
38
54
  Every `createFeedback()` requires `feedbackType` and `value`. Add `traceId` or `spanId` when the feedback should be anchored to a trace or a specific span. Use `feedbackSource` as optional string metadata, such as `user`, `qa`, `studio`, or `system`.
@@ -122,6 +122,7 @@ If you set the strategy to `'auto'`, the `MastraStorageExporter` automatically s
122
122
  | **[PostgreSQL](https://mastra.ai/reference/storage/postgresql)** | batch-with-updates | batch-with-updates, insert-only | Production (low volume) |
123
123
  | **[MSSQL](https://mastra.ai/reference/storage/mssql)** | batch-with-updates | batch-with-updates, insert-only | Production (low volume) |
124
124
  | **[MongoDB](https://mastra.ai/reference/storage/mongodb)** | batch-with-updates | batch-with-updates, insert-only | Production (low volume) |
125
+ | **[OracleDB](https://mastra.ai/reference/storage/oracledb)** | batch-with-updates | batch-with-updates, insert-only | Production (low volume) |
125
126
  | **[libSQL](https://mastra.ai/reference/storage/libsql)** | batch-with-updates | batch-with-updates, insert-only | Default storage, good for development |
126
127
 
127
128
  ### Providers without Observability Support
@@ -17,6 +17,8 @@ Authentication is optional. If no auth is configured, all routes and Studio are
17
17
 
18
18
  See [Custom API Routes](https://mastra.ai/docs/server/custom-api-routes) for controlling authentication on custom endpoints. Visit the [Studio Auth docs](https://mastra.ai/docs/studio/auth) for more on securing your Studio deployment.
19
19
 
20
+ > **Warning:** The default auth configuration protects `/api/*` and treats `/api`, `/api/auth/*` as public. When you set a custom `server.apiPrefix`, those defaults no longer match and built-in routes fall outside the protected pattern. Update `server.auth.protected` and `server.auth.public` to reference your new prefix.
21
+
20
22
  > **Note:** Authentication for Studio is currently supported by the following providers: Simple Auth, JWT, WorkOS, Better Auth, and Google.
21
23
 
22
24
  ## Available providers
@@ -69,15 +69,15 @@ The Mastra Client SDK exposes all resources served by the Mastra Server.
69
69
  - **[Logs](https://mastra.ai/reference/client-js/logs)**: View logs and debug system behavior.
70
70
  - **[Telemetry](https://mastra.ai/reference/client-js/telemetry)**: View app performance and trace activity.
71
71
 
72
- ## Create and run stored workflows
72
+ ## Create and run dynamic workflows
73
73
 
74
- Use `upsertStoredWorkflow()` to create or replace a persisted workflow definition. A successful upsert validates the complete definition, registers it with the running Mastra instance, and makes it available through the standard workflow execution API.
74
+ Use `upsertDynamicWorkflow()` to create or replace a persisted workflow definition. A successful upsert validates the complete definition, registers it with the running Mastra instance, and makes it available through the standard workflow execution API.
75
75
 
76
76
  The following example shows the full lifecycle of a mapping workflow, from creation and inspection through execution and deletion:
77
77
 
78
78
  ```typescript
79
79
  import { MastraClient } from '@mastra/client-js'
80
- import type { UpsertStoredWorkflowParams } from '@mastra/client-js'
80
+ import type { UpsertDynamicWorkflowParams } from '@mastra/client-js'
81
81
 
82
82
  const client = new MastraClient({
83
83
  baseUrl: process.env.MASTRA_API_URL || 'http://localhost:4111',
@@ -105,25 +105,25 @@ const definition = {
105
105
  }),
106
106
  },
107
107
  ],
108
- } satisfies UpsertStoredWorkflowParams
108
+ } satisfies UpsertDynamicWorkflowParams
109
109
 
110
- await client.upsertStoredWorkflow(definition)
110
+ await client.upsertDynamicWorkflow(definition)
111
111
 
112
- const storedWorkflow = client.getStoredWorkflow(definition.id)
113
- const storedDefinition = await storedWorkflow.details()
112
+ const dynamicWorkflow = client.getDynamicWorkflow(definition.id)
113
+ const dynamicDefinition = await dynamicWorkflow.details()
114
114
 
115
- const workflow = client.getWorkflow(storedDefinition.id)
115
+ const workflow = client.getWorkflow(dynamicDefinition.id)
116
116
  const run = await workflow.createRun()
117
117
  const result = await run.startAsync({ inputData: { name: 'Ada' } })
118
118
 
119
119
  console.log(result)
120
120
 
121
- await storedWorkflow.delete()
121
+ await dynamicWorkflow.delete()
122
122
  ```
123
123
 
124
- Use `listStoredWorkflows()` to list persisted definitions. Calling `upsertStoredWorkflow()` again with the same `id` replaces the stored definition and live workflow registration.
124
+ Use `listDynamicWorkflows()` to list persisted definitions. Calling `upsertDynamicWorkflow()` again with the same `id` replaces the stored definition and live workflow registration.
125
125
 
126
- > **Warning:** Durable storage requires a configured storage adapter that supports the `workflowDefinitions` domain. Without that domain, Core can register a workflow in memory, but the server's stored-workflow API can't preserve it across restarts.
126
+ > **Warning:** Durable storage requires a configured storage adapter that supports the `workflowDefinitions` domain. Without that domain, Core can register a workflow in memory, but the server's dynamic-workflow API can't preserve it across restarts.
127
127
  >
128
128
  > Stored definitions support declarative agent, tool, mapping, nested workflow, parallel, foreach, sleep, sleep-until, conditional, and loop entries. They can't contain JavaScript closures. Conditional and loop logic must use the declarative predicate format, and referenced agents, tools, and nested workflows must already be registered.
129
129
  >
@@ -193,6 +193,7 @@ Each provider page includes installation instructions, configuration parameters,
193
193
  - [libSQL](https://mastra.ai/reference/storage/libsql)
194
194
  - [PostgreSQL](https://mastra.ai/reference/storage/postgresql)
195
195
  - [MongoDB](https://mastra.ai/reference/storage/mongodb)
196
+ - [OracleDB](https://mastra.ai/reference/storage/oracledb)
196
197
  - [Upstash](https://mastra.ai/reference/storage/upstash)
197
198
  - [Redis](https://mastra.ai/reference/storage/redis)
198
199
  - [Cloudflare D1](https://mastra.ai/reference/storage/cloudflare-d1)
@@ -123,7 +123,7 @@ export const testWorkflow = createWorkflow({})
123
123
  .commit()
124
124
  ```
125
125
 
126
- `.agent()` records a declarative entry in the workflow graph rather than an opaque step, so workflows built this way can be persisted as [stored workflows](https://mastra.ai/docs/workflows/stored-workflows). Visit [Workflow.agent()](https://mastra.ai/reference/workflows/workflow-methods/agent) for all parameters.
126
+ `.agent()` records a declarative entry in the workflow graph rather than an opaque step, so workflows built this way can be persisted as [dynamic workflows](https://mastra.ai/docs/workflows/dynamic-workflows). Visit [Workflow.agent()](https://mastra.ai/reference/workflows/workflow-methods/agent) for all parameters.
127
127
 
128
128
  ## Using tools in workflows
129
129
 
@@ -184,7 +184,7 @@ import { testTool } from '../tools/test-tool'
184
184
  export const testWorkflow = createWorkflow({}).then(step1).tool(testTool).commit()
185
185
  ```
186
186
 
187
- Like `.agent()`, `.tool()` records a declarative entry, so the workflow can be persisted as a [stored workflow](https://mastra.ai/docs/workflows/stored-workflows). Visit [Workflow.tool()](https://mastra.ai/reference/workflows/workflow-methods/tool) for all parameters.
187
+ Like `.agent()`, `.tool()` records a declarative entry, so the workflow can be persisted as a [dynamic workflow](https://mastra.ai/docs/workflows/dynamic-workflows). Visit [Workflow.tool()](https://mastra.ai/reference/workflows/workflow-methods/tool) for all parameters.
188
188
 
189
189
  ## Related
190
190