fix: clamp 'minimal' reasoning effort to 'low' on Responses API (#9429)

GPT-5.4 supports none/low/medium/high/xhigh but not 'minimal'.
Users may configure 'minimal' via OpenRouter conventions, which would
cause a 400 on native OpenAI. Clamp to 'low' in the codex_responses
path before sending.
This commit is contained in:
Teknium 2026-04-13 23:11:13 -07:00 committed by GitHub
parent 38ad158b6b
commit 19199cd38d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 69 additions and 0 deletions

View file

@ -6143,6 +6143,12 @@ class AIAgent:
elif self.reasoning_config.get("effort"):
reasoning_effort = self.reasoning_config["effort"]
# Clamp effort levels not supported by the Responses API model.
# GPT-5.4 supports none/low/medium/high/xhigh but not "minimal".
# "minimal" is valid on OpenRouter and GPT-5 but fails on 5.2/5.4.
_effort_clamp = {"minimal": "low"}
reasoning_effort = _effort_clamp.get(reasoning_effort, reasoning_effort)
kwargs = {
"model": self.model,
"instructions": instructions,

View file

@ -287,6 +287,69 @@ def test_build_api_kwargs_codex(monkeypatch):
assert "extra_body" not in kwargs
def test_build_api_kwargs_codex_clamps_minimal_effort(monkeypatch):
"""'minimal' reasoning effort is clamped to 'low' on the Responses API.
GPT-5.4 supports none/low/medium/high/xhigh but NOT 'minimal'.
Users may configure 'minimal' via OpenRouter conventions, so the Codex
Responses path must clamp it to the nearest supported level.
"""
_patch_agent_bootstrap(monkeypatch)
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": "minimal"},
)
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
agent._save_session_log = lambda messages: None
kwargs = agent._build_api_kwargs(
[
{"role": "system", "content": "You are Hermes."},
{"role": "user", "content": "Ping"},
]
)
assert kwargs["reasoning"]["effort"] == "low"
def test_build_api_kwargs_codex_preserves_supported_efforts(monkeypatch):
"""Effort levels natively supported by the Responses API pass through unchanged."""
_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
agent._save_session_log = lambda messages: 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"
def test_build_api_kwargs_copilot_responses_omits_openai_only_fields(monkeypatch):
agent = _build_copilot_agent(monkeypatch)
kwargs = agent._build_api_kwargs([{"role": "user", "content": "hi"}])