Skip to main content
Everything on this page is imported from charter.auth, not charter. Charter never acquires or stores credentials. A CredentialProvider is the seam between the host application, which owns them, and the runtime, which needs a bearer token for the length of one request. A missing or rejected token raises CredentialError; the runtime never re-authenticates on its own.

Credentials

A bearer token, and optionally when it stops being valid.
str
required
The bearer token, sent as Authorization: Bearer ....
Optional[datetime]
When the token lapses. None means the caller has not said, and the token is treated as valid — the API is then the judge.

Credentials.is_expired

Whether the token is past expires_at minus leeway_seconds. Credentials with no expires_at never report expired. A naive datetime is read as UTC, so a provider handing back a naive timestamp is not treated as far-future or far-past.

CredentialProvider

The protocol every provider satisfies. Runtime-checkable, so isinstance(obj, CredentialProvider) is a structural check on the method.
str
required
The identifier the tool was declared with — "google", "slack". It names the API, never the end user, so one implementation can serve several APIs. For who a call acts as, see SubjectProvider.
Anything with that one async method works: a secrets manager, a broker, a class of your own.

StaticTokenProvider

Hands back one token, unchanged, for every provider. The right choice for a script, a test, or any place you already hold a valid access token. An empty token raises CredentialError at construction. Its repr masks the token.

EnvTokenProvider

Reads the token from an environment variable on every call — re-read per call on purpose, so a sidecar that refreshes the variable is picked up without restarting the process.
str
required
The variable to read. An empty name raises CredentialError at construction; an unset or empty variable raises CredentialError at call time, naming the variable.

CallbackProvider

Delegates to a function of your own, sync or async — the hook for a credential store you already run. A non-callable raises CredentialError.
provider names the API, not the person: one of these serves one identity. For many, see SubjectProvider; to refresh a grant rather than read a stored token, see OAuth2Client.

SubjectProvider

One credential provider per end user, resolved per call. Give it a factory that builds a provider for a subject — typically reading that user’s refresh token from your database and returning an OAuth2Client.
Callable[[str], CredentialProvider | Awaitable[CredentialProvider]]
required
Builds the provider for one subject. Sync or async. Returning None raises CredentialError naming the subject. A non-callable raises CredentialError at construction.
int
default:"1000"
How many built providers to keep, evicted least-recently-used. Below 1 raises ValueError. Each provider carries its own cached token and refresh lock, so eviction removes both together.

Methods

Credentials
Resolves the current subject, then delegates. Concurrent cold starts for one subject are single-flighted, so twelve simultaneous calls read your token store once.
str
The subject for this call. Never falls back to a default or to whoever went last: an unset subject raises CredentialError naming what to do about it.
None
Drop a subject’s provider — after a revocation, or a sign-out.
int
How many providers are currently held.
Two limits worth knowing. One of these belongs to one event loop: resolution is a read, a reorder and sometimes an insert, and that sequence is not atomic across threads. And a subject evicted mid-refresh, against a server that rotates, is rebuilt from whatever your store holds — which needs max_subjects distinct other users inside one refresh, so raise the cap rather than tuning around it.

current_subject

Who the next tool call acts for. Read by your provider, never by the runtime: the executor still calls get_credentials(name) and knows nothing else. A ContextVar is per-task in asyncio, so concurrent requests sharing one set of tools cannot see each other’s subject. Set it directly with current_subject.set(...) when you own the reset, or use the context manager below.

use_subject

Set current_subject for the duration of a block. Resets on the way out, including on an exception, so a failed request cannot leave its identity behind for the next one. An empty subject raises CredentialError.