Mastra
Capture traces from Mastra agents with the Observability + OtelExporter API
Choose a setup method
| Method | Use it when |
|---|---|
| Voxmith skill | You want your coding agent to inspect the app, make the change, and verify it. |
| Voxmith SDK | You want explicit control over the interaction boundaries and fields. |
| OpenTelemetry | The framework already emits useful spans or you operate an OTel pipeline. |
Start with one method for a call path. Combining SDK tracking with framework OpenTelemetry on the same call can create duplicate interactions.
Recommended: Voxmith skill
Recommended. Choose this path when you want your coding agent to inspect the project, select a supported transport, make the smallest instrumentation change, send a test event, and verify that it reached Voxmith.
Install the skill once in your coding-agent environment:
npx skills add Voxmith/skills --skill voxmithRun the framework-specific prompt below from the application root. Review the resulting diff before deploying it.
Use the voxmith skill to add Voxmith analytics to this Mastra application.
Org ID: your-org-id
Instrument the real agent.generate() path and verify one fresh interaction.Manual setup: Voxmith SDK
npm install voxmithaiimport * as voxmith from 'voxmithai';
voxmith.init('your-org-id');
const interaction = voxmith.begin({ userId: 'u-42', agentName: 'mastra-support', input: prompt });
try {
const result = await agent.generate([{ role: 'user', content: prompt }]);
interaction.end(result.text);
} catch (error) {
interaction.end(String(error), false);
throw error;
} finally {
await voxmith.shutdown();
}Manual setup: OpenTelemetry
Mastra ships an OtelExporter that targets any OTLP endpoint. Wire it into your Mastra instance, then pass userId / conversationId per call.
1. Install
Already have @mastra/observability and @mastra/otel-exporter? Skip.
No Observability set up yet?
npm install @mastra/observability @mastra/otel-exporter2. Wire the OtelExporter pointing at Voxmith
Already have Mastra Observability? Append Voxmith to the existing exporters array: Mastra fans traces out to every exporter in the list:
import { OtelExporter } from '@mastra/otel-exporter';
const voxmithExporter = new OtelExporter({
provider: {
custom: {
endpoint: 'https://otel.voxmith.com/v1/traces',
headers: { 'X-Voxmith-Org-ID': process.env.VOXMITH_ORG_ID! },
protocol: 'http/protobuf',
},
},
});
// Inside your existing Observability config:
exporters: [
// ...your existing exporters,
voxmithExporter,
]No Observability yet? Full setup:
import { Mastra } from '@mastra/core';
import { Observability } from '@mastra/observability';
import { OtelExporter } from '@mastra/otel-exporter';
export const mastra = new Mastra({
agents: { agent },
observability: new Observability({
configs: {
default: {
serviceName: 'my-mastra-app',
exporters: [
new OtelExporter({
provider: {
custom: {
endpoint: 'https://otel.voxmith.com/v1/traces',
headers: { 'X-Voxmith-Org-ID': process.env.VOXMITH_ORG_ID! },
protocol: 'http/protobuf',
},
},
}),
],
},
},
}),
});3. Pass userId / conversationId per call
await agent.generate('Hello', {
tracingOptions: {
metadata: {
userId: 'user-42',
conversationId: 'conv-abc123',
},
},
});Reserved keys userId, conversationId, and threadId in tracingOptions.metadata are read by Voxmith for user / session grouping.
What appears in Voxmith
- Conversations grouped by
conversationIdorthreadId. - User-level analytics grouped by
userId. - Events for spans exported by Mastra.
Verify
Run one agent.generate call, then open Events in Voxmith. Confirm the span has your userId and conversationId.
Troubleshooting
- Confirm the
OtelExporteris included in the active Mastra observability config. - Confirm
protocol: 'http/protobuf'and/v1/tracesare used. - Confirm metadata keys are spelled
userId,conversationId, orthreadId.
References
Next steps
- Conversations: review the complete Mastra interaction.
- Events: inspect agent and model activity.
- Intents: organize production conversations by what users wanted.