personaai ships two top-level client classes, one for each world:
Both expose exactly the same resource surface — the two are mirrors, and every method on the
async client is the
await-ed equivalent of the sync one (resource methods differ by prefix: sync
client.agents.create(...), async await client.agents.create(...)).
Resource accessors
Every method on every resource client is a thin, typed 1:1 wrapper over a real endpoint — there’s
no hidden behavior. See Resources for the per-resource
reference.
whoami()
Resolves the principal context the credential (and optional external_user_id) maps to — a
side-effect-free way to sanity-check auth wiring before making real calls.
external_user_id:
These are the two members of the exported
PrincipalContext union (see
Types). There is no third ProjectAdmin variant
reachable from the SDK — that context only comes from a Clerk-authenticated human admin session
(Developer Studio), a completely different auth model the SDK deliberately doesn’t implement.
Lifecycle and context managers
A client owns its underlyinghttpx client only if it created it. Pass your own http_client=
and the SDK will never close it (not even via close()/context-manager exit) — ownership stays
with you.
A note on the sync/async pairs
The resource classes are separate sync/async pairs (Providers/AsyncProviders, etc.) rather than
one class with dual-mode methods — Python needs a regular generator for sync streaming and an async
generator for async streaming, and await-ing can’t be abstracted over. The chat client is the
clearest case: ChatClient.stream() is a regular generator, AsyncChatClient.stream() is an async
generator. All resource classes, both chat clients, and every type are exported from the package
root (from personaai import Providers, AsyncProviders, ChatClient, ...).