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

# Vercel AI SDK v7

> Trace Vercel AI SDK v7 calls with the @ai-sdk/otel telemetry integration and send OpenInference spans to Arize AX.

[Vercel AI SDK](https://github.com/vercel/ai) v7 calls LLMs from TypeScript through helpers like `generateText`, `streamText`, and `generateObject`. Unlike v6 — which wrote OpenTelemetry spans to the global tracer directly — **v7 moved telemetry to a pluggable "integrations" model**: the SDK emits internal telemetry events, and a registered integration turns them into spans. Vercel ships [`@ai-sdk/otel`](https://www.npmjs.com/package/@ai-sdk/otel) as the OpenTelemetry integration. Arize AX then ingests those spans through the [`@arizeai/openinference-vercel`](https://github.com/Arize-ai/openinference/tree/main/js/packages/openinference-vercel) span processor.

<Note>
  If you're on **AI SDK v6 or earlier**, use the [Vercel AI SDK (v6 and earlier)](/ax/integrations/ts-js-agent-frameworks/vercel/vercel-ai-sdk-tracing) guide instead — v6 emits OpenTelemetry spans natively and does not need `@ai-sdk/otel`. The two SDK versions wire telemetry differently, so the setup is not interchangeable.
</Note>

## Prerequisites

* Node.js 22+ (required by `@arizeai/openinference-vercel@3` and `@ai-sdk/otel`)
* An Arize AX account ([sign up](https://arize.com/sign-up/))
* An `OPENAI_API_KEY` from the [OpenAI Platform](https://platform.openai.com/api-keys)
* Vercel AI SDK 7 (`ai@^7`)

## Launch Arize AX

1. Sign in to your [Arize AX account](https://app.arize.com/).
2. From **Space Settings**, copy your **Space ID** and **API Key**. You will set them as `ARIZE_SPACE_ID` and `ARIZE_API_KEY` below.

## Install

Install the AI SDK v7, the `@ai-sdk/otel` telemetry integration, and the OpenInference processor. Pick the tab for your runtime — they differ only in the OpenTelemetry registration helper.

<Tabs>
  <Tab title="Node.js">
    ```bash theme={null}
    npm install ai@^7 @ai-sdk/openai@^4 @ai-sdk/otel \
      @arizeai/openinference-vercel@^3 \
      @opentelemetry/api \
      @opentelemetry/exporter-trace-otlp-proto \
      @opentelemetry/resources \
      @opentelemetry/sdk-trace-node
    ```
  </Tab>

  <Tab title="Next.js">
    ```bash theme={null}
    npm install ai@^7 @ai-sdk/openai@^4 @ai-sdk/otel \
      @arizeai/openinference-vercel@^3 \
      @vercel/otel \
      @opentelemetry/api \
      @opentelemetry/exporter-trace-otlp-proto
    ```
  </Tab>
</Tabs>

<Note>
  `@ai-sdk/otel` is the piece that makes v7 emit spans at all. Without a registered telemetry integration, `experimental_telemetry: { isEnabled: true }` enables the SDK's telemetry events but nothing converts them to OpenTelemetry spans, so nothing reaches Arize.
</Note>

## Configure credentials

```bash theme={null}
export ARIZE_SPACE_ID="<your-space-id>"
export ARIZE_API_KEY="<your-api-key>"
export ARIZE_PROJECT_NAME="vercel-ai-sdk-v7-tracing-example"
export OPENAI_API_KEY="<your-openai-api-key>"
```

## Setup tracing

Register the OpenTelemetry provider **and** the `@ai-sdk/otel` integration in one startup file. `registerTelemetry(new OpenTelemetry())` (from `ai` and `@ai-sdk/otel`) installs the integration globally, so individual `generateText`/`streamText` calls only need the `experimental_telemetry: { isEnabled: true }` opt-in. Pick the tab that matches your runtime. The processor's `spanFilter` and `reparentOrphanedSpans` options control which spans reach Arize and how each trace is rooted — see [Span filter](#span-filter).

<Tabs>
  <Tab title="Node.js">
    ```typescript theme={null}
    // instrumentation.ts
    import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
    import { resourceFromAttributes } from "@opentelemetry/resources";
    import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
    import {
      isOpenInferenceSpan,
      OpenInferenceSimpleSpanProcessor,
    } from "@arizeai/openinference-vercel";
    import { registerTelemetry } from "ai";
    import { OpenTelemetry } from "@ai-sdk/otel";

    const projectName =
      process.env.ARIZE_PROJECT_NAME ?? "vercel-ai-sdk-v7-tracing-example";

    export const provider = new NodeTracerProvider({
      resource: resourceFromAttributes({
        model_id: projectName,
        model_version: "1.0.0",
      }),
      spanProcessors: [
        new OpenInferenceSimpleSpanProcessor({
          exporter: new OTLPTraceExporter({
            url: "https://otlp.arize.com/v1/traces",
            headers: {
              "arize-space-id": process.env.ARIZE_SPACE_ID ?? "",
              "arize-api-key": process.env.ARIZE_API_KEY ?? "",
            },
          }),
          spanFilter: isOpenInferenceSpan,
          reparentOrphanedSpans: true,
        }),
      ],
    });

    provider.register();

    // v7: bridge the AI SDK's telemetry events to OpenTelemetry spans. Register
    // once, globally — `experimental_telemetry: { isEnabled: true }` on each call
    // is then all that's needed.
    registerTelemetry(new OpenTelemetry());

    console.log("Arize AX tracing initialized for Vercel AI SDK v7.");
    ```
  </Tab>

  <Tab title="Next.js">
    In Next.js, use `@vercel/otel`'s `registerOTel` from a root-level `instrumentation.ts` (alongside `package.json`, or in `src/` if you use that layout). Next.js calls the exported `register()` function **once on the server, before any request**, so you do not create a `NodeTracerProvider` or call `forceFlush()` yourself.

    ```typescript theme={null}
    // instrumentation.ts (project root)
    import { registerOTel } from "@vercel/otel";
    import {
      isOpenInferenceSpan,
      OpenInferenceSimpleSpanProcessor,
    } from "@arizeai/openinference-vercel";
    import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
    import { registerTelemetry } from "ai";
    import { OpenTelemetry } from "@ai-sdk/otel";

    export function register() {
      registerOTel({
        serviceName:
          process.env.ARIZE_PROJECT_NAME ?? "vercel-ai-sdk-v7-tracing-example",
        spanProcessors: [
          new OpenInferenceSimpleSpanProcessor({
            exporter: new OTLPTraceExporter({
              url: "https://otlp.arize.com/v1/traces",
              headers: {
                "arize-space-id": process.env.ARIZE_SPACE_ID ?? "",
                "arize-api-key": process.env.ARIZE_API_KEY ?? "",
              },
            }),
            spanFilter: isOpenInferenceSpan,
            reparentOrphanedSpans: true,
          }),
        ],
      });

      // v7: bridge the AI SDK's telemetry events to OpenTelemetry spans.
      registerTelemetry(new OpenTelemetry());
    }
    ```

    <Note>
      **Serverless flushing.** `OpenInferenceSimpleSpanProcessor` exports each span synchronously as it ends, so it does not depend on a process-exit flush — this is what makes it safe on short-lived serverless routes (Vercel functions, edge) where you can't call `forceFlush()`. Keep `SimpleSpanProcessor` rather than `BatchSpanProcessor` in those environments; batching can drop spans when the function freezes between invocations.
    </Note>
  </Tab>
</Tabs>

## Run Vercel AI SDK

```typescript theme={null}
// example.ts

// Importing instrumentation first ensures the OTel provider and the
// @ai-sdk/otel integration are registered before the AI SDK is used.
import { provider } from "./instrumentation";

import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";

// `experimental_telemetry: { isEnabled: true }` opts this call into the AI
// SDK's telemetry; the integration registered in instrumentation.ts turns
// those events into OpenTelemetry spans.
const { text } = await generateText({
  model: openai("gpt-5.5"),
  prompt: "Why is the ocean salty? Answer in two sentences.",
  experimental_telemetry: { isEnabled: true },
});

console.log(text);

// Flush any pending spans before the process exits.
await provider.forceFlush();
```

<Note>
  This is a standalone Node script. In **Next.js**, you don't import `provider` or call `forceFlush()` — the root `instrumentation.ts` registers tracing automatically. Just add `experimental_telemetry: { isEnabled: true }` to the `generateText`/`streamText` calls inside your route handlers or server actions.
</Note>

### Expected output

```text wrap theme={null}
Arize AX tracing initialized for Vercel AI SDK v7.
The ocean is salty because rivers continuously dissolve mineral salts from rocks and soil and carry them to the sea, where they accumulate over millions of years. Water leaves the ocean through evaporation but the salts remain, steadily concentrating until reaching today's roughly 3.5% salinity.
```

## Verify in Arize AX

1. Open your Arize AX space and select project **`vercel-ai-sdk-v7-tracing-example`**.
2. Within \~30 seconds you should see a trace for the call. v7 names its spans with the GenAI convention rather than the v6 `ai.generateText` names — the OpenInference processor classifies them by **span kind**, which is what you read in the UI:

```text theme={null}
invoke_agent gpt-5.5   [agent]        the generateText call
  └─ step 1            [llm]          the step
       └─ chat gpt-5.5  [llm]         model request (prompt, response, tokens)
```

The top **agent** span carries the call; the `chat` **LLM** span holds the prompt, the model's response, and token usage. Tool calls appear as additional **tool** spans under the step.

1. If no traces appear, see [Troubleshooting](#troubleshooting).

## Span filter

Other instrumentations registered alongside the AI SDK (`@opentelemetry/instrumentation-http`, `@vercel/otel`, Next.js's built-in tracing) emit `POST` / `GET` spans for every fetch, and the AI SDK's spans nest under those HTTP roots. Two options on the processor control which spans reach Arize and how they're rooted:

* **`spanFilter: isOpenInferenceSpan`** keeps only the AI spans and drops the rest — the raw HTTP/fetch spans those other instrumentations emit.
* **`reparentOrphanedSpans: true`** re-roots any AI span left orphaned when the filter drops its parent, so the top-level call span becomes a clean trace root instead of pointing at a parent that was never exported.

```typescript theme={null}
new OpenInferenceSimpleSpanProcessor({
  exporter,
  spanFilter: isOpenInferenceSpan,
  reparentOrphanedSpans: true, // default: false
});
```

## Troubleshooting

* **No traces in Arize AX.** v7 emits no spans unless a telemetry integration is registered — confirm `@ai-sdk/otel` is installed and `registerTelemetry(new OpenTelemetry())` runs in your `instrumentation.ts`. Each call also needs `experimental_telemetry: { isEnabled: true }`. Confirm `ARIZE_SPACE_ID` and `ARIZE_API_KEY` are set in the same shell, and enable debug logs with `export OTEL_LOG_LEVEL=debug`.
* **`401` from OpenAI.** Verify `OPENAI_API_KEY` is set and has access to `gpt-5.5`. Swap `openai("gpt-5.5")` for a model your key can call.
* **Process exits before spans flush.** Always `await provider.forceFlush()` (or `provider.shutdown()`) before the process exits, otherwise trailing spans are dropped.
* **Next.js / Vercel runtime.** Use `@vercel/otel`'s `registerOTel(...)` instead of `NodeTracerProvider`, and pin versions: `@vercel/otel@1.x` requires `@opentelemetry/*` `1.x`; `@vercel/otel@2.x` requires `2.x`. Mismatches surface as silent missing traces.
* **AI SDK spans orphaned on the Traces tab.** Set `reparentOrphanedSpans: true` on the processor as shown in [Span filter](#span-filter), and confirm `@arizeai/openinference-vercel` is **3.0.0 or later** — stable v7 telemetry support (and the v7-aware reparenting) landed in the v3 major.
* **You want the v6 span names.** `@ai-sdk/otel` also exports a `LegacyOpenTelemetry` integration that emits the older `ai.generateText` / `ai.generateText.doGenerate` span names; register it in place of `OpenTelemetry` if you have dashboards or evaluators keyed on those names.

## Resources

<CardGroup>
  <Card icon="book-open" href="https://sdk.vercel.ai/docs" title="Vercel AI SDK Documentation" horizontal />

  <Card icon="terminal" href="https://www.npmjs.com/package/@ai-sdk/otel" title="@ai-sdk/otel" horizontal />

  <Card icon="terminal" href="https://github.com/Arize-ai/openinference/tree/main/js/packages/openinference-vercel" title="OpenInference Vercel Span Processor" horizontal />
</CardGroup>
