From b389796ae3a33256ff1b4077acc1169831fb63e1 Mon Sep 17 00:00:00 2001 From: zccyman Date: Thu, 14 May 2026 07:49:52 +0800 Subject: [PATCH] fix(auxiliary): resolve api_key_env alias in named custom provider path of resolve_provider_client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In resolve_provider_client(), the named custom provider code path at ~line 2914 only checked the ``key_env`` field when looking for an environment-variable-based API key. The documented ``api_key_env`` snake_case alias was silently ignored, causing custom providers configured with ``api_key_env`` to fall through to the ``no-key-required`` placeholder — which produces a confusing 401 (``****ired`` mask) on auth-required remote endpoints. This mirrors the same fix already applied to run_agent.py in commit 6ddc48b05 (fix(fallback): resolve api_key_env in fallback chain entries). Also adds a logger.warning() when the placeholder is reached, so future alias gaps are easier to debug. Closes #25091 --- agent/auxiliary_client.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/agent/auxiliary_client.py b/agent/auxiliary_client.py index cfc44e5f2a6..102ff79f1ce 100644 --- a/agent/auxiliary_client.py +++ b/agent/auxiliary_client.py @@ -3049,10 +3049,17 @@ def resolve_provider_client( if custom_entry: custom_base = custom_entry.get("base_url", "").strip() custom_key = custom_entry.get("api_key", "").strip() - custom_key_env = custom_entry.get("key_env", "").strip() + custom_key_env = (custom_entry.get("key_env") or custom_entry.get("api_key_env") or "").strip() if not custom_key and custom_key_env: custom_key = os.getenv(custom_key_env, "").strip() custom_key = custom_key or "no-key-required" + if custom_key == "no-key-required": + logger.warning( + "resolve_provider_client: named custom provider %r has no resolvable " + "api_key — request will be sent with placeholder no-key-required " + "and will 401 on auth-required endpoints", + custom_entry.get("name") or provider, + ) # An explicit per-task api_mode override (from _resolve_task_provider_model) # wins; otherwise fall back to what the provider entry declared. entry_api_mode = (api_mode or custom_entry.get("api_mode") or "").strip()