Skip to main content
Vercel AI SDK (3.3+) provides high-level helpers — generateText, streamText, generateObject — for calling LLMs from TypeScript apps. Arize AX captures every AI SDK call by ingesting the SDK’s native OpenTelemetry spans through the @arizeai/openinference-vercel span processor.

Prerequisites

  • Node.js 18+
  • An Arize AX account (sign up)
  • An OPENAI_API_KEY from the OpenAI Platform
  • Vercel AI SDK 3.3 or higher

Launch Arize AX

  1. Sign in to your Arize AX account.
  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

Pick the tab for your runtime — both install the same @arizeai/openinference-vercel processor and differ only in the OpenTelemetry registration helper.
This guide targets AI SDK v6 and earlier (ai@^6 with @ai-sdk/openai@^3). AI SDK v7 reworked how experimental_telemetry emits OpenTelemetry spans, so the wiring shown here does not produce spans on ai@7 — for v7, use the Vercel AI SDK v7 guide instead.Pin the processor to @arizeai/openinference-vercel@^2 as shown below. The latest major (@arizeai/openinference-vercel@3) targets AI SDK v7: it peer-depends on ai@^7 and @ai-sdk/otel, requires Node.js 22+, and ships ESM-only, so it does not work with this v6 setup.
npm install ai@^6 @ai-sdk/openai@^3 \
  @arizeai/openinference-vercel@^2 \
  @arizeai/openinference-semantic-conventions \
  @opentelemetry/api \
  @opentelemetry/exporter-trace-otlp-proto \
  @opentelemetry/resources \
  @opentelemetry/sdk-trace-node
Both runtimes wire the same OpenInferenceSimpleSpanProcessor from @arizeai/openinference-vercel — they differ only in how OpenTelemetry is registered, shown in the matching tab under Setup tracing. See Troubleshooting for the version-pinning rules.

Configure credentials

export ARIZE_SPACE_ID="<your-space-id>"
export ARIZE_API_KEY="<your-api-key>"
export ARIZE_PROJECT_NAME="vercel-ai-sdk-tracing-example"
export OPENAI_API_KEY="<your-openai-api-key>"

Setup tracing

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.
// 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 { SEMRESATTRS_PROJECT_NAME } from "@arizeai/openinference-semantic-conventions";

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

export const provider = new NodeTracerProvider({
  resource: resourceFromAttributes({
    [SEMRESATTRS_PROJECT_NAME]: 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();

console.log("Arize AX tracing initialized for Vercel AI SDK.");

Run Vercel AI SDK

// example.ts

// Importing instrumentation first ensures tracing is set up before the
// AI SDK is used.
import { provider } from "./instrumentation";

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

// `experimental_telemetry: { isEnabled: true }` is the AI SDK opt-in
// flag — without it, no spans are emitted no matter how OTel is wired.
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();
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; that opt-in flag is the only app-code change needed.

Expected output

Arize AX tracing initialized for Vercel AI SDK.
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-tracing-example.
  2. You should see a new trace within ~30 seconds containing an ai.generateText parent span wrapping an ai.generateText.doGenerate LLM child span (with prompt, response, and token usage attached).
  3. If no traces appear, see Troubleshooting.

Check from the skill, CLI, or SDK

Confirm spans are actually reaching your Arize AX project. Use whichever fits your workflow — the skill and CLI work for any framework; the SDK check is shown for each language.
Install the Arize Skills plugin and let your coding agent check for you:
npx skills add Arize-ai/arize-skills
Then prompt your agent:
Use the arize-trace skill to export and analyze recent traces from my project. Confirm spans are arriving, and summarize any errors or latency issues.

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 highest-level AI SDK span (ai.generateText, ai.streamText, …) becomes a clean trace root instead of pointing at a parent that was never exported.
new OpenInferenceSimpleSpanProcessor({
  exporter,
  spanFilter: isOpenInferenceSpan,
  reparentOrphanedSpans: true, // default: false
});

Troubleshooting

  • No traces in Arize AX. Every AI SDK call needs experimental_telemetry: { isEnabled: true } set on it — without that flag, the SDK never emits spans. Also confirm ARIZE_SPACE_ID and ARIZE_API_KEY are set in the same shell that runs example.ts. Enable OpenTelemetry debug logs with export OTEL_LOG_LEVEL=debug and re-run.
  • 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 (0.1.x for unstable APIs); @vercel/otel@2.x requires @opentelemetry/* 2.x (0.2.x). Mismatches surface as silent missing traces.
  • AI SDK spans orphaned on the Traces tab. Happens when isOpenInferenceSpan drops the HTTP root without re-rooting its children. Set reparentOrphanedSpans: true on the processor as shown in Span filter, and confirm @arizeai/openinference-vercel is 2.8.0 or later on the v2 line (@arizeai/openinference-vercel@^2). The v3 major targets AI SDK v7 and will not emit spans for this v6 setup.

Resources

Vercel AI SDK Documentation

OpenInference Vercel Span Processor

Vercel AI SDK GitHub