BrowserStack AI Evals
Integrations

Use with Vercel AI SDK

Trace Vercel AI SDK calls (generateText, streamText, generateObject, embeddings, agents) by wrapping the ai module with wrapVercelAI().

Use with Vercel AI SDK

The Vercel AI SDK (the ai package) is traced by wrapping the ai module with wrapVercelAI(). Pass the imported module through the wrapper once, then use the functions it returns in place of the originals — every generateText, streamText, and so on is captured as a trace.

The Vercel AI SDK integration is TypeScript / Node.js only.

Install

npm install @browserstack/ai-sdk ai @ai-sdk/openai

@ai-sdk/openai is the model-provider package used in this example. Install the one that matches your model instead (@ai-sdk/anthropic, @ai-sdk/google, etc.) — @browserstack/ai-sdk and ai are always required.

Set your credentials as environment variables before running. The SDK reads AISDK_PUBLIC_KEY / AISDK_SECRET_KEY; the OpenAI provider reads OPENAI_API_KEY:

export AISDK_PUBLIC_KEY=pk-...
export AISDK_SECRET_KEY=sk-...
export OPENAI_API_KEY=sk-...

node app.js

Prefer keeping keys in a .env file? Install dotenv and add import 'dotenv/config'; as the first line — it loads the file into process.env. It's a convenience, not an SDK requirement.

Usage

Wrap the ai module with wrapVercelAI(), create your model provider as usual, then call the wrapped functions. This is a complete, runnable ES module (node app.js with "type": "module", or app.mjs).

import * as aiModule from 'ai';
import { createOpenAI } from '@ai-sdk/openai';
import { wrapVercelAI } from '@browserstack/ai-sdk';

// Wrap the module once; use the returned functions everywhere.
const ai = wrapVercelAI(aiModule);

// Wait for auto-instrumentation to finish initializing so the first call is
// traced. Short scripts only — a long-running server does not need this.
await new Promise((r) => setTimeout(r, 5000));

const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function main() {
  // generateText — captured as a trace
  const { text } = await ai.generateText({
    model: openai('gpt-4o-mini'),
    prompt: 'In one sentence, what is the capital of France?',
  });
  console.log('generateText →', text);

  // Short-lived scripts exit before spans are exported — wait briefly so the
  // batch is flushed. A long-running server does not need this.
  await new Promise((r) => setTimeout(r, 5000));
  console.log('Done');
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});

Any function you use is read off the wrapped module the same way — ai.generateObject, ai.streamObject, ai.embed, and so on.

About the two setTimeout waits

They exist only because this example is a short-lived script that starts calling the model immediately and then exits. They are not part of the tracing API.

  • The wait before the calls gives the SDK's auto-instrumentation a moment to finish initializing after wrapVercelAI(), so the first generateText call is captured instead of slipping through before setup completes.
  • The wait before exit lets the batched spans finish exporting. Spans are sent in the background in batches; a script that exits the instant the call returns can terminate before that batch is flushed, dropping the trace.

Neither wait is needed in production. A long-running service (API server, background worker) initializes tracing once at startup — well before it serves any traffic — and never exits between requests, so spans export continuously on their own. Remove both waits there. Only in environments that start fresh and exit per invocation (a serverless function, a one-shot CLI) do you need to guarantee the final spans are sent — and there you should flush explicitly on graceful shutdown rather than relying on a fixed setTimeout.

What gets traced

wrapVercelAI instruments the module's core functions:

CategoryFunctions
Text & objectsgenerateText, generateObject
StreamingstreamText, streamObject
Embeddingsembed, embedMany
ImagesgenerateImage
Rerankingrerank
AgentsAgent / ToolLoopAgent (generate / stream), including tool calls

Each call is captured with the model, prompt / messages, response, and token usage. Streaming calls also record time-to-first-token, and agent loops capture each step and tool call as nested spans.

See also