@mastra/mcp-docs-server 1.1.35-alpha.8 → 1.1.36-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.docs/course/03-agent-memory/18-advanced-configuration-semantic-recall.md +48 -4
- package/.docs/docs/agents/background-tasks.md +62 -2
- package/.docs/docs/agents/processors.md +9 -1
- package/.docs/docs/agents/response-caching.md +148 -0
- package/.docs/docs/agents/signals.md +151 -0
- package/.docs/docs/agents/using-tools.md +8 -0
- package/.docs/docs/browser/agent-browser.md +15 -0
- package/.docs/docs/browser/stagehand.md +25 -1
- package/.docs/docs/deployment/cloud-providers.md +1 -1
- package/.docs/docs/deployment/overview.md +6 -5
- package/.docs/docs/editor/tools.md +1 -1
- package/.docs/docs/index.md +2 -2
- package/.docs/docs/mastra-platform/configuration.md +22 -6
- package/.docs/docs/mastra-platform/observability.md +99 -0
- package/.docs/docs/mastra-platform/overview.md +12 -55
- package/.docs/{guides/deployment/mastra-platform.md → docs/mastra-platform/server.md} +30 -37
- package/.docs/docs/mastra-platform/studio.md +81 -0
- package/.docs/docs/memory/observational-memory.md +61 -13
- package/.docs/docs/memory/semantic-recall.md +68 -6
- package/.docs/docs/observability/logging.md +2 -2
- package/.docs/docs/observability/metrics/overview.md +4 -4
- package/.docs/docs/observability/overview.md +15 -10
- package/.docs/docs/observability/tracing/bridges/otel.md +25 -0
- package/.docs/docs/observability/tracing/exporters/arize.md +5 -5
- package/.docs/docs/observability/tracing/exporters/braintrust.md +37 -0
- package/.docs/docs/observability/tracing/exporters/langfuse.md +21 -0
- package/.docs/docs/observability/tracing/exporters/{cloud.md → mastra-platform.md} +35 -33
- package/.docs/docs/observability/tracing/exporters/{default.md → mastra-storage.md} +56 -19
- package/.docs/docs/observability/tracing/exporters/otel.md +79 -2
- package/.docs/docs/observability/tracing/overview.md +30 -29
- package/.docs/docs/observability/tracing/processors/sensitive-data-filter.md +6 -6
- package/.docs/docs/server/mastra-server.md +30 -19
- package/.docs/docs/studio/deployment.md +1 -37
- package/.docs/docs/studio/observability.md +31 -26
- package/.docs/docs/studio/overview.md +8 -2
- package/.docs/docs/voice/overview.md +84 -0
- package/.docs/docs/workflows/suspend-and-resume.md +28 -1
- package/.docs/guides/deployment/inngest.md +23 -0
- package/.docs/guides/getting-started/quickstart.md +4 -4
- package/.docs/guides/migrations/mastra-cloud.md +12 -12
- package/.docs/guides/migrations/upgrade-to-v1/tracing.md +19 -17
- package/.docs/models/gateways/netlify.md +2 -1
- package/.docs/models/gateways/openrouter.md +4 -1
- package/.docs/models/gateways/vercel.md +2 -1
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/alibaba-cn.md +1 -1
- package/.docs/models/providers/alibaba.md +1 -1
- package/.docs/models/providers/chutes.md +23 -54
- package/.docs/models/providers/claudinio.md +71 -0
- package/.docs/models/providers/databricks.md +96 -0
- package/.docs/models/providers/deepinfra.md +3 -1
- package/.docs/models/providers/deepseek.md +3 -1
- package/.docs/models/providers/digitalocean.md +9 -2
- package/.docs/models/providers/firepass.md +71 -0
- package/.docs/models/providers/google.md +4 -3
- package/.docs/models/providers/kilo.md +6 -4
- package/.docs/models/providers/llmgateway.md +8 -2
- package/.docs/models/providers/nebius.md +37 -55
- package/.docs/models/providers/novita-ai.md +5 -5
- package/.docs/models/providers/nvidia.md +59 -49
- package/.docs/models/providers/ollama-cloud.md +1 -1
- package/.docs/models/providers/openai.md +2 -0
- package/.docs/models/providers/opencode.md +44 -43
- package/.docs/models/providers/poe.md +4 -1
- package/.docs/models/providers/sarvam.md +72 -0
- package/.docs/models/providers/wafer.ai.md +4 -5
- package/.docs/models/providers/xiaomi-token-plan-ams.md +6 -5
- package/.docs/models/providers/xiaomi-token-plan-cn.md +6 -5
- package/.docs/models/providers/xiaomi-token-plan-sgp.md +6 -5
- package/.docs/models/providers.md +4 -1
- package/.docs/reference/agents/agent.md +85 -0
- package/.docs/reference/browser/agent-browser.md +37 -11
- package/.docs/reference/browser/stagehand-browser.md +35 -9
- package/.docs/reference/cli/create-mastra.md +6 -0
- package/.docs/reference/cli/mastra.md +63 -15
- package/.docs/reference/client-js/agents.md +115 -1
- package/.docs/reference/client-js/responses.md +4 -0
- package/.docs/reference/configuration.md +6 -6
- package/.docs/reference/editor/tool-provider.md +3 -3
- package/.docs/reference/harness/harness-class.md +22 -9
- package/.docs/reference/index.md +5 -0
- package/.docs/reference/memory/observational-memory.md +11 -1
- package/.docs/reference/observability/metrics/automatic-metrics.md +2 -4
- package/.docs/reference/observability/tracing/bridges/datadog.md +2 -2
- package/.docs/reference/observability/tracing/bridges/otel.md +26 -4
- package/.docs/reference/observability/tracing/configuration.md +6 -3
- package/.docs/reference/observability/tracing/exporters/arize.md +1 -1
- package/.docs/reference/observability/tracing/exporters/braintrust.md +2 -0
- package/.docs/reference/observability/tracing/exporters/cloud-exporter.md +5 -3
- package/.docs/reference/observability/tracing/exporters/console-exporter.md +2 -2
- package/.docs/reference/observability/tracing/exporters/default-exporter.md +7 -1
- package/.docs/reference/observability/tracing/exporters/mastra-platform-exporter.md +263 -0
- package/.docs/reference/observability/tracing/exporters/mastra-storage-exporter.md +194 -0
- package/.docs/reference/observability/tracing/exporters/otel.md +12 -8
- package/.docs/reference/observability/tracing/instances.md +2 -2
- package/.docs/reference/observability/tracing/interfaces.md +37 -2
- package/.docs/reference/observability/tracing/processors/sensitive-data-filter.md +22 -0
- package/.docs/reference/observability/tracing/span-filtering.md +2 -2
- package/.docs/reference/processors/prefill-error-handler.md +3 -3
- package/.docs/reference/processors/response-cache.md +114 -0
- package/.docs/reference/processors/tool-call-filter.md +28 -0
- package/.docs/reference/storage/clickhouse.md +8 -8
- package/.docs/reference/storage/cloudflare-d1.md +1 -1
- package/.docs/reference/storage/cloudflare.md +1 -1
- package/.docs/reference/storage/composite.md +1 -1
- package/.docs/reference/storage/convex.md +1 -1
- package/.docs/reference/storage/dsql.md +428 -0
- package/.docs/reference/storage/duckdb.md +3 -3
- package/.docs/reference/storage/dynamodb.md +1 -1
- package/.docs/reference/storage/lance.md +1 -1
- package/.docs/reference/storage/libsql.md +1 -1
- package/.docs/reference/storage/postgresql.md +1 -1
- package/.docs/reference/storage/upstash.md +1 -1
- package/.docs/reference/streaming/ChunkType.md +44 -0
- package/.docs/reference/tools/brightdata.md +167 -0
- package/.docs/reference/tools/create-tool.md +46 -0
- package/.docs/reference/voice/inworld.md +133 -0
- package/.docs/reference/workflows/workflow-state-reader.md +113 -0
- package/CHANGELOG.md +113 -0
- package/package.json +6 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Advanced
|
|
1
|
+
# Advanced configuration of semantic recall
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Configure semantic recall with the `semanticRecall` option:
|
|
4
4
|
|
|
5
5
|
```typescript
|
|
6
6
|
const memory = new Memory({
|
|
@@ -19,11 +19,55 @@ const memory = new Memory({
|
|
|
19
19
|
before: 2,
|
|
20
20
|
after: 1,
|
|
21
21
|
},
|
|
22
|
+
scope: 'resource', // Search all threads for this resource
|
|
23
|
+
filter: { projectId: { $eq: 'project-a' } },
|
|
22
24
|
},
|
|
23
25
|
},
|
|
24
26
|
})
|
|
25
27
|
```
|
|
26
28
|
|
|
27
|
-
The `topK` parameter controls how many
|
|
29
|
+
The `topK` parameter controls how many similar messages Mastra retrieves. A higher value retrieves more messages, which can help with complex topics but may include less relevant information. The default value is `4`.
|
|
28
30
|
|
|
29
|
-
The `messageRange` parameter controls how much context
|
|
31
|
+
The `messageRange` parameter controls how much context Mastra includes with each match. Messages before and after the match help the agent understand the matched message.
|
|
32
|
+
|
|
33
|
+
The `scope` parameter controls whether Mastra searches the current thread (`'thread'`) or all threads owned by a resource (`'resource'`). Use `scope: 'resource'` to let the agent recall information from past conversations for the same resource.
|
|
34
|
+
|
|
35
|
+
The `filter` parameter restricts semantic recall results to messages with matching thread metadata, such as a project ID or category.
|
|
36
|
+
|
|
37
|
+
Filters match metadata stored on message embeddings when messages are saved. If thread metadata changes later, existing embeddings keep their previous metadata until those messages are saved or indexed again.
|
|
38
|
+
|
|
39
|
+
Supported filter operators:
|
|
40
|
+
|
|
41
|
+
- `$and`: Logical AND
|
|
42
|
+
- `$eq`: Equal to
|
|
43
|
+
- `$gt`: Greater than
|
|
44
|
+
- `$gte`: Greater than or equal
|
|
45
|
+
- `$in`: In array
|
|
46
|
+
- `$lt`: Less than
|
|
47
|
+
- `$lte`: Less than or equal
|
|
48
|
+
- `$ne`: Not equal to
|
|
49
|
+
- `$nin`: Not in array
|
|
50
|
+
- `$or`: Logical OR
|
|
51
|
+
|
|
52
|
+
The following example demonstrates metadata filters for common use cases:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// Filter by project
|
|
56
|
+
const options = {
|
|
57
|
+
semanticRecall: { filter: { projectId: { $eq: 'my-project' } } },
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Filter by multiple categories
|
|
61
|
+
const options = {
|
|
62
|
+
semanticRecall: { filter: { category: { $in: ['work', 'research'] } } },
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Filter by project and priority
|
|
66
|
+
const options = {
|
|
67
|
+
semanticRecall: {
|
|
68
|
+
filter: {
|
|
69
|
+
$and: [{ projectId: { $eq: 'project-a' } }, { priority: { $gte: 3 } }],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
```
|
|
@@ -127,10 +127,12 @@ When a tool call dispatches as a background task, two streams may surface lifecy
|
|
|
127
127
|
| `background-task-completed` | The task finished successfully. The `payload.result` matches the eventual tool result. | Manager stream |
|
|
128
128
|
| `background-task-failed` | The task threw or timed out. | Manager stream |
|
|
129
129
|
| `background-task-cancelled` | The task was cancelled before completing. | Manager stream |
|
|
130
|
+
| `background-task-suspended` | The tool called `suspend()` from inside its execute. | Manager stream |
|
|
131
|
+
| `background-task-resumed` | A suspended task was resumed via `manager.resume(taskId, resumeData)`. | Manager stream |
|
|
130
132
|
|
|
131
|
-
`agent.stream().fullStream` only emits the agent-loop chunks (`background-task-started`, `background-task-progress`) on its own. `agent.streamUntilIdle()` emits the same two chunks and additionally subscribes to the manager pubsub for the run's memory scope and pipes the
|
|
133
|
+
`agent.stream().fullStream` only emits the agent-loop chunks (`background-task-started`, `background-task-progress`) on its own. `agent.streamUntilIdle()` emits the same two chunks and additionally subscribes to the manager pubsub for the run's memory scope and pipes the seven manager chunks (`background-task-running`, `background-task-output`, `background-task-completed`, `background-task-failed`, `background-task-cancelled`, `background-task-suspended`, `background-task-resumed`) into the same `fullStream`.
|
|
132
134
|
|
|
133
|
-
`backgroundTaskManager.stream()` only emits the
|
|
135
|
+
`backgroundTaskManager.stream()` only emits the seven manager chunks.
|
|
134
136
|
|
|
135
137
|
The full payload shapes are documented in the [background task chunks reference](https://mastra.ai/reference/streaming/ChunkType).
|
|
136
138
|
|
|
@@ -210,6 +212,64 @@ When this `researchAgent` is delegated to from a supervisor that has no backgrou
|
|
|
210
212
|
|
|
211
213
|
Use this pattern when you want a subagent to behave consistently in the background regardless of which supervisor invokes it. Use the supervisor-side opt-in (above) when you want to tune background behavior centrally per supervisor.
|
|
212
214
|
|
|
215
|
+
## Suspending and resuming
|
|
216
|
+
|
|
217
|
+
A background task can pause itself mid-execution and wait for an external signal before continuing. This is useful for human approvals, webhooks, or any flow where the next step depends on data that arrives later.
|
|
218
|
+
|
|
219
|
+
A tool calls `suspend(data)` from inside its `execute`, which:
|
|
220
|
+
|
|
221
|
+
- Persists `status: 'suspended'` and the `data` payload on the task record.
|
|
222
|
+
- Saves the workflow snapshot so the run survives process restarts.
|
|
223
|
+
- Emits a `background-task-suspended` chunk on the manager stream.
|
|
224
|
+
- Releases the concurrency slot so other tasks can run.
|
|
225
|
+
|
|
226
|
+
Resume the task with `mastra.backgroundTaskManager.resume(taskId, resumeData)`. The `resumeData` arrives in the tool's `execute` options on the resumed run, and the task transitions back to `running`.
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { createTool } from '@mastra/core/tools'
|
|
230
|
+
import { z } from 'zod'
|
|
231
|
+
|
|
232
|
+
export const reviewTool = createTool({
|
|
233
|
+
id: 'review',
|
|
234
|
+
description: 'Submit a draft for human review.',
|
|
235
|
+
inputSchema: z.object({ draft: z.string() }),
|
|
236
|
+
outputSchema: z.object({ approvedBy: z.string(), edits: z.string().optional() }),
|
|
237
|
+
background: { enabled: true },
|
|
238
|
+
execute: async ({ draft }, context) => {
|
|
239
|
+
const { suspend, resumeData } = context.agent
|
|
240
|
+
if (!resumeData) {
|
|
241
|
+
await suspend?.({ awaiting: 'approval', draft })
|
|
242
|
+
return { approvedBy: '', edits: undefined }
|
|
243
|
+
}
|
|
244
|
+
const { reviewer, edits } = resumeData as { reviewer: string; edits?: string }
|
|
245
|
+
return { approvedBy: reviewer, edits }
|
|
246
|
+
},
|
|
247
|
+
})
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The first invocation of `execute` sees `resumeData === undefined` and calls `suspend`. After the task is resumed, the runtime restarts the tool with `resumeData` populated; the `if` branch falls through and the tool returns its real result.
|
|
251
|
+
|
|
252
|
+
To resume the task once an approval arrives:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
await mastra.backgroundTaskManager?.resume(taskId, {
|
|
256
|
+
reviewer: 'alice@example.com',
|
|
257
|
+
edits: 'Reworded paragraph 3.',
|
|
258
|
+
})
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### What happens to the agent loop
|
|
262
|
+
|
|
263
|
+
When a task suspends mid-`streamUntilIdle()`, the wrapper treats it as terminal for the current iteration and closes. To continue the agent immediately when the resume payload is in hand, call `agent.resumeStreamUntilIdle(resumeData, { runId, toolCallId, memory })`: the resumed bg task runs to completion, its result lands in the message list, and the agent runs a follow-up turn — all on the same SSE connection. If you'd rather drive the resume out-of-band, call `mastra.backgroundTaskManager.resume(taskId, resumeData)` directly and the result still writes into the thread for the next user turn to pick up.
|
|
264
|
+
|
|
265
|
+
### Re-registering the executor on resume
|
|
266
|
+
|
|
267
|
+
The manager keeps tool executors in process memory. If the process restarts while a task is suspended, the executor closure is gone — the caller of `resume()` must re-register it first via `manager.registerTaskContext(taskId, ...)`. Tasks dispatched and resumed inside the same process don't need this.
|
|
268
|
+
|
|
269
|
+
### Cancelling a suspended task
|
|
270
|
+
|
|
271
|
+
`manager.cancel(taskId)` works against suspended tasks the same way it works for running ones: the row flips to `cancelled`, the workflow snapshot is cleaned up, and a `task.cancelled` event fires.
|
|
272
|
+
|
|
213
273
|
## Lifecycle callbacks
|
|
214
274
|
|
|
215
275
|
Each layer can register terminal-state callbacks. They don't replace one another, and success/failure hooks fire for their respective outcomes:
|
|
@@ -11,7 +11,7 @@ You can use individual [`Processor`](https://mastra.ai/reference/processors/proc
|
|
|
11
11
|
|
|
12
12
|
Some processors implement both input and output logic and can be used in either array depending on where the transformation should occur.
|
|
13
13
|
|
|
14
|
-
Some built-in processors also
|
|
14
|
+
Some built-in processors also send hidden system reminder signals. These signals are persisted in raw memory history and converted to `<system-reminder>...</system-reminder>` context before the next model call, but standard UI-facing message conversions and default memory recall hide them unless you explicitly opt in.
|
|
15
15
|
|
|
16
16
|
## When to use processors
|
|
17
17
|
|
|
@@ -391,6 +391,14 @@ new ToolCallFilter({
|
|
|
391
391
|
})
|
|
392
392
|
```
|
|
393
393
|
|
|
394
|
+
Set `preserveModelOutput: true` to keep compact `toModelOutput` history for filtered completed tool results. The filter keeps only the model-facing output and removes raw tool args and raw results.
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
new ToolCallFilter({
|
|
398
|
+
preserveModelOutput: true,
|
|
399
|
+
})
|
|
400
|
+
```
|
|
401
|
+
|
|
394
402
|
See the [`ToolCallFilter` reference](https://mastra.ai/reference/processors/tool-call-filter) for configuration options and the [Memory Processors](https://mastra.ai/docs/memory/memory-processors) page for pre-memory filtering.
|
|
395
403
|
|
|
396
404
|
### `ToolSearchProcessor`
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Response caching
|
|
2
|
+
|
|
3
|
+
Response caching skips the LLM call and replays a previously cached response when an agent receives an identical request. Use it to drop latency to single-digit milliseconds and avoid paying for repeated calls.
|
|
4
|
+
|
|
5
|
+
Caching is implemented as the [`ResponseCache`](https://mastra.ai/reference/processors/response-cache) input processor. There is no agent-level option — to enable caching, register the processor explicitly. This keeps the API surface small while we collect feedback; per-call overrides flow through `RequestContext`.
|
|
6
|
+
|
|
7
|
+
## When to use response caching
|
|
8
|
+
|
|
9
|
+
Reach for it when the same request shape repeats across users or sessions, for example prompt templates, suggested-prompt buttons, agentic search re-asks, or guardrail LLMs that classify the same input over and over. Skip it when calls trigger external side effects through tools, since cache hits replay tool calls without re-executing them.
|
|
10
|
+
|
|
11
|
+
## Quickstart
|
|
12
|
+
|
|
13
|
+
Add a `ResponseCache` to the agent's `inputProcessors` and pass any `MastraServerCache` as the backend. For development, `InMemoryServerCache` works out of the box:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { Agent } from '@mastra/core/agent'
|
|
17
|
+
import { InMemoryServerCache } from '@mastra/core/cache'
|
|
18
|
+
import { ResponseCache } from '@mastra/core/processors'
|
|
19
|
+
|
|
20
|
+
const cache = new InMemoryServerCache()
|
|
21
|
+
|
|
22
|
+
export const searchAgent = new Agent({
|
|
23
|
+
name: 'Search Agent',
|
|
24
|
+
instructions: 'You answer questions concisely.',
|
|
25
|
+
model: 'openai/gpt-5',
|
|
26
|
+
inputProcessors: [new ResponseCache({ cache, ttl: 600 })], // 10 minutes
|
|
27
|
+
})
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The first call runs the LLM normally and writes the response to the cache. Subsequent calls with an identical resolved prompt return the cached response without invoking the LLM.
|
|
31
|
+
|
|
32
|
+
## Per-call overrides via RequestContext
|
|
33
|
+
|
|
34
|
+
Per-call config flows through `RequestContext`. Use `ResponseCache.context()` to build a fresh context, or `ResponseCache.applyContext()` to merge into one you already have:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { ResponseCache } from '@mastra/core/processors'
|
|
38
|
+
import { RequestContext } from '@mastra/core/request-context'
|
|
39
|
+
|
|
40
|
+
// Fresh context with the override
|
|
41
|
+
await agent.stream('hello', {
|
|
42
|
+
requestContext: ResponseCache.context({ key: 'custom-key', bust: true }),
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// Or merge into an existing context
|
|
46
|
+
const ctx = new RequestContext()
|
|
47
|
+
ctx.set('caller-meta', { userId: 'u-123' })
|
|
48
|
+
ResponseCache.applyContext(ctx, { bust: true })
|
|
49
|
+
await agent.stream('hello', { requestContext: ctx })
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Three fields are overridable per call:
|
|
53
|
+
|
|
54
|
+
- `key` — string or function. Overrides the auto-derived cache key for this request only.
|
|
55
|
+
- `scope` — string or `null`. Overrides the tenant/user scope for this request only. `null` opts out of scoping.
|
|
56
|
+
- `bust` — boolean. Skips the cache read but still writes on completion (useful for "force refresh" buttons).
|
|
57
|
+
|
|
58
|
+
`cache`, `ttl`, and `agentId` stay on the constructor — they are instance-level concerns and not safe to vary per call.
|
|
59
|
+
|
|
60
|
+
## Tenant scoping
|
|
61
|
+
|
|
62
|
+
By default, `ResponseCache` looks up `MASTRA_RESOURCE_ID_KEY` on the request context and uses it as the cache scope. This means an agent that already populates the resource id (e.g. via memory) gets per-user isolation automatically — two users never see each other's cached responses.
|
|
63
|
+
|
|
64
|
+
Override explicitly when you need a different scope:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
new Agent({
|
|
68
|
+
// ...
|
|
69
|
+
inputProcessors: [
|
|
70
|
+
new ResponseCache({
|
|
71
|
+
cache,
|
|
72
|
+
scope: 'org-123', // explicit tenant scope
|
|
73
|
+
}),
|
|
74
|
+
],
|
|
75
|
+
})
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Pass `scope: null` to deliberately share entries across all callers — only use this for known-public, non-personalized content.
|
|
79
|
+
|
|
80
|
+
## Custom cache backend
|
|
81
|
+
|
|
82
|
+
`ResponseCache` accepts any `MastraServerCache`. For production, use `RedisCache` from `@mastra/redis`:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { Agent } from '@mastra/core/agent'
|
|
86
|
+
import { ResponseCache } from '@mastra/core/processors'
|
|
87
|
+
import { RedisCache } from '@mastra/redis'
|
|
88
|
+
|
|
89
|
+
const cache = new RedisCache({ url: process.env.REDIS_URL })
|
|
90
|
+
|
|
91
|
+
export const agent = new Agent({
|
|
92
|
+
name: 'Cached Agent',
|
|
93
|
+
instructions: '...',
|
|
94
|
+
model: 'openai/gpt-5',
|
|
95
|
+
inputProcessors: [new ResponseCache({ cache })],
|
|
96
|
+
})
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
For a custom backend, extend `MastraServerCache` and implement its abstract methods (the processor only calls `get` and `set`).
|
|
100
|
+
|
|
101
|
+
## How caching is implemented
|
|
102
|
+
|
|
103
|
+
`ResponseCache` hooks into `processLLMRequest` (cache lookup, short-circuits on hit) and `processLLMResponse` (cache write on completion). Both run inside the agentic loop _after_ memory has loaded and earlier input processors have transformed the prompt.
|
|
104
|
+
|
|
105
|
+
This means the cache key is derived from the resolved `LanguageModelV2Prompt` Mastra is about to send to the model — i.e. _after_ memory has loaded and earlier input processors have run — and each step in an agentic tool loop is independently cached.
|
|
106
|
+
|
|
107
|
+
## What's in the cache key
|
|
108
|
+
|
|
109
|
+
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.
|
|
110
|
+
|
|
111
|
+
### Customize the cache key
|
|
112
|
+
|
|
113
|
+
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>`):
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { ResponseCache, buildResponseCacheKey } from '@mastra/core/processors'
|
|
117
|
+
|
|
118
|
+
await agent.stream(input, {
|
|
119
|
+
requestContext: ResponseCache.context({
|
|
120
|
+
// Cache only on the model id and the resolved prompt tail — ignore
|
|
121
|
+
// step number, scope, etc.
|
|
122
|
+
key: ({ model, prompt }) => `qa:${model.modelId}:${JSON.stringify(prompt).slice(-200)}`,
|
|
123
|
+
}),
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
// Or reuse the deterministic helper while overriding individual fields:
|
|
127
|
+
await agent.stream(input, {
|
|
128
|
+
requestContext: ResponseCache.context({
|
|
129
|
+
key: inputs => buildResponseCacheKey({ ...inputs, scope: 'global' }),
|
|
130
|
+
}),
|
|
131
|
+
})
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
If the function throws, the processor falls back to the default key derivation so the call still benefits from caching.
|
|
135
|
+
|
|
136
|
+
## How cache hits work
|
|
137
|
+
|
|
138
|
+
When the processor finds a cache hit, it short-circuits the LLM call by returning the cached chunks from `processLLMRequest`. The agentic loop synthesizes a stream from those chunks instead of calling the model. `agent.generate()` collects them into a `FullOutput`; `agent.stream()` returns a `MastraModelOutput` whose chunks come from the cached buffer, so consumers iterating `fullStream` or awaiting `text`, `usage`, and `finishReason` see the cached values.
|
|
139
|
+
|
|
140
|
+
Cache writes happen after the response completes. Failed runs (errors, tripwire activations) are not cached, so the next call retries cleanly.
|
|
141
|
+
|
|
142
|
+
## Related
|
|
143
|
+
|
|
144
|
+
- [`ResponseCache` reference](https://mastra.ai/reference/processors/response-cache)
|
|
145
|
+
- [Processors](https://mastra.ai/docs/agents/processors)
|
|
146
|
+
- [Guardrails](https://mastra.ai/docs/agents/guardrails)
|
|
147
|
+
- [Agent.stream()](https://mastra.ai/reference/streaming/agents/stream)
|
|
148
|
+
- [Agent.generate()](https://mastra.ai/reference/agents/generate)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Signals
|
|
2
|
+
|
|
3
|
+
> **Experimental:** Agent signals are experimental. The API may change in a future release.
|
|
4
|
+
|
|
5
|
+
Signals are a way to interact with an agent through a thread. Instead of starting every interaction with `agent.stream()`, subscribe to a thread and send signals. Mastra either wakes the agent when the thread is idle or drops the signal into the running agent loop.
|
|
6
|
+
|
|
7
|
+
Signals are a context engineering tool for guiding the agent in real time as the agent loop progresses. Use them to add system-generated content from external event sources, such as incoming email notifications, GitHub pull request comments, background task notifications, and similar events.
|
|
8
|
+
|
|
9
|
+
## Quickstart
|
|
10
|
+
|
|
11
|
+
Subscribe to the thread before sending signals. The subscription receives the active stream when the signal wakes the agent or enters a running loop.
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
const subscription = await agent.subscribeToThread({
|
|
15
|
+
resourceId: 'user_123',
|
|
16
|
+
threadId: 'thread_456',
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
agent.sendSignal(
|
|
20
|
+
{
|
|
21
|
+
type: 'user-message',
|
|
22
|
+
contents: 'Compare that with the previous option.',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
resourceId: 'user_123',
|
|
26
|
+
threadId: 'thread_456',
|
|
27
|
+
},
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
for await (const chunk of subscription.stream) {
|
|
31
|
+
console.log(chunk)
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
When the thread has a running agent stream, the signal becomes new input inside that agent loop. When the thread is idle, Mastra starts a stream with the signal as the first input.
|
|
36
|
+
|
|
37
|
+
## Control signal behavior
|
|
38
|
+
|
|
39
|
+
By default, Mastra delivers signals to active runs and wakes idle threads. Use `ifActive.behavior` and `ifIdle.behavior` to change that behavior.
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
const result = agent.sendSignal(
|
|
43
|
+
{
|
|
44
|
+
type: 'user-message',
|
|
45
|
+
contents: 'Store this for later, but do not wake the agent.',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
resourceId: 'user_123',
|
|
49
|
+
threadId: 'thread_456',
|
|
50
|
+
ifIdle: {
|
|
51
|
+
behavior: 'persist',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
await result.persisted
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The behavior options are:
|
|
60
|
+
|
|
61
|
+
- `ifActive.behavior: 'deliver'`: Add the signal to the running agent loop. This is the default.
|
|
62
|
+
- `ifActive.behavior: 'persist'`: Save the signal to memory without adding it to the running loop.
|
|
63
|
+
- `ifActive.behavior: 'discard'`: Ignore the signal while the thread is active.
|
|
64
|
+
- `ifIdle.behavior: 'wake'`: Start a stream with the signal as the first input. This is the default.
|
|
65
|
+
- `ifIdle.behavior: 'persist'`: Save the signal to memory without starting a stream.
|
|
66
|
+
- `ifIdle.behavior: 'discard'`: Ignore the signal while the thread is idle.
|
|
67
|
+
|
|
68
|
+
Pass `ifIdle.streamOptions` when the idle wake-up stream needs options such as model settings, tools, or runtime context. You do not need to repeat `memory.resource` or `memory.thread`; Mastra uses the top-level `resourceId` and `threadId` for the thread.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
agent.sendSignal(
|
|
72
|
+
{
|
|
73
|
+
type: 'user-message',
|
|
74
|
+
contents: 'Continue with the next step.',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
resourceId: 'user_123',
|
|
78
|
+
threadId: 'thread_456',
|
|
79
|
+
ifIdle: {
|
|
80
|
+
behavior: 'wake',
|
|
81
|
+
streamOptions: {
|
|
82
|
+
maxSteps: 3,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Send external event context
|
|
90
|
+
|
|
91
|
+
Use custom signal types for system-generated context. Non-user signal types are rendered as XML-style user-role context so they can appear inside conversation history without looking like assistant output.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
agent.sendSignal(
|
|
95
|
+
{
|
|
96
|
+
type: 'system-reminder',
|
|
97
|
+
contents: 'User X has left a new PR comment asking for a smaller API surface.',
|
|
98
|
+
attributes: {
|
|
99
|
+
type: 'github',
|
|
100
|
+
pr: '123',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
resourceId: 'user_123',
|
|
105
|
+
threadId: 'thread_456',
|
|
106
|
+
},
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The model receives the custom signal as context like this:
|
|
111
|
+
|
|
112
|
+
```xml
|
|
113
|
+
<system-reminder type="github" pr="123">User X has left a new PR comment asking for a smaller API surface.</system-reminder>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Use XML-safe signal type names and attribute names. Signal type names and attribute names can contain letters, numbers, underscores, periods, and hyphens. They must start with a letter or underscore.
|
|
117
|
+
|
|
118
|
+
## Use the client SDK
|
|
119
|
+
|
|
120
|
+
The JavaScript client exposes the same thread signal APIs. Use `subscribeToThread()` before `sendSignal()` so the client can render the stream that wakes from, or receives, the signal.
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
const agent = client.getAgent('supportAgent')
|
|
124
|
+
|
|
125
|
+
const subscription = await agent.subscribeToThread({
|
|
126
|
+
resourceId: 'user_123',
|
|
127
|
+
threadId: 'thread_456',
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
await agent.sendSignal({
|
|
131
|
+
signal: {
|
|
132
|
+
type: 'user-message',
|
|
133
|
+
contents: 'Show the shorter version.',
|
|
134
|
+
},
|
|
135
|
+
resourceId: 'user_123',
|
|
136
|
+
threadId: 'thread_456',
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
await subscription.processDataStream({
|
|
140
|
+
onChunk: chunk => {
|
|
141
|
+
console.log(chunk)
|
|
142
|
+
},
|
|
143
|
+
})
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Related
|
|
147
|
+
|
|
148
|
+
- [`Agent.sendSignal()`](https://mastra.ai/reference/agents/agent)
|
|
149
|
+
- [`Agent.subscribeToThread()`](https://mastra.ai/reference/agents/agent)
|
|
150
|
+
- [`client.getAgent().sendSignal()`](https://mastra.ai/reference/client-js/agents)
|
|
151
|
+
- [`client.getAgent().subscribeToThread()`](https://mastra.ai/reference/client-js/agents)
|
|
@@ -224,6 +224,14 @@ export const weatherTool = createTool({
|
|
|
224
224
|
})
|
|
225
225
|
```
|
|
226
226
|
|
|
227
|
+
## Transform tool payloads for UI and transcripts
|
|
228
|
+
|
|
229
|
+
Use `transform` when a tool returns raw data your application needs, but browser-facing streams or user-visible transcript messages should receive a smaller or safer shape. `transform` is separate from `toModelOutput`: `toModelOutput` shapes the payload sent back to the model, while `transform` shapes tool input, output, errors, approval payloads, and suspension payloads for `display` and `transcript` targets.
|
|
230
|
+
|
|
231
|
+
If a transform is configured and it fails, Mastra does not fall back to the raw payload for display or transcript targets. Input deltas are suppressed when no safe `inputDelta` transform is available.
|
|
232
|
+
|
|
233
|
+
See the [`createTool()` reference](https://mastra.ai/reference/tools/create-tool) for a `transform` example. For shared rules across several tools, configure the agent-level `transform` policy in the [`Agent` constructor](https://mastra.ai/reference/agents/agent).
|
|
234
|
+
|
|
227
235
|
## Control tool selection
|
|
228
236
|
|
|
229
237
|
Pass `toolChoice` or `activeTools` to `.generate()` or `.stream()` to control which tools the agent uses at runtime.
|
|
@@ -65,6 +65,21 @@ When interacting with pages:
|
|
|
65
65
|
|
|
66
66
|
> **Note:** For local launches (the default), AgentBrowser requires a Chromium binary installed via Playwright. This is normally downloaded automatically when you install `@mastra/agent-browser`. If launching the browser fails with `"browser executable is missing"`, run `npx playwright install chromium`. If you connect to a remote browser using the [`cdpUrl`](https://mastra.ai/reference/browser/agent-browser) option, no local Chromium is needed.
|
|
67
67
|
|
|
68
|
+
## Screenshots
|
|
69
|
+
|
|
70
|
+
When the agent uses the `browser_screenshot` tool, it captures a PNG image of the current page and returns it as image content that vision-capable models can interpret directly.
|
|
71
|
+
|
|
72
|
+
Use screenshots when you need to visually inspect the page — for example, evaluating images, layout, or colors. For text or structured data, use `browser_snapshot` instead.
|
|
73
|
+
|
|
74
|
+
To disable the screenshot tool for models that do not support vision, use `excludeTools`:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const browser = new AgentBrowser({
|
|
78
|
+
headless: false,
|
|
79
|
+
excludeTools: ['browser_screenshot'],
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
68
83
|
## Element refs
|
|
69
84
|
|
|
70
85
|
AgentBrowser uses accessibility tree refs to identify elements. When an agent calls `browser_snapshot`, it receives a text representation of the page with refs like `@e1`, `@e2`, etc. The agent then uses these refs with other tools to interact with elements.
|
|
@@ -61,7 +61,8 @@ Use stagehand tools to interact with pages:
|
|
|
61
61
|
- stagehand_navigate to go to URLs
|
|
62
62
|
- stagehand_act to perform actions described in natural language
|
|
63
63
|
- stagehand_extract to get structured data from the page
|
|
64
|
-
- stagehand_observe to find available actions on the page
|
|
64
|
+
- stagehand_observe to find available actions on the page
|
|
65
|
+
- stagehand_screenshot to visually inspect the page`,
|
|
65
66
|
})
|
|
66
67
|
```
|
|
67
68
|
|
|
@@ -107,6 +108,29 @@ Returns a list of available actions:
|
|
|
107
108
|
]
|
|
108
109
|
```
|
|
109
110
|
|
|
111
|
+
## Screenshots
|
|
112
|
+
|
|
113
|
+
When the agent uses the `stagehand_screenshot` tool, it captures a PNG image of the current page and returns it as image content that vision-capable models can interpret directly.
|
|
114
|
+
|
|
115
|
+
Use screenshots when you need to visually inspect the page — for example, evaluating images, layout, or colors. For text or structured data, use `stagehand_extract` or `stagehand_observe` instead.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
const browser = new StagehandBrowser({
|
|
119
|
+
headless: false,
|
|
120
|
+
model: 'openai/gpt-5.4',
|
|
121
|
+
})
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
To disable the screenshot tool for models that do not support vision, use `excludeTools`:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const browser = new StagehandBrowser({
|
|
128
|
+
headless: false,
|
|
129
|
+
model: 'openai/gpt-5.4',
|
|
130
|
+
excludeTools: ['stagehand_screenshot'],
|
|
131
|
+
})
|
|
132
|
+
```
|
|
133
|
+
|
|
110
134
|
## Browserbase
|
|
111
135
|
|
|
112
136
|
Stagehand has native Browserbase integration for cloud browser infrastructure:
|
|
@@ -4,7 +4,7 @@ Mastra applications can be deployed to cloud providers and serverless platforms.
|
|
|
4
4
|
|
|
5
5
|
## Mastra platform
|
|
6
6
|
|
|
7
|
-
Mastra provides a platform to deploy your server to the cloud. Read the [Mastra platform deployment guide](https://mastra.ai/
|
|
7
|
+
Mastra provides a platform to deploy your server to the cloud. Read the [Mastra platform deployment guide](https://mastra.ai/docs/mastra-platform/overview) to learn more.
|
|
8
8
|
|
|
9
9
|
## Cloud providers
|
|
10
10
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Deployment overview
|
|
2
2
|
|
|
3
|
-
Mastra applications can be deployed to any Node.js-compatible environment. You can deploy a Mastra server, integrate with an existing web framework, deploy to cloud providers, or use [Mastra platform](https://mastra.ai/docs/mastra-platform/overview) for Studio and server deployment.
|
|
3
|
+
Mastra applications can be deployed to any Node.js-compatible environment. You can deploy a Mastra server, integrate with an existing web framework, deploy to cloud providers, or use [Mastra platform](https://mastra.ai/docs/mastra-platform/overview) for observability, Studio, and server deployment.
|
|
4
4
|
|
|
5
5
|
## Runtime support
|
|
6
6
|
|
|
@@ -27,12 +27,13 @@ Read about [monorepo deployment](https://mastra.ai/docs/deployment/monorepo).
|
|
|
27
27
|
|
|
28
28
|
### Mastra platform
|
|
29
29
|
|
|
30
|
-
The [Mastra platform](https://mastra.ai/docs/mastra-platform/overview) provides
|
|
30
|
+
The [Mastra platform](https://mastra.ai/docs/mastra-platform/overview) provides three products for deploying, monitoring, and managing AI applications built with the Mastra framework:
|
|
31
31
|
|
|
32
|
-
- **
|
|
33
|
-
- **
|
|
32
|
+
- [**Observability**](https://mastra.ai/docs/mastra-platform/observability): A standalone hosted product for searchable traces, logs, and metrics across Mastra projects and deploys
|
|
33
|
+
- [**Studio**](https://mastra.ai/docs/mastra-platform/studio): A hosted visual environment for testing agents, running workflows, and inspecting traces
|
|
34
|
+
- [**Server**](https://mastra.ai/docs/mastra-platform/server): A production deployment target that runs your Mastra application as an API server
|
|
34
35
|
|
|
35
|
-
Learn more in the [
|
|
36
|
+
Learn more in the [Mastra platform overview](https://mastra.ai/docs/mastra-platform/overview).
|
|
36
37
|
|
|
37
38
|
### Cloud Providers
|
|
38
39
|
|
|
@@ -73,7 +73,7 @@ Integration providers connect external tool platforms to the editor. Once regist
|
|
|
73
73
|
})
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
Composio tool slugs use a format like `GITHUB_CREATE_ISSUE`. Tool calls are scoped to
|
|
76
|
+
Composio tool slugs use a format like `GITHUB_CREATE_ISSUE`. Tool calls are scoped to the `resourceId` passed through request context for per-user authentication.
|
|
77
77
|
|
|
78
78
|
### Arcade
|
|
79
79
|
|
package/.docs/docs/index.md
CHANGED
|
@@ -126,8 +126,8 @@ Templates: [Customer Feedback Summarization](https://mastra.ai/templates/custome
|
|
|
126
126
|
|
|
127
127
|
Browse [templates](https://mastra.ai/templates) for working examples.
|
|
128
128
|
|
|
129
|
-
##
|
|
129
|
+
## Want to learn more?
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
Here's a quick introduction:
|
|
132
132
|
|
|
133
133
|
[YouTube video player](https://www.youtube-nocookie.com/embed/1qnmnRICX50)
|
|
@@ -41,18 +41,34 @@ To pin the deploy to a specific env file (instead of relying on the default sele
|
|
|
41
41
|
mastra studio deploy --env-file .env.production --yes
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
### Observability
|
|
45
|
+
|
|
46
|
+
The following environment variables configure the Observability product on the Mastra platform.
|
|
47
|
+
|
|
48
|
+
| Variable | Description |
|
|
49
|
+
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| `MASTRA_PLATFORM_ACCESS_TOKEN` | Org-scoped access token. The CLI writes this during observability provisioning and uses it for platform authentication. |
|
|
51
|
+
| `MASTRA_PROJECT_ID` | UUID of the platform project. `MastraPlatformExporter` uses it to link observability data to the platform project. Studio and Server deploys read the project ID from `.mastra-project.json`. |
|
|
52
|
+
| `MASTRA_PLATFORM_OBSERVABILITY_ENDPOINT` | Optional observability endpoint override. This is only set automatically for local platform development. Defaults to `https://observability.mastra.ai`. |
|
|
53
|
+
| `MASTRA_ORG_ID` | Overrides the active organization for CLI commands. You can also set it with the `--org` flag on supported commands. |
|
|
54
|
+
|
|
55
|
+
`MastraPlatformExporter` reads `MASTRA_PLATFORM_ACCESS_TOKEN` to authenticate platform export.
|
|
56
|
+
|
|
44
57
|
## Multiple environments
|
|
45
58
|
|
|
46
|
-
A platform project maps to a single deployed instance with one set of env vars.
|
|
59
|
+
A platform project maps to a single deployed instance with one set of env vars. Platform projects don't have built-in `staging` vs `production` slots. To run the same codebase across multiple environments, create one project per environment and use the matching `.mastra-project.json` file for each deploy.
|
|
47
60
|
|
|
48
61
|
```bash
|
|
49
|
-
# Create
|
|
62
|
+
# Create and deploy each environment for the first time.
|
|
50
63
|
mastra studio deploy --project "my-app-staging" --env-file .env.staging --yes
|
|
51
64
|
mastra studio deploy --project "my-app-production" --env-file .env.production --yes
|
|
52
65
|
|
|
53
|
-
#
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
# For subsequent deploys, restore the matching .mastra-project.json file before deploying.
|
|
67
|
+
cp .mastra-project.staging.json .mastra-project.json
|
|
68
|
+
mastra studio deploy --env-file .env.staging --yes
|
|
69
|
+
|
|
70
|
+
cp .mastra-project.production.json .mastra-project.json
|
|
71
|
+
mastra studio deploy --env-file .env.production --yes
|
|
56
72
|
```
|
|
57
73
|
|
|
58
|
-
Each project has its own Studio URL and
|
|
74
|
+
Each project has its own Studio URL and can send observability data to the Mastra platform. When using [`MastraPlatformExporter`](https://mastra.ai/docs/observability/tracing/exporters/mastra-platform), set `MASTRA_PROJECT_ID` and `MASTRA_PLATFORM_ACCESS_TOKEN` per environment so traces route to the matching platform project.
|