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/openaiai 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 field | Mesedi event | Notes |
|---|---|---|
result.steps[i] | llm_call | Model, prompt, response, token counts from stepusage. |
result.toolCalls[i] + result.toolResults[i] | tool_call | Paired by toolCallId. Missing result or result.error field marks failure. |
Thrown error from generateText | llm_call (status failed) | Error re-thrown after emit; original stack preserved. |
Current limitations
streamText/streamObjectare 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 togenerateText's but the response field is.objectnot.text.- OpenTelemetry-based instrumentation via Vercel's
experimental_telemetryis not used. That path requires@opentelemetry/apias a peer dependency; the wrapper approach avoids the extra install. - Outside a wrap, the wrapper still calls the underlying
generateTextand returns its result — no Mesedi events are emitted.