Summary
Anthropic has released Workload Identity Federation (WIF) — a keyless authentication method that replaces static sk-ant-... API keys with short-lived tokens derived from external OIDC identity providers (AWS IAM, GCP, GitHub Actions, Kubernetes, Microsoft Entra ID, Okta, etc.).
Current State (Already Working)
Our existing code transparently handles WIF-minted tokens with no changes needed:
- Token detection —
_is_oauth_token() in agent/anthropic_adapter.py already matches sk-ant-oat01-... tokens (WIF output) via the key.startswith("sk-ant-") check, routing them to Bearer auth correctly.
- Environment inheritance — When spawning Claude Code via
--acp, copilot_acp_client.py does os.environ.copy(), so WIF env vars (ANTHROPIC_FEDERATION_RULE_ID, ANTHROPIC_IDENTITY_TOKEN_FILE, etc.) flow through automatically.
- SDK-level handling — If users set WIF env vars and do NOT set
ANTHROPIC_API_KEY, the Anthropic Python SDK handles the token exchange internally before Hermes ever sees the credential.
Proposed Enhancements (Nice-to-Have)
1. hermes doctor awareness of WIF env vars
Add WIF-related env vars to the doctor checks so users get clear feedback when federation is configured:
ANTHROPIC_FEDERATION_RULE_ID
ANTHROPIC_ORGANIZATION_ID
ANTHROPIC_SERVICE_ACCOUNT_ID
ANTHROPIC_IDENTITY_TOKEN_FILE
2. Document WIF as an auth option in claude-code skill
Add a section to the Prerequisites noting that WIF is an alternative to API keys/OAuth for server-side and CI/CD deployments.
3. Auth status reporting
resolve_anthropic_token() could detect and report when federation env vars are present (even if the actual exchange is SDK-managed), so error messages and hermes login / hermes doctor can inform users which auth method is active.
4. Credential precedence warning
The WIF docs explicitly warn that ANTHROPIC_API_KEY shadows federation silently (it sits higher in SDK precedence). We could add a warning in hermes doctor or startup when both ANTHROPIC_API_KEY and ANTHROPIC_FEDERATION_RULE_ID are set simultaneously — this is almost always a misconfiguration.
5. Native token exchange (optional, low priority)
Currently the Anthropic SDK handles the POST /v1/oauth/token exchange. We could add our own exchange logic in anthropic_adapter.py for environments where the SDK is not installed or where we want finer control over token refresh. This would mirror our existing OAuth refresh logic for Claude Code credentials.
How WIF Works (Reference)
- Workload obtains a JWT from its identity provider (ambient on most platforms)
- SDK exchanges the JWT at
POST /v1/oauth/token using RFC 7523 jwt-bearer grant
- Anthropic validates claims against federation rules configured in the Console
- Returns
sk-ant-oat01-... short-lived token (60s–86400s, default 1h)
- SDK caches + auto-refreshes before expiry
Key env vars for zero-argument SDK construction:
ANTHROPIC_FEDERATION_RULE_ID — which federation rule to match (fdrl_...)
ANTHROPIC_ORGANIZATION_ID — org UUID
ANTHROPIC_SERVICE_ACCOUNT_ID — service account (svac_...)
ANTHROPIC_IDENTITY_TOKEN_FILE — path to the JWT file
Priority
Low — this is a forward-looking enhancement. WIF is an enterprise/server-side feature primarily useful for CI/CD pipelines and Kubernetes deployments. The current passthrough behavior works correctly without any code changes.
Summary
Anthropic has released Workload Identity Federation (WIF) — a keyless authentication method that replaces static
sk-ant-...API keys with short-lived tokens derived from external OIDC identity providers (AWS IAM, GCP, GitHub Actions, Kubernetes, Microsoft Entra ID, Okta, etc.).Current State (Already Working)
Our existing code transparently handles WIF-minted tokens with no changes needed:
_is_oauth_token()inagent/anthropic_adapter.pyalready matchessk-ant-oat01-...tokens (WIF output) via thekey.startswith("sk-ant-")check, routing them to Bearer auth correctly.--acp,copilot_acp_client.pydoesos.environ.copy(), so WIF env vars (ANTHROPIC_FEDERATION_RULE_ID,ANTHROPIC_IDENTITY_TOKEN_FILE, etc.) flow through automatically.ANTHROPIC_API_KEY, the Anthropic Python SDK handles the token exchange internally before Hermes ever sees the credential.Proposed Enhancements (Nice-to-Have)
1.
hermes doctorawareness of WIF env varsAdd WIF-related env vars to the doctor checks so users get clear feedback when federation is configured:
ANTHROPIC_FEDERATION_RULE_IDANTHROPIC_ORGANIZATION_IDANTHROPIC_SERVICE_ACCOUNT_IDANTHROPIC_IDENTITY_TOKEN_FILE2. Document WIF as an auth option in
claude-codeskillAdd a section to the Prerequisites noting that WIF is an alternative to API keys/OAuth for server-side and CI/CD deployments.
3. Auth status reporting
resolve_anthropic_token()could detect and report when federation env vars are present (even if the actual exchange is SDK-managed), so error messages andhermes login/hermes doctorcan inform users which auth method is active.4. Credential precedence warning
The WIF docs explicitly warn that
ANTHROPIC_API_KEYshadows federation silently (it sits higher in SDK precedence). We could add a warning inhermes doctoror startup when bothANTHROPIC_API_KEYandANTHROPIC_FEDERATION_RULE_IDare set simultaneously — this is almost always a misconfiguration.5. Native token exchange (optional, low priority)
Currently the Anthropic SDK handles the
POST /v1/oauth/tokenexchange. We could add our own exchange logic inanthropic_adapter.pyfor environments where the SDK is not installed or where we want finer control over token refresh. This would mirror our existing OAuth refresh logic for Claude Code credentials.How WIF Works (Reference)
POST /v1/oauth/tokenusing RFC 7523jwt-bearergrantsk-ant-oat01-...short-lived token (60s–86400s, default 1h)Key env vars for zero-argument SDK construction:
ANTHROPIC_FEDERATION_RULE_ID— which federation rule to match (fdrl_...)ANTHROPIC_ORGANIZATION_ID— org UUIDANTHROPIC_SERVICE_ACCOUNT_ID— service account (svac_...)ANTHROPIC_IDENTITY_TOKEN_FILE— path to the JWT filePriority
Low — this is a forward-looking enhancement. WIF is an enterprise/server-side feature primarily useful for CI/CD pipelines and Kubernetes deployments. The current passthrough behavior works correctly without any code changes.