Summary
A brand-new user who installs praisonai and runs praisonai run "hello" hits a raw provider error unless they have already exported OPENAI_API_KEY. There is no guided way to store credentials, pick a default model, or verify the setup. The wrapper should own a world-class first-run flow: praisonai auth login, secure credential storage, and a clear actionable message when no key is configured.
Current behaviour
praisonai/llm/env.py resolves the endpoint purely from environment variables (resolve_llm_endpoint()), silently defaulting to gpt-4o-mini with api_key=None; the failure surfaces later as a raw API error mid-run.
- There is no
auth command in praisonai/cli/commands/ β the closest is environment.py, which can view/check env vars (redacted) but cannot set or persist anything.
- The config system (
praisonai/cli/configuration/loader.py, paths.py, schema.py) supports ~/.praison/config.toml + project .praison/config.toml, but holds no credential or provider section and is not consulted for keys.
praisonai onboard (cli/commands/onboard.py) is bot-channel onboarding (Telegram/Discord/Slack), not LLM provider setup.
Desired behaviour
praisonai auth login [provider] β interactive prompt (paste key, optional base URL/model), validated with a cheap live call, persisted to ~/.praison/credentials.json with 0o600 permissions. Non-interactive: praisonai auth login openai --key-stdin.
praisonai auth list / praisonai auth logout [provider] for inspection and removal (keys always redacted in output).
- Credential resolution order: explicit env var β stored credential β fail fast. The wrapper exports the resolved key into the process env before invoking
praisonaiagents, so the core SDK stays untouched.
- When no key is found,
praisonai run exits immediately with a one-line fix: No API key configured. Run: praisonai auth login β instead of a mid-run provider traceback.
- Default model/provider selection persisted in the existing
config.toml (e.g. [llm] model = "...") and honoured by praisonai run when --model is absent.
Layer placement
- Primary layer: wrapper
- Why not core: the core SDK is protocol-driven and correctly receives credentials via env/parameters; credential storage and onboarding are install/UX concerns that must not add I/O or prompts to the runtime.
- Why not wrapper: n/a β this is the wrapper's job (install, first run, defaults).
- Why not tools: not agent-callable functionality.
- Why not plugins: not a lifecycle hook, guardrail, or policy.
- Secondary touch (optional): none required; wrapper exports resolved values via env, which
praisonaiagents already reads.
- 3-way surface (CLI + YAML + Python): yes β CLI (
praisonai auth ...), YAML/TOML (config.toml [llm] defaults referenced by agents.yaml runs), Python (env injection means Agent(...) works unchanged after auth login).
Proposed approach
- Add
praisonai/cli/commands/auth.py (Typer group: login, list, logout, status) and register it in cli/app.py.
- Add a small
CredentialStore in praisonai/cli/configuration/ β JSON file keyed by provider, written atomically with 0o600, lazy-imported.
- Extend
resolve_llm_endpoint() to optionally accept a fallback lookup injected by the wrapper (env always wins; backward-compatible signature).
- Add the fail-fast preflight check to
praisonai run / direct-prompt paths with the actionable message.
- Extend
ConfigSchema with an [llm] section (model, provider, base_url) consumed by run when flags are absent.
Resolution sketch
cli/commands/auth.py (~150 lines), cli/configuration/credentials.py (~80 lines).
llm/env.py: add optional fallback parameter to resolve_llm_endpoint().
cli/commands/run.py: preflight check + config-default model resolution.
- Tests: store round-trip, permission bits, precedence (env > store), preflight error message. Real agentic test:
praisonai run "What is 2+2?" succeeds after auth login with no env vars set.
Severity
Critical β this is the single biggest barrier between pip install praisonai and first success; every new CLI user hits it.
Validation
- Traced:
praisonai/llm/env.py (env-only resolution, api_key=None default), praisonai/cli/commands/ (no auth command exists), cli/commands/environment.py (view-only), cli/configuration/schema.py (no credential/llm section).
- No duplication:
environment, config, and onboard commands cover adjacent but distinct concerns.
Summary
A brand-new user who installs
praisonaiand runspraisonai run "hello"hits a raw provider error unless they have already exportedOPENAI_API_KEY. There is no guided way to store credentials, pick a default model, or verify the setup. The wrapper should own a world-class first-run flow:praisonai auth login, secure credential storage, and a clear actionable message when no key is configured.Current behaviour
praisonai/llm/env.pyresolves the endpoint purely from environment variables (resolve_llm_endpoint()), silently defaulting togpt-4o-miniwithapi_key=None; the failure surfaces later as a raw API error mid-run.authcommand inpraisonai/cli/commands/β the closest isenvironment.py, which can view/check env vars (redacted) but cannot set or persist anything.praisonai/cli/configuration/loader.py,paths.py,schema.py) supports~/.praison/config.toml+ project.praison/config.toml, but holds no credential or provider section and is not consulted for keys.praisonai onboard(cli/commands/onboard.py) is bot-channel onboarding (Telegram/Discord/Slack), not LLM provider setup.Desired behaviour
praisonai auth login [provider]β interactive prompt (paste key, optional base URL/model), validated with a cheap live call, persisted to~/.praison/credentials.jsonwith0o600permissions. Non-interactive:praisonai auth login openai --key-stdin.praisonai auth list/praisonai auth logout [provider]for inspection and removal (keys always redacted in output).praisonaiagents, so the core SDK stays untouched.praisonai runexits immediately with a one-line fix:No API key configured. Run: praisonai auth loginβ instead of a mid-run provider traceback.config.toml(e.g.[llm] model = "...") and honoured bypraisonai runwhen--modelis absent.Layer placement
praisonaiagentsalready reads.praisonai auth ...), YAML/TOML (config.toml[llm]defaults referenced byagents.yamlruns), Python (env injection meansAgent(...)works unchanged afterauth login).Proposed approach
praisonai/cli/commands/auth.py(Typer group:login,list,logout,status) and register it incli/app.py.CredentialStoreinpraisonai/cli/configuration/β JSON file keyed by provider, written atomically with0o600, lazy-imported.resolve_llm_endpoint()to optionally accept a fallback lookup injected by the wrapper (env always wins; backward-compatible signature).praisonai run/ direct-prompt paths with the actionable message.ConfigSchemawith an[llm]section (model, provider, base_url) consumed byrunwhen flags are absent.Resolution sketch
cli/commands/auth.py(~150 lines),cli/configuration/credentials.py(~80 lines).llm/env.py: add optionalfallbackparameter toresolve_llm_endpoint().cli/commands/run.py: preflight check + config-default model resolution.praisonai run "What is 2+2?"succeeds afterauth loginwith no env vars set.Severity
Critical β this is the single biggest barrier between
pip install praisonaiand first success; every new CLI user hits it.Validation
praisonai/llm/env.py(env-only resolution,api_key=Nonedefault),praisonai/cli/commands/(no auth command exists),cli/commands/environment.py(view-only),cli/configuration/schema.py(no credential/llm section).environment,config, andonboardcommands cover adjacent but distinct concerns.