# Track Vercel AI SDK costs and LLM calls in Next.js

> Add LLM cost tracking to your Next.js app with Sentry, and see Vercel AI SDK token usage, per-model costs, tool calls, and agent traces with full-stack context

**URL:** https://sentry.io/cookbook/monitor-ai-agent-costs-nextjs/

---

Add Sentry to your Next.js app to see Vercel AI SDK token usage, LLM costs, tool calls, and agent traces with full-stack trace context. Spot which models drive spend without leaving Sentry.

**Time:** 10–15 minutes | **Difficulty:** Beginner

## What You'll Learn

- Configured Sentry tracing in your Next.js app

- Turned on automatic LLM instrumentation with the Vercel AI integration

- Named your AI SDK calls and grouped the turns of each chat into one conversation

- Found the cost, tool calls, and errors of each conversation in Explore → Agents

- Read a conversation turn by turn and followed it into the full trace

**Topics:** AI Observability, Tracing, Agent Tracing

**SDKs:** Next.js

## Before you start

**SDKs & packages**

- A [Next.js](https://nextjs.org) 14+ app (App Router recommended) with Sentry set up, on `@sentry/nextjs` 11 or later. If Sentry isn't set up yet, follow the [Next.js setup guide](https://docs.sentry.io/platforms/javascript/guides/nextjs/) first

- [Vercel AI SDK](https://ai-sdk.dev/) installed (`ai` package)

- Node.js 22+ if you're on AI SDK 7

**Accounts & access**

- [Sentry account](https://sentry.io/signup/) with a Next.js project created

**Knowledge**

- Basic familiarity with Next.js API routes or Route Handlers

- Basic understanding of the Vercel AI SDK (`streamText`, `generateText`)

## Steps

### 1. Enable tracing

Open `sentry.server.config.ts` and make sure `tracesSampleRate` is greater than zero. In Sentry JavaScript SDK v11, `vercelAIIntegration` is enabled by default once tracing is on, so you don't need to add it yourself. Add it to `integrations` only if you want to change its options, like turning off input and output recording.

```typescript
import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  // Tracing must be on. vercelAIIntegration is enabled by default.
  tracesSampleRate: 1.0,
});
```

[Vercel AI integration options](https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/integrations/vercelai/)

### 2. Name your AI SDK calls and set a conversation ID

In any Route Handler that uses the Vercel AI SDK, add a `functionId` to the `telemetry` option of your `streamText` or `generateText` call. Sentry uses it as the agent name, so you can find and filter each agent in Explore → Agents. On AI SDK 6 and earlier, the option is called `experimental_telemetry`.

Then call `Sentry.setConversationId()` with the chat ID. `useChat` sends the same `id` with each message of a chat, and Sentry uses it to group all turns of that chat into one conversation.

Sentry records the full prompts and completions by default. To turn this off for one route, set `recordInputs` and `recordOutputs` to `false` in that call's `telemetry` option. Keep these routes on the Node.js runtime, because Sentry doesn't instrument AI calls on the Edge runtime.

```typescript
import * as Sentry from '@sentry/nextjs';
import { convertToModelMessages, streamText, type UIMessage } from 'ai';
import { openai } from '@ai-sdk/openai';

export async function POST(req: Request) {
  // useChat sends the same chat id with every turn
  const { id, messages }: { id: string; messages: UIMessage[] } = await req.json();

  // Groups all turns of this chat into one conversation in Sentry
  Sentry.setConversationId(id);

  const result = streamText({
    model: openai('gpt-5-mini'),
    messages: await convertToModelMessages(messages),
    telemetry: {
      functionId: 'chat-route', // shows up as the agent name in Sentry
    },
  });

  return result.toUIMessageStreamResponse();
}
```

[Naming your agents](https://docs.sentry.io/product/agents/naming/)

### 3. Find your conversations in Sentry

Chat with your app a few times, then open [Explore → Agents](https://sentry.io/orgredirect/organizations/:orgslug/explore/agents/) in Sentry. The charts at the top show estimated cost split by model, agent runs, and tool calls over time.

The **Conversations** tab lists each chat with its timespan, number of messages, errors, cost, and the tools it called. Search by user, model, or message to find a specific chat. The **Traces** tab shows single agent runs, and the **LLM Calls** tab shows each model request with its tokens and cost.

[Conversations documentation](https://docs.sentry.io/product/agents/conversations/)

### 4. Read a conversation turn by turn

Click a conversation to open it. The header shows the totals for the whole chat: LLM calls, errors, tokens, and cost. The **Transcript** tab shows each user message, each tool call with its inputs, and each agent reply with its cost and duration. A failed tool call shows in red, so you can see which turn broke and what the agent told the user. The **Timeline** tab shows when each step ran and how long it took.

[How Sentry calculates model costs](https://docs.sentry.io/product/agents/costs/)

### 5. Drill into the full trace

Click the trace link in the conversation header to open the trace. The **Agent Activity** tab shows each LLM call and tool call in order, with tokens, cost, and duration. Select a call to see its model, prompt, and output.

Switch to the **Waterfall** tab to see the entire request lifecycle, from the page load or API call all the way down to each LLM request and tool execution. This gives you the full-stack context to understand whether a slow tool call is a database issue, a network problem, or an AI provider timeout.

[Trace Explorer documentation](https://docs.sentry.io/product/trace-explorer/)

## Summary

**You know exactly what your agents cost.**

Every token, tool call, and model request shows up in Sentry with full trace context, so you can optimize cost and debug performance without switching tabs.

## Pro Tips

- Use a meaningful `functionId` for each `streamText` or `generateText` call (for example `'chat-route'` or `'summarize-document'`). It becomes the agent name in Sentry and makes runs much easier to filter.

- Set `tracesSampleRate` to a lower value like `0.2` in production to reduce volume, then raise it temporarily when debugging a specific issue.

- To compare cost and token types (input, cached input, output, and reasoning) by model, open the prebuilt **AI Agents Model Details** dashboard from [Dashboards](https://sentry.io/orgredirect/organizations/:orgslug/dashboards/?filter=onlyPrebuilt&query=agents).

- Tool calls that hit your database appear as child spans inside the agent trace. If a tool is slow, check whether the database span is the actual bottleneck.

## Common Pitfalls

- Forgetting to set `tracesSampleRate` greater than zero. AI spans are only captured when tracing is active.

- Running AI calls on the Edge runtime. In SDK v11, `vercelAIIntegration` relies on diagnostics channels, which Edge doesn't support, so those routes send no AI spans. Keep AI routes on the Node.js runtime.

- Calling the AI SDK's `registerTelemetry` alongside Sentry. `vercelAIIntegration` already instruments the AI SDK, so registering telemetry separately gives you duplicate spans.

- Not wrapping tool calls in Sentry spans. If your agent calls external APIs or runs database queries as tools, they won't appear in the trace unless instrumented. Use the Sentry SDK or auto-instrumented libraries so tool performance shows up alongside your LLM spans.

- Miscounting cached tokens in manual instrumentation. `gen_ai.usage.input_tokens` should be the total including cached tokens, with the cached portion reported separately as `gen_ai.usage.cache_read.input_tokens`. Reporting only the non-cached portion causes Sentry to calculate negative costs.

- Forgetting that prompts are captured by default. Opt out per call with `telemetry: { recordInputs: false, recordOutputs: false }`, or for the whole app with `dataCollection.genAI`. Setting these options on `vercelAIIntegration()` overrides every per-call setting.

## FAQ

**Which AI providers are supported automatically?**

The Vercel AI SDK integration automatically instruments all providers supported by the AI SDK, including OpenAI, Anthropic, Google Gen AI, and others. For unsupported providers, you can add custom spans with the `gen_ai.chat` operation.

**Do I need to use the Vercel AI SDK?**

No. If you're using OpenAI, Anthropic, LangChain, or another supported library directly, Sentry has dedicated integrations for each. The `telemetry` option and `functionId` naming in this recipe are specific to the Vercel AI SDK.

**Will this affect my app's performance?**

No. Sentry uses asynchronous, non-blocking transport. Spans are batched and sent in the background with negligible overhead on your request latency.

**How much does it cost in Sentry?**

Sentry bills tracing by span volume. Sentry's free plan includes enough spans to get started, and you can lower `tracesSampleRate` to control exactly how many traces you send.

**Can I capture the actual prompts and responses?**

Yes, and Sentry does it by default. For a privacy-sensitive route, set `recordInputs: false` and `recordOutputs: false` in that call's `telemetry` option. To turn it off for the whole app, use `dataCollection: { genAI: { inputs: false, outputs: false } }` in `Sentry.init()`. Sentry then captures only metadata like token counts and model names.

## Next Steps

- [solution/ai-observability](https://sentry.io/solutions/ai-observability/)

- [product/tracing](https://sentry.io/product/tracing/)

- [Set up alerts on spend spikes](https://sentry.io/orgredirect/organizations/:orgslug/monitors/alerts/): Create a Sentry metric alert to notify you when token usage or LLM cost crosses a threshold.

---

*Source: [sentry.io/cookbook/monitor-ai-agent-costs-nextjs/](https://sentry.io/cookbook/monitor-ai-agent-costs-nextjs/)*
