From a699de83ec6463b92e3cffbcb4bb2fff3a80e84b Mon Sep 17 00:00:00 2001 From: Nami4D Date: Tue, 19 May 2026 11:23:40 +0900 Subject: [PATCH] fix(xai-oauth): strip service_tier and add safety-net sanitization for slash enums xAI's /v1/responses endpoint rejects service_tier with HTTP 400 "Argument not supported: service_tier" when users activate /fast mode. Also add a safety-net strip_slash_enum call in _preflight_codex_api_kwargs to catch any tool schemas that might slip through the caller-level sanitization. xAI's Responses API grammar compiler rejects enum values containing forward slashes (e.g. HuggingFace model IDs like "Qwen/Qwen3.5-0.8B") with the opaque "Invalid arguments passed to the model" error. Fixes the root cause of "Invalid arguments passed to the model" errors reported by xAI OAuth (SuperGrok) users. --- agent/codex_responses_adapter.py | 20 ++++++++++++++++++++ agent/transports/codex.py | 11 +++++++++++ 2 files changed, 31 insertions(+) diff --git a/agent/codex_responses_adapter.py b/agent/codex_responses_adapter.py index e539656b7d1..230a6e613b1 100644 --- a/agent/codex_responses_adapter.py +++ b/agent/codex_responses_adapter.py @@ -913,6 +913,26 @@ def _preflight_codex_api_kwargs( elif "stream" in api_kwargs: raise ValueError("Codex Responses stream flag is only allowed in fallback streaming requests.") + # Safety-net sanitization for xAI Responses (#28490): defense-in-depth + # for the same slash-enum strip that ``chat_completion_helpers`` and + # ``auxiliary_client`` apply at request-build time. If a future code + # path forgets to sanitize before calling us, this catches the bypass + # so xAI doesn't 400 with ``Invalid arguments passed to the model`` + # (HuggingFace IDs like ``Qwen/Qwen3.5-0.8B`` from MCP tool schemas). + # + # Gated on the model name pattern because native Codex (OpenAI) DOES + # accept slash-containing enum values — stripping them there would + # silently degrade tool-schema constraints. xAI is the only + # Responses-API surface that rejects the shape. + model_name_for_provider_check = str(api_kwargs.get("model") or "").lower() + is_xai_model = model_name_for_provider_check.startswith(("grok-", "x-ai/grok-")) + if is_xai_model and normalized.get("tools"): + try: + from tools.schema_sanitizer import strip_slash_enum + normalized["tools"], _ = strip_slash_enum(normalized["tools"]) + except Exception: + pass # Best-effort — the caller-level sanitization should have handled it + unexpected = sorted(key for key in api_kwargs if key not in allowed_keys) if unexpected: raise ValueError( diff --git a/agent/transports/codex.py b/agent/transports/codex.py index f24f2304899..9a4a3a4b937 100644 --- a/agent/transports/codex.py +++ b/agent/transports/codex.py @@ -184,6 +184,17 @@ class ResponsesApiTransport(ProviderTransport): if request_overrides: kwargs.update(request_overrides) + # xAI Responses API rejects ``service_tier`` (HTTP 400 "Argument not + # supported: service_tier") — hit when ``/fast`` priority-processing + # mode lingers from a prior model in the same session, or when a + # user explicitly sets ``agent.service_tier`` in config.yaml. The + # main-loop guard (``resolve_fast_mode_overrides`` only returns + # ``service_tier`` for OpenAI fast-eligible models) doesn't cover + # those leak paths, so strip defensively when targeting xAI. See + # #28490 for the original report. + if is_xai_responses: + kwargs.pop("service_tier", None) + # Forward per-request timeout to the SDK so OpenAI/Anthropic clients # honor it. Without this, ``providers..request_timeout_seconds`` # is silently dropped on the main agent Codex path while the