Skip to content

[LLM-Gen] Codex Responses API Subset Analysis

Human Motivation

I asked the code agent to compare the OpenAI /response API with Codex usage, as I want to know:

  • How Codex uses the /response API
  • What features offered by the /response API are not used by Codex

The OpenAI /response API documentation is extensive. It doesn't make sense to analyze it manually.


Generated Docs

The following content analyzes the differences between the OpenAI Responses API specification and the Codex Rust implementation (ResponsesApiRequest in codex-rs/codex-api/src/common.rs).

1. Architectural Positioning

Codex implements a subset of the OpenAI Responses API with two core architectural differences:

1.1 State Management

Aspect OpenAI API Codex Trade-off
Conversation state Server-side (conversation, previous_response_id) Client-side (ContextManager) Codex: full control for editing/compression; OpenAI: simpler client logic
History transmission Optional incremental Required full history Bandwidth cost mitigated by prompt_cache_key for prefix caching
State persistence OpenAI servers Local storage Enables stateless architecture and complex context operations
Caching Built-in conversation cache prompt_cache_key for prefix caching Leverages OpenAI's prefix caching to avoid reprocessing

1.2 Parameter Simplification

Codex removes generative tuning parameters:

  • Sampling: temperature, top_p, top_logprobs
  • Resource limits: max_output_tokens, max_tool_calls
  • Stream options: stream_options, truncation

Rationale: Optimized for code generation with model defaults. Use OpenAI SDK directly if fine-grained control is needed.


2. API Schema Mapping

JSON structure showing OpenAI Responses API request fields with Codex support status:

{
  // ===== Core Parameters =====
  "model": "[weak] String (no Enum constraint)",
  "instructions": "[full] string",
  "input": "[subset+extension] Vec<ResponseItem>, see Section 3",

  // ===== Tool Control =====
  "tools": "[weak] Vec<serde_json::Value> (avoids 12+ type union)",
  "tool_choice": "[simplified] string only (e.g. \"auto\"), no object constraint",
  "parallel_tool_calls": "[full] boolean",

  // ===== Generation Control =====
  "temperature": "[not supported] uses model default",
  "top_p": "[not supported] uses model default",
  "top_logprobs": "[not supported] uses model default",
  "max_output_tokens": "[not supported] uses model default",
  "max_tool_calls": "[not supported] uses model default",
  "reasoning": "[full] { effort?, summary? }",
  "text": "[partial] json_schema format only",
  "stream": "[full] SSE streaming",

  // ===== State Management (architectural difference, not supported) =====
  "conversation": "[not supported] Codex uses client-side state",
  "previous_response_id": "[not supported] Codex uses client-side state",
  "prompt": "[not supported] use input field instead",
  "prompt_cache_retention": "[not supported] uses model default",

  // ===== Optimization Options =====
  "prompt_cache_key": "[full] string key for prefix caching",
  "service_tier": "[weak] Option<String> (no Enum constraint)",
  "include": "[weak] Vec<String> (no enum validation)",

  // ===== Metadata (not supported) =====
  "metadata": "[not supported]",
  "user": "[not supported] use session-level identifier",

  // ===== Other (not supported) =====
  "background": "[not supported]",
  "context_management": "[not supported]",
  "safety_identifier": "[not supported]",
  "stream_options": "[not supported]",
  "truncation": "[not supported]"
}

Legend:

  • [full] - Fully implemented
  • [weak] - Implemented but relaxed type constraints (Enum → String)
  • [simplified] - Partial implementation, complex features removed
  • [partial] - Only subset of sub-features supported
  • [not supported] - Not implemented, uses model default or architectural alternative

Coverage:

  • By field count: ~50% (13 of 30 fields)
  • Weighted by functionality: ~60% (core features complete, tuning params and metadata missing)

3. Input Field Processing

OpenAI API accepts 25+ input types. Codex represents all as Vec<ResponseItem> and filters/transforms before transmission.

3.1 Supported OpenAI Standard Types

Sent directly to OpenAI:

ResponseItem Variant OpenAI Type
Message EasyInputMessage / ResponseOutputMessage
Reasoning Reasoning
FunctionCall FunctionCall
FunctionCallOutput FunctionCallOutput
WebSearchCall WebSearchCall
ImageGenerationCall ImageGenerationCall

3.2 Codex-Specific Extensions

Internal types processed by ContextManager::for_prompt() before transmission:

Type Purpose Pre-transmission Processing
LocalShellCall Local shell command execution Ensures call_id has corresponding FunctionCallOutput
CustomToolCall Custom tool invocation Ensures call_id has corresponding CustomToolCallOutput
CustomToolCallOutput Custom tool result Kept in history for context
GhostSnapshot Compression snapshot (GhostCommit) Filtered out, not transmitted
Compaction Encrypted compression summary Used for token estimation
Other Fallback for unknown types Forward compatibility

3.3 Transformation Pipeline

Internal ResponseItem Vec
┌─────────────────────────────────────────┐
│ ContextManager::for_prompt()            │
│                                         │
│ 1. normalize_history()                  │
│    - ensure_call_outputs_present()      │
│    - remove_orphan_outputs()            │
│    - rewrite_image_generation_calls()   │
│    - strip_images_when_unsupported()    │
│                                         │
│ 2. retain(|item| !GhostSnapshot)        │
└─────────────────────────────────────────┘
Ready for OpenAI ResponseItem Vec
    JSON Serialization
   OpenAI API Request

4. Type Safety and Engineering Trade-offs

Codex uses "relaxed exterior, strict interior" typing strategy:

4.1 Weak Types at External Boundaries

  • model, service_tier, include: Enum → String
  • tools: 12+ type union → Vec<serde_json::Value>

Benefits:

  • Forward compatibility: new fields/values require no code changes
  • Reduced maintenance: avoids syncing OpenAI's massive type definitions
  • Decoupled upgrades: API changes don't block compilation

Costs:

  • Runtime validation: invalid values rejected at request time
  • Lost autocomplete: IDE can't provide enum completion

4.2 Strong Types Internally

  • input field uses Vec<ResponseItem> enum for full type safety in memory
  • Enables complex context operations (editing, compression, rollback) without breaking structure

4.3 Engineering Conclusion

Layered strategy prioritizes flexibility and compatibility at system boundaries (API interaction) while maintaining type safety and maintainability internally (state management).


5. Code Comparison

5.1 OpenAI Standard API

const response = await openai.responses.create({
  model: "gpt-5",
  conversation: "conv_abc123",           // server-side state
  input: "New user message",             // simplified input
  temperature: 0.8,                      // sampling control
  max_output_tokens: 4000,               // resource limit
  tool_choice: {                         // complex constraint
    type: "allowed_tools",
    mode: "required",
    tools: [{ type: "function", name: "get_weather" }]
  }
});

5.2 Codex Implementation

let request = ResponsesApiRequest {
    model: "gpt-5".to_string(),          // String, no enum
    instructions: "System instructions".to_string(),
    input: vec![                          // full history, ResponseItem enum
        /* Message, FunctionCall, FunctionCallOutput, ... */
    ],
    tools: vec![                          // Vec<Value>, no types
        /* tool definitions as JSON */
    ],
    tool_choice: "auto".to_string(),      // simplified string
    parallel_tool_calls: true,
    reasoning: Some(Reasoning {
        effort: Some(ReasoningEffortConfig::Medium),
        summary: Some(ReasoningSummaryConfig::Auto),
    }),
    store: false,
    stream: true,
    prompt_cache_key: Some(conversation_id),
    // no temperature, top_p, max_output_tokens
    // no conversation, previous_response_id
};

Document Version: 5.0 (Restructured) Generated: 2025-03-11 Based on: spec.md and codex-rs/codex-api/src/common.rs