Skip to main content

OpenAI Adapter

@accordkit/provider-openai decorates the official OpenAI JavaScript SDK. It emits normalized AccordKit events (message, tool_call, usage, tool_result, span) without changing how you call chat.completions.create or the newer beta namespaces.

Install

pnpm add @accordkit/tracer @accordkit/provider-openai openai

Wrap the client

src/openai.ts
import OpenAI from 'openai';
import { FileSink, Tracer } from '@accordkit/tracer';
import { withOpenAI } from '@accordkit/provider-openai';

const tracer = new Tracer({ sink: new FileSink() });

const client = withOpenAI(
new OpenAI({ apiKey: process.env.OPENAI_API_KEY }),
tracer,
);

withOpenAI returns a proxy that mirrors the SDK. Re-wrapping the same client is idempotent—the adapter remembers the proxy and returns it.

Emitted events

EventWhen it firesKey fields
messagePrompts (before the request) and assistant completionsrole, content, model, requestId
tool_callAssistant requests a function/tooltool, parsed input, $ext.id
usageOpenAI reports token accountinginputTokens, outputTokens, $ext.totalTokens
tool_resultRequest completes (success or error)ok, latencyMs, output summary
spanSurrounds each API invocationoperation, durationMs, status, attrs.model

All events share the same trace context so downstream tooling can correlate them easily.

Options

Adapter options
withOpenAI(client, tracer, {
enableResponsesApi: true,
enableImagesApi: true,
enableAudioApi: false,
provider: 'openai',
operationName: 'my-app.chat',
emitPrompts: true,
emitResponses: true,
emitToolCalls: true,
emitUsage: true,
emitToolResults: true,
emitSpan: true,
});
OptionDefaultEffect
enableResponsesApifalseWrap the beta responses namespace so responses.create emits AccordKit events.
enableImagesApifalseInstrument images.generate to emit tool_result and span events (no binary payloads).
enableAudioApifalseInstrument audio.speech/transcriptions/translations.
provider'openai'Provider label attached to every emitted event.
operationName'openai.chat.completions.create'Name recorded on tool_result and span events.
emitPromptstrueEmit message events for system/user prompts.
emitResponsestrueEmit message events for assistant replies.
emitToolCallstrueEmit tool_call events for tool/function requests.
emitUsagetrueEmit usage events when the SDK returns usage.
emitToolResultstrueEmit tool_result events summarising success/error and latency.
emitSpantrueEmit a span around every request.

Streaming behaviour

Streaming responses are detected automatically. The adapter waits for finalChatCompletion() (or an equivalent helper) and then emits the same completion, usage, tool result, and span events you get for non-streaming calls. Intermediate deltas are not emitted individually yet, so the stream API remains unchanged for your application.

Redacting sensitive fields

Use tracer middleware to scrub content before it leaves your process.

src/redaction.ts
import { HttpSink, Tracer, type TraceMiddleware } from '@accordkit/tracer';

const redactEmails: TraceMiddleware = (event) => {
if (event.type === 'message' && typeof event.content === 'string') {
event.content = event.content.replace(/\S+@\S+/g, '[redacted]');
}
return event;
};

const tracer = new Tracer({
sink: new HttpSink({ endpoint: 'https://example.com/ingest' }),
middlewares: [redactEmails],
});

Middleware runs on every emitted event, regardless of whether it originated from your code or the adapter.

Next steps