> ## Documentation Index
> Fetch the complete documentation index at: https://puzzlet-9ba7bb98.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Vercel AI SDK

> Trace Vercel AI SDK calls in AgentMark by exporting its OpenTelemetry spans to the AgentMark OTLP endpoint.

The [Vercel AI SDK](https://github.com/vercel/ai) 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

<Steps>
  <Step title="Install @vercel/otel and the OTLP exporter">
    ```bash theme={null}
    npm install @vercel/otel @opentelemetry/exporter-trace-otlp-http
    ```
  </Step>

  <Step title="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.

    ```typescript theme={null}
    // 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!,
          },
        }),
      });
    }
    ```
  </Step>

  <Step title="Enable telemetry on your AI SDK calls">
    Set `experimental_telemetry` on each call you want traced.

    ```typescript theme={null}
    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 },
    });
    ```
  </Step>

  <Step title="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](/observe/traces-and-logs).
  </Step>
</Steps>

## 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](/observe/cost-and-token-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](/integrations/tracing/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:

```bash theme={null}
npm install @vercel/otel @arizeai/openinference-vercel @opentelemetry/exporter-trace-otlp-http
```

Then wrap the exporter with the OpenInference span processor:

```typescript theme={null}
// 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](/integrations/tracing/openinference#what-agentmark-captures) for that attribute mapping.

## Next steps

<CardGroup cols={2}>
  <Card title="OpenInference" icon="diagram-project" href="/integrations/tracing/openinference">
    How AgentMark reads OpenInference attributes
  </Card>

  <Card title="Traces and logs" icon="list-tree" href="/observe/traces-and-logs">
    Explore traces once they arrive
  </Card>
</CardGroup>

<div className="mt-8 rounded-lg bg-blue-50 p-6 dark:bg-blue-900/30">
  <h3 className="font-semibold mb-3">Have questions?</h3>
  <p className="mb-4">Reach out any time:</p>

  <ul>
    <li>
      Email the team at <a href="mailto:hello@agentmark.co" className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-200">[hello@agentmark.co](mailto:hello@agentmark.co)</a> for support
    </li>

    <li>
      Schedule an <a href="https://cal.com/ryan-randall/enterprise" className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-200">Enterprise Demo</a> to learn about AgentMark's business solutions
    </li>
  </ul>
</div>
