From cd712b176a9be62b0d1e70a865c1226bd1b0e6a3 Mon Sep 17 00:00:00 2001 From: Julien Talbot Date: Fri, 8 May 2026 23:45:47 +0400 Subject: [PATCH] feat(transports/codex): pass reasoning.effort to xAI Responses API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The is_xai_responses branch only sent include=[reasoning.encrypted_content] without forwarding the resolved reasoning_effort. Other Responses providers (OpenAI, GitHub) already get effort forwarded — this aligns the xAI path. Without this, agent.reasoning_effort is silently dropped on the xAI direct path, making Hermes unable to control reasoning depth on grok-4.x via api.x.ai. Tests added to TestCodexBuildKwargs cover effort passthrough, disabled state, and minimal-clamp parity with non-xAI. --- agent/transports/codex.py | 1 + .../agent/transports/test_codex_transport.py | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/agent/transports/codex.py b/agent/transports/codex.py index 2ebc396fbb1..f011034dae8 100644 --- a/agent/transports/codex.py +++ b/agent/transports/codex.py @@ -105,6 +105,7 @@ class ResponsesApiTransport(ProviderTransport): if reasoning_enabled and is_xai_responses: kwargs["include"] = ["reasoning.encrypted_content"] + kwargs["reasoning"] = {"effort": reasoning_effort} elif reasoning_enabled: if is_github_responses: github_reasoning = params.get("github_reasoning_extra") diff --git a/tests/agent/transports/test_codex_transport.py b/tests/agent/transports/test_codex_transport.py index 26145660cca..7217f2e9e6a 100644 --- a/tests/agent/transports/test_codex_transport.py +++ b/tests/agent/transports/test_codex_transport.py @@ -149,6 +149,37 @@ class TestCodexBuildKwargs: # "minimal" should be clamped to "low" assert kw.get("reasoning", {}).get("effort") == "low" + def test_xai_reasoning_effort_passed(self, transport): + messages = [{"role": "user", "content": "Hi"}] + kw = transport.build_kwargs( + model="grok-4.3", messages=messages, tools=[], + is_xai_responses=True, + reasoning_config={"effort": "high"}, + ) + # xAI Responses must receive both encrypted reasoning content and the effort + assert kw.get("reasoning") == {"effort": "high"} + assert "reasoning.encrypted_content" in kw.get("include", []) + + def test_xai_reasoning_disabled_no_reasoning_key(self, transport): + messages = [{"role": "user", "content": "Hi"}] + kw = transport.build_kwargs( + model="grok-4.3", messages=messages, tools=[], + is_xai_responses=True, + reasoning_config={"enabled": False}, + ) + # When reasoning is disabled, do not send the reasoning key at all + assert "reasoning" not in kw + + def test_xai_minimal_effort_clamped(self, transport): + messages = [{"role": "user", "content": "Hi"}] + kw = transport.build_kwargs( + model="grok-4.3", messages=messages, tools=[], + is_xai_responses=True, + reasoning_config={"effort": "minimal"}, + ) + # "minimal" should be clamped to "low" for xAI as well + assert kw.get("reasoning", {}).get("effort") == "low" + class TestCodexValidateResponse: