praisonai auth stores provider credentials locally so praisonai run works without exporting env vars every session. Two methods are supported: a long-lived API key, or a short-lived OAuth token signed in via your browser.
Quick Start
- Picker
- API Key
- OAuth (Browser)
- Headless / SSH
ModelCatalogue.list_providers(): openai, anthropic, google, ollama first, every other catalogue provider (Groq, OpenRouter, Mistral, DeepSeek, xAI, …) next, and custom last.Commands
auth login now accepts an optional provider. Run praisonai auth login with no argument to pick from a catalogue-driven list (any provider ModelCatalogue knows about — Groq, OpenRouter, Mistral, DeepSeek, xAI, …); curated providers appear first, custom last. Scripts that pass the provider positionally still work unchanged. A one-line “Get your key” hint prints before the masked prompt for well-known providers.Login flags
Which --method should I use?
--method auto on a registry provider without a --client-id prints an info line telling you how to switch to OAuth explicitly, then falls back to the API-key prompt.Provider Picker
Omit the provider argument andauth login opens a catalogue-driven picker so you never have to memorise a provider id.
ModelCatalogue.list_providers(): openai, anthropic, google, ollama first, every other catalogue provider appended, custom last. Picking custom prompts for a free-form provider id. The positional <provider> argument still works unchanged — keep passing it in scripts and CI.
OAuth Login (browser-based)
Two flows are negotiated automatically per provider:- Device code (RFC 8628) — prints a short code + URL, polls until you approve. Default on headless servers.
- Authorization code + PKCE (RFC 7636) — opens your default browser and listens on
127.0.0.1for the redirect. Default on desktops.
Built-in providers ship with endpoints but no
client_id (registration-specific). Supply your OAuth app’s id via --client-id; the CLI resolves the rest.Token storage & refresh
Self-hosted / custom OAuth providers
praisonai auth login ships built-in endpoints for github, google, gemini, and azure. For a provider outside the registry (e.g. a self-hosted gateway), supply the endpoints directly with CLI flags:
device flow when a --device-authorization-url is present, or falls back to authcode (PKCE) when you pass --authorization-url instead.
As an escape hatch, you can also register a provider config from Python before invoking the flow:
Headless / SSH
API Key Login
auth login (and setup) print a Get your key: link to the provider’s key-creation page before the hidden prompt for catalogue providers, so first-run users don’t have to guess where to find one:PROVIDER_KEY_URLS map (key_url_for_provider()). Providers without a mapped URL skip the hint silently.List & status
Logout
List & Status — new columns
Source shows where the live credential comes from: stored (from ~/.praisonai/credentials.json) or env (VARNAME) when an active environment variable is present. An env key that shadows a stored one is flagged env (VARNAME) [live, overrides stored].
Expires shows (n/a) for API keys, 59m, 1h 23m, <1m, or expired for OAuth tokens, and (no expiry) when the provider didn’t include one.
Stored vs environment credentials
auth list and auth status surface both stored credentials (from ~/.praisonai/credentials.json) and active environment-variable keys for catalogue-known providers. The Source column disambiguates them:
When
PRAISONAI_AUTH_CONTENT is set, every stored-side entry reports env (in-memory) instead of stored:
Source line appends [live, overrides stored] so it’s visible:
sk-1***efgh).
The
auth list and auth status table columns changed in this release — Method, Source, and Expires columns were added, and active env-var credentials are now surfaced. Scripts that parse the table output need to be updated. The --json output is additive only (new source / env_var keys added; no existing keys removed).Credential env-var aliases
Some providers declare more than one credential env-var spelling — Together’sTOGETHER_API_KEY / TOGETHERAI_API_KEY, Fireworks’ FIREWORKS_API_KEY / FIREWORKS_AI_API_KEY, Google’s GOOGLE_API_KEY / GEMINI_API_KEY. auth list and auth status recognise every alias — a key set under a secondary spelling is surfaced exactly like one set under the canonical first.
Source column names whichever alias is live in the environment, so it always tells you exactly which variable the runtime is reading — even when a secondary spelling is the one you set. If no alias is set but the provider is otherwise referenced, the canonical first var name is shown for display only.
Multi-alias recognition was fixed in PraisonAI PR #4099. Before this fix,
auth list / auth status only knew the canonical first spelling for each provider and would report “not found” for a key the runtime happily accepted under a secondary alias. After the fix, auth matches runtime detection exactly.Credential Fields (ProviderCredential)
Each stored provider credential contains the following fields:
auth list and auth status show Method and Expires columns reflecting these fields.
Storage & Security
Path change — auto-migrated. Prior releases stored credentials at
~/.praison/credentials.json. The canonical path is now ~/.praisonai/credentials.json; the legacy path is still read if the canonical file doesn’t exist yet, and any subsequent auth login or setup transparently migrates your old entries onto the canonical file. No re-login is required.Zero-disk mode (PRAISONAI_AUTH_CONTENT)
Set PRAISONAI_AUTH_CONTENT to a JSON credential store and PraisonAI runs entirely from memory — nothing is ever read from or written to ~/.praisonai/credentials.json.
Use it for ephemeral containers (Docker/Kubernetes), CI runners, and secret-hygiene-sensitive deployments where OAuth and refresh tokens must not touch disk. A single secret injects the whole store — including OAuth entries — with zero on-disk footprint.
The value is a JSON object mapping provider name → credential object. Each credential object mirrors the on-disk ProviderCredential fields — api_key and auth_method for API keys, plus access_token, refresh_token, and expires_at for OAuth:
- Bash / CI
- Python
Precedence: the env blob always wins over any on-disk
credentials.json. Per-provider API-key env vars (OPENAI_API_KEY, …) still win for that specific provider at run time — unchanged.auth list and auth status report the Source column as env (in-memory) in this mode via the CredentialStore.is_in_memory property, so zero-disk runs are never silently invisible.
Sibling for config:
PRAISONAI_CONFIG_CONTENT and PRAISONAI_CONFIG do the same thing for the user-config layer. Setting both alongside PRAISONAI_AUTH_CONTENT gives you a fully zero-disk PraisonAI run. See Security Environment Variables → PRAISONAI_CONFIG_CONTENT.Supported Providers
praisonai auth list / praisonai auth status recognise every provider in PROVIDER_ENV_CATALOGUE — the same catalogue that drives first-run credential detection (full 14-row table) and praisonai setup.
Unknown providers accept API keys with length ≥ 10. OAuth is opt-in per provider; registry providers ship endpoints but no
client_id — pass yours with --client-id.
Optional dependency
The OAuth flow uses therequests library. It is lazy-imported, so users on the API-key path never see it. If a user runs --method oauth without it installed:
How Run Uses Credentials
praisonai run resolves credentials in this order:
- Environment variables (
OPENAI_API_KEY,ANTHROPIC_API_KEY, …) - Stored credentials — OAuth tokens refreshed transparently (~60 s before expiry) before injection. When
PRAISONAI_AUTH_CONTENTis set, this store is the in-memory env blob instead of~/.praisonai/credentials.json, and any OAuth refresh stays in memory only - LLM endpoint resolution via
resolve_llm_endpoint_with_credentials
Model → provider inference
Whenpraisonai run picks a model id from your environment (rather than a --model flag or [llm] config entry), it prints a one-line transparency notice naming the credential that drove the choice:
OPENROUTER_API_KEY, MISTRAL_API_KEY, DEEPSEEK_API_KEY, XAI_API_KEY, TOGETHER_API_KEY / TOGETHERAI_API_KEY, FIREWORKS_API_KEY / FIREWORKS_AI_API_KEY, PERPLEXITYAI_API_KEY, or COHERE_API_KEY all produce the notice with the alias you actually set — so you can see which key the runtime picked up before the first LLM call.
For providers with multiple credential spellings, the notice names whichever alias is live in os.environ, matching the Source column of auth list.
Coverage was extended in PraisonAI PR #4099. Before this fix,
_provider_for_model() silently returned None for openrouter/mistral/deepseek/xai/together/fireworks, so no transparency notice printed for those providers even when a key was set. After the fix, every catalogued provider prints the notice.praisonai run reports:
Related
Run
Preflight credential check before execution
Config
Default model via
[llm] in config.tomlSetup
First-run setup wizard

