Repository navigation
[Bug] Reasoning effort selected in Codex Desktop is not propagated to routed DeepSeek and GLM models #1100
Description
Client or integration
Codex App
Area
Catalog / models
Summary
When a routed third-party model is selected in Codex Desktop with reasoning effort set to Max, the UI shows Max, but the actual request received by OpenCodex contains no reasoning effort.
The model is routed correctly, but Logs & Debug shows Effort: -, and the raw log contains none of:
requestedEfforteffectiveEffortreasoningWireFieldreasoningWireValue
This is reproducible with both DeepSeek and GLM, in direct conversations and in sub-agent paths.
Important nuance: in normal use, both GLM-5.2 Max and DeepSeek V4 Flash Max subjectively appear to have meaningful reasoning depth. This report is therefore about missing propagation/observability and the lack of a verifiable effort guarantee, not a claim that the upstream models definitely run without thinking.
Expected: when Codex Desktop displays Max for a routed model, the inbound Responses request should preserve the selected effort so OpenCodex can map it to the provider wire format and report the effective value.
Actual: the provider/model selection is preserved, but the reasoning effort is absent before the request reaches the provider adapter.
Reproduction
A. Direct DeepSeek conversation
-
Start OpenCodex and sync routed models into Codex.
-
Open a new Codex Desktop conversation.
-
Select
deepseek/deepseek-v4-flash. -
Select reasoning effort
Max. -
Send a no-tool prompt such as:
This is a reasoning effort propagation test. Do not call tools. Reply only: DIRECT_MAX_PROBE -
Inspect the request in OpenCodex Logs & Debug.
Observed:
Model: deepseek-v4-flash
Effort: -
Provider: deepseek
Status: 200
The request reports nonzero reasoningOutputTokens, so thinking is enabled, but the selected effort tier cannot be verified.
B. Direct GLM conversation
Provider setup:
- Custom provider using BigModel.cn Coding Plan
- Base URL:
https://open.bigmodel.cn/api/coding/paas/v4 - Model:
GLM/glm-5.2 - Adapter: OpenAI-compatible chat
Steps:
- Open a new Codex Desktop conversation.
- Select
GLM/glm-5.2. - Select reasoning effort
Max. - Send the same no-tool probe.
- Inspect the request in Logs & Debug.
Observed:
Model: glm-5.2
Effort: -
Provider: GLM
Status: 200
Again, no effort-related raw log fields are present.
C. Explicit V1 spawn_agent override
A gpt-5.6-sol Medium parent invoked V1 spawn_agent with:
model = deepseek/deepseek-v4-flash
reasoning_effort = max
fork_context = false
The child was created successfully and routed to DeepSeek without fallback, but the resulting DeepSeek requests again showed Effort: - and no effort-related raw log fields.
D. Custom agent role
A user-level Codex agent role was configured with:
model = "deepseek/deepseek-v4-flash"
model_reasoning_effort = "max"The role was registered and successfully selected through:
agent_type = deepseek_executor_max
fork_context = false
The role's developer instructions were applied correctly, and the child returned the expected role marker. The model was also correctly routed to DeepSeek, but the request still showed Effort: - with no effort-related raw log fields.
No provider fallback was observed in any reproduction.
Version
@bitkyc08/opencodex@2.10.1
Operating system
Windows 10, build 19045, x64
Provider and model
deepseek / deepseek-v4-flash- Custom
GLM / glm-5.2using BigModel.cn Coding Plan
Logs or error output
# Direct DeepSeek request
Model: deepseek-v4-flash
Effort: -
Provider: deepseek
Status: 200
# Sanitized raw log excerpt
{
"model": "deepseek-v4-flash",
"provider": "deepseek",
"admissionKind": "loopback",
"inboundProtocol": "responses",
"requestedModel": "deepseek/deepseek-v4-flash",
"resolvedModel": "deepseek-v4-flash",
"status": 200,
"routeDecision": {
"routeKind": "explicit-provider",
"selected": {
"provider": "deepseek",
"model": "deepseek-v4-flash",
"reason": "explicit-provider-namespace"
}
}
}
# Direct GLM request
Model: glm-5.2
Effort: -
Provider: GLM
Status: 200
# Sanitized raw log excerpt
{
"model": "glm-5.2",
"provider": "GLM",
"admissionKind": "loopback",
"inboundProtocol": "responses",
"requestedModel": "GLM/glm-5.2",
"resolvedModel": "glm-5.2",
"status": 200,
"routeDecision": {
"routeKind": "explicit-provider",
"selected": {
"provider": "GLM",
"model": "glm-5.2",
"reason": "explicit-provider-namespace"
}
}
}
# Missing from both request records
requestedEffort
effectiveEffort
reasoningWireField
reasoningWireValueScreenshots and supporting files
The behavior was reproduced in Codex Desktop and OpenCodex Logs & Debug. Sanitized raw logs are included above. No secrets or complete local paths are included.
Redacted configuration
{
"opencodexVersion": "2.10.1",
"client": "Codex Desktop for Windows",
"subAgentSurface": "v1",
"providers": {
"deepseek": {
"model": "deepseek-v4-flash",
"adapter": "openai-chat"
},
"GLM": {
"baseUrl": "https://open.bigmodel.cn/api/coding/paas/v4",
"model": "glm-5.2",
"adapter": "openai-chat"
}
}
}Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Activity
github-actions commentedon Aug 6, 2026
Automated translation bookkeeping — detected language: English.
github-actions commentedon Aug 6, 2026
Issue reopened
The report now contains the information required by the automated check. Thanks for updating it.
c3right commentedon Aug 6, 2026
Potentially related upstream Codex issues:
model_reasoning_effortis silently omitted for some custom/routed model slugs when fallback metadata does not mark the model as reasoning-capable. The reported symptom is an outbound Responses request withreasoning: nulldespite a configured effort.model_reasoning_effortwas not forwarded to third-party providers.Our reproduction differs in that opencodex has already generated routed catalog entries and Codex Desktop visibly offers
Max, yet the inbound request still reaches opencodex without any effort field for bothdeepseek/deepseek-v4-flashandGLM/glm-5.2. This may still share the same upstream request-construction gate around model metadata.lidge-jun commentedon Aug 6, 2026
Investigated this on current
devand against your 2.10.1. Thank you for the four-path reproduction — running the same probe through direct chat, a custom provider, V1spawn_agent, and a custom agent role is what makes the finding below provable rather than speculative, because all four failing while routing succeeds narrows the cause sharply.Your read is correct, and your upstream link openai/codex#30697 is the right one. The trigger, though, is metadata we emit.
What we found, in the order it matters:
1. Nothing arrives. Inbound parsing accepts only Responses
reasoning.effort(src/responses/schema.ts:126,144→src/responses/parser.ts:652), andrequestedEffortis assigned directly from that parsed value before routing (src/server/responses/core.ts:1379). SoEffort: -with norequestedEffortmeans the field is genuinely absent on the wire, not dropped by us. That holds in 2.10.1 too.2. Our request path does not drop it. For the GLM route, the OpenAI-chat adapter maps a parsed effort and writes
reasoning_effortplus the wire diagnostics (src/adapters/openai-chat.ts:759,771). For DeepSeek's Responses passthrough, the normalizers strip unsupported summary and context fields but never an effort (src/adapters/openai-responses.ts:171,193). Given an effort, both paths would carry it.3. The routed catalog we sync to Codex is internally contradictory. Every routed entry has
supports_reasoning_summariesdeleted and then defaulted tofalse(src/codex/catalog/parsing.ts:353then:266), whilesupported_reasoning_levelsis populated with a full ladder includingmax(src/codex/catalog/sync.ts:266,src/codex/catalog/effort.ts:150). Generated locally with no network,deepseek/deepseek-v4-flashcomes out assupported_reasoning_levels: ["low","high","max","ultra"]withsupports_reasoning_summaries: false;GLM/glm-5.2is the same shape. Nativegpt-5.6-solhas the ladder andtrue.That combination is exactly what openai/codex#30697 describes: Codex gates construction of the whole
reasoningobject on the capability flag, so the picker renders every level insupported_reasoning_levelswhile the outbound request omitsreasoningentirely. The picker showingMaxand the wire carrying nothing are consistent with each other under that gate.Worth being precise about why that
deleteexists — it is deliberate, not an oversight. The comment atparsing.ts:352says routed rows cloned from native templates must not inherit OpenAI-only summary delivery. Reasoning summaries are a different capability from reasoning effort, and we were right not to claim the former for arbitrary providers. The bug is that upstream appears to treat one flag as gating both, so being honest about summaries costs us effort propagation.One qualification against overclaiming. The missing
effectiveEffort/reasoningWire*fields are not independently decisive for DeepSeek, because the Responses passthrough has noreasoningLogproducer and those fields only populate when an adapter supplies one (src/server/request-log.ts:397).requestedEffortis the load-bearing signal. For GLM's chat route, a parsed effort would have produced them.On #1057/#1069: that shipped in v2.10.2, after your 2.10.1. It corrected DeepSeek's advertised ladder to what each model honors, but
maxwas already advertised and mapped in 2.10.1, so upgrading will not fix this. Please do not expect it to.What would settle it beyond doubt: one sanitized full HTTP body as it arrives at opencodex ingress for a single
Maxrequest. If it contains"reasoning":{"effort":"max"}, the defect is ours and we will chase it. Ifreasoningis absent or null, the upstream gate is confirmed and the fix is on the catalog side. Your existing Logs & Debug raw view should have this; redact anything sensitive.Keeping this open as a real defect, not as needs-info — the catalog contradiction is ours regardless of where the final fix lands, and there is currently no test asserting the joint contract that a routed model advertising reasoning levels also carries whatever flag Codex needs to emit
reasoning.effort. That gap is on us.Your closing nuance was the right instinct, by the way: nonzero
reasoningOutputTokensmeans the providers are thinking at their own defaults, so this is a lost-control and lost-observability problem rather than thinking being off.lidge-jun commentedon Aug 6, 2026
Follow-up with something actionable you can try today, plus what landed on our side.
There is a supported workaround, and it works for your exact provider shape. Set
modelSupportsReasoningSummariesfor the model in your provider config:I generated the catalog locally with your provider shape, no network, and compared with and without that one key:
That flag is what Codex gates the whole Responses
reasoningobject on, so setting it should make yourMaxselection actually reach the wire. The same applies to a DeepSeek entry you configure yourself.Be clear-eyed about what you are asserting when you set it. It tells Codex the model accepts reasoning-summary delivery. For GLM and DeepSeek that is very likely fine, and the field is documented today only as a way to turn summaries off — using it to turn them on is the other half of the same switch. If your endpoint rejects the resulting request shape, that is the signal to take it back out, and I would want to hear about it. Please report back either way: a confirmation that
Effort:starts showing a value is exactly the evidence that would close this issue.What we changed. Nothing in the request path — the investigation held up, and the effort genuinely is absent before it reaches us. What was missing on our side was any test asserting that the opt-in survives the routed-catalog normalization at all. It survives only because of the order of two calls in
src/codex/catalog/sync.ts, and a future reordering would have silently disabled effort propagation for every provider that opted in, with a green suite. That contract is now pinned by three tests, including one that fails if the order is swapped.What we deliberately did not change: routed models still default to
supports_reasoning_summaries: false. Claiming OpenAI-only summary delivery for every third-party endpoint would trade your problem for a harder one — requests failing at providers that reject the shape, for users who configured nothing. The per-model opt-in above is the honest version of that fix.So this stays open, and your upstream links remain the right thread to pull: if Codex gated on a reasoning-specific capability rather than on summaries, the default would not have to be a trade-off at all. If the workaround does not restore effort for you, that would point back at us and I would reopen the request-path investigation.
c3right commentedon Aug 7, 2026
Tested the documented per-model workaround successfully on Windows with
@bitkyc08/opencodex@2.10.2.I added only the following opt-in to each existing provider entry (no other provider fields were changed):
and separately:
After closing Codex, running Sync, reopening Codex, and starting fresh requests, reasoning effort propagation was restored for both providers.
GLM / BigModel Coding Plan
Provider endpoint:
Direct GLM requests succeeded with both
xhighandmaxselected in Codex.For
max, Logs & Debug showed:Sanitized raw-log fields:
{ "requestedModel": "GLM/glm-5.2", "requestedEffort": "max", "effectiveEffort": "max", "reasoningWireField": "reasoning_effort", "reasoningWireValue": "max", "resolvedModel": "glm-5.2", "status": 200 }xhighbehaved the same way:{ "requestedEffort": "xhigh", "effectiveEffort": "xhigh", "reasoningWireField": "reasoning_effort", "reasoningWireValue": "xhigh", "status": 200 }I also tested GLM as a V1 sub-agent from a
gpt-5.6-lunaparent running athigh. Both independently requested child efforts worked:luna/high-> childGLM/glm-5.2/max: PASSluna/high-> childGLM/glm-5.2/xhigh: PASSThe child logs again showed the requested/effective/wire effort values and HTTP 200.
DeepSeek V4 Flash
Direct
deepseek/deepseek-v4-flashwith Codex set toMaxnow shows:Sanitized raw-log fields:
{ "requestedModel": "deepseek/deepseek-v4-flash", "requestedEffort": "max", "resolvedModel": "deepseek-v4-flash", "status": 200 }A direct
xhighselection also arrived as:{ "requestedModel": "deepseek/deepseek-v4-flash", "requestedEffort": "xhigh", "resolvedModel": "deepseek-v4-flash", "status": 200 }I then tested DeepSeek as a V1 sub-agent from the same
gpt-5.6-luna/highparent, explicitly requestingdeepseek/deepseek-v4-flashatmax. The child completed successfully and its request showed:{ "requestedModel": "deepseek/deepseek-v4-flash", "requestedEffort": "max", "resolvedModel": "deepseek-v4-flash", "status": 200, "usage": { "reasoningOutputTokens": 530 } }So the workaround is working for both direct conversations and V1
spawn_agentmodel/effort overrides in my setup.One UI/logging difference confirmed
GLM shows the smaller gray wire-diagnostic line under the effort value, e.g.:
DeepSeek does not show that gray secondary line; it only shows
max(orxhigh) in the main Effort field. The DeepSeek raw log likewise hasrequestedEffortbut noeffectiveEffort/reasoningWireField/reasoningWireValue.This matches your earlier explanation that DeepSeek's Responses passthrough has no
reasoningLogproducer and thatrequestedEffortis the load-bearing signal there, while GLM's OpenAI-chat adapter produces the additional wire diagnostics.No 4xx/provider rejection or other obvious regression was observed during these tests.
fix(codex): propagate routed DeepSeek and GLM effort
fix(codex): reach custom-named providers, and keep summary defaults o…
docs(devlog): record the #1100 audit findings and the deferred BigMod…
22 remaining items
feat(xai): expose grok-4.20-multi-agent on the Responses lane
feat(xai): expose grok-4.20-multi-agent on the Responses lane
feat(xai): expose grok-4.20-multi-agent on the Responses lane (carry of
fix(xai): stop advertising text.verbosity, including on combo and liv…
fix(catalog): resolve the verbosity default from config, not the regi…
feat(xai): expose grok-4.20-multi-agent on the Responses lane (carry of
fix(codex): propagate routed DeepSeek and GLM effort
fix(codex): reach custom-named providers, and keep summary defaults o…
docs(devlog): record the lidge-jun#1100 audit findings and the deferr…
fix(providers): register BigModel's Coding Plan endpoint, which lidge…
test(catalog): pin the custom-provider reasoning-summary opt-in (lidg…
Merge pull request lidge-jun#1274 from lidge-jun/codex/260808-1100-cu…
fix(xai): stop advertising text.verbosity, including on combo and liv…
fix(catalog): resolve the verbosity default from config, not the regi…
feat(xai): expose grok-4.20-multi-agent on the Responses lane (carry of