Vercel AI

Adds instrumentation for Vercel AI SDK.

Import name: Sentry.vercelAIIntegration

The vercelAIIntegration adds instrumentation for the ai SDK by Vercel to capture spans using the AI SDK's built-in telemetry.

The integration is not enabled by default. Add it yourself:

Copied
Sentry.init({
  dsn: "___PUBLIC_DSN___",
  tracesSampleRate: 1.0,
  integrations: [Sentry.vercelAIIntegration()],
});

Deno can't load OpenTelemetry instrumentation, so Sentry can't patch your call sites. Adding the integration is not enough on its own — you must also pass experimental_telemetry on every call. See Turn on telemetry.

Prompts and completions are not captured by default, because they usually contain user data. Turn recording on with recordInputs and recordOutputs.

Sentry resolves both settings in this order, and stops at the first one that is set:

  1. The integration option — applies to every call.
  2. The call's experimental_telemetry — applies to that call.
  3. dataCollection.genAI — applies to every call.

The integration option wins over the call, not the other way around. If you set recordInputs: false on the integration, no call site can turn it back on.

Copied
const result = await generateText({
  model: openai("gpt-4o"),
  experimental_telemetry: {
    isEnabled: true,
    recordInputs: true,
    recordOutputs: true,
  },
});

Every instrumented ai function takes an experimental_telemetry object. Use it to control one call instead of all of them. For the full list of fields, see the AI SDK telemetry metadata docs.

Set isEnabled to true on every instrumented call. Without it, the AI SDK emits no spans and Sentry has nothing to capture:

Copied
const result = await generateText({
  model: openai("gpt-4o"),
  experimental_telemetry: { isEnabled: true },
});

For ToolLoopAgent, set it on the constructor instead. See ToolLoopAgent.

To capture no span for one call, set isEnabled to false:

Copied
const result = await generateText({
  model: openai("gpt-4o"),
  experimental_telemetry: { isEnabled: false },
});

Spans carry the AI SDK function name, not yours, so a trace with several generateText calls is hard to read. Set functionId to label the call site. It appears on the span as gen_ai.function_id:

Copied
const result = await generateText({
  model: openai("gpt-4o"),
  experimental_telemetry: {
    functionId: "summarize-ticket",
  },
});

The integration captures spans for the ToolLoopAgent class. Each call to generate() or stream() creates an agent span, with the individual LLM requests and tool executions as child spans.

ToolLoopAgent takes its telemetry settings on the constructor, not on generate() or stream():

Copied
const agent = new ToolLoopAgent({
  model: openai("gpt-4o"),
  tools: {
    /* ... */
  },
  experimental_telemetry: {
    isEnabled: true,
    functionId: "weather-agent",
  },
});

const result = await agent.generate({
  prompt: "What is the weather in San Francisco?",
});

Pass these to Sentry.vercelAIIntegration(). Deno accepts enableTruncation only. It has no module detection to override, so force does not apply.

Type: boolean

Truncates recorded input messages so large payloads stay within span size limits. Affects inputs only, not outputs.

Defaults to true.

Copied
Sentry.init({
  integrations: [Sentry.vercelAIIntegration({ enableTruncation: false })],
});

Type: boolean

Records inputs to the ai function call. See Record inputs and outputs for the full resolution order and the per-call alternative.

Type: boolean

Records outputs from the ai function call. See Record inputs and outputs for the full resolution order and the per-call alternative.

Spans are captured for these ai functions. Pass experimental_telemetry to each one, as described in Turn on telemetry:

  • generateText()
  • streamText()
  • generateObject()
  • streamObject()
  • embed()
  • embedMany()
  • rerank()

Plus generate() and stream() on ToolLoopAgent.

  • ai: >=3.0.0 <=7
  • Sentry SDK: 10.12.0+

Why are my prompts and completions missing?

Recording is off unless you turn it on. Check, in order:

  1. recordInputs and recordOutputs are set. See Record inputs and outputs.
  2. You set them in a place the runtime reads. Some runtimes ignore the integration options and take them per call only.
  3. No integration option is overriding your per-call value. The integration option wins.
Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").