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.
Don't use the AI SDK's registerTelemetry API (AI SDK v7 and above) together with this integration. vercelAIIntegration already instruments the AI SDK, so registering telemetry separately produces duplicate spans.
The integration is not enabled by default. Add it yourself:
Sentry.init({
dsn: "___PUBLIC_DSN___",
tracesSampleRate: 1.0,
integrations: [Sentry.vercelAIIntegration()],
});
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:
- The integration option — applies to every call.
- The call's
experimental_telemetry— applies to that call. 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.
Deno ignores recordInputs and recordOutputs on the integration. It accepts no error and logs no warning — your prompts are simply missing. Set both per call.
const result = await generateText({
model: openai("gpt-4o"),
experimental_telemetry: {
isEnabled: true,
recordInputs: true,
recordOutputs: true,
},
});
const result = await generateText({
model: openai("gpt-4o"),
experimental_telemetry: {
isEnabled: true,
recordInputs: true,
recordOutputs: true,
},
});
dataCollection: {} also turns recording on, but it opts you into the SDK's permissive defaults for every other category too: user identity, cookies, headers, HTTP bodies, query parameters, and stack-frame locals. Prefer the integration and per-call options above unless you want all of it. See dataCollection.
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:
const result = await generateText({
model: openai("gpt-4o"),
experimental_telemetry: { isEnabled: true },
});
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:
const result = await generateText({
model: openai("gpt-4o"),
experimental_telemetry: { isEnabled: false },
});
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:
const result = await generateText({
model: openai("gpt-4o"),
experimental_telemetry: {
functionId: "summarize-ticket",
},
});
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():
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?",
});
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.
Sentry.init({
integrations: [Sentry.vercelAIIntegration({ enableTruncation: false })],
});
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+
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").