OpenInference JS
    Preparing search index...

    Module @arizeai/openinference-vercel

    OpenInference Vercel

    npm version

    This package provides utilities to transform Vercel AI SDK OpenTelemetry spans into OpenInference spans for platforms like Arize AX and Phoenix.

    Note: This package targets AI SDK v7 telemetry. Use @arizeai/openinference-vercel v2.x for AI SDK v6.

    AI SDK version Support level Notes
    v7.x Supported Uses @ai-sdk/otel OpenTelemetry, which emits gen_ai.* spans by default. Optional supplemental ai.* attributes fill non-GenAI data gaps.
    v6.x and older Unsupported Use @arizeai/openinference-vercel v2.x. AI SDK v6 used experimental_telemetry and emitted a different span shape.

    AI SDK v7 and this package require Node.js 22 or newer and are ESM-only. Configure your application accordingly before upgrading.

    npm install --save @arizeai/openinference-vercel
    

    You will also need OpenTelemetry, ai, @ai-sdk/otel, and the AI SDK provider package you use. The examples below use @ai-sdk/openai.

    npm i @arizeai/openinference-vercel ai@^7 @ai-sdk/otel@^1 @ai-sdk/openai@^4 @opentelemetry/api @opentelemetry/exporter-trace-otlp-proto @opentelemetry/resources @opentelemetry/sdk-trace-base @opentelemetry/sdk-trace-node @opentelemetry/semantic-conventions @arizeai/openinference-semantic-conventions
    

    For Next.js applications deployed on Vercel, also install @vercel/otel:

    npm i @vercel/otel
    

    @arizeai/openinference-vercel provides span processors that convert AI SDK v7 telemetry into OpenInference attributes before spans are exported. To get started, add OpenTelemetry to your application and register AI SDK telemetry once at application startup.

    For Next.js apps deployed on Vercel, registerOTel from @vercel/otel still registers the OpenTelemetry provider, resource attributes, exporters, and span processors. AI SDK v7's registerTelemetry(new OpenTelemetry(...)) does not replace that setup; it configures the AI SDK's telemetry integration.

    To process Vercel AI SDK spans, add OpenInferenceSimpleSpanProcessor or OpenInferenceBatchSpanProcessor to your OpenTelemetry configuration.

    Note

    The OpenInferenceSpanProcessor does not handle the exporting of spans by itself, pass it an exporter as a parameter.

    For a standalone TypeScript or Node.js application exporting to Phoenix, create an instrumentation module and import it before your AI SDK calls run.

    // instrumentation.ts
    import { SEMRESATTRS_PROJECT_NAME } from "@arizeai/openinference-semantic-conventions";
    import { OpenInferenceBatchSpanProcessor } from "@arizeai/openinference-vercel";

    import { OpenTelemetry } from "@ai-sdk/otel";
    import { diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
    import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
    import { Resource } from "@opentelemetry/resources";
    import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
    import { registerTelemetry } from "ai";

    // For troubleshooting, set the log level to DiagLogLevel.DEBUG.
    diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO);

    const phoenixUrl = process.env["PHOENIX_COLLECTOR_ENDPOINT"] ?? "http://localhost:6006/v1/traces";
    const phoenixApiKey = process.env["PHOENIX_API_KEY"];

    export const tracerProvider = new NodeTracerProvider({
    resource: new Resource({
    [SEMRESATTRS_PROJECT_NAME]: process.env["PHOENIX_PROJECT_NAME"] ?? "my-typescript-app",
    }),
    spanProcessors: [
    new OpenInferenceBatchSpanProcessor({
    exporter: new OTLPTraceExporter({
    url: phoenixUrl,
    headers: phoenixApiKey
    ? {
    api_key: phoenixApiKey,
    Authorization: `Bearer ${phoenixApiKey}`,
    }
    : undefined,
    }),
    }),
    ],
    });

    tracerProvider.register();

    registerTelemetry(
    new OpenTelemetry({
    // Optional, but recommended for fuller OpenInference coverage.
    usage: true,
    providerMetadata: true,
    embedding: true,
    reranking: true,
    runtimeContext: true,
    headers: true,
    toolChoice: true,
    schema: true,
    }),
    );

    Then import the instrumentation module before using the AI SDK.

    import "./instrumentation";

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

    const result = await generateText({
    model: openai("gpt-4o-mini"),
    prompt: "Write a short story about a cat.",
    // Telemetry is enabled by default once OpenTelemetry is registered.
    // Use telemetry for per-call metadata or to opt out with isEnabled: false.
    telemetry: { functionId: "story-agent" },
    });
    // instrumentation.ts
    import { registerOTel } from "@vercel/otel";
    import { registerTelemetry } from "ai";
    import { OpenTelemetry } from "@ai-sdk/otel";
    import {
    isOpenInferenceSpan,
    OpenInferenceSimpleSpanProcessor,
    } from "@arizeai/openinference-vercel";
    import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
    import { SEMRESATTRS_PROJECT_NAME } from "@arizeai/openinference-semantic-conventions";

    export function register() {
    const phoenixApiKey = process.env["PHOENIX_API_KEY"];

    registerTelemetry(
    new OpenTelemetry({
    // Optional, but recommended for fuller OpenInference coverage.
    usage: true,
    providerMetadata: true,
    embedding: true,
    reranking: true,
    runtimeContext: true,
    headers: true,
    toolChoice: true,
    schema: true,
    }),
    );

    registerOTel({
    serviceName: "phoenix-next-app",
    attributes: {
    // This is not required but it will ensure your traces get added to a specific project in Arize Phoenix
    [SEMRESATTRS_PROJECT_NAME]: "your-next-app",
    },
    spanProcessors: [
    new OpenInferenceSimpleSpanProcessor({
    exporter: new OTLPTraceExporter({
    headers: phoenixApiKey
    ? {
    api_key: phoenixApiKey,
    Authorization: `Bearer ${phoenixApiKey}`,
    }
    : undefined,
    url:
    process.env["PHOENIX_COLLECTOR_ENDPOINT"] ?? "https://app.phoenix.arize.com/v1/traces",
    }),
    spanFilter: (span) => {
    // Remove this filter if you want to export non-generative spans too.
    return isOpenInferenceSpan(span);
    },
    }),
    ],
    });
    }

    Once registerTelemetry(new OpenTelemetry()) is called, AI SDK v7 telemetry is enabled by default. Use telemetry only for metadata such as functionId or to opt out.

    const result = await generateText({
    model: openai("gpt-4-turbo"),
    prompt: "Write a short story about a cat.",
    telemetry: { functionId: "story-agent" },
    });

    To disable telemetry for a single call, set telemetry: { isEnabled: false }.

    For details on AI SDK v7 telemetry, see the AI SDK telemetry documentation.

    For more information on Vercel OpenTelemetry support, see the Vercel OpenTelemetry guide.

    When you filter with spanFilter: isOpenInferenceSpan, only AI-related spans are exported. But the highest-level AI span (e.g. ai.generateText, ai.streamText) is frequently parented under a non-AI span — for example the HTTP/server span that Next.js parents everything under. That parent is filtered out, leaving the AI span orphaned: it references a parent that was never exported, so backends may not be able to render the trace correctly.

    Set reparentOrphanedSpans: true to detach (re-root) any AI span whose direct parent is a non-AI span, so it becomes a trace root. Multiple sibling AI spans in the same trace are each re-rooted, and AI spans nested under an AI parent keep their place.

    new OpenInferenceSimpleSpanProcessor({
    exporter,
    spanFilter: isOpenInferenceSpan,
    reparentOrphanedSpans: true, // default: false
    });

    The check is stateless — the parent span is read from the start-time context, so no per-trace bookkeeping is kept.

    If the re-rooted span is an ai.* framework wrapper that the package doesn't map to a span kind (for example a per-turn span an agent framework emits on top of the AI SDK), it would otherwise be kind-less and dropped by the filter. Such a root is tagged openinference.span.kind = AGENT so it is kept as the trace root. This is matched by shape (an unrecognized AI-like root), not by any specific framework span name.

    reparentOrphanedSpans is opt-in (default false). It is intended for use alongside a filter that drops non-AI parent spans — which is exactly the situation that orphans the AI children in the first place: when the filter removes a non-AI parent, every AI span beneath it is left pointing at a parent that was never exported. Reparenting re-roots those children so the trace still renders. (Conversely, without such a filter the non-AI parent is still exported, so there is nothing to orphan, and reparenting would only split an otherwise-intact trace.)

    The Vercel AI SDK creates its own spans, so — unlike the OpenInference instrumentors, which build spans through an OITracer — this processor does not read the OpenInference context. That means values you set with the @arizeai/openinference-core helpers (setSession, setUser, setMetadata, setTags) never reach the exported AI spans. A session.id set around a call like this would otherwise be lost:

    import { context } from "@opentelemetry/api";
    import { setSession } from "@arizeai/openinference-core";

    context.with(setSession(context.active(), { sessionId }), () =>
    streamText({ model, prompt, experimental_telemetry: { isEnabled: true } }),
    );

    propagateContextAttributes copies every OpenInference attribute on the start-time context (session.id, user.id, metadata.*, tag.tags, …) directly onto each span at onStart, so traces group into sessions in Arize / Phoenix. It is enabled by default; set it to false to opt out.

    new OpenInferenceSimpleSpanProcessor({
    exporter,
    spanFilter: isOpenInferenceSpan,
    reparentOrphanedSpans: true,
    propagateContextAttributes: true, // default: true
    });

    Because the values are written directly onto the span, they survive both reparentOrphanedSpans re-rooting and export, and spans started in the same context (child model/tool calls) inherit them.

    Modules

    AISemanticConventions
    constants
    contextPropagation
    index
    OpenInferenceSpanProcessor
    reparenting
    TraceAggregateManager
    types
    typeUtils
    utils
    VercelAISemanticConventions