Skip to content

Use anthropic SDK 0.109+ credentials= for long-running token refresh (drop AnthropicIdentity subclass) #42

Description

Background

The long-running sample src/hello_claude_token_refresh.py defines an AnthropicIdentity(Anthropic) subclass that overrides the �uth_token property as a workaround for the SDK only accepting a static �uth_token: str. The plain Anthropic client's captured Entra ID token would otherwise start failing with 401 after ~1 hour, which is why the shim exists.

What changed upstream

Anthropic Python SDK v0.98.0 (May 2026) added a public credentials= constructor parameter on Anthropic / AsyncAnthropic that takes an AccessTokenProvider (a callable returning an AccessToken(token, expires_at)). The SDK wraps it in an internal TokenCache that:

  • Calls the provider lazily (no token fetched at client construction).
  • Caches the token and reuses it across requests.
  • On a 401 response, invalidates the cache and retries the request once with a freshly minted token (_should_retry override in _client.py).

This is exactly the capability the AnthropicIdentity shim was emulating. auth_token itself is still a static str (so anthropics/anthropic-sdk-python#1496 remains open for the narrower "make auth_token accept a Callable" ask), but the more general credentials= path solves the long-running use case cleanly.

Verified against src/anthropic/lib/credentials/_types.py and src/anthropic/_client.py at tag v0.109.1.

Proposed change

  • Bump anthropic>=0.109.1 in requirements.txt.
  • Rewrite src/hello_claude_token_refresh.py to:
    • Delete the AnthropicIdentity(Anthropic) subclass.
    • Build a tiny AccessTokenProvider from DefaultAzureCredential that returns AccessToken(token=t.token, expires_at=t.expires_on) (expires_on is unix seconds, same format the SDK expects).
    • Pass it to Anthropic(credentials=provider, base_url=...).
  • Update the long-running code snippet in the README's collapsed SDK call shape section to match. The one-shot hello_claude.py and its snippet are unchanged.

Out of scope

  • No change to src/hello_claude.py (the short-lived script path keeps using auth_token=token — still the simplest pattern for one-shot runs).
  • No change to src/check_claude_quota.py, src/hello_claude_apikey.py, or the verifier scripts.
  • No change to RBAC, infra, or hooks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions