The wrapOpenAI() function wraps an OpenAI client to enable automatic LangSmith tracing for all completions.
Installation
npm install langsmith openai
Basic usage
import { OpenAI } from "openai" ;
import { wrapOpenAI } from "langsmith/wrappers/openai" ;
const client = wrapOpenAI ( new OpenAI ());
const response = await client . chat . completions . create ({
model: "gpt-4" ,
messages: [{ role: "user" , content: "Hello!" }],
});
Signature
function wrapOpenAI < T extends OpenAIType >(
openai : T ,
options ?: Partial < RunTreeConfig >
) : PatchedOpenAIClient < T >
An OpenAI client instance to wrap.
LangSmith tracing options
Override the default run name.
The LangSmith project name.
Metadata to attach to runs. Can include ls_invocation_params for pre-populated invocation parameters.
Custom LangSmith client instance.
Whether to enable tracing.
The wrapped OpenAI client with automatic tracing.
Supported methods
The wrapper automatically traces:
chat.completions.create() - Chat completions (streaming and non-streaming)
chat.completions.parse() - Structured output parsing
chat.completions.stream() - Chat completion streams
completions.create() - Legacy text completions
beta.chat.completions.parse() - Beta structured outputs
beta.chat.completions.stream() - Beta chat streams
responses.create() - Responses API (if available)
responses.parse() - Responses API parsing
responses.stream() - Responses API streaming
Features
The wrapper automatically extracts:
Provider (“openai” or “azure”)
Model name
Temperature
Max tokens
Stop sequences
Usage metadata (input/output tokens, cache hits, reasoning tokens)
Service tier information
Streaming support
Streaming responses are fully supported:
const stream = await client . chat . completions . create ({
model: "gpt-4" ,
messages: [{ role: "user" , content: "Count to 5" }],
stream: true ,
});
for await ( const chunk of stream ) {
process . stdout . write ( chunk . choices [ 0 ]?. delta ?. content || "" );
}
Token usage is automatically tracked:
const response = await client . chat . completions . create ({
model: "gpt-4" ,
messages: [{ role: "user" , content: "Hello!" }],
});
// Usage metadata is automatically logged to LangSmith
// Including:
// - input_tokens
// - output_tokens
// - total_tokens
// - cache_read tokens (if applicable)
// - reasoning tokens (for o1 models)
Azure OpenAI support
The wrapper automatically detects Azure OpenAI clients:
import { AzureOpenAI } from "openai" ;
import { wrapOpenAI } from "langsmith/wrappers/openai" ;
const client = wrapOpenAI ( new AzureOpenAI ({
apiKey: process . env . AZURE_OPENAI_API_KEY ,
endpoint: process . env . AZURE_OPENAI_ENDPOINT ,
apiVersion: "2024-02-15-preview" ,
}));
Pass additional metadata via the langsmithExtra parameter:
const response = await client . chat . completions . create (
{
model: "gpt-4" ,
messages: [{ role: "user" , content: "Hello!" }],
},
{
langsmithExtra: {
name: "custom-chat" ,
metadata: { user_id: "123" },
tags: [ "production" ],
},
}
);
Additional LangSmith configuration for this specific call
ExtraRunTreeConfig properties
Pre-populated invocation parameters
Set default invocation parameters at the client level:
const client = wrapOpenAI ( new OpenAI (), {
metadata: {
ls_invocation_params: {
api_version: "2024-02-15" ,
deployment_name: "my-deployment" ,
},
},
});
// These parameters will be included in all traces
Complete example
import { OpenAI } from "openai" ;
import { wrapOpenAI } from "langsmith/wrappers/openai" ;
const client = wrapOpenAI ( new OpenAI (), {
project_name: "my-openai-project" ,
tags: [ "production" ],
metadata: {
environment: "prod" ,
},
});
// Non-streaming
const response = await client . chat . completions . create (
{
model: "gpt-4" ,
messages: [
{ role: "system" , content: "You are a helpful assistant." },
{ role: "user" , content: "What is LangSmith?" },
],
temperature: 0.7 ,
max_tokens: 1000 ,
},
{
langsmithExtra: {
metadata: { user_id: "user-123" },
},
}
);
console . log ( response . choices [ 0 ]. message . content );
// Streaming
const stream = await client . chat . completions . create ({
model: "gpt-4" ,
messages: [{ role: "user" , content: "Count to 10" }],
stream: true ,
});
for await ( const chunk of stream ) {
process . stdout . write ( chunk . choices [ 0 ]?. delta ?. content || "" );
}
// Structured outputs
const completion = await client . beta . chat . completions . parse ({
model: "gpt-4" ,
messages: [{ role: "user" , content: "Extract: John is 30 years old" }],
response_format: {
type: "json_schema" ,
json_schema: {
name: "person" ,
schema: {
type: "object" ,
properties: {
name: { type: "string" },
age: { type: "number" },
},
},
},
},
});
Error handling
try {
const response = await client . chat . completions . create ({
model: "gpt-4" ,
messages: [{ role: "user" , content: "Hello!" }],
});
} catch ( error ) {
// Errors are automatically logged to LangSmith
console . error ( error );
}
Nested tracing
The wrapper works seamlessly with traceable():
import { traceable } from "langsmith/traceable" ;
const myChain = traceable (
async ( input : string ) => {
const response = await client . chat . completions . create ({
model: "gpt-4" ,
messages: [{ role: "user" , content: input }],
});
return response . choices [ 0 ]. message . content ;
},
{ name: "my-chain" , run_type: "chain" }
);
await myChain ( "Hello!" );
// Creates a trace with the chain as parent and LLM call as child
Notes
The wrapper preserves all original OpenAI SDK functionality
Method signatures remain unchanged except for the optional langsmithExtra parameter
Wrapping a client multiple times will throw an error
All traced calls use run_type: "llm"