From 2f78beebb872701255b4f7d98186f3114be3f407 Mon Sep 17 00:00:00 2001 From: joelbrilliant Date: Tue, 21 Jul 2026 13:31:19 +1000 Subject: [PATCH 1/2] fix(codex): clamp reasoning effort max/ultra to xhigh on Responses wire Codex/OpenAI Responses rejects reasoning.effort=max with HTTP 400 invalid_value (allowed: none|minimal|low|medium|high|xhigh). Hermes config and generic effort ladder still use max/ultra; previously gpt-5.6 even mapped ultra to max on the wire. Clamp max and ultra to xhigh for the Codex Responses path (xAI still caps stronger levels at high). Covers fallback swaps onto openai-codex with a global agent.reasoning_effort of max. Evidence: desktop session 20260721_060132_be3b5e agent.log 11:31:52. Signed-off-by: joelbrilliant --- agent/transports/codex.py | 11 ++++--- .../agent/transports/test_codex_transport.py | 29 ++++++++++++++++--- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/agent/transports/codex.py b/agent/transports/codex.py index 15dd3409e3fc7..691edeb1cf2a3 100644 --- a/agent/transports/codex.py +++ b/agent/transports/codex.py @@ -221,10 +221,13 @@ def build_kwargs( elif reasoning_config.get("effort"): reasoning_effort = reasoning_config["effort"] - _effort_clamp = {"minimal": "low"} - if "gpt-5.6" in (model or "").lower(): - # Ultra is the Codex product tier; the Responses API wire value is max. - _effort_clamp["ultra"] = "max" + # Clamp Hermes-generic effort levels onto the wire vocabulary for this + # surface. Codex/OpenAI Responses accepts none|minimal|low|medium|high|xhigh + # (observed 2026-07: effort=max returns HTTP 400 invalid_value). xAI + # Responses tops out at high. "minimal" is always promoted to "low" for + # backends that never learned the minimal tier. + reasoning_effort = str(reasoning_effort or "medium").strip().lower() + _effort_clamp = {"minimal": "low", "max": "xhigh", "ultra": "xhigh"} if params.get("is_xai_responses", False): # xAI Responses tops out at high; keep generic stronger values usable. _effort_clamp.update({"xhigh": "high", "max": "high", "ultra": "high"}) diff --git a/tests/agent/transports/test_codex_transport.py b/tests/agent/transports/test_codex_transport.py index cf8f7dcc3e2e9..83df5f18963b2 100644 --- a/tests/agent/transports/test_codex_transport.py +++ b/tests/agent/transports/test_codex_transport.py @@ -38,12 +38,33 @@ def test_convert_tools(self, transport): class TestCodexBuildKwargs: + @pytest.mark.parametrize("effort, wire_effort", [("max", "xhigh"), ("ultra", "xhigh")]) + def test_extended_reasoning_efforts_use_api_wire_value(self, transport, effort, wire_effort): + kw = transport.build_kwargs( + model="gpt-5.6-sol", + messages=[{"role": "user", "content": "Hi"}], + tools=[], + reasoning_config={"enabled": True, "effort": effort}, + ) + assert kw.get("reasoning", {}).get("effort") == wire_effort + def test_max_effort_clamped_for_non_56_codex_models(self, transport): + """Config effort=max must not reach Codex wire as max (HTTP 400).""" + kw = transport.build_kwargs( + model="gpt-5.5", + messages=[{"role": "user", "content": "Hi"}], + tools=[], + reasoning_config={"enabled": True, "effort": "max"}, + ) + assert kw.get("reasoning", {}).get("effort") == "xhigh" - - - - + def test_reasoning_disabled(self, transport): + messages = [{"role": "user", "content": "Hi"}] + kw = transport.build_kwargs( + model="gpt-5.4", messages=messages, tools=[], + reasoning_config={"enabled": False}, + ) + assert "reasoning" not in kw or kw.get("include") == [] def test_cache_key_is_content_addressed_not_session_id(self, transport): """prompt_cache_key is content-addressed from the static prefix From b4b50f2d6b7b229d66d651abfb8076cad80e94e5 Mon Sep 17 00:00:00 2001 From: joelbrilliant Date: Tue, 21 Jul 2026 13:56:30 +1000 Subject: [PATCH 2/2] test(codex): expect max/ultra clamp to xhigh on Responses wire CI failed on test_build_api_kwargs_codex_preserves_supported_efforts, which still treated max as a pass-through wire value. Align with the transport clamp (max/ultra -> xhigh) that fixes the live HTTP 400. Signed-off-by: joelbrilliant --- .../test_run_agent_codex_responses.py | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/tests/run_agent/test_run_agent_codex_responses.py b/tests/run_agent/test_run_agent_codex_responses.py index f4a0515910bc2..d013aec063fb8 100644 --- a/tests/run_agent/test_run_agent_codex_responses.py +++ b/tests/run_agent/test_run_agent_codex_responses.py @@ -323,8 +323,55 @@ def test_build_api_kwargs_mantle_sets_extended_prompt_cache_retention(monkeypatc assert kwargs["prompt_cache_retention"] == "24h" +def test_build_api_kwargs_codex_preserves_supported_efforts(monkeypatch): + """Wire-supported effort levels pass through; Hermes max/ultra clamp to xhigh.""" + _patch_agent_bootstrap(monkeypatch) + + for effort in ("low", "medium", "high", "xhigh"): + agent = run_agent.AIAgent( + model="gpt-5-codex", + base_url="https://chatgpt.com/backend-api/codex", + api_key="codex-token", + quiet_mode=True, + max_iterations=4, + skip_context_files=True, + skip_memory=True, + reasoning_config={"enabled": True, "effort": effort}, + ) + agent._cleanup_task_resources = lambda task_id: None + agent._persist_session = lambda messages, history=None: None + agent._save_trajectory = lambda messages, user_message, completed: None + + kwargs = agent._build_api_kwargs( + [ + {"role": "system", "content": "sys"}, + {"role": "user", "content": "hi"}, + ] + ) + assert kwargs["reasoning"]["effort"] == effort, f"{effort} should pass through unchanged" + for effort, wire in (("max", "xhigh"), ("ultra", "xhigh")): + agent = run_agent.AIAgent( + model="gpt-5-codex", + base_url="https://chatgpt.com/backend-api/codex", + api_key="codex-token", + quiet_mode=True, + max_iterations=4, + skip_context_files=True, + skip_memory=True, + reasoning_config={"enabled": True, "effort": effort}, + ) + agent._cleanup_task_resources = lambda task_id: None + agent._persist_session = lambda messages, history=None: None + agent._save_trajectory = lambda messages, user_message, completed: None + kwargs = agent._build_api_kwargs( + [ + {"role": "system", "content": "sys"}, + {"role": "user", "content": "hi"}, + ] + ) + assert kwargs["reasoning"]["effort"] == wire, f"{effort} should clamp to {wire}" @@ -1740,4 +1787,3 @@ def test_duplicate_detection_uses_commentary_when_hidden_reasoning_changes(monke -