Docs / Integrations / Vercel AI SDK

Vercel AI SDK

Mesedi ships a higher-order wrapper for Vercel's AI SDK generateText. Import wrapGenerateText, wrap the real generateText, and use the wrapped version. Every LLM step + tool call inside a wrap() flows into Mesedi with byte-identical wire format to hand-instrumented code.

Install

npm install mesedi ai @ai-sdk/openai

ai is declared as an optional peer dependency on mesedi. Installing mesedi doesn't require it. If your project already has ai installed, the wrapper picks it up automatically.

Wire it up

import { configure, wrap } from "mesedi";
import { wrapGenerateText } from "mesedi/integrations/vercel_ai";
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";

configure({ apiKey: process.env.MESEDI_API_KEY });

const generateTextM = wrapGenerateText(generateText);

export const runAgent = wrap(
  { agentName: "support-triage" },
  async (question: string) => {
    const result = await generateTextM({
      model: openai("gpt-4o"),
      prompt: question,
      tools: { lookup, search },
      maxSteps: 5,
    });
    return result.text;
  },
);

wrapGenerateText is a higher-order function that takes the real Vercel generateText and returns a drop-in replacement with the same signature plus telemetry side effects. Your agent code does not change beyond the import swap.

Step-to-event mapping

Multi-step (ReAct) generation is the common case for agent workflows: generateText({ maxSteps: 5, tools: { ... } }) makes up to 5 LLM calls with tool calls between each. Vercel exposes the per-step record on result.steps. The wrapper iterates that array and emits one llm_call event per step plus one tool_call event per tool invocation within the step.

Vercel result fieldMesedi eventNotes
result.steps[i]llm_callModel, prompt, response, token counts from stepusage.
result.toolCalls[i] + result.toolResults[i]tool_callPaired by toolCallId. Missing result or result.error field marks failure.
Thrown error from generateTextllm_call (status failed)Error re-thrown after emit; original stack preserved.

Current limitations

  • streamText / streamObject are not currently wrapped. The emit-on-stream-end variant would need to drain the stream first or instrument the stream's transform.
  • generateObject (structured output) is not currently wrapped. The shape is similar to generateText's but the response field is .object not .text.
  • OpenTelemetry-based instrumentation via Vercel's experimental_telemetry is not used. That path requires @opentelemetry/api as a peer dependency; the wrapper approach avoids the extra install.
  • Outside a wrap, the wrapper still calls the underlying generateText and returns its result — no Mesedi events are emitted.

Related