fix(examples): merge validation fixes phases 2-4 into main (stacked on #1855)#1893
fix(examples): merge validation fixes phases 2-4 into main (stacked on #1855)#1893Dhivya-Bharathy wants to merge 10 commits into
Conversation
…ames - Fix MemoryConfig(memory=...) → user_id=... in agent_centric_api.py - Fix Session(memory=...) → user_id=... in session-example.py - Fix build_context_for_task(memory=...) → user_id=... in memory-quality-example.py Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
…ame__ guards - Fixed TypeError in RouterAgent._build_system_prompt() by removing **kwargs from super() call - Added if __name__ == '__main__' guards to 6 example files to prevent auto-execution on import - Addresses Gemini Code Assist review feedback Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
📝 WalkthroughWalkthroughThis PR updates many example scripts to use consolidated constructor shapes (memory/knowledge/output), adds main guards and env/capability checks, normalizes result shapes, and updates RouterAgent._build_system_prompt to accept tools/kwargs. ChangesExamples and API alignment
Estimated code review effort 🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
@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:
|
There was a problem hiding this comment.
Code Review
This pull request refactors numerous example scripts to align with consolidated configuration parameters, particularly updating memory, web search, and output options, while also wrapping execution blocks with standard __main__ guards. The code review identified two key issues: a missing import of AgentTeam in self-reflection-optimization-patterns.py that will cause a NameError at runtime, and a recommendation in router_agent.py to forward **kwargs to super()._build_system_prompt when overriding the method to ensure robust parameter propagation.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| def _build_system_prompt(self, tools=None, **kwargs) -> str: | ||
| """Build system prompt (inherited from parent but can be customized).""" | ||
| base_prompt = super()._build_system_prompt() | ||
| base_prompt = super()._build_system_prompt(tools=tools) |
There was a problem hiding this comment.
When overriding _build_system_prompt, it is highly recommended to forward **kwargs to super()._build_system_prompt to ensure any other keyword arguments are correctly passed to the parent class's method and prevent potential bugs if other mixins or future updates add more parameters.
| def _build_system_prompt(self, tools=None, **kwargs) -> str: | |
| """Build system prompt (inherited from parent but can be customized).""" | |
| base_prompt = super()._build_system_prompt() | |
| base_prompt = super()._build_system_prompt(tools=tools) | |
| def _build_system_prompt(self, tools=None, **kwargs) -> str: | |
| """Build system prompt (inherited from parent but can be customized).""" | |
| base_prompt = super()._build_system_prompt(tools=tools, **kwargs) |
| if __name__ == "__main__": | ||
| print("Starting self-reflection optimization demonstration...") | ||
| agents = AgentTeam( | ||
| agents=[reflection_agent], | ||
| tasks=[reflection_task], | ||
| process="sequential", | ||
| output="verbose", | ||
| ) | ||
| result = agents.start() |
There was a problem hiding this comment.
The AgentTeam class is used here but it is not imported in this file, which will cause a NameError at runtime. Please import AgentTeam from praisonaiagents.
| if __name__ == "__main__": | |
| print("Starting self-reflection optimization demonstration...") | |
| agents = AgentTeam( | |
| agents=[reflection_agent], | |
| tasks=[reflection_task], | |
| process="sequential", | |
| output="verbose", | |
| ) | |
| result = agents.start() | |
| if __name__ == "__main__": | |
| from praisonaiagents import AgentTeam | |
| print("Starting self-reflection optimization demonstration...") | |
| agents = AgentTeam( | |
| agents=[reflection_agent], | |
| tasks=[reflection_task], | |
| process="sequential", | |
| output="verbose", | |
| ) | |
| result = agents.start() |
|
@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
Phase 2: FIX Valid Issues Phase 3: Final Verdict |
|
Claude finished @MervinPraison's task —— View job Final Architecture Review ✅Todo List:
Phase 1: Architecture Review per AGENTS.md✅ Protocol-driven: Changes maintain proper separation between core SDK (praisonaiagents) and wrapper (praisonai). The fixes are minimal and focused. ✅ Backward compatible: No breaking changes. All fixes are internal improvements that maintain API compatibility. ✅ Performance: No hot-path regressions. Changes are focused on import structure and method parameter forwarding. Phase 2: Critical Issues FixedFixed Issues:
Files Modified:
What I Skipped:
Phase 3: Final Verdict✅ APPROVE - All critical issues have been resolved:
Recommendation: This PR is ready to merge. The validation fixes align examples with the current API while maintaining architectural principles. The two critical runtime issues have been resolved. Commit: 763f7c8d | |
- Fix missing AgentTeam import in self-reflection-optimization-patterns.py - Forward kwargs properly in RouterAgent._build_system_prompt to super() - Addresses critical issues identified by Gemini code reviewer Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
Greptile SummaryThis PR lands example validation fixes from phases 2–4 (memory/knowledge/metrics, session/output/execution, persistence/workflows/web/CLI) onto
Confidence Score: 3/5Two example files are syntactically broken due to merge-conflict residue and must be fixed before merging. The SDK change in router_agent.py is correct and isolated. The ~71 example migrations are well-structured. However, knowledge_qdrant.py and session-example.py each contain a bare examples/persistence/knowledge_qdrant.py and examples/python/stateful/session-example.py both require removal of the stray Important Files Changed
Reviews (1): Last reviewed commit: "Merge branch 'main' into phase4-api-fixe..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (8)
examples/knowledge/context_required_example.py (1)
95-96:⚠️ Potential issue | 🟠 Major | ⚡ Quick winDefensive response normalization is still missing in one verification path.
Line 95still assumesresponseis a string. Ifagent.chat()returnsNone/non-string, this path can raise at runtime. Normalize here the same way asLine 83andLine 107(e.g.,normalized = str(response or "")).🤖 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 `@examples/knowledge/context_required_example.py` around lines 95 - 96, The verification branch that checks for "47.50" currently assumes response is a string and can raise if agent.chat() returned None or a non-string; normalize the value the same way as the other checks by creating a normalized = str(response or "") before using it in the if condition and then check normalized for "47.50" or "$47.50" (use the existing response normalization pattern seen around the other agent.chat() checks).examples/python/tools/langchain/google-serper-search.py (1)
2-2:⚠️ Potential issue | 🟠 MajorLazy-load
GoogleSerperAPIWrapperto avoid crashing whenlangchain_communityis missing
examples/python/tools/langchain/google-serper-search.pyimportsGoogleSerperAPIWrapperat module import time (line 2), so an ImportError occurs before theSERPER_API_KEYguard inif __name__ == "__main__":(lines 13-21) can skip the example. Move the import inside the guarded block and handleImportErrorwith a clearpip install langchain-communityhint.Same module-level
langchain_community.utilitiesimport pattern exists in other examples (e.g.,serp-search.py,serp-api.py,searchapi-search.py,wikipedia-search.py).🤖 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 `@examples/python/tools/langchain/google-serper-search.py` at line 2, The module-level import of GoogleSerperAPIWrapper causes ImportError before the SERPER_API_KEY guard runs; move the import of langchain_community.utilities.GoogleSerperAPIWrapper inside the if __name__ == "__main__": block (after checking SERPER_API_KEY) and wrap it in a try/except ImportError that prints a clear message advising to pip install langchain-community (or skips running the example), so the example doesn’t crash when langchain_community is not installed; apply the same lazy-import pattern to other example files that import langchain_community.utilities (e.g., serp-search.py, serp-api.py, searchapi-search.py, wikipedia-search.py).examples/python/concepts/self-reflection-optimization-patterns.py (1)
11-11:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMove banner print under the main guard.
Line 11 still executes on import, so this module still has import-time side effects. Put that print inside the
if __name__ == "__main__":flow.🤖 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 `@examples/python/concepts/self-reflection-optimization-patterns.py` at line 11, The top-level print("=== Self-Reflection Optimization Patterns Example ===\n") causes import-time side effects; move this banner into the module's entry point by placing the print inside an if __name__ == "__main__": block (and ensure any demo/run logic in this file is also executed only under that guard), referencing the module's top-level print statement and the main guard to locate where to move it.examples/python/managed-agents/19_manage_environments.py (1)
5-16:⚠️ Potential issue | 🟠 Major | ⚡ Quick winGuard runtime demo code behind
if __name__ == "__main__":.This file still creates agents and calls
agent.start(...)at import time, which causes network side effects during import. Wrap the demo setup/execution in a main guard.🤖 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 `@examples/python/managed-agents/19_manage_environments.py` around lines 5 - 16, The demo currently instantiates ManagedAgent/ManagedConfig and calls agent.start("Say hello briefly") at import time; wrap the demo setup and execution (the ManagedAgent(...), Agent(...), and agent.start(...) lines) inside a main guard by moving them under if __name__ == "__main__": so importing this module has no network side effects while still allowing the script to run when executed directly.examples/python/token-metrics/01_basic_token_tracking.py (1)
2-5:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRoot cause: token-metrics example prose was not migrated with the API.
Both files now correctly useoutput={"metrics": True}in code, but user-facing text/comments still instructmetrics=True. Update both docs/comments together to keep onboarding and copy-paste paths accurate.🤖 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 `@examples/python/token-metrics/01_basic_token_tracking.py` around lines 2 - 5, The example prose still instructs using the old Agent(metrics=True) API; update all user-facing text and comments to reflect the current API by replacing references to "metrics=True" or "Agent(metrics=True)" with the new usage "output={\"metrics\": True}" (and mention Agent(output={\"metrics\": True}) where applicable) so copy-paste snippets and onboarding text match the actual code; change this in the token-metrics example and its companion doc/comments to keep them consistent.examples/python/mongodb/mongodb_memory_example.py (1)
30-39:⚠️ Potential issue | 🟠 MajorFix MongoDB memory config shape (
providermust be top-level)
examples/python/mongodb/mongodb_memory_example.pycurrently nests"provider": "mongodb"under"config"(creating{"config": {"provider": ...}}). TheMemoryconfig shape expects{"provider": "...", "config": {...}}(with connection/database settings insideconfig), so move"provider"to the top level and keep only MongoDB connection options under"config".🤖 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 `@examples/python/mongodb/mongodb_memory_example.py` around lines 30 - 39, The mongodb_memory_config object has provider nested under "config" but the Memory config expects provider at the top level; update mongodb_memory_config so "provider": "mongodb" is a top-level key and leave only connection/database/vector/search options (connection_string, database, use_vector_search, max_pool_size, min_pool_size, server_selection_timeout) inside the "config" dict to match the expected shape used by Memory.Source: Coding guidelines
examples/python/token-metrics/03_cost_estimation.py (1)
4-4:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate the docstring to reflect the new consolidated API.
The comment references
Agent(metrics=True), but the code now usesoutput={"metrics": True}. Update line 4 to match the current API.📝 Suggested documentation fix
""" Cost Estimation Example - SIMPLIFIED VERSION -This example demonstrates automatic token metrics and cost tracking -using just Agent(metrics=True). All tracking and display is automatic! +This example demonstrates automatic token metrics and cost tracking +using just Agent(output={"metrics": True}). All tracking and display is automatic! For custom cost calculations, you can still access the detailed reports. """🤖 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 `@examples/python/token-metrics/03_cost_estimation.py` at line 4, Update the docstring sentence that currently mentions "Agent(metrics=True)" to reference the new consolidated API by mentioning the actual parameter used in the code: "output={\"metrics\": True}" (or say using Agent(..., output={\"metrics\": True} if you want to show context). Locate the docstring near the top where Agent is described and replace the old API text so the docstring matches the runtime usage of output={"metrics": True}.examples/web/01_agent_web_config.py (1)
1-5:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate the example to match its stated purpose or revise the docstring.
The docstring claims "fine-grained control" using
WebConfig, butWebConfighas been removed and both agents now use the identicalweb="search_only"preset (lines 15 and 21). This example no longer demonstrates differentiated configuration.Consider either:
- Updating the docstring to describe the simplified preset-based API, or
- Demonstrating different presets/configurations if the goal is to show fine-grained control
📝 Suggested docstring fix
""" -WebConfig Example +Web Preset Configuration Example -Demonstrates using WebConfig for fine-grained control. +Demonstrates using web presets for search capabilities. """🤖 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 `@examples/web/01_agent_web_config.py` around lines 1 - 5, The example's docstring wrongly promises "fine-grained control" via WebConfig but WebConfig was removed and both agents use the same web="search_only" preset; either update the docstring to explain the new preset-based, simplified API (mentioning web="search_only" preset) or modify the example to demonstrate different presets/configurations (e.g., use two different web presets or agent configs instead of WebConfig) so the code actually shows differentiated behavior; locate references to WebConfig and the web="search_only" usage in this file and apply the chosen change.
🧹 Nitpick comments (8)
examples/python/telemetry/production-telemetry-example.py (2)
41-49: ⚡ Quick winConsider adding error handling to demonstrate production-grade patterns.
The script is labeled "Production Telemetry Example" but lacks exception handling around task execution. If
agents.start()raises an error, the entire loop will terminate. For an example demonstrating production telemetry patterns, wrapping the task execution in a try/except block would better showcase robust error handling and telemetry under failure conditions.♻️ Proposed enhancement to add error handling
with trace_cm: + try: task = Task( name=f"customer_request_{idx}", description=description, expected_output="Professional customer service response with solution", agent=customer_service_agent, ) agents = AgentTeam(agents=[customer_service_agent], tasks=[task], output="minimal") result = agents.start() print(f"✅ Request {idx} completed, response length={len(str(result))}") + except Exception as e: + print(f"❌ Request {idx} failed: {e}") + # In production, you might want to log this to your telemetry collector + continue🤖 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 `@examples/python/telemetry/production-telemetry-example.py` around lines 41 - 49, The loop around Task/AgentTeam execution lacks exception handling so a failure in agents.start() will abort the script; wrap the call to AgentTeam.start() (reference: AgentTeam and its agents.start()) in a try/except that catches Exception, logs the error (include context like task name/customer_request_{idx}) and records/flushes telemetry before continuing to the next iteration, ensuring the Task creation/print remains outside or in the finally block as appropriate.
38-40: 💤 Low valueConsider adding a comment to explain the trace context fallback pattern.
The dynamic trace context retrieval with
getattr/callablecheck is correct and defensive, but the pattern may not be immediately clear to readers. A brief comment explaining that this falls back tonullcontext()when the collector doesn't support tracing would improve readability.📝 Suggested clarifying comment
for idx, description in enumerate(requests, start=1): + # Use collector.trace() if available, otherwise no-op context trace_ctx = getattr(collector, "trace", None) trace_cm = trace_ctx(f"customer_request_{idx}") if callable(trace_ctx) else nullcontext()🤖 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 `@examples/python/telemetry/production-telemetry-example.py` around lines 38 - 40, Add a brief inline comment above the trace context setup (the trace_ctx/trace_cm assignments) explaining the fallback pattern: we use getattr(collector, "trace", None) to safely obtain a trace context factory, check callable(trace_ctx) to ensure it can be used as a context manager, and fall back to nullcontext() when the collector does not support tracing so the with trace_cm: block remains safe. Include reference to the variables trace_ctx, trace_cm, collector, and nullcontext so readers understand the defensive behavior.examples/python/mcp/websocket-mcp.py (1)
29-33: ⚡ Quick winAvoid inline auth token literals in example code.
Line 31andLine 40embed token strings directly. Even as placeholders, prefer environment-backed values to avoid copy/paste secret leakage patterns.Also applies to: 38-42
🤖 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 `@examples/python/mcp/websocket-mcp.py` around lines 29 - 33, Replace the inline auth token literals passed to the MCP constructor with environment-backed values: read the token via os.environ.get or os.getenv (e.g., token = os.getenv("MCP_AUTH_TOKEN")) and pass that variable into MCP(..., auth_token=token, ...), using a safe default or raising a clear error when missing; update both occurrences around the MCP(...) instantiation and any other examples that currently use "Bearer your-secret-token" so examples illustrate secure env-backed patterns.Source: Linters/SAST tools
examples/skills/basic_skill_usage.py (1)
55-63: ⚡ Quick winUpdate comment to match the code.
The comment on line 56 references
skills_dirs, but the code now uses theskillsparameter. This inconsistency may confuse users reading the example.📝 Suggested fix
# Example 3: Discovering skills from multiple directories print("\n" + "=" * 50) -print("Example 3: Using skills_dirs for discovery") +print("Example 3: Using skills for directory discovery") print("=" * 50)🤖 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 `@examples/skills/basic_skill_usage.py` around lines 55 - 63, Update the example header/comment to match the actual code: replace the text referencing "skills_dirs" with wording that reflects the Agent(...) call using the skills parameter (e.g., "Using skills for discovery" or "Scanning current directory via skills"), so the printed banner and comment align with the Agent(...) instantiation and the skills=["./"] argument.examples/python/usecases/analysis/code-analysis-agents.py (3)
103-106: ⚡ Quick winNarrow exception handling may miss operational failures.
The try/except block only catches
RuntimeError, but other exceptions (network errors, API failures, authentication issues) from the LLM or gitingest could propagate uncaught, causing unhelpful stack traces for users.🛡️ Suggested improvement
try: result = analyze_code(code_source) - except RuntimeError as exc: - print(f"Code analysis failed: {exc}") + except Exception as exc: + print(f"Code analysis failed: {exc.__class__.__name__}: {exc}") sys.exit(1)🤖 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 `@examples/python/usecases/analysis/code-analysis-agents.py` around lines 103 - 106, The current try/except around the analyze_code call only catches RuntimeError and can let other failures (network, API, auth, gitingest) crash with raw traces; change the handler for the analyze_code invocation to catch broad exceptions (e.g., Exception) instead of only RuntimeError, and log or print the full error details/stack (use logging.exception or include str(exc) and traceback) before calling sys.exit(1); locate the block around the analyze_code(...) call and update its except clause accordingly so all operational failures are caught and reported clearly.
93-96: ⚡ Quick winAdd remediation hint to error message.
The error message should help users understand why the result is None and what they can do about it.
💬 Suggested improvement
if result is None: - raise RuntimeError("No analysis result returned by AgentTeam.start()") + raise RuntimeError( + "No analysis result returned by AgentTeam.start(). " + "Verify the agent configuration, LLM connectivity, and that the code source contains analyzable content." + )As per coding guidelines: "Fail fast with clear error messages; include remediation hints in exceptions".
🤖 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 `@examples/python/usecases/analysis/code-analysis-agents.py` around lines 93 - 96, The runtime check after calling agents.start(context_text) should raise a RuntimeError that includes a remediation hint; update the exception thrown where result is None (the block after agents.start(context_text) / AgentTeam.start()) to include actionable guidance such as verifying the provided context_text is non-empty, confirming agents are configured/enabled, and checking individual agent run logs or exceptions for failures so users know what to inspect to fix the issue.Source: Coding guidelines
64-67: ⚡ Quick winAdd remediation hint to error message.
The error message should guide users on how to fix the problem. Consider including installation instructions or troubleshooting steps.
💬 Suggested improvement
except Exception as exc: - raise RuntimeError(f"Failed to ingest code source: {exc}") from exc + raise RuntimeError( + f"Failed to ingest code source: {exc}. " + "Ensure 'gitingest' is installed (pip install gitingest) and the source path/URL is accessible." + ) from excAs per coding guidelines: "Fail fast with clear error messages; include remediation hints in exceptions".
🤖 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 `@examples/python/usecases/analysis/code-analysis-agents.py` around lines 64 - 67, The RuntimeError raised in the ingest block should include a remediation hint to help users fix the issue: update the message raised from the except clause (around the ingest(code_source) call) to append guidance such as verifying that code_source path/URL is correct, ensuring required dependencies are installed, and providing example install/troubleshooting commands (e.g., pip install <needed-package> or checking read permissions). Keep the original exception chained (from exc) and include the ingest function name and code_source reference in the message for context.Source: Coding guidelines
examples/managed-agents/persistence/neon_managed.py (1)
28-33: 💤 Low valueUpdate commented example to match the new API.
The commented "Option 2" example still uses the old API with separate
db=andsession_id=parameters. For consistency and to avoid confusion, update it to use thememory={...}pattern like the active code above.♻️ Proposed update
# Option 2: Direct URL # agent = Agent( # name="Neon Agent", # instructions="You are a helpful assistant.", -# db={"database_url": "postgresql://user:pass@ep-xxx.neon.tech/dbname?sslmode=require"}, -# session_id="neon-demo-session", +# memory={ +# "session_id": "neon-demo-session", +# "db": {"database_url": "postgresql://user:pass@ep-xxx.neon.tech/dbname?sslmode=require"}, +# }, # )🤖 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 `@examples/managed-agents/persistence/neon_managed.py` around lines 28 - 33, The commented example uses the old API with db= and session_id=; update the Agent instantiation to the new memory= pattern used elsewhere: create Agent(name="Neon Agent", instructions="You are a helpful assistant.", memory={"neon": {"database_url": "postgresql://user:pass@ep-xxx.neon.tech/dbname?sslmode=require"}, "session_id": "neon-demo-session"}) instead of db=... and session_id=..., so adjust the commented block around the Agent(...) call to pass a single memory dict.
🤖 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.
Inline comments:
In `@examples/observability/multi_agent_tracing.py`:
- Around line 23-31: The helper set_span_attr currently silently no-ops when the
span neither implements set_attribute() nor exposes an attributes dict; update
set_span_attr to explicitly raise a clear exception (e.g., TypeError) in that
fallback path with a message naming the function (set_span_attr) and the span
object, describing that the span type is unsupported and advising to provide an
object implementing set_attribute(key, value) or an attributes dict so
attributes appear in traces; this ensures callers fail fast and get remediation
guidance instead of silent omission.
In `@examples/persistence/knowledge_qdrant.py`:
- Around line 53-57: Remove the stray "main" token from the knowledge dict (it's
invalid Python syntax) and replace it with the expected nested vector_store
configuration described in the PR: ensure the knowledge dict (where "sources":
[doc_path]) contains a "vector_store" mapping that sets "provider" (e.g.,
"qdrant") and the "url" (or connection details) so the structure matches the
nested vector_store configuration used elsewhere; update the dict assigned to
knowledge in examples/persistence/knowledge_qdrant.py (search for the knowledge
variable) to a valid Python dict without the leftover merge token.
In `@examples/policy/basic_policy.py`:
- Around line 57-61: The docstring/example for PolicyConfig is inconsistent with
the actual Agent API: Agent.__init__ has no policy parameter but Agent.policy
setter exists and examples use agent.policy = engine; update the PolicyConfig
docstring/snippet to construct a PolicyEngine from PolicyConfig (use
PolicyEngine(PolicyConfig(...))) and then set it via agent.policy = engine (or
alternatively add a policy parameter to Agent.__init__ if you prefer to change
the API), referencing the Agent class, its policy property setter, PolicyConfig,
and PolicyEngine so the snippet matches the real usage.
In `@examples/python/agents/autoagents-hierarchical-generation.py`:
- Around line 63-69: Top-level print statements cause import-time side effects;
move all banner/console output and any demo setup into the existing entrypoint
guard so importing the module is side-effect free. Specifically, relocate the
prints around agents_system.start() (the banner lines and the two informational
print() calls) so they execute only inside the if __name__ == "__main__": block
and ensure any demo initialization that produces console output is also moved
there; leave agents_system.start() invocation inside that guard and remove or
wrap any remaining top-level prints.
In `@examples/python/camera/camera-basic.py`:
- Line 93: The lookup for task_results can return None because
result.get("task_results") has no default; update the parsing so task_results =
result.get("task_results", result) (use a default of result) wherever you
extract task_results from a dict (e.g., the task_results assignment in
camera-basic.py that reads result and assigns task_results) to preserve non-dict
or alternate payloads—make the same change at the other symmetric occurrence
noted in the review.
In `@examples/python/failover_example.py`:
- Line 21: Update the code that prints/reads auth profiles to use the renamed
field profile.rate_limit_rpm instead of the old profile.rate_limit; locate the
print/logging logic and any places in the __main__ flow that reference
profile.rate_limit (e.g., when iterating over auth profiles or calling a
function that formats profile info) and change those accesses to
profile.rate_limit_rpm so the output path matches the new profile field name.
In `@examples/python/managed-agents/19_manage_environments.py`:
- Around line 41-42: Replace the broad "except Exception as e:" that prints
"Delete skipped (expected if sessions exist): {e}" with narrowly scoped handlers
for the specific delete-conflict and expected HTTP errors (e.g.,
ResourceConflictError or ConflictError from your SDK, and
HTTPError/HTTPStatusError if using requests/httpx) and import those exception
classes; for example, handle "except (ConflictError, HTTPStatusError) as e:" to
print the expected message and let any other exceptions propagate (or re-raise
them) so unexpected auth/network/schema failures are not masked.
In `@examples/python/memory/gemini-embedding-example.py`:
- Around line 88-97: Remove the stray bare token "main" from the memory
dictionary so the dict directly contains the "embedder" and "config" keys; edit
the memory structure around where the variable/assignment named memory is
defined (the block containing "embedder": {"provider":"gemini",...} and
"config": {"provider":"sqlite"}) to eliminate the merge residue and restore
valid Python dict syntax.
In `@examples/python/save_output/03_workflow_output_file.py`:
- Around line 36-62: The module executes the workflow at import time via result
= workflow.start() and prints results; refactor by moving the creation of
writer, workflow, and the call to workflow.start() and subsequent print("✅
Workflow completed!")/print("Output saved to: generated/tutorial.md") into a
main() function, then call that function under an if __name__ == "__main__":
guard; keep the Agent/AgentFlow/Task construction (symbols: Agent, AgentFlow,
Task, writer, workflow, workflow.start()) unchanged except to relocate them
inside main().
In `@examples/python/stateful/session-example.py`:
- Around line 16-19: The Session constructor call has a stray token "main"
causing a syntax error and an invalid positional-after-keyword argument; update
the Session(...) invocation (the Session class instantiation where
session_id="demo_chat_001") to remove the stray token and pass the intended
memory keyword argument, e.g. include memory={"user_id": "demo_user"} alongside
session_id so the call becomes Session(session_id="demo_chat_001",
memory={"user_id": "demo_user"}).
In `@src/praisonai-agents/praisonaiagents/agent/router_agent.py`:
- Around line 356-358: RouterAgent._build_system_prompt currently accepts
**kwargs but calls super()._build_system_prompt(tools=tools) so any extra
keyword args are silently dropped; either remove **kwargs from the
RouterAgent._build_system_prompt signature or explicitly validate and reject
unexpected kwargs by checking if kwargs is non-empty and raising a clear error
that tells callers which unsupported keys were passed and suggests removing them
or adding support; update the method (RouterAgent._build_system_prompt) to
forward kwargs to super()._build_system_prompt if the parent supports them,
otherwise raise a ValueError listing the keys in kwargs and remediation.
---
Outside diff comments:
In `@examples/knowledge/context_required_example.py`:
- Around line 95-96: The verification branch that checks for "47.50" currently
assumes response is a string and can raise if agent.chat() returned None or a
non-string; normalize the value the same way as the other checks by creating a
normalized = str(response or "") before using it in the if condition and then
check normalized for "47.50" or "$47.50" (use the existing response
normalization pattern seen around the other agent.chat() checks).
In `@examples/python/concepts/self-reflection-optimization-patterns.py`:
- Line 11: The top-level print("=== Self-Reflection Optimization Patterns
Example ===\n") causes import-time side effects; move this banner into the
module's entry point by placing the print inside an if __name__ == "__main__":
block (and ensure any demo/run logic in this file is also executed only under
that guard), referencing the module's top-level print statement and the main
guard to locate where to move it.
In `@examples/python/managed-agents/19_manage_environments.py`:
- Around line 5-16: The demo currently instantiates ManagedAgent/ManagedConfig
and calls agent.start("Say hello briefly") at import time; wrap the demo setup
and execution (the ManagedAgent(...), Agent(...), and agent.start(...) lines)
inside a main guard by moving them under if __name__ == "__main__": so importing
this module has no network side effects while still allowing the script to run
when executed directly.
In `@examples/python/mongodb/mongodb_memory_example.py`:
- Around line 30-39: The mongodb_memory_config object has provider nested under
"config" but the Memory config expects provider at the top level; update
mongodb_memory_config so "provider": "mongodb" is a top-level key and leave only
connection/database/vector/search options (connection_string, database,
use_vector_search, max_pool_size, min_pool_size, server_selection_timeout)
inside the "config" dict to match the expected shape used by Memory.
In `@examples/python/token-metrics/01_basic_token_tracking.py`:
- Around line 2-5: The example prose still instructs using the old
Agent(metrics=True) API; update all user-facing text and comments to reflect the
current API by replacing references to "metrics=True" or "Agent(metrics=True)"
with the new usage "output={\"metrics\": True}" (and mention
Agent(output={\"metrics\": True}) where applicable) so copy-paste snippets and
onboarding text match the actual code; change this in the token-metrics example
and its companion doc/comments to keep them consistent.
In `@examples/python/token-metrics/03_cost_estimation.py`:
- Line 4: Update the docstring sentence that currently mentions
"Agent(metrics=True)" to reference the new consolidated API by mentioning the
actual parameter used in the code: "output={\"metrics\": True}" (or say using
Agent(..., output={\"metrics\": True} if you want to show context). Locate the
docstring near the top where Agent is described and replace the old API text so
the docstring matches the runtime usage of output={"metrics": True}.
In `@examples/python/tools/langchain/google-serper-search.py`:
- Line 2: The module-level import of GoogleSerperAPIWrapper causes ImportError
before the SERPER_API_KEY guard runs; move the import of
langchain_community.utilities.GoogleSerperAPIWrapper inside the if __name__ ==
"__main__": block (after checking SERPER_API_KEY) and wrap it in a try/except
ImportError that prints a clear message advising to pip install
langchain-community (or skips running the example), so the example doesn’t crash
when langchain_community is not installed; apply the same lazy-import pattern to
other example files that import langchain_community.utilities (e.g.,
serp-search.py, serp-api.py, searchapi-search.py, wikipedia-search.py).
In `@examples/web/01_agent_web_config.py`:
- Around line 1-5: The example's docstring wrongly promises "fine-grained
control" via WebConfig but WebConfig was removed and both agents use the same
web="search_only" preset; either update the docstring to explain the new
preset-based, simplified API (mentioning web="search_only" preset) or modify the
example to demonstrate different presets/configurations (e.g., use two different
web presets or agent configs instead of WebConfig) so the code actually shows
differentiated behavior; locate references to WebConfig and the
web="search_only" usage in this file and apply the chosen change.
---
Nitpick comments:
In `@examples/managed-agents/persistence/neon_managed.py`:
- Around line 28-33: The commented example uses the old API with db= and
session_id=; update the Agent instantiation to the new memory= pattern used
elsewhere: create Agent(name="Neon Agent", instructions="You are a helpful
assistant.", memory={"neon": {"database_url":
"postgresql://user:pass@ep-xxx.neon.tech/dbname?sslmode=require"}, "session_id":
"neon-demo-session"}) instead of db=... and session_id=..., so adjust the
commented block around the Agent(...) call to pass a single memory dict.
In `@examples/python/mcp/websocket-mcp.py`:
- Around line 29-33: Replace the inline auth token literals passed to the MCP
constructor with environment-backed values: read the token via os.environ.get or
os.getenv (e.g., token = os.getenv("MCP_AUTH_TOKEN")) and pass that variable
into MCP(..., auth_token=token, ...), using a safe default or raising a clear
error when missing; update both occurrences around the MCP(...) instantiation
and any other examples that currently use "Bearer your-secret-token" so examples
illustrate secure env-backed patterns.
In `@examples/python/telemetry/production-telemetry-example.py`:
- Around line 41-49: The loop around Task/AgentTeam execution lacks exception
handling so a failure in agents.start() will abort the script; wrap the call to
AgentTeam.start() (reference: AgentTeam and its agents.start()) in a try/except
that catches Exception, logs the error (include context like task
name/customer_request_{idx}) and records/flushes telemetry before continuing to
the next iteration, ensuring the Task creation/print remains outside or in the
finally block as appropriate.
- Around line 38-40: Add a brief inline comment above the trace context setup
(the trace_ctx/trace_cm assignments) explaining the fallback pattern: we use
getattr(collector, "trace", None) to safely obtain a trace context factory,
check callable(trace_ctx) to ensure it can be used as a context manager, and
fall back to nullcontext() when the collector does not support tracing so the
with trace_cm: block remains safe. Include reference to the variables trace_ctx,
trace_cm, collector, and nullcontext so readers understand the defensive
behavior.
In `@examples/python/usecases/analysis/code-analysis-agents.py`:
- Around line 103-106: The current try/except around the analyze_code call only
catches RuntimeError and can let other failures (network, API, auth, gitingest)
crash with raw traces; change the handler for the analyze_code invocation to
catch broad exceptions (e.g., Exception) instead of only RuntimeError, and log
or print the full error details/stack (use logging.exception or include str(exc)
and traceback) before calling sys.exit(1); locate the block around the
analyze_code(...) call and update its except clause accordingly so all
operational failures are caught and reported clearly.
- Around line 93-96: The runtime check after calling agents.start(context_text)
should raise a RuntimeError that includes a remediation hint; update the
exception thrown where result is None (the block after
agents.start(context_text) / AgentTeam.start()) to include actionable guidance
such as verifying the provided context_text is non-empty, confirming agents are
configured/enabled, and checking individual agent run logs or exceptions for
failures so users know what to inspect to fix the issue.
- Around line 64-67: The RuntimeError raised in the ingest block should include
a remediation hint to help users fix the issue: update the message raised from
the except clause (around the ingest(code_source) call) to append guidance such
as verifying that code_source path/URL is correct, ensuring required
dependencies are installed, and providing example install/troubleshooting
commands (e.g., pip install <needed-package> or checking read permissions). Keep
the original exception chained (from exc) and include the ingest function name
and code_source reference in the message for context.
In `@examples/skills/basic_skill_usage.py`:
- Around line 55-63: Update the example header/comment to match the actual code:
replace the text referencing "skills_dirs" with wording that reflects the
Agent(...) call using the skills parameter (e.g., "Using skills for discovery"
or "Scanning current directory via skills"), so the printed banner and comment
align with the Agent(...) instantiation and the skills=["./"] argument.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 64a6be5b-83fe-42fb-a994-868a6f6818cd
📒 Files selected for processing (73)
examples/approval/agent_approval.pyexamples/consolidated_params/advanced_workflow_full_features.pyexamples/consolidated_params/basic_web.pyexamples/knowledge/context_required_example.pyexamples/managed-agents/persistence/cockroachdb_managed.pyexamples/managed-agents/persistence/neon_managed.pyexamples/managed-agents/persistence/supabase_direct_managed.pyexamples/managed-agents/persistence/turso_managed.pyexamples/middleware/configurable_model.pyexamples/middleware/injected_state.pyexamples/observability/multi_agent_tracing.pyexamples/persistence/knowledge_qdrant.pyexamples/persistence/minimal_agent_db.pyexamples/persistence/postgres_runs_traces.pyexamples/persistence/redis_state.pyexamples/persistence/session_resume.pyexamples/persistence/simple_db_agent.pyexamples/persistence/sqlite_local.pyexamples/policy/basic_policy.pyexamples/python/agents/autoagents-hierarchical-generation.pyexamples/python/api/simple-mcp-server.pyexamples/python/camera/camera-basic.pyexamples/python/camera/camera-continuous.pyexamples/python/camera/camera-multi-agent.pyexamples/python/cli/autonomy_modes_example.pyexamples/python/cli/cost_tracking_example.pyexamples/python/cli/slash_commands_example.pyexamples/python/concepts/repetitive-agents.pyexamples/python/concepts/self-reflection-optimization-patterns.pyexamples/python/custom_tools/example_latency_tracking.pyexamples/python/data/cot-agents.pyexamples/python/failover_example.pyexamples/python/general/memory_example.pyexamples/python/general/multimodal.pyexamples/python/guardrails/production-guardrails-patterns.pyexamples/python/linear_agent_example.pyexamples/python/managed-agents/19_manage_environments.pyexamples/python/mcp/mcp-resumability.pyexamples/python/mcp/mcp-session-management.pyexamples/python/mcp/streamable-http-mcp.pyexamples/python/mcp/websocket-mcp.pyexamples/python/memory/advanced-graph-memory-integration.pyexamples/python/memory/advanced-memory-search-optimization.pyexamples/python/memory/gemini-embedding-example.pyexamples/python/models/deepseek/deepseek-rag-agents.pyexamples/python/models/googlegemini/any-llm-agents-advanced.pyexamples/python/mongodb/mongodb_memory_example.pyexamples/python/save_output/03_workflow_output_file.pyexamples/python/session/session_persistence_example.pyexamples/python/stateful/advanced-state-management-patterns.pyexamples/python/stateful/session-example.pyexamples/python/telemetry/production-telemetry-example.pyexamples/python/token-metrics/01_basic_token_tracking.pyexamples/python/token-metrics/02_session_metrics.pyexamples/python/token-metrics/03_cost_estimation.pyexamples/python/tools/exa-tool/rag_examples/agentic_rag/rag_agent.pyexamples/python/tools/langchain/google-serper-search.pyexamples/python/usecases/analysis/code-analysis-agents.pyexamples/python/usecases/analysis/cv-analysis.pyexamples/python/usecases/analysis/hackathon-judge-agent.pyexamples/python/video/video_azure.pyexamples/python/workflows/task_callbacks.pyexamples/python/workflows/workflow_conditional.pyexamples/python/workflows/workflow_mixed_steps.pyexamples/python/workflows/workflow_robustness.pyexamples/retrieval/basic_retrieval.pyexamples/skills/basic_skill_usage.pyexamples/storage/storage_backends_example.pyexamples/terminal_bench/test_integration.pyexamples/web/00_agent_web_basic.pyexamples/web/01_agent_web_config.pyexamples/yaml/workflows/example_usage.pysrc/praisonai-agents/praisonaiagents/agent/router_agent.py
💤 Files with no reviewable changes (1)
- examples/python/custom_tools/example_latency_tracking.py
| def set_span_attr(span, key, value): | ||
| """Set span attribute safely across observability implementations.""" | ||
| if hasattr(span, "set_attribute"): | ||
| span.set_attribute(key, value) | ||
| return | ||
| attrs = getattr(span, "attributes", None) | ||
| if attrs is not None: | ||
| attrs[key] = value | ||
|
|
There was a problem hiding this comment.
Add explicit error handling for unsupported span objects.
The helper silently does nothing when the span supports neither set_attribute() nor an attributes dict. For an example demonstrating observability patterns, this silent failure could confuse users who copy this code—attributes won't appear in traces without any indication why.
As per coding guidelines, you should "fail fast with clear error messages; include remediation hints in exceptions."
🛡️ Proposed fix to add explicit error handling
def set_span_attr(span, key, value):
"""Set span attribute safely across observability implementations."""
if hasattr(span, "set_attribute"):
span.set_attribute(key, value)
return
attrs = getattr(span, "attributes", None)
if attrs is not None:
attrs[key] = value
+ return
+ raise AttributeError(
+ f"Span object does not support attribute setting. "
+ f"Expected 'set_attribute' method or 'attributes' dict, got {type(span).__name__}"
+ )🤖 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 `@examples/observability/multi_agent_tracing.py` around lines 23 - 31, The
helper set_span_attr currently silently no-ops when the span neither implements
set_attribute() nor exposes an attributes dict; update set_span_attr to
explicitly raise a clear exception (e.g., TypeError) in that fallback path with
a message naming the function (set_span_attr) and the span object, describing
that the span type is unsupported and advising to provide an object implementing
set_attribute(key, value) or an attributes dict so attributes appear in traces;
this ensures callers fail fast and get remediation guidance instead of silent
omission.
Source: Coding guidelines
| agent = Agent( | ||
| name="SecureAgent", | ||
| instructions="You are a file management assistant.", | ||
| policy=engine | ||
| ) | ||
| agent.policy = engine |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check if PolicyConfig pattern exists and how policy is used in other examples
# Search for PolicyConfig usage
ast-grep --pattern 'class PolicyConfig'
# Search for policy parameter usage in Agent constructor
rg -n -C3 'Agent\(' --type=py | rg -C3 'policy='
# Search for post-construction policy assignment pattern
rg -n 'agent\.policy\s*=' --type=pyRepository: MervinPraison/PraisonAI
Length of output: 22058
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Inspect the example around the flagged lines
echo "### examples/policy/basic_policy.py:57-80"
sed -n '50,90p' examples/policy/basic_policy.py
# 2) Find the Agent class definition and show its __init__ signature
echo
echo "### Locate Agent class"
fd -a "agent.py" . || true
fd -a "*agent*" src examples -t f || true
# Prefer AST-grep to find the class and __init__ params
echo
echo "### AST-grep: class Agent and __init__"
ast-grep --pattern $'class Agent { $$$ }' || true
# Fallback: text search for def __init__ with policy inside Agent-related files
echo
echo "### rg: Agent __init__ signature candidates"
rg -n --type=py "class Agent\b" -S src/praisonai-agents/praisonaiagents || true
rg -n --type=py "def __init__\(" -S src/praisonai-agents/praisonaiagents | rg -n "Agent|agent" || true
rg -n --type=py "policy\s*=" -S examples src/praisonai-agents/praisonaiagents | head -n 50
# 3) Search for Agent(policy=...) more robustly (multiline friendly)
echo
echo "### rg multiline-ish: Agent( ... policy="
rg -n --type=py "Agent\s*\(\s*[\s\S]{0,200}policy\s*=" src examples || trueRepository: MervinPraison/PraisonAI
Length of output: 50685
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Read the Python Agent implementation used by examples/policy/basic_policy.py
echo "### Candidate Agent python files (praisonai-agents)"
fd -a "agent.py" src/praisonai-agents/praisonaiagents/agent -t f
# Print the most likely one(s)
for f in src/praisonai-agents/praisonaiagents/agent/agent.py src/praisonai-agents/praisonaiagents/agent/*.py; do
if [ -f "$f" ]; then
echo "---- $f"
rg -n "class Agent\b|def __init__\(" "$f" | head -n 30 || true
rg -n "\bpolicy\b" "$f" | head -n 80 || true
fi
done
# 2) Focused: show Agent __init__ signature where 'policy' is mentioned
echo
echo "### Focused search for policy in python Agent __init__"
rg -n --type=py "def __init__\(" src/praisonai-agents/praisonaiagents/agent | head -n 50
rg -n --type=py -C3 "\bpolicy\b" src/praisonai-agents/praisonaiagents/agent/agent.py src/praisonai-agents/praisonaiagents/agent/*.py || true
# 3) Scan examples for policy usage patterns
echo
echo "### examples: PolicyConfig usage"
rg -n --type=py "PolicyConfig\s*\(" examples | head -n 50 || true
echo
echo "### examples: direct Agent(..., policy=...)"
rg -n --type=py -S "Agent\s*\(" examples | rg -n "policy\s*=" | head -n 80 || true
echo
echo "### examples: post-construction agent.policy assignment"
rg -n --type=py "agent\.policy\s*=" examples | head -n 50 || trueRepository: MervinPraison/PraisonAI
Length of output: 27379
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the flagged example end-to-end enough to see how `engine` is created.
echo "### examples/policy/basic_policy.py (top to ~90)"
sed -n '1,120p' examples/policy/basic_policy.py
# Inspect Agent.__init__ signature/doc around where `policy` is defined (agent.py is large).
echo
echo "### src/praisonai-agents/praisonaiagents/agent/agent.py: __init__ policy parameter context"
python3 - <<'PY'
import itertools
path="src/praisonai-agents/praisonaiagents/agent/agent.py"
start=480
end=920
with open(path,'r',encoding='utf-8') as f:
for i,line in enumerate(f,1):
if start<=i<=end:
print(f"{i}:{line.rstrip()}")
PY
# Inspect how policy is applied during execution (quick targeted searches).
echo
echo "### Search for policy usage inside agent.py (top-level)"
rg -n "policy" src/praisonai-agents/praisonaiagents/agent/agent.py | head -n 80
echo
echo "### Search for PolicyEngine/PolicyConfig classes"
fd -a "engine.py|Engine|policy_engine|PolicyEngine" src/praisonai-agents/praisonaiagents/policy -t f || true
rg -n --type=py "class PolicyEngine|PolicyEngine|PolicyConfig" src/praisonai-agents/praisonaiagents/policy -S || true
# Inspect policy engine implementation and whether it is configured via PolicyConfig.
echo
echo "### src/praisonai-agents/praisonaiagents/policy/* (policy engine/config definitions)"
for f in $(fd -a -t f src/praisonai-agents/praisonaiagents/policy); do
rg -n --type=py "class (PolicyEngine|PolicyConfig)\b" "$f" && echo "---- $f"
done 2>/dev/null || true
# Finally, scan for any other examples that do Agent(policy=PolicyConfig(...)) for policy engine usage.
echo
echo "### examples: Agent(..., policy=...) where policy is present (broader)"
rg -n --type=py "Agent\s*\(" examples | rg -n "policy\s*=" | head -n 100 || trueRepository: MervinPraison/PraisonAI
Length of output: 31742
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Re-print the full Agent.__init__ signature area (small window) and search for "policy" inside it
echo "### Print Agent.__init__ signature lines 500-590"
sed -n '500,590p' src/praisonai-agents/praisonaiagents/agent/agent.py
echo
echo "### rg for 'policy' within the Agent.__init__ signature window"
rg -n --type=py "policy\s*:" -n src/praisonai-agents/praisonaiagents/agent/agent.py | head -n 50 || true
# 2) Look for any config default resolver / consolidated param handling for policy
echo
echo "### rg for consolidated handling of policy in agent.py"
rg -n --type=py "PolicyConfig|policy\s*=|apply_config_defaults\(\"policy\"\)|param_name=\"policy\"|resolve\(.*policy" src/praisonai-agents/praisonaiagents/agent/agent.py | head -n 120
# 3) Find where policy is actually used during execution/tool checks
echo
echo "### rg for self._policy usage"
rg -n --type=py "self\._policy|_policy" src/praisonai-agents/praisonaiagents/agent/agent.py | head -n 120
# 4) Search in whole python package for Agent(policy=...) usage (beyond examples)
echo
echo "### rg: Agent(policy=...) across src/praisonai-agents"
rg -n --type=py "Agent\s*\([^)]*policy\s*=" src/praisonai-agents | head -n 80 || trueRepository: MervinPraison/PraisonAI
Length of output: 6858
🏁 Script executed:
#!/bin/bash
set -euo pipefail
AGENT_PY="src/praisonai-agents/praisonaiagents/agent/agent.py"
echo "### All occurrences of 'policy' in $AGENT_PY (first 80)"
rg -n "policy" "$AGENT_PY" | head -n 80
echo
echo "### Agent policy resolution block (around line 800-900)"
python3 - <<'PY'
path="src/praisonai-agents/praisonaiagents/agent/agent.py"
for start,end in [(760,880),(880,1020),(1860,2020),(2020,2210)]:
print(f"\n--- {start}-{end} ---")
with open(path,'r',encoding='utf-8') as f:
for i,line in enumerate(f,1):
if start<=i<=end:
print(f"{i}:{line.rstrip()}")
PY
echo
echo "### Look for 'param_name=\"policy\"' or 'policy' passed to resolve/apply_config_defaults"
rg -n --type=py "param_name\s*=\s*\"policy\"|apply_config_defaults\\(\"policy\"\\)|resolve\\(.*policy" "$AGENT_PY" || true
echo
echo "### Search for any mention of PolicyEngine/PolicyConfig in Agent python code"
rg -n --type=py "PolicyEngine|PolicyConfig" src/praisonai-agents/praisonaiagents/agent | head -n 50 || trueRepository: MervinPraison/PraisonAI
Length of output: 30826
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show PolicyEngine/PolicyConfig definitions relevant to configuration expectations
echo "### src/praisonai-agents/praisonaiagents/policy/engine.py"
sed -n '1,120p' src/praisonai-agents/praisonaiagents/policy/engine.py
echo
echo "### src/praisonai-agents/praisonaiagents/policy/config.py (top + usage snippet)"
sed -n '1,120p' src/praisonai-agents/praisonaiagents/policy/config.py
echo
echo "### src/praisonai-agents/praisonaiagents/policy/config.py (end of file / helpers if any)"
tail -n 80 src/praisonai-agents/praisonaiagents/policy/config.py
echo
echo "### src/praisonai-agents/praisonaiagents/policy/__init__.py"
sed -n '1,120p' src/praisonai-agents/praisonaiagents/policy/__init__.py
echo
echo "### Scan for any docs/example using Agent(policy=PolicyConfig(...)) in python agent codebase"
rg -n --type=py "Agent\s*\(\s*policy\s*=" src/praisonai-agents | head -n 50 || trueRepository: MervinPraison/PraisonAI
Length of output: 13060
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Confirm what praisonaiagents.Agent exports
echo "### src/praisonai-agents/praisonaiagents/__init__.py"
sed -n '1,120p' src/praisonai-agents/praisonaiagents/__init__.py
echo
echo "### src/praisonai-agents/praisonaiagents/agent/__init__.py"
sed -n '1,120p' src/praisonai-agents/praisonaiagents/agent/__init__.py
# 2) Search for any Python Agent __init__ that has a 'policy' parameter in its signature
echo
echo "### Search: Python Agent __init__ signatures that mention 'policy' (single-line)"
rg -n --type=py "def __init__\([^)]*policy[^)]*\)" src/praisonai-agents | head -n 50 || true
echo
echo "### Search: broader 'policy' near Agent __init__ (within same file)"
rg -n --type=py "def __init__\(" src/praisonai-agents/praisonaiagents/agent | head -n 50 || true
# 3) Check PolicyEngine supports PolicyConfig input (already saw config param, but confirm usage)
echo
echo "### Search in policy/engine.py for PolicyConfig usage"
rg -n "PolicyConfig" src/praisonai-agents/praisonaiagents/policy/engine.py
echo
echo "### Search examples for PolicyEngine(PolicyConfig"
rg -n --type=py "PolicyEngine\s*\(\s*PolicyConfig" examples src || trueRepository: MervinPraison/PraisonAI
Length of output: 13557
Clarify policy configuration API: agent.policy = engine is the current supported pattern
examples/policy/basic_policy.pyusesagent.policy = engine, which matches the currentpraisonaiagents.agent.AgentAPI:Agent.__init__has nopolicyparameter, but thepolicyproperty setter exists.- The
PolicyConfigdocstring still showsAgent(policy=PolicyConfig(...)), which doesn’t align with the PythonAgentsignature; update that snippet to usePolicyEngine(PolicyConfig(...))+agent.policy = engine(or addpolicysupport toAgent.__init__).
🤖 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 `@examples/policy/basic_policy.py` around lines 57 - 61, The docstring/example
for PolicyConfig is inconsistent with the actual Agent API: Agent.__init__ has
no policy parameter but Agent.policy setter exists and examples use agent.policy
= engine; update the PolicyConfig docstring/snippet to construct a PolicyEngine
from PolicyConfig (use PolicyEngine(PolicyConfig(...))) and then set it via
agent.policy = engine (or alternatively add a policy parameter to Agent.__init__
if you prefer to change the API), referencing the Agent class, its policy
property setter, PolicyConfig, and PolicyEngine so the snippet matches the real
usage.
Source: Coding guidelines
| if __name__ == "__main__": | ||
| print("Starting hierarchical agent generation...") | ||
| result = agents_system.start() | ||
|
|
||
| print(f"\nHierarchical Result: {result[:200]}...") | ||
| print("\n✅ AutoAgents hierarchical generation complete!") | ||
| print("Demonstrated coordinated hierarchical workflow between manager and specialist agents.") No newline at end of file | ||
| print(f"\nHierarchical Result: {str(result)[:200]}...") | ||
| print("\n✅ AutoAgents hierarchical generation complete!") | ||
| print("Demonstrated coordinated hierarchical workflow between manager and specialist agents.") No newline at end of file |
There was a problem hiding this comment.
Root cause: partial entrypoint-guard migration still leaves top-level side effects.
Both files guard start() but still print at module scope (Line 11 in each file). Move banner/console output (and ideally demo setup) fully under if __name__ == "__main__": to make imports side-effect free.
🤖 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 `@examples/python/agents/autoagents-hierarchical-generation.py` around lines 63
- 69, Top-level print statements cause import-time side effects; move all
banner/console output and any demo setup into the existing entrypoint guard so
importing the module is side-effect free. Specifically, relocate the prints
around agents_system.start() (the banner lines and the two informational print()
calls) so they execute only inside the if __name__ == "__main__": block and
ensure any demo initialization that produces console output is also moved there;
leave agents_system.start() invocation inside that guard and remove or wrap any
remaining top-level prints.
| if result: | ||
| print("\n🔍 Analysis Results:") | ||
| for task_id, task_result in result["task_results"].items(): | ||
| task_results = result.get("task_results") if isinstance(result, dict) else result |
There was a problem hiding this comment.
Shared result-parsing bug: missing default for task_results lookup.
Both files use result.get("task_results") without a fallback, so alternate dict payloads degrade to None. Use result.get("task_results", result) in both places.
🤖 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 `@examples/python/camera/camera-basic.py` at line 93, The lookup for
task_results can return None because result.get("task_results") has no default;
update the parsing so task_results = result.get("task_results", result) (use a
default of result) wherever you extract task_results from a dict (e.g., the
task_results assignment in camera-basic.py that reads result and assigns
task_results) to preserve non-dict or alternate payloads—make the same change at
the other symmetric occurrence noted in the review.
| except Exception as e: | ||
| print(f"Delete skipped (expected if sessions exist): {e}") |
There was a problem hiding this comment.
Narrow exception handling for environment deletion.
except Exception masks unexpected failures (auth/network/schema) as “expected.” Catch only the known delete-conflict/error types and let others surface.
🧰 Tools
🪛 Ruff (0.15.15)
[warning] 41-41: Do not catch blind exception: Exception
(BLE001)
🤖 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 `@examples/python/managed-agents/19_manage_environments.py` around lines 41 -
42, Replace the broad "except Exception as e:" that prints "Delete skipped
(expected if sessions exist): {e}" with narrowly scoped handlers for the
specific delete-conflict and expected HTTP errors (e.g., ResourceConflictError
or ConflictError from your SDK, and HTTPError/HTTPStatusError if using
requests/httpx) and import those exception classes; for example, handle "except
(ConflictError, HTTPStatusError) as e:" to print the expected message and let
any other exceptions propagate (or re-raise them) so unexpected
auth/network/schema failures are not masked.
Source: Linters/SAST tools
| # Build agent and workflow from config dict | ||
| writer_cfg = workflow_config["agents"]["writer"] | ||
| writer = Agent( | ||
| name="writer", | ||
| role=writer_cfg["role"], | ||
| goal=writer_cfg["goal"], | ||
| llm=writer_cfg["llm"], | ||
| ) | ||
|
|
||
| step_cfg = workflow_config["steps"][0] | ||
| workflow = AgentFlow( | ||
| name=workflow_config["metadata"]["name"], | ||
| variables=workflow_config["variables"], | ||
| steps=[ | ||
| Task( | ||
| name="write_tutorial", | ||
| description=step_cfg["action"], | ||
| expected_output=step_cfg["expected_output"], | ||
| output_file=step_cfg["output_file"], | ||
| agent=writer, | ||
| ) | ||
| ], | ||
| ) | ||
| result = workflow.start() | ||
|
|
||
| print("✅ Workflow completed!") | ||
| print("Output saved to: generated/tutorial.md") |
There was a problem hiding this comment.
Move workflow execution behind a main guard to avoid import-time side effects.
Line 59 executes workflow.start() at import time, which can trigger external calls/file writes when this module is imported by tests or docs tooling. Wrap execution/prints in main() and gate with if __name__ == "__main__":.
Suggested fix
-# Build agent and workflow from config dict
-writer_cfg = workflow_config["agents"]["writer"]
-writer = Agent(
- name="writer",
- role=writer_cfg["role"],
- goal=writer_cfg["goal"],
- llm=writer_cfg["llm"],
-)
-
-step_cfg = workflow_config["steps"][0]
-workflow = AgentFlow(
- name=workflow_config["metadata"]["name"],
- variables=workflow_config["variables"],
- steps=[
- Task(
- name="write_tutorial",
- description=step_cfg["action"],
- expected_output=step_cfg["expected_output"],
- output_file=step_cfg["output_file"],
- agent=writer,
- )
- ],
-)
-result = workflow.start()
-
-print("✅ Workflow completed!")
-print("Output saved to: generated/tutorial.md")
+def main():
+ # Build agent and workflow from config dict
+ writer_cfg = workflow_config["agents"]["writer"]
+ writer = Agent(
+ name="writer",
+ role=writer_cfg["role"],
+ goal=writer_cfg["goal"],
+ llm=writer_cfg["llm"],
+ )
+
+ step_cfg = workflow_config["steps"][0]
+ workflow = AgentFlow(
+ name=workflow_config["metadata"]["name"],
+ variables=workflow_config["variables"],
+ steps=[
+ Task(
+ name="write_tutorial",
+ description=step_cfg["action"],
+ expected_output=step_cfg["expected_output"],
+ output_file=step_cfg["output_file"],
+ agent=writer,
+ )
+ ],
+ )
+ workflow.start()
+
+ print("✅ Workflow completed!")
+ print("Output saved to: generated/tutorial.md")
+
+
+if __name__ == "__main__":
+ main()🤖 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 `@examples/python/save_output/03_workflow_output_file.py` around lines 36 - 62,
The module executes the workflow at import time via result = workflow.start()
and prints results; refactor by moving the creation of writer, workflow, and the
call to workflow.start() and subsequent print("✅ Workflow
completed!")/print("Output saved to: generated/tutorial.md") into a main()
function, then call that function under an if __name__ == "__main__": guard;
keep the Agent/AgentFlow/Task construction (symbols: Agent, AgentFlow, Task,
writer, workflow, workflow.start()) unchanged except to relocate them inside
main().
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/persistence/knowledge_qdrant.py (1)
42-67:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winProtect temp directory cleanup with
try/finally.If
Agent(...)oragent.chat(...)raises,shutil.rmtree(temp_dir)is skipped and temp artifacts are leaked. Wrap the runtime block so cleanup always executes.Suggested fix
temp_dir = tempfile.mkdtemp() doc_path = os.path.join(temp_dir, "guide.txt") -with open(doc_path, "w") as f: - f.write(sample_doc) - -print("=== Qdrant Knowledge Store Demo (Agent-First) ===") - -# Agent-first approach: use knowledge parameter with Qdrant -agent = Agent( - name="KnowledgeAssistant", - instructions="You are a helpful assistant with access to technical documentation.", - knowledge={ - "sources": [doc_path], - "vector_store": { - "provider": "qdrant", - "url": "http://localhost:6333", - }, - } -) - -# Chat - agent uses knowledge for RAG -response = agent.chat("What programming language is good for AI?") -print(f"Response: {response}") - -# Cleanup -shutil.rmtree(temp_dir) +try: + with open(doc_path, "w") as f: + f.write(sample_doc) + + print("=== Qdrant Knowledge Store Demo (Agent-First) ===") + + # Agent-first approach: use knowledge parameter with Qdrant + agent = Agent( + name="KnowledgeAssistant", + instructions="You are a helpful assistant with access to technical documentation.", + knowledge={ + "sources": [doc_path], + "vector_store": { + "provider": "qdrant", + "url": "http://localhost:6333", + }, + } + ) + + # Chat - agent uses knowledge for RAG + response = agent.chat("What programming language is good for AI?") + print(f"Response: {response}") +finally: + shutil.rmtree(temp_dir, ignore_errors=True)🤖 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 `@examples/persistence/knowledge_qdrant.py` around lines 42 - 67, The temp directory cleanup can be skipped if Agent(...) or agent.chat(...) raises; wrap the runtime block that uses tempfile.mkdtemp(), doc_path, Agent (KnowledgeAssistant) and agent.chat(...) in a try/finally so shutil.rmtree(temp_dir) is always executed; locate the temp_dir usage around tempfile.mkdtemp(), doc_path, Agent(...) and agent.chat(...) and move those calls into the try block and place shutil.rmtree(temp_dir) in the finally block to guarantee cleanup even on exceptions.
🧹 Nitpick comments (1)
examples/persistence/knowledge_qdrant.py (1)
24-69: ⚡ Quick winMove executable demo flow under a
__main__guard.Line 24 onward runs on import (file I/O + network-dependent chat). Gate this under
if __name__ == "__main__":to prevent import-time side effects.🤖 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 `@examples/persistence/knowledge_qdrant.py` around lines 24 - 69, The demo code runs on import and should be guarded; wrap the executable flow in an if __name__ == "__main__": block. Move creation of sample_doc, temp_dir, doc_path, writing the file, Agent instantiation (Agent, knowledge config with qdrant), the agent.chat call and shutil.rmtree cleanup into that guard so imports don’t perform file I/O or network calls; ensure variables remain scoped inside the block and preserve existing behavior/output.
🤖 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.
Outside diff comments:
In `@examples/persistence/knowledge_qdrant.py`:
- Around line 42-67: The temp directory cleanup can be skipped if Agent(...) or
agent.chat(...) raises; wrap the runtime block that uses tempfile.mkdtemp(),
doc_path, Agent (KnowledgeAssistant) and agent.chat(...) in a try/finally so
shutil.rmtree(temp_dir) is always executed; locate the temp_dir usage around
tempfile.mkdtemp(), doc_path, Agent(...) and agent.chat(...) and move those
calls into the try block and place shutil.rmtree(temp_dir) in the finally block
to guarantee cleanup even on exceptions.
---
Nitpick comments:
In `@examples/persistence/knowledge_qdrant.py`:
- Around line 24-69: The demo code runs on import and should be guarded; wrap
the executable flow in an if __name__ == "__main__": block. Move creation of
sample_doc, temp_dir, doc_path, writing the file, Agent instantiation (Agent,
knowledge config with qdrant), the agent.chat call and shutil.rmtree cleanup
into that guard so imports don’t perform file I/O or network calls; ensure
variables remain scoped inside the block and preserve existing behavior/output.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2bfbe39d-c29a-4f8a-8b59-37b7cb1e80da
📒 Files selected for processing (7)
examples/persistence/knowledge_qdrant.pyexamples/python/concepts/self-reflection-optimization-patterns.pyexamples/python/general/memory_example.pyexamples/python/memory/gemini-embedding-example.pyexamples/python/models/deepseek/deepseek-rag-agents.pyexamples/python/stateful/session-example.pysrc/praisonai-agents/praisonaiagents/agent/router_agent.py
💤 Files with no reviewable changes (2)
- examples/python/memory/gemini-embedding-example.py
- examples/python/general/memory_example.py
🚧 Files skipped from review as they are similar to previous changes (2)
- src/praisonai-agents/praisonaiagents/agent/router_agent.py
- examples/python/concepts/self-reflection-optimization-patterns.py
|
Greptile encountered an error while reviewing this PR. Please reach out to support@greptile.com for assistance. |
Summary
Final merge PR to land all example validation fixes (phases 2–4) onto
main.Phases 1–4 were previously merged as stacked PRs (#1855 → #1859 → #1864 → #1865). Phase 1 (#1855) is already on
main. This PR brings the remaining work fromphase4-api-fixesintomain.What's included
mainalready?__main__guardsValidation baseline: 796 examples → 503 PASS / 197 FAIL / 96 BLOCKED (Windows, v4.6.52).
Why 113 files vs
mainThis compares the full validation branch to
main. Phase 1 overlap with #1855 may appear in the diff; phases 2–4 (~64 unique example fixes) plus 1 SDK fix are the net new changes not yet onmain.Test plan
test-windows) passespython -m py_compileon changed examplesresults.jsonlin diffSummary by CodeRabbit
New Features
Configuration Changes
Examples & Documentation