# 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

<Note>
  **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.
</Note>

Install the skill once in your coding-agent environment:

```bash theme={null}
npx skills add Voxmith/skills --skill voxmith
```

Run the framework-specific prompt below from the application root. Review the
resulting diff before deploying it.

```text theme={null}
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

```bash theme={null}
npm install voxmithai
```

```typescript theme={null}
import * 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?**

```bash theme={null}
npm install @mastra/observability @mastra/otel-exporter
```

### 2. 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:

```typescript theme={null}
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:

```typescript theme={null}
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

```typescript theme={null}
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 `conversationId` or `threadId`.
* **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 `OtelExporter` is included in the active Mastra observability config.
* Confirm `protocol: 'http/protobuf'` and `/v1/traces` are used.
* Confirm metadata keys are spelled `userId`, `conversationId`, or `threadId`.

### References

* [Enable OpenTelemetry export](https://mastra.ai/docs/observability/tracing/exporters/otel)
* [Add custom metadata](https://mastra.ai/docs/observability/tracing/overview)

## Next steps

* [Conversations](/using-conversations): review the complete Mastra interaction.
* [Events](/using-events): inspect agent and model activity.
* [Intents](/using-intents): organize production conversations by what users wanted.
