---
title: "Vercel AI"
description: "Adds instrumentation for Vercel AI SDK."
url: https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai/
---

# Vercel AI | Sentry for Next.js

*Import name: `Sentry.vercelAIIntegration`*

The `vercelAIIntegration` adds instrumentation for the [`ai`](https://www.npmjs.com/package/ai) SDK by Vercel to capture spans using the [AI SDK's built-in telemetry](https://sdk.vercel.ai/docs/ai-sdk-core/telemetry).

Don't use the AI SDK's `registerTelemetry` API (AI SDK v7 and above) together with this integration. `vercelAIIntegration` already instruments the AI SDK, so registering telemetry separately produces duplicate spans.

## [Runtime Differences](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#runtime-differences)

Next.js runs your server code in two runtimes. In both, you must pass `experimental_telemetry` on every call. See [Turn on telemetry](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#turn-on-telemetry).

Everything else depends on which runtime you're in:

|                           | Node runtime            | Edge runtime                        |
| ------------------------- | ----------------------- | ----------------------------------- |
| Enabled by default        | Yes                     | No — add it to `sentry.edge.config` |
| Record inputs and outputs | Integration or per call | Per call only                       |
| `force`                   | Available               | Not available — always active       |
| AI SDK v7                 | Supported               | Not supported                       |

## [Setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#setup)

### [Node Runtime](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#node-runtime)

The integration is enabled by default:

```javascript
Sentry.init({
  dsn: "https://<key>@o<orgId>.ingest.sentry.io/<projectId>",
  tracesSampleRate: 1.0,
});
```

### [Edge Runtime](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#edge-runtime)

The integration is not enabled by default. Add it yourself:

```javascript
Sentry.init({
  dsn: "https://<key>@o<orgId>.ingest.sentry.io/<projectId>",
  tracesSampleRate: 1.0,
  integrations: [Sentry.vercelAIIntegration()],
});
```

In both runtimes, adding the integration is not enough on its own. You must also pass `experimental_telemetry` on every call. See [Turn on telemetry](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#turn-on-telemetry).

If your spans have raw names like `ai.toolCall`, see [Troubleshooting](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#troubleshooting).

## [Record Inputs and Outputs](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#record-inputs-and-outputs)

Prompts and completions are not captured by default, because they usually contain user data. Turn recording on with `recordInputs` and `recordOutputs`.

Sentry resolves both settings in this order, and stops at the first one that is set:

1. The integration option — applies to every call.
2. The call's `experimental_telemetry` — applies to that call.
3. [`dataCollection.genAI`](https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options.md#dataCollection) — applies to every call.

The integration option wins over the call, not the other way around. If you set `recordInputs: false` on the integration, no call site can turn it back on.

Set the options on the integration to cover every call (Node runtime only). Re-adding the integration replaces the default instance and configures it:

```javascript
Sentry.init({
  dsn: "https://<key>@o<orgId>.ingest.sentry.io/<projectId>",
  tracesSampleRate: 1.0,
  integrations: [
    Sentry.vercelAIIntegration({
      recordInputs: true,
      recordOutputs: true,
    }),
  ],
});
```

The Edge runtime ignores `recordInputs` and `recordOutputs` on the integration. It accepts no error and logs no warning — your prompts are simply missing. Set both per call.

Or set them per call, which works in both runtimes:

```javascript
const result = await generateText({
  model: openai("gpt-4o"),
  experimental_telemetry: {
    isEnabled: true,
    recordInputs: true,
    recordOutputs: true,
  },
});
```

`dataCollection: {}` also turns recording on, but it opts you into the SDK's permissive defaults for every other category too: user identity, cookies, headers, HTTP bodies, query parameters, and stack-frame locals. Prefer the integration and per-call options above unless you want all of it. See [`dataCollection`](https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options.md#dataCollection).

## [Configure individual calls](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#configure-individual-calls)

Every instrumented `ai` function takes an `experimental_telemetry` object. Use it to control one call instead of all of them. For the full list of fields, see the [AI SDK telemetry metadata docs](https://sdk.vercel.ai/docs/ai-sdk-core/telemetry#telemetry-metadata).

### [Turn on Telemetry](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#turn-on-telemetry)

Required in both the Node and Edge runtimes.

Set `isEnabled` to `true` on every instrumented call. Without it, the AI SDK emits no spans and Sentry has nothing to capture:

```javascript
const result = await generateText({
  model: openai("gpt-4o"),
  experimental_telemetry: { isEnabled: true },
});
```

For `ToolLoopAgent`, set it on the constructor instead. See [ToolLoopAgent](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#toolloopagent).

### [Skip a Call](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#skip-a-call)

To capture no span for one call, set `isEnabled` to `false`:

```javascript
const result = await generateText({
  model: openai("gpt-4o"),
  experimental_telemetry: { isEnabled: false },
});
```

### [Identify Your Call Sites](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#identify-your-call-sites)

Spans carry the AI SDK function name, not yours, so a trace with several `generateText` calls is hard to read. Set `functionId` to label the call site. It appears on the span as `gen_ai.function_id`:

```javascript
const result = await generateText({
  model: openai("gpt-4o"),
  experimental_telemetry: {
    functionId: "summarize-ticket",
  },
});
```

### [ToolLoopAgent](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#toolloopagent)

The integration captures spans for the [`ToolLoopAgent`](https://ai-sdk.dev/docs/agents/overview#toolloopagent-class) class. Each call to `generate()` or `stream()` creates an agent span, with the individual LLM requests and tool executions as child spans.

`ToolLoopAgent` takes its telemetry settings on the constructor, not on `generate()` or `stream()`:

```javascript
const agent = new ToolLoopAgent({
  model: openai("gpt-4o"),
  tools: {
    /* ... */
  },
  experimental_telemetry: {
    isEnabled: true,
    functionId: "weather-agent",
  },
});

const result = await agent.generate({
  prompt: "What is the weather in San Francisco?",
});
```

## [Options](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#options)

Pass these to `Sentry.vercelAIIntegration()`. The Edge runtime accepts `enableTruncation` only.

### [`enableTruncation`](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#enabletruncation)

*Type: `boolean`*

Truncates recorded input messages so large payloads stay within span size limits. Affects inputs only, not outputs.

Defaults to `true`.

```javascript
Sentry.init({
  integrations: [Sentry.vercelAIIntegration({ enableTruncation: false })],
});
```

### [`force`](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#force)

*Type: `boolean`*

Registers the integration's span processors even when the `ai` module can't be detected. Set this when your build bundles `ai`, which defeats module detection. See [Troubleshooting](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#troubleshooting).

Defaults to `false`.

```javascript
Sentry.init({
  integrations: [Sentry.vercelAIIntegration({ force: true })],
});
```

`force` only registers the span processors. You still need `experimental_telemetry` on every call. Not available in the Edge runtime, where the integration is always active once you add it.

### [`recordInputs`](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#recordinputs)

*Type: `boolean`*

Records inputs to the `ai` function call. See [Record inputs and outputs](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#record-inputs-and-outputs) for the full resolution order and the per-call alternative.

### [`recordOutputs`](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#recordoutputs)

*Type: `boolean`*

Records outputs from the `ai` function call. See [Record inputs and outputs](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#record-inputs-and-outputs) for the full resolution order and the per-call alternative.

## [Supported Operations](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#supported-operations)

Spans are captured for these `ai` functions. Pass `experimental_telemetry` to each one, as described in [Turn on telemetry](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#turn-on-telemetry):

* `generateText()`
* `streamText()`
* `generateObject()`
* `streamObject()`
* `embed()`
* `embedMany()`
* `rerank()`

Plus `generate()` and `stream()` on [`ToolLoopAgent`](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#toolloopagent).

## [Supported Versions](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#supported-versions)

* `ai`: `>=3.0.0 <=7`

- Sentry SDK: `10.6.0`+
- Edge runtime: `ai` v7 is not supported. Use v6 or below, or run the call in the Node runtime.

## [Troubleshooting](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#troubleshooting)

Why do my AI spans show 'ai.toolCall' instead of 'gen\_ai.execute\_tool' on Vercel?

Raw names mean the AI SDK's telemetry is already on and emitting spans — Sentry's span processors just aren't registered to rename them. Add `force: true`:

```javascript
Sentry.init({
  dsn: "https://<key>@o<orgId>.ingest.sentry.io/<projectId>",
  integrations: [Sentry.vercelAIIntegration({ force: true })],
});
```

Keep `experimental_telemetry` on your calls. It's what produces the spans in the first place, so `force: true` without it leaves you with no AI spans at all. If only some of your spans have raw names, the remaining call sites are missing it:

```javascript
const result = await generateText({
  model: openai("gpt-4o"),
  experimental_telemetry: { isEnabled: true },
});
```

Why are my prompts and completions missing?

Recording is off unless you turn it on. Check, in order:

1. `recordInputs` and `recordOutputs` are set. See [Record inputs and outputs](https://docs.sentry.io/platforms/javascript/guides/nextjs/agent-tracing/vercelai.md#record-inputs-and-outputs).
2. You set them in a place the runtime reads. Some runtimes ignore the integration options and take them per call only.
3. No integration option is overriding your per-call value. The integration option wins.
