Skip to content

fix: clear provider guidance on praisonai --init when no LLM key set#2338

Merged
MervinPraison merged 2 commits into
mainfrom
claude/issue-90-20260626-1428
Jun 26, 2026
Merged

fix: clear provider guidance on praisonai --init when no LLM key set#2338
MervinPraison merged 2 commits into
mainfrom
claude/issue-90-20260626-1428

Conversation

@praisonai-triage-agent

@praisonai-triage-agent praisonai-triage-agent Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Fixes #90

Summary

Addresses the long-standing feedback that PraisonAI onboarding feels OpenAI-only. Most of the issue is already resolved on main; this PR closes the one remaining beginner-UX gap (acceptance criterion #1).

Audit findings (2026-06-26)

  • Multi-provider support already exists (llm/env.py): OpenAI, Anthropic, Google/Gemini, Groq, Cohere, Ollama, OpenRouter + 100+ via LiteLLM.
  • "Empty tools" bug already fixed — auto.py uses role_details.get('tools', []) (no hardcoded ['']).
  • Beginner-friendly interactive setup already exists: praisonai setup (provider picker + hidden API-key prompt + unified ~/.praisonai/config.yaml), no shell export required.
  • Gap: the --init flow called the LLM immediately without checking for a configured provider, so a user with no key got a raw stack trace instead of guidance.

Change

  • Add _provider_preflight_message() in cli/main.py that uses the existing provider-aware is_configured() gate.
  • praisonai --init now prints a clear, actionable message (pointing at praisonai setup and listing supported providers) when no provider credential is found, instead of crashing.
  • The check is fail-safe: any internal error returns None so a configured user is never blocked.

Test plan

  • New tests/unit/cli/test_init_provider_guard.py (3 tests): unconfigured → message; configured → None; internal error → None.
  • Verified existing tests/unit/llm/test_credentials_is_configured.py (25 tests) still pass.

Routing / architecture

  • WRAPPER-only change (praisonai/ CLI). No new dependencies, no Agent params added, no core SDK changes. praisonai-rust / praisonai-ts untouched.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved the init flow to check for required AI provider setup before generating agents.
    • If no provider is configured, the app now shows clear setup guidance and stops early instead of failing later.
    • Unexpected credential-check errors no longer block initialization.
  • Tests
    • Added coverage for the provider setup check when credentials are missing, present, or when validation errors occur.

fixes #90)

Non-programmer users running `praisonai --init` with no API key (or a
non-OpenAI key for the OpenAI-default model) previously got a raw stack
trace, reinforcing the impression that PraisonAI is OpenAI-only. Add a
pre-flight credential check that emits an actionable message pointing at
the existing interactive `praisonai setup` wizard (no shell `export`
needed) and lists supported providers.

Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
@MervinPraison

Copy link
Copy Markdown
Owner

@coderabbitai review

@MervinPraison

Copy link
Copy Markdown
Owner

/review

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@praisonai-triage-agent praisonai-triage-agent Bot mentioned this pull request Jun 26, 2026
@greptile-apps

greptile-apps Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds clearer provider setup handling for praisonai --init.

  • Adds a preflight check before init-time LLM generation.
  • Injects saved credentials before checking provider setup.
  • Uses runtime model overrides when checking whether credentials match.
  • Adds unit coverage for the guard and init early return.

Confidence Score: 4/5

This is close, but the provider guard should be fixed before merging.

  • The new guard is placed before generator construction.
  • The mapped providers now follow the runtime model override more closely.
  • OpenRouter can still pass the guard without making its saved key available to generation.

src/praisonai/praisonai/cli/main.py and the credential provider mapping

Important Files Changed

Filename Overview
src/praisonai/praisonai/cli/main.py Adds the init provider guard, but the OpenRouter credential path still does not match runtime generation.
src/praisonai/tests/unit/cli/test_init_provider_guard.py Adds focused coverage for the new guard and init early return behavior.

Reviews (2): Last reviewed commit: "fix: align --init provider preflight wit..." | Re-trigger Greptile

Comment thread src/praisonai/praisonai/cli/main.py
Comment thread src/praisonai/praisonai/cli/main.py Outdated
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 50b13d0e-d4dc-4795-82c6-334cb9f7fa1b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The CLI init flow now checks for configured LLM provider credentials before generating agents. If none are detected, it prints setup guidance and exits early. New unit tests cover missing credentials, configured credentials, and credential-check errors.

Changes

Provider pre-flight guard

Layer / File(s) Summary
Helper and init gate
src/praisonai/praisonai/cli/main.py
_provider_preflight_message() checks provider configuration, returns setup guidance when absent, and the init path prints that message and returns early.
Provider guard tests
src/praisonai/tests/unit/cli/test_init_provider_guard.py
Unit tests cover _provider_preflight_message() for unconfigured, configured, and exception cases.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • MervinPraison

Poem

A bunny peeked at init time bright,
Sniffed for provider keys just right.
No keys? A hop, a helpful note;
With keys? I leap and let things float.
🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title matches the main change: clearer provider guidance during praisonai --init when no credential is configured.
Linked Issues check ✅ Passed The PR addresses issue #90's core ask by replacing raw init failures with actionable provider guidance and a fail-safe guard.
Out of Scope Changes check ✅ Passed Changes stay focused on init provider preflight logic and tests, with no unrelated scope added.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/issue-90-20260626-1428

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@MervinPraison

Copy link
Copy Markdown
Owner

@copilot Do a thorough review of this PR. Read ALL existing reviewer comments above from Qodo, Coderabbit, and Gemini first — incorporate their findings.

Review areas:

  1. Bloat check: Are changes minimal and focused? Any unnecessary code or scope creep?
  2. Security: Any hardcoded secrets, unsafe eval/exec, missing input validation?
  3. Performance: Any module-level heavy imports? Hot-path regressions?
  4. Tests: Are tests included? Do they cover the changes adequately?
  5. Backward compat: Any public API changes without deprecation?
  6. Code quality: DRY violations, naming conventions, error handling?
  7. Address reviewer feedback: If Qodo, Coderabbit, or Gemini flagged valid issues, include them in your review
  8. Suggest specific improvements with code examples where possible

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/praisonai/tests/unit/cli/test_init_provider_guard.py (1)

20-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add one test for the actual --init early-return path.

These cases only exercise _provider_preflight_message(). If Line 784's guard is removed or moved after _get_auto_generator(), this file still passes while praisonai --init regresses. Please add one PraisonAI.main() test that forces args.init, returns a preflight message, and asserts the generator is never reached.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai/tests/unit/cli/test_init_provider_guard.py` around lines 20 -
43, Add a test for the real `PraisonAI.main()` `--init` early-return path,
because the existing `_provider_preflight_message()` unit tests do not cover the
guard in `main`. In the new test, force `args.init` to be true and mock
`_provider_preflight_message()` to return a message, then assert
`PraisonAI.main()` returns early with that message and does not call
`_get_auto_generator()`. Use the existing `PraisonAI.main`,
`_provider_preflight_message`, and `_get_auto_generator` symbols so the test
stays aligned even if the guard moves.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/praisonai/tests/unit/cli/test_init_provider_guard.py`:
- Around line 20-43: Add a test for the real `PraisonAI.main()` `--init`
early-return path, because the existing `_provider_preflight_message()` unit
tests do not cover the guard in `main`. In the new test, force `args.init` to be
true and mock `_provider_preflight_message()` to return a message, then assert
`PraisonAI.main()` returns early with that message and does not call
`_get_auto_generator()`. Use the existing `PraisonAI.main`,
`_provider_preflight_message`, and `_get_auto_generator` symbols so the test
stays aligned even if the guard moves.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4684466-1d0e-4abd-af7a-1aeb5d06821c

📥 Commits

Reviewing files that changed from the base of the PR and between b5a45bf and 3184351.

📒 Files selected for processing (2)
  • src/praisonai/praisonai/cli/main.py
  • src/praisonai/tests/unit/cli/test_init_provider_guard.py

@MervinPraison

Copy link
Copy Markdown
Owner

@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAI (not a fork), you are able to make modifications to this branch and push directly. SCOPE: Focus ONLY on Python packages (praisonaiagents, praisonai). Do NOT modify praisonai-rust or praisonai-ts. CodeRabbit: 2 comments | Qodo: 1 comments | Greptile: 1 comments.

Review Context: 7 total comments, 4 bot reviews.

Phase 1: Review per AGENTS.md principles (protocol-driven, backward compatible, no perf impact, SDK value gate — no feature bloat).
Do not bloat the Agent class with additional params — only if absolutely required; we already support many params.
Phase 2: FIX valid issues found by prior reviewers.
Phase 3: Provide final verdict (approve or request changes).

@praisonai-triage-agent

praisonai-triage-agent Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Claude finished @MervinPraison's task —— View job


Final Architecture Review — PR #2338

  • Read AGENTS.md & repo guidelines
  • Read changed files (main.py, tests)
  • Trace is_configured() vs AutoGenerator credential/model resolution
  • Evaluate Greptile P1 findings — both VALID, fixed
  • Evaluate CodeRabbit nitpick — valid, fixed
  • Fix valid issues
  • Run tests (6 guard + 25 credentials = all pass)
  • Commit & push (85fa5719)

Phase 1 — Architecture (AGENTS.md)

  • Routing: WRAPPER-only (praisonai/cli/main.py). No core SDK change, no Agent params added, no new deps. ✅
  • Protocol-driven: reuses existing praisonai.llm.credentials helpers (is_configured, inject_credentials_into_env). No duplication. ✅
  • Backward compatible: fail-safe guard (any internal error → None, never blocks a configured user). Default no-override path unchanged. ✅
  • No perf impact: lazy imports inside the function; only runs on --init. ✅

Phase 2 — Fixes applied

I confirmed both Greptile P1s were real mismatches between the gate and runtime, and fixed them:

  1. Stored-credential bypass (main.py:787) — is_configured() consults the credential store (lines 235–241), but AutoGenerator.__init__ calls plain resolve_llm_endpoint() (env-only, no fallback_lookup). A key saved via praisonai setup passed the gate but yielded api_key=None at runtime → raw auth error.
    Fix: call inject_credentials_into_env() before gating, so stored keys reach the env-only resolver (consistent with the rest of the wrapper).

  2. Model-override skips guard (credentials.py:133) — guard called is_configured() with no model, so it inferred the provider default and ignored MODEL_NAME/OPENAI_MODEL_NAME. With ANTHROPIC_API_KEY + stale MODEL_NAME=gpt-4o-mini, the gate passed but runtime resolved the OpenAI model with no OPENAI_API_KEY.
    Fix: gate on the exact runtime model: is_configured(model=os.environ.get("MODEL_NAME") or os.environ.get("OPENAI_MODEL_NAME")). When no override is set, model=None preserves the prior inferred-default behaviour.

  3. CodeRabbit / Greptile test gap — added TestInitGuardWiring.test_init_returns_early_without_calling_generator, which drives the real PraisonAI.main() --init path and asserts _get_auto_generator is never called when the preflight returns a message (so the guard can't silently regress if moved/removed). Also added two unit tests covering credential injection and runtime-model gating.

Files modified

  • src/praisonai/praisonai/cli/main.py — preflight now mirrors runtime resolution (inject creds + gate on runtime model).
  • src/praisonai/tests/unit/cli/test_init_provider_guard.py — +3 tests (now 6 total).

Skipped: CodeRabbit's docstring-coverage warning — the new test functions are intentionally self-documenting via comments; adding boilerplate docstrings would be noise (out of scope for a bug fix).

Test results

tests/unit/cli/test_init_provider_guard.py ...... 6 passed
tests/unit/llm/test_credentials_is_configured.py  25 passed

Phase 3 — Verdict: ✅ Approve (after these fixes)

Minimal, protocol-driven, backward-compatible. The gate now provably agrees with runtime resolution, closing both P1 mismatches. No bloat, no new deps, no core/Agent changes.
Branch claude/issue-90-20260626-1428

…solution

Address Greptile P1 findings: the preflight gate could disagree with what
AutoGenerator actually does at runtime, so a user could pass the guard and
still hit a raw provider auth error.

- Inject stored credentials into env before gating so keys saved via
  `praisonai setup` reach the env-only AutoGenerator resolver.
- Gate on the exact runtime model (MODEL_NAME / OPENAI_MODEL_NAME) so a stale
  OpenAI override with only a non-OpenAI key is caught with guidance instead
  of failing later.
- Add regression tests: stored-credential injection, runtime model override
  gating, and the real PraisonAI.main() --init early-return path asserting the
  generator is never constructed.

Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
@MervinPraison

Copy link
Copy Markdown
Owner

@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAI (not a fork), you are able to make modifications to this branch and push directly. SCOPE: Focus ONLY on Python packages (praisonaiagents, praisonai). Do NOT modify praisonai-rust or praisonai-ts. Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding.

Phase 1: Review per AGENTS.md

  1. Protocol-driven: check heavy implementations vs core SDK
  2. Backward compatible: ensure zero feature regressions
  3. Performance: no hot-path regressions
  4. SDK value: review in depth whether the change genuinely adds value to the SDK — never add features for the sake of adding them. It must strengthen the SDK (simpler, more user-friendly, robust, world-class, secure). If it does not clearly add value, request changes or recommend rejecting/closing rather than merging scope creep
  5. Do not bloat the Agent class with additional params — only if absolutely required; we already support many params.

Phase 2: FIX Valid Issues
5. For any VALID bugs or architectural flaws found by Gemini, CodeRabbit, Qodo, Copilot, or any other reviewer: implement the fix
6. Push all code fixes directly to THIS branch (do NOT create a new PR)
7. Comment a summary of exact files modified and what you skipped

Phase 3: Final Verdict
8. If all issues are resolved, approve the PR / close the Issue
9. If blocking issues remain, request changes / leave clear action items

@praisonai-triage-agent

praisonai-triage-agent Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Claude finished @MervinPraison's task —— View job


Final Architecture Review — PR #2338

  • Read AGENTS.md & repo guidelines
  • Read changed files (main.py, tests) — current branch state
  • Verify prior fixes (Greptile P1s, CodeRabbit test gap) are landed
  • Trace is_configured() vs AutoGenerator credential/model resolution
  • Run tests (6 guard + 25 credentials = all pass)
  • Final verdict

Phase 1 — Architecture (AGENTS.md)

  • Routing: WRAPPER-only (praisonai/cli/main.py). No core SDK change, no Agent params added, no new deps. ✅
  • Protocol-driven: reuses existing praisonai.llm.credentials helpers (is_configured, inject_credentials_into_env) — no duplication. ✅
  • Backward compatible: fail-safe guard — any internal error → None, never blocks a configured user (main.py:153-154). Default no-override path unchanged (model=None). ✅
  • No perf impact: lazy imports inside the function; only runs on --init. ✅
  • SDK value: Genuine UX gap closed — onboarding no longer dumps a raw stack trace when no provider is set. Not feature bloat; it's the last acceptance criterion of Feedback  #90. ✅

Phase 2 — Prior reviewer findings (all already fixed on 85fa5719, re-verified)

I traced each finding against the live code and confirmed the fixes are correct:

  1. Greptile P1 — stored-credential bypass ✅ FIXED. is_configured() consults the credential store, but AutoGeneratorresolve_llm_endpoint() (auto.py:387) is env-only. Guard now calls inject_credentials_into_env() (main.py:146) first, so a key saved via praisonai setup is exported into env before gating and actually reaches generation.

  2. Greptile P1 — model-override skips guard ✅ FIXED. resolve_llm_endpoint resolves model as MODEL_NAME > OPENAI_MODEL_NAME > … (env.py:36,152). Guard now gates on the exact runtime model is_configured(model=MODEL_NAME or OPENAI_MODEL_NAME) (main.py:148-151), matching runtime. Stale MODEL_NAME=gpt-4o-mini with only a non-OpenAI key is now caught here instead of at the LLM call. When no override is set → model=None preserves prior inferred-default behaviour.

  3. CodeRabbit nitpick — missing --init early-return test ✅ FIXED. TestInitGuardWiring.test_init_returns_early_without_calling_generator drives the real PraisonAI.main() --init path and asserts _get_auto_generator is never called when preflight returns a message — guards against the gate being moved/removed.

No new fixes were required — the branch already reflects all valid prior feedback. Nothing additional to push.

Skipped: CodeRabbit docstring-coverage warning on test functions — the new tests are self-documenting via inline comments; boilerplate docstrings would be noise (out of scope for a bug fix).

Test results

tests/unit/cli/test_init_provider_guard.py ......            6 passed
tests/unit/llm/test_credentials_is_configured.py             25 passed

Phase 3 — Verdict: ✅ Approve

Minimal, protocol-driven, backward-compatible, fail-safe. The preflight gate provably mirrors runtime credential + model resolution, closing both Greptile P1 mismatches and the CodeRabbit test-coverage gap. No bloat, no new deps, no core/Agent changes. Ready to merge.

Note: I cannot submit a formal GitHub PR approval (security restriction) — this comment is my review verdict.
• Branch claude/issue-90-20260626-1428

runtime_model = _os.environ.get("MODEL_NAME") or _os.environ.get(
"OPENAI_MODEL_NAME"
)
if is_configured(model=runtime_model):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 OpenRouter still bypasses

This check still disagrees with the runtime path for OpenRouter models. resolve_llm_endpoint() treats openrouter/... as requiring OPENROUTER_API_KEY, but the credential guard path does not map OpenRouter for model-scoped checks or stored credential injection. When MODEL_NAME=openrouter/... is set and the key was saved through praisonai setup, this guard can proceed while the later generator path never exports OPENROUTER_API_KEY, so --init can still end in the raw provider auth failure instead of the setup guidance.

@MervinPraison

Copy link
Copy Markdown
Owner

MERGE_GATE_VERDICT: APPROVE

Automated fallback — Claude assess did not post a verdict comment (e.g. GitHub MCP unavailable).
All deterministic merge gates passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feedback

1 participant