@mastra/mcp-docs-server 1.2.15-alpha.1 → 1.2.15-alpha.6

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 (56) 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/subagents.md +23 -5
  5. package/.docs/docs/connections/overview.md +94 -0
  6. package/.docs/docs/datasets/running-experiments.md +18 -0
  7. package/.docs/docs/evals/overview.md +16 -4
  8. package/.docs/docs/harness/agent-controller.md +6 -0
  9. package/.docs/docs/harness/overview.md +26 -0
  10. package/.docs/docs/index.md +1 -1
  11. package/.docs/docs/mcp/overview.md +10 -0
  12. package/.docs/docs/observability/feedback.md +16 -0
  13. package/.docs/guides/build-your-ui/ai-sdk-ui.md +25 -14
  14. package/.docs/guides/getting-started/quickstart.md +1 -1
  15. package/.docs/models/gateways/neon.md +15 -9
  16. package/.docs/models/gateways/netlify.md +1 -2
  17. package/.docs/models/gateways/openrouter.md +3 -2
  18. package/.docs/models/gateways/vercel.md +10 -3
  19. package/.docs/models/index.md +1 -1
  20. package/.docs/models/providers/cortecs.md +2 -1
  21. package/.docs/models/providers/deepinfra.md +6 -3
  22. package/.docs/models/providers/digitalocean.md +4 -3
  23. package/.docs/models/providers/empiriolabs.md +6 -4
  24. package/.docs/models/providers/friendli.md +8 -9
  25. package/.docs/models/providers/huggingface.md +4 -1
  26. package/.docs/models/providers/hyper.md +5 -6
  27. package/.docs/models/providers/kilo.md +9 -7
  28. package/.docs/models/providers/llmgateway.md +3 -3
  29. package/.docs/models/providers/meta.md +7 -5
  30. package/.docs/models/providers/nano-gpt.md +7 -4
  31. package/.docs/models/providers/neuralwatt.md +2 -1
  32. package/.docs/models/providers/ofox.md +74 -16
  33. package/.docs/models/providers/opencode-go.md +1 -1
  34. package/.docs/models/providers/opencode.md +2 -3
  35. package/.docs/models/providers/upstage.md +3 -2
  36. package/.docs/models/providers/vivgrid.md +4 -2
  37. package/.docs/models/providers/wandb.md +1 -1
  38. package/.docs/reference/agents/channels.md +20 -1
  39. package/.docs/reference/agents/generate.md +1 -1
  40. package/.docs/reference/ai-sdk/chat-route.md +2 -0
  41. package/.docs/reference/client-js/observability.md +22 -0
  42. package/.docs/reference/client-js/workflows.md +13 -0
  43. package/.docs/reference/file-based-agents/config.md +22 -21
  44. package/.docs/reference/file-based-agents/instructions.md +42 -17
  45. package/.docs/reference/index.md +1 -0
  46. package/.docs/reference/observability/metrics/automatic-metrics.md +10 -8
  47. package/.docs/reference/server/routes.md +25 -11
  48. package/.docs/reference/storage/composite.md +58 -0
  49. package/.docs/reference/streaming/agents/stream.md +1 -1
  50. package/.docs/reference/tools/bedrock-kb-tool.md +117 -0
  51. package/.docs/reference/tools/mcp-client.md +54 -0
  52. package/.docs/reference/voice/google.md +19 -3
  53. package/.docs/reference/workflows/step.md +40 -0
  54. package/.docs/reference/workspace/workspace-class.md +2 -0
  55. package/CHANGELOG.md +23 -0
  56. package/package.json +7 -7
@@ -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
 
@@ -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.
@@ -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`.
@@ -393,16 +393,17 @@ Use Custom UI when you want to:
393
393
 
394
394
  Mastra streams data to the frontend as "parts" within messages. Each part has a `type` that determines how to render it. The `@mastra/ai-sdk` package transforms Mastra streams into AI SDK-compatible [UI Message DataParts](https://ai-sdk.dev/docs/reference/ai-sdk-core/ui-message#datauipart).
395
395
 
396
- | Data Part Type | Source | Description |
397
- | -------------------- | ----------------------- | ---------------------------------------------------------------------------------- |
398
- | `tool-{toolKey}` | AI SDK built-in | Tool invocation with states: `input-available`, `output-available`, `output-error` |
399
- | `data-workflow` | `workflowRoute()` | Workflow execution state snapshots with step status and final outputs |
400
- | `data-workflow-step` | `workflowRoute()` | Workflow step delta with the full payload for the changed step |
401
- | `data-network` | `networkRoute()` | Agent network execution with ordered steps and outputs |
402
- | `data-tool-agent` | Nested agent in tool | Agent output streamed from within a tool's `execute()` |
403
- | `data-tool-workflow` | Nested workflow in tool | Workflow output streamed from within a tool's `execute()` |
404
- | `data-tool-network` | Nested network in tool | Network output streamed from within a tool's `execute()` |
405
- | `data-{custom}` | `writer.custom()` | Custom events for progress indicators, status updates, etc. |
396
+ | Data Part Type | Source | Description |
397
+ | ---------------------- | ----------------------- | ---------------------------------------------------------------------------------- |
398
+ | `tool-{toolKey}` | AI SDK built-in | Tool invocation with states: `input-available`, `output-available`, `output-error` |
399
+ | `data-workflow` | `workflowRoute()` | Workflow execution state snapshots with step status and final outputs |
400
+ | `data-workflow-step` | `workflowRoute()` | Workflow step delta with the full payload for the changed step |
401
+ | `data-network` | `networkRoute()` | Agent network execution with ordered steps and outputs |
402
+ | `data-tool-agent` | Nested agent in tool | Compact nested-agent snapshot while the current step is still running |
403
+ | `data-tool-agent-step` | Nested agent in tool | Full nested-agent step payload emitted when a nested step finishes |
404
+ | `data-tool-workflow` | Nested workflow in tool | Workflow output streamed from within a tool's `execute()` |
405
+ | `data-tool-network` | Nested network in tool | Network output streamed from within a tool's `execute()` |
406
+ | `data-{custom}` | `writer.custom()` | Custom events for progress indicators, status updates, etc. |
406
407
 
407
408
  ### Rendering tool outputs
408
409
 
@@ -1256,7 +1257,7 @@ For a complete implementation, see the [workflow-suspend-resume example](https:/
1256
1257
 
1257
1258
  ### Nested agent streams in tools
1258
1259
 
1259
- Tools can call agents internally and stream the agent's output back to the UI. This creates `data-tool-agent` parts that can be rendered alongside the tool's final output.
1260
+ Tools can call agents internally and stream the agent's output back to the UI. This creates compact `data-tool-agent` snapshots while the nested step is still running, `data-tool-agent-step` parts when a nested step finishes, and one full `data-tool-agent` snapshot when the nested run finishes.
1260
1261
 
1261
1262
  The pattern uses:
1262
1263
 
@@ -1315,13 +1316,13 @@ export const forecastAgent = new Agent({
1315
1316
 
1316
1317
  **Frontend**:
1317
1318
 
1318
- Handle `data-tool-agent` parts to display the nested agent's streamed output.
1319
+ Handle `data-tool-agent` parts for the live snapshot and `data-tool-agent-step` parts for the completed nested step payload.
1319
1320
 
1320
1321
  ```typescript
1321
1322
  import { useChat } from '@ai-sdk/react'
1322
1323
  import { DefaultChatTransport } from 'ai'
1323
1324
  import { useState } from 'react'
1324
- import type { AgentDataPart } from '@mastra/ai-sdk'
1325
+ import type { AgentDataPart, AgentStepDataPart } from '@mastra/ai-sdk'
1325
1326
 
1326
1327
  export function NestedAgentChat() {
1327
1328
  const [input, setInput] = useState('')
@@ -1361,6 +1362,15 @@ export function NestedAgentChat() {
1361
1362
  </div>
1362
1363
  )
1363
1364
  }
1365
+ if (part.type === 'data-tool-agent-step') {
1366
+ const { data } = part as AgentStepDataPart
1367
+ return (
1368
+ <div key={index} className="nested-agent-step">
1369
+ <strong>Completed nested step {data.stepIndex + 1}</strong>
1370
+ {data.step.text && <p>{data.step.text}</p>}
1371
+ </div>
1372
+ )
1373
+ }
1364
1374
  return null
1365
1375
  })}
1366
1376
  </div>
@@ -1373,7 +1383,8 @@ export function NestedAgentChat() {
1373
1383
  Key points:
1374
1384
 
1375
1385
  - Piping `fullStream` to `context.writer` creates `data-tool-agent` parts
1376
- - The `AgentDataPart` has `id` (on the part) and `data.text` (the agent's streamed text)
1386
+ - Read `data-tool-agent-step` when you need the full payload for the nested step that just finished
1387
+ - The `AgentDataPart` has `id` (on the part) and `data.text` (the current nested-agent text snapshot)
1377
1388
  - The tool still returns its own output after the stream completes
1378
1389
 
1379
1390
  For a complete implementation, see the [tool-nested-streams example](https://github.com/mastra-ai/ui-dojo/blob/main/src/pages/ai-sdk/tool-nested-streams.tsx) in UI Dojo.
@@ -27,7 +27,7 @@ npm create mastra@latest
27
27
  **pnpm**:
28
28
 
29
29
  ```bash
30
- pnpm create mastra
30
+ pnpm create mastra@latest
31
31
  ```
32
32
 
33
33
  **Yarn**:
@@ -2,7 +2,7 @@
2
2
 
3
3
  # ![Neon logo](https://models.dev/logos/neon.svg)Neon
4
4
 
5
- Neon aggregates models from multiple providers with enhanced features like rate limiting and failover. Access 36 models through Mastra's model router.
5
+ Neon aggregates models from multiple providers with enhanced features like rate limiting and failover. Access 42 models through Mastra's model router.
6
6
 
7
7
  Learn more in the [Neon documentation](https://neon.com/docs).
8
8
 
@@ -15,7 +15,7 @@ const agent = new Agent({
15
15
  id: "my-agent",
16
16
  name: "My Agent",
17
17
  instructions: "You are a helpful assistant",
18
- model: "neon/claude-haiku-4-5"
18
+ model: "neon/claude-fable-5"
19
19
  });
20
20
  ```
21
21
 
@@ -33,37 +33,43 @@ NEON_AI_GATEWAY_TOKEN=your-gateway-key
33
33
 
34
34
  | Model |
35
35
  | ----------------------------- |
36
+ | `claude-fable-5` |
36
37
  | `claude-haiku-4-5` |
37
38
  | `claude-opus-4-1` |
38
39
  | `claude-opus-4-5` |
39
40
  | `claude-opus-4-6` |
40
41
  | `claude-opus-4-7` |
41
42
  | `claude-opus-4-8` |
42
- | `claude-sonnet-4` |
43
+ | `claude-opus-5` |
43
44
  | `claude-sonnet-4-5` |
44
45
  | `claude-sonnet-4-6` |
45
- | `gemini-2-5-flash` |
46
- | `gemini-2-5-pro` |
46
+ | `claude-sonnet-5` |
47
47
  | `gemini-3-1-flash-lite` |
48
48
  | `gemini-3-1-pro` |
49
49
  | `gemini-3-5-flash` |
50
+ | `gemini-3-5-flash-lite` |
51
+ | `gemini-3-6-flash` |
50
52
  | `gemini-3-flash` |
51
- | `gemini-3-pro` |
52
53
  | `gemma-3-12b` |
54
+ | `glm-5-2` |
53
55
  | `gpt-5` |
54
56
  | `gpt-5-1` |
55
- | `gpt-5-1-codex-max` |
56
- | `gpt-5-1-codex-mini` |
57
57
  | `gpt-5-2` |
58
- | `gpt-5-2-codex` |
59
58
  | `gpt-5-3-codex` |
60
59
  | `gpt-5-4` |
61
60
  | `gpt-5-4-mini` |
62
61
  | `gpt-5-4-nano` |
62
+ | `gpt-5-5` |
63
+ | `gpt-5-5-pro` |
64
+ | `gpt-5-6-luna` |
65
+ | `gpt-5-6-sol` |
66
+ | `gpt-5-6-terra` |
63
67
  | `gpt-5-mini` |
64
68
  | `gpt-5-nano` |
65
69
  | `gpt-oss-120b` |
66
70
  | `gpt-oss-20b` |
71
+ | `inkling` |
72
+ | `kimi-k3` |
67
73
  | `llama-4-maverick` |
68
74
  | `meta-llama-3-1-8b-instruct` |
69
75
  | `meta-llama-3-3-70b-instruct` |
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Netlify
4
4
 
5
- Netlify AI Gateway provides unified access to multiple providers with built-in caching and observability. Access 67 models through Mastra's model router.
5
+ Netlify AI Gateway provides unified access to multiple providers with built-in caching and observability. Access 66 models through Mastra's model router.
6
6
 
7
7
  Learn more in the [Netlify documentation](https://docs.netlify.com/build/ai-gateway/overview/).
8
8
 
@@ -84,7 +84,6 @@ ANTHROPIC_API_KEY=ant-...
84
84
  | `openai/gpt-5.2-2025-12-11` |
85
85
  | `openai/gpt-5.2-pro` |
86
86
  | `openai/gpt-5.2-pro-2025-12-11` |
87
- | `openai/gpt-5.3-chat-latest` |
88
87
  | `openai/gpt-5.3-codex` |
89
88
  | `openai/gpt-5.4` |
90
89
  | `openai/gpt-5.4-2026-03-05` |