Vercel AI SDK

Pass bc.telemetry() as the AI SDK’s experimental_telemetry. Breadcrumb reads the ai.* and gen_ai.* attributes the SDK emits — model, provider, token usage (including cache and reasoning tokens), inputs, and outputs.

const { text } = await streamText({
  model: openai("gpt-5"),
  prompt,
  experimental_telemetry: bc.telemetry({
    functionId: "generate-answer",
    userId,
    sessionId,
    metadata: { plan: "pro" },
  }),
});

functionId names the call and is what cost is attributed to — it holds wherever the call sits, including under a span from some other tracer (Sentry, Langfuse, an HTTP middleware). userId and sessionId group traces by user and by conversation; anything else goes in metadata.

Usage is counted once per model call, even across multi-step tool loops — the outer wrapper spans the SDK emits are treated as duplicates, not double-counted.

If you already have OpenTelemetry

Apps with their own tracer provider can skip bc.telemetry() entirely: register bc.spanProcessor once and plain { isEnabled: true, functionId } is enough.

Next steps