anthropics / anthropics/anthropic-sdk-python
Accept a callable for bearer-token auth (`auth_token: str | Callable[[], str]`)
- Linguagem predominante
- Python
- Estrelas
- 3.9k
- Forks
- 853
- Merge médio
- 1d 18h
- PRs com merge (30d)
- 11
Descrição
Most enterprise customers are required by policy to use short-lived, broker-issued bearer tokens (Entra ID, Okta, Ping, Vault) instead of long-lived API keys. Those tokens expire (Entra is ~1h), so any long-running client needs the credential resolved per request, not captured once at construction.
**State of the SDK (v0.109.x).** Two auth inputs exist and neither covers the simple callable case:
- `api_key` and `auth_token` are `str` only, fixed at construction.
- `credentials=` accepts an `AccessTokenProvider` with caching, refresh, and refresh-on-401. This is the right tool for expiry-aware providers, but it requires the full protocol, `__call__(self, *, force_refresh: bool = False) -> AccessToken`. A plain `Callable[[], str]`, which is what most identity stacks already hand you, can't be passed without a wrapper:
```python
from anthropic import AccessToken
def bearer_provider(get_token):
def _provider(*, force_refresh: bool = False) -> AccessToken:
return AccessToken(token=get_token(), expires_at=None)
return _provider
```
Every caller writes the same adapter, and `force_refresh` typically can't be honored (common token getters have no force-refresh hook), so a 401 retry can re-serve a stale token.
**Ask.** Make `auth_token` accept `str | Callable[[], str]`. When callable, invoke it per request to build `Authorization: Bearer `. No `AccessToken` and no `force_refresh` for the simple case; static behavior unchanged; `credentials=` stays the advanced path. This is the same callable-credential pattern the peer Stainless-generated SDKs already expose.
```python
def get_token() -> str:
return my_auth.get_access_token()
client = Anthropic(base_url=..., auth_token=get_token)
```
**Async parity.** `AsyncAnthropic` should accept `auth_token: str | Callable[[], Awaitable[str]]`, awaited per request. The credential subsystem is sync-only today (even `credentials=` is run via a thread-pool `asyncify` bridge), so an async-native credential can't be used without pulling in its sync counterpart. This can land as a follow-up increment so it doesn't block the sync callable, but it's the same feature and the peer Stainless-generated SDKs already type their async callable as returning an awaitable.
**Status:** implemented in #1516 (currently needs a rebase and review).
Guia de contribuição
Avaliação
Esta issue ainda não foi avaliada.