Trace Vercel AI SDK calls in Next.js

Configure the traceAI span processor and OTLP/HTTP export for model calls in a Node.js Next.js API route.

Send model-call spans from a Node.js Next.js API route to an Observe project in Future AGI.

1. Install

Use this setup in an existing Next.js application with the Node.js runtime, not Edge. It uses AI SDK 6.0.0 and @traceai/vercel 0.1.0. The traceAI processor extends the OpenTelemetry 1.x span processor, so keep the SDK packages on the versions below rather than mixing them with OpenTelemetry 2.x.

npm install @traceai/vercel@0.1.0 @vercel/otel@1.13.0 \
  @opentelemetry/api@1.9.0 @opentelemetry/sdk-trace-base@1.30.1 \
  @opentelemetry/exporter-trace-otlp-http@0.57.2 \
  ai@6.0.0 @ai-sdk/openai@3.0.0 zod@3.25.76
yarn add @traceai/vercel@0.1.0 @vercel/otel@1.13.0 \
  @opentelemetry/api@1.9.0 @opentelemetry/sdk-trace-base@1.30.1 \
  @opentelemetry/exporter-trace-otlp-http@0.57.2 \
  ai@6.0.0 @ai-sdk/openai@3.0.0 zod@3.25.76
pnpm add @traceai/vercel@0.1.0 @vercel/otel@1.13.0 \
  @opentelemetry/api@1.9.0 @opentelemetry/sdk-trace-base@1.30.1 \
  @opentelemetry/exporter-trace-otlp-http@0.57.2 \
  ai@6.0.0 @ai-sdk/openai@3.0.0 zod@3.25.76

For the processor API, see the traceAI Vercel package.

2. Set credentials

Set these in the environment of your Next.js server. For local development, use Next.js’s environment-file support; do not commit credentials.

FI_API_KEY=YOUR_FI_API_KEY
FI_SECRET_KEY=YOUR_FI_SECRET_KEY
OPENAI_API_KEY=YOUR_OPENAI_API_KEY
# Self-hosted: set your collector origin, without /tracer/v1/traces.
# FI_BASE_URL=https://your-futureagi-instance.example

3. Register tracing at server startup

Create instrumentation.ts in the project root, or in src/ if your application uses that directory. Next.js calls register() once per server instance; do not import or call it from _app.tsx or an API handler. If you already configure OpenTelemetry, add the Future AGI processor to that setup instead of registering another provider.

export async function register() {
  if (process.env.NEXT_RUNTIME !== "nodejs") return;

  const { registerOTel } = await import("@vercel/otel");
  const { FISimpleSpanProcessor, isFISpan } = await import("@traceai/vercel");
  const { OTLPTraceExporter } = await import("@opentelemetry/exporter-trace-otlp-http");

  const apiKey = process.env.FI_API_KEY;
  const secretKey = process.env.FI_SECRET_KEY;
  if (!apiKey || !secretKey) {
    throw new Error("Set FI_API_KEY and FI_SECRET_KEY before starting Next.js.");
  }
  const baseUrl = (process.env.FI_BASE_URL || "https://api.futureagi.com").replace(/\/+$/, "");

  registerOTel({
    serviceName: "vercel-project",
    attributes: {
      project_name: "vercel-project",
      project_type: "observe",
    },
    spanProcessors: [
      new FISimpleSpanProcessor({
        exporter: new OTLPTraceExporter({
          url: `${baseUrl}/tracer/v1/traces`,
          headers: { "X-Api-Key": apiKey, "X-Secret-Key": secretKey },
        }),
        spanFilter: isFISpan,
      }),
    ],
  });
}

The HTTP exporter sends traces with both Future AGI auth headers. project_name and project_type are resource attributes, not camel-case settings. isFISpan limits export to spans recognized by the traceAI processor rather than unrelated Next.js spans.

4. Add a model call

In AI SDK 6.0.0, enable telemetry on the call with experimental_telemetry. The versioned telemetry settings record inputs and outputs by default; this example disables both.

Warning

Input/output switches are not complete redaction. Errors, custom telemetry metadata and request headers can still contain sensitive data. Do not put secrets or private request data in telemetry metadata, and review exported data before using private workloads.

import type { NextApiRequest, NextApiResponse } from "next";
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const result = await generateText({
    model: openai("gpt-4o-mini"),
    prompt: "Write a short creative story about a time-traveling detective.",
    maxOutputTokens: 300,
    experimental_telemetry: {
      isEnabled: true,
      recordInputs: false,
      recordOutputs: false,
    },
  });

  res.status(200).json({ story: result.text });
}

To include prompts and responses, set recordInputs and recordOutputs to true only for data you are allowed to store in Future AGI.

5. Open the trace

Run your Next.js application and request /api/story. Open Observe in Future AGI and select vercel-project to inspect the model-call spans. Input and Output content is hidden by the call’s settings above.

Troubleshooting

  • No spans: confirm the Node.js server loads instrumentation.ts, both Future AGI keys are set, and the call has experimental_telemetry.isEnabled=true.
  • Collector rejects the export: check both auth headers, the collector URL and the project_name resource attribute.
  • Processor type errors: keep the OpenTelemetry SDK on the pinned 1.x line; do not install a 2.x span processor alongside this traceAI release.
Was this page helpful?

Questions & Discussion