From 6ef3a47ce5c02c63563f29da7fa663a7092a02a8 Mon Sep 17 00:00:00 2001 From: HangGlidersRule <637186+HangGlidersRule@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:05:36 -0400 Subject: [PATCH] fix: use Azure API key directly for Azure endpoints, bypass OAuth token priority chain --- hermes_cli/runtime_provider.py | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/hermes_cli/runtime_provider.py b/hermes_cli/runtime_provider.py index 09895b62918..11398f9d522 100644 --- a/hermes_cli/runtime_provider.py +++ b/hermes_cli/runtime_provider.py @@ -978,13 +978,6 @@ def resolve_runtime_provider( # Anthropic (native Messages API) if provider == "anthropic": - from agent.anthropic_adapter import resolve_anthropic_token - token = resolve_anthropic_token() - if not token: - raise AuthError( - "No Anthropic credentials found. Set ANTHROPIC_TOKEN or ANTHROPIC_API_KEY, " - "run 'claude setup-token', or authenticate with 'claude /login'." - ) # Allow base URL override from config.yaml model.base_url, but only # when the configured provider is anthropic — otherwise a non-Anthropic # base_url (e.g. Codex endpoint) would leak into Anthropic requests. @@ -993,6 +986,33 @@ def resolve_runtime_provider( if cfg_provider == "anthropic": cfg_base_url = (model_cfg.get("base_url") or "").strip().rstrip("/") base_url = cfg_base_url or "https://api.anthropic.com" + + # For Azure AI Foundry endpoints, use ANTHROPIC_API_KEY directly — + # Claude Code OAuth tokens (sk-ant-oat01) are not accepted by Azure. + # Azure keys don't start with "sk-ant-" so resolve_anthropic_token() + # would find the Claude Code OAuth token first (priority 3) and return + # that instead, causing 401s. Detect Azure endpoints and use the env + # key directly to bypass the OAuth priority chain. + _is_azure_endpoint = "azure.com" in base_url.lower() or ( + cfg_base_url and "azure.com" in cfg_base_url.lower() + ) + if _is_azure_endpoint: + token = ( + os.getenv("AZURE_ANTHROPIC_KEY", "").strip() + or os.getenv("ANTHROPIC_API_KEY", "").strip() + ) + if not token: + raise AuthError( + "No Azure Anthropic API key found. Set AZURE_ANTHROPIC_KEY or ANTHROPIC_API_KEY." + ) + else: + from agent.anthropic_adapter import resolve_anthropic_token + token = resolve_anthropic_token() + if not token: + raise AuthError( + "No Anthropic credentials found. Set ANTHROPIC_TOKEN or ANTHROPIC_API_KEY, " + "run 'claude setup-token', or authenticate with 'claude /login'." + ) return { "provider": "anthropic", "api_mode": "anthropic_messages",