Skip to main content
Trace OpenAI Realtime sessions with Maxim to gain full observability into your real-time voice and text interactions.

Prerequisites

Environment Variables

MAXIM_API_KEY=your_maxim_api_key
MAXIM_LOG_REPO_ID=your_log_repository_id
OPENAI_API_KEY=your_openai_api_key

Initialize Maxim Logger

import { Maxim } from "@maximai/maxim-js";

const maxim = new Maxim({ apiKey: process.env.MAXIM_API_KEY });
const logger = await maxim.logger({ id: process.env.MAXIM_LOG_REPO_ID });

if (!logger) {
  throw new Error("Failed to create logger");
}

Wrap OpenAI Realtime Client

Use the wrapOpenAIRealtime function to automatically trace all events in your Realtime session:
import { OpenAIRealtimeWS } from "openai/realtime/ws";
import { wrapOpenAIRealtime } from "@maximai/maxim-js/openai";

const rt = new OpenAIRealtimeWS({ model: "gpt-4o-realtime-preview-2024-12-17" });

const wrapper = wrapOpenAIRealtime(rt, logger);

Add Custom Session Metadata

You can pass additional metadata to enrich your Realtime sessions with custom names and tags:
const wrapper = wrapOpenAIRealtime(rt, logger, {
  "maxim-session-name": "Voice Assistant Demo",
  "maxim-session-tags": { 
    mode: "audio", 
    feature: "customer-support",
    environment: "production"
  },
});

Available Metadata Options

The third parameter to wrapOpenAIRealtime accepts the following options:
OptionTypeDescription
maxim-session-namestringCustom name for the session displayed in the Maxim dashboard
maxim-session-tagsRecord<string, string> | stringKey-value pairs for filtering and organizing sessions
maxim-session-idstringCustom ID for the session (auto-generated if not provided)

Basic Usage Example

Here’s a minimal example showing how to set up OpenAI Realtime with Maxim tracing:
import { OpenAIRealtimeWS } from "openai/realtime/ws";
import { Maxim } from "@maximai/maxim-js";
import { wrapOpenAIRealtime } from "@maximai/maxim-js/openai";

async function main() {
  // Initialize Maxim
  const maxim = new Maxim({ apiKey: process.env.MAXIM_API_KEY });
  const logger = await maxim.logger({ id: process.env.MAXIM_LOG_REPO_ID });

  if (!logger) {
    throw new Error("Failed to create logger");
  }

  // Create and wrap the Realtime client
  const rt = new OpenAIRealtimeWS({ model: "gpt-4o-realtime-preview-2024-12-17" });
  const wrapper = wrapOpenAIRealtime(rt, logger, {
    "maxim-session-name": "Realtime Audio Chat",
    "maxim-session-tags": { mode: "audio", tools: "enabled" },
  });

  // Configure session on connection
  rt.socket.on("open", () => {
    rt.send({
      type: "session.update",
      session: {
        output_modalities: ["audio"],
        instructions: "You are a helpful voice assistant.",
        audio: {
          input: {
            transcription: { model: "gpt-4o-mini-transcribe" },
            turn_detection: {
              type: "server_vad",
              threshold: 0.5,
              prefix_padding_ms: 300,
              silence_duration_ms: 500,
            },
          },
          output: {
            voice: "coral",
          },
        },
      },
    });
  });

  // Handle events
  rt.on("session.updated", () => {
    console.log("Session ready!");
  });

  rt.on("error", (err) => {
    console.error("Error:", err);
  });
}

main().catch(console.error);

Cleanup

Always clean up resources when your session ends:
async function cleanup() {
  rt.close();
  wrapper.cleanup();
  await logger?.flush();
  await logger?.cleanup();
  await maxim.cleanup();
}

// Handle graceful shutdown
process.on("SIGINT", cleanup);
rt.socket.on("close", cleanup);

What Gets Traced

The Maxim wrapper automatically captures:
  • Session lifecycle: Connection, configuration updates, and disconnection
  • Audio events: Input/output audio buffers and transcriptions (if audio modality is enabled)
  • Conversation items: User messages, assistant responses, and function calls
  • Tool calls: Function invocations and their results
  • Errors: Any errors that occur during the session

View traces in the Maxim dashboard

Resources