Quick Start
The most basic usage involves creating a Codex client, starting a thread, and running a turn:
import { Codex } from "@openai/codex-sdk" ;
const codex = new Codex ();
const thread = codex . startThread ();
const turn = await thread . run ( "Diagnose the test failure and propose a fix" );
console . log ( turn . finalResponse );
console . log ( turn . items );
Core SDK Exports
The SDK exports the following main classes and types:
Main Classes
Main client for interacting with the Codex agent. Used to create and resume threads.
Represents a conversation with the agent. Supports multiple consecutive turns.
Type Exports
Events
Items
Options
Results
import type {
ThreadEvent ,
ThreadStartedEvent ,
TurnStartedEvent ,
TurnCompletedEvent ,
TurnFailedEvent ,
ItemStartedEvent ,
ItemUpdatedEvent ,
ItemCompletedEvent ,
ThreadError ,
ThreadErrorEvent ,
Usage ,
} from "@openai/codex-sdk" ;
Creating a Codex Client
The Codex class accepts optional configuration:
import { Codex } from "@openai/codex-sdk" ;
const codex = new Codex ({
// API configuration
baseUrl: "https://api.openai.com/v1" ,
apiKey: process . env . OPENAI_API_KEY ,
// CLI path override (if codex is not in PATH)
codexPathOverride: "/custom/path/to/codex" ,
// Environment variables for the CLI process
env: {
PATH: process . env . PATH ,
HOME: process . env . HOME ,
},
// Additional CLI configuration overrides
config: {
show_raw_agent_reasoning: true ,
sandbox_workspace_write: {
network_access: true ,
},
},
});
Custom API base URL. Defaults to the OpenAI API endpoint.
OpenAI API key. Can also be set via OPENAI_API_KEY environment variable.
Path to the codex CLI binary. Used when codex is not in your PATH.
Environment variables passed to the Codex CLI process. When provided, the SDK will not inherit from process.env.
Additional --config overrides passed to the CLI. The SDK flattens this object into dotted paths.
Starting a Thread
Create a new conversation thread with optional configuration:
const thread = codex . startThread ({
workingDirectory: "/path/to/project" ,
sandboxMode: "workspace-write" ,
model: "gpt-4" ,
skipGitRepoCheck: false ,
modelReasoningEffort: "medium" ,
networkAccessEnabled: true ,
webSearchMode: "cached" ,
approvalPolicy: "on-request" ,
additionalDirectories: [ "/path/to/extra/context" ],
});
Thread Options
Working directory for the agent. Defaults to the current directory.
sandboxMode
'read-only' | 'workspace-write' | 'danger-full-access'
File system access level for the agent.
Model to use for this thread (e.g., "gpt-4", "gpt-4-turbo").
Skip the Git repository check. Defaults to false.
modelReasoningEffort
'minimal' | 'low' | 'medium' | 'high' | 'xhigh'
Amount of reasoning effort the model should apply.
Enable network access for the agent.
webSearchMode
'disabled' | 'cached' | 'live'
Web search configuration for the agent.
approvalPolicy
'never' | 'on-request' | 'on-failure' | 'untrusted'
When to request user approval for actions.
Additional directories to include in the agent’s context.
Running a Turn
Buffered Execution
Use run() to execute a turn and wait for the complete result:
const turn = await thread . run ( "Fix the failing tests" );
console . log ( "Response:" , turn . finalResponse );
console . log ( "Items:" , turn . items );
console . log ( "Usage:" , turn . usage );
The returned Turn object contains:
The agent’s final text response (or JSON if using structured output).
Array of all items produced during the turn (commands, file changes, tool calls, etc.).
Token usage statistics for the turn.
Streaming Events
Use runStreamed() to receive real-time events as the agent works:
const { events } = await thread . runStreamed ( "Analyze this codebase" );
for await ( const event of events ) {
switch ( event . type ) {
case "thread.started" :
console . log ( "Thread ID:" , event . thread_id );
break ;
case "turn.started" :
console . log ( "Turn started" );
break ;
case "item.started" :
console . log ( "Item started:" , event . item );
break ;
case "item.updated" :
console . log ( "Item updated:" , event . item );
break ;
case "item.completed" :
console . log ( "Item completed:" , event . item );
break ;
case "turn.completed" :
console . log ( "Turn completed. Usage:" , event . usage );
break ;
case "turn.failed" :
console . error ( "Turn failed:" , event . error . message );
break ;
case "error" :
console . error ( "Fatal error:" , event . message );
break ;
}
}
Structured Output
Provide a JSON schema to get structured responses:
const schema = {
type: "object" ,
properties: {
summary: { type: "string" },
status: { type: "string" , enum: [ "ok" , "action_required" ] },
issues: {
type: "array" ,
items: {
type: "object" ,
properties: {
file: { type: "string" },
line: { type: "number" },
description: { type: "string" },
},
required: [ "file" , "description" ],
},
},
},
required: [ "summary" , "status" ],
additionalProperties: false ,
} as const ;
const turn = await thread . run ( "Analyze the codebase for issues" , {
outputSchema: schema ,
});
const result = JSON . parse ( turn . finalResponse );
console . log ( result . summary );
console . log ( result . issues );
Using Zod Schemas
You can also use Zod schemas with the zod-to-json-schema package:
import { z } from "zod" ;
import { zodToJsonSchema } from "zod-to-json-schema" ;
const schema = z . object ({
summary: z . string (),
status: z . enum ([ "ok" , "action_required" ]),
issues: z . array (
z . object ({
file: z . string (),
line: z . number (). optional (),
description: z . string (),
})
),
});
const turn = await thread . run ( "Analyze the codebase" , {
outputSchema: zodToJsonSchema ( schema , { target: "openAi" }),
});
const result = schema . parse ( JSON . parse ( turn . finalResponse ));
Attaching Images
Provide images alongside text prompts:
const turn = await thread . run ([
{ type: "text" , text: "Describe these UI screenshots and suggest improvements" },
{ type: "local_image" , path: "./screenshots/dashboard.png" },
{ type: "local_image" , path: "./screenshots/settings.png" },
]);
Image entries must use the local_image type with an absolute or relative path to the image file.
Resuming Threads
Threads are persisted in ~/.codex/sessions. Resume a previous conversation:
// Save the thread ID from a previous session
const threadId = thread . id ;
// Later, resume the thread
const resumedThread = codex . resumeThread ( threadId );
const nextTurn = await resumedThread . run ( "Continue from where we left off" );
Working with Thread Items
Each turn produces various item types representing the agent’s work:
Agent Messages
Command Execution
File Changes
MCP Tool Calls
Web Search
Todo List
Reasoning
Errors
if ( item . type === "agent_message" ) {
console . log ( "Agent says:" , item . text );
}
Token Usage
Access detailed token usage after each turn:
const turn = await thread . run ( "Refactor this module" );
if ( turn . usage ) {
console . log ( "Input tokens:" , turn . usage . input_tokens );
console . log ( "Cached input tokens:" , turn . usage . cached_input_tokens );
console . log ( "Output tokens:" , turn . usage . output_tokens );
const total = turn . usage . input_tokens + turn . usage . output_tokens ;
const cacheHitRate = turn . usage . cached_input_tokens / turn . usage . input_tokens ;
console . log ( "Total tokens:" , total );
console . log ( "Cache hit rate:" , ( cacheHitRate * 100 ). toFixed ( 2 ) + "%" );
}
Aborting a Turn
Cancel a turn using an AbortSignal:
const controller = new AbortController ();
// Cancel after 30 seconds
setTimeout (() => controller . abort (), 30000 );
try {
const turn = await thread . run ( "Long running task" , {
signal: controller . signal ,
});
} catch ( error ) {
if ( error . name === "AbortError" ) {
console . log ( "Turn was cancelled" );
}
}
Error Handling
Handle errors gracefully:
try {
const turn = await thread . run ( "Fix the bug" );
console . log ( turn . finalResponse );
} catch ( error ) {
if ( error . message . includes ( "rate limit" )) {
console . error ( "Rate limit exceeded. Retrying..." );
// Implement retry logic
} else if ( error . message . includes ( "authentication" )) {
console . error ( "Invalid API key" );
} else {
console . error ( "Unexpected error:" , error . message );
}
}
Advanced Example
Here’s a complete example combining multiple features:
import { Codex } from "@openai/codex-sdk" ;
import { z } from "zod" ;
import { zodToJsonSchema } from "zod-to-json-schema" ;
// Define structured output schema
const analysisSchema = z . object ({
summary: z . string (),
filesAnalyzed: z . number (),
issues: z . array (
z . object ({
severity: z . enum ([ "low" , "medium" , "high" ]),
file: z . string (),
description: z . string (),
})
),
recommendations: z . array ( z . string ()),
});
// Create Codex client
const codex = new Codex ({
apiKey: process . env . OPENAI_API_KEY ,
config: {
show_raw_agent_reasoning: true ,
},
});
// Start thread with configuration
const thread = codex . startThread ({
workingDirectory: "/path/to/project" ,
sandboxMode: "read-only" ,
modelReasoningEffort: "high" ,
});
// Run analysis with streaming
const { events } = await thread . runStreamed (
"Analyze the codebase for security issues and best practices" ,
{
outputSchema: zodToJsonSchema ( analysisSchema , { target: "openAi" }),
}
);
// Process events
for await ( const event of events ) {
if ( event . type === "item.completed" ) {
const item = event . item ;
if ( item . type === "command_execution" ) {
console . log ( `Executed: ${ item . command } ` );
} else if ( item . type === "agent_message" ) {
const analysis = analysisSchema . parse ( JSON . parse ( item . text ));
console . log ( " \n Analysis Complete" );
console . log ( "Summary:" , analysis . summary );
console . log ( "Files analyzed:" , analysis . filesAnalyzed );
console . log ( " \n Issues found:" );
analysis . issues . forEach ( issue => {
console . log ( ` [ ${ issue . severity . toUpperCase () } ] ${ issue . file } ` );
console . log ( ` ${ issue . description } ` );
});
console . log ( " \n Recommendations:" );
analysis . recommendations . forEach (( rec , i ) => {
console . log ( ` ${ i + 1 } . ${ rec } ` );
});
}
}
if ( event . type === "turn.completed" ) {
console . log ( " \n Token usage:" , event . usage );
}
}