Send traces from the AI SDK
Send traces of Vercel AI SDK calls, tool calls and agent steps.
This guide sends traces from a Node.js application that uses the Vercel AI SDK. Each generateText, streamText or agent call becomes a trace, with a span for each model call and tool call.
Before you start
You need an API key with the traces:write scope. Create one under Settings in the dashboard, or run div login.
Install the OpenTelemetry SDK and the OTLP exporter:
npm install @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-http @opentelemetry/resources
Set the exporter’s endpoint and key:
export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.divergentlabs.xyz/api/otlp
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20$DIVERGENT_API_KEY"
export OTEL_SERVICE_NAME=my-app
Register a tracer provider at startup, before any AI SDK call:
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
const provider = new NodeTracerProvider({
spanProcessors: [new BatchSpanProcessor(new OTLPTraceExporter())],
})
provider.register()
In a Next.js app, registerOTel from @vercel/otel in instrumentation.ts does the same.
AI SDK 7
-
Install the AI SDK’s OpenTelemetry integration.
npm install @ai-sdk/otel -
Register it once, after the tracer provider. Every AI SDK call is then traced.
import { registerTelemetry } from 'ai' import { OpenTelemetry } from '@ai-sdk/otel' registerTelemetry(new OpenTelemetry()) -
Name the call with
functionId. The trace takes the name of its first span,invoke_agent <model>, andfunctionIdis kept asgen_ai.agent.name.const result = await generateText({ model, prompt: 'What is the weather in Amsterdam?', telemetry: { functionId: 'answer-weather' }, })
To filter traces by session or user, run the call inside a span of your own that sets session.id and user.id. The AI SDK’s spans become its children:
import { trace } from '@opentelemetry/api'
await trace.getTracer('my-app').startActiveSpan('answer question', async (span) => {
span.setAttributes({ 'session.id': sessionId, 'user.id': userId })
await generateText({ model, prompt })
span.end()
})
AI SDK 5 and 6
Enable telemetry on each call. metadata.sessionId and metadata.userId become the trace’s session and user:
const result = await generateText({
model,
prompt: 'What is the weather in Amsterdam?',
experimental_telemetry: {
isEnabled: true,
functionId: 'answer-weather',
metadata: { sessionId, userId },
},
})
AI SDK 7’s LegacyOpenTelemetry integration writes the same attributes as AI SDK 5 and 6. Tracing reads both.
Keep content out of traces
Set recordInputs: false and recordOutputs: false in telemetry (AI SDK 7) or experimental_telemetry (AI SDK 5 and 6). Spans then carry the model, tokens and timings, and no prompts or completions.
AI SDK 5, 6 and 7’s LegacyOpenTelemetry record the headers passed to a call. Tracing drops them before a span is stored, except content-type, content-length and user-agent.
Tokens
An AI SDK trace has an outer span for the call and a span for each model call inside it, and the outer span repeats the usage of the calls inside it. Tracing counts a trace’s tokens from the model calls only, so a call that made two requests of 21 input tokens shows 42, not 84.