Integration guides ยท 2026-08-29

An LLMTR model provider for Codex CLI and its Responses-only constraint

Codex CLI has narrowed its wire protocol to a single variant. This guide covers the provider table in the configuration file, why model selection is limited to identifiers with a Responses binding, and how reasoning effort is set.

LLMTR guide diagram showing the one-way protocol bridge from the Codex CLI configuration file into the Responses endpoint of the LLMTR gateway, with chat-only models filtered out.

The wire protocol now has a single variant

Codex CLI needs no separate build or patch; the provider definition lives in your own configuration file. That flexibility has one hard edge, and the rest of this guide turns around it: the tool's protocol enumeration currently holds exactly one variant, Responses.

The enumeration in the source accepts only the responses value, and that value is also the default. The former chat value is now rejected with a dedicated message, and any unrecognised value makes the parser report responses as the only valid option. There is no route back to the chat completion protocol on the tool side.

Message returned when the old protocol value is used in configuration

`wire_api = "chat"` is no longer supported.
How to fix: set `wire_api = "responses"` in your provider config.

Writing the provider table into the configuration file

Providers come from two places: built-in defaults compiled into the binary, and entries under the model_providers key in the user's configuration file. The built-in set is deliberately small, holding openai, two Amazon Bedrock entries and the local ollama and lmstudio runners. Leaving third-party providers to the user is described in the source as an intentional choice.

One behaviour is easy to miss: built-in entries are not generally overridable. For keys other than Bedrock the merge keeps the existing record and inserts yours only when the key is free. If you try to redefine openai so it points at LLMTR, your record is discarded without a message. Pick a fresh identifier instead.

The field names come straight from the provider record. The base URL carries its path suffix: the built-in default also ends in /v1, and the endpoint path is appended to it. The key is never written into the file; env_key names an environment variable, and an empty value makes the tool report the missing variable by name. Because the record schema rejects unknown fields, a single mistyped field name invalidates the whole configuration.

An LLMTR provider record added to the user configuration

model_provider = "llmtr"
model = "openai/gpt-5.3-codex"

[model_providers.llmtr]
name = "LLMTR"
base_url = "https://llmtr.com/v1"
env_key = "LLMTR_API_KEY"
wire_api = "responses"

The bridge runs one way, so the model list narrows

Every model on LLMTR carries one or more bindings. A request arriving at the Responses endpoint works only for identifiers that hold a Responses binding; there is no path that lifts a chat-completions model onto that endpoint. Since Codex CLI speaks nothing else, the two constraints stack and the selectable set shrinks to a subset of the catalog.

The practical rule is simple: check the supported operations of an identifier in the catalog before you write it into the configuration. A chat-bound identifier does not fail at load time, it fails on the first call, and what you see in the terminal is an endpoint mismatch. The table below compares several identifiers that exist in the catalog today through exactly that lens.

Codex CLI compatibility against the catalog state on 29 August 2026
Model identifierBinding in catalogStatus with Codex CLI
openai/gpt-5.3-codexRESPONSESCallable
openai/gpt-5.5RESPONSESCallable
xai/grok-4.6RESPONSESCallable
google/gemini-3.1-pro-previewCHAT_COMPLETIONS and RESPONSESCallable
anthropic/claude-sonnet-5CHAT_COMPLETIONSNot callable on this endpoint
deepseek/deepseek-v4-proCHAT_COMPLETIONSNot callable on this endpoint
llmtr/gemma-4CHAT_COMPLETIONSNot callable on this endpoint

Watch for retired identifiers in the Codex family

One finding from preparing this guide deserves its own note: most Codex model identifiers used as examples in the Responses endpoint documentation are now retired in the catalog. Retired records stay reachable and their pages stay published, but they should not be copied into a fresh setup.

The only Codex identifier live today is openai/gpt-5.3-codex. If you are carrying an older configuration, replace the model line with it. Re-checking an identifier against the catalog costs less than discovering the problem on the first call.

Retired Codex identifiers and their live counterpart as of 29 August 2026
Retired identifierCatalog stateLive counterpart
openai/gpt-5-codexRetiredopenai/gpt-5.3-codex
openai/gpt-5.1-codexRetiredopenai/gpt-5.3-codex
openai/gpt-5.1-codex-maxRetiredopenai/gpt-5.3-codex
openai/gpt-5.1-codex-miniRetiredopenai/gpt-5.3-codex
openai/gpt-5.2-codexRetiredopenai/gpt-5.3-codex

Reasoning effort has two entry points

The Responses endpoint accepts a reasoning level in two ways: a suffix appended to the model identifier, or a reasoning object in the request body. When both are present the body wins. From Codex CLI it is more practical to use the suffix, because the configuration already carries a model line and the body is produced by the tool.

The levels are minimal, low, medium, high and xhigh, with short suffix aliases such as med and max. An unsupported level returns 400 with a capability error, and an unrecognised suffix returns 400 as an invalid request. Higher levels usually produce more output tokens and longer runs, and because billing is token based, the level you pin is a cost decision.

  • The suffix is appended to the identifier with a colon and lives on the model line
  • The body field is useful when a single request should run at a different level
  • If both are supplied, the body field takes precedence
  • Unrecognised suffixes are not ignored quietly, the request is rejected

Pinning the reasoning level as a suffix on the model line

model_provider = "llmtr"
model = "openai/gpt-5.3-codex:high"

[model_providers.llmtr]
name = "LLMTR"
base_url = "https://llmtr.com/v1"
env_key = "LLMTR_API_KEY"
wire_api = "responses"
request_max_retries = 4

Verification and separating the failure classes

Before running the tool, send the same identifier to the endpoint in a single request. That is the fastest way to split a configuration fault from a model-selection fault: if the direct call works, the problem is in the provider record, and if it fails here too, the problem is the identifier.

It helps to sort failures into three groups by origin. Configuration parse errors appear at startup and point at a field in the file. Credential errors appear when the environment variable cannot be read and name that variable. Endpoint errors arrive on the first call, and the error type in the body names the constraint you crossed.

  • An endpoint mismatch means the chosen model has no Responses binding
  • A capability error means the model does not support the requested reasoning level
  • An authentication error means the variable named by env_key is empty or invalid
  • A balance error means credit needs topping up; the platform margin applies only on credit top-up and is eight percent

Testing the model identifier independently of the tool

export LLMTR_API_KEY=llmtr-your_key

curl https://llmtr.com/v1/responses \
  -H "Authorization: Bearer $LLMTR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"openai/gpt-5.3-codex","input":"ping"}'

Frequently asked questions

Do I need a separate build of Codex CLI?

No. The provider record is added to the user configuration and the tool merges it into the built-in list. There is no modified binary and no separate repository to track; all it takes is a correctly spelled model_providers table and an environment variable holding the key.

Why can I not select a chat-completions model?

The tool speaks only the Responses protocol, and on LLMTR the Responses endpoint accepts only identifiers that carry a Responses binding. Both constraints point the same way, so there is no bridge in the opposite direction. Check the supported operations of an identifier in the catalog before writing it down.

Can I repoint the built-in openai record at LLMTR?

In practice, no. For built-in keys other than Bedrock the merge keeps the existing record and your entry is never inserted. Because the result is a silent no-op rather than an error, it is awkward to diagnose. Use an unused identifier such as llmtr instead.

How does a higher reasoning level affect cost?

Higher levels usually produce more output tokens and longer runs. Since billing is token based, that lands directly on consumption. Setting the level per task is more measured than carrying a fixed high value into every session.

Related posts