Vercel AI SDK — Example Configuration

JavaScript / TypeScript only — The Vercel AI SDK uses a provider-middleware architecture. Weflayr plugs in via wrapLanguageModel; the provider and every call site stay unchanged.

Setup

Wrap your model once at init. Every generateText, streamText, generateObject, or streamObject call using that model is automatically observed.

const { weflayr_setup, weflayr_vercel_ai_middleware } = require('weflayr');
const { wrapLanguageModel, generateText } = require('ai');
const { createOpenAICompatible } = require('@ai-sdk/openai-compatible');

weflayr_setup({
  intake_url:    process.env.WEFLAYR_INTAKE_URL,
  client_id:     process.env.WEFLAYR_CLIENT_ID,
  client_secret: process.env.WEFLAYR_CLIENT_SECRET,
});

const provider = createOpenAICompatible({
  name:    'openai',
  baseURL: 'https://api.openai.com/v1',
  headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` },
});

const model = wrapLanguageModel({
  model: provider('gpt-4o-mini'),
  middleware: weflayr_vercel_ai_middleware({
    model: 'openai/gpt-4o-mini',
    tags:  { env: 'production' },
  }),
});

await generateText({ model, prompt: 'Hello!' });

The model string passed to the middleware ('openai/gpt-4o-mini') is the identifier recorded in every event’s args.model field. It is decoupled from the underlying provider so you can use any naming convention that fits your dashboard.

Tagging with weflayr_propagate

Use weflayr_propagate to attach a tag to every LLM call made in the current async context — useful for request-scoped metadata like customer_id.

const { weflayr_propagate } = require('weflayr');

weflayr_propagate('customer_id', 'acme-corp');
await generateText({ model, prompt: 'Hello!' });

Tags set via weflayr_propagate are merged with the static tags from weflayr_vercel_ai_middleware. Per-call tags take priority over propagated ones, which take priority over static ones.

Streaming

streamText is instrumented automatically. The after event is emitted once the stream is fully drained and includes usage and finish_reason from the provider’s finish chunk.

const { weflayr_setup, weflayr_vercel_ai_middleware } = require('weflayr');
const { wrapLanguageModel, streamText } = require('ai');
const { createOpenAICompatible } = require('@ai-sdk/openai-compatible');

weflayr_setup({
  intake_url:    process.env.WEFLAYR_INTAKE_URL,
  client_id:     process.env.WEFLAYR_CLIENT_ID,
  client_secret: process.env.WEFLAYR_CLIENT_SECRET,
});

const provider = createOpenAICompatible({
  name:    'openai',
  baseURL: 'https://api.openai.com/v1',
  headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` },
});

const model = wrapLanguageModel({
  model: provider('gpt-4o-mini'),
  middleware: weflayr_vercel_ai_middleware({
    model: 'openai/gpt-4o-mini',
    tags:  { feature: 'chat' },
  }),
});

const { textStream } = streamText({ model, prompt: 'Hello!' });
for await (const _chunk of textStream) {}

What Weflayr captures

Field generateText streamText
event_type before + after before + stream_start + after
args.model model string from middleware options model string from middleware options
tags static + propagated static + propagated
response.usage { promptTokens, completionTokens } { promptTokens, completionTokens }
response.finish_reason e.g. "stop" e.g. "stop"
elapsed_ms ✓ (time to full drain)