@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.
- package/.docs/docs/agents/a2a.md +75 -2
- package/.docs/docs/agents/processors.md +2 -0
- package/.docs/docs/agents/skills.md +15 -1
- package/.docs/docs/capabilities/channels/overview.md +19 -0
- package/.docs/docs/capabilities/subagents.md +23 -5
- package/.docs/docs/connections/overview.md +94 -0
- package/.docs/docs/datasets/running-experiments.md +18 -0
- package/.docs/docs/evals/overview.md +16 -4
- package/.docs/docs/harness/agent-controller.md +6 -0
- package/.docs/docs/harness/overview.md +26 -0
- package/.docs/docs/index.md +1 -1
- package/.docs/docs/mcp/overview.md +10 -0
- package/.docs/docs/memory/multi-user-threads.md +1 -1
- package/.docs/docs/memory/observational-memory.md +1 -1
- package/.docs/docs/memory/semantic-recall.md +2 -1
- package/.docs/docs/memory/working-memory.md +1 -0
- package/.docs/docs/observability/feedback.md +16 -0
- package/.docs/docs/observability/integrations/exporters/mastra-storage.md +1 -0
- package/.docs/docs/server/auth.md +2 -0
- package/.docs/docs/server/mastra-client.md +11 -11
- package/.docs/docs/storage/overview.md +1 -0
- package/.docs/docs/workflows/agents-and-tools.md +2 -2
- package/.docs/docs/workflows/{stored-workflows.md → dynamic-workflows.md} +23 -23
- package/.docs/docs/workflows/snapshots.md +3 -1
- package/.docs/guides/build-your-ui/ai-sdk-ui.md +25 -14
- package/.docs/guides/getting-started/quickstart.md +1 -1
- package/.docs/guides/rag/overview.md +1 -1
- package/.docs/guides/rag/retrieval.md +17 -0
- package/.docs/guides/rag/vector-databases.md +41 -0
- package/.docs/guides/voice/realtime-voice.md +28 -2
- package/.docs/models/gateways/neon.md +20 -14
- package/.docs/models/gateways/netlify.md +1 -2
- package/.docs/models/gateways/openrouter.md +4 -2
- package/.docs/models/gateways/vercel.md +10 -3
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/anthropic.md +2 -2
- package/.docs/models/providers/cortecs.md +2 -1
- package/.docs/models/providers/deepinfra.md +6 -3
- package/.docs/models/providers/digitalocean.md +6 -5
- package/.docs/models/providers/empiriolabs.md +6 -4
- package/.docs/models/providers/friendli.md +8 -9
- package/.docs/models/providers/huggingface.md +4 -1
- package/.docs/models/providers/hyper.md +5 -6
- package/.docs/models/providers/kilo.md +11 -9
- package/.docs/models/providers/llmgateway.md +3 -3
- package/.docs/models/providers/meta.md +7 -5
- package/.docs/models/providers/minimax.md +25 -23
- package/.docs/models/providers/nano-gpt.md +7 -4
- package/.docs/models/providers/neuralwatt.md +2 -1
- package/.docs/models/providers/ofox.md +74 -16
- package/.docs/models/providers/openai.md +28 -26
- package/.docs/models/providers/opencode-go.md +1 -1
- package/.docs/models/providers/opencode.md +2 -3
- package/.docs/models/providers/perplexity-agent.md +24 -24
- package/.docs/models/providers/pioneer.md +27 -1
- package/.docs/models/providers/regolo-ai.md +25 -20
- package/.docs/models/providers/upstage.md +3 -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/agents/generate.md +1 -1
- package/.docs/reference/ai-sdk/chat-route.md +2 -0
- package/.docs/reference/browser/agent-browser.md +1 -1
- package/.docs/reference/browser/mastra-browser.md +1 -1
- package/.docs/reference/browser/stagehand-browser.md +1 -1
- package/.docs/reference/channels/slack-provider.md +2 -0
- package/.docs/reference/client-js/observability.md +22 -0
- package/.docs/reference/client-js/workflows.md +32 -19
- package/.docs/reference/configuration.md +26 -1
- package/.docs/reference/core/{addStoredWorkflow.md → addDynamicWorkflow.md} +10 -10
- package/.docs/reference/core/{addStoredWorkflows.md → addDynamicWorkflows.md} +9 -9
- package/.docs/reference/editor/tool-provider.md +26 -1
- package/.docs/reference/file-based-agents/config.md +22 -21
- package/.docs/reference/file-based-agents/instructions.md +42 -17
- package/.docs/reference/file-based-agents/schedules.md +232 -0
- package/.docs/reference/index.md +7 -3
- package/.docs/reference/observability/metrics/automatic-metrics.md +10 -8
- package/.docs/reference/rag/metadata-filters.md +13 -4
- package/.docs/reference/server/register-api-route.md +2 -0
- package/.docs/reference/server/routes.md +38 -24
- package/.docs/reference/storage/composite.md +58 -0
- package/.docs/reference/storage/oracledb.md +239 -0
- package/.docs/reference/storage/overview.md +9 -9
- package/.docs/reference/storage/retention.md +1 -1
- package/.docs/reference/streaming/agents/stream.md +1 -1
- package/.docs/reference/tools/bedrock-kb-tool.md +117 -0
- package/.docs/reference/tools/mcp-client.md +54 -0
- package/.docs/reference/vectors/oracledb.md +347 -0
- package/.docs/reference/voice/google.md +19 -3
- package/.docs/reference/workflows/{stored-workflow-definition.md → dynamic-workflow-definition.md} +7 -7
- package/.docs/reference/workflows/step.md +40 -0
- package/.docs/reference/workflows/workflow-methods/agent.md +3 -3
- package/.docs/reference/workflows/workflow-methods/tool.md +3 -3
- package/.docs/reference/workspace/daytona-sandbox.md +21 -0
- package/.docs/reference/workspace/workspace-class.md +2 -0
- package/CHANGELOG.md +51 -0
- package/package.json +6 -6
package/.docs/docs/agents/a2a.md
CHANGED
|
@@ -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`,
|
|
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
|
|
108
|
-
|
|
|
109
|
-
| `primitiveId`
|
|
110
|
-
| `prompt`
|
|
111
|
-
| `iteration`
|
|
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. |
|
package/.docs/docs/index.md
CHANGED
|
@@ -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/
|
|
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/
|
|
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
|
|
72
|
+
## Create and run dynamic workflows
|
|
73
73
|
|
|
74
|
-
Use `
|
|
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 {
|
|
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
|
|
108
|
+
} satisfies UpsertDynamicWorkflowParams
|
|
109
109
|
|
|
110
|
-
await client.
|
|
110
|
+
await client.upsertDynamicWorkflow(definition)
|
|
111
111
|
|
|
112
|
-
const
|
|
113
|
-
const
|
|
112
|
+
const dynamicWorkflow = client.getDynamicWorkflow(definition.id)
|
|
113
|
+
const dynamicDefinition = await dynamicWorkflow.details()
|
|
114
114
|
|
|
115
|
-
const workflow = client.getWorkflow(
|
|
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
|
|
121
|
+
await dynamicWorkflow.delete()
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
Use `
|
|
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
|
|
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 [
|
|
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 [
|
|
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
|
|