You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Route Codex (global model_reasoning_effort = "ultra", so requests carry effort max) to a local ollama model: hf.co/JonathanColetti/Qwen3.8-27B-Uncensored-GGUF:Q4_K_M (27B Q4_K_M GGUF with an embedded Jinja chat template). The template validates reasoning_effort against exactly xhigh/medium/low and — crucially — its top mode is only selected when the field is absent:
I want a working ladder: low/medium for fast turns, deep thinking (template xhigh) for high/xhigh/max/ultra.
What prevents this today?
1. Default behavior is a hard 500 retry loop. With the stock ollama provider config (adapter: openai-chat, baseUrl: http://localhost:11434/v1) the requested effort is forwarded as-is. ollama returns 500 and Codex retries indefinitely (usage.jsonl):
{"requestedModel":"ollama/qwen3.8-uncensored:27b-q4","requestedEffort":"max","effectiveEffort":"max",
"reasoningWireValue":"max","status":500,"errorCode":"upstream_server_error",
"upstreamError":"Provider error 500: ... Jinja Exception: Unexpected reasoning effort max. Supported types are xhigh (default), medium, and low."}
2. ollama ≥0.32 normalizes effort values before template rendering, so even ladder-correct values fail. Empirically verified on ollama 0.32.15 (probing which template instruction the model actually received):
wire value sent to ollama /v1/chat/completions
value the template sees
result
(field omitted)
default xhigh
✅ deep mode
minimal
low
✅
low
low
✅
medium
medium
✅
high
high
❌ 500
xhigh, ultra, max
max (normalized by ollama)
❌ 500
none
thinking disabled
✅
So the template's xhigh mode is unreachable through any wire value — only by omitting reasoning_effort entirely.
3. No existing config can express per-effort omission.
modelReasoningEffortMap can only rewrite values; every reachable wire value ≥ high is rejected upstream.
noReasoningModels omits the field for all efforts, losing low/medium control.
clampToSupportedCodexEffort cannot help either: the failure is on the wire, not in the Codex ladder.
What should OpenCodex do?
Support per-effort omission. Minimal change: treat a sentinel wire value (e.g. "__omit__") in reasoningEffortMap/modelReasoningEffortMap as "drop reasoning_effort from the body". Verified locally against 2.29.0 with this one-line patch in src/adapters/openai-chat.ts:
Verified end-to-end through the proxy: max → HTTP 200 with the model confirming the template's xhigh instruction; low → HTTP 200 with the low instruction.
Optionally, also document (or registry-default for the ollama provider) that xhigh is never a safe wire value under ollama ≥0.32, since ollama collapses xhigh/ultra/max to max before the template sees it.
noReasoningModels — works but forces deep mode for every turn and removes effort control.
Editing the model's embedded GGUF template is not viable via Modelfile: ollama create parses TEMPLATE as a Go template and rejects this Jinja (template error: function "content" not defined).
Environment
opencodex 2.29.0 (@bitkyc08/opencodex on npm), service mode on Windows 11 x64
Related: #1870, #2279 (catalog-layer synthetic rungs). This is the wire-layer counterpart: even with an exact catalog ladder, requests still need per-effort field omission for templates like this one.
Area
Providers / reasoning-effort mapping (openai-chat adapter, ollama provider)
What are you trying to accomplish?
Route Codex (global
model_reasoning_effort = "ultra", so requests carry effortmax) to a local ollama model:hf.co/JonathanColetti/Qwen3.8-27B-Uncensored-GGUF:Q4_K_M(27B Q4_K_M GGUF with an embedded Jinja chat template). The template validatesreasoning_effortagainst exactlyxhigh/medium/lowand — crucially — its top mode is only selected when the field is absent:I want a working ladder:
low/mediumfor fast turns, deep thinking (templatexhigh) forhigh/xhigh/max/ultra.What prevents this today?
1. Default behavior is a hard 500 retry loop. With the stock ollama provider config (
adapter: openai-chat,baseUrl: http://localhost:11434/v1) the requested effort is forwarded as-is. ollama returns 500 and Codex retries indefinitely (usage.jsonl):{"requestedModel":"ollama/qwen3.8-uncensored:27b-q4","requestedEffort":"max","effectiveEffort":"max", "reasoningWireValue":"max","status":500,"errorCode":"upstream_server_error", "upstreamError":"Provider error 500: ... Jinja Exception: Unexpected reasoning effort max. Supported types are xhigh (default), medium, and low."}2. ollama ≥0.32 normalizes effort values before template rendering, so even ladder-correct values fail. Empirically verified on ollama 0.32.15 (probing which template instruction the model actually received):
xhighminimallowlowlowmediummediumhighhighxhigh,ultra,maxmax(normalized by ollama)noneSo the template's
xhighmode is unreachable through any wire value — only by omittingreasoning_effortentirely.3. No existing config can express per-effort omission.
modelReasoningEffortMapcan only rewrite values; every reachable wire value ≥highis rejected upstream.noReasoningModelsomits the field for all efforts, losinglow/mediumcontrol.clampToSupportedCodexEffortcannot help either: the failure is on the wire, not in the Codex ladder.What should OpenCodex do?
Support per-effort omission. Minimal change: treat a sentinel wire value (e.g.
"__omit__") inreasoningEffortMap/modelReasoningEffortMapas "dropreasoning_effortfrom the body". Verified locally against 2.29.0 with this one-line patch insrc/adapters/openai-chat.ts:with provider config:
Verified end-to-end through the proxy:
max→ HTTP 200 with the model confirming the template'sxhighinstruction;low→ HTTP 200 with thelowinstruction.Optionally, also document (or registry-default for the ollama provider) that
xhighis never a safe wire value under ollama ≥0.32, since ollama collapsesxhigh/ultra/maxtomaxbefore the template sees it.Alternatives or workarounds
noReasoningModels— works but forces deep mode for every turn and removes effort control.ollama createparses TEMPLATE as a Go template and rejects this Jinja (template error: function "content" not defined).Environment
@bitkyc08/opencodexon npm), service mode on Windows 11 x64Related: #1870, #2279 (catalog-layer synthetic rungs). This is the wire-layer counterpart: even with an exact catalog ladder, requests still need per-effort field omission for templates like this one.