model_reasoning_effort not forwarded to third-party providers (Chat never sends `reasoning_effort`; Responses gated by model slug)
What version of Codex is running?
codex-cli 0.64.0
What subscription do you have?
gpt-5.1-codex via ZenMux API
Which model were you using?
gpt-5.1-codex
What platform is your computer?
Microsoft Windows NT 10.0.19045.0 x64
What issue are you seeing?
Configured model_reasoning_effort = "high" (and model_reasoning_summary = "auto"). When routing via a custom provider (base_url points to a relay that adds an openai/ prefix to model names), Codex does not forward reasoning controls:
- Chat wire (POST /v1/chat/completions): Body never contains a top‑level
"reasoning_effort"key. - Responses wire (POST /v1/responses):
"reasoning"becomesnullunless the model slug matches specific patterns (appears tied to CONTEXT_WINDOW_272K‑related checks). With the relay’sopenai/prefix, the slug check never matches, so"reasoning"staysnull.
Representative (redacted) downstream log (Chat wire): POST /chat/completions Headers: { "authorization": "Bearer ****(masked)", "accept": "text/event-stream", ... } JSON Body:
{
"model": "openai/gpt-5.1-codex",
"messages": [
{"role":"system","content":"..."},
{"role":"user","content":"test"}
]
// No "reasoning_effort" present
}
Code pointer found while investigating:
pub(crate) fn get_model_info(model_family: &ModelFamily) -> Option<ModelInfo> {
let slug = model_family.slug.as_str();
match slug {
// ...
_ if slug.starts_with("gpt-5-codex")
|| slug.starts_with("gpt-5.1-codex")
|| slug.starts_with("gpt-5.1-codex-max") => {
Some(ModelInfo::new(CONTEXT_WINDOW_272K))
}
_ if slug.starts_with("gpt-5") => Some(ModelInfo::new(CONTEXT_WINDOW_272K)),
_ if slug.starts_with("codex-") => Some(ModelInfo::new(CONTEXT_WINDOW_272K)),
_ if slug.starts_with("exp-") => Some(ModelInfo::new(CONTEXT_WINDOW_272K)),
_ => None,
}
}
Observation (correlation, not proof): In our testing, models whose names match the above prefixes tend to produce a non-null "reasoning" in responses mode, while names that do not match (relay prefixes them with openai/…) result in "reasoning": null.
What steps can reproduce the bug?
- Start a local transparent proxy to print requests and forward to the real third‑party relay (any simple HTTP proxy that dumps JSON is fine).
- Configure Codex to use a custom provider with that proxy’s
base_url.
config.toml (redacted)
model = "openai/gpt-5.1-codex"
model_provider = "my3p"
model_reasoning_effort = "high"
model_reasoning_summary = "auto"
[model_providers.my3p]
name = "ThirdParty"
base_url = "http://127.0.0.1:8787/v1" # points to local proxy
env_key = "THIRDPARTY_API_KEY"
wire_api = "chat" # also test "responses"
- Run Codex once (any trivial prompt, e.g., “test”).
- Inspect the proxy logs.
Observed:
- With
wire_api="chat"→ body lacks"reasoning_effort". - With
wire_api="responses"→"reasoning"isnullunless the model slug matches internal patterns; when the relay prefixes model withopenai/…, it never matches, so"reasoning"staysnull.
Note: The relay consistently rewrites the model name to include openai/ (e.g., openai/gpt-5.1-codex).
What is the expected behavior?
- When
model_reasoning_effortis set in config:- Chat wire should include a top‑level
"reasoning_effort": "<low|medium|high|minimal>"in the request body. - Responses wire should include
"reasoning": { "effort": "<…>", "summary": "<auto|…>" }".
- Chat wire should include a top‑level
- Emission of these fields should not depend on model‑name heuristics or context‑window families. Providers that don’t support the field can reject it server‑side.
Additional information
No response
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
- #6375
- #5775
Powered by Codex Action
+1 on this issue.
Another use case is when the model name on the deployment doesn't match at all. So maybe we want abstract deployments called default and think-harder that happen to map behind the scenes to gpt-5.1-codex and gpt-5.1-codex-max, respectively. Ideally, Codex CLI wouldn't need to interrogate my model names to try to guess whether I'm allowed to change things like model_reasoning_effort and should instead trust that I know what I'm doing. Furthermore, when gpt-5.2-codex models come out, I shouldn't necessarily have to update Codex CLI in order for it to work.
I do realize that Codex is interrogating names for good reasons, like deciding which prompts to use. Perhaps there should be a more explicit setting like model_family that can be set in config.toml to allow this?