Skip to main content
The Vercel AI SDK emits OpenTelemetry spans when you enable its telemetry option. AgentMark ingests those spans directly. Point any OpenTelemetry exporter at the AgentMark endpoint and AgentMark reads model calls, tool calls, token usage, and finish reasons as normalized traces, with no third-party span processor required. This works with AI SDK v4, v5, and v6.

Setup

1

Install @vercel/otel and the OTLP exporter

npm install @vercel/otel @opentelemetry/exporter-trace-otlp-http
2

Register OpenTelemetry and point the exporter at AgentMark

In a Next.js app this goes in instrumentation.ts at the project root. Use your AgentMark API key and app id from project settings.
// instrumentation.ts
import { registerOTel } from "@vercel/otel";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";

export function register() {
  registerOTel({
    serviceName: "my-app",
    traceExporter: new OTLPTraceExporter({
      url: "https://api.agentmark.co/v1/traces",
      headers: {
        Authorization: process.env.AGENTMARK_API_KEY!, // raw key, no "Bearer" prefix
        "X-Agentmark-App-Id": process.env.AGENTMARK_APP_ID!,
      },
    }),
  });
}
3

Enable telemetry on your AI SDK calls

Set experimental_telemetry on each call you want traced.
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";

const result = await generateText({
  model: openai("gpt-4o"),
  prompt: "Write a short story about a cat.",
  experimental_telemetry: { isEnabled: true },
});
4

Run your app

Run your app as usual. Each model call and tool call arrives in AgentMark as a span, grouped into a trace. See Traces and logs.

What AgentMark captures

AgentMark normalizes the AI SDK’s ai.* and gen_ai.* span attributes natively:
  • Generations: each ai.generateText.doGenerate and ai.streamText.doStream span (and the object variants) becomes a generation carrying its model id, input messages, and output text or object.
  • Tool calls: AgentMark labels tool-call spans by tool name, with their arguments and results.
  • Token usage: input, output, total, and reasoning tokens, which feed cost tracking.
  • Finish reason and settings: the response finish reason plus request settings such as temperature, max tokens, top-p, and penalties.
  • Metadata: AgentMark preserves anything you pass via experimental_telemetry.metadata on the trace.

Alternative: route through OpenInference

If you already standardize on the OpenInference conventions across frameworks, you can map the AI SDK’s spans onto them with the OpenInference span processor instead of exporting raw. AgentMark reads either shape. Install the span processor alongside the exporter:
npm install @vercel/otel @arizeai/openinference-vercel @opentelemetry/exporter-trace-otlp-http
Then wrap the exporter with the OpenInference span processor:
// instrumentation.ts
import { registerOTel } from "@vercel/otel";
import {
  isOpenInferenceSpan,
  OpenInferenceSimpleSpanProcessor,
} from "@arizeai/openinference-vercel";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";

export function register() {
  registerOTel({
    serviceName: "my-app",
    spanProcessors: [
      new OpenInferenceSimpleSpanProcessor({
        exporter: new OTLPTraceExporter({
          url: "https://api.agentmark.co/v1/traces",
          headers: {
            Authorization: process.env.AGENTMARK_API_KEY!, // raw key, no "Bearer" prefix
            "X-Agentmark-App-Id": process.env.AGENTMARK_APP_ID!,
          },
        }),
        // Export only the AI SDK's generative spans, dropping unrelated ones.
        spanFilter: (span) => isOpenInferenceSpan(span),
      }),
    ],
  });
}
With this processor in place, spans use the OpenInference attribute conventions. See OpenInference for that attribute mapping.

Next steps

OpenInference

How AgentMark reads OpenInference attributes

Traces and logs

Explore traces once they arrive

Have questions?

Reach out any time: