> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bronto.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Send Vercel AI SDK traces to Bronto with OpenTelemetry

> Trace Vercel AI SDK 7 model calls, tool calls and agent runs with OpenTelemetry and send them to Bronto, from Next.js or Node.js, with token usage and AI Gateway cost.

The [Vercel AI SDK](https://ai-sdk.dev) (`ai`) is a TypeScript toolkit for model calls, tools and agents. It emits OpenTelemetry spans that follow the [GenAI semantic conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/): one span per call, per step, per model request and per tool call, with the model, token usage and tool names as `gen_ai.*` attributes. Since Vercel AI SDK 7, you register its OpenTelemetry integration once, and every call is traced. You don't need a Bronto-specific SDK.

> [!NOTE]
>
> This page was verified on **October 22, 2026** with `ai` 7.0.148, `@ai-sdk/otel` 1.0.148, `@vercel/otel` 2.1.3, Next.js 16.3 and Node.js 24. Vercel AI SDK 6 and earlier turned telemetry on per call with `experimental_telemetry`; in Vercel AI SDK 7 that name is a deprecated alias, and it creates no spans without the registration below.

## Prerequisites

* Vercel AI SDK 7 and Node.js 22 or later
* A Bronto API key with the **Ingestion** role (see [API Keys](/Account-Management/API-Keys.md))

## Set up

**Next.js**

Install the Vercel AI SDK's OpenTelemetry integration and `@vercel/otel`:

```bash theme={"dark"}
npm install ai @ai-sdk/otel @vercel/otel @opentelemetry/api
```

Register both in `instrumentation.ts`, in the project root or in `src/`:

```ts instrumentation.ts theme={"dark"}
import { OpenTelemetry } from "@ai-sdk/otel";
import { registerOTel } from "@vercel/otel";
import { registerTelemetry } from "ai";

export function register() {
  // The exporter reads OTEL_EXPORTER_OTLP_ENDPOINT and OTEL_EXPORTER_OTLP_HEADERS
  registerOTel({ serviceName: "my-ai-app" });
  registerTelemetry(new OpenTelemetry());
}
```

Set the exporter in the environment, on Vercel in the project's environment variables:

```bash theme={"dark"}
OTEL_EXPORTER_OTLP_ENDPOINT=https://ingestion.eu.bronto.io
OTEL_EXPORTER_OTLP_HEADERS=x-bronto-api-key=<YOUR_API_KEY>
```

The Vercel AI SDK's spans sit inside the route's span, next to the `fetch` spans that `@vercel/otel` records for each request to the model provider.

For more on `@vercel/otel` on Vercel, including trace context for services outside Vercel, see [OpenTelemetry in Vercel Functions](/integrations/vercel-otel.md).

**Node.js**

Install the Vercel AI SDK's OpenTelemetry integration and the OpenTelemetry Node.js SDK:

```bash theme={"dark"}
npm install ai @ai-sdk/otel @opentelemetry/sdk-node
```

Start the SDK and register the integration in an instrumentation module:

```js instrumentation.mjs theme={"dark"}
import { OpenTelemetry } from "@ai-sdk/otel";
import { NodeSDK } from "@opentelemetry/sdk-node";
import { registerTelemetry } from "ai";

// Reads OTEL_SERVICE_NAME and OTEL_EXPORTER_OTLP_* from the environment
export const sdk = new NodeSDK();
sdk.start();

registerTelemetry(new OpenTelemetry());
```

Load it before your application:

```bash theme={"dark"}
export OTEL_SERVICE_NAME=my-ai-app
export OTEL_EXPORTER_OTLP_ENDPOINT=https://ingestion.eu.bronto.io
export OTEL_EXPORTER_OTLP_HEADERS=x-bronto-api-key=<YOUR_API_KEY>
node --import ./instrumentation.mjs app.mjs
```

In a script that exits on its own, import `sdk` from the instrumentation module and call `await sdk.shutdown()` after the last Vercel AI SDK call, so the spans are exported before the process ends.

> [!TIP]
>
> Don't install `@opentelemetry/api` at a fixed version yourself. `@ai-sdk/otel` pins its own copy, and the current OpenTelemetry Node.js SDK needs a newer one; npm installs both, and the spans still reach the SDK.

Use `https://ingestion.us.bronto.io` for the US region. To send through an OpenTelemetry Collector instead, point `OTEL_EXPORTER_OTLP_ENDPOINT` at the Collector and see [Connect OpenTelemetry to Bronto](/agent-setup/open-telemetry.md).

## What you get

A `generateText` call with one tool call produces this trace:

```text theme={"dark"}
invoke_agent anthropic/claude-haiku-5.5    (the whole call)
  step 1
    chat anthropic/claude-haiku-5.5        (one per model request)
    execute_tool weather                   (one per tool call)
  step 2
    chat anthropic/claude-haiku-5.5
```

The most useful attributes:

| Attribute | On | What it holds |
| - | - | - |
| `gen_ai.operation.name` | all | `invoke_agent`, `chat` or `execute_tool` |
| `gen_ai.provider.name` | `invoke_agent`, `chat` | The provider, `gateway` for calls through the Vercel AI Gateway |
| `gen_ai.request.model` / `gen_ai.response.model` | `invoke_agent`, `chat` | Requested and served model |
| `gen_ai.agent.name` | `invoke_agent` | The call's `functionId` (see below) |
| `gen_ai.usage.input_tokens` / `gen_ai.usage.output_tokens` | `invoke_agent`, `chat` | Tokens, summed over all steps on `invoke_agent` |
| `gen_ai.usage.cache_read.input_tokens` / `gen_ai.usage.cache_creation.input_tokens` | `invoke_agent`, `chat` | Prompt-cache usage |
| `gen_ai.response.finish_reasons` | `invoke_agent`, `chat` | For example `tool-calls` or `stop` |
| `gen_ai.client.operation.duration` | `chat` | Duration of the model request, in seconds |
| `gen_ai.tool.name`, `gen_ai.tool.call.arguments`, `gen_ai.tool.call.result` | `execute_tool` | The tool and its input and output |
| `gen_ai.input.messages` / `gen_ai.output.messages` | `chat` | Prompt and reply |

See [LLM Observability](/ai-features/llm-observability.md#3-know-what-youll-see) for the field definitions and aggregation examples.

## Control what's recorded

The Vercel AI SDK records prompts, replies, and tool arguments and results by default. Set these per call in `telemetry`:

```ts theme={"dark"}
const result = await generateText({
  model: "anthropic/claude-haiku-5.5",
  prompt,
  telemetry: {
    functionId: "support-reply", // becomes gen_ai.agent.name
    recordInputs: false,         // no prompts or tool arguments
    recordOutputs: false,        // no replies or tool results
  },
});
```

`telemetry: { isEnabled: false }` leaves a call out entirely.

> [!WARNING]
>
> Recorded content is searchable by everyone with access to the dataset. If your prompts or tool results contain personal or regulated data, turn recording off for those calls.

### AI Gateway cost and routing

Calls through the [Vercel AI Gateway](https://vercel.com/docs/ai-gateway) return the gateway's cost and routing in the provider metadata. To record it on the `chat` spans, pass `providerMetadata: true`:

```ts theme={"dark"}
registerTelemetry(new OpenTelemetry({ providerMetadata: true }));
```

Each `chat` span then carries `ai.response.providerMetadata`, a JSON string with the provider's own usage details and a `gateway` object: `cost` in USD, the provider that served the request, and every provider attempt.

## Verify in Bronto

Send one request, then open [Explore Traces](/tracing/explore-traces.md) and filter by your `service.name`. Model calls are the spans named `chat <model>`. To select them in [Log Search](https://app.bronto.io/search):

```sql theme={"dark"}
"$gen_ai.operation.name" = 'chat'
```

Sum `$gen_ai.usage.input_tokens` and `$gen_ai.usage.output_tokens` grouped by `$gen_ai.request.model` to see token usage per model, or group by `$gen_ai.agent.name` to see it per feature.

## Troubleshooting

* **Only Next.js spans, no Vercel AI SDK spans:** `registerTelemetry(new OpenTelemetry())` is missing. In Vercel AI SDK 7, `telemetry` or `experimental_telemetry` options alone don't create spans.
* **No spans at all:** check that `instrumentation.ts` is in the project root (or in `src/`), and the endpoint and API key header. In Node.js, load the module with `--import` before the application.
* **Spans missing at the end of a script:** call `await sdk.shutdown()` before the process exits.
* **On Vercel with a trace drain:** a trace drain also forwards the spans your code creates, so with a direct export as well they arrive twice. See [OpenTelemetry in Vercel Functions](/integrations/vercel-otel.md#with-a-trace-drain-on-the-same-project).
* **Agents built with eve:** eve registers OpenTelemetry itself and traces its model and tool calls. Add a destination as shown in [Agents built with eve](/integrations/vercel-otel.md#agents-built-with-eve) instead.

## References

* [Vercel AI SDK telemetry](https://ai-sdk.dev/docs/ai-sdk-core/telemetry)
* [Vercel AI SDK 7 migration guide](https://ai-sdk.dev/docs/migration-guides/migration-guide-7-0)
* [OpenTelemetry GenAI semantic conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/)
* [LLM Observability](/ai-features/llm-observability.md)
* [Node.js](/opentelemetry/nodejs.md)
* [OpenTelemetry in Vercel Functions](/integrations/vercel-otel.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.