Skip to main content

Documentation Index

Fetch the complete documentation index at: https://www.getmaxim.ai/docs/llms.txt

Use this file to discover all available pages before exploring further.

Trace OpenAI Chat Completions with Maxim to gain full observability into your LLM interactions, including tool calls and streaming responses.

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 Client

Use MaximOpenAIClient to wrap your OpenAI client for automatic tracing:
import OpenAI from "openai";
import { MaximOpenAIClient } from "@maximai/maxim-js/openai-sdk";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const client = new MaximOpenAIClient(openai, logger);

Basic Usage

Make chat completion requests using the wrapped client:
const response = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [
    { role: "user", content: "What is the capital of France?" }
  ],
  max_tokens: 200,
});

console.log(response.choices[0]?.message?.content);

Custom Headers for Tracing

You can pass custom headers to enrich your traces:
const response = await client.chat.completions.create(
  {
    model: "gpt-4o-mini",
    messages: [{ role: "user", content: "Hello!" }],
    max_tokens: 200,
  },
  {
    headers: {
      "maxim-trace-id": "your-custom-trace-id",
      "maxim-generation-name": "greeting-response",
    },
  }
);

Available Header Options

HeaderTypeDescription
maxim-trace-idstringLink this generation to an existing trace
maxim-session-idstringLink the parent trace to an existing session
maxim-trace-tagsstring (JSON)Custom tags for the trace (e.g., '{"env": "prod"}')
maxim-generation-namestringCustom name for the generation in the dashboard

Tool Calling Example

Here’s a complete example demonstrating tool calls with tracing:
import OpenAI from "openai";
import { Maxim } from "@maximai/maxim-js";
import { MaximOpenAIClient } from "@maximai/maxim-js/openai-sdk";
import { v4 as uuid } from "uuid";

async function main() {
  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("Logger is not available");
  }

  const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
  const client = new MaximOpenAIClient(openai, logger);

  // Create a trace to group all generations in the tool call flow
  const trace = logger.trace({ id: uuid() });

  // Define tools
  const tools: OpenAI.Chat.Completions.ChatCompletionTool[] = [
    {
      type: "function",
      function: {
        name: "get_weather",
        description: "Get the current weather in a given location",
        parameters: {
          type: "object",
          properties: {
            location: {
              type: "string",
              description: "The city and state, e.g. San Francisco, CA",
            },
            unit: {
              type: "string",
              enum: ["celsius", "fahrenheit"],
            },
          },
          required: ["location"],
        },
      },
    },
  ];

  const messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [
    { role: "user", content: "What's the weather like in San Francisco?" },
  ];

  // First call - model requests a tool call
  const firstResponse = await client.chat.completions.create(
    {
      model: "gpt-4o-mini",
      messages: messages,
      tools: tools,
      tool_choice: "required",
      max_tokens: 200,
    },
    {
      headers: {
        "maxim-trace-id": trace.id,
        "maxim-generation-name": "tool-call-request",
      },
    }
  );

  const toolCall = firstResponse.choices[0]?.message?.tool_calls?.[0];

  // Simulate tool execution
  const toolResult = JSON.stringify({
    location: "San Francisco, CA",
    temperature: 72,
    unit: "fahrenheit",
    condition: "sunny",
  });

  // Second call - pass tool result back to model
  const secondMessages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [
    ...messages,
    firstResponse.choices[0]?.message as OpenAI.Chat.Completions.ChatCompletionMessageParam,
    {
      role: "tool",
      tool_call_id: toolCall!.id,
      content: toolResult,
    },
  ];

  const secondResponse = await client.chat.completions.create(
    {
      model: "gpt-4o-mini",
      messages: secondMessages,
      tools: tools,
      max_tokens: 200,
    },
    {
      headers: {
        "maxim-trace-id": trace.id,
        "maxim-generation-name": "tool-call-response",
      },
    }
  );

  console.log("Response:", secondResponse.choices[0]?.message?.content);

  // Set trace output and end
  trace.output(secondResponse.choices[0]?.message?.content || "");
  trace.end();

  await logger.cleanup();
  await maxim.cleanup();
}

main().catch(console.error);

Grouping Generations with Traces

Use traces to group related generations together:
// Create a trace
const trace = logger.trace({ id: uuid() });

// All generations with the same trace ID are grouped together
await client.chat.completions.create(
  { model: "gpt-4o-mini", messages: [...] },
  { headers: { "maxim-trace-id": trace.id } }
);

await client.chat.completions.create(
  { model: "gpt-4o-mini", messages: [...] },
  { headers: { "maxim-trace-id": trace.id } }
);

// Set the final output and end the trace
trace.output("Final result");
trace.end();

Streaming Support

The wrapped client supports streaming responses:
const stream = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Write a haiku about coding" }],
  stream: true,
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content || "");
}

Cleanup

Always clean up resources when done:
await logger.cleanup();
await maxim.cleanup();

What gets logged to Maxim

  • Request Details: Model name, parameters, and all other settings
  • Message History: Complete conversation history including user messages and assistant responses
  • Response Content: Full assistant responses and metadata
  • Usage Statistics: Input tokens, output tokens, total tokens consumed
  • Error Handling: Any errors that occur during the request
Chat Completions Trace

Resources

OpenAI Chat Completions

Official OpenAI Chat Completions documentation

Maxim JS SDK

Maxim TypeScript SDK on npm