fix(aux): default Codex reasoning effort to medium when extra_body.reasoning.effort is falsy#17012
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes Codex auxiliary request construction so extra_body.reasoning.effort defaults to "medium" when the key is present but falsy (e.g., None/""), matching the main Codex transport behavior and avoiding Codex 400s.
Changes:
- Coalesce falsy
extra_body.reasoning.effortvalues to"medium"in_CodexCompletionsAdapter.create(). - Add regression tests covering
effort=Noneandeffort=""to ensure the outgoingreasoningpayload is valid.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
agent/auxiliary_client.py |
Adjusts reasoning effort defaulting to avoid forwarding invalid falsy values to Codex. |
tests/agent/test_auxiliary_client.py |
Adds focused regression tests for falsy-but-present effort values. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| """Parity with agent/transports/codex.py::build_kwargs() — falsy | ||
| ``effort`` (None / empty / 0) keeps the default ``medium`` instead | ||
| of being forwarded to Codex. Codex rejects ``{"effort": null}`` | ||
| with HTTP 400 (Invalid value for parameter `reasoning.effort`).""" |
|
@copilot Finding addressed in commit Finding ( |
|
CI audit — all 35 Same baseline set observable on every other PR opened today (#16851, #16902, #16990, …) — Locally on this branch the focused suite is green: including the falsy-effort coverage extension ( |
…asoning.effort is falsy
auxiliary.<task>.extra_body.reasoning, but the new translation path in
_CodexCompletionsAdapter.create() reads the effort with
``reasoning_cfg.get("effort", "medium")``. That returns the configured
value verbatim when the key is present, so ``effort: null`` /
``effort: ""`` (both common YAML shapes) flow through as
``{"effort": null, "summary": "auto"}`` and Codex rejects the request
with "Invalid value for parameter ``reasoning.effort``".
agent/transports/codex.py::build_kwargs() — which the new adapter is
documented to mirror — uses a truthy check (``elif
reasoning_config.get("effort"):``) so the same falsy values keep the
"medium" default. Switch the auxiliary adapter to the same
``or "medium"`` truthy form so identical config produces identical
requests on both paths.
- [x] Two new regression tests cover ``effort: None`` and
``effort: ""`` and assert the request goes out as
``{"effort": "medium", "summary": "auto"}``.
- [x] Old behaviour fails the new tests (``{'effort': None} !=
{'effort': 'medium'}``); fixed behaviour passes all 11 tests in the
``TestCodexAdapterReasoningTranslation`` class.
- [x] Adjacent suites green: ``tests/agent/test_auxiliary_client.py``
(108 passed) and ``tests/agent/transports/test_codex_transport.py +
test_chat_completions.py`` (73 passed).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot review on PR NousResearch#17012 noted the docstring/comment lists `0` among the falsy effort values that fall back to `medium`, but the existing regression tests only cover `None` and `""`. Add the third case to lock in the full contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
e4f83c0 to
0185fbf
Compare
|
Rebased onto current Conflict resolution: kept all four kimi-coding vision-skip tests intact and inserted the three reasoning-effort fallback tests ( Verified: |
Copilot review on PR #17012 noted the docstring/comment lists `0` among the falsy effort values that fall back to `medium`, but the existing regression tests only cover `None` and `""`. Add the third case to lock in the full contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot review on PR #17012 noted the docstring/comment lists `0` among the falsy effort values that fall back to `medium`, but the existing regression tests only cover `None` and `""`. Add the third case to lock in the full contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot review on PR NousResearch#17012 noted the docstring/comment lists `0` among the falsy effort values that fall back to `medium`, but the existing regression tests only cover `None` and `""`. Add the third case to lock in the full contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot review on PR NousResearch#17012 noted the docstring/comment lists `0` among the falsy effort values that fall back to `medium`, but the existing regression tests only cover `None` and `""`. Add the third case to lock in the full contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot review on PR NousResearch#17012 noted the docstring/comment lists `0` among the falsy effort values that fall back to `medium`, but the existing regression tests only cover `None` and `""`. Add the third case to lock in the full contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot review on PR NousResearch#17012 noted the docstring/comment lists `0` among the falsy effort values that fall back to `medium`, but the existing regression tests only cover `None` and `""`. Add the third case to lock in the full contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot review on PR NousResearch#17012 noted the docstring/comment lists `0` among the falsy effort values that fall back to `medium`, but the existing regression tests only cover `None` and `""`. Add the third case to lock in the full contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot review on PR NousResearch#17012 noted the docstring/comment lists `0` among the falsy effort values that fall back to `medium`, but the existing regression tests only cover `None` and `""`. Add the third case to lock in the full contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot review on PR NousResearch#17012 noted the docstring/comment lists `0` among the falsy effort values that fall back to `medium`, but the existing regression tests only cover `None` and `""`. Add the third case to lock in the full contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
"medium"whenauxiliary.<task>.extra_body.reasoning.effortisnull/""/0instead of forwarding the falsy value to Codex (which 400s)._CodexCompletionsAdapter.create()(PR feat(aux): translate extra_body.reasoning into Codex Responses API #17004) into parity withagent/transports/codex.py::build_kwargs(), which the new adapter is explicitly documented to mirror.The bug
PR #17004 (391f1ca) wired
extra_body.reasoningthrough to the Codex Responses API:The two-arg
dict.getonly fills in the default when the key is absent. If the user has the key but with a falsy value — which is whateffort: ~oreffort:(no value) produces in YAML —effortis bound toNone/""and goes out as:The Codex Responses API rejects that with HTTP 400 (
Invalid value for parameter "reasoning.effort"), so the auxiliary call fails on a config shape that the main agent accepts cleanly.The main-agent path the new adapter is mirroring (
agent/transports/codex.py:79-90) uses a truthy check:so falsy values stay at the
"medium"default. The same config that works for the main agent'sreasoning_configshould work for the auxiliary adapter'sextra_body.reasoning.The fix
One-line change in
_CodexCompletionsAdapter.create():The
or "medium"mirrors the truthy check from the main-agent transport —None,"",0all coalesce to the default rather than getting forwarded to Codex. Truthy strings ("low","medium","high","minimal", etc.) behave exactly as before, and the existingminimal → lowclamp still runs after this.Test plan
TestCodexAdapterReasoningTranslationcovereffort: Noneandeffort: ""and assert the outgoing request is{"effort": "medium", "summary": "auto"}.{'effort': None} != {'effort': 'medium'}and{'effort': ''} != {'effort': 'medium'}. With the fix applied, all 11 tests in the class pass.tests/agent/test_auxiliary_client.py— 108 passed.tests/agent/transports/test_codex_transport.py+test_chat_completions.py— 73 passed.Related