> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://respan.ai/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://respan.ai/_mcp/server.

# Vercel AI SDK (tracing)

> Trace Vercel AI SDK calls with Respan — model calls, tool execution, token usage, and workflow context.

The [AI SDK](https://ai-sdk.dev/) (by Vercel) is a TypeScript toolkit for building AI-powered applications with Next.js, React, and other frameworks. It provides unified APIs for text generation, streaming, tool use, and structured outputs across multiple LLM providers. Respan captures model calls, tool execution, token usage, and multi-step workflow structure when AI SDK telemetry is enabled.

#### Set up Respan

Create an account at [platform.respan.ai](https://platform.respan.ai) and grab an [API key](https://platform.respan.ai/platform/api/api-keys).

Run `npx @respan/cli setup` to set up with your coding agent.

#### Use Respan Gateway

See [Vercel AI SDK gateway setup](/docs/gateway/vercel) to route this integration through the Respan gateway.

#### Example projects

* [TypeScript examples](https://github.com/respanai/respan-example-projects/tree/main/typescript/tracing/vercel-ai-sdk)

## Setup

**Supported AI SDK range:** `ai >=4 <8` (AI SDK 4.x through 7.x). AI SDK 7.x requires `@respan/instrumentation-vercel` 1.0.10 or later for modern `gen_ai.*` span support and AI SDK telemetry auto-registration, plus the optional peer package `@ai-sdk/otel`. AI SDK 4.x-6.x use the legacy `experimental_telemetry` option and do not require `@ai-sdk/otel`.

#### Install packages

```bash
npm install ai@^7 @ai-sdk/otel @ai-sdk/openai @respan/respan @respan/instrumentation-vercel@^1.0.10
```

#### Set environment variables

```bash
export OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
```

`OPENAI_API_KEY` is used for LLM requests. `RESPAN_API_KEY` is used to export traces to Respan.

#### Initialize Respan

#### Next.js

Create `instrumentation.ts` in your project root (same level as `package.json`). Next.js calls `register()` automatically at startup.

```typescript instrumentation.ts
import { Respan } from "@respan/respan";
import { VercelAIInstrumentor } from "@respan/instrumentation-vercel";

export async function register() {
  const respan = new Respan({
    apiKey: process.env.RESPAN_API_KEY,
    instrumentations: [new VercelAIInstrumentor()],
  });
  await respan.initialize();
}
```

Then add `serverExternalPackages` to `next.config.ts`:

```typescript next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  serverExternalPackages: [
    "@respan/respan",
    "@respan/instrumentation-vercel",
    "ai",
    "@ai-sdk/otel",
  ],
};

export default nextConfig;
```

#### Serverless / Node

Initialize Respan at the top of your handler or entry point:

```typescript
import { Respan } from "@respan/respan";
import { VercelAIInstrumentor } from "@respan/instrumentation-vercel";

const respan = new Respan({
  apiKey: process.env.RESPAN_API_KEY,
  instrumentations: [new VercelAIInstrumentor()],
});
await respan.initialize();
```

`VercelAIInstrumentor` automatically registers the AI SDK 7 OpenTelemetry bridge when `@ai-sdk/otel` is installed. If the optional peer is missing, initialization logs a warning and AI SDK 7 calls do not emit the required spans.

#### Initialize and run

```typescript
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";

const result = await generateText({
  model: openai("gpt-4.1-nano"),
  prompt: "Tell me a joke about AI",
  telemetry: { isEnabled: true },
});

console.log(result.text);
```

#### View your trace

Open the [Traces page](https://platform.respan.ai/platform/traces) to see your AI calls with input/output, token usage, and tool calls.

## Configuration

| Parameter          | Type                      | Default                   | Description                          |
| ------------------ | ------------------------- | ------------------------- | ------------------------------------ |
| `apiKey`           | `string \| undefined`     | `RESPAN_API_KEY` env var  | Respan API key.                      |
| `baseURL`          | `string \| undefined`     | `"https://api.respan.ai"` | API base URL.                        |
| `instrumentations` | `RespanInstrumentation[]` | `[]`                      | Plugin instrumentations to activate. |

## Attributes

### With app-managed AI SDK 7 OpenTelemetry attributes

For global custom attributes, register a configured bridge before Respan initializes and disable the instrumentor's automatic registration. Register the bridge only once during application startup.

```typescript
import { OpenTelemetry } from "@ai-sdk/otel";
import { VercelAIInstrumentor } from "@respan/instrumentation-vercel";
import { Respan } from "@respan/respan";
import { registerTelemetry } from "ai";

registerTelemetry(
  new OpenTelemetry({
    enrichSpan: () => ({
      "ai.telemetry.metadata.customer_identifier": "user-123",
      "ai.telemetry.metadata.thread_identifier": "thread-abc",
      "ai.telemetry.metadata.trace_group_identifier": "onboarding-flow",
    }),
  })
);

const respan = new Respan({
  instrumentations: [
    new VercelAIInstrumentor({ autoRegisterAISDKTelemetry: false }),
  ],
});
await respan.initialize();
```

### With propagateAttributes

Override per-request using a context scope. All AI SDK calls within the scope inherit these attributes.

```typescript
import { Respan } from "@respan/respan";
import { VercelAIInstrumentor } from "@respan/instrumentation-vercel";

const respan = new Respan({
  instrumentations: [new VercelAIInstrumentor()],
});
await respan.initialize();

async function handleRequest(userId: string, message: string) {
  return respan.propagateAttributes(
    {
      customer_identifier: userId,
      thread_identifier: "conv_abc_123",
      metadata: { plan: "pro" },
    },
    async () => {
      const result = await generateText({
        model: openai("gpt-4.1-nano"),
        prompt: message,
        telemetry: { isEnabled: true },
      });
      return result.text;
    }
  );
}
```

| Attribute             | Type                     | Description                                  |
| --------------------- | ------------------------ | -------------------------------------------- |
| `customer_identifier` | `string`                 | Identifies the end user in Respan analytics. |
| `thread_identifier`   | `string`                 | Groups related messages into a conversation. |
| `metadata`            | `Record<string, string>` | Custom key-value pairs attached to spans.    |

## Decorators (optional)

Decorators are not required. After the AI SDK 7 OpenTelemetry bridge is registered and request telemetry is enabled, model and tool operations emit spans automatically. Use `withWorkflow` and `withTask` to group AI calls into named workflows with nested tasks.

```typescript
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { Respan, withWorkflow, withTask } from "@respan/respan";
import { VercelAIInstrumentor } from "@respan/instrumentation-vercel";

const respan = new Respan({
  apiKey: process.env.RESPAN_API_KEY,
  instrumentations: [new VercelAIInstrumentor()],
});
await respan.initialize();

await withWorkflow({ name: "joke_pipeline" }, async () => {
  const intent = await withTask({ name: "classify_intent" }, () =>
    generateText({
      model: openai("gpt-4.1-nano"),
      prompt: 'Classify this intent in one word: "Tell me a joke"',
      telemetry: { isEnabled: true },
    })
  );

  const joke = await withTask({ name: "generate_joke" }, () =>
    generateText({
      model: openai("gpt-4.1-nano"),
      prompt: `The intent is "${intent.text}". Tell a short joke.`,
      telemetry: { isEnabled: true },
    })
  );

  console.log(joke.text);
});

```

## Examples

### Streaming with tools

```typescript
import { stepCountIs, streamText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";

const result = streamText({
  model: openai("gpt-4.1-nano"),
  messages: [{ role: "user", content: "What's the weather in Paris?" }],
  tools: {
    getWeather: tool({
      description: "Get weather for a city",
      inputSchema: z.object({ city: z.string() }),
      execute: async ({ city }) => `${city}: sunny, 72F`,
    }),
  },
  stopWhen: stepCountIs(5),
  telemetry: { isEnabled: true },
});

for await (const chunk of result.textStream) {
  process.stdout.write(chunk);
}
```

## AI SDK 4.x-6.x

Keep `@respan/instrumentation-vercel` current, omit `@ai-sdk/otel`, and enable the legacy request telemetry option:

```typescript
const result = await generateText({
  model: openai("gpt-4.1-nano"),
  prompt: "Tell me a joke about AI",
  experimental_telemetry: {
    isEnabled: true,
    metadata: { customer_identifier: "user-123" },
  },
});
```

The debug message `Total instrumentations ready for SDK: 0` refers to legacy Traceloop auto-discovery. It does not mean `VercelAIInstrumentor` failed to load; that plugin is registered explicitly in `Respan({ instrumentations: [...] })`.