@mastra/mcp-docs-server 1.1.42-alpha.4 → 1.1.42-alpha.5
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/agent-builder/memory.md +1 -1
- package/.docs/docs/agents/adding-voice.md +31 -0
- package/.docs/docs/agents/agent-approval.md +14 -0
- package/.docs/docs/agents/code-mode.md +163 -0
- package/.docs/docs/agents/signals.md +132 -71
- package/.docs/docs/getting-started/manual-install.md +1 -1
- package/.docs/docs/memory/semantic-recall.md +1 -1
- package/.docs/docs/observability/metrics/overview.md +1 -0
- package/.docs/docs/observability/metrics/querying.md +292 -0
- package/.docs/docs/server/auth/fga.md +2 -0
- package/.docs/docs/voice/overview.md +62 -0
- package/.docs/docs/voice/speech-to-speech.md +52 -1
- package/.docs/docs/workspace/sandbox.md +4 -2
- package/.docs/guides/guide/firecrawl.md +5 -5
- package/.docs/models/embeddings.md +2 -2
- package/.docs/reference/agents/agent.md +46 -17
- package/.docs/reference/index.md +3 -0
- package/.docs/reference/observability/metrics/automatic-metrics.md +7 -1
- package/.docs/reference/processors/tool-search-processor.md +31 -0
- package/.docs/reference/server/routes.md +81 -9
- package/.docs/reference/templates/overview.md +2 -2
- package/.docs/reference/tools/mcp-client.md +51 -0
- package/.docs/reference/vectors/pg.md +2 -0
- package/.docs/reference/voice/inworld-realtime.md +353 -0
- package/.docs/reference/voice/inworld.md +2 -0
- package/.docs/reference/workspace/agentcore-runtime-sandbox.md +202 -0
- package/.docs/reference/workspace/blaxel-sandbox.md +3 -0
- package/.docs/reference/workspace/docker-sandbox.md +3 -1
- package/.docs/reference/workspace/vercel-microvm-sandbox.md +199 -0
- package/.docs/reference/workspace/vercel.md +2 -0
- package/CHANGELOG.md +8 -0
- package/package.json +8 -6
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# Querying metrics
|
|
2
|
+
|
|
3
|
+
Mastra exposes the same five OLAP queries (`getMetricAggregate`, `getMetricBreakdown`, `getMetricTimeSeries`, `getMetricPercentiles`, and discovery helpers) through three surfaces: an in-process store accessor, the runtime HTTP API, and the `mastra api metric` CLI. All three accept the same Zod-validated input shapes, so you can move from a one-off CLI investigation to a programmatic dashboard tool without re-learning the API.
|
|
4
|
+
|
|
5
|
+
## When to use this
|
|
6
|
+
|
|
7
|
+
- Build a custom dashboard or KPI tile alongside Studio.
|
|
8
|
+
- Power a scheduled alert that fires when token cost or latency crosses a threshold.
|
|
9
|
+
- Give an agent a tool that reads its own performance metrics and explains them in chat.
|
|
10
|
+
- Run one-off investigations from a terminal with `mastra api metric ...`.
|
|
11
|
+
|
|
12
|
+
For setup of the observability store itself, see the [Metrics overview](https://mastra.ai/docs/observability/metrics/overview). For the list of metric names you can query, see the [Automatic metrics reference](https://mastra.ai/reference/observability/metrics/automatic-metrics).
|
|
13
|
+
|
|
14
|
+
> **Note:** Metric queries are served by the observability domain, which requires an OLAP-capable store (DuckDB locally, ClickHouse in production). See [Metrics overview](https://mastra.ai/docs/observability/metrics/overview) for setup. If the observability store is not configured, `getStore('observability')` returns `null`.
|
|
15
|
+
|
|
16
|
+
## Surfaces
|
|
17
|
+
|
|
18
|
+
### In-process
|
|
19
|
+
|
|
20
|
+
Inside a tool, server route, or workflow step, get the observability store from the Mastra storage:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { createTool } from '@mastra/core/tools'
|
|
24
|
+
import { z } from 'zod'
|
|
25
|
+
|
|
26
|
+
export const agentLatencyTool = createTool({
|
|
27
|
+
id: 'agentLatency',
|
|
28
|
+
description: 'Average agent latency over the last hour.',
|
|
29
|
+
inputSchema: z.object({}),
|
|
30
|
+
execute: async (_input, context) => {
|
|
31
|
+
const observability = await context.mastra!.getStorage()!.getStore('observability')
|
|
32
|
+
if (!observability) {
|
|
33
|
+
throw new Error('Observability domain is not configured (requires DuckDB or ClickHouse)')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const result = await observability.getMetricAggregate({
|
|
37
|
+
name: ['mastra_agent_duration_ms'],
|
|
38
|
+
aggregation: 'avg',
|
|
39
|
+
filters: {
|
|
40
|
+
timestamp: { start: new Date(Date.now() - 60 * 60 * 1000) },
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return { averageMs: result.value }
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`getStore('observability')` returns `null` when the configured backend does not support OLAP queries.
|
|
50
|
+
|
|
51
|
+
### HTTP
|
|
52
|
+
|
|
53
|
+
The `mastra dev` server (and any deployed Mastra runtime) exposes the same queries under `/api/observability/metrics/*`. Aggregate, breakdown, time series, and percentile endpoints take a JSON body with `POST`. Discovery endpoints use `GET` with query parameters.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
curl -sS -X POST http://localhost:4111/api/observability/metrics/aggregate \
|
|
57
|
+
-H "content-type: application/json" \
|
|
58
|
+
-d '{"name":["mastra_agent_duration_ms"],"aggregation":"avg"}'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Available routes:
|
|
62
|
+
|
|
63
|
+
- `POST /api/observability/metrics/aggregate`
|
|
64
|
+
- `POST /api/observability/metrics/breakdown`
|
|
65
|
+
- `POST /api/observability/metrics/timeseries`
|
|
66
|
+
- `POST /api/observability/metrics/percentiles`
|
|
67
|
+
- `GET /api/observability/metrics` (raw rows, paginated)
|
|
68
|
+
- `GET /api/observability/discovery/metric-names`
|
|
69
|
+
- `GET /api/observability/discovery/metric-label-keys`
|
|
70
|
+
- `GET /api/observability/discovery/metric-label-values`
|
|
71
|
+
|
|
72
|
+
The `@mastra/client-js` SDK wraps the same routes as `mastraClient.getMetricAggregate(...)`, `getMetricBreakdown(...)`, and so on.
|
|
73
|
+
|
|
74
|
+
### CLI
|
|
75
|
+
|
|
76
|
+
`mastra api metric ...` calls the same endpoints with a single JSON argument, so an agent or shell script can fetch metrics without writing any code:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
mastra api metric aggregate \
|
|
80
|
+
'{"name":["mastra_agent_duration_ms"],"aggregation":"avg"}' \
|
|
81
|
+
--url http://localhost:4111 --pretty
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
By default the CLI targets hosted Mastra observability (`https://observability.mastra.ai`). Pass `--url http://localhost:4111` to query a local `mastra dev` server. See [`mastra api metric aggregate`](https://mastra.ai/reference/cli/mastra) and the surrounding entries for the full command list.
|
|
85
|
+
|
|
86
|
+
## Queries
|
|
87
|
+
|
|
88
|
+
### `getMetricAggregate`
|
|
89
|
+
|
|
90
|
+
Returns a single scalar — the building block for KPI cards.
|
|
91
|
+
|
|
92
|
+
Inputs:
|
|
93
|
+
|
|
94
|
+
- `name`: Array of one or more metric names.
|
|
95
|
+
- `aggregation`: One of `'sum' | 'avg' | 'min' | 'max' | 'count' | 'count_distinct' | 'last'`.
|
|
96
|
+
- `filters`: Optional [filter object](#filtering).
|
|
97
|
+
- `comparePeriod`: Optional `'previous_period' | 'previous_day' | 'previous_week'` for period-over-period comparison.
|
|
98
|
+
|
|
99
|
+
Response:
|
|
100
|
+
|
|
101
|
+
- `value`, `previousValue`, `changePercent`.
|
|
102
|
+
- `estimatedCost`, `costUnit`, `previousEstimatedCost`, `costChangePercent` for token metrics.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
const observability = await mastra.getStorage()!.getStore('observability')
|
|
106
|
+
|
|
107
|
+
const cost = await observability!.getMetricAggregate({
|
|
108
|
+
name: ['mastra_model_total_input_tokens', 'mastra_model_total_output_tokens'],
|
|
109
|
+
aggregation: 'sum',
|
|
110
|
+
comparePeriod: 'previous_day',
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
console.log(cost.value, cost.estimatedCost, cost.costUnit, cost.changePercent)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### `getMetricBreakdown`
|
|
117
|
+
|
|
118
|
+
Groups rows by one or more dimensions and aggregates each group — the building block for top-N tables (e.g. "tokens by agent").
|
|
119
|
+
|
|
120
|
+
Inputs:
|
|
121
|
+
|
|
122
|
+
- `name`: Array of metric names.
|
|
123
|
+
- `groupBy`: Array of fields to group by (for example `['entityName']`).
|
|
124
|
+
- `aggregation`: Same enum as above.
|
|
125
|
+
- `limit`: Server-side top-K cap. Required for high-cardinality `groupBy`.
|
|
126
|
+
- `orderDirection`: `'ASC' | 'DESC'` (defaults to `DESC`).
|
|
127
|
+
- `filters`: Optional.
|
|
128
|
+
|
|
129
|
+
Response: `groups[]`, each with `dimensions` (record of group keys to values), `value`, and `estimatedCost`.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const byAgent = await observability!.getMetricBreakdown({
|
|
133
|
+
name: ['mastra_model_total_input_tokens'],
|
|
134
|
+
groupBy: ['entityName'],
|
|
135
|
+
aggregation: 'sum',
|
|
136
|
+
limit: 10,
|
|
137
|
+
orderDirection: 'DESC',
|
|
138
|
+
})
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### `getMetricTimeSeries`
|
|
142
|
+
|
|
143
|
+
Buckets values by a fixed interval — the building block for line and bar charts.
|
|
144
|
+
|
|
145
|
+
Inputs:
|
|
146
|
+
|
|
147
|
+
- `name`: Array of metric names.
|
|
148
|
+
- `interval`: One of `'1m' | '5m' | '15m' | '1h' | '1d'`.
|
|
149
|
+
- `aggregation`: Same enum.
|
|
150
|
+
- `groupBy`: Optional. When omitted, multiple metric names are summed into one series; use one call per metric to keep them separate.
|
|
151
|
+
- `filters`: Optional.
|
|
152
|
+
|
|
153
|
+
Response: `series[]`, each with `name`, `costUnit`, and `points[]` of `{ timestamp, value, estimatedCost }`.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
const inputTokens = await observability!.getMetricTimeSeries({
|
|
157
|
+
name: ['mastra_model_total_input_tokens'],
|
|
158
|
+
aggregation: 'sum',
|
|
159
|
+
interval: '1h',
|
|
160
|
+
filters: {
|
|
161
|
+
timestamp: { start: new Date(Date.now() - 24 * 60 * 60 * 1000) },
|
|
162
|
+
},
|
|
163
|
+
})
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### `getMetricPercentiles`
|
|
167
|
+
|
|
168
|
+
Returns percentile values bucketed by time — the building block for latency charts.
|
|
169
|
+
|
|
170
|
+
Inputs:
|
|
171
|
+
|
|
172
|
+
- `name`: Single metric name (string, not array).
|
|
173
|
+
- `percentiles`: Array of numbers between `0` and `1`, for example `[0.5, 0.95, 0.99]`.
|
|
174
|
+
- `interval`: Same enum as `getMetricTimeSeries`.
|
|
175
|
+
- `filters`: Optional.
|
|
176
|
+
|
|
177
|
+
Response: `series[]`, each with `percentile` and `points[]` of `{ timestamp, value }`.
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
const latency = await observability!.getMetricPercentiles({
|
|
181
|
+
name: 'mastra_agent_duration_ms',
|
|
182
|
+
percentiles: [0.5, 0.95],
|
|
183
|
+
interval: '1h',
|
|
184
|
+
})
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Discovery
|
|
188
|
+
|
|
189
|
+
Use these endpoints to populate dropdowns or to give an agent the menu of values it can filter by. All discovery routes are `GET` and live under `/api/observability/discovery/`.
|
|
190
|
+
|
|
191
|
+
**Metric-specific** (also exposed as `mastra api metric` subcommands):
|
|
192
|
+
|
|
193
|
+
| Method | Args | Path suffix | CLI |
|
|
194
|
+
| ---------------------- | ------------------------------------------- | --------------------- | -------------------------------- |
|
|
195
|
+
| `getMetricNames` | `{ prefix?, limit? }` | `metric-names` | `mastra api metric names` |
|
|
196
|
+
| `getMetricLabelKeys` | `{ metricName }` | `metric-label-keys` | `mastra api metric label-keys` |
|
|
197
|
+
| `getMetricLabelValues` | `{ metricName, labelKey, prefix?, limit? }` | `metric-label-values` | `mastra api metric label-values` |
|
|
198
|
+
|
|
199
|
+
**Shared with traces and logs** (HTTP-only, no dedicated CLI subcommand):
|
|
200
|
+
|
|
201
|
+
| Method | Args | Path suffix |
|
|
202
|
+
| ----------------- | ----------------- | --------------- |
|
|
203
|
+
| `getEntityTypes` | `{}` | `entity-types` |
|
|
204
|
+
| `getEntityNames` | `{ entityType? }` | `entity-names` |
|
|
205
|
+
| `getServiceNames` | `{}` | `service-names` |
|
|
206
|
+
| `getEnvironments` | `{}` | `environments` |
|
|
207
|
+
| `getTags` | `{ entityType? }` | `tags` |
|
|
208
|
+
|
|
209
|
+
## Filtering
|
|
210
|
+
|
|
211
|
+
Every query accepts the same `filters` object. The most useful fields:
|
|
212
|
+
|
|
213
|
+
- `name`: Restrict to specific metric names. (Top-level `name` already does this for aggregate/breakdown/timeseries; use `filters.name` when you want to mix multiple metrics under a single query.)
|
|
214
|
+
- `timestamp`: `{ start, end, startExclusive, endExclusive }`. Both bounds are optional; omit `end` for "until now".
|
|
215
|
+
- `provider`, `model`, `costUnit`: For token and cost metrics.
|
|
216
|
+
- `labels`: Exact key-value match on metric labels, for example `{ status: 'error' }` for duration metrics.
|
|
217
|
+
- Correlation fields: `entityType`, `entityName`, `parentEntityName`, `rootEntityName`, `userId`, `organizationId`, `resourceId`, `runId`, `sessionId`, `threadId`, `requestId`, `executionSource`, `environment`, `serviceName`, `experimentId`, `tags`.
|
|
218
|
+
|
|
219
|
+
The same `filters` shape works across all three surfaces:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
// In-process
|
|
223
|
+
await observability!.getMetricAggregate({
|
|
224
|
+
name: ['mastra_tool_duration_ms'],
|
|
225
|
+
aggregation: 'avg',
|
|
226
|
+
filters: { entityName: 'weatherTool', labels: { status: 'error' } },
|
|
227
|
+
})
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# CLI
|
|
232
|
+
mastra api metric aggregate \
|
|
233
|
+
'{"name":["mastra_tool_duration_ms"],"aggregation":"avg","filters":{"entityName":"weatherTool","labels":{"status":"error"}}}' \
|
|
234
|
+
--url http://localhost:4111
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
# HTTP
|
|
239
|
+
curl -sS -X POST http://localhost:4111/api/observability/metrics/aggregate \
|
|
240
|
+
-H "content-type: application/json" \
|
|
241
|
+
-d '{"name":["mastra_tool_duration_ms"],"aggregation":"avg","filters":{"entityName":"weatherTool","labels":{"status":"error"}}}'
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Example: build a custom KPI tile
|
|
245
|
+
|
|
246
|
+
The following tool returns input-token volume and estimated cost for the last hour. An agent or a dashboard can call it as `structuredContent` without re-implementing the query.
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import { createTool } from '@mastra/core/tools'
|
|
250
|
+
import { z } from 'zod'
|
|
251
|
+
|
|
252
|
+
export const tokenKpiTool = createTool({
|
|
253
|
+
id: 'tokenKpi',
|
|
254
|
+
description: 'Returns input-token volume and estimated cost for the last hour.',
|
|
255
|
+
inputSchema: z.object({}),
|
|
256
|
+
outputSchema: z.object({
|
|
257
|
+
inputTokens: z.number().nullable(),
|
|
258
|
+
estimatedCost: z.number().nullable(),
|
|
259
|
+
costUnit: z.string().nullable(),
|
|
260
|
+
changePercent: z.number().nullable(),
|
|
261
|
+
}),
|
|
262
|
+
execute: async (_input, context) => {
|
|
263
|
+
const observability = await context.mastra!.getStorage()!.getStore('observability')
|
|
264
|
+
if (!observability) {
|
|
265
|
+
throw new Error('Observability domain is not configured (requires DuckDB or ClickHouse)')
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const result = await observability.getMetricAggregate({
|
|
269
|
+
name: ['mastra_model_total_input_tokens'],
|
|
270
|
+
aggregation: 'sum',
|
|
271
|
+
filters: {
|
|
272
|
+
timestamp: { start: new Date(Date.now() - 60 * 60 * 1000) },
|
|
273
|
+
},
|
|
274
|
+
comparePeriod: 'previous_period',
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
inputTokens: result.value,
|
|
279
|
+
estimatedCost: result.estimatedCost ?? null,
|
|
280
|
+
costUnit: result.costUnit ?? null,
|
|
281
|
+
changePercent: result.changePercent ?? null,
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
})
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Related
|
|
288
|
+
|
|
289
|
+
- [Metrics overview](https://mastra.ai/docs/observability/metrics/overview)
|
|
290
|
+
- [Automatic metrics reference](https://mastra.ai/reference/observability/metrics/automatic-metrics)
|
|
291
|
+
- [CLI: `mastra api metric ...`](https://mastra.ai/reference/cli/mastra)
|
|
292
|
+
- [Studio observability](https://mastra.ai/docs/studio/observability)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Fine-Grained Authorization (FGA)
|
|
2
2
|
|
|
3
|
+
> **Note:** Fine-Grained Authorization is part of the Mastra Enterprise Edition. Production deployments require a valid EE license. [Contact sales](https://mastra.ai/contact) for more information.
|
|
4
|
+
|
|
3
5
|
Fine-Grained Authorization (FGA) adds resource-level permission checks to your Mastra application. While RBAC answers "can this role do this action?", FGA answers **"can this user do this action on this specific resource?"**
|
|
4
6
|
|
|
5
7
|
## When to use FGA
|
|
@@ -686,6 +686,48 @@ await voiceAgent.voice.send(micStream)
|
|
|
686
686
|
|
|
687
687
|
Visit the [AWS Nova Sonic Reference](https://mastra.ai/reference/voice/aws-nova-sonic) for more information on the AWS Nova Sonic voice provider.
|
|
688
688
|
|
|
689
|
+
**Inworld Realtime**:
|
|
690
|
+
|
|
691
|
+
```typescript
|
|
692
|
+
import { Agent } from '@mastra/core/agent'
|
|
693
|
+
import { playAudio, getMicrophoneStream } from '@mastra/node-audio'
|
|
694
|
+
import { InworldRealtimeVoice } from '@mastra/voice-inworld'
|
|
695
|
+
|
|
696
|
+
const voiceAgent = new Agent({
|
|
697
|
+
id: 'voice-agent',
|
|
698
|
+
name: 'Voice Agent',
|
|
699
|
+
instructions: 'You are a voice assistant that can help users with their tasks.',
|
|
700
|
+
model: 'openai/gpt-5.4',
|
|
701
|
+
voice: new InworldRealtimeVoice({
|
|
702
|
+
apiKey: process.env.INWORLD_API_KEY,
|
|
703
|
+
model: 'inworld/models/gemma-4-26b-a4b-it',
|
|
704
|
+
speaker: 'Sarah',
|
|
705
|
+
}),
|
|
706
|
+
})
|
|
707
|
+
|
|
708
|
+
// Connect before using speak/send
|
|
709
|
+
await voiceAgent.voice.connect()
|
|
710
|
+
|
|
711
|
+
// Listen for agent audio (PCM stream)
|
|
712
|
+
voiceAgent.voice.on('speaker', stream => {
|
|
713
|
+
playAudio(stream)
|
|
714
|
+
})
|
|
715
|
+
|
|
716
|
+
// Listen for text responses and transcriptions
|
|
717
|
+
voiceAgent.voice.on('writing', ({ text, role }) => {
|
|
718
|
+
console.log(`${role}: ${text}`)
|
|
719
|
+
})
|
|
720
|
+
|
|
721
|
+
// Initiate the conversation
|
|
722
|
+
await voiceAgent.voice.speak('How can I help you today?')
|
|
723
|
+
|
|
724
|
+
// Send continuous audio from the microphone
|
|
725
|
+
const micStream = getMicrophoneStream()
|
|
726
|
+
await voiceAgent.voice.send(micStream)
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
Visit the [Inworld Realtime Reference](https://mastra.ai/reference/voice/inworld-realtime) for more information on the Inworld Realtime voice provider.
|
|
730
|
+
|
|
689
731
|
**xAI**:
|
|
690
732
|
|
|
691
733
|
```typescript
|
|
@@ -1051,6 +1093,26 @@ const voice = new NovaSonicVoice({
|
|
|
1051
1093
|
|
|
1052
1094
|
Visit the [AWS Nova Sonic Reference](https://mastra.ai/reference/voice/aws-nova-sonic) for more information on the AWS Nova Sonic voice provider.
|
|
1053
1095
|
|
|
1096
|
+
**Inworld Realtime**:
|
|
1097
|
+
|
|
1098
|
+
```typescript
|
|
1099
|
+
// Inworld Realtime Voice Configuration
|
|
1100
|
+
const voice = new InworldRealtimeVoice({
|
|
1101
|
+
apiKey: process.env.INWORLD_API_KEY,
|
|
1102
|
+
model: 'inworld/models/gemma-4-26b-a4b-it',
|
|
1103
|
+
speaker: 'Sarah',
|
|
1104
|
+
// Typed Inworld realtime knobs (semantic VAD, playback speed, MCP tool routing, ...)
|
|
1105
|
+
session: {
|
|
1106
|
+
audio: {
|
|
1107
|
+
output: { speed: 1.1 },
|
|
1108
|
+
input: { turn_detection: { type: 'semantic_vad', eagerness: 'high' } },
|
|
1109
|
+
},
|
|
1110
|
+
},
|
|
1111
|
+
})
|
|
1112
|
+
```
|
|
1113
|
+
|
|
1114
|
+
Visit the [Inworld Realtime Reference](https://mastra.ai/reference/voice/inworld-realtime) for more information on the Inworld Realtime voice provider.
|
|
1115
|
+
|
|
1054
1116
|
**AI SDK**:
|
|
1055
1117
|
|
|
1056
1118
|
```typescript
|
|
@@ -143,4 +143,55 @@ Note:
|
|
|
143
143
|
|
|
144
144
|
- Available regions: `us-east-1`, `us-west-2`, and `ap-northeast-1`.
|
|
145
145
|
- Authenticates through the standard AWS credential provider chain. Pass `credentials` to override.
|
|
146
|
-
- Events: `speaking` (Int16Array audio), `writing` (text with `generationStage`), `toolCall`, `interrupt`, `turnComplete`, `usage`, `session`, and `error`.
|
|
146
|
+
- Events: `speaking` (Int16Array audio), `writing` (text with `generationStage`), `toolCall`, `interrupt`, `turnComplete`, `usage`, `session`, and `error`.
|
|
147
|
+
|
|
148
|
+
## Inworld Realtime
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import { Agent } from '@mastra/core/agent'
|
|
152
|
+
import { InworldRealtimeVoice } from '@mastra/voice-inworld'
|
|
153
|
+
import { playAudio, getMicrophoneStream } from '@mastra/node-audio'
|
|
154
|
+
|
|
155
|
+
const agent = new Agent({
|
|
156
|
+
id: 'agent',
|
|
157
|
+
name: 'Inworld Realtime Agent',
|
|
158
|
+
instructions: 'You are a helpful assistant with real-time voice capabilities.',
|
|
159
|
+
// Model used for text generation; voice provider handles realtime audio
|
|
160
|
+
model: 'openai/gpt-5.4',
|
|
161
|
+
voice: new InworldRealtimeVoice({
|
|
162
|
+
apiKey: process.env.INWORLD_API_KEY,
|
|
163
|
+
model: 'inworld/models/gemma-4-26b-a4b-it',
|
|
164
|
+
speaker: 'Sarah',
|
|
165
|
+
// Typed Inworld realtime knobs (semantic VAD, playback speed, etc.)
|
|
166
|
+
// session: {
|
|
167
|
+
// audio: {
|
|
168
|
+
// output: { speed: 1.1 },
|
|
169
|
+
// input: { turn_detection: { type: 'semantic_vad', eagerness: 'high' } },
|
|
170
|
+
// },
|
|
171
|
+
// },
|
|
172
|
+
}),
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
await agent.voice.connect()
|
|
176
|
+
|
|
177
|
+
agent.voice.on('speaker', stream => {
|
|
178
|
+
playAudio(stream)
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
agent.voice.on('writing', ({ role, text }) => {
|
|
182
|
+
console.log(`${role}: ${text}`)
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
await agent.voice.speak('How can I help you today?')
|
|
186
|
+
|
|
187
|
+
const micStream = getMicrophoneStream()
|
|
188
|
+
await agent.voice.send(micStream)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Note:
|
|
192
|
+
|
|
193
|
+
- Requires `INWORLD_API_KEY`. Inworld API keys ship pre-Basic-encoded — paste them verbatim.
|
|
194
|
+
- The WebSocket URL appends a client-generated `?key=...&protocol=realtime`. The model is configured via the initial `session.update`, not in the URL.
|
|
195
|
+
- Inworld's wire protocol is the OpenAI Realtime GA spec, so event names match `@mastra/voice-openai-realtime`.
|
|
196
|
+
- Typed Inworld realtime knobs (MCP tool routing, semantic VAD eagerness, playback speed, transcription model, output modalities, …) are exposed through the `session` constructor field; an untyped `providerData` escape hatch is also deep-merged for forward compatibility with new Inworld features.
|
|
197
|
+
- Events: `speaker` (PCM audio stream), `speaking` (audio Buffer per delta), `writing` (text), `conversation.item.added`, `conversation.item.done`, `function_call.arguments`, `tool-call-start`, `tool-call-result`, and `error`.
|
|
@@ -16,6 +16,7 @@ A sandbox provider executes commands in a controlled environment:
|
|
|
16
16
|
## Supported providers
|
|
17
17
|
|
|
18
18
|
- [`LocalSandbox`](https://mastra.ai/reference/workspace/local-sandbox): Executes commands on the local machine
|
|
19
|
+
- [`AgentCoreRuntimeSandbox`](https://mastra.ai/reference/workspace/agentcore-runtime-sandbox): Executes commands in AWS Bedrock AgentCore Runtime sessions
|
|
19
20
|
- [`BlaxelSandbox`](https://mastra.ai/reference/workspace/blaxel-sandbox): Executes commands in isolated Blaxel cloud sandboxes
|
|
20
21
|
- [`DaytonaSandbox`](https://mastra.ai/reference/workspace/daytona-sandbox): Executes commands in isolated Daytona cloud sandboxes
|
|
21
22
|
- [`E2BSandbox`](https://mastra.ai/reference/workspace/e2b-sandbox): Executes commands in isolated E2B cloud sandboxes
|
|
@@ -118,9 +119,10 @@ Use `null` or `false` for cloud sandboxes (for example, E2B, Daytona, or Modal)
|
|
|
118
119
|
## Related
|
|
119
120
|
|
|
120
121
|
- [`SandboxProcessManager` reference](https://mastra.ai/reference/workspace/process-manager)
|
|
121
|
-
- [`
|
|
122
|
-
- [`ModalSandbox` reference](https://mastra.ai/reference/workspace/modal-sandbox)
|
|
122
|
+
- [`AgentCoreRuntimeSandbox` reference](https://mastra.ai/reference/workspace/agentcore-runtime-sandbox)
|
|
123
123
|
- [`DaytonaSandbox` reference](https://mastra.ai/reference/workspace/daytona-sandbox)
|
|
124
124
|
- [`E2BSandbox` reference](https://mastra.ai/reference/workspace/e2b-sandbox)
|
|
125
|
+
- [`LocalSandbox` reference](https://mastra.ai/reference/workspace/local-sandbox)
|
|
126
|
+
- [`ModalSandbox` reference](https://mastra.ai/reference/workspace/modal-sandbox)
|
|
125
127
|
- [Workspace overview](https://mastra.ai/docs/workspace/overview)
|
|
126
128
|
- [Filesystem](https://mastra.ai/docs/workspace/filesystem)
|
|
@@ -16,25 +16,25 @@ Install the Firecrawl SDK:
|
|
|
16
16
|
**npm**:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
npm install
|
|
19
|
+
npm install firecrawl
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
**pnpm**:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
pnpm add
|
|
25
|
+
pnpm add firecrawl
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
**Yarn**:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
yarn add
|
|
31
|
+
yarn add firecrawl
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
**Bun**:
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
bun add
|
|
37
|
+
bun add firecrawl
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
## Configure environment variables
|
|
@@ -53,7 +53,7 @@ Create a tool file that exposes Firecrawl search and scrape to Mastra.
|
|
|
53
53
|
1. Create `src/mastra/tools/firecrawl.ts` and set up Firecrawl:
|
|
54
54
|
|
|
55
55
|
```ts
|
|
56
|
-
import Firecrawl from '
|
|
56
|
+
import { Firecrawl } from 'firecrawl'
|
|
57
57
|
import { createTool } from '@mastra/core/tools'
|
|
58
58
|
import { z } from 'zod'
|
|
59
59
|
|
|
@@ -40,12 +40,12 @@ const embedder = new ModelRouterEmbeddingModel("google/gemini-embedding-001");
|
|
|
40
40
|
The model router automatically detects API keys from environment variables:
|
|
41
41
|
|
|
42
42
|
- **OpenAI**: `OPENAI_API_KEY`
|
|
43
|
-
- **Google**: `GOOGLE_GENERATIVE_AI_API_KEY`
|
|
43
|
+
- **Google**: `GOOGLE_API_KEY` (falls back to `GOOGLE_GENERATIVE_AI_API_KEY`)
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
46
|
# .env
|
|
47
47
|
OPENAI_API_KEY=sk-...
|
|
48
|
-
|
|
48
|
+
GOOGLE_API_KEY=...
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
## Custom Providers
|
|
@@ -96,9 +96,9 @@ export const agent = new Agent({
|
|
|
96
96
|
|
|
97
97
|
## Thread signals
|
|
98
98
|
|
|
99
|
-
Use Agent signals to send real-time context into a memory thread.
|
|
99
|
+
Use Agent signals to send real-time input and context into a memory thread. Message APIs are for user-authored input. `sendSignal()` is the lower-level API for system-generated context.
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
When the target thread is running, `sendMessage()` delivers the message into the active agent loop. When the thread is idle, Mastra starts a stream with the message as the first input by default.
|
|
102
102
|
|
|
103
103
|
```typescript
|
|
104
104
|
const subscription = await agent.subscribeToThread({
|
|
@@ -112,26 +112,22 @@ void (async () => {
|
|
|
112
112
|
}
|
|
113
113
|
})()
|
|
114
114
|
|
|
115
|
-
agent.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
streamOptions: {
|
|
122
|
-
maxSteps: 3,
|
|
123
|
-
},
|
|
115
|
+
agent.sendMessage('Use the latest customer note too.', {
|
|
116
|
+
resourceId: 'user-123',
|
|
117
|
+
threadId: 'thread-abc',
|
|
118
|
+
ifIdle: {
|
|
119
|
+
streamOptions: {
|
|
120
|
+
maxSteps: 3,
|
|
124
121
|
},
|
|
125
122
|
},
|
|
126
|
-
)
|
|
123
|
+
})
|
|
127
124
|
```
|
|
128
125
|
|
|
129
|
-
Use `attributes` to identify different users in a shared thread. The
|
|
126
|
+
Use `attributes` to identify different users in a shared thread. The attributes are rendered as XML so the model can distinguish who said what:
|
|
130
127
|
|
|
131
128
|
```typescript
|
|
132
|
-
agent.
|
|
129
|
+
agent.sendMessage(
|
|
133
130
|
{
|
|
134
|
-
type: 'user',
|
|
135
131
|
contents: 'Can we simplify the API surface?',
|
|
136
132
|
attributes: { name: 'Devin', from: 'slack' },
|
|
137
133
|
},
|
|
@@ -147,11 +143,44 @@ The model receives this as:
|
|
|
147
143
|
|
|
148
144
|
The UI sees just the message contents but can also read `attributes` and `metadata` off the signal message for custom rendering (e.g. showing user names, avatars, or platform badges).
|
|
149
145
|
|
|
146
|
+
### `sendMessage(message, options)`
|
|
147
|
+
|
|
148
|
+
Sends a user message to an active run or memory thread. Use this when the active agent should receive the message immediately.
|
|
149
|
+
|
|
150
|
+
**message** (`string | Array<TextPart | FilePart> | { contents: string | Array<TextPart | FilePart>; attributes?: Record<string, JSONValue>; metadata?: Record<string, unknown>; providerOptions?: ProviderMetadata }`): User-authored input. Bare strings and parts without attributes are sent to the model as normal user input. When \`attributes\` are present, Mastra renders the message as a \`\<user>\` XML element with the attributes included.
|
|
151
|
+
|
|
152
|
+
**options.runId** (`string`): Run ID to target directly. Use this when you already know the active run ID.
|
|
153
|
+
|
|
154
|
+
**options.resourceId** (`string`): Resource ID for the memory thread. Required with \`threadId\` for thread-targeted messages.
|
|
155
|
+
|
|
156
|
+
**options.threadId** (`string`): Thread ID to target. Required with \`resourceId\` for thread-targeted messages.
|
|
157
|
+
|
|
158
|
+
**options.ifActive.behavior** (`'deliver' | 'persist' | 'discard'`): Controls what happens when the target thread is active. Defaults to \`deliver\`.
|
|
159
|
+
|
|
160
|
+
**options.ifIdle.behavior** (`'wake' | 'persist' | 'discard'`): Controls what happens when the target thread is idle. Defaults to \`wake\`.
|
|
161
|
+
|
|
162
|
+
**options.ifIdle.streamOptions** (`AgentExecutionOptions`): Options for the stream that starts when \`ifIdle.behavior\` is \`wake\`. Mastra uses the top-level \`resourceId\` and \`threadId\` for memory context.
|
|
163
|
+
|
|
164
|
+
Returns `{ accepted: true, runId: string, signal: CreatedAgentSignal, persisted?: Promise<void> }`. `persisted` is only present for `persist` behavior and resolves when Mastra finishes writing the message to memory.
|
|
165
|
+
|
|
166
|
+
### `queueMessage(message, options)`
|
|
167
|
+
|
|
168
|
+
Queues a user message for the next turn on a thread. If the thread is active, Mastra waits for the active run to finish, then starts a new run with the queued message. If the thread is idle, Mastra starts a run immediately.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
agent.queueMessage('Also check whether the tests need updates.', {
|
|
172
|
+
resourceId: 'user-123',
|
|
173
|
+
threadId: 'thread-abc',
|
|
174
|
+
})
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
`queueMessage()` accepts the same `message` and `options` shape as `sendMessage()` and returns `{ accepted: true, runId: string, signal: CreatedAgentSignal, persisted?: Promise<void> }`.
|
|
178
|
+
|
|
150
179
|
### `sendSignal(signal, options)`
|
|
151
180
|
|
|
152
181
|
Sends a signal to an active run or memory thread.
|
|
153
182
|
|
|
154
|
-
**signal** (`{ type: 'user-message' | 'system-reminder'
|
|
183
|
+
**signal** (`{ type: 'user' | 'state' | 'reactive' | 'notification' | 'user-message' | 'system-reminder'; tagName?: string; contents: string | Array<TextPart | FilePart>; attributes?: Record<string, JSONValue>; metadata?: Record<string, unknown>; providerOptions?: ProviderMetadata }`): Signal context to send to the thread. \`type\` is the semantic signal category. \`tagName\` controls the XML tag the model sees. For example, \`{ type: 'notification', tagName: 'github-review' }\` renders as \`\<github-review>...\</github-review>\`. Legacy \`user-message\` and \`system-reminder\` payloads are still accepted and normalized. Unknown \`type\` values are rejected; use \`tagName\` for custom XML tags.
|
|
155
184
|
|
|
156
185
|
**options.runId** (`string`): Run ID to target directly. Use this when you already know the active run ID.
|
|
157
186
|
|
|
@@ -169,7 +198,7 @@ Returns `{ accepted: true, runId: string, signal: CreatedAgentSignal, persisted?
|
|
|
169
198
|
|
|
170
199
|
### `subscribeToThread(options)`
|
|
171
200
|
|
|
172
|
-
Subscribes to raw stream chunks for a memory thread. Use this before calling `sendSignal()` when you need to render stream output, observe signal echoes, or abort the active run.
|
|
201
|
+
Subscribes to raw stream chunks for a memory thread. Use this before calling `sendMessage()`, `queueMessage()`, or `sendSignal()` when you need to render stream output, observe signal echoes, or abort the active run.
|
|
173
202
|
|
|
174
203
|
**options.resourceId** (`string`): Resource ID for the memory thread.
|
|
175
204
|
|
package/.docs/reference/index.md
CHANGED
|
@@ -274,6 +274,7 @@ The Reference section provides documentation of Mastra's API, including paramete
|
|
|
274
274
|
- [Google](https://mastra.ai/reference/voice/google)
|
|
275
275
|
- [Google Gemini Live](https://mastra.ai/reference/voice/google-gemini-live)
|
|
276
276
|
- [Inworld](https://mastra.ai/reference/voice/inworld)
|
|
277
|
+
- [Inworld Realtime](https://mastra.ai/reference/voice/inworld-realtime)
|
|
277
278
|
- [Mastra Voice](https://mastra.ai/reference/voice/mastra-voice)
|
|
278
279
|
- [Murf](https://mastra.ai/reference/voice/murf)
|
|
279
280
|
- [OpenAI](https://mastra.ai/reference/voice/openai)
|
|
@@ -315,6 +316,7 @@ The Reference section provides documentation of Mastra's API, including paramete
|
|
|
315
316
|
- [.start()](https://mastra.ai/reference/workflows/run-methods/start)
|
|
316
317
|
- [.startAsync()](https://mastra.ai/reference/workflows/run-methods/startAsync)
|
|
317
318
|
- [.timeTravel()](https://mastra.ai/reference/workflows/run-methods/timeTravel)
|
|
319
|
+
- [AgentCoreRuntimeSandbox](https://mastra.ai/reference/workspace/agentcore-runtime-sandbox)
|
|
318
320
|
- [AgentFSFilesystem](https://mastra.ai/reference/workspace/agentfs-filesystem)
|
|
319
321
|
- [AzureBlobFilesystem](https://mastra.ai/reference/workspace/azure-blob-filesystem)
|
|
320
322
|
- [BlaxelSandbox](https://mastra.ai/reference/workspace/blaxel-sandbox)
|
|
@@ -329,6 +331,7 @@ The Reference section provides documentation of Mastra's API, including paramete
|
|
|
329
331
|
- [ModalSandbox](https://mastra.ai/reference/workspace/modal-sandbox)
|
|
330
332
|
- [S3Filesystem](https://mastra.ai/reference/workspace/s3-filesystem)
|
|
331
333
|
- [SandboxProcessManager](https://mastra.ai/reference/workspace/process-manager)
|
|
334
|
+
- [VercelMicroVMSandbox](https://mastra.ai/reference/workspace/vercel-microvm-sandbox)
|
|
332
335
|
- [VercelSandbox](https://mastra.ai/reference/workspace/vercel)
|
|
333
336
|
- [Workspace Class](https://mastra.ai/reference/workspace/workspace-class)
|
|
334
337
|
- [WorkspaceFilesystem](https://mastra.ai/reference/workspace/filesystem)
|
|
@@ -127,4 +127,10 @@ When you spot a spike in latency or token usage on the Metrics dashboard, correl
|
|
|
127
127
|
### Token metrics are missing
|
|
128
128
|
|
|
129
129
|
- **Span is a model generation**: Token metrics are only emitted from `MODEL_GENERATION` spans.
|
|
130
|
-
- **Provider reports usage**: The model provider must include `usage` data in its response. If usage is absent, no token metrics are emitted.
|
|
130
|
+
- **Provider reports usage**: The model provider must include `usage` data in its response. If usage is absent, no token metrics are emitted.
|
|
131
|
+
|
|
132
|
+
## Related
|
|
133
|
+
|
|
134
|
+
- [Metrics overview](https://mastra.ai/docs/observability/metrics/overview)
|
|
135
|
+
- [Querying metrics](https://mastra.ai/docs/observability/metrics/querying)
|
|
136
|
+
- [Studio observability](https://mastra.ai/docs/studio/observability)
|