Skip to content

fix: resolve cli_backend validation, bot streaming, and tool resolution regressions#2004

Open
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-investigation-7ed9
Open

fix: resolve cli_backend validation, bot streaming, and tool resolution regressions#2004
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-investigation-7ed9

Conversation

@cursor

@cursor cursor Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes three critical regressions found in the 2026-06-18 scheduled bug scan.

Bugs fixed

1. cli_backend validation always fails (PR #1988 regression)

  • Impact: Any YAML with cli_backend or runtime on framework: praisonai raised ValueError, blocking all CLI-backend workflows.
  • Root cause: _prepare_for_run() passed the adapter object to _validate_cli_backend_compatibility(), which compared framework != 'praisonai' — always true for an object.
  • Fix: Pass adapter.name instead.

2. Progressive streaming bots crash on first message

  • Impact: Telegram/Discord/Slack bots with streaming=True hit TypeError: achat() got an unexpected keyword argument 'stream_callback' on every message.
  • Root cause: _session.py passed stream_callback directly to agent.astart(), but achat() does not accept that parameter.
  • Fix: Bridge callbacks via agent.stream_emitter.add_callback() and call astart(stream=True, cancel_token=controller).

3. Bot default tools silently dropped

  • Impact: Bots received only a small hardcoded fallback toolset instead of the full configured defaults (clarify, todo_*, file tools, etc.).
  • Root cause: _defaults.py imported non-existent ToolResolver from praisonaiagents.tools; AttributeError was caught and returned [].
  • Fix: Import from praisonai.tool_resolver.

Validation

  • Added tests/unit/test_critical_bug_fixes_20260618.py (4 tests)
  • All 4 regression tests pass
Open in Web View Automation 

Summary by CodeRabbit

Bug Fixes

  • Fixed CLI backend compatibility validation to correctly handle non-default framework configurations
  • Enhanced streaming event handling in chat by routing callbacks through agent event emitters instead of passing them directly, with improved timeout and cancellation support

Tests

  • Added regression tests validating CLI backend validation and streaming callback behavior

… changes

- Pass adapter.name (not adapter object) to cli_backend validation so
  praisonai YAML configs with cli_backend/runtime no longer always fail
- Bridge bot streaming callbacks via stream_emitter and pass cancel_token
  to astart(), fixing TypeError on first streamed message and /stop handling
- Import ToolResolver from praisonai.tool_resolver in bot defaults so
  configured tools are not silently dropped to the fallback set

Adds regression tests covering all three fixes.

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 18, 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.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 366e9d9c-360f-4f5e-b62d-083309db1110

📥 Commits

Reviewing files that changed from the base of the PR and between 9d5db0c and e0318f3.

📒 Files selected for processing (4)
  • src/praisonai/praisonai/agents_generator.py
  • src/praisonai/praisonai/bots/_defaults.py
  • src/praisonai/praisonai/bots/_session.py
  • src/praisonai/tests/unit/test_critical_bug_fixes_20260618.py

📝 Walkthrough

Walkthrough

Three bug fixes are applied: _prepare_for_run now passes adapter.name (a string) instead of the adapter object to _validate_cli_backend_compatibility; _resolve_tool_names_with_workspace imports ToolResolver from praisonai.tool_resolver instead of praisonaiagents.tools; and BotSessionManager.chat bridges streaming through agent.stream_emitter instead of passing stream_callback directly to agent.astart(). A new regression test module covers all three fixes.

Changes

Three Bug Fixes and Regression Tests

Layer / File(s) Summary
CLI validator argument, ToolResolver import, and streaming bridge
src/praisonai/praisonai/agents_generator.py, src/praisonai/praisonai/bots/_defaults.py, src/praisonai/praisonai/bots/_session.py
Passes adapter.name string to _validate_cli_backend_compatibility; switches ToolResolver import to praisonai.tool_resolver; replaces direct stream_callback kwarg on agent.astart() with a bridged_stream_callback registered on agent.stream_emitter, wrapped in asyncio.wait_for with timeout and cancellation.
Regression tests
src/praisonai/tests/unit/test_critical_bug_fixes_20260618.py
Adds TestCliBackendValidation, TestBotStreamingPath, and TestBotDefaultToolResolution covering each of the three fixes: validator string argument, streaming emitter bridging, and ToolResolver import path.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • MervinPraison/PraisonAI#1797: Both PRs touch the CLI backend compatibility validation path in AgentsGenerator, specifically how _validate_cli_backend_compatibility is invoked with a framework argument.
  • MervinPraison/PraisonAI#1884: Both PRs modify AgentsGenerator._prepare_for_run around the CLI backend compatibility validation call.
  • MervinPraison/PraisonAI#1726: Both PRs interact with ToolResolver resolution behavior, where this PR switches to praisonai.tool_resolver.ToolResolver and that PR enhanced its caching.

Suggested reviewers

  • MervinPraison

Poem

🐇 Three little bugs were hiding away,
A wrong object, a wrong import path,
A callback passed in the wrong way!
The rabbit patched each with a one-line fix,
And tests to prove no more broken tricks. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the three main fixes: CLI backend validation, bot streaming, and tool resolution regressions are the primary changes reflected in the code modifications and test additions.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/critical-bug-investigation-7ed9

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 and usage tips.

@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

@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

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

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

@praisonai-triage-agent

praisonai-triage-agent Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Claude finished @MervinPraison's task —— View job


✅ Architecture Review Complete

Review Checklist:

  • Read AGENTS.md architecture guidelines
  • Review changed files for protocol-driven design compliance
  • Check backward compatibility
  • Verify no performance regressions
  • Analyze other reviewer feedback
  • Test the changes
  • Provide final verdict

📋 Review Summary

I've thoroughly reviewed all changes and comments from other reviewers (Qodo, CodeRabbit). This PR fixes three critical regressions with minimal, focused changes.

🔍 Detailed Analysis

1. CLI Backend Validation Fix (agents_generator.py:392)

  • Issue: Passing adapter object instead of adapter.name string to validation
  • Fix: Correctly passes adapter.name
  • Impact: Restores functionality for CLI-backend workflows
  • Architecture: ✅ Compliant - simple parameter fix

2. Bot Streaming Crash Fix (_session.py:303-337)

  • Issue: stream_callback passed directly to agent.astart() which doesn't accept it
  • Fix: Bridges callback via agent.stream_emitter.add_callback()
  • Architecture: ✅ Compliant - proper event emitter pattern
  • Performance: No regression - adds minimal overhead only in streaming path

3. Tool Resolution Fix (_defaults.py:164)

  • Issue: Import from non-existent praisonaiagents.tools.ToolResolver
  • Fix: Correct import from praisonai.tool_resolver
  • Architecture: ✅ Compliant - fixes import path

✅ Architecture Compliance

All changes follow AGENTS.md guidelines:

  • Protocol-driven: No new protocols added, only fixes existing implementations
  • Backward compatible: All fixes restore broken functionality without API changes
  • Performance: No hot-path regressions, streaming fix adds callback only when needed
  • Minimal scope: Changes are surgical, totaling only ~30 lines of actual fixes

🧪 Test Coverage

Tests added in test_critical_bug_fixes_20260618.py:

  • ✅ CLI backend validation with both allowed/rejected cases
  • ✅ Streaming callback bridging verification
  • ✅ Tool resolver import path validation

🔎 Other Reviewer Feedback

Qodo: Reviews paused (no issues raised)
CodeRabbit: No actionable items found

✅ Final Verdict

APPROVED - All three fixes are valid, minimal, and restore critical functionality without introducing new issues. The changes are well-tested and follow architectural guidelines.

No additional fixes required. The PR is ready to merge.


@MervinPraison MervinPraison marked this pull request as ready for review June 18, 2026 10:50
@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 →

@greptile-apps

greptile-apps Bot commented Jun 18, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes three independent regressions: a type mismatch that caused CLI-backend validation to always fail, a TypeError crash in bot streaming due to an unsupported keyword argument, and a silent AttributeError that returned an empty tool list instead of the configured defaults.

  • agents_generator.py: Passes adapter.name (string) instead of adapter (object) to _validate_cli_backend_compatibility(), correcting a comparison that was always True for any non-string value.
  • bots/_session.py: Streaming path now registers the caller's callback via agent.stream_emitter.add_callback() (matching the existing pattern in gateway/server.py) and invokes astart(stream=True, cancel_token=...) — eliminating the unsupported stream_callback kwarg.
  • bots/_defaults.py: Fixes the import of ToolResolver from praisonai.tool_resolver (where the class actually lives) instead of the non-existent praisonaiagents.tools location.

Confidence Score: 4/5

All three fixes are targeted and low-risk; the streaming change is consistent with the existing pattern in gateway/server.py.

Each fix is a small, well-scoped change. The adapter.name and ToolResolver import fixes are trivially correct. The streaming bridge mirrors existing production code in gateway/server.py. The one open edge — no warning emitted when stream_emitter is absent at runtime — is benign for real agents (the property always initializes) but could cause silent callback loss for non-standard agent objects.

bots/_session.py is the most behaviorally complex change and worth a second look, specifically the emitter is None branch where a provided stream_callback is silently discarded.

Important Files Changed

Filename Overview
src/praisonai/praisonai/agents_generator.py One-line fix: passes adapter.name (string) instead of adapter (object) to _validate_cli_backend_compatibility(), resolving the always-failing comparison.
src/praisonai/praisonai/bots/_defaults.py Import source for ToolResolver corrected from non-existent praisonaiagents.tools to praisonai.tool_resolver; the target class exists and the fix is correct.
src/praisonai/praisonai/bots/_session.py Streaming path now bridges via agent.stream_emitter.add_callback/remove_callback and calls astart(stream=True, cancel_token=...), consistent with gateway/server.py. Cleanup in finally is correct. Minor gap: no warning when emitter is None but stream_callback is provided.
src/praisonai/tests/unit/test_critical_bug_fixes_20260618.py Four regression tests added; CLI validation and streaming bridge paths are well covered, but the tool-resolver test only exercises the profile path and doesn't call resolver.resolve_many().

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Bot as Bot Handler
    participant BSM as BotSessionManager.chat()
    participant Emitter as agent.stream_emitter
    participant Agent as agent.astart()
    participant CB as stream_callback

    Bot->>BSM: chat(agent, user_id, prompt, stream_callback)
    BSM->>Emitter: getattr(agent, "stream_emitter", None)
    alt emitter is not None
        BSM->>Emitter: add_callback(bridged_stream_callback)
    end
    BSM->>Agent: "astart(prompt, stream=True, cancel_token=controller)"
    Agent-->>Emitter: emit(event) [during streaming]
    Emitter-->>CB: bridged_stream_callback(event) → stream_callback(event)
    Agent-->>BSM: response
    BSM->>Emitter: remove_callback(bridged_stream_callback)
    BSM-->>Bot: response
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Bot as Bot Handler
    participant BSM as BotSessionManager.chat()
    participant Emitter as agent.stream_emitter
    participant Agent as agent.astart()
    participant CB as stream_callback

    Bot->>BSM: chat(agent, user_id, prompt, stream_callback)
    BSM->>Emitter: getattr(agent, "stream_emitter", None)
    alt emitter is not None
        BSM->>Emitter: add_callback(bridged_stream_callback)
    end
    BSM->>Agent: "astart(prompt, stream=True, cancel_token=controller)"
    Agent-->>Emitter: emit(event) [during streaming]
    Emitter-->>CB: bridged_stream_callback(event) → stream_callback(event)
    Agent-->>BSM: response
    BSM->>Emitter: remove_callback(bridged_stream_callback)
    BSM-->>Bot: response
Loading

Reviews (1): Last reviewed commit: "fix: resolve three critical regressions ..." | Re-trigger Greptile

Comment on lines 303 to +316
if stream_callback:
# Streaming path: use agent.astart() with stream callback and timeout
# Streaming path: bridge events via stream_emitter because
# achat()/astart() do not accept stream_callback directly.
emitter = getattr(agent, "stream_emitter", None)
if emitter is not None:
def bridged_stream_callback(event):
try:
result = stream_callback(event)
if asyncio.iscoroutine(result):
asyncio.get_running_loop().create_task(result)
except Exception as cb_exc:
logger.warning("Stream callback failed: %s", cb_exc)

emitter.add_callback(bridged_stream_callback)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Silent callback drop when stream_emitter is absent

When stream_callback is provided but getattr(agent, "stream_emitter", None) returns None, the callback is never registered yet astart(stream=True) is still called. The original caller's streaming callback is silently ignored with no log warning, making it hard to diagnose why no stream events arrive. A logger.warning when emitter is None would make this detectable in production.

Comment on lines +93 to +107
class TestBotDefaultToolResolution:
"""Bot defaults must resolve tools via praisonai.tool_resolver.ToolResolver."""

def test_resolve_tool_names_uses_praisonai_tool_resolver(self):
from praisonai.bots._defaults import _resolve_tool_names_with_workspace

sentinel = object()
with patch(
"praisonaiagents.tools.profiles.resolve_profiles",
return_value=[sentinel],
) as mock_profiles:
resolved = _resolve_tool_names_with_workspace(["search_web"])

assert sentinel in resolved
mock_profiles.assert_called_once_with("web")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 ToolResolver code path is not exercised

The test only passes ["search_web"], which maps through profile_map and exits via resolve_profiles before ToolResolver is ever instantiated. The import of ToolResolver is validated implicitly (an ImportError would surface), but resolver.resolve_many([...]) for a non-profile tool is never exercised. Adding a second assertion with a tool name that falls through to individual_tools (e.g. "my_custom_tool") would cover the full intended fix path.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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.

2 participants