diff --git a/agent/credential_pool.py b/agent/credential_pool.py index 8d10bbb1cbf..da1f307284c 100644 --- a/agent/credential_pool.py +++ b/agent/credential_pool.py @@ -2162,7 +2162,17 @@ def _seed_from_env(provider: str, entries: List[PooledCredential]) -> Tuple[bool if _is_source_suppressed(provider, source): continue active_sources.add(source) - auth_type = AUTH_TYPE_OAUTH if provider == "anthropic" and not token.startswith("sk-ant-api") else AUTH_TYPE_API_KEY + # Claude Code OAuth tokens are the only Anthropic credentials that should + # flow into the OAuth refresh path. Match the `sk-ant-oat` prefix + # positively — matching by negation (everything not `sk-ant-api`) wrongly + # tagged admin keys (`sk-ant-admin*`) and any future API-key prefix as + # OAuth, which then got immediately marked exhausted on first use because + # they have no refresh token. + auth_type = ( + AUTH_TYPE_OAUTH + if provider == "anthropic" and token.startswith("sk-ant-oat") + else AUTH_TYPE_API_KEY + ) base_url = env_url or pconfig.inference_base_url if provider == "kimi-coding": base_url = _resolve_kimi_base_url(token, pconfig.inference_base_url, env_url)