Compare commits

...
8 Commits
Author SHA1 Message Date
Mervin Praison 13a9a3e07d Release v3.8.8 2026-01-13 13:06:26 +00:00
Mervin Praison b95f6b0665 Release v3.8.7 2026-01-13 12:55:43 +00:00
github-actions[bot] e8c4410014 docs: auto-update api.md [skip ci] 2026-01-13 09:30:27 +00:00
Mervin Praison 6c2d852ed1 Release v3.8.6 2026-01-13 09:30:11 +00:00
Mervin Praison 6f95ae8d9d Release v3.8.5 2026-01-13 07:04:53 +00:00
Mervin Praison 8e2dd09b3b Release v3.8.4 2026-01-13 06:17:09 +00:00
github-actions[bot] 8ecfad5c5a docs: auto-update api.md [skip ci] 2026-01-13 06:01:35 +00:00
Mervin Praison 35a88a0913 Release v3.8.3 2026-01-13 06:01:20 +00:00
179 changed files with 1752 additions and 1139 deletions

No files matched your search

+5 -448
View File
@@ -3,27 +3,11 @@
This file is auto-generated. Do not edit manually.
Regenerate with: `praisonai docs api-md --write`
# Shared Types
Types:
```python
from praisonaiagents import ContextPolicy, GuardrailResult, HandoffConfig, HandoffCycleError, HandoffDepthError, HandoffError, HandoffInputData, HandoffResult, HandoffTimeoutError, ReflectionOutput, StepResult, TaskOutput, ToolResult, ToolValidationError, WorkflowContext
```
Methods:
* <code title="class GuardrailResult">GuardrailResult.<a href="./src/praisonai-agents/praisonaiagents/guardrails/guardrail_result.py">from_tuple</a>(result: Tuple[bool, Any]) -> 'GuardrailResult'</code>
* <code title="class HandoffConfig">HandoffConfig.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">from_dict</a>(data: Dict[str, Any]) -> 'HandoffConfig'</code>
* <code title="class HandoffConfig">HandoffConfig.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">to_dict</a>() -> Dict[str, Any]</code>
* <code title="class TaskOutput">TaskOutput.<a href="./src/praisonai-agents/praisonaiagents/main.py">json</a>() -> Optional[str]</code>
* <code title="class TaskOutput">TaskOutput.<a href="./src/praisonai-agents/praisonaiagents/main.py">to_dict</a>() -> dict</code>
* <code title="class ToolResult">ToolResult.<a href="./src/praisonai-agents/praisonaiagents/tools/base.py">to_dict</a>() -> Dict[str, Any]</code>
# Agents
Types:
```python
from praisonaiagents import Agent, Agents, AutoAgents, AutoRagAgent, ContextAgent, DeepResearchAgent, ImageAgent, PraisonAIAgents, PromptExpanderAgent, QueryRewriterAgent, create_context_agent
from praisonaiagents import Agent, Agents
```
Methods:
@@ -77,7 +61,7 @@ Methods:
* <code title="class Agent">Agent.<a href="./src/praisonai-agents/praisonaiagents/agent/agent.py">run_autonomous</a>(prompt: str, max_iterations: Optional[int] = None, timeout_seconds: Optional[float] = None)</code>
* <code title="class Agent">Agent.<a href="./src/praisonai-agents/praisonaiagents/agent/agent.py">session_id</a>() -> Optional[str]</code>
* <code title="class Agent">Agent.<a href="./src/praisonai-agents/praisonaiagents/agent/agent.py">skill_manager</a>()</code>
* <code title="class Agent">Agent.<a href="./src/praisonai-agents/praisonaiagents/agent/agent.py">start</a>(prompt: str, **kwargs)</code>
* <code title="class Agent">Agent.<a href="./src/praisonai-agents/praisonaiagents/agent/agent.py">start</a>(prompt: str = None, **kwargs)</code>
* <code title="class Agent">Agent.<a href="./src/praisonai-agents/praisonaiagents/agent/agent.py">store_memory</a>(content: str, memory_type: str = 'short_term', **kwargs)</code>
* <code title="class Agent">Agent.<a href="./src/praisonai-agents/praisonaiagents/agent/agent.py">switch_model</a>(new_model: str) -> None</code>
* <code title="class Agent">Agent.<a href="./src/praisonai-agents/praisonaiagents/agent/agent.py">thinking_budget</a>()</code>
@@ -117,462 +101,35 @@ Methods:
* <code title="class Agents">Agents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">save_output_to_file</a>(task, task_output)</code>
* <code title="class Agents">Agents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">save_session_state</a>(session_id: str, include_memory: bool = True) -> None</code>
* <code title="class Agents">Agents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">set_state</a>(key: str, value: Any) -> None</code>
* <code title="class Agents">Agents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">start</a>(content = None, return_dict = False, **kwargs)</code>
* <code title="class Agents">Agents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">start</a>(content = None, return_dict = False, output = None, **kwargs)</code>
* <code title="class Agents">Agents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">todo_list</a>()</code>
* <code title="class Agents">Agents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">update_plan_step_status</a>(step_id: str, status: str) -> bool</code>
* <code title="class Agents">Agents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">update_state</a>(updates: Dict) -> None</code>
* <code title="class AutoAgents">AutoAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/autoagents.py">astart</a>()</code>
* <code title="class AutoAgents">AutoAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/autoagents.py">start</a>()</code>
* <code title="class AutoRagAgent">AutoRagAgent.<a href="./src/praisonai-agents/praisonaiagents/agents/auto_rag_agent.py">achat</a>(message: str, **kwargs) -> str</code>
* <code title="class AutoRagAgent">AutoRagAgent.<a href="./src/praisonai-agents/praisonaiagents/agents/auto_rag_agent.py">chat</a>(message: str, **kwargs) -> str</code>
* <code title="class AutoRagAgent">AutoRagAgent.<a href="./src/praisonai-agents/praisonaiagents/agents/auto_rag_agent.py">name</a>() -> str</code>
* <code title="class AutoRagAgent">AutoRagAgent.<a href="./src/praisonai-agents/praisonaiagents/agents/auto_rag_agent.py">rag</a>() -> Optional['RAG']</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">analyze_codebase_with_gitingest</a>(project_path: str) -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">analyze_integration_points</a>(project_path: str) -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">analyze_test_patterns</a>(project_path: str) -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">build_implementation_blueprint</a>(feature_request: str, context_analysis: Dict[str, Any] = None) -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">compile_context_documentation</a>(project_path: str) -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">create_quality_gates</a>(requirements: List[str]) -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">create_validation_framework</a>(project_path: str) -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">execute_prp</a>(prp_file_path: str) -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">extract_implementation_patterns</a>(project_path: str, ast_analysis: Dict[str, Any] = None) -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">generate_comprehensive_prp</a>(feature_request: str, context_analysis: Dict[str, Any] = None) -> str</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">generate_feature_prp</a>(feature_request: str) -> str</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">get_agent_interaction_summary</a>() -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">log_debug</a>(message: str, **kwargs)</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">perform_ast_analysis</a>(project_path: str) -> Dict[str, Any]</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">save_comprehensive_session_report</a>()</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">save_markdown_output</a>(content: str, filename: str, section_title: str = 'Output')</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">setup_logging</a>()</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">setup_output_directories</a>()</code>
* <code title="class ContextAgent">ContextAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">start</a>(input_text: str) -> str</code>
* <code title="class DeepResearchAgent">DeepResearchAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/deep_research_agent.py">aresearch</a>(query: str, instructions: Optional[str] = None, model: Optional[str] = None, summary_mode: Optional[Literal['auto', 'detailed', 'concise']] = None, web_search: Optional[bool] = None, code_interpreter: Optional[bool] = None, mcp_servers: Optional[List[Dict[str, Any]]] = None, file_ids: Optional[List[str]] = None, file_search: Optional[bool] = None, file_search_stores: Optional[List[str]] = None) -> DeepResearchResponse</code>
* <code title="class DeepResearchAgent">DeepResearchAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/deep_research_agent.py">async_openai_client</a>()</code>
* <code title="class DeepResearchAgent">DeepResearchAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/deep_research_agent.py">clarify</a>(query: str, model: Optional[str] = None) -> str</code>
* <code title="class DeepResearchAgent">DeepResearchAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/deep_research_agent.py">follow_up</a>(query: str, previous_interaction_id: str, model: Optional[str] = None) -> DeepResearchResponse</code>
* <code title="class DeepResearchAgent">DeepResearchAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/deep_research_agent.py">gemini_client</a>()</code>
* <code title="class DeepResearchAgent">DeepResearchAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/deep_research_agent.py">openai_client</a>()</code>
* <code title="class DeepResearchAgent">DeepResearchAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/deep_research_agent.py">research</a>(query: str, instructions: Optional[str] = None, model: Optional[str] = None, summary_mode: Optional[Literal['auto', 'detailed', 'concise']] = None, web_search: Optional[bool] = None, code_interpreter: Optional[bool] = None, mcp_servers: Optional[List[Dict[str, Any]]] = None, file_ids: Optional[List[str]] = None, file_search: Optional[bool] = None, file_search_stores: Optional[List[str]] = None, stream: bool = True) -> DeepResearchResponse</code>
* <code title="class DeepResearchAgent">DeepResearchAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/deep_research_agent.py">rewrite_query</a>(query: str, model: Optional[str] = None) -> str</code>
* <code title="class ImageAgent">ImageAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/image_agent.py">achat</a>(prompt: str, temperature: float = 0.2, tools: Optional[List[Any]] = None, output_json: Optional[str] = None, output_pydantic: Optional[Any] = None, reasoning_steps: bool = False, **kwargs) -> Union[str, Dict[str, Any]]</code>
* <code title="class ImageAgent">ImageAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/image_agent.py">agenerate_image</a>(prompt: str, **kwargs) -> Dict[str, Any]</code>
* <code title="class ImageAgent">ImageAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/image_agent.py">chat</a>(prompt: str, **kwargs) -> Dict[str, Any]</code>
* <code title="class ImageAgent">ImageAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/image_agent.py">generate_image</a>(prompt: str, **kwargs) -> Dict[str, Any]</code>
* <code title="class ImageAgent">ImageAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/image_agent.py">litellm</a>()</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">add_task</a>(task)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">aexecute_task</a>(task_id)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">append_to_state</a>(key: str, value: Any, max_length: Optional[int] = None) -> List[Any]</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">arun_all_tasks</a>()</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">arun_task</a>(task_id)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">astart</a>(content = None, return_dict = False, **kwargs)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">clean_json_output</a>(output: str) -> str</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">clear_state</a>() -> None</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">context_manager</a>()</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">current_plan</a>()</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">default_completion_checker</a>(task, agent_output)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">delete_state</a>(key: str) -> bool</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">display_token_usage</a>()</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">execute_task</a>(task_id)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_agent_details</a>(agent_name)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_all_state</a>() -> Dict[str, Any]</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_all_tasks_status</a>()</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_detailed_token_report</a>() -> Dict[str, Any]</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_plan_markdown</a>() -> str</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_state</a>(key: str, default: Any = None) -> Any</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_task_details</a>(task_id)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_task_result</a>(task_id)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_task_status</a>(task_id)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_todo_markdown</a>() -> str</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">get_token_usage_summary</a>() -> Dict[str, Any]</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">has_state</a>(key: str) -> bool</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">increment_state</a>(key: str, amount: float = 1, default: float = 0) -> float</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">launch</a>(path: str = '/agents', port: int = 8000, host: str = '0.0.0.0', debug: bool = False, protocol: str = 'http')</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">restore_session_state</a>(session_id: str) -> bool</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">run</a>(content = None, return_dict = False, **kwargs)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">run_all_tasks</a>()</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">run_task</a>(task_id)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">save_output_to_file</a>(task, task_output)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">save_session_state</a>(session_id: str, include_memory: bool = True) -> None</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">set_state</a>(key: str, value: Any) -> None</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">start</a>(content = None, return_dict = False, **kwargs)</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">todo_list</a>()</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">update_plan_step_status</a>(step_id: str, status: str) -> bool</code>
* <code title="class PraisonAIAgents">PraisonAIAgents.<a href="./src/praisonai-agents/praisonaiagents/agents/agents.py">update_state</a>(updates: Dict) -> None</code>
* <code title="class PromptExpanderAgent">PromptExpanderAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/prompt_expander_agent.py">agent</a>()</code>
* <code title="class PromptExpanderAgent">PromptExpanderAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/prompt_expander_agent.py">expand</a>(prompt: str, strategy: ExpandStrategy = ..., context: Optional[str] = None) -> ExpandResult</code>
* <code title="class PromptExpanderAgent">PromptExpanderAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/prompt_expander_agent.py">expand_basic</a>(prompt: str, context: Optional[str] = None) -> ExpandResult</code>
* <code title="class PromptExpanderAgent">PromptExpanderAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/prompt_expander_agent.py">expand_creative</a>(prompt: str, context: Optional[str] = None) -> ExpandResult</code>
* <code title="class PromptExpanderAgent">PromptExpanderAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/prompt_expander_agent.py">expand_detailed</a>(prompt: str, context: Optional[str] = None) -> ExpandResult</code>
* <code title="class PromptExpanderAgent">PromptExpanderAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/prompt_expander_agent.py">expand_structured</a>(prompt: str, context: Optional[str] = None) -> ExpandResult</code>
* <code title="class QueryRewriterAgent">QueryRewriterAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">add_abbreviation</a>(abbrev: str, expansion: str) -> None</code>
* <code title="class QueryRewriterAgent">QueryRewriterAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">add_abbreviations</a>(abbreviations: Dict[str, str]) -> None</code>
* <code title="class QueryRewriterAgent">QueryRewriterAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">agent</a>()</code>
* <code title="class QueryRewriterAgent">QueryRewriterAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">rewrite</a>(query: str, strategy: RewriteStrategy = ..., chat_history: Optional[List[Dict[str, str]]] = None, context: Optional[str] = None, num_queries: int = None) -> RewriteResult</code>
* <code title="class QueryRewriterAgent">QueryRewriterAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">rewrite_basic</a>(query: str) -> RewriteResult</code>
* <code title="class QueryRewriterAgent">QueryRewriterAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">rewrite_contextual</a>(query: str, chat_history: List[Dict[str, str]]) -> RewriteResult</code>
* <code title="class QueryRewriterAgent">QueryRewriterAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">rewrite_hyde</a>(query: str) -> RewriteResult</code>
* <code title="class QueryRewriterAgent">QueryRewriterAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">rewrite_multi_query</a>(query: str, num_queries: int = None) -> RewriteResult</code>
* <code title="class QueryRewriterAgent">QueryRewriterAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">rewrite_step_back</a>(query: str) -> RewriteResult</code>
* <code title="class QueryRewriterAgent">QueryRewriterAgent.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">rewrite_sub_queries</a>(query: str) -> RewriteResult</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/agent/context_agent.py">create_context_agent</a>(llm: Optional[Union[str, Any]] = None, **kwargs) -> ContextAgent</code>
# Tools
Types:
```python
from praisonaiagents import BaseTool, FunctionTool, ToolRegistry, Tools, get_registry, get_tool, register_tool, tool, validate_tool
from praisonaiagents import Tools, tool
```
Methods:
* <code title="class BaseTool">BaseTool.<a href="./src/praisonai-agents/praisonaiagents/tools/base.py">__call__</a>(**kwargs) -> Any</code>
* <code title="class BaseTool">BaseTool.<a href="./src/praisonai-agents/praisonaiagents/tools/base.py">get_schema</a>() -> Dict[str, Any]</code>
* <code title="class BaseTool">BaseTool.<a href="./src/praisonai-agents/praisonaiagents/tools/base.py">run</a>(**kwargs) -> Any</code>
* <code title="class BaseTool">BaseTool.<a href="./src/praisonai-agents/praisonaiagents/tools/base.py">safe_run</a>(**kwargs) -> ToolResult</code>
* <code title="class BaseTool">BaseTool.<a href="./src/praisonai-agents/praisonaiagents/tools/base.py">validate</a>() -> bool</code>
* <code title="class BaseTool">BaseTool.<a href="./src/praisonai-agents/praisonaiagents/tools/base.py">validate_class</a>() -> bool</code>
* <code title="class FunctionTool">FunctionTool.<a href="./src/praisonai-agents/praisonaiagents/tools/decorator.py">__call__</a>(*args, **kwargs) -> Any</code>
* <code title="class FunctionTool">FunctionTool.<a href="./src/praisonai-agents/praisonaiagents/tools/decorator.py">injected_params</a>() -> Dict[str, Any]</code>
* <code title="class FunctionTool">FunctionTool.<a href="./src/praisonai-agents/praisonaiagents/tools/decorator.py">run</a>(**kwargs) -> Any</code>
* <code title="class ToolRegistry">ToolRegistry.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">clear</a>() -> None</code>
* <code title="class ToolRegistry">ToolRegistry.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">discover_plugins</a>() -> int</code>
* <code title="class ToolRegistry">ToolRegistry.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">get</a>(name: str) -> Optional[Union[BaseTool, Callable]]</code>
* <code title="class ToolRegistry">ToolRegistry.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">get_all</a>() -> Dict[str, Union[BaseTool, Callable]]</code>
* <code title="class ToolRegistry">ToolRegistry.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">list_base_tools</a>() -> List[BaseTool]</code>
* <code title="class ToolRegistry">ToolRegistry.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">list_tools</a>() -> List[str]</code>
* <code title="class ToolRegistry">ToolRegistry.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">register</a>(tool: Union[BaseTool, Callable], name: Optional[str] = None, overwrite: bool = False) -> None</code>
* <code title="class ToolRegistry">ToolRegistry.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">unregister</a>(name: str) -> bool</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">get_registry</a>() -> ToolRegistry</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">get_tool</a>(name: str) -> Optional[Union[BaseTool, Callable]]</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/tools/registry.py">register_tool</a>(tool: Union[BaseTool, Callable], name: Optional[str] = None) -> None</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/tools/decorator.py">tool</a>(func: Optional[Callable] = None) -> Union[FunctionTool, Callable[[Callable], FunctionTool]]</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/tools/base.py">validate_tool</a>(tool: Any) -> bool</code>
# Workflows
Types:
```python
from praisonaiagents import Loop, Parallel, Pipeline, Repeat, Route, Workflow, WorkflowStep, loop, parallel, repeat, route
```
Methods:
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">arun</a>(input: str = '', llm: Optional[str] = None, verbose: bool = False) -> Dict[str, Any]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">astart</a>(input: str = '', llm: Optional[str] = None, verbose: bool = False) -> Dict[str, Any]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">from_template</a>(uri: str, config: Optional[Dict[str, Any]] = None, offline: bool = False, **kwargs) -> 'Workflow'</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">memory_config</a>() -> Optional[Dict[str, Any]]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">on_step_complete</a>() -> Optional[Callable]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">on_step_error</a>() -> Optional[Callable]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">on_step_start</a>() -> Optional[Callable]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">on_workflow_complete</a>() -> Optional[Callable]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">on_workflow_start</a>() -> Optional[Callable]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">planning_llm</a>() -> Optional[str]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">reasoning</a>() -> bool</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">run</a>(input: str = '', llm: Optional[str] = None, verbose: bool = False, stream: bool = None) -> Dict[str, Any]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">start</a>(input: str = '', **kwargs) -> Dict[str, Any]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">stream</a>() -> bool</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">to_dict</a>() -> Dict[str, Any]</code>
* <code title="class Workflow">Workflow.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">verbose</a>() -> bool</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">async_execution</a>() -> bool</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">branch_condition</a>() -> Optional[Dict[str, List[str]]]</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">context_from</a>() -> Optional[List[str]]</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">evaluator</a>()</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">executor</a>()</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">max_retries</a>() -> int</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">next_steps</a>() -> Optional[List[str]]</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">on_error</a>() -> str</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">output_file</a>() -> Optional[str]</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">output_json</a>() -> Optional[Any]</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">output_pydantic</a>() -> Optional[Any]</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">output_variable</a>() -> Optional[str]</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">quality_check</a>() -> bool</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">rerun</a>() -> bool</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">retain_full_context</a>() -> bool</code>
* <code title="class WorkflowStep">WorkflowStep.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">to_dict</a>() -> Dict[str, Any]</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">loop</a>(step: Any, over: Optional[str] = None, from_csv: Optional[str] = None, from_file: Optional[str] = None, var_name: str = 'item') -> Loop</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">parallel</a>(steps: List) -> Parallel</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">repeat</a>(step: Any, until: Optional[Callable[[WorkflowContext], bool]] = None, max_iterations: int = 10) -> Repeat</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/workflows/workflows.py">route</a>(routes: Dict[str, List], default: Optional[List] = None) -> Route</code>
# DB
Types:
```python
from praisonaiagents import db
```
# Memory
Types:
```python
from praisonaiagents import Memory
```
Methods:
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">build_context_for_task</a>(task_descr: str, user_id: Optional[str] = None, additional: str = '', max_items: int = 3, include_in_output: Optional[bool] = None) -> str</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">calculate_quality_metrics</a>(output: str, expected_output: str, llm: Optional[str] = None, custom_prompt: Optional[str] = None) -> Dict[str, float]</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">compute_quality_score</a>(completeness: float, relevance: float, clarity: float, accuracy: float, weights: Dict[str, float] = None) -> float</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">finalize_task_output</a>(content: str, agent_name: str, quality_score: float, threshold: float = 0.7, metrics: Dict[str, Any] = None, task_id: str = None)</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">get_all_memories</a>() -> List[Dict[str, Any]]</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">get_learn_context</a>() -> str</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">learn</a>()</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">reset_all</a>()</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">reset_entity_only</a>()</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">reset_long_term</a>()</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">reset_short_term</a>()</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">reset_user_memory</a>()</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">search</a>(query: str, user_id: Optional[str] = None, agent_id: Optional[str] = None, run_id: Optional[str] = None, limit: int = 5, rerank: bool = False, **kwargs) -> List[Dict[str, Any]]</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">search_entity</a>(query: str, limit: int = 5) -> List[Dict[str, Any]]</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">search_long_term</a>(query: str, limit: int = 5, relevance_cutoff: float = 0.0, min_quality: float = 0.0, rerank: bool = False, **kwargs) -> List[Dict[str, Any]]</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">search_short_term</a>(query: str, limit: int = 5, min_quality: float = 0.0, relevance_cutoff: float = 0.0, rerank: bool = False, **kwargs) -> List[Dict[str, Any]]</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">search_user_memory</a>(user_id: str, query: str, limit: int = 5, rerank: bool = False, **kwargs) -> List[Dict[str, Any]]</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">search_with_quality</a>(query: str, min_quality: float = 0.0, memory_type: Literal['short', 'long'] = 'long', limit: int = 5) -> List[Dict[str, Any]]</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">store_entity</a>(name: str, type_: str, desc: str, relations: str)</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">store_long_term</a>(text: str, metadata: Dict[str, Any] = None, completeness: float = None, relevance: float = None, clarity: float = None, accuracy: float = None, weights: Dict[str, float] = None, evaluator_quality: float = None)</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">store_quality</a>(text: str, quality_score: float, task_id: Optional[str] = None, iteration: Optional[int] = None, metrics: Optional[Dict[str, float]] = None, memory_type: Literal['short', 'long'] = 'long') -> None</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">store_short_term</a>(text: str, metadata: Dict[str, Any] = None, completeness: float = None, relevance: float = None, clarity: float = None, accuracy: float = None, weights: Dict[str, float] = None, evaluator_quality: float = None)</code>
* <code title="class Memory">Memory.<a href="./src/praisonai-agents/praisonaiagents/memory/memory.py">store_user_memory</a>(user_id: str, text: str, extra: Dict[str, Any] = None)</code>
# Knowledge
Types:
```python
from praisonaiagents import Chunking, Knowledge
```
Methods:
* <code title="class Chunking">Chunking.<a href="./src/praisonai-agents/praisonaiagents/knowledge/chunking.py">SUPPORTED_CHUNKERS</a>() -> Dict[str, Any]</code>
* <code title="class Chunking">Chunking.<a href="./src/praisonai-agents/praisonaiagents/knowledge/chunking.py">__call__</a>(text: Union[str, List[str]], **kwargs) -> Union[List[Any], List[List[Any]]]</code>
* <code title="class Chunking">Chunking.<a href="./src/praisonai-agents/praisonaiagents/knowledge/chunking.py">chunk</a>(text: Union[str, List[str]], **kwargs) -> Union[List[Any], List[List[Any]]]</code>
* <code title="class Chunking">Chunking.<a href="./src/praisonai-agents/praisonaiagents/knowledge/chunking.py">chunker</a>()</code>
* <code title="class Chunking">Chunking.<a href="./src/praisonai-agents/praisonaiagents/knowledge/chunking.py">embedding_model</a>()</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">add</a>(file_path, user_id = None, agent_id = None, run_id = None, metadata = None)</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">chunker</a>()</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">config</a>()</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">delete</a>(memory_id)</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">delete_all</a>(user_id = None, agent_id = None, run_id = None)</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">get</a>(memory_id)</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">get_all</a>(user_id = None, agent_id = None, run_id = None)</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">get_corpus_stats</a>()</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">history</a>(memory_id)</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">index</a>(path: str, incremental: bool = True, force: bool = False, include_glob: list = None, exclude_glob: list = None, user_id: str = None, agent_id: str = None, run_id: str = None)</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">markdown</a>()</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">memory</a>()</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">normalize_content</a>(content)</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">reset</a>()</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">search</a>(query, user_id = None, agent_id = None, run_id = None, rerank = None, **kwargs)</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">store</a>(content, user_id = None, agent_id = None, run_id = None, metadata = None)</code>
* <code title="class Knowledge">Knowledge.<a href="./src/praisonai-agents/praisonaiagents/knowledge/knowledge.py">update</a>(memory_id, data)</code>
# RAG
Types:
```python
from praisonaiagents import RAG, RAGCitation, RAGConfig, RAGResult
```
Methods:
* <code title="class RAG">RAG.<a href="./src/praisonai-agents/praisonaiagents/rag/pipeline.py">aquery</a>(question: str, user_id: Optional[str] = None, agent_id: Optional[str] = None, run_id: Optional[str] = None, **kwargs) -> RAGResult</code>
* <code title="class RAG">RAG.<a href="./src/praisonai-agents/praisonaiagents/rag/pipeline.py">aretrieve</a>(query: str, **kwargs) -> ContextPack</code>
* <code title="class RAG">RAG.<a href="./src/praisonai-agents/praisonaiagents/rag/pipeline.py">astream</a>(question: str, user_id: Optional[str] = None, agent_id: Optional[str] = None, run_id: Optional[str] = None, **kwargs) -> AsyncIterator[str]</code>
* <code title="class RAG">RAG.<a href="./src/praisonai-agents/praisonaiagents/rag/pipeline.py">get_citations</a>(question: str, user_id: Optional[str] = None, agent_id: Optional[str] = None, run_id: Optional[str] = None, **kwargs) -> List[Citation]</code>
* <code title="class RAG">RAG.<a href="./src/praisonai-agents/praisonaiagents/rag/pipeline.py">llm</a>()</code>
* <code title="class RAG">RAG.<a href="./src/praisonai-agents/praisonaiagents/rag/pipeline.py">query</a>(question: str, user_id: Optional[str] = None, agent_id: Optional[str] = None, run_id: Optional[str] = None, **kwargs) -> RAGResult</code>
* <code title="class RAG">RAG.<a href="./src/praisonai-agents/praisonaiagents/rag/pipeline.py">retrieve</a>(query: str, **kwargs) -> ContextPack</code>
* <code title="class RAG">RAG.<a href="./src/praisonai-agents/praisonaiagents/rag/pipeline.py">stream</a>(question: str, user_id: Optional[str] = None, agent_id: Optional[str] = None, run_id: Optional[str] = None, **kwargs) -> Iterator[str]</code>
* <code title="class RAGCitation">RAGCitation.<a href="./src/praisonai-agents/praisonaiagents/rag/models.py">from_dict</a>(data: Dict[str, Any]) -> 'Citation'</code>
* <code title="class RAGCitation">RAGCitation.<a href="./src/praisonai-agents/praisonaiagents/rag/models.py">to_dict</a>() -> Dict[str, Any]</code>
* <code title="class RAGConfig">RAGConfig.<a href="./src/praisonai-agents/praisonaiagents/rag/models.py">from_dict</a>(data: Dict[str, Any]) -> 'RAGConfig'</code>
* <code title="class RAGConfig">RAGConfig.<a href="./src/praisonai-agents/praisonaiagents/rag/models.py">to_dict</a>() -> Dict[str, Any]</code>
* <code title="class RAGResult">RAGResult.<a href="./src/praisonai-agents/praisonaiagents/rag/models.py">format_answer_with_citations</a>() -> str</code>
* <code title="class RAGResult">RAGResult.<a href="./src/praisonai-agents/praisonaiagents/rag/models.py">from_dict</a>(data: Dict[str, Any]) -> 'RAGResult'</code>
* <code title="class RAGResult">RAGResult.<a href="./src/praisonai-agents/praisonaiagents/rag/models.py">has_citations</a>() -> bool</code>
* <code title="class RAGResult">RAGResult.<a href="./src/praisonai-agents/praisonaiagents/rag/models.py">to_dict</a>() -> Dict[str, Any]</code>
# Handoff
Types:
```python
from praisonaiagents import Handoff, RECOMMENDED_PROMPT_PREFIX, handoff, handoff_filters, prompt_with_handoff_instructions
```
Methods:
* <code title="class Handoff">Handoff.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">default_tool_description</a>() -> str</code>
* <code title="class Handoff">Handoff.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">default_tool_name</a>() -> str</code>
* <code title="class Handoff">Handoff.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">execute_async</a>(source_agent: 'Agent', prompt: str, context: Optional[Dict[str, Any]] = None) -> HandoffResult</code>
* <code title="class Handoff">Handoff.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">execute_programmatic</a>(source_agent: 'Agent', prompt: str, context: Optional[Dict[str, Any]] = None) -> HandoffResult</code>
* <code title="class Handoff">Handoff.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">to_tool_function</a>(source_agent: 'Agent') -> Callable</code>
* <code title="class Handoff">Handoff.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">tool_description</a>() -> str</code>
* <code title="class Handoff">Handoff.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">tool_name</a>() -> str</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">handoff</a>(agent: 'Agent', tool_name_override: Optional[str] = None, tool_description_override: Optional[str] = None, on_handoff: Optional[Callable] = None, input_type: Optional[type] = None, input_filter: Optional[Callable[[HandoffInputData], HandoffInputData]] = None, config: Optional[HandoffConfig] = None, context_policy: Optional[str] = None, timeout_seconds: Optional[float] = None, max_concurrent: Optional[int] = None, detect_cycles: Optional[bool] = None, max_depth: Optional[int] = None) -> Handoff</code>
* <code title="class handoff_filters">handoff_filters.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">keep_last_n_messages</a>(n: int) -> Callable[[HandoffInputData], HandoffInputData]</code>
* <code title="class handoff_filters">handoff_filters.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">remove_all_tools</a>(data: HandoffInputData) -> HandoffInputData</code>
* <code title="class handoff_filters">handoff_filters.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">remove_system_messages</a>(data: HandoffInputData) -> HandoffInputData</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/agent/handoff.py">prompt_with_handoff_instructions</a>(base_prompt: str, agent: 'Agent') -> str</code>
# Guardrails
Types:
```python
from praisonaiagents import LLMGuardrail
```
Methods:
* <code title="class LLMGuardrail">LLMGuardrail.<a href="./src/praisonai-agents/praisonaiagents/guardrails/llm_guardrail.py">__call__</a>(task_output: TaskOutput) -> Tuple[bool, Union[str, TaskOutput]]</code>
# Skills
Types:
```python
from praisonaiagents import SkillLoader, SkillManager, SkillMetadata, SkillProperties
```
Methods:
* <code title="class SkillLoader">SkillLoader.<a href="./src/praisonai-agents/praisonaiagents/skills/loader.py">activate</a>(skill: LoadedSkill) -> bool</code>
* <code title="class SkillLoader">SkillLoader.<a href="./src/praisonai-agents/praisonaiagents/skills/loader.py">load</a>(skill_path: str, activate: bool = False) -> Optional[LoadedSkill]</code>
* <code title="class SkillLoader">SkillLoader.<a href="./src/praisonai-agents/praisonaiagents/skills/loader.py">load_all_resources</a>(skill: LoadedSkill) -> None</code>
* <code title="class SkillLoader">SkillLoader.<a href="./src/praisonai-agents/praisonaiagents/skills/loader.py">load_assets</a>(skill: LoadedSkill) -> dict</code>
* <code title="class SkillLoader">SkillLoader.<a href="./src/praisonai-agents/praisonaiagents/skills/loader.py">load_metadata</a>(skill_path: str) -> Optional[LoadedSkill]</code>
* <code title="class SkillLoader">SkillLoader.<a href="./src/praisonai-agents/praisonaiagents/skills/loader.py">load_references</a>(skill: LoadedSkill) -> dict</code>
* <code title="class SkillLoader">SkillLoader.<a href="./src/praisonai-agents/praisonaiagents/skills/loader.py">load_scripts</a>(skill: LoadedSkill) -> dict</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">activate</a>(skill: LoadedSkill) -> bool</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">activate_by_name</a>(name: str) -> bool</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">add_skill</a>(skill_path: str) -> Optional[LoadedSkill]</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">clear</a>() -> None</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">discover</a>(skill_dirs: Optional[List[str]] = None, include_defaults: bool = True) -> int</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">get_available_skills</a>() -> List[SkillMetadata]</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">get_instructions</a>(name: str) -> Optional[str]</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">get_skill</a>(name: str) -> Optional[LoadedSkill]</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">load_resources</a>(name: str) -> bool</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">skill_names</a>() -> List[str]</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">skills</a>() -> List[LoadedSkill]</code>
* <code title="class SkillManager">SkillManager.<a href="./src/praisonai-agents/praisonaiagents/skills/manager.py">to_prompt</a>() -> str</code>
* <code title="class SkillMetadata">SkillMetadata.<a href="./src/praisonai-agents/praisonaiagents/skills/models.py">from_properties</a>(props: SkillProperties) -> 'SkillMetadata'</code>
* <code title="class SkillProperties">SkillProperties.<a href="./src/praisonai-agents/praisonaiagents/skills/models.py">to_dict</a>() -> dict</code>
# Session
Types:
```python
from praisonaiagents import Session
```
Methods:
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">Agent</a>(name: str, role: str = 'Assistant', instructions: Optional[str] = None, tools: Optional[List[Any]] = None, memory: bool = True, knowledge: Optional[List[str]] = None, **kwargs) -> 'Agent'</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">add_knowledge</a>(source: str) -> None</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">add_memory</a>(text: str, memory_type: str = 'long', **metadata) -> None</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">chat</a>(message: str, **kwargs) -> str</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">clear_memory</a>(memory_type: str = 'all') -> None</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">create_agent</a>(*args, **kwargs) -> 'Agent'</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">get_context</a>(query: str, max_items: int = 3) -> str</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">get_state</a>(key: str, default: Any = None) -> Any</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">increment_state</a>(key: str, increment: int = 1, default: int = 0) -> None</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">knowledge</a>() -> 'Knowledge'</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">memory</a>() -> 'Memory'</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">restore_state</a>() -> Dict[str, Any]</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">save_state</a>(state_data: Dict[str, Any]) -> None</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">search_knowledge</a>(query: str, limit: int = 5) -> List[Dict[str, Any]]</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">search_memory</a>(query: str, memory_type: str = 'long', limit: int = 5) -> List[Dict[str, Any]]</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">send_message</a>(message: str, **kwargs) -> str</code>
* <code title="class Session">Session.<a href="./src/praisonai-agents/praisonaiagents/session/api.py">set_state</a>(key: str, value: Any) -> None</code>
# Telemetry
Types:
```python
from praisonaiagents import get_telemetry
```
Methods:
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/telemetry/__init__.py">get_telemetry</a>() -> 'MinimalTelemetry'</code>
# Observability
Types:
```python
from praisonaiagents import FlowDisplay, obs, track_workflow
```
Methods:
* <code title="class FlowDisplay">FlowDisplay.<a href="./src/praisonai-agents/praisonaiagents/flow_display.py">display</a>()</code>
* <code title="class FlowDisplay">FlowDisplay.<a href="./src/praisonai-agents/praisonaiagents/flow_display.py">start</a>()</code>
* <code title="class FlowDisplay">FlowDisplay.<a href="./src/praisonai-agents/praisonaiagents/flow_display.py">stop</a>()</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/flow_display.py">track_workflow</a>()</code>
# Context
Types:
```python
from praisonaiagents import ContextManager, ManagerConfig
```
Methods:
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">capture_llm_boundary</a>(messages: List[Dict[str, Any]], tools: List[Dict[str, Any]]) -> SnapshotHookData</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">estimate_tokens</a>(text: str, validate: bool = False) -> Tuple[int, Optional[EstimationMetrics]]</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">get_history</a>() -> List[Dict[str, Any]]</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">get_last_snapshot_hook</a>() -> Optional[SnapshotHookData]</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">get_resolved_config</a>() -> Dict[str, Any]</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">get_stats</a>() -> Dict[str, Any]</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">get_tool_budget</a>(tool_name: str) -> int</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">process</a>(messages: List[Dict[str, Any]], system_prompt: str = '', tools: Optional[List[Dict[str, Any]]] = None, trigger: Literal['turn', 'tool_call', 'manual', 'overflow'] = 'turn') -> Dict[str, Any]</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">register_snapshot_callback</a>(callback: Callable[[SnapshotHookData], None]) -> None</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">reset</a>() -> None</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">set_tool_budget</a>(tool_name: str, max_tokens: int, protected: bool = False) -> None</code>
* <code title="class ContextManager">ContextManager.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">truncate_tool_output</a>(tool_name: str, output: str) -> str</code>
* <code title="class ManagerConfig">ManagerConfig.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">from_env</a>() -> 'ManagerConfig'</code>
* <code title="class ManagerConfig">ManagerConfig.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">merge</a>(**overrides) -> 'ManagerConfig'</code>
* <code title="class ManagerConfig">ManagerConfig.<a href="./src/praisonai-agents/praisonaiagents/context/manager.py">to_dict</a>() -> Dict[str, Any]</code>
# Display
Types:
```python
from praisonaiagents import async_display_callbacks, clean_triple_backticks, display_error, display_generating, display_instruction, display_interaction, display_self_reflection, display_tool_call, error_logs, register_display_callback, sync_display_callbacks
```
Methods:
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/main.py">clean_triple_backticks</a>(text: str) -> str</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/main.py">display_error</a>(message: str, console = None)</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/main.py">display_generating</a>(content: str = '', start_time: Optional[float] = None)</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/main.py">display_instruction</a>(message: str, console = None, agent_name: str = None, agent_role: str = None, agent_tools: List[str] = None)</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/main.py">display_interaction</a>(message, response, markdown = True, generation_time = None, console = None, agent_name = None, agent_role = None, agent_tools = None, task_name = None, task_description = None, task_id = None)</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/main.py">display_self_reflection</a>(message: str, console = None)</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/main.py">display_tool_call</a>(message: str, console = None, tool_name: str = None, tool_input: dict = None, tool_output: str = None)</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/main.py">register_display_callback</a>(display_type: str, callback_fn, is_async: bool = False)</code>
# Other
Types:
```python
from praisonaiagents import AutoRagConfig, Citation, CodeExecutionStep, DeepResearchResponse, ExpandResult, ExpandStrategy, FileSearchCall, MCPCall, Provider, RagRetrievalPolicy, ReasoningStep, RewriteResult, RewriteStrategy, Task, WebSearchCall, warmup
from praisonaiagents import Task
```
Methods:
* <code title="class AutoRagConfig">AutoRagConfig.<a href="./src/praisonai-agents/praisonaiagents/agents/auto_rag_agent.py">from_dict</a>(data: Dict[str, Any]) -> 'AutoRagConfig'</code>
* <code title="class AutoRagConfig">AutoRagConfig.<a href="./src/praisonai-agents/praisonaiagents/agents/auto_rag_agent.py">to_dict</a>() -> Dict[str, Any]</code>
* <code title="class Citation">Citation.<a href="./src/praisonai-agents/praisonaiagents/rag/models.py">from_dict</a>(data: Dict[str, Any]) -> 'Citation'</code>
* <code title="class Citation">Citation.<a href="./src/praisonai-agents/praisonaiagents/rag/models.py">to_dict</a>() -> Dict[str, Any]</code>
* <code title="class DeepResearchResponse">DeepResearchResponse.<a href="./src/praisonai-agents/praisonaiagents/agent/deep_research_agent.py">get_all_sources</a>() -> List[Dict[str, str]]</code>
* <code title="class DeepResearchResponse">DeepResearchResponse.<a href="./src/praisonai-agents/praisonaiagents/agent/deep_research_agent.py">get_citation_text</a>(citation: Citation) -> str</code>
* <code title="class RewriteResult">RewriteResult.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">all_queries</a>() -> List[str]</code>
* <code title="class RewriteResult">RewriteResult.<a href="./src/praisonai-agents/praisonaiagents/agent/query_rewriter_agent.py">primary_query</a>() -> str</code>
* <code title="class Task">Task.<a href="./src/praisonai-agents/praisonaiagents/task/task.py">execute_callback</a>(task_output: TaskOutput) -> None</code>
* <code title="class Task">Task.<a href="./src/praisonai-agents/praisonaiagents/task/task.py">execute_callback_sync</a>(task_output: TaskOutput) -> None</code>
* <code title="class Task">Task.<a href="./src/praisonai-agents/praisonaiagents/task/task.py">initialize_memory</a>()</code>
* <code title="class Task">Task.<a href="./src/praisonai-agents/praisonaiagents/task/task.py">store_in_memory</a>(content: str, agent_name: str = None, task_id: str = None)</code>
* <code title="function">praisonaiagents.<a href="./src/praisonai-agents/praisonaiagents/__init__.py">warmup</a>(include_litellm: bool = False, include_openai: bool = True) -> dict</code>
# Wrapper (praisonai)
+1 -1
View File
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
praisonai_tools \
"praisonai>=3.8.2" \
"praisonai>=3.8.8" \
"praisonai[chat]" \
"embedchain[github,youtube]"
+1 -1
View File
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
praisonai_tools \
"praisonai>=3.8.2" \
"praisonai>=3.8.8" \
"praisonai[ui]" \
"praisonai[chat]" \
"praisonai[realtime]" \
+1 -1
View File
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
# Install Python packages (using latest versions)
RUN pip install --no-cache-dir \
praisonai_tools \
"praisonai>=3.8.2" \
"praisonai>=3.8.8" \
"praisonai[ui]" \
"praisonai[crewai]"
@@ -22,7 +22,7 @@ agents: # Canonical: use 'agents' instead of 'roles'
verbose: true
allow_delegation: false
llm:
model: "gpt-5-nano"
model: "gpt-4o-mini"
temperature: 0.3
tools:
- "InternetSearchTool"
@@ -76,7 +76,7 @@ agents: # Canonical: use 'agents' instead of 'roles'
verbose: true
allow_delegation: false
llm:
model: "gpt-5-nano"
model: "gpt-4o-mini"
temperature: 0.3
tools:
- "InternetSearchTool"
@@ -130,7 +130,7 @@ agents: # Canonical: use 'agents' instead of 'roles'
verbose: true
allow_delegation: false
llm:
model: "gpt-5-nano"
model: "gpt-4o-mini"
temperature: 0.3
tools:
- "InternetSearchTool"
@@ -185,7 +185,7 @@ agents: # Canonical: use 'agents' instead of 'roles'
verbose: true
allow_delegation: false
llm:
model: "gpt-5-nano"
model: "gpt-4o-mini"
temperature: 0.4
tools:
- "InternetSearchTool"
@@ -239,7 +239,7 @@ agents: # Canonical: use 'agents' instead of 'roles'
verbose: true
allow_delegation: false
llm:
model: "gpt-5-nano"
model: "gpt-4o-mini"
temperature: 0.3
tools:
- "InternetSearchTool"
@@ -299,7 +299,7 @@ agents: # Canonical: use 'agents' instead of 'roles'
verbose: true
allow_delegation: false
llm:
model: "gpt-5-nano"
model: "gpt-4o-mini"
temperature: 0.3
tasks:
report_synthesis:
@@ -46,7 +46,7 @@ agent = RouterAgent(
name="Smart Assistant",
role="Adaptive AI Assistant",
goal="Complete tasks using the most appropriate model",
models=["gpt-5-nano", "gpt-5-nano", "claude-3-5-sonnet-20241022"],
models=["gpt-4o-mini", "gpt-4o-mini", "claude-3-5-sonnet-20241022"],
routing_strategy="auto" # Automatic model selection
)
@@ -90,7 +90,7 @@ analyzer = RouterAgent(
goal="Analyze data efficiently",
models={
"gemini/gemini-1.5-flash": {},
"gpt-5-nano": {},
"gpt-4o-mini": {},
"claude-3-haiku-20240307": {}
},
model_router=router,
@@ -207,7 +207,7 @@ for i, agent in enumerate(auto.agents):
name=agent.name,
role=agent.role,
goal=agent.goal,
models=["gpt-5-nano", "gpt-5-nano", "claude-3-5-sonnet"],
models=["gpt-4o-mini", "gpt-4o-mini", "claude-3-5-sonnet"],
routing_strategy="auto"
)
+1 -1
View File
@@ -97,7 +97,7 @@ researcher = Agent(
name="Researcher",
role="Information Researcher",
goal="Store information with semantic understanding",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create task
+1 -1
View File
@@ -17,7 +17,7 @@ def my_function():
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
with track_api_call("agent_request"):
+1 -1
View File
@@ -13,7 +13,7 @@ agent = Agent(
role="Assistant",
goal="Help users",
backstory="You are helpful.",
llm="gpt-5-nano",
llm="gpt-4o-mini",
metrics=True # 🎯 That's it!
)
@@ -177,7 +177,7 @@ Set your API keys:
```bash
export OPENAI_API_KEY="your-api-key"
export OPENAI_MODEL_NAME="gpt-5-nano"
export OPENAI_MODEL_NAME="gpt-4o-mini"
```
## 📝 Customization
@@ -38,7 +38,7 @@ def main():
# Create agent
agent = Agent(
instructions="You are a helpful assistant that explains scientific concepts simply",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Track the API call performance
@@ -13,8 +13,8 @@ def main():
role="Research Specialist",
goal="Find information about a topic",
backstory="You are an expert researcher who finds comprehensive information.",
verbose=True,
llm="gpt-5-nano", # Use a cost-effective model for examples
output="verbose",
llm="gpt-4o-mini", # Use a cost-effective model for examples
metrics=True # 🎯 SIMPLIFIED: Just add this parameter!
)
@@ -29,7 +29,7 @@ def main():
agents = Agents(
agents=[research_agent],
tasks=[research_task],
verbose=True
output="verbose"
)
print("🚀 Running agent task...")
@@ -54,7 +54,7 @@ def create_agents():
goal="Gather comprehensive information on renewable energy",
backstory="Expert researcher with deep knowledge of energy sector",
instructions="You are a thorough researcher. Provide detailed, fact-based information.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
analyst = Agent(
@@ -63,7 +63,7 @@ def create_agents():
goal="Analyze trends and patterns in renewable energy data",
backstory="Experienced data analyst specializing in energy markets",
instructions="You are an analytical thinker. Focus on trends, patterns, and insights.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
writer = Agent(
@@ -72,7 +72,7 @@ def create_agents():
goal="Create clear, compelling reports",
backstory="Professional technical writer with expertise in energy sector",
instructions="You are a skilled writer. Create clear, well-structured reports.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
return researcher, analyst, writer
@@ -104,8 +104,7 @@ def main():
workflow = Agents(
agents=[researcher, analyst, writer],
tasks=[research_task, analysis_task, report_task],
process="sequential",
verbose=True
process="sequential"
)
result = workflow.start()
@@ -11,7 +11,7 @@ Shows how to monitor agent performance when using external tools.
"""
from praisonaiagents import Agent
from praisonaiagents.tools import duckduckgo, wikipedia
from praisonaiagents.tools import duckduckgo, wikipedia_tools
from praisonaiagents.telemetry import (
monitor_function, track_api_call, get_api_stats,
get_slowest_functions, performance_monitor
@@ -48,8 +48,8 @@ def main():
instructions="""You are a research assistant that helps find information.
Use the available tools to search for information and provide comprehensive answers.
Be thorough in your research and cite your sources.""",
llm="gpt-5-nano",
tools=[duckduckgo, wikipedia] # Add search tools
llm="gpt-4o-mini",
tools=[duckduckgo, wikipedia_tools] # Add search tools
)
# Test queries to demonstrate tool performance monitoring
@@ -97,7 +97,9 @@ def main():
# Slowest functions analysis
print("\n🐌 Slowest Functions:")
slowest = get_slowest_functions()
for func_name, avg_time in slowest:
for item in slowest[:5]:
func_name = item.get('function', 'unknown')
avg_time = item.get('average_time', 0)
print(f" {func_name}: {avg_time:.3f}s average")
# Real-time performance data
@@ -54,7 +54,7 @@ async def run_async_agent(query: str):
# Create agent
agent = Agent(
instructions="You are an efficient AI assistant that processes requests quickly",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Track the agent execution
@@ -60,7 +60,7 @@ def run_robust_agent(query: str, with_error_simulation: bool = True):
instructions="""You are a resilient AI assistant.
Even when facing challenges, you provide helpful responses.
If you encounter errors, acknowledge them and offer alternatives.""",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
try:
@@ -65,7 +65,7 @@ def run_stateful_agent(query: str, session_id: str, conversation_turn: int):
instructions="""You are a memory-enabled AI assistant. You can remember
previous conversations and build on past interactions. Use your memory
to provide personalized and contextual responses.""",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Pre-processing: retrieve relevant memories
@@ -165,7 +165,9 @@ def main():
# Slowest operations
print("\n🐌 Slowest Memory Operations:")
slowest = get_slowest_functions()
for func_name, avg_time in slowest[:5]: # Top 5 slowest
for item in slowest[:5]: # Top 5 slowest
func_name = item.get('function', 'unknown')
avg_time = item.get('average_time', 0)
print(f" {func_name}: {avg_time:.3f}s average")
# Memory operation breakdown
@@ -77,7 +77,7 @@ def run_hierarchical_workflow():
backstory="Experienced project manager with expertise in team coordination",
instructions="""You are a project manager. Break down complex projects into tasks,
assign them to appropriate team members, and coordinate the overall effort.""",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create worker agents
@@ -87,7 +87,7 @@ def run_hierarchical_workflow():
goal="Conduct thorough research on assigned topics",
backstory="Expert researcher with deep analytical skills",
instructions="You are a research specialist. Provide detailed, factual information.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
analysis_worker = Agent(
@@ -96,7 +96,7 @@ def run_hierarchical_workflow():
goal="Analyze data and identify patterns and insights",
backstory="Experienced data analyst with strong analytical thinking",
instructions="You are a data analyst. Focus on patterns, trends, and insights.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
writing_worker = Agent(
@@ -105,7 +105,7 @@ def run_hierarchical_workflow():
goal="Create clear, well-structured documentation and reports",
backstory="Professional writer specializing in technical content",
instructions="You are a technical writer. Create clear, comprehensive reports.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Project tasks
@@ -180,7 +180,7 @@ def run_agent_with_custom_tools():
instructions="""You are a technical assistant with access to various tools.
Use the appropriate tools to help with data processing, API calls, database queries,
and file operations. Always explain what tools you're using and why.""",
llm="gpt-5-nano",
llm="gpt-4o-mini",
tools=[process_data, call_external_api, query_database, file_operation]
)
@@ -263,7 +263,7 @@ def main():
# Slowest operations
print("\n🐌 Slowest Tool Operations:")
slowest = get_slowest_functions()
tool_slowest = [(name, time) for name, time in slowest if 'tool' in name.lower()]
tool_slowest = [(item.get('function', 'unknown'), item.get('average_time', 0)) for item in slowest if 'tool' in item.get('function', '').lower()]
for tool_name, avg_time in tool_slowest[:3]:
print(f" {tool_name}: {avg_time:.3f}s")
@@ -60,7 +60,7 @@ def get_real_time_agent_response(query: str, response_id: int):
# Create a lightweight agent for streaming
agent = Agent(
instructions="You are a real-time assistant. Provide quick, helpful responses.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
with track_api_call(f"streaming_response_{response_id}"):
@@ -42,19 +42,19 @@ def collect_comprehensive_data():
agents = {
'quick_agent': Agent(
instructions="You are a quick-response agent. Provide concise answers.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
),
'analytical_agent': Agent(
instructions="You are an analytical agent. Provide detailed analysis.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
),
'research_agent': Agent(
instructions="You are a research agent. Provide comprehensive information.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
),
'creative_agent': Agent(
instructions="You are a creative agent. Provide imaginative responses.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
}
@@ -98,19 +98,19 @@ def simulate_complex_workflow():
planner = Agent(
name="planner",
instructions="You are a project planner. Break down tasks and plan execution.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
executor = Agent(
name="executor",
instructions="You are a task executor. Complete assigned tasks efficiently.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
reviewer = Agent(
name="reviewer",
instructions="You are a quality reviewer. Review and improve work.",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create workflow tasks
@@ -302,13 +302,17 @@ def display_dashboard(dashboard_data, benchmark_results):
perf_data = dashboard_data['performance_data']
print(" Fastest Functions:")
fastest_functions = sorted(perf_data['slowest_functions'], key=lambda x: x[1])[:3]
for name, time in fastest_functions:
print(f" {name}: {time:.3f}s")
fastest_functions = sorted(perf_data['slowest_functions'], key=lambda x: x.get('average_time', float('inf')))[:3]
for item in fastest_functions:
name = item.get('function', 'unknown')
time_val = item.get('average_time', 0)
print(f" {name}: {time_val:.3f}s")
print(" Slowest Functions:")
for name, time in perf_data['slowest_functions'][:3]:
print(f" {name}: {time:.3f}s")
for item in perf_data['slowest_functions'][:3]:
name = item.get('function', 'unknown')
time_val = item.get('average_time', 0)
print(f" {name}: {time_val:.3f}s")
# Benchmark Results
print(f"\n⚡ BENCHMARK RESULTS")
+1 -1
View File
@@ -111,7 +111,7 @@ agent = Agent(
role="Agent Role",
goal="Agent Goal",
backstory="Agent Background",
llm="gpt-5-nano", # or other LLM
llm="gpt-4o-mini", # or other LLM
self_reflect=True, # Enable self-reflection
min_reflect=1, # Minimum reflection iterations
max_reflect=3, # Maximum reflection iterations
@@ -1,98 +1,75 @@
#!/usr/bin/env python3
"""
Agent-level guardrails example.
This example demonstrates how to use guardrails at the Agent level,
This example demonstrates how to use guardrails at the Agent level
which will apply to all tasks executed by that agent.
"""
from typing import Tuple, Any
from praisonaiagents import Agent, TaskOutput
def validate_content_length(task_output: TaskOutput) -> Tuple[bool, Any]:
"""
Validate that task output content meets minimum length requirement.
Args:
task_output: The task output to validate
Returns:
Tuple of (success, result_or_error_message)
"""
if len(task_output.raw) < 50:
return False, "Content too short - must be at least 50 characters"
return True, task_output
def validate_professional_tone(task_output: TaskOutput) -> Tuple[bool, Any]:
"""
Validate that the content has a professional tone.
Args:
task_output: The task output to validate
Returns:
Tuple of (success, result_or_error_message)
"""
content = task_output.raw.lower()
unprofessional_words = ['yo', 'dude', 'awesome', 'cool', 'lol']
for word in unprofessional_words:
if word in content:
return False, f"Content contains unprofessional word: '{word}'"
return True, task_output
def main():
"""Demonstrate Agent-level guardrails with function-based and LLM-based validation."""
print("=== Agent Guardrail Examples ===\n")
# Example 1: Function-based guardrail
print("1. Function-based guardrail (content length validation):")
agent1 = Agent(
name="ContentWriter",
instructions="You are a professional content writer who creates detailed responses",
guardrail=validate_content_length,
max_guardrail_retries=2
name="ContentWriter"
instructions="You are a professional content writer who creates detailed responses"
guardrails=validate_content_length
)
try:
result1 = agent1.start("Write a brief welcome message")
print(f"Result: {result1}\n")
except Exception as e:
print(f"Error: {e}\n")
# Example 2: LLM-based guardrail (string description)
print("2. LLM-based guardrail (professional tone validation):")
agent2 = Agent(
name="BusinessWriter",
instructions="You are a business communication expert",
guardrail="Ensure the content is professional, formal, and suitable for business communication. No casual language or slang.",
max_guardrail_retries=3
instructions="You are a business communication expert"
guardrails="Ensure the content is professional, formal, and suitable for business communication. No casual language or slang."
)
try:
result2 = agent2.start("Write a welcome message for new employees")
print(f"Result: {result2}\n")
except Exception as e:
print(f"Error: {e}\n")
# Example 3: Multiple agents with different guardrails
print("3. Professional tone function-based guardrail:")
agent3 = Agent(
name="ProfessionalWriter",
instructions="Write professional business content",
guardrail=validate_professional_tone,
max_guardrail_retries=2
name="ProfessionalWriter"
instructions="Write professional business content"
guardrails=validate_professional_tone
)
try:
result3 = agent3.start("Write a casual greeting message")
print(f"Result: {result3}\n")
except Exception as e:
print(f"Error: {e}\n")
print("=== Agent Guardrails Demonstration Complete ===")
if __name__ == "__main__":
main()
@@ -21,7 +21,7 @@ article_agent = Agent(
goal="Fetch the user's favorite morning article",
tools=[fetch_favorite_article],
llm="gemini/gemini-2.5-flash-lite-preview-06-17",
verbose=True
output="verbose"
)
news_agent = Agent(
@@ -30,7 +30,7 @@ news_agent = Agent(
goal="Search for trending news in Kenya",
tools=[search_trending_kenya],
llm="gemini/gemini-2.5-flash-lite-preview-06-17",
verbose=True
output="verbose"
)
twitter_agent = Agent(
@@ -39,7 +39,7 @@ twitter_agent = Agent(
goal="Fetch the latest Twitter feed",
tools=[fetch_twitter_feed],
llm="gemini/gemini-2.5-flash-lite-preview-06-17",
verbose=True
output="verbose"
)
aggregator = Agent(
@@ -47,7 +47,7 @@ aggregator = Agent(
role="Result Aggregator",
goal="Aggregate and summarize all results",
llm="gemini/gemini-2.5-flash-lite-preview-06-17",
verbose=True
output="verbose"
)
# Tasks for each agent
@@ -92,7 +92,7 @@ async def main():
agents=[article_agent, news_agent, twitter_agent, aggregator],
tasks=[article_task, news_task, twitter_task, aggregate_task],
process="workflow",
verbose=True
output="verbose"
)
results = await workflow.astart(dict_output=True)
+2 -2
View File
@@ -5,8 +5,8 @@ async def main():
agent = Agent(
instructions="You are a helpful assistant",
llm="gemini/gemini-1.5-flash-8b",
self_reflect=True,
verbose=True
reflection=True,
output="verbose"
)
# Use achat instead of start/chat for async operation
@@ -10,7 +10,7 @@ import os
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
llm_config = {
"model": "gpt-5-nano", # Changed from Gemini to gpt-5-nano for better tool support
"model": "gpt-4o-mini", # Changed from Gemini to gpt-5-nano for better tool support
"temperature": 0.7,
"response_format": {
"type": "text"
@@ -79,7 +79,7 @@ async def run_parallel_searches():
backstory="Expert in web search and information retrieval. You have access to the tavily_search tool to search the web.",
tools=[tavily_search],
llm=llm_config,
verbose=True
output="verbose"
)
# Create summary agent
+1 -1
View File
@@ -5,7 +5,7 @@ def get_weather(city: str) -> str:
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano",
llm="gpt-4o-mini",
tools=[get_weather]
)
+1 -2
View File
@@ -1,4 +1,3 @@
from praisonaiagents import Agent
agent = Agent(instructions="You are a helpful assistant")
result = agent.start("Why is the sky blue?")
print(result)
result = agent.start("Why is the sky blue?")
@@ -1,6 +1,6 @@
# PraisonAI Agents - Real Execution Benchmark
**Generated:** 2025-12-18 14:43:52
**Generated:** 2026-01-13 06:07:28
**Model:** gpt-4o-mini
**Iterations:** 3
**Prompt:** "What is 2+2? Reply with just the number."
@@ -9,18 +9,18 @@
| Framework | Method | Avg Time | Relative |
|-----------|--------|----------|----------|
| **PraisonAI** | `agent.start()` | **0.45s** | **1.00x (fastest)** |
| PraisonAI (LiteLLM) | `agent.start()` | 0.55s | 1.22x |
| CrewAI | `crew.kickoff()` | 0.58s | 1.28x |
| Agno | `agent.run()` | 0.92s | 2.05x |
| **PraisonAI (LiteLLM)** | `agent.start()` | **0.55s** | **1.00x (fastest)** |
| PraisonAI | `agent.start()` | 0.64s | 1.15x |
| CrewAI | `crew.kickoff()` | 0.95s | 1.71x |
| Agno | `agent.run()` | 1.05s | 1.90x |
## Package Versions
| Package | Version |
|---------|--------|
| PraisonAI | 0.1.5 |
| Agno | 2.3.14 |
| CrewAI | 1.6.1 |
| PraisonAI | 0.11.7 |
| Agno | 2.3.25 |
| CrewAI | 1.8.0 |
## How to Reproduce
@@ -1,6 +1,6 @@
# PraisonAI Agents - Real-World Execution Benchmark
**Generated:** 2025-12-18 14:33:49
**Generated:** 2026-01-13 06:05:09
**Model:** gpt-4o-mini
**Iterations:** 3 per test
@@ -8,60 +8,60 @@
| Test | PraisonAI (avg) | Agno (avg) | Difference |
|------|-----------------|------------|------------|
| Single Agent | 2.04s | 3.18s | PraisonAI 1.56x faster |
| 2 Agents | 2.49s | 20.49s | PraisonAI 8.21x faster |
| 3 Agents | 6.52s | 13.97s | PraisonAI 2.14x faster |
| Single Agent | 2.09s | 3.25s | PraisonAI 1.55x faster |
| 2 Agents | 2.50s | 9.73s | PraisonAI 3.89x faster |
| 3 Agents | 6.25s | 13.56s | PraisonAI 2.17x faster |
## Detailed Results
### praisonai_single
- Average: 2.04s
- Min: 1.95s
- Max: 2.19s
- Std Dev: 0.13s
- Times: ['2.19s', '1.95s', '2.00s']
- Average: 2.09s
- Min: 1.64s
- Max: 2.84s
- Std Dev: 0.66s
- Times: ['2.84s', '1.79s', '1.64s']
### agno_single
- Average: 3.18s
- Min: 3.00s
- Max: 3.51s
- Std Dev: 0.28s
- Times: ['3.51s', '3.00s', '3.04s']
- Average: 3.25s
- Min: 3.14s
- Max: 3.35s
- Std Dev: 0.10s
- Times: ['3.35s', '3.25s', '3.14s']
### praisonai_two_agents
- Average: 2.49s
- Min: 2.22s
- Max: 2.65s
- Std Dev: 0.24s
- Times: ['2.65s', '2.22s', '2.62s']
- Average: 2.50s
- Min: 2.38s
- Max: 2.75s
- Std Dev: 0.21s
- Times: ['2.38s', '2.75s', '2.38s']
### agno_two_agents
- Average: 20.49s
- Min: 9.96s
- Max: 35.05s
- Std Dev: 13.02s
- Times: ['16.46s', '9.96s', '35.05s']
- Average: 9.73s
- Min: 9.34s
- Max: 10.53s
- Std Dev: 0.69s
- Times: ['10.53s', '9.34s', '9.34s']
### praisonai_three_agents
- Average: 6.52s
- Min: 5.62s
- Max: 7.39s
- Std Dev: 0.88s
- Times: ['5.62s', '6.54s', '7.39s']
- Average: 6.25s
- Min: 5.86s
- Max: 6.80s
- Std Dev: 0.49s
- Times: ['6.80s', '6.09s', '5.86s']
### agno_three_agents
- Average: 13.97s
- Min: 11.69s
- Max: 15.32s
- Std Dev: 1.99s
- Times: ['14.91s', '11.69s', '15.32s']
- Average: 13.56s
- Min: 12.26s
- Max: 14.90s
- Std Dev: 1.32s
- Times: ['14.90s', '13.51s', '12.26s']
## Package Versions
| Package | Version |
|---------|--------|
| PraisonAI | 0.1.5 |
| Agno | 2.3.14 |
| PraisonAI | 0.11.7 |
| Agno | 2.3.25 |
## How to Reproduce
@@ -52,12 +52,11 @@ def benchmark_praisonai(model, iterations, prompt):
agent = Agent(
name="Calculator",
instructions="You are a helpful assistant. Be very brief.",
llm=model,
verbose=False
llm=model
)
start = time.perf_counter()
response = agent.start(prompt)
response = agent.start(prompt, output="silent")
elapsed = time.perf_counter() - start
times.append(elapsed)
@@ -80,12 +79,11 @@ def benchmark_praisonai_litellm(model, iterations, prompt):
agent = Agent(
name="Calculator",
instructions="You are a helpful assistant. Be very brief.",
llm=f"openai/{model}",
verbose=False
llm=f"openai/{model}"
)
start = time.perf_counter()
response = agent.start(prompt)
response = agent.start(prompt, output="silent")
elapsed = time.perf_counter() - start
times.append(elapsed)
@@ -103,12 +103,11 @@ def benchmark_praisonai_single(iterations: int = 3) -> ExecutionResult:
name="Assistant",
instructions="You are a helpful assistant. Be very brief.",
llm="gpt-4o-mini",
tools=[get_weather],
verbose=False
tools=[get_weather]
)
start = time.perf_counter()
response = agent.start("What's the weather in NYC? Reply in one sentence.")
response = agent.start("What's the weather in NYC? Reply in one sentence.", output="silent")
elapsed = time.perf_counter() - start
result.times.append(elapsed)
@@ -132,8 +131,7 @@ def benchmark_praisonai_two_agents(iterations: int = 3) -> ExecutionResult:
goal="Gather weather information",
instructions="Get weather data and pass to reporter. Be brief.",
llm="gpt-4o-mini",
tools=[get_weather],
verbose=False
tools=[get_weather]
)
reporter = Agent(
@@ -141,18 +139,16 @@ def benchmark_praisonai_two_agents(iterations: int = 3) -> ExecutionResult:
role="News Reporter",
goal="Create weather report",
instructions="Create a one-sentence weather summary.",
llm="gpt-4o-mini",
verbose=False
llm="gpt-4o-mini"
)
agents = Agents(
agents=[researcher, reporter],
process="sequential",
verbose=False
process="sequential"
)
start = time.perf_counter()
response = agents.start("Get NYC weather and create a brief report.")
response = agents.start("Get NYC weather and create a brief report.", output="silent")
elapsed = time.perf_counter() - start
result.times.append(elapsed)
@@ -176,8 +172,7 @@ def benchmark_praisonai_three_agents(iterations: int = 3) -> ExecutionResult:
goal="Get weather data",
instructions="Fetch weather information. Be brief.",
llm="gpt-4o-mini",
tools=[get_weather],
verbose=False
tools=[get_weather]
)
time_agent = Agent(
@@ -186,8 +181,7 @@ def benchmark_praisonai_three_agents(iterations: int = 3) -> ExecutionResult:
goal="Get time information",
instructions="Fetch timezone information. Be brief.",
llm="gpt-4o-mini",
tools=[get_time],
verbose=False
tools=[get_time]
)
summarizer = Agent(
@@ -195,18 +189,16 @@ def benchmark_praisonai_three_agents(iterations: int = 3) -> ExecutionResult:
role="Summary Writer",
goal="Combine information",
instructions="Create a one-sentence summary combining weather and time.",
llm="gpt-4o-mini",
verbose=False
llm="gpt-4o-mini"
)
agents = Agents(
agents=[weather_agent, time_agent, summarizer],
process="sequential",
verbose=False
process="sequential"
)
start = time.perf_counter()
response = agents.start("Get NYC weather and EST time, then summarize.")
response = agents.start("Get NYC weather and EST time, then summarize.", output="silent")
elapsed = time.perf_counter() - start
result.times.append(elapsed)
+1 -1
View File
@@ -1,5 +1,5 @@
from praisonaiagents import ContextAgent
agent = ContextAgent(llm="gpt-5-nano", auto_analyze=False)
agent = ContextAgent(llm="gpt-4o-mini", auto_analyze=False)
agent.start("https://github.com/MervinPraison/PraisonAI/ Need to add Authentication")
+1 -1
View File
@@ -14,7 +14,7 @@ def test_agent_direct():
agent = Agent(
instructions="""You are a helpful assistant that can break down complex problems.
Use the available tools when relevant to perform step-by-step analysis.""",
llm="gpt-5-nano",
llm="gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
@@ -14,7 +14,7 @@ llm_config = {
agent = Agent(
instructions="You are a helpful assistant. Be concise and clear.",
llm=llm_config,
verbose=True,
output="verbose",
self_reflect=True,
max_reflect=2,
min_reflect=1
@@ -7,8 +7,7 @@ def validate_content(data):
agent = Agent(
instructions="You are a writer",
guardrail=validate_content,
max_guardrail_retries=1
guardrails=validate_content
)
agent.start("Write a welcome message with 5 words")
+1 -1
View File
@@ -32,7 +32,7 @@ agent = Agent(
instructions="You are a helpful Assistant specialized in scientific explanations. "
"Provide clear, accurate, and engaging responses.",
llm=llm_config, # Pass the detailed configuration
verbose=True, # Enable detailed output
output="verbose", # Enable detailed output
markdown=True, # Format responses in markdown
self_reflect=True, # Enable self-reflection
max_reflect=3, # Maximum reflection iterations
+1 -1
View File
@@ -3,7 +3,7 @@ from praisonaiagents import Agent, MCP
agent = Agent(
instructions="""You are a helpful assistant that can check stock prices and perform other tasks.
Use the available tools when relevant to answer user questions.""",
llm="gpt-5-nano",
llm="gpt-4o-mini",
tools = MCP("/Users/praison/miniconda3/envs/mcp/bin/python /Users/praison/stockprice/app.py")
)
@@ -71,7 +71,7 @@ def main():
tools=[mongodb_tools],
memory=True,
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# 2. Knowledge Curator Agent - manages knowledge base
@@ -85,7 +85,7 @@ def main():
knowledge_config=mongodb_knowledge_config,
memory=True,
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# 3. Business Analyst Agent - analyzes data and provides insights
@@ -99,7 +99,7 @@ def main():
tools=[mongodb_tools],
memory=True,
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# 4. Customer Service Agent - handles customer interactions
@@ -114,7 +114,7 @@ def main():
tools=[mongodb_tools],
memory=True,
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create comprehensive business tasks
@@ -55,11 +55,9 @@ def main():
retrieve information from a comprehensive MongoDB knowledge base. You excel
at finding relevant information, synthesizing knowledge from multiple sources,
and providing accurate, context-aware responses.""",
knowledge_config=mongodb_knowledge_config,
knowledge=[os.path.join(os.path.dirname(__file__), "llms.md")],
memory=True,
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create a research assistant agent
@@ -72,8 +70,7 @@ def main():
knowledge base. You ensure information is accurate, well-structured,
and properly categorized.""",
memory=True,
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create tasks for knowledge management
@@ -128,7 +125,7 @@ def main():
agents=[research_agent, knowledge_agent],
tasks=knowledge_tasks,
memory=True,
verbose=True
output="verbose"
)
# Execute the knowledge management pipeline
@@ -59,7 +59,7 @@ def main():
knowledge=[os.path.join(os.path.dirname(__file__), "llms.md")],
memory=True,
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create a research assistant agent
@@ -73,7 +73,7 @@ def main():
and properly categorized.""",
memory=True,
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create tasks for knowledge management
+2 -2
View File
@@ -3,7 +3,7 @@ from praisonaiagents.memory import Memory
from praisonaiagents.agent import ContextAgent
import pymongo
context_agent = ContextAgent(llm="gpt-5-nano", auto_analyze=False)
context_agent = ContextAgent(llm="gpt-4o-mini", auto_analyze=False)
context_output = context_agent.start("https://github.com/MervinPraison/PraisonAI/ Need to add Authentication")
@@ -25,7 +25,7 @@ implementation_agent = Agent(
goal="Implement authentication features based on project requirements",
backstory="Expert software implementer specializing in authentication systems, security features, and seamless integration with existing codebases",
memory=True,
llm="gpt-5-nano",
llm="gpt-4o-mini",
)
implementation_task = Task(
@@ -50,7 +50,7 @@ def main():
retrieve relevant information from your persistent memory store.""",
memory=True,
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create research tasks
@@ -38,7 +38,7 @@ def main():
for data management and retrieval.""",
tools=[mongodb_tools],
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create a Data Analysis Agent
@@ -51,7 +51,7 @@ def main():
identify patterns and trends in the stored information.""",
tools=[mongodb_tools],
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create tasks for MongoDB operations
+7
View File
@@ -0,0 +1,7 @@
from praisonaiagents import Agent, Agents
research_agent = Agent(instructions="Research about AI")
summarise_agent = Agent(instructions="Summarise research agent's findings")
agents = Agents(agents=[research_agent, summarise_agent])
response = agents.start()
+1 -1
View File
@@ -2,6 +2,6 @@ from praisonaiagents import Agent
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
agent.start("Why sky is Blue?")
+1 -1
View File
@@ -2,7 +2,7 @@ from praisonaiagents import Agent
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
agent.start("Why sky is Blue?")
agent.start("What was my previous question?")
+1 -1
View File
@@ -3,7 +3,7 @@ import asyncio
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
agent.run("Why sea is Blue?")
+1 -1
View File
@@ -22,7 +22,7 @@ def multiply(a: int, b: int) -> int:
agent = Agent(
instructions="You are a helpful assistant. You can use the tools provided to you to help the user.",
llm="gpt-5-nano",
llm="gpt-4o-mini",
tools=[get_stock_price, multiply]
)
+1 -2
View File
@@ -14,8 +14,7 @@ task2 = Task(description="Write a short article about meditation benefits", agen
agents = Agents(
agents=[researcher, writer],
tasks=[task1, task2],
planning=True,
auto_approve_plan=True # Auto-approve the generated plan
planning=True
)
agents.start()
+1 -1
View File
@@ -22,7 +22,7 @@ def multiply(a: int, b: int) -> int:
agent = Agent(
instructions="You are a helpful assistant. You can use the tools provided to you to help the user.",
llm="gpt-5-nano",
llm="gpt-4o-mini",
tools=[get_stock_price, multiply]
)
+105 -180
View File
@@ -25,6 +25,14 @@ from .tools.registry import get_registry, register_tool, get_tool, ToolRegistry
from .db import db
from .obs import obs
# Sub-packages for organized imports (pa.config, pa.tools, etc.)
# These enable: import praisonaiagents as pa; pa.config.MemoryConfig
from . import config
from . import tools
from . import memory
from . import workflows
# Note: knowledge and mcp are lazy-loaded via __getattr__ due to heavy deps
# Workflows - lightweight module
from .workflows import (
Workflow, WorkflowStep, WorkflowContext, StepResult,
@@ -442,6 +450,51 @@ def __getattr__(name):
_lazy_cache[name] = ContextManager
return ContextManager
# =========================================================================
# Sub-package fallback: delegate to sub-packages for additional symbols
# This enables: from praisonaiagents import duckduckgo, FileMemory, etc.
# =========================================================================
# Try tools sub-package (110+ tool functions)
try:
from . import tools as _tools_module
if hasattr(_tools_module, name):
result = getattr(_tools_module, name)
_lazy_cache[name] = result
return result
except (ImportError, AttributeError):
pass
# Try memory sub-package (FileMemory, RulesManager, etc.)
try:
from . import memory as _memory_module
if hasattr(_memory_module, name):
result = getattr(_memory_module, name)
_lazy_cache[name] = result
return result
except (ImportError, AttributeError):
pass
# Try config sub-package (already handled above, but catch any stragglers)
try:
from . import config as _config_module
if hasattr(_config_module, name):
result = getattr(_config_module, name)
_lazy_cache[name] = result
return result
except (ImportError, AttributeError):
pass
# Try workflows sub-package (Pipeline, Route, etc. - already imported, catch aliases)
try:
from . import workflows as _workflows_module
if hasattr(_workflows_module, name):
result = getattr(_workflows_module, name)
_lazy_cache[name] = result
return result
except (ImportError, AttributeError):
pass
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
@@ -532,189 +585,61 @@ def warmup(include_litellm: bool = False, include_openai: bool = True) -> dict:
return timings
# ============================================================================
# PUBLIC API: __all__ (controls IDE autocomplete and `from X import *`)
# ============================================================================
# DESIGN: Keep __all__ minimal for clean IDE experience.
# All 186+ symbols are still accessible via __getattr__ for backwards compat.
# Organized imports available via sub-packages: config, tools, memory, workflows
# ============================================================================
__all__ = [
# Core classes (lazy loaded)
# Core classes - the essentials
'Agent',
'ImageAgent',
'ContextAgent',
'create_context_agent',
'PraisonAIAgents',
'Agents',
'Tools',
'Task',
# Plugin system
'BaseTool',
'ToolResult',
'ToolValidationError',
'validate_tool',
# Tool essentials
'tool',
'FunctionTool',
'ToolRegistry',
'get_registry',
'register_tool',
'get_tool',
'TaskOutput',
'ReflectionOutput',
'AutoAgents',
'AutoRagAgent',
'AutoRagConfig',
'RagRetrievalPolicy',
'Session',
'Memory',
'db',
'obs',
'display_interaction',
'display_self_reflection',
'display_instruction',
'display_tool_call',
'display_error',
'display_generating',
'clean_triple_backticks',
'error_logs',
'register_display_callback',
'sync_display_callbacks',
'async_display_callbacks',
'Knowledge',
'Chunking',
'GuardrailResult',
'LLMGuardrail',
'Handoff',
'handoff',
'handoff_filters',
'RECOMMENDED_PROMPT_PREFIX',
'prompt_with_handoff_instructions',
'HandoffConfig',
'HandoffResult',
'HandoffInputData',
'ContextPolicy',
'HandoffError',
'HandoffCycleError',
'HandoffDepthError',
'HandoffTimeoutError',
'get_telemetry',
'enable_telemetry',
'disable_telemetry',
'enable_performance_mode',
'disable_performance_mode',
'cleanup_telemetry_resources',
'MinimalTelemetry',
'TelemetryCollector',
'DeepResearchAgent',
'DeepResearchResponse',
'Citation',
'ReasoningStep',
'WebSearchCall',
'CodeExecutionStep',
'MCPCall',
'FileSearchCall',
'Provider',
'QueryRewriterAgent',
'RewriteStrategy',
'RewriteResult',
'PromptExpanderAgent',
'ExpandStrategy',
'ExpandResult',
# Workflows
'Workflow',
'WorkflowStep',
'WorkflowContext',
'StepResult',
'Route',
'Parallel',
'Loop',
'Repeat',
'route',
'parallel',
'loop',
'repeat',
'Pipeline',
# MCP
'MCP',
# Flow display
'FlowDisplay',
'track_workflow',
# FastContext
'FastContext',
'FastContextResult',
'FileMatch',
'LineRange',
# Agent Skills
'SkillManager',
'SkillProperties',
'SkillMetadata',
'SkillLoader',
# Planning
'Plan',
'PlanStep',
'TodoList',
'TodoItem',
'PlanStorage',
'PlanningAgent',
'ApprovalCallback',
'READ_ONLY_TOOLS',
'RESTRICTED_TOOLS',
# UI
'AGUI',
'A2A',
# RAG
'RAG',
'RAGConfig',
'RAGResult',
'RAGCitation',
# Feature Configs (agent-centric API)
'MemoryConfig',
'KnowledgeConfig',
'PlanningConfig',
'ReflectionConfig',
'GuardrailConfig',
'WebConfig',
'OutputConfig',
'ExecutionConfig',
'TemplateConfig',
'CachingConfig',
'HooksConfig',
'SkillsConfig',
'AutonomyConfig',
'MemoryBackend',
'ChunkingStrategy',
'GuardrailAction',
'WebSearchProvider',
'OutputPreset',
'ExecutionPreset',
'AutonomyLevel',
# Multi-Agent Feature Configs
'MultiAgentHooksConfig',
'MultiAgentOutputConfig',
'MultiAgentExecutionConfig',
'MultiAgentPlanningConfig',
'MultiAgentMemoryConfig',
# Context Management
'ManagerConfig',
'ContextManager',
# Parameter Resolution (agent-centric API)
'resolve',
'ArrayMode',
'resolve_guardrails',
'resolve_guardrail_policies',
# Presets (agent-centric API)
'GUARDRAIL_PRESETS',
'KNOWLEDGE_PRESETS',
# Parse Utilities
'is_policy_string',
'parse_policy_string',
# Performance utilities
'warmup',
# Cortex - Continuous Improvement System
'CortexConfig',
'CaptureStore',
'CaptureMode',
'CaptureScope',
'PersonaConfig',
'InsightConfig',
'ThreadConfig',
'EntityConfig',
'PatternConfig',
'DecisionConfig',
'FeedbackConfig',
'ImprovementConfig',
'Tools',
# Sub-packages for organized imports
# Usage: import praisonaiagents as pa; pa.config.MemoryConfig
'config',
'tools',
'memory',
'workflows',
]
def __dir__():
"""
Return clean list for dir() - matches __all__ plus standard attributes.
This keeps IDE autocomplete clean while preserving full backwards
compatibility via __getattr__ for all 186+ legacy exports.
"""
return list(__all__) + [
# Standard module attributes
'__name__', '__doc__', '__file__', '__path__', '__package__',
'__loader__', '__spec__', '__cached__', '__builtins__',
]
# ============================================================================
# BACKWARDS COMPATIBILITY: Legacy __all__ items (for reference)
# ============================================================================
# All items below are still importable via __getattr__ but NOT in autocomplete:
# - ImageAgent, ContextAgent, create_context_agent, PraisonAIAgents
# - BaseTool, ToolResult, ToolValidationError, validate_tool, FunctionTool
# - ToolRegistry, get_registry, register_tool, get_tool
# - TaskOutput, ReflectionOutput, AutoAgents, AutoRagAgent, AutoRagConfig
# - Session, Memory, db, obs, Knowledge, Chunking
# - GuardrailResult, LLMGuardrail, Handoff, handoff, handoff_filters
# - MemoryConfig, KnowledgeConfig, PlanningConfig, OutputConfig, etc.
# - Workflow, WorkflowStep, Route, Parallel, Loop, Repeat, Pipeline, etc.
# - MCP, FlowDisplay, track_workflow, FastContext, etc.
# - Plan, PlanStep, TodoList, PlanningAgent, ApprovalCallback, etc.
# - RAG, RAGConfig, RAGResult, AGUI, A2A, etc.
# - All telemetry, display, and utility functions
# ============================================================================
@@ -775,7 +775,15 @@ class Agent:
# If instructions are provided, use them to set role, goal, and backstory
if instructions:
self.name = name or "Agent"
# Only use explicitly provided name, don't auto-generate from instructions
# Auto-generation was producing confusing names like "You Are Agent" from
# instructions like "You are a helpful assistant"
if name:
self.name = name
else:
# Don't auto-generate - None signals "no explicit name provided"
# Display logic will skip Agent Info panel when name is None
self.name = None
self.role = role or "Assistant"
self.goal = goal or instructions
self.backstory = backstory or instructions
@@ -1089,6 +1097,13 @@ Your Goal: {self.goal}
# Action trace mode - handled via display callbacks, not separate emitter
self._actions_trace = actions_trace
# Telemetry
try:
from ..telemetry import get_telemetry
self._telemetry = get_telemetry()
except (ImportError, AttributeError):
self._telemetry = None
@property
def auto_memory(self):
"""AutoMemory instance for automatic memory extraction."""
@@ -2840,6 +2855,10 @@ Your Goal: {self.goal}"""
"""
logging.debug(f"{self.name} executing tool {function_name} with arguments: {arguments}")
# Notify callbacks that tool is being called (for dynamic status updates)
from ..main import execute_sync_callback
execute_sync_callback('tool_call', tool_name=function_name, tool_input=arguments)
# Set up injection context for tools with Injected parameters
from ..tools.injected import AgentState, with_injection_context
state = AgentState(
@@ -3871,6 +3890,10 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
async def achat(self, prompt: str, temperature=1.0, tools=None, output_json=None, output_pydantic=None, reasoning_steps=False, task_name=None, task_description=None, task_id=None):
"""Async version of chat method with self-reflection support."""
# Track execution via telemetry
if hasattr(self, '_telemetry') and self._telemetry:
self._telemetry.track_agent_execution(self.name, success=True)
# Reset the final display flag for each new conversation
self._final_display_shown = False
@@ -4269,8 +4292,8 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
Returns:
The agent's response as a string
"""
# Force non-streaming, non-display for production use
kwargs['stream'] = False
# Remove stream from kwargs since achat() doesn't accept it
kwargs.pop('stream', None)
return await self.achat(prompt, **kwargs)
async def astart(self, prompt: str, **kwargs):
@@ -4301,15 +4324,15 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
def run(self, prompt: str, **kwargs):
"""Execute agent silently and return structured result.
Production-friendly execution. Does not stream or display output by default.
Use this for programmatic/scripted usage where you want the result only.
Production-friendly execution. Always uses silent mode with no streaming
or verbose display, regardless of TTY status. Use this for programmatic,
scripted, or automated usage where you want just the result.
Args:
prompt: The input prompt to process
**kwargs: Additional arguments:
- stream (bool): Force streaming if True. Default: False
- display (bool): Force terminal display if True. Default: False
- output (str): Output preset override
- output (str): Output preset override (rarely needed)
Returns:
The agent's response as a string
@@ -4320,6 +4343,14 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
result = agent.run("What is 2+2?") # Silent, returns "4"
print(result)
```
Note:
Unlike .start() which enables verbose output in TTY for interactive
use, .run() is always silent. This makes it suitable for:
- Production pipelines
- Automated scripts
- Background processing
- API endpoints
"""
# Production defaults: no streaming, no display
if 'stream' not in kwargs:
@@ -4471,18 +4502,20 @@ Write the complete compiled report:"""
# Chat history is preserved in self.chat_history (no action needed)
def start(self, prompt: str, **kwargs):
"""Start the agent interactively with streaming output.
def start(self, prompt: str = None, **kwargs):
"""Start the agent interactively with verbose output.
Beginner-friendly execution. Streams output by default when running in a TTY.
Use this for interactive/terminal usage where you want to see output in real-time.
Beginner-friendly execution. Defaults to verbose output with streaming
when running in a TTY. Use this for interactive/terminal usage where
you want to see output in real-time with rich formatting.
Args:
prompt: The input prompt to process
prompt: The input prompt to process. If not provided, uses the
agent's instructions as the task (useful when instructions
already describe what the agent should do).
**kwargs: Additional arguments:
- stream (bool | None): Override streaming. None = auto-detect TTY
- display (bool | None): Override display. None = auto (True if streaming)
- output (str): Output preset override
- output (str): Output preset override (e.g., "silent", "verbose")
Returns:
- If streaming: Generator yielding response chunks
@@ -4490,21 +4523,32 @@ Write the complete compiled report:"""
Example:
```python
agent = Agent(instructions="You are helpful")
# Minimal usage - instructions IS the task
agent = Agent(instructions="Research AI trends and summarize")
result = agent.start() # Uses instructions as task
# Interactive use - streams by default in terminal
for chunk in agent.start("Tell me a story"):
print(chunk, end="", flush=True)
# Or let it handle display automatically
result = agent.start("What is 2+2?") # Streams if TTY
# With explicit prompt (overrides/adds to instructions)
agent = Agent(instructions="You are a helpful assistant")
result = agent.start("What is 2+2?") # Uses prompt as task
```
Note:
Unlike .run() which is always silent (production use), .start()
enables verbose output by default when in a TTY for beginner-friendly
interactive use. Use .run() for programmatic/scripted usage.
"""
import sys
# If no prompt provided, use instructions as the task
if prompt is None:
prompt = self.instructions or "Hello"
# Load history from past sessions
self._load_history_context()
# Determine if we're in an interactive TTY
is_tty = sys.stdout.isatty()
# Determine streaming behavior
# Priority: explicit kwarg > agent's stream attribute > TTY detection
stream_requested = kwargs.get('stream')
@@ -4514,24 +4558,192 @@ Write the complete compiled report:"""
stream_requested = self.stream
else:
# Auto-detect: stream if stdout is a TTY (interactive terminal)
stream_requested = sys.stdout.isatty()
stream_requested = is_tty
# Check if planning mode is enabled
if self.planning:
result = self._start_with_planning(prompt, **kwargs)
elif stream_requested:
# Return a generator for streaming response
kwargs['stream'] = True
result = self._start_stream(prompt, **kwargs)
else:
# Return regular chat response
kwargs['stream'] = False
result = self.chat(prompt, **kwargs)
# ─────────────────────────────────────────────────────────────────────
# Enable verbose output in TTY for beginner-friendly interactive use
# Priority: explicit output= kwarg > TTY auto-verbose > agent's default
# ─────────────────────────────────────────────────────────────────────
original_verbose = self.verbose
original_markdown = self.markdown
output_override = kwargs.pop('output', None) # Pop to prevent passing to chat()
# Auto-save session if enabled
self._auto_save_session()
return result
try:
# If running in TTY and no explicit output override, enable verbose
if is_tty and output_override is None:
self.verbose = True
self.markdown = True
elif output_override:
# Apply explicit output preset for this call
from ..config.presets import OUTPUT_PRESETS
if output_override in OUTPUT_PRESETS:
preset = OUTPUT_PRESETS[output_override]
self.verbose = preset.get('verbose', False)
self.markdown = preset.get('markdown', False)
# Check if planning mode is enabled
if self.planning:
result = self._start_with_planning(prompt, **kwargs)
elif stream_requested:
# Return a generator for streaming response
kwargs['stream'] = True
result = self._start_stream(prompt, **kwargs)
else:
# Return regular chat response with animated working status
kwargs['stream'] = False
# Show animated status during LLM call if verbose
if self.verbose and is_tty:
from rich.live import Live
from rich.console import Group
from rich.status import Status
from ..main import PRAISON_COLORS, sync_display_callbacks
import threading
import time as time_module
console = Console()
start_time = time_module.time()
# ─────────────────────────────────────────────────────────────
# Shared state for dynamic status messages (thread-safe)
# Updated by callbacks during tool execution
# ─────────────────────────────────────────────────────────────
current_status = ["Analyzing query..."]
tools_called = []
# Register a temporary callback to track tool calls
def status_tool_callback(**kwargs):
tool_name = kwargs.get('tool_name', '')
if tool_name:
tools_called.append(tool_name)
current_status[0] = f"Calling tool: {tool_name}..."
# Store original callback and register ours
original_tool_callback = sync_display_callbacks.get('tool_call')
sync_display_callbacks['tool_call'] = status_tool_callback
# Animation state
result_holder = [None]
error_holder = [None]
# Temporarily disable verbose in chat to prevent duplicate output
original_verbose_chat = self.verbose
def run_chat():
try:
# Suppress verbose during animation - we'll display result ourselves
self.verbose = False
current_status[0] = "Sending to LLM..."
result_holder[0] = self.chat(prompt, **kwargs)
current_status[0] = "Finalizing response..."
except Exception as e:
error_holder[0] = e
finally:
self.verbose = original_verbose_chat
# Restore original callback
if original_tool_callback:
sync_display_callbacks['tool_call'] = original_tool_callback
elif 'tool_call' in sync_display_callbacks:
del sync_display_callbacks['tool_call']
# Start chat in background thread
chat_thread = threading.Thread(target=run_chat)
chat_thread.start()
from rich.panel import Panel
from rich.text import Text
from rich.markdown import Markdown
# ─────────────────────────────────────────────────────────────
# Smart Agent Info: Only show if user provided meaningful info
# Skip if using defaults ("Agent"/"Assistant") with single agent
# ─────────────────────────────────────────────────────────────
has_custom_name = self.name and self.name not in ("Agent", "agent", None, "")
has_custom_role = self.role and self.role not in ("Assistant", "AI Assistant", "assistant", None, "")
has_tools = bool(self.tools)
show_agent_info = has_custom_name or has_custom_role or has_tools
agent_panel = None
if show_agent_info:
agent_info_parts = []
if has_custom_name:
agent_info_parts.append(f"[bold {PRAISON_COLORS['task']}]👤 Agent:[/] [{PRAISON_COLORS['agent_text']}]{self.name}[/]")
if has_custom_role:
agent_info_parts.append(f"[bold {PRAISON_COLORS['metrics']}]Role:[/] [{PRAISON_COLORS['agent_text']}]{self.role}[/]")
if has_tools:
tools_list = [t.__name__ if hasattr(t, '__name__') else str(t) for t in self.tools][:5]
tools_str = ", ".join(f"[italic {PRAISON_COLORS['response']}]{tool}[/]" for tool in tools_list)
agent_info_parts.append(f"[bold {PRAISON_COLORS['agent']}]Tools:[/] {tools_str}")
agent_panel = Panel(
"\n".join(agent_info_parts),
border_style=PRAISON_COLORS["agent"],
title="[bold]Agent Info[/]",
title_align="left",
padding=(1, 2)
)
# Create task panel
task_panel = Panel.fit(
Markdown(prompt) if self.markdown else Text(prompt),
title="Task",
border_style=PRAISON_COLORS["task"]
)
# Show initial panels (agent info if applicable, then task)
if agent_panel:
console.print(agent_panel)
console.print(task_panel)
# ─────────────────────────────────────────────────────────────
# Animate with Rich.Status showing DYNAMIC status from callbacks
# ─────────────────────────────────────────────────────────────
with console.status(
f"[bold yellow]Working...[/] {current_status[0]}",
spinner="dots",
spinner_style="yellow"
) as status:
last_status = current_status[0]
while chat_thread.is_alive():
time_module.sleep(0.15) # More responsive updates
# Only update if status changed (reduces flicker)
if current_status[0] != last_status:
last_status = current_status[0]
status.update(f"[bold yellow]Working...[/] {current_status[0]}")
# Calculate elapsed time
elapsed = time_module.time() - start_time
# Re-raise any error from chat
if error_holder[0]:
raise error_holder[0]
result = result_holder[0]
# Display response panel
response_panel = Panel.fit(
Markdown(str(result)) if self.markdown else Text(str(result)),
title=f"Response ({elapsed:.1f}s)",
border_style=PRAISON_COLORS["response"]
)
console.print(response_panel)
# Show tool activity summary if tools were called
if tools_called:
tools_summary = ", ".join(tools_called)
console.print(f"[dim]🔧 Tools used: {tools_summary}[/dim]")
else:
result = self.chat(prompt, **kwargs)
# Auto-save session if enabled
self._auto_save_session()
return result
finally:
# Restore original output settings
self.verbose = original_verbose
self.markdown = original_markdown
def iter_stream(self, prompt: str, **kwargs):
"""Stream agent response as an iterator of chunks.
@@ -435,7 +435,6 @@ This report contains all agent interactions and outputs from a complete ContextA
Provide comprehensive analysis that follows the PRD template principles and enables
AI assistants to implement features that perfectly match existing codebase patterns.""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
prompt = f"""Analyze this gitingest codebase digest following PRD template methodology:
@@ -516,7 +515,6 @@ codebase style and architecture following PRD template principles."""
goal="Perform comprehensive manual codebase analysis following PRD methodology",
instructions="""Analyze the codebase samples following PRD template methodology for complete understanding.""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
# Format comprehensive sample
@@ -567,7 +565,6 @@ Analyze following PRD principles to extract patterns, conventions, and architect
7. Code complexity metrics
8. API and interface patterns""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
# Perform AST analysis on Python files
@@ -625,7 +622,6 @@ Extract comprehensive patterns that follow PRD template principles for implement
For each pattern, provide the pattern name, where it's used, and how to replicate it
following PRD template principles.""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
# Get representative code samples
@@ -675,7 +671,6 @@ patterns and best practices for first-try success."""
instructions="""Analyze testing patterns to understand validation approaches and create
comprehensive test frameworks following PRD methodology.""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
# Get test files
@@ -802,7 +797,6 @@ Extract testing patterns for validation framework creation following PRD princip
Generate PRPs following this EXACT structure for first-try implementation success.""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
prompt = f"""Generate a comprehensive Product Requirements Prompt (PRP) following the EXACT PRD template structure:
@@ -851,7 +845,6 @@ on the first try following PRD template principles."""
7. DOCUMENTATION VALIDATION: Documentation completeness
8. DEPENDENCY VALIDATION: Dependency analysis and security""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
# Analyze existing validation patterns
@@ -898,7 +891,6 @@ following PRD template principles."""
README files, API documentation, setup guides, architecture docs, and any other
relevant documentation that provides context for implementation.""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
# Get documentation files
@@ -944,7 +936,6 @@ following PRD template principles."""
APIs, databases, external services, configuration points, and any other
integration requirements that affect implementation.""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
# Get configuration and dependency files
@@ -1005,7 +996,6 @@ following PRD template principles."""
9. INTEGRATION STEPS: How to integrate with existing systems
10. VALIDATION CHECKPOINTS: Validation steps at each phase""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
prompt = f"""Create detailed implementation blueprint following PRD methodology:
@@ -1303,7 +1293,6 @@ Every agent interaction has been saved for full audit trail and reproducibility.
Be precise and extract only what is explicitly mentioned or clearly implied.""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
prompt = f"""Parse this user input to extract codebase and goal:
@@ -1537,7 +1526,6 @@ Note: Detailed function/class metadata not available due to content access limit
Make the output easy for a file selection agent to understand which files contain what functionality.""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
structure_text = basic_structure.get('structure', '')
@@ -1771,7 +1759,6 @@ Focus on creating clear, structured metadata that will help with intelligent fil
Maximum 50 files for efficient analysis.""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
# Prepare enhanced structure information
@@ -1924,7 +1911,6 @@ Maximum 50 files.""".format(goal=goal)
Since these files were pre-selected for relevance, provide deep analysis of how each contributes to implementing: {goal}""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
prompt = f"""Analyze these carefully selected repository files for implementing: {goal}
@@ -2025,7 +2011,6 @@ Since these files were pre-selected for relevance, explain how each contributes
Focus everything on successfully implementing: {goal}""",
llm=self.llm if hasattr(self, 'llm') else "gpt-4o-mini",
verbose=getattr(self, 'verbose', True)
)
chunk_info = ""
@@ -466,10 +466,16 @@ class Agents:
if self.shared_memory:
for task in tasks:
if not task.memory:
task.memory = self.shared_memory
logger.info(f"Assigned shared memory to task {task.id}")
# Telemetry
try:
from ..telemetry import get_telemetry
self._telemetry = get_telemetry()
except (ImportError, AttributeError):
self._telemetry = None
def add_task(self, task):
task_id = self.task_id_counter
task.id = task_id
@@ -821,13 +827,17 @@ Context:
await loop.run_in_executor(None, self.run_task, task_id)
async def astart(self, content=None, return_dict=False, **kwargs):
"""Async version of start method
"""Async version of start method.
Args:
content: Optional content to add to all tasks' context
return_dict: If True, returns the full results dictionary instead of only the final response
**kwargs: Additional arguments
"""
# Track execution via telemetry
if hasattr(self, '_telemetry') and self._telemetry:
self._telemetry.track_agent_execution(self.name, success=True, async_mode=True)
if content:
# Add content to context of all tasks
for task in self.tasks.values():
@@ -1193,30 +1203,146 @@ Context:
return str(agent[0])
return None
def start(self, content=None, return_dict=False, **kwargs):
"""Start agent execution with optional content and config
def start(self, content=None, return_dict=False, output=None, **kwargs):
"""Start agent execution with verbose output (beginner-friendly).
Shows Rich panels with workflow progress when in TTY. Use .run() for
silent execution in production/scripts.
Args:
content: Optional content to add to all tasks' context
return_dict: If True, returns the full results dictionary instead of only the final response
return_dict: If True, returns the full results dictionary
output: Output preset - "silent", "verbose", "normal", etc.
Default in TTY: "verbose" (shows progress)
Default non-TTY: "silent"
**kwargs: Additional arguments
Example:
```python
# Interactive - shows Rich panels
agents = Agents(agents=[agent1, agent2])
result = agents.start() # Verbose output by default
# Force silent mode
result = agents.start(output="silent")
```
"""
# Track execution via telemetry
if hasattr(self, '_telemetry') and self._telemetry:
self._telemetry.track_agent_execution(self.name, success=True)
import sys
from ..main import PRAISON_COLORS
# Determine if we're in an interactive TTY
is_tty = sys.stdout.isatty()
# Resolve output mode (TTY-aware)
if output is None:
# Default: verbose in TTY (beginner-friendly), silent otherwise
# Note: Don't check self.verbose here - start() is for interactive use
show_verbose = is_tty
elif output == "silent":
show_verbose = False
elif output in ("verbose", "debug", "normal"):
show_verbose = True
else:
show_verbose = is_tty
# Add content to context if provided
if content:
# Add content to context of all tasks
for task in self.tasks.values():
if isinstance(content, (str, list)):
# If context is empty, initialize it
if not task.context:
task.context = []
# Add content to context
task.context.append(content)
# Planning Mode: Create plan and todo list before execution
if self.planning:
self._run_with_planning()
# ─────────────────────────────────────────────────────────────
# Verbose Mode: Show Rich panels for multi-agent workflow
# ─────────────────────────────────────────────────────────────
if show_verbose and is_tty:
from rich.panel import Panel
from rich.text import Text
console = Console()
import time as time_module
# Show workflow overview panel
agent_names = " → ".join([a.name for a in self.agents])
workflow_info = f"[bold {PRAISON_COLORS['metrics']}]Process:[/] {self.process}\n"
workflow_info += f"[bold {PRAISON_COLORS['metrics']}]Agents:[/] {agent_names}"
console.print(Panel(
workflow_info,
title="[bold]Multi-Agent Workflow[/]",
border_style=PRAISON_COLORS["agent"],
padding=(1, 2)
))
console.print()
# Execute tasks with verbose output
total_agents = len(self.agents)
workflow_start_time = time_module.time()
for idx, (task_id, task) in enumerate(self.tasks.items(), 1):
agent = task.agent
agent_name = agent.name if agent else "Unknown"
agent_model = getattr(agent, 'llm', 'gpt-4o-mini') if agent else "unknown"
# Show agent task panel with model info
task_desc = task.description[:100] + "..." if len(task.description) > 100 else task.description
panel_content = f"[bold {PRAISON_COLORS['task_text']}]📋 Task:[/] {task_desc}\n"
panel_content += f"[dim]🤖 Model: {agent_model}[/dim]"
console.print(Panel.fit(
panel_content,
title=f"[bold]Agent [{idx}/{total_agents}]: {agent_name}[/]",
border_style=PRAISON_COLORS["task"]
))
# Execute with timing and status
start_time = time_module.time()
# Show working spinner
with console.status(
f"[bold yellow]Working...[/] {agent_name} generating response...",
spinner="dots",
spinner_style="yellow"
):
# Run the task
if self.planning:
self._run_with_planning()
break # Planning mode handles all tasks
else:
self.run_task(task_id)
elapsed = time_module.time() - start_time
# Show response panel - FULL response, no truncation
result = self.get_task_result(task_id)
if result:
response_text = str(result.raw)
# No truncation - show full response in verbose mode
console.print(Panel(
Text(response_text),
title=f"[bold]Agent [{idx}/{total_agents}] Complete ({elapsed:.1f}s)[/]",
border_style=PRAISON_COLORS["response"],
padding=(1, 2)
))
console.print()
# Workflow summary panel
total_elapsed = time_module.time() - workflow_start_time
console.print(Panel.fit(
f"[bold green]Total Time:[/] {total_elapsed:.1f}s\n"
f"[bold green]Agents Run:[/] {total_agents}/{total_agents}",
title="[bold]✅ Workflow Complete[/]",
border_style="green"
))
console.print()
else:
# Run tasks as before
self.run_all_tasks()
# Silent mode: Run tasks without display
if self.planning:
self._run_with_planning()
else:
self.run_all_tasks()
# Auto-display token metrics if any agent has metrics=True
metrics_enabled = any(getattr(agent, 'metrics', False) for agent in self.agents)
@@ -1224,10 +1350,8 @@ Context:
try:
self.display_token_usage()
except (ImportError, AttributeError) as e:
# Token tracking not available or not properly configured
logging.debug(f"Could not auto-display token usage: {e}")
except Exception as e:
# Log unexpected errors for debugging
logging.debug(f"Unexpected error in token metrics display: {e}")
# Get results
@@ -1238,7 +1362,6 @@ Context:
# By default, return only the final agent's response
if not return_dict:
# Get the last task (assuming sequential processing)
task_ids = list(self.tasks.keys())
if task_ids:
last_task_id = task_ids[-1]
@@ -1246,12 +1369,21 @@ Context:
if last_result:
return last_result.raw
# Return full results dict if return_dict is True or if no final result was found
return results
def run(self, content=None, return_dict=False, **kwargs):
"""Alias for start() method to provide consistent API with Agent class"""
return self.start(content=content, return_dict=return_dict, **kwargs)
"""Run agents silently (production use).
Unlike .start() which shows verbose output, .run() executes silently
for programmatic/production use.
Args:
content: Optional content to add to all tasks' context
return_dict: If True, returns the full results dictionary
**kwargs: Additional arguments
"""
# Always run silently - no verbose output
return self.start(content=content, return_dict=return_dict, output="silent", **kwargs)
def set_state(self, key: str, value: Any) -> None:
"""Set a state value"""
@@ -1540,6 +1540,7 @@ Now provide your final answer using this result."""
max_iterations = 10 # Prevent infinite loops
iteration_count = 0
final_response_text = ""
response_text = "" # Initialize to prevent UnboundLocalError on API errors
stored_reasoning_content = None # Store reasoning content from tool execution
accumulated_tool_results = [] # Store all tool results across iterations
@@ -739,7 +739,8 @@ class OpenAIClient:
content=content
))
first_token_emitted = True
else:
elif _emit:
# Emit DELTA_TEXT for subsequent tokens
stream_callback(StreamEvent(
type=StreamEventType.DELTA_TEXT,
timestamp=last_content_time,
+204 -23
View File
@@ -30,6 +30,53 @@ async_display_callbacks = {}
# Global approval callback registry
approval_callback = None
# ─────────────────────────────────────────────────────────────────────────────
# PraisonAI Unique Color Palette: "Elegant Intelligence"
# Creates a visual narrative flow: Agent → Task → Working → Response
# ─────────────────────────────────────────────────────────────────────────────
PRAISON_COLORS = {
# Agent identity - grounded, stable
"agent": "#86A789", # Soft Sage Green
"agent_text": "#D2E3C8", # Light sage for text
# Task/Question - input, attention-grabbing
"task": "#FF9B9B", # Warm Coral
"task_text": "#FFE5E5", # Light coral for text
# Working/Processing - action, energy
"working": "#FFB347", # Amber
"working_text": "#FFF3E0", # Light amber for text
# Response/Output - completion, calm
"response": "#4A90D9", # Ocean Blue
"response_text": "#E3F2FD", # Light blue for text
# Tool calls - special action
"tool": "#9B7EDE", # Violet Accent
"tool_text": "#EDE7F6", # Light violet for text
# Reasoning - thought process
"reasoning": "#78909C", # Blue Gray
"reasoning_text": "#ECEFF1", # Light gray for text
# Error/Warning - alert
"error": "#E57373", # Alert Red
"error_text": "#FFEBEE", # Light red for text
# Metrics - meta information
"metrics": "#B4B4B3", # Cool Gray
"metrics_text": "#FAFAFA", # Near white for text
}
# Status animation frames for "Working" indicator
WORKING_FRAMES = ["●○○", "○●○", "○○●", "○●○"]
WORKING_PHASES = [
"Analyzing query...",
"Processing context...",
"Generating response...",
"Finalizing output...",
]
# At the top of the file, add display_callbacks to __all__
__all__ = [
'error_logs',
@@ -39,7 +86,19 @@ __all__ = [
'async_display_callbacks',
'execute_callback',
'approval_callback',
# ... other exports
# Color palette and animation constants
'PRAISON_COLORS',
'WORKING_FRAMES',
'WORKING_PHASES',
# Display functions
'display_interaction',
'display_instruction',
'display_tool_call',
'display_error',
'display_generating',
'display_reasoning_steps',
'display_working_status',
'display_self_reflection',
]
def register_display_callback(display_type: str, callback_fn, is_async: bool = False):
@@ -149,10 +208,14 @@ def _clean_display_content(content: str, max_length: int = 20000) -> str:
return content.strip()
def display_interaction(message, response, markdown=True, generation_time=None, console=None, agent_name=None, agent_role=None, agent_tools=None, task_name=None, task_description=None, task_id=None):
def display_interaction(message, response, markdown=True, generation_time=None, console=None, agent_name=None, agent_role=None, agent_tools=None, task_name=None, task_description=None, task_id=None, metrics=None):
"""Synchronous version of display_interaction.
Displays the task/message and response in clean panels with response time in title.
Displays the task/message and response in clean panels with semantic colors
and optional metrics footer. Uses PraisonAI's unique color palette.
Args:
metrics: Optional dict with token_in, token_out, cost, model for footer display
"""
if console is None:
console = Console()
@@ -180,20 +243,40 @@ def display_interaction(message, response, markdown=True, generation_time=None,
agent_tools=agent_tools,
task_name=task_name,
task_description=task_description,
task_id=task_id
task_id=task_id,
metrics=metrics
)
# Build response title with time (Agno-style: "Response (1.2s)")
# Build response title with time
response_title = "Response"
if generation_time:
response_title = f"Response ({generation_time:.1f}s)"
# Build response content with optional metrics footer
response_content = response
if metrics and isinstance(metrics, dict):
# Add dashed separator and compact metrics line
tokens_in = metrics.get('tokens_in', 0)
tokens_out = metrics.get('tokens_out', 0)
cost = metrics.get('cost', 0)
model = metrics.get('model', '')
metrics_line = f"\n\n─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─\n📊 {tokens_in} tokens in · {tokens_out} out"
if cost > 0:
metrics_line += f" · ${cost:.4f}"
if model:
metrics_line += f" · {model}"
response_content = response + metrics_line
# Task is inline (less visual weight), Response keeps panel (it's the main content)
# Format: 📝 Task message
task_prefix = "[bold #FF9B9B]📝[/]"
if markdown:
console.print(Panel.fit(Markdown(message), title="Task", border_style="cyan"))
console.print(Panel.fit(Markdown(response), title=response_title, border_style="cyan"))
console.print(f"{task_prefix} {message}\n")
console.print(Panel.fit(Markdown(response_content), title=response_title, border_style=PRAISON_COLORS["response"]))
else:
console.print(Panel.fit(Text(message, style="bold green"), title="Task", border_style="cyan"))
console.print(Panel.fit(Text(response, style="bold blue"), title=response_title, border_style="cyan"))
console.print(f"{task_prefix} [bold {PRAISON_COLORS['task_text']}]{message}[/]\n")
console.print(Panel.fit(Text(response_content, style=f"bold {PRAISON_COLORS['response_text']}"), title=response_title, border_style=PRAISON_COLORS["response"]))
def display_self_reflection(message: str, console=None):
if not message or not message.strip():
@@ -231,8 +314,11 @@ def display_instruction(message: str, console=None, agent_name: str = None, agen
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
console.print(Panel.fit(Text(message, style="bold blue"), title="Instruction", border_style="cyan"))
def display_tool_call(message: str, console=None, tool_name: str = None, tool_input: dict = None, tool_output: str = None):
"""Display tool call information in a consolidated panel.
def display_tool_call(message: str, console=None, tool_name: str = None, tool_input: dict = None, tool_output: str = None, elapsed_time: float = None, success: bool = True):
"""Display tool call information in PraisonAI's unique timeline format.
Uses ▸ prefix, inline timing [X.Xs], and status icons ✓/✗ for a clean,
scannable tool activity display.
Args:
message: The tool call message (legacy format)
@@ -240,6 +326,8 @@ def display_tool_call(message: str, console=None, tool_name: str = None, tool_in
tool_name: Name of the tool being called
tool_input: Input arguments to the tool
tool_output: Output from the tool (if available)
elapsed_time: Time taken for tool execution in seconds
success: Whether the tool call succeeded
"""
logging.debug(f"display_tool_call called with message: {repr(message)}")
if not message or not message.strip():
@@ -251,19 +339,41 @@ def display_tool_call(message: str, console=None, tool_name: str = None, tool_in
# Execute synchronous callbacks (always, even when console is None)
execute_sync_callback('tool_call', message=message, tool_name=tool_name, tool_input=tool_input, tool_output=tool_output)
# Only print panel if console is provided (verbose mode)
# Only print if console is provided (verbose mode)
if console is not None:
# Build consolidated tool call display (Agno-style)
if tool_name and tool_input is not None:
# Format: tool_name(arg1=val1, arg2=val2)
args_str = ", ".join(f"{k}={v}" for k, v in tool_input.items()) if tool_input else ""
tool_display = f"• {tool_name}({args_str})"
# Build clean inline format - no panels, just prefixed lines
if tool_name:
# Format: ▸ tool_name(args) → result [X.Xs] ✓
args_str = ""
if tool_input:
# Truncate long values for display
args_parts = []
for k, v in tool_input.items():
v_str = str(v)
if len(v_str) > 50:
v_str = v_str[:47] + "..."
args_parts.append(f"{k}={repr(v_str) if isinstance(v, str) else v_str}")
args_str = ", ".join(args_parts)
# Build the inline entry
status_icon = "[green]✓[/]" if success else "[red]✗[/]"
time_str = f"[dim][{elapsed_time:.1f}s][/]" if elapsed_time else ""
# Base tool call line
tool_line = f"[bold #86A789]▸[/] [#B4D4FF]{tool_name}[/]({args_str})"
# Add output inline with arrow if available
if tool_output:
tool_display += f"\n → {tool_output}"
console.print(Panel.fit(Text(tool_display, style="bold cyan"), title="Tool Call", border_style="green"))
output_str = str(tool_output)
if len(output_str) > 80:
output_str = output_str[:77] + "..."
tool_line += f" [dim]→[/] [italic]{output_str}[/]"
tool_line += f" {time_str} {status_icon}"
console.print(tool_line)
else:
# Legacy format
console.print(Panel.fit(Text(message, style="bold cyan"), title="Tool Call", border_style="green"))
# Legacy format - simple inline
console.print(f"[bold #86A789]▸[/] {message}")
def display_error(message: str, console=None):
if not message or not message.strip():
@@ -275,7 +385,12 @@ def display_error(message: str, console=None):
# Execute synchronous callbacks
execute_sync_callback('error', message=message)
console.print(Panel.fit(Text(message, style="bold red"), title="Error", border_style="red"))
# Use semantic error color
console.print(Panel.fit(
Text(message, style=f"bold {PRAISON_COLORS['error_text']}"),
title="⚠ Error",
border_style=PRAISON_COLORS["error"]
))
error_logs.append(message)
def display_generating(content: str = "", start_time: Optional[float] = None):
@@ -293,7 +408,73 @@ def display_generating(content: str = "", start_time: Optional[float] = None):
# Execute synchronous callbacks
execute_sync_callback('generating', content=content, elapsed_time=elapsed_str.strip() if elapsed_str else None)
return Panel(Markdown(content), title=f"Generating...{elapsed_str}", border_style="green")
# Use semantic response color
return Panel(Markdown(content), title=f"Generating...{elapsed_str}", border_style=PRAISON_COLORS["response"])
def display_reasoning_steps(steps: List[str], console=None):
"""Display reasoning steps with unique numbered circles.
Uses ①②③ numbered circles for a distinctive, scannable format
that shows the agent's thought process.
Args:
steps: List of reasoning step descriptions
console: Rich console for output
"""
if not steps:
return
if console is None:
console = Console()
# Circle number mapping (supports up to 20 steps)
circle_numbers = "①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳"
# Build reasoning display with numbered circles
reasoning_lines = []
for i, step in enumerate(steps):
circle = circle_numbers[i] if i < len(circle_numbers) else f"({i+1})"
step_text = _clean_display_content(str(step))
if len(step_text) > 80:
step_text = step_text[:77] + "..."
reasoning_lines.append(f"{circle} {step_text}")
reasoning_display = "\n".join(reasoning_lines)
console.print(Panel.fit(
Text(reasoning_display, style=f"italic {PRAISON_COLORS['reasoning_text']}"),
title="Reasoning",
border_style=PRAISON_COLORS["reasoning"]
))
def display_working_status(phase: int = 0, status_text: str = None, console=None):
"""Display animated working status with pulsing dots.
Shows a unique "Working ●○○" indicator with phase-specific status.
This is PraisonAI's distinctive approach to showing processing status.
Args:
phase: Current animation phase (0-3)
status_text: Optional status description
console: Rich console for output
Returns:
Panel object for use with Rich.Live
"""
if console is None:
console = Console()
# Get current frame and phase text
frame = WORKING_FRAMES[phase % len(WORKING_FRAMES)]
phase_text = status_text or WORKING_PHASES[phase % len(WORKING_PHASES)]
# Build working status display
working_display = f"Working {frame} {phase_text}"
return Panel.fit(
Text(working_display, style=f"bold {PRAISON_COLORS['working_text']}"),
title="Status",
border_style=PRAISON_COLORS["working"]
)
# Async versions with 'a' prefix
async def adisplay_interaction(message, response, markdown=True, generation_time=None, console=None, agent_name=None, agent_role=None, agent_tools=None, task_name=None, task_description=None, task_id=None):
@@ -162,11 +162,13 @@ class Session:
from ..agent import Agent as AgentClass
# Filter out parameters that are not valid for Agent.__init__
valid_kwargs = {k: v for k, v in kwargs.items() if k not in ('verbose', 'user_id')}
agent_kwargs = {
"name": name,
"role": role,
"user_id": self.user_id,
**kwargs
**valid_kwargs
}
if instructions:
@@ -177,7 +179,6 @@ class Session:
agent_kwargs["memory"] = self.memory
if knowledge:
agent_kwargs["knowledge"] = knowledge
agent_kwargs["knowledge_config"] = self.knowledge_config
agent = AgentClass(**agent_kwargs)
@@ -26,16 +26,41 @@ _telemetry_executor = None
_telemetry_queue = None
_queue_processor_running = False
_queue_lock = threading.Lock()
_atexit_registered = False
def _atexit_cleanup():
"""Cleanup handler registered with atexit to prevent hanging on exit."""
global _queue_processor_running, _telemetry_executor, _telemetry_queue
# Signal queue processor to stop
_queue_processor_running = False
# Shutdown executor without waiting (to prevent hang)
if _telemetry_executor is not None:
try:
_telemetry_executor.shutdown(wait=False)
except:
pass
_telemetry_executor = None
_telemetry_queue = None
def _get_telemetry_executor():
"""Get or create the shared telemetry thread pool executor."""
global _telemetry_executor
global _telemetry_executor, _atexit_registered
if _telemetry_executor is None:
# Use a small thread pool to avoid resource overhead
_telemetry_executor = concurrent.futures.ThreadPoolExecutor(
max_workers=2,
thread_name_prefix="telemetry"
)
# Register atexit cleanup to prevent hanging on exit
if not _atexit_registered:
import atexit
atexit.register(_atexit_cleanup)
_atexit_registered = True
return _telemetry_executor
def _get_telemetry_queue():
@@ -48,8 +73,13 @@ def _get_telemetry_queue():
with _queue_lock:
if not _queue_processor_running:
_queue_processor_running = True
executor = _get_telemetry_executor()
executor.submit(_process_telemetry_queue)
# Use a daemon thread directly instead of executor to prevent hang
processor_thread = threading.Thread(
target=_process_telemetry_queue,
name="telemetry-queue-processor",
daemon=True # Daemon thread will be killed on exit
)
processor_thread.start()
return _telemetry_queue
@@ -61,12 +91,22 @@ def _process_telemetry_queue():
try:
while _queue_processor_running:
# Check if interpreter is shutting down
try:
import sys
if hasattr(sys, 'is_finalizing') and sys.is_finalizing():
break
except:
break
events = []
deadline = time.time() + batch_timeout
# Collect events until batch size or timeout
while len(events) < batch_size and time.time() < deadline:
try:
if _telemetry_queue is None:
break
event = _telemetry_queue.get(timeout=0.1)
events.append(event)
_telemetry_queue.task_done()
@@ -381,6 +381,10 @@ class PerformanceMonitor:
Returns:
List of flow events showing function execution order and timing
"""
# If monitoring is disabled, return empty results
if self._monitoring_disabled:
return []
with self._lock:
flow = []
for event in self._function_flow.copy():
@@ -400,6 +404,10 @@ class PerformanceMonitor:
def get_active_calls(self) -> Dict[str, Any]:
"""Get information about currently executing functions."""
# If monitoring is disabled, return empty results
if self._monitoring_disabled:
return {}
with self._lock:
active = {}
current_time = time.time()
@@ -417,6 +425,10 @@ class PerformanceMonitor:
def get_slowest_functions(self, limit: int = 10) -> List[Dict[str, Any]]:
"""Get the slowest performing functions."""
# If monitoring is disabled, return empty results
if self._monitoring_disabled:
return []
with self._lock:
functions = []
for name, stats in self._function_stats.items():
@@ -435,6 +447,10 @@ class PerformanceMonitor:
def get_slowest_api_calls(self, limit: int = 10) -> List[Dict[str, Any]]:
"""Get the slowest performing API calls."""
# If monitoring is disabled, return empty results
if self._monitoring_disabled:
return []
with self._lock:
apis = []
for name, stats in self._api_calls.items():
@@ -539,6 +555,10 @@ class PerformanceMonitor:
def clear_statistics(self):
"""Clear all performance statistics."""
# If monitoring is disabled, nothing to clear
if self._monitoring_disabled:
return
with self._lock:
self._function_stats.clear()
self._api_calls.clear()
@@ -433,15 +433,24 @@ class MinimalTelemetry:
if posthog_client:
try:
# Include captured metrics in the event properties
event_properties = {
'version': self._environment.get('framework_version', 'unknown'),
'os': platform.system(),
'python_version': platform.python_version(),
'$process_person_profile': False,
'$geoip_disable': True,
'session_id': self.session_id
}
# Add all metrics to properties
if metrics:
event_properties.update(metrics)
posthog_client.capture(
distinct_id='anonymous',
event='sdk_used',
properties={
'version': self._environment['framework_version'],
'os': platform.system(),
'$process_person_profile': False,
'$geoip_disable': True
}
properties=event_properties
)
# Don't flush here - let PostHog handle it asynchronously
except:
@@ -691,7 +700,7 @@ def force_shutdown_telemetry():
def enable_telemetry():
"""Programmatically enable telemetry (if not disabled by environment)."""
global _telemetry_instance
if not _TELEMETRY_DISABLED:
if not _is_telemetry_disabled():
if _telemetry_instance:
_telemetry_instance.enabled = True
else:
@@ -5,6 +5,12 @@ from typing import Any
# Export Injected type for tool state injection
from .injected import Injected
# Export core tool items for organized imports
from .base import BaseTool, ToolResult, ToolValidationError, validate_tool
from .decorator import tool, FunctionTool
from .registry import get_registry, register_tool, get_tool, ToolRegistry
from .tools import Tools
# Map of function names to their module and class (if any)
TOOL_MAPPINGS = {
# Direct functions
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "praisonaiagents"
version = "0.11.8"
version = "0.11.19"
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
readme = "README.md"
requires-python = ">=3.10"
+1 -1
View File
@@ -4,7 +4,7 @@ import os
sequential_agent = Agent(
instructions="""You are a helpful assistant that can break down complex problems.
Use the available tools when relevant to perform step-by-step analysis.""",
llm="gpt-5-nano",
llm="gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
+1 -1
View File
@@ -13,7 +13,7 @@ allowed_dirs = [
filesystem_agent = Agent(
instructions="""You are a helpful assistant that can interact with the filesystem.
Use the available tools when relevant to manage files and directories.""",
llm="gpt-5-nano",
llm="gpt-4o-mini",
tools=MCP(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem"] + allowed_dirs
+1 -1
View File
@@ -5,7 +5,7 @@ from praisonaiagents import Agent
print("Creating agent...")
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
print("Starting agent...")
@@ -40,7 +40,7 @@ def test_agent_lazy_loading():
role="Assistant",
goal="Help users",
backstory="I am a helpful assistant",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
init_time = time.time() - start
print(f" Agent initialization: {init_time:.4f}s")
@@ -67,7 +67,7 @@ def test_agent_system_prompt_cache():
goal="Test caching",
backstory="I test caches",
tools=[calculator],
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# First build - no cache
@@ -98,7 +98,7 @@ def test_agent_tool_formatting_cache():
goal="Use tools",
backstory="I use tools",
tools=[calculator, sample_tool],
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# First format - no cache
@@ -412,7 +412,7 @@ def test_console_lazy_loading():
print("\n13. Testing console lazy loading across all classes...")
# Test Agent console
agent = Agent(instructions="Test", llm="gpt-5-nano")
agent = Agent(instructions="Test", llm="gpt-4o-mini")
assert agent._console is None, "Agent console should not be initialized"
console1 = agent.console
assert agent._console is not None, "Agent console should be initialized"
@@ -448,7 +448,7 @@ def test_with_openai_basic():
start = time.time()
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
agent_init = time.time() - start
print(f" Agent initialization time: {agent_init:.4f}s")
@@ -484,7 +484,7 @@ def benchmark_agent_creation(num_agents=5):
goal="Help users",
backstory="I am a helpful assistant",
tools=[calculator] if i % 2 == 0 else None, # Half with tools
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
creation_time = time.time() - start
times.append(creation_time)
+1 -1
View File
@@ -11,7 +11,7 @@ def test_agent_direct():
agent = Agent(
instructions="You are a helpful assistant that can break down complex problems.",
llm="gpt-5-nano",
llm="gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
+1 -1
View File
@@ -34,7 +34,7 @@ agent = Agent(
role="Assistant",
goal="Help with tasks",
backstory="I am a helpful assistant",
llm="gpt-5-nano", # Using a simple model for testing
llm="gpt-4o-mini", # Using a simple model for testing
verbose=False
)
@@ -43,7 +43,7 @@ def test_single_display_no_tools():
MagicMock(choices=[MagicMock(delta=MagicMock(content="!"))])
]
llm = LLM(model="gpt-5-nano", verbose=False)
llm = LLM(model="gpt-4o-mini", verbose=False)
response = llm.get_response(
prompt="Test prompt",
verbose=True,
@@ -139,7 +139,7 @@ def test_single_display_with_self_reflection():
mock_completion.side_effect = mock_streaming
llm = LLM(model="gpt-5-nano", verbose=False, self_reflect=True, min_reflect=1, max_reflect=2)
llm = LLM(model="gpt-4o-mini", verbose=False, self_reflect=True, min_reflect=1, max_reflect=2)
response = llm.get_response(
prompt="Test prompt",
verbose=True,
@@ -179,7 +179,7 @@ def test_async_single_display():
mock_acompletion.return_value = async_generator()
llm = LLM(model="gpt-5-nano", verbose=False)
llm = LLM(model="gpt-4o-mini", verbose=False)
response = await llm.get_response_async(
prompt="Test async",
verbose=True,
+1 -1
View File
@@ -14,7 +14,7 @@ def test_self_reflection_fix():
goal="Solve math problems accurately",
backstory="You are a helpful math assistant",
self_reflect=True,
llm="gpt-5-nano", # Use a more widely available model
llm="gpt-4o-mini", # Use a more widely available model
verbose=True,
tools=[evaluate],
min_reflect=1,
@@ -24,7 +24,7 @@ test_agent = Agent(
role="Test Agent",
goal="Test the fix",
tools=[simple_tool],
llm="gpt-5-nano", # Using OpenAI for testing
llm="gpt-4o-mini", # Using OpenAI for testing
verbose=False # This is key - verbose=False triggers the bug
)
+22
View File
@@ -0,0 +1,22 @@
"""Test full agent flow with new verbose UI."""
from praisonaiagents import Agent
# Create agent - use output preset for verbose mode
agent = Agent(
name="AIAssistant",
role="Helpful AI",
instructions="You are a helpful assistant. Be concise and give short answers.",
output="verbose", # Use output preset instead of verbose kwarg
)
if __name__ == "__main__":
print("\n" + "=" * 60)
print("TESTING FULL AGENT FLOW WITH NEW UI")
print("=" * 60 + "\n")
# Use start() which should show verbose output
result = agent.start("What is the capital of France? One sentence only.")
print("\n" + "=" * 60)
print(f"FINAL RESULT: {result}")
print("=" * 60)
@@ -29,7 +29,7 @@ def test_gemini_embedding():
role="Memory Tester",
goal="Test memory storage with embeddings",
backstory="An agent that tests memory functionality",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create a task
@@ -60,7 +60,7 @@ def test_gemini_embedding():
role="Memory Tester",
goal="Test memory storage with explicit OpenAI embeddings",
backstory="An agent that tests memory functionality",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
task2 = Task(
@@ -95,7 +95,7 @@ def test_gemini_embedding():
role="Memory Tester with Gemini",
goal="Test memory storage with Gemini embeddings",
backstory="An agent that tests Gemini embedding functionality",
llm="gpt-5-nano" # Still use GPT for chat, but Gemini for embeddings
llm="gpt-4o-mini" # Still use GPT for chat, but Gemini for embeddings
)
task3 = Task(
@@ -51,7 +51,7 @@ def test_guardrail_return_types():
role="Tester",
goal="Test guardrails",
backstory="Testing guardrail functionality",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Test creating tasks with each guardrail type
@@ -105,7 +105,7 @@ def test_guardrail_result_handling():
role="Tester",
goal="Test guardrails",
backstory="Testing guardrail functionality",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
test_output = TaskOutput(
+1 -1
View File
@@ -13,7 +13,7 @@ langtrace.init(
def example():
client = OpenAI()
response = client.chat.completions.create(
model="gpt-5-nano",
model="gpt-4o-mini",
messages=[
{
"role": "system",
+2 -2
View File
@@ -58,7 +58,7 @@ def test_router_agent():
name="Test Agent",
role="Test Assistant",
goal="Test multi-model functionality",
models=["gpt-5-nano"], # Using single model for testing
models=["gpt-4o-mini"], # Using single model for testing
routing_strategy="auto",
verbose=False
)
@@ -86,7 +86,7 @@ def test_integration():
name="Integration Test Agent",
role="Tester",
goal="Test the integration",
models=["gpt-5-nano"], # Single model for testing
models=["gpt-4o-mini"], # Single model for testing
routing_strategy="manual", # Use manual to avoid complexity
verbose=False
)
+3 -3
View File
@@ -41,7 +41,7 @@ def test_ollama_provider_detection():
return False
# Test non-Ollama provider
openai_llm = LLM(model="gpt-5-nano")
openai_llm = LLM(model="gpt-4o-mini")
is_not_ollama = not openai_llm._is_ollama_provider()
if is_not_ollama:
@@ -99,7 +99,7 @@ def test_tool_summary_generation():
return False
# Test with non-Ollama model (should NOT generate summary)
non_ollama_llm = LLM(model="gpt-5-nano")
non_ollama_llm = LLM(model="gpt-4o-mini")
summary_non_ollama = non_ollama_llm._generate_ollama_tool_summary(tool_results, "")
if summary_non_ollama is None:
print("✅ Tool summary generation correctly skips non-Ollama models")
@@ -120,7 +120,7 @@ def test_backward_compatibility():
# Test that non-Ollama providers aren't affected
models_to_test = [
"gpt-5-nano",
"gpt-4o-mini",
"claude-3-sonnet",
"gemini/gemini-2.5-pro"
]
+1 -2
View File
@@ -10,8 +10,7 @@ try:
posthog_client = Posthog(
project_api_key='phc_skZpl3eFLQJ4iYjsERNMbCO6jfeSJi2vyZlPahKgxZ7',
host='https://eu.i.posthog.com',
disable_geoip=True,
events_to_ignore=['test-event']
disable_geoip=True
)
print(f"✅ PostHog client created: {posthog_client}")
except Exception as e:
+4 -4
View File
@@ -34,17 +34,17 @@ except Exception as e:
print(f"❌ PostHog capture failed: {e}")
print("\n4. Testing telemetry module...")
from praisonaiagents.telemetry.telemetry import MinimalTelemetry, POSTHOG_AVAILABLE
print(f"POSTHOG_AVAILABLE in telemetry module: {POSTHOG_AVAILABLE}")
from praisonaiagents.telemetry.telemetry import MinimalTelemetry
print("✅ MinimalTelemetry imported successfully")
print("\n5. Creating MinimalTelemetry instance...")
telemetry = MinimalTelemetry(enabled=True)
print(f"Telemetry enabled: {telemetry.enabled}")
print(f"Telemetry _posthog: {telemetry._posthog}")
print(f"Telemetry has _posthog: {hasattr(telemetry, '_posthog') and telemetry._posthog is not None}")
print("\n6. Checking get_telemetry()...")
from praisonaiagents.telemetry import get_telemetry
global_telemetry = get_telemetry()
print(f"Global telemetry enabled: {global_telemetry.enabled}")
print(f"Global telemetry _posthog: {global_telemetry._posthog}")
print(f"Global telemetry has _posthog: {hasattr(global_telemetry, '_posthog') and global_telemetry._posthog is not None}")
print(f"Global telemetry session_id: {global_telemetry.session_id}")
+1 -1
View File
@@ -53,7 +53,7 @@ def test_real_streaming():
role="Testing Assistant",
goal="Test streaming behavior",
backstory="I am a test agent for verifying streaming functionality.",
llm="gpt-5-nano", # You can change this to test other providers
llm="gpt-4o-mini", # You can change this to test other providers
stream=test_case["stream"],
verbose=test_case["verbose"]
)
+3 -3
View File
@@ -10,7 +10,7 @@ def test_agent_self_reflection():
agent = Agent(
name="ReflectiveAgent",
instructions="You are a helpful assistant.",
llm="gpt-5-nano",
llm="gpt-4o-mini",
self_reflect=True,
min_reflect=1,
max_reflect=3
@@ -23,7 +23,7 @@ def test_agent_self_reflection():
def test_llm_self_reflection():
"""Test self-reflection in LLM class directly"""
print("=== Testing LLM Self-Reflection ===")
llm = LLM(model="gpt-5-nano")
llm = LLM(model="gpt-4o-mini")
response = llm.get_response(
prompt="What is 2+2? Be brief.",
@@ -39,7 +39,7 @@ def test_llm_self_reflection():
def test_llm_no_reflection():
"""Test LLM without self-reflection for comparison"""
print("=== Testing LLM Without Self-Reflection ===")
llm = LLM(model="gpt-5-nano")
llm = LLM(model="gpt-4o-mini")
response = llm.get_response(
prompt="What is 2+2? Be brief.",
@@ -36,7 +36,7 @@ def test_self_reflection_with_tools():
goal="Analyze and provide insights on given topics",
backstory="You are an expert analyst with strong critical thinking skills",
self_reflect=True,
llm="gpt-5-nano", # Using OpenAI model for testing
llm="gpt-4o-mini", # Using OpenAI model for testing
verbose=True,
tools=[mock_tool],
max_reflect=2, # Keep it small for testing
@@ -76,7 +76,7 @@ def test_self_reflection_without_tools():
goal="Analyze and provide insights on given topics",
backstory="You are an expert analyst with strong critical thinking skills",
self_reflect=True,
llm="gpt-5-nano", # Using OpenAI model for testing
llm="gpt-4o-mini", # Using OpenAI model for testing
verbose=True,
max_reflect=2, # Keep it small for testing
min_reflect=1
@@ -115,7 +115,7 @@ def test_llm_directly():
mock_tool = create_mock_tool()
# Create LLM instance
llm = LLM(model="gpt-5-nano")
llm = LLM(model="gpt-4o-mini")
def mock_tool_executor(function_name, arguments):
"""Mock tool executor that simulates tool execution"""
@@ -26,7 +26,7 @@ def simple_calculator(operation: str, a: int, b: int) -> int:
def test_llm_self_reflection_with_tools():
"""Test self-reflection in LLM class directly with tools"""
print("=== Testing LLM Self-Reflection WITH Tools ===")
llm = LLM(model="gpt-5-nano")
llm = LLM(model="gpt-4o-mini")
def mock_tool_executor(function_name, arguments):
"""Mock tool executor for testing"""
@@ -54,7 +54,7 @@ def test_llm_self_reflection_with_tools():
def test_llm_self_reflection_without_tools():
"""Test self-reflection in LLM class directly without tools"""
print("=== Testing LLM Self-Reflection WITHOUT Tools ===")
llm = LLM(model="gpt-5-nano")
llm = LLM(model="gpt-4o-mini")
response = llm.get_response(
prompt="Calculate 5 + 3 and then reflect on your answer",
@@ -73,7 +73,7 @@ def test_agent_self_reflection_with_tools():
agent = Agent(
name="CalculatorAgent",
instructions="You are a helpful assistant with access to a calculator tool.",
llm="gpt-5-nano",
llm="gpt-4o-mini",
self_reflect=True,
min_reflect=1,
max_reflect=2,
@@ -90,7 +90,7 @@ def test_agent_self_reflection_without_tools():
agent = Agent(
name="BasicAgent",
instructions="You are a helpful assistant.",
llm="gpt-5-nano",
llm="gpt-4o-mini",
self_reflect=True,
min_reflect=1,
max_reflect=2
+1 -1
View File
@@ -11,7 +11,7 @@ def test_agent_direct():
agent = Agent(
instructions="You are a helpful assistant that can break down complex problems.",
llm="gpt-5-nano",
llm="gpt-4o-mini",
tools=MCP("npx -y @modelcontextprotocol/server-sequential-thinking")
)
@@ -19,7 +19,7 @@ def test_stream_parameter():
role="Test Assistant",
goal="Test streaming behavior",
backstory="A test agent for verifying stream parameter handling",
llm="gpt-5-nano",
llm="gpt-4o-mini",
stream=True, # Default to streaming
verbose=True
)
@@ -50,7 +50,7 @@ def test_stream_parameter():
role="Test Assistant 2",
goal="Test non-streaming behavior",
backstory="A test agent for verifying non-stream parameter handling",
llm="gpt-5-nano",
llm="gpt-4o-mini",
stream=False, # Default to non-streaming
verbose=True
)
@@ -15,14 +15,14 @@ def test_streaming_behavior():
test_cases = [
{
"name": "OpenAI - Stream True",
"llm": "gpt-5-nano",
"llm": "gpt-4o-mini",
"stream": True,
"verbose": True,
"expected": "Should show real-time streaming"
},
{
"name": "OpenAI - Stream False",
"llm": "gpt-5-nano",
"llm": "gpt-4o-mini",
"stream": False,
"verbose": True,
"expected": "Should show 'Generating...' animation during API call"
+3 -3
View File
@@ -19,7 +19,7 @@ def test_streaming_logic():
print("1. Testing default agent (no stream parameter)...")
agent1 = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
print(f" ✅ Agent created successfully")
@@ -35,7 +35,7 @@ def test_streaming_logic():
print("\n2. Testing explicit stream=False...")
agent2 = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano",
llm="gpt-4o-mini",
stream=False
)
@@ -52,7 +52,7 @@ def test_streaming_logic():
print("\n3. Testing explicit stream=True...")
agent3 = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano",
llm="gpt-4o-mini",
stream=True
)
+1 -1
View File
@@ -26,7 +26,7 @@ try:
# Create agent with minimal setup
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
print(f"[{datetime.now()}] Agent created successfully")
@@ -21,7 +21,7 @@ agent = Agent(
role="Tester",
goal="Test telemetry",
backstory="I test things",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
task = Task(
@@ -60,7 +60,7 @@ new_agent = Agent(
role="Tester",
goal="Test auto telemetry",
backstory="I test auto-instrumentation",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
print(f" New agent instrumented: {hasattr(new_agent.execute, '__wrapped__')}")
@@ -21,7 +21,7 @@ try:
role="Test Role",
goal="Test Goal",
backstory="Test backstory",
llm="gpt-5-nano",
llm="gpt-4o-mini",
metrics=True,
base_url="http://localhost:1234/v1", # Use local URL to trigger LLM instance creation
api_key="test-key"
@@ -51,7 +51,7 @@ try:
role="Test Role",
goal="Test Goal",
backstory="Test backstory",
llm={"model": "gpt-5-nano", "base_url": "http://localhost:1234/v1"},
llm={"model": "gpt-4o-mini", "base_url": "http://localhost:1234/v1"},
metrics=True,
api_key="test-key"
)
@@ -25,7 +25,7 @@ def test_user_code_pattern_with_tools():
goal="Analyze and provide insights on given topics",
backstory="You are an expert analyst with strong critical thinking skills",
self_reflect=True,
llm="gpt-5-nano", # Using OpenAI instead of Gemini for testing
llm="gpt-4o-mini", # Using OpenAI instead of Gemini for testing
verbose=True,
tools=[google_web_search_llm]
)
@@ -67,7 +67,7 @@ def test_user_code_pattern_without_tools():
goal="Analyze and provide insights on given topics",
backstory="You are an expert analyst with strong critical thinking skills",
self_reflect=True,
llm="gpt-5-nano", # Using OpenAI instead of Gemini for testing
llm="gpt-4o-mini", # Using OpenAI instead of Gemini for testing
verbose=True
)
@@ -21,7 +21,7 @@ def test_combination(verbose: bool, stream: bool, test_name: str):
role="Test Assistant",
goal="Test display behavior",
backstory="A test agent",
llm="gpt-5-nano",
llm="gpt-4o-mini",
verbose=verbose,
stream=stream
)
@@ -52,7 +52,7 @@ def main():
role="Test Assistant",
goal="Test display behavior",
backstory="A test agent",
llm="gpt-5-nano",
llm="gpt-4o-mini",
verbose=True,
stream=True # Agent default is streaming
)
+112
View File
@@ -0,0 +1,112 @@
"""Test script with forced verbose mode to verify PraisonAI's unique output UI."""
import sys
from rich.console import Console
# Force Rich to think we're in a TTY for testing
console = Console(force_terminal=True)
from praisonaiagents import Agent
from praisonaiagents.main import (
display_interaction,
display_instruction,
display_tool_call,
display_reasoning_steps,
display_working_status,
display_error,
PRAISON_COLORS
)
print("=" * 70)
print("TESTING PRAISONAI UNIQUE VERBOSE OUTPUT UI")
print("=" * 70)
# Test 1: Display Agent Info panel
print("\n[TEST 1] Agent Info Panel (Sage Green border)")
display_instruction(
message="Test instruction",
console=console,
agent_name="ResearchAgent",
agent_role="Data Analyst",
agent_tools=["search_web", "calculate", "read_file"]
)
# Test 2: Display interaction with semantic colors
print("\n[TEST 2] Task (Coral) + Response (Ocean Blue) panels")
display_interaction(
message="What is 2+2?",
response="2+2 equals 4. This is a basic arithmetic operation.",
markdown=True,
generation_time=1.5,
console=console
)
# Test 3: Display interaction with metrics footer
print("\n[TEST 3] Response with Metrics Footer")
display_interaction(
message="Explain quantum computing",
response="Quantum computing uses qubits instead of classical bits.",
markdown=True,
generation_time=3.2,
console=console,
metrics={
'tokens_in': 45,
'tokens_out': 128,
'cost': 0.0023,
'model': 'gpt-4o-mini'
}
)
# Test 4: Display tool call with timeline format
print("\n[TEST 4] Tool Activity Panel (Violet border, timeline format)")
display_tool_call(
message="search_web(query='quantum computing')",
console=console,
tool_name="search_web",
tool_input={"query": "quantum computing"},
tool_output="Found 5 relevant articles",
elapsed_time=0.8,
success=True
)
# Test 5: Display tool call failure
print("\n[TEST 5] Tool Activity Panel (Failed call)")
display_tool_call(
message="api_call failed",
console=console,
tool_name="api_call",
tool_input={"endpoint": "/users", "method": "GET"},
tool_output="Connection timeout",
elapsed_time=5.0,
success=False
)
# Test 6: Display reasoning steps with numbered circles
print("\n[TEST 6] Reasoning Steps (Numbered circles ①②③)")
display_reasoning_steps(
steps=[
"Identified query about arithmetic",
"Retrieved basic math rules",
"Calculated result: 2+2=4",
"Formulated concise response"
],
console=console
)
# Test 7: Display working status (static, shows format)
print("\n[TEST 7] Working Status (Amber border, pulsing dots)")
for phase in range(4):
panel = display_working_status(phase=phase, console=console)
console.print(panel)
# Test 8: Display error
print("\n[TEST 8] Error Panel (Red border)")
display_error(
message="API rate limit exceeded. Please try again in 60 seconds.",
console=console
)
print("\n" + "=" * 70)
print("COLORS BEING USED:")
for name, color in PRAISON_COLORS.items():
console.print(f" {name}: [bold {color}]████████[/] {color}")
print("=" * 70)
+1 -1
View File
@@ -13,7 +13,7 @@ try:
print("✅ Import successful!")
print("Testing Agent creation...")
agent = praisonaiagents.Agent(instructions="Test agent", llm="gpt-5-nano")
agent = praisonaiagents.Agent(instructions="Test agent", llm="gpt-4o-mini")
print("✅ Agent created successfully!")
except Exception as e:
@@ -18,7 +18,7 @@ def main():
backstory="You are a knowledgeable assistant who explains scientific concepts clearly.",
instructions="You are a helpful assistant",
verbose=True,
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
# Create a task to answer the question
+1 -1
View File
@@ -2,7 +2,7 @@ from praisonaiagents import Agent
agent = Agent(
instructions="You are a helpful assistant",
llm="gpt-5-nano"
llm="gpt-4o-mini"
)
agent.start("Why sky is Blue?")
@@ -23,13 +23,13 @@ def code_interpreter(code: str):
code_agent = Agent(
name="code_agent",
llm="gpt-5-nano",
llm="gpt-4o-mini",
backstory="Expert in writing Python scripts",
self_reflect=False
)
execution_agent = Agent(
name="execution_agent",
llm="gpt-5-nano",
llm="gpt-4o-mini",
backstory="Expert in executing Python scripts",
self_reflect=False,
tools=[code_interpreter]
@@ -8,7 +8,7 @@ cot_agent = Agent(
goal="Generate and manage chain of thought solutions for Q&A pairs",
backstory="Expert in breaking down problems and generating detailed solution steps",
tools=[cot_save],
llm="gpt-5-nano", # Using recommended model
llm="gpt-4o-mini", # Using recommended model
)
save_to_huggingface_agent = Agent(
@@ -17,7 +17,7 @@ save_to_huggingface_agent = Agent(
goal="Save the generated chain of thought solutions to a Huggingface dataset",
backstory="Expert in saving data to Huggingface",
tools=[cot_upload_to_huggingface],
llm="gpt-5-nano", # Using recommended model
llm="gpt-4o-mini", # Using recommended model
)
# Define question-answer pairs to process in batches
Loaded 100 of 179 files, more files were not shown because too many files have changed in this diff. Show more