You could always see what a task did. Now you can see what it spent. One flag, nothing to install, and every LLM call shows up timed and priced, from a single span up to your whole AI bill.
Turn it on
Set experimental_telemetry on any Vercel AI SDK call. Nothing to install.
import { task } from "@trigger.dev/sdk";import { generateText } from "ai";import { anthropic } from "@ai-sdk/anthropic";export const summarize = task({ id: "summarize", run: async (payload: { text: string }) => { const { text } = await generateText({ model: anthropic("claude-sonnet-4-5"), prompt: payload.text, experimental_telemetry: { isEnabled: true }, }); return text; },});
It works the same on generateText, streamText, and generateObject. Every call becomes its own span.
The AI SDK is just one way to emit those spans. They follow the OpenTelemetry GenAI semantic conventions, and that's the whole contract: any span with the standard gen_ai attributes gets cost data attached and the same trace and dashboard observability, whatever produced it.
See the whole workload
The dashboard at the top rolls up every recorded call across your project: cost over time, cost by model, total tokens, latency. The shape of your AI spend, without instrumenting anything.
It runs on TRQL, our SQL-style query language for your Trigger.dev data. It reads LLM usage alongside your runs and metrics tables, so cost per task, tokens by model, and latency trends are one query. Or ask in plain English on the Query page and it writes the query for you:
Show me the 10 most expensive tasks over the last 7 days
Open any single call
The dashboard tells you what you spent. The trace tells you why. Open a model span and the AI inspector breaks the call down:
- Overview: model, provider, prompt/completion/total token counts, cost, and an input/output preview
- Messages: the full thread sent to the model, system prompt and tool results included
- Tools: the tool definitions you passed and every tool call the model made, with arguments
So when a call runs slow or a bill jumps, you open the span and see which model ran, what went in, and what came back. No guessing which of five generateText calls in a task was the expensive one.
Link a call to its prompt
If you manage prompts with Prompts, resolve one and spread toAISDKTelemetry() into the call. The span then carries the prompt too, and you can tag it with your own attributes:
const resolved = await summarizePrompt.resolve({ tone: "brief" });const result = await generateText({ model: anthropic("claude-sonnet-4-5"), prompt: resolved.text, ...resolved.toAISDKTelemetry({ "task.type": "summarization", "customer.tier": "enterprise", }),});
A fourth Prompt tab appears on the span with the linked template, its version, and the input variables, so a bad output traces straight back to the prompt that caused it.
Chat agents get it too
chat.agent reports its model calls through the same telemetry. chat.toStreamTextOptions() folds it in with the stored prompt, model, and config, so once you set a system prompt with chat.prompt.set(), every turn shows up in the trace with no extra wiring.
Get started
Add experimental_telemetry: { isEnabled: true } to a task, trigger a run, and the whole workload starts filling in. Custom metadata and prompt linking are in the AI observability docs.

