Vercel AI SDK
generateText, streamText, generateObject, and tool calls capture automatically on v7, or with experimental_telemetry on v5/v6.
Every ai call inside wrap your agent becomes a span, model calls as llm, tool executions as tool.
How the AI SDK reports telemetry changed in v7, so which setup you need depends on your version:
| AI SDK | What you do |
|---|---|
| v7+ | Nothing, on trodo-node 2.23.4 or later. registerOTel() registers Trodo's telemetry integration for you, including under ESM and Next.js. |
| v5 / v6 | Pass experimental_telemetry: { isEnabled: true } per call. |
What's captured
| Call | Span kind | Auto-extracted |
|---|---|---|
generateText | llm | model, provider, tokens, prompt, completion |
streamText | llm | same, accumulated |
generateObject / streamObject | llm | model, tokens, schema, parsed object |
tool() and the tool-call loop | tool | tool name, input, output |
embed / embedMany | llm | model, tokens |
The provider field is whichever adapter you use (openai, anthropic, google).
Install
npm install ai @ai-sdk/openaiNo OpenTelemetry package is needed on any version.
Minimal example
import trodo from 'trodo-node';
import { generateText, tool } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
trodo.init({ siteId: process.env.TRODO_SITE_ID });
await trodo.wrapAgent('ai-sdk-bot', async (run) => {
const { text } = await generateText({
model: openai('gpt-4o-mini'),
prompt: 'What is the weather in SF?',
tools: {
get_weather: tool({
description: 'Current weather in a city',
inputSchema: z.object({ city: z.string() }), // AI SDK v5+: inputSchema (was `parameters` in v4)
execute: async ({ city }) => `Sunny in ${city}, 72F`,
}),
},
experimental_telemetry: { isEnabled: true }, // required
});
run.setOutput(text);
});On v5 / v6 the experimental_telemetry: { isEnabled: true } flag is
required, without it the AI SDK emits no spans. On v7 it is harmless to
leave in, and harmless to remove.
The provider on each span is the vendor alone (openai, anthropic,
google), so cost and provider filters line up with every other span. The AI
SDK's fuller id (openai.responses, anthropic.messages) is kept on the span
as ai.provider_id, alongside ai.finish_reason.