Responses API vs Chat Completions for Codex

Responses API vs Chat Completions explains why Codex provider compatibility needs more than a base URL change.

By Dora 10 min read
Responses API vs Chat Completions for Codex

For Codex provider work, Responses ​API​ vs Chat Completions is not a naming debate. It is a runtime contract question. A chat app can survive with a simple message list, one response, and a few streamed text chunks. A coding agent cannot. It needs long task state, tool calls, command output, file edits, cancellations, retries, and enough event detail to recover when something breaks halfway through.

The practical takeaway is simple: changing a base ​URL​ is not the same as becoming Codex-compatible.

Why Codex Provider Compatibility Is Hard

Base URL compatibility versus protocol compatibility

A base ​URL​ tells Codex where to send requests. It does not prove that the provider speaks the same protocol. The official Codex configuration docs describe custom model providers in terms of base URL, authentication, optional headers, and wire API behavior. That distinction matters because Codex wire_api is not cosmetic. It decides what request shape, streaming format, tool state, and response semantics Codex expects.

This is where provider claims often get blurry. “OpenAI-compatible” may mean only that /v1/chat/completions accepts a familiar JSON body. For Codex, compatibility has to cover the full agent loop: instructions, tool calls, partial output, errors, retries, and state reconstruction.

Codex third-party models can be useful behind gateways, routers, or private deployment layers. The risk is treating the gateway as a translation sticker. If the upstream model only supports a chat-shaped interaction, the provider layer still has to decide what to do with response IDs, reasoning metadata, structured output, and event lifecycles.

I paused here because this is usually where production bugs start.

Why coding agents expose edge cases faster than chat apps

Coding agents create hostile protocol tests without trying. ​They run for minutes, not seconds. They open files, produce patches, call shell tools, wait for command output, and resume after interruptions. They may generate partial edits, then cancel, then retry with a different plan.

A normal chatbot can lose a streamed token and still look fine. A coding agent can lose a tool call boundary and corrupt task state. It can duplicate a command, apply a stale patch, or continue from an outdated assumption.

That is why Codex compatibility needs to be tested with agent behavior, not only with “hello world” prompts.

Responses API vs Chat Completions

Message format, state, previous_response_id, and event model

The official Responses API overview frames Responses as OpenAI’s newer interface for model output, multimodal input, built-in tools, function calling, and stateful interactions. For agent infrastructure, the key idea is that a response request carries input, while the returned response object contains an ID, output items, status, usage, tool configuration and activity, and continuation-related fields.

Chat Completions is older and simpler. The Chat Completions API reference centers on a list of messages and a returned completion. It works well for many chat products, but Codex pushes beyond basic chat. The provider has to represent task history, tool output, cancellations, and replayable state.

One major difference is previous_response_id. In the Responses model, a request can point to a prior response so the server-side state chain can continue. That is not the same as sending a manually rebuilt array of chat messages. It changes who owns state and how much the provider must remember.

A compact comparison:

AreaResponses APIChat Completions
Conversation stateCan use response-linked state such as previous_response_idUsually client rebuilds message history
StreamingRich event lifecycleChunk-based deltas
ToolsOutput items and tool-call argument eventsTool calls in chat message deltas
Agent fitBetter for long-running agent workflowsWorks for simpler chat flows, weaker for Codex edge cases

This is also where instruction handling matters. Responses supports developer and system instructions with precedence over user input. If a gateway flattens those into ordinary messages, it may pass casual tests while weakening agent control in real work.

Tool calls, reasoning traces, structured output, and streaming events

Tool calling is not just “the model returned JSON.” A provider has to preserve the tool schema, the call identity, the argument stream, the final arguments, the tool result, and the next model step. If any of those are collapsed into plain text, Codex loses control of the task.

Reasoning creates a second compatibility pressure. Some models expose reasoning configuration or reasoning-related output differently. A provider does not need to invent reasoning support it does not have, but it must be honest about what is passed through, ignored, transformed, or unavailable.

Structured output has the same rule. If a model or gateway claims JSON schema support, Codex-facing docs need to say whether strict schema behavior is actually enforced. “Usually valid JSON” is not the same as structured output support.

Streaming is where this becomes visible. Chat Completions streams chunks. Responses streams typed events. A UI or agent runtime can use those events to understand whether the model is creating text, building function arguments, finishing an item, failing, or ending the response.

Where Protocol Conversion Breaks

SSE mapping, partial deltas, tool state, cancellations, and retries

Responses protocol conversion is possible in narrow cases, but it is not a lossless mapping by default. The official Responses streaming events include lifecycle events such as response creation, output item creation, text deltas, function-call argument deltas, completion, failure, and incomplete states. Chat Completions streaming is shaped around completion chunks.

A converter has to answer several awkward questions:

Does the upstream stream expose enough information to emit a real output item lifecycle? Can partial function arguments be streamed safely? Can the converter tell the difference between a text delta and a tool argument delta? Can it produce stable item IDs? Can it mark a response as incomplete instead of pretending it completed?

Cancellations are another hard case. If Codex cancels a response while a tool call is forming, the provider needs to stop generation, clean up partial output, and report a state the client can understand. If cancellation is only a dropped HTTP connection, the upstream model may keep running. That can create duplicate tool calls or confusing audit trails.

Retries need equal care. A retry after a network failure must not blindly repeat a sensitive command or commit a duplicated action. For coding tasks, command output and file state are part of the conversation. A provider should keep enough IDs, timestamps, and error details to explain what happened.

Context reconstruction and developer/system instruction handling

State reconstruction is where many gateways quietly bend the truth. The official conversation state guide is the right reference point for how OpenAI describes state across turns. If a client sends previous_response_id, the provider must either support that state model or reject it clearly. Silently converting it into a best-effort message list can change behavior.

Developer and system instructions are especially sensitive. Codex uses instruction hierarchy to preserve task rules, safety constraints, and environment behavior. A provider that merges every role into a single prompt string may still generate good-looking text, but it is not preserving the same contract.

The same applies to tool outputs. Tool results are not normal user messages. They are execution records with a specific place in the loop. If the converter loses that structure, later model steps may reason from the wrong source.

This is where my data ends for broad claims: a provider can say it is compatible only after its own implementation is tested against the actual Codex paths it plans to support.

What a Provider Must Support for Codex

Long tasks, file edits, command output, tool calls, and recovery

For Agent API compatibility, I would treat these as the minimum production bar.

First, long task stability. ​Codex sessions can sit inside a task for a long time, with streaming output, idle gaps, command execution, and retries. The provider needs sane timeouts, retry behavior, and error surfaces that do not erase task context.

Second, file-edit awareness. The model may propose changes, inspect files, revise patches, and respond to test failures. The provider does not edit files itself, but it must preserve the conversation state that lets Codex coordinate those steps.

Third, command output handling. Shell output can be large, partial, delayed, or noisy. A compatible provider should tolerate long context, structured tool outputs, and follow-up reasoning based on logs.

Fourth, tool-call correctness. Tool names, schemas, arguments, IDs, and outputs need to survive streaming, retries, and cancellation. If tool calls are unsupported, the docs should say so plainly.

Fifth, recovery. Failures are normal in coding-agent work. The important question is whether Codex can continue after a dropped connection, malformed tool output, partial stream, rate limit, or model-side refusal. A provider that only works on clean single-turn requests is not production-compatible for Codex.

Current Codex configuration docs define responses as the only supported wire_api value. Chat Completions was a deprecated legacy provider path and is no longer a current Codex target, so new provider work must implement the Responses protocol.

FAQ

Who approves protocol claims before publishing provider docs?

Protocol claims should be approved by the platform engineering owner, the agent runtime owner, and the docs or developer relations owner. Marketing alone should not approve “Codex-compatible” language.

The approval packet should include request and response samples, streaming logs, supported wire_api settings, tool-call tests, cancellation tests, retry behavior, and state handling notes. If previous_response_id is only partially supported, the public wording needs to say that directly.

What evidence should support collect for compatibility disputes?

Support should collect the Codex version, provider configuration, model name, base URL class, wire_api value, timestamps, request IDs, raw error bodies, SSE event logs, tool schemas, tool-call IDs, cancellation timing, retry attempts, and the relevant response chain.

For customer-sensitive sessions, logs should be redacted with a repeatable policy. The goal is not to store everything forever. The goal is to keep enough evidence to reconstruct whether the provider, gateway, model, tool, or client state caused the failure.

How should teams label partially compatible providers?

Use narrow labels. “Responses-compatible for text streaming” is better than “Codex-compatible” if tools and state are missing. “Chat Completions-compatible only; not supported by the current Codex wire_api” is clearer than hiding the risk. “Tool calling not supported” is better than letting users discover it during a live task.

A full compatibility label should require tested support for streaming, tool calls, state, long tasks, cancellations, retries, and error recovery.

Conclusion

Responses API vs Chat Completions matters for Codex because Codex is not just asking for text. It is running an agent loop. Base URL compatibility can start the connection, but protocol compatibility keeps the task alive.

For provider teams, the clean path is to document the exact protocol surface, test real coding-agent workflows, and avoid broad compatibility claims until state, tools, streaming events, and recovery all behave predictably. That is less glamorous than a one-line “OpenAI-compatible” badge, but it is the part users feel when the task gets hard.


Previous posts: