diff --git a/README.md b/README.md index 63e4ff625..08b993428 100644 --- a/README.md +++ b/README.md @@ -538,11 +538,11 @@ python app.py Create app.py file and add the code below: ```python -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents research_agent = Agent(instructions="Research about AI") summarise_agent = Agent(instructions="Summarise research agent's findings") -agents = PraisonAIAgents(agents=[research_agent, summarise_agent]) +agents = Agents(agents=[research_agent, summarise_agent]) agents.start() ``` @@ -3380,11 +3380,11 @@ See [Agent Memory](#6-agent-memory-zero-dependencies) for more options. How do I run multiple agents together? ```python -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents agent1 = Agent(instructions="Research topics") agent2 = Agent(instructions="Summarize findings") -agents = PraisonAIAgents(agents=[agent1, agent2]) +agents = Agents(agents=[agent1, agent2]) agents.start() ``` diff --git a/docker/Dockerfile.chat b/docker/Dockerfile.chat index be3c9f351..42b022156 100644 --- a/docker/Dockerfile.chat +++ b/docker/Dockerfile.chat @@ -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.4.0" \ + "praisonai>=3.4.1" \ "praisonai[chat]" \ "embedchain[github,youtube]" diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev index a334a018e..3d642dbc3 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -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.4.0" \ + "praisonai>=3.4.1" \ "praisonai[ui]" \ "praisonai[chat]" \ "praisonai[realtime]" \ diff --git a/docker/Dockerfile.ui b/docker/Dockerfile.ui index 08bcdc084..ec35df3bf 100644 --- a/docker/Dockerfile.ui +++ b/docker/Dockerfile.ui @@ -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.4.0" \ + "praisonai>=3.4.1" \ "praisonai[ui]" \ "praisonai[crewai]" diff --git a/examples/context/09_context_budgeting.py b/examples/context/09_context_budgeting.py index ebedd5fa8..993dd9eaa 100644 --- a/examples/context/09_context_budgeting.py +++ b/examples/context/09_context_budgeting.py @@ -189,8 +189,8 @@ def main(): print("-" * 40) print("Auto-agents mode default: context=False (zero overhead)") print("To enable for multi-agent workflows:") - print(" from praisonaiagents import PraisonAIAgents") - print(" agents = PraisonAIAgents(agents=[...], context=True)") + print(" from praisonaiagents import Agents") + print(" agents = Agents(agents=[...], context=True)") print("") print("Recommended config for long tasks:") print(" context=ManagerConfig(") diff --git a/examples/context/12_multi_agent_context.py b/examples/context/12_multi_agent_context.py index 1f3027bc2..bfa811fb5 100644 --- a/examples/context/12_multi_agent_context.py +++ b/examples/context/12_multi_agent_context.py @@ -2,14 +2,14 @@ """ Multi-Agent Context Isolation Example -Demonstrates how to use multi-agent context with PraisonAIAgents via context= param, +Demonstrates how to use multi-agent context with Agents via context= param, and also shows low-level MultiAgentLedger usage for advanced scenarios. Agent-Centric Quick Start: - from praisonaiagents import Agent, PraisonAIAgents + from praisonaiagents import Agent, Agents from praisonaiagents.context import ManagerConfig - agents = PraisonAIAgents( + agents = Agents( agents=[agent1, agent2], context=ManagerConfig(policy="isolated"), # or "shared" ) @@ -17,7 +17,7 @@ Agent-Centric Quick Start: import os import tempfile -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from praisonaiagents.context import ( ManagerConfig, MultiAgentLedger, @@ -49,7 +49,7 @@ def agent_centric_example(): # Multi-agent setup with isolated context policy # (each agent maintains its own context) print("Created agents with context=True") - print("Use PraisonAIAgents(agents=[...], context=ManagerConfig(policy='isolated'))") + print("Use Agents(agents=[...], context=ManagerConfig(policy='isolated'))") print("for multi-agent context isolation") diff --git a/examples/context/14_agent_context_param.py b/examples/context/14_agent_context_param.py index 8c7e4a5ad..1b6c6eaf2 100644 --- a/examples/context/14_agent_context_param.py +++ b/examples/context/14_agent_context_param.py @@ -156,7 +156,7 @@ def example_5_multi_agent(): print("Example 5: Multi-Agent Context Management") print("=" * 60) - from praisonaiagents import PraisonAIAgents, Task + from praisonaiagents import Agents, Task config = ManagerConfig( auto_compact=True, @@ -181,7 +181,7 @@ def example_5_multi_agent(): task2 = Task(description="Write a summary", agent=writer) # Create multi-agent system with context management - agents = PraisonAIAgents( + agents = Agents( agents=[researcher, writer], tasks=[task1, task2], context=config, # Shared context config diff --git a/examples/guardrail_example_fixed.py b/examples/guardrail_example_fixed.py index fd298f0af..70fc5e623 100644 --- a/examples/guardrail_example_fixed.py +++ b/examples/guardrail_example_fixed.py @@ -4,7 +4,7 @@ Fixed example demonstrating proper guardrail usage with PraisonAI Agents. This addresses the issues reported in issue #875. """ -from praisonaiagents import Agent, Task, GuardrailResult, PraisonAIAgents, TaskOutput +from praisonaiagents import Agent, Task, GuardrailResult, Agents, TaskOutput from typing import Tuple, Any import trafilatura @@ -103,7 +103,7 @@ task_with_llm_guardrail = Task( # Run with GuardrailResult example print("=== Running with GuardrailResult guardrail ===") -agents_gr = PraisonAIAgents( +agents_gr = Agents( agents=[agent], tasks=[task_with_guardrailresult] ) @@ -113,7 +113,7 @@ agents_gr = PraisonAIAgents( # Run with Tuple example print("\n=== Running with Tuple[bool, Any] guardrail ===") -agents_tuple = PraisonAIAgents( +agents_tuple = Agents( agents=[agent], tasks=[task_with_tuple] ) @@ -123,7 +123,7 @@ agents_tuple = PraisonAIAgents( # Run with LLM guardrail example print("\n=== Running with LLM-based guardrail ===") -agents_llm = PraisonAIAgents( +agents_llm = Agents( agents=[agent], tasks=[task_with_llm_guardrail] ) diff --git a/examples/observability/multi_agent_tracing.py b/examples/observability/multi_agent_tracing.py index 8dec199b8..da6a994f3 100644 --- a/examples/observability/multi_agent_tracing.py +++ b/examples/observability/multi_agent_tracing.py @@ -14,7 +14,7 @@ Usage: from praisonai_tools.observability import obs from praisonai_tools.observability.base import SpanKind -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents # Initialize observability obs.init() diff --git a/examples/output_ux/basic_output_example.py b/examples/output_ux/basic_output_example.py index 689314dc2..66929467b 100644 --- a/examples/output_ux/basic_output_example.py +++ b/examples/output_ux/basic_output_example.py @@ -13,7 +13,7 @@ Features demonstrated: import sys sys.path.insert(0, '/Users/praison/praisonai-package/src/praisonai-agents') -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents def get_weather(city: str) -> str: @@ -106,7 +106,7 @@ def example_multi_agent(): agent=writer ) - agents = PraisonAIAgents( + agents = Agents( agents=[researcher, writer], tasks=[task1, task2], process="sequential", diff --git a/examples/python/agents/autoagents-hierarchical-generation.py b/examples/python/agents/autoagents-hierarchical-generation.py index e21ab0967..d6213a2d2 100644 --- a/examples/python/agents/autoagents-hierarchical-generation.py +++ b/examples/python/agents/autoagents-hierarchical-generation.py @@ -5,7 +5,7 @@ This example demonstrates hierarchical agent patterns using PraisonAI for structured task delegation and coordinated workflows. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import internet_search print("=== AutoAgents Hierarchical Generation Example ===\n") @@ -58,7 +58,7 @@ execution_task = Task( ) # Run hierarchical workflow -agents_system = PraisonAIAgents( +agents_system = Agents( agents=[manager_agent, research_agent], tasks=[planning_task, execution_task], process="sequential", diff --git a/examples/python/agents/code-agent.py b/examples/python/agents/code-agent.py index 241940950..98f9e98ec 100644 --- a/examples/python/agents/code-agent.py +++ b/examples/python/agents/code-agent.py @@ -5,7 +5,7 @@ This example demonstrates a comprehensive code agent that can write, analyze, de It includes self-reflection for improving code quality and multiple specialized tools. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import CodeInterpreter # Initialize code execution tool @@ -84,7 +84,7 @@ def demonstrate_code_agent(): ) # Create workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[code_writer, code_reviewer, code_executor], tasks=[write_task, review_task, execute_task], process="sequential", diff --git a/examples/python/agents/image-agent.py b/examples/python/agents/image-agent.py index f784482a5..6d5a15471 100644 --- a/examples/python/agents/image-agent.py +++ b/examples/python/agents/image-agent.py @@ -4,7 +4,7 @@ from praisonaiagents.tools import duckduckgo agent = Agent(instructions="You are a Image Analysis Agent", tools=[duckduckgo]) agent.start("I want to go London next week, find me a good hotel and flight") -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create Image Analysis Agent image_agent = Agent( @@ -35,8 +35,8 @@ task2 = Task( images=["image.jpg"] ) -# Create PraisonAIAgents instance -agents = PraisonAIAgents( +# Create Agents instance +agents = Agents( agents=[image_agent], tasks=[task1, task2], process="sequential", diff --git a/examples/python/agents/image-to-text-agent.py b/examples/python/agents/image-to-text-agent.py index f784482a5..6d5a15471 100644 --- a/examples/python/agents/image-to-text-agent.py +++ b/examples/python/agents/image-to-text-agent.py @@ -4,7 +4,7 @@ from praisonaiagents.tools import duckduckgo agent = Agent(instructions="You are a Image Analysis Agent", tools=[duckduckgo]) agent.start("I want to go London next week, find me a good hotel and flight") -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create Image Analysis Agent image_agent = Agent( @@ -35,8 +35,8 @@ task2 = Task( images=["image.jpg"] ) -# Create PraisonAIAgents instance -agents = PraisonAIAgents( +# Create Agents instance +agents = Agents( agents=[image_agent], tasks=[task1, task2], process="sequential", diff --git a/examples/python/agents/math-agent.py b/examples/python/agents/math-agent.py index 211000ff5..3e838ae8e 100644 --- a/examples/python/agents/math-agent.py +++ b/examples/python/agents/math-agent.py @@ -5,7 +5,7 @@ This example demonstrates a mathematical problem-solving agent that can handle v including calculations, equation solving, and step-by-step explanations. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import Dict, Any import math import re @@ -123,7 +123,7 @@ def solve_math_problem_workflow(): context=[solve_task] ) - workflow = PraisonAIAgents( + workflow = Agents( agents=[problem_solver_agent, calculation_agent, math_tutor_agent], tasks=[understand_task, solve_task, verify_task], process="sequential", diff --git a/examples/python/agents/multi-provider-agent.py b/examples/python/agents/multi-provider-agent.py index b5672e1e4..582824238 100644 --- a/examples/python/agents/multi-provider-agent.py +++ b/examples/python/agents/multi-provider-agent.py @@ -6,7 +6,7 @@ agent-based selection for cost optimization and performance. """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.agent import RouterAgent from praisonaiagents.llm.model_router import ModelRouter, ModelProfile, TaskComplexity @@ -49,7 +49,7 @@ def example_auto_routing(): ) # Run the tasks - agents = PraisonAIAgents( + agents = Agents( agents=[research_agent], tasks=[simple_task, moderate_task, complex_task], process="sequential", @@ -118,7 +118,7 @@ def example_cost_optimized_workflow(): ) # Run workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[analyzer, writer], tasks=[analysis_task, writing_task], process="sequential", @@ -249,7 +249,7 @@ def example_custom_routing(): ] # Run tasks - agents = PraisonAIAgents( + agents = Agents( agents=[coder], tasks=tasks, process="sequential", diff --git a/examples/python/agents/video-agent.py b/examples/python/agents/video-agent.py index 3dde39737..8087bc9ad 100644 --- a/examples/python/agents/video-agent.py +++ b/examples/python/agents/video-agent.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create Video Analysis Agent video_agent = Agent( @@ -24,8 +24,8 @@ task1 = Task( images=["video.mp4"] ) -# Create PraisonAIAgents instance -agents = PraisonAIAgents( +# Create Agents instance +agents = Agents( agents=[video_agent], tasks=[task1], process="sequential", diff --git a/examples/python/agents/wikipedia-agent.py b/examples/python/agents/wikipedia-agent.py index fdf9643f1..85fb1cf19 100644 --- a/examples/python/agents/wikipedia-agent.py +++ b/examples/python/agents/wikipedia-agent.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import wiki_search, wiki_summary, wiki_page, wiki_random, wiki_language agent = Agent( diff --git a/examples/python/api/secondary-market-research-api.py b/examples/python/api/secondary-market-research-api.py index f18f38b1c..b1041a1f9 100644 --- a/examples/python/api/secondary-market-research-api.py +++ b/examples/python/api/secondary-market-research-api.py @@ -32,7 +32,7 @@ import os from pathlib import Path # Import our market research system -from praisonaiagents import Agent, Task, PraisonAIAgents, Tools +from praisonaiagents import Agent, Task, Agents, Tools # Create FastAPI app app = FastAPI( @@ -266,7 +266,7 @@ async def generate_market_research_report(job_id: str, config: MarketResearchCon job_status[job_id]["message"] = "Setting up research workflow..." # Create workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=list(agents.values()), tasks=tasks, process="sequential", diff --git a/examples/python/camera/camera-basic.py b/examples/python/camera/camera-basic.py index a92a51d4b..59d80894d 100644 --- a/examples/python/camera/camera-basic.py +++ b/examples/python/camera/camera-basic.py @@ -16,7 +16,7 @@ Environment Variables: import cv2 import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents def capture_and_analyze(): @@ -58,7 +58,7 @@ def capture_and_analyze(): ) # Run analysis - agents = PraisonAIAgents( + agents = Agents( agents=[vision_agent], tasks=[task], process="sequential", diff --git a/examples/python/camera/camera-continuous.py b/examples/python/camera/camera-continuous.py index 774ddf896..3dd147198 100644 --- a/examples/python/camera/camera-continuous.py +++ b/examples/python/camera/camera-continuous.py @@ -18,7 +18,7 @@ import cv2 import time import os from datetime import datetime -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents class ContinuousCameraMonitor: @@ -71,7 +71,7 @@ class ContinuousCameraMonitor: images=[image_path] ) - agents = PraisonAIAgents( + agents = Agents( agents=[self.vision_agent], tasks=[task], process="sequential", diff --git a/examples/python/camera/camera-multi-agent.py b/examples/python/camera/camera-multi-agent.py index 77734915a..b03ab6bce 100644 --- a/examples/python/camera/camera-multi-agent.py +++ b/examples/python/camera/camera-multi-agent.py @@ -17,7 +17,7 @@ Environment Variables: import cv2 import os from datetime import datetime -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents def capture_camera_frame(camera_id=0): @@ -114,7 +114,7 @@ def analyze_with_multiple_agents(): ) # Run multi-agent analysis - agents = PraisonAIAgents( + agents = Agents( agents=[security_agent, object_detector, scene_analyst], tasks=[security_task, object_task, scene_task], process="parallel", # Run all analyses in parallel diff --git a/examples/python/camera/camera-video-analysis.py b/examples/python/camera/camera-video-analysis.py index 57840cbab..55c62abce 100644 --- a/examples/python/camera/camera-video-analysis.py +++ b/examples/python/camera/camera-video-analysis.py @@ -18,7 +18,7 @@ import cv2 import os import time from datetime import datetime -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents class CameraVideoAnalyzer: @@ -131,7 +131,7 @@ class CameraVideoAnalyzer: images=[video_path] # PraisonAI supports video files in images parameter ) - agents = PraisonAIAgents( + agents = Agents( agents=[self.video_agent], tasks=[task], process="sequential", diff --git a/examples/python/concepts/context-engineering-workflow.py b/examples/python/concepts/context-engineering-workflow.py index 0e25b758d..e2082d93e 100644 --- a/examples/python/concepts/context-engineering-workflow.py +++ b/examples/python/concepts/context-engineering-workflow.py @@ -24,7 +24,7 @@ from pathlib import Path project_root = Path(__file__).parent.parent.parent.parent / "src" / "praisonai-agents" sys.path.insert(0, str(project_root)) -from praisonaiagents import Agent, Task, PraisonAIAgents, create_context_agent +from praisonaiagents import Agent, Task, Agents, create_context_agent class ContextEngineeringWorkflow: """ @@ -312,7 +312,7 @@ class ContextEngineeringWorkflow: print("\nāš™ļø Executing Context Engineering Workflow") print("-" * 50) - agents_workflow = PraisonAIAgents( + agents_workflow = Agents( agents=[ self.product_manager, self.architect, diff --git a/examples/python/concepts/csv-processing-agents.py b/examples/python/concepts/csv-processing-agents.py index a5558b6e3..ed0f04e6d 100644 --- a/examples/python/concepts/csv-processing-agents.py +++ b/examples/python/concepts/csv-processing-agents.py @@ -11,7 +11,7 @@ Author: Generated for GitHub Issue #23 """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import read_csv, write_csv def create_sample_urls_csv(): @@ -81,7 +81,7 @@ def method_1_simple_loop(): ) # Initialize the agents system - agents = PraisonAIAgents( + agents = Agents( agents=[loop_agent], tasks=[loop_task], process="workflow", @@ -145,7 +145,7 @@ def method_2_manual_csv(): ) # Initialize and run - agents = PraisonAIAgents( + agents = Agents( agents=[csv_agent], tasks=[csv_task], process="sequential" @@ -211,7 +211,7 @@ def method_3_url_processing(): ) # Initialize and run - agents = PraisonAIAgents( + agents = Agents( agents=[url_agent], tasks=[url_task], process="sequential" @@ -319,7 +319,7 @@ def method_4_advanced_processing(): ) # Initialize and run with sequential processing - agents = PraisonAIAgents( + agents = Agents( agents=[validator_agent, processor_agent], tasks=[validation_task, processing_task], process="sequential" # Validation must complete before processing diff --git a/examples/python/concepts/knowledge-agents-task.py b/examples/python/concepts/knowledge-agents-task.py index 407c19f79..64bcf8865 100644 --- a/examples/python/concepts/knowledge-agents-task.py +++ b/examples/python/concepts/knowledge-agents-task.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import logging import os @@ -37,7 +37,7 @@ knowledge_task = Task( ) # Create and start the agents -agents = PraisonAIAgents( +agents = Agents( agents=[knowledge_agent], tasks=[knowledge_task], process="sequential", diff --git a/examples/python/concepts/rag-agents.py b/examples/python/concepts/rag-agents.py index e8111cf99..9baab2a2c 100644 --- a/examples/python/concepts/rag-agents.py +++ b/examples/python/concepts/rag-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Define the configuration for the Knowledge instance config = { @@ -29,7 +29,7 @@ rag_task = Task( ) # Build Agents -agents = PraisonAIAgents( +agents = Agents( agents=[rag_agent], tasks=[rag_task], user_id="user1" diff --git a/examples/python/concepts/reasoning-extraction.py b/examples/python/concepts/reasoning-extraction.py index 0c2839f54..8933e1e95 100644 --- a/examples/python/concepts/reasoning-extraction.py +++ b/examples/python/concepts/reasoning-extraction.py @@ -8,7 +8,7 @@ This example demonstrates how to extract and utilize reasoning patterns in Prais - Decision rationale extraction """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import Dict, List, Tuple from pydantic import BaseModel import json @@ -100,7 +100,7 @@ def demonstrate_reasoning_extraction(): context=[problem_task] ) - workflow = PraisonAIAgents( + workflow = Agents( agents=[cot_agent, reasoning_extractor], tasks=[problem_task, extract_task], process="sequential", @@ -184,7 +184,7 @@ def advanced_reasoning_patterns(): context=[deductive_task, inductive_task, abductive_task] ) - workflow = PraisonAIAgents( + workflow = Agents( agents=[cot_agent, reasoning_validator], tasks=[deductive_task, inductive_task, abductive_task, validation_task], process="sequential", diff --git a/examples/python/concepts/repetitive-agents.py b/examples/python/concepts/repetitive-agents.py index 53ad928ad..ec83c0f96 100644 --- a/examples/python/concepts/repetitive-agents.py +++ b/examples/python/concepts/repetitive-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents agent = Agent( instructions="You are a loop agent that creating a loop of tasks.", @@ -12,7 +12,7 @@ task = Task( input_file="tasks.csv" ) -agents = PraisonAIAgents( +agents = Agents( agents=[agent], tasks=[task], process="workflow", diff --git a/examples/python/concepts/routing-patterns.py b/examples/python/concepts/routing-patterns.py index 9978cbe53..df89aed7c 100644 --- a/examples/python/concepts/routing-patterns.py +++ b/examples/python/concepts/routing-patterns.py @@ -8,7 +8,7 @@ This example demonstrates various routing patterns in PraisonAI including: - Dynamic task selection """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import Dict, Any import random @@ -77,7 +77,7 @@ def conditional_routing_example(): agent=processor_agent ) - workflow = PraisonAIAgents( + workflow = Agents( agents=[analyzer_agent, processor_agent], tasks=[analysis_task, premium_task, standard_task, basic_task], process="workflow", @@ -110,7 +110,7 @@ def loop_pattern_example(): agent=validator_agent ) - workflow = PraisonAIAgents( + workflow = Agents( agents=[processor_agent, validator_agent], tasks=[process_task, finalize_task], process="workflow", @@ -185,7 +185,7 @@ def decision_tree_example(): all_tasks = [categorize_task, technical_task, business_task] + terminal_tasks - workflow = PraisonAIAgents( + workflow = Agents( agents=[analyzer_agent, processor_agent], tasks=all_tasks, process="workflow", @@ -272,7 +272,7 @@ def dynamic_routing_example(): agent=processor_agent ) - workflow = PraisonAIAgents( + workflow = Agents( agents=[dynamic_router, processor_agent], tasks=[route_task, escalate_task, automate_task, review_task, standard_task], process="workflow", diff --git a/examples/python/concepts/self-reflection-details.py b/examples/python/concepts/self-reflection-details.py index 69d4dd737..e8f2c69cc 100644 --- a/examples/python/concepts/self-reflection-details.py +++ b/examples/python/concepts/self-reflection-details.py @@ -8,7 +8,7 @@ This example demonstrates the self-reflection capabilities in PraisonAI agents: - Impact on output quality """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import Dict, Any import time @@ -162,7 +162,7 @@ def reflection_workflow_example(): context=[create_task, review_task] ) - workflow = PraisonAIAgents( + workflow = Agents( agents=[creator_agent, reviewer_agent, polisher_agent], tasks=[create_task, review_task, polish_task], process="sequential", diff --git a/examples/python/concepts/self-reflection-optimization-patterns.py b/examples/python/concepts/self-reflection-optimization-patterns.py index e8aeedc59..f47c35862 100644 --- a/examples/python/concepts/self-reflection-optimization-patterns.py +++ b/examples/python/concepts/self-reflection-optimization-patterns.py @@ -5,7 +5,7 @@ This example demonstrates self-reflection capabilities using PraisonAI's built-in reflection features for iterative improvement and quality optimization. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import internet_search print("=== Self-Reflection Optimization Patterns Example ===\n") diff --git a/examples/python/concepts/simple-csv-url-processor.py b/examples/python/concepts/simple-csv-url-processor.py index ed55b89dc..99b6772d9 100644 --- a/examples/python/concepts/simple-csv-url-processor.py +++ b/examples/python/concepts/simple-csv-url-processor.py @@ -9,7 +9,7 @@ This is the simplest possible implementation for processing URLs from a CSV file Author: Generated for GitHub Issue #23 """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import write_csv def create_url_csv(): @@ -59,7 +59,7 @@ def main(): ) # Step 4: Run the agents - agents = PraisonAIAgents( + agents = Agents( agents=[url_agent], tasks=[url_task], process="workflow", diff --git a/examples/python/custom_tools/example_latency_tracking.py b/examples/python/custom_tools/example_latency_tracking.py index 065aa09b2..5dcadcbc2 100644 --- a/examples/python/custom_tools/example_latency_tracking.py +++ b/examples/python/custom_tools/example_latency_tracking.py @@ -4,7 +4,7 @@ Example: Using Latency Tracking Tool with PraisonAI This example shows how to track latency without modifying core files. """ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from latency_tracker_tool import ( latency_tracking_tool, create_tracked_agent, diff --git a/examples/python/custom_tools/mcp_server_latency_example.py b/examples/python/custom_tools/mcp_server_latency_example.py index 0fe2e4672..eab70ee88 100644 --- a/examples/python/custom_tools/mcp_server_latency_example.py +++ b/examples/python/custom_tools/mcp_server_latency_example.py @@ -5,7 +5,7 @@ This shows how to add latency tracking to an MCP server without modifying PraisonAI core files. """ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from hosted_server import HostedMCPServer # Import from local file from latency_tracker_tool import tracker, get_latency_metrics import json diff --git a/examples/python/data/cot-agents.py b/examples/python/data/cot-agents.py index 61836e622..323a3a0d3 100644 --- a/examples/python/data/cot-agents.py +++ b/examples/python/data/cot-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import cot_save, cot_upload_to_huggingface from pydantic import BaseModel import os @@ -131,7 +131,7 @@ upload_to_huggingface_task = Task( ) # Initialize workflow -agents = PraisonAIAgents( +agents = Agents( agents=[qa_generator, total_questions_evaluator, cot_generator, upload_to_huggingface], tasks=[generate_task, evaluate_total_questions_task, generate_cot_task, upload_to_huggingface_task], process="workflow", diff --git a/examples/python/escalation_example.py b/examples/python/escalation_example.py new file mode 100644 index 000000000..c060c78b6 --- /dev/null +++ b/examples/python/escalation_example.py @@ -0,0 +1,192 @@ +""" +Escalation Pipeline Example. + +Demonstrates the progressive escalation from direct response to autonomous mode. +""" + +import asyncio +from praisonaiagents.escalation import ( + EscalationPipeline, + EscalationStage, + EscalationConfig, + EscalationTrigger, + DoomLoopDetector, + ObservabilityHooks, + EventType, +) + + +def demo_signal_detection(): + """Demonstrate signal detection from prompts.""" + print("\n" + "="*60) + print("SIGNAL DETECTION DEMO") + print("="*60) + + trigger = EscalationTrigger() + + # Test various prompts + test_prompts = [ + ("What is Python?", "Simple question"), + ("Read the file src/main.py", "File reference"), + ("Refactor the authentication module and add tests", "Complex task"), + ("First, analyze the code. Then, fix the bug. Finally, test it.", "Multi-step"), + ] + + for prompt, description in test_prompts: + signals = trigger.analyze(prompt) + stage = trigger.recommend_stage(signals) + + print(f"\nšŸ“ Prompt: {prompt[:50]}...") + print(f" Description: {description}") + print(f" Signals: {[s.value for s in signals]}") + print(f" Recommended Stage: {stage.name}") + + +def demo_doom_loop_detection(): + """Demonstrate doom loop detection.""" + print("\n" + "="*60) + print("DOOM LOOP DETECTION DEMO") + print("="*60) + + detector = DoomLoopDetector() + detector.start_session() + + # Simulate repeated identical actions + print("\nšŸ”„ Simulating repeated identical actions...") + for i in range(4): + detector.record_action( + action_type="read_file", + args={"path": "config.py"}, + result="same content", + success=True, + ) + + if detector.is_doom_loop(): + loop_type = detector.get_loop_type() + recovery = detector.get_recovery_action() + print(f" āš ļø Doom loop detected after {i+1} actions!") + print(f" Type: {loop_type.value}") + print(f" Recovery: {recovery.value}") + break + else: + print(f" Action {i+1}: No loop detected") + + # Show stats + stats = detector.get_stats() + print(f"\nšŸ“Š Stats: {stats}") + + +def demo_observability(): + """Demonstrate observability hooks.""" + print("\n" + "="*60) + print("OBSERVABILITY DEMO") + print("="*60) + + hooks = ObservabilityHooks() + + # Register event handlers + def on_stage_change(event): + print(f" šŸ“ Stage changed: {event.data}") + + def on_tool_call(event): + print(f" šŸ”§ Tool called: {event.data}") + + hooks.on(EventType.STAGE_ESCALATE, on_stage_change) + hooks.on(EventType.TOOL_CALL_END, on_tool_call) + + # Simulate events + print("\nšŸŽÆ Simulating execution events...") + hooks.start_execution("session_123") + + hooks.set_stage(EscalationStage.DIRECT) + hooks.emit(EventType.STEP_START, {"step": 1}) + hooks.emit(EventType.TOOL_CALL_END, {"tool": "read_file", "path": "main.py"}) + hooks.emit(EventType.STEP_END, {"step": 1}) + + hooks.emit(EventType.STAGE_ESCALATE, {"from": "DIRECT", "to": "HEURISTIC"}) + hooks.set_stage(EscalationStage.HEURISTIC) + + hooks.end_execution(1500.0) + + # Show summary + summary = hooks.get_summary() + print(f"\nšŸ“Š Summary: {summary}") + + +def demo_stage_descriptions(): + """Show descriptions of each escalation stage.""" + print("\n" + "="*60) + print("ESCALATION STAGES") + print("="*60) + + trigger = EscalationTrigger() + + stages = [ + (EscalationStage.DIRECT, "Simple questions, no tools needed"), + (EscalationStage.HEURISTIC, "File references, code blocks"), + (EscalationStage.PLANNED, "Edit intent, test/build tasks"), + (EscalationStage.AUTONOMOUS, "Multi-step, refactoring tasks"), + ] + + for stage, example in stages: + desc = trigger.get_stage_description(stage) + print(f"\nšŸŽÆ Stage {stage.value}: {stage.name}") + print(f" Description: {desc}") + print(f" Example use: {example}") + + +async def demo_pipeline_analysis(): + """Demonstrate pipeline analysis.""" + print("\n" + "="*60) + print("PIPELINE ANALYSIS DEMO") + print("="*60) + + config = EscalationConfig( + max_steps=20, + max_time_seconds=60, + auto_escalate=True, + ) + + pipeline = EscalationPipeline(config=config) + + prompts = [ + "What is a Python decorator?", + "Read the file src/auth.py and explain it", + "Refactor the user authentication to use JWT tokens", + ] + + for prompt in prompts: + stage = pipeline.analyze(prompt) + print(f"\nšŸ“ Prompt: {prompt[:50]}...") + print(f" Recommended Stage: {stage.name}") + + +def main(): + """Run all demos.""" + print("\n" + "="*60) + print("PRAISONAI ESCALATION PIPELINE DEMO") + print("="*60) + print("\nThis demo shows the progressive escalation system that") + print("automatically adjusts execution complexity based on task signals.") + + # Run demos + demo_stage_descriptions() + demo_signal_detection() + demo_doom_loop_detection() + demo_observability() + asyncio.run(demo_pipeline_analysis()) + + print("\n" + "="*60) + print("DEMO COMPLETE") + print("="*60) + print("\nKey takeaways:") + print("1. Simple tasks stay at DIRECT stage (no tools)") + print("2. File references trigger HEURISTIC stage") + print("3. Edit/test tasks trigger PLANNED stage") + print("4. Multi-step/refactor tasks trigger AUTONOMOUS stage") + print("5. Doom loop detection prevents infinite loops") + print("6. Observability hooks enable monitoring") + + +if __name__ == "__main__": + main() diff --git a/examples/python/general/advanced-callback-systems.py b/examples/python/general/advanced-callback-systems.py index 21cb7b5f8..b1ef1c2ca 100644 --- a/examples/python/general/advanced-callback-systems.py +++ b/examples/python/general/advanced-callback-systems.py @@ -5,7 +5,7 @@ This example demonstrates callback systems using PraisonAI's built-in callback functionality for monitoring agent interactions and tool usage. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.display_callback import register_display_callback from praisonaiagents.tools import internet_search diff --git a/examples/python/general/async_example.py b/examples/python/general/async_example.py index 15ae5edea..10744c8f3 100644 --- a/examples/python/general/async_example.py +++ b/examples/python/general/async_example.py @@ -1,7 +1,7 @@ import asyncio import time from typing import List, Dict -from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput +from praisonaiagents import Agent, Task, Agents, TaskOutput from praisonaiagents.main import ( display_error, display_interaction, @@ -160,7 +160,7 @@ workflow_async_task = Task( def run_sync_example(): """Run synchronous example""" display_instruction("\nRunning Synchronous Example...", console) - agents = PraisonAIAgents( + agents = Agents( agents=[sync_agent], tasks=[sync_task], verbose=1, @@ -172,7 +172,7 @@ def run_sync_example(): async def run_async_example(): """Run asynchronous example""" display_instruction("\nRunning Asynchronous Example...", console) - agents = PraisonAIAgents( + agents = Agents( agents=[async_agent], tasks=[async_task], verbose=1, @@ -184,7 +184,7 @@ async def run_async_example(): async def run_mixed_example(): """Run mixed sync/async example""" display_instruction("\nRunning Mixed Sync/Async Example...", console) - agents = PraisonAIAgents( + agents = Agents( agents=[sync_agent, async_agent], tasks=[sync_task, async_task], verbose=1, @@ -196,7 +196,7 @@ async def run_mixed_example(): async def run_workflow_example(): """Run workflow example with both sync and async tasks""" display_instruction("\nRunning Workflow Example...", console) - agents = PraisonAIAgents( + agents = Agents( agents=[sync_agent, async_agent], tasks=[workflow_sync_task, workflow_async_task], verbose=1, diff --git a/examples/python/general/async_example_full.py b/examples/python/general/async_example_full.py index 3c3b373c0..d9e90b3e6 100644 --- a/examples/python/general/async_example_full.py +++ b/examples/python/general/async_example_full.py @@ -1,7 +1,7 @@ import asyncio import time from typing import List, Dict -from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput +from praisonaiagents import Agent, Task, Agents, TaskOutput from duckduckgo_search import DDGS from pydantic import BaseModel @@ -114,8 +114,8 @@ async def run_parallel_tasks(): context=parallel_tasks ) - # Create a single PraisonAIAgents instance with both agents - agents = PraisonAIAgents( + # Create a single Agents instance with both agents + agents = Agents( agents=[async_agent, summary_agent], tasks=parallel_tasks + [summary_task], verbose=1, diff --git a/examples/python/general/async_example_full_multigroups.py b/examples/python/general/async_example_full_multigroups.py index f0c3e1b84..17bfd5f08 100644 --- a/examples/python/general/async_example_full_multigroups.py +++ b/examples/python/general/async_example_full_multigroups.py @@ -1,7 +1,7 @@ import asyncio import time from typing import List, Dict -from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput +from praisonaiagents import Agent, Task, Agents, TaskOutput from duckduckgo_search import DDGS from pydantic import BaseModel @@ -103,7 +103,7 @@ async_task = Task( async def run_single_task(): """Run single async task""" print("\nRunning Single Async Task...") - agents = PraisonAIAgents( + agents = Agents( agents=[async_agent], tasks=[async_task], verbose=1, @@ -187,7 +187,7 @@ Present the summary in a clear, structured format with sections for findings, pa ) # First run parallel search tasks - agents = PraisonAIAgents( + agents = Agents( agents=[async_agent], tasks=parallel_tasks, # Only run search tasks first verbose=1, @@ -212,7 +212,7 @@ Present the summary in a clear, structured format with sections for findings, pa summary_task.context = completed_tasks # Run summarization task with summary agent - summary_agents = PraisonAIAgents( + summary_agents = Agents( agents=[summary_agent], # Use summary agent for synthesis tasks=[summary_task], verbose=1, diff --git a/examples/python/general/autonomous-agent.py b/examples/python/general/autonomous-agent.py index cb18de012..cc5b8c306 100644 --- a/examples/python/general/autonomous-agent.py +++ b/examples/python/general/autonomous-agent.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time def get_environment_state(): @@ -86,7 +86,7 @@ feedback_task = Task( ) # Create workflow manager -workflow = PraisonAIAgents( +workflow = Agents( agents=[llm_caller, action_agent, feedback_agent], tasks=[monitor_task, action_task, feedback_task], process="workflow", diff --git a/examples/python/general/code_agents_example.py b/examples/python/general/code_agents_example.py index 7f29a164a..653d504c6 100644 --- a/examples/python/general/code_agents_example.py +++ b/examples/python/general/code_agents_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import json from e2b_code_interpreter import Sandbox @@ -46,5 +46,5 @@ execution_agent_task = Task( agent=execution_agent ) -agents = PraisonAIAgents(agents=[code_agent, execution_agent], tasks=[code_agent_task, execution_agent_task]) +agents = Agents(agents=[code_agent, execution_agent], tasks=[code_agent_task, execution_agent_task]) agents.start() \ No newline at end of file diff --git a/examples/python/general/evaluator-optimiser.py b/examples/python/general/evaluator-optimiser.py index 3f83b52b9..9527af4f7 100644 --- a/examples/python/general/evaluator-optimiser.py +++ b/examples/python/general/evaluator-optimiser.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create generator and evaluator agents generator = Agent( @@ -53,7 +53,7 @@ evaluate_task = Task( ) # Create workflow manager -workflow = PraisonAIAgents( +workflow = Agents( agents=[generator, evaluator], tasks=[generate_task, evaluate_task], process="workflow", diff --git a/examples/python/general/example_callback.py b/examples/python/general/example_callback.py index c18e933f5..2339edcbc 100644 --- a/examples/python/general/example_callback.py +++ b/examples/python/general/example_callback.py @@ -1,7 +1,7 @@ from praisonaiagents import ( Agent, Task, - PraisonAIAgents, + Agents, error_logs, register_display_callback, sync_display_callbacks, @@ -190,7 +190,7 @@ def main(): ) # Create and run agents manager - agents = PraisonAIAgents( + agents = Agents( agents=[researcher, writer], tasks=[task1, task2, task3, task4], verbose=True, diff --git a/examples/python/general/example_custom_tools.py b/examples/python/general/example_custom_tools.py index 8e210a081..f7ee722db 100644 --- a/examples/python/general/example_custom_tools.py +++ b/examples/python/general/example_custom_tools.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import List, Dict, Union from duckduckgo_search import DDGS from langchain_community.tools import YouTubeSearchTool @@ -141,7 +141,7 @@ validate_task = Task( ) # 4. Workflow -agents = PraisonAIAgents( +agents = Agents( agents=[data_agent], tasks=[collect_task, validate_task], verbose=1, diff --git a/examples/python/general/example_sequential.py b/examples/python/general/example_sequential.py index b4e97ffa5..67301dab0 100644 --- a/examples/python/general/example_sequential.py +++ b/examples/python/general/example_sequential.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs +from praisonaiagents import Agent, Task, Agents, error_logs from duckduckgo_search import DDGS def my_callback(output): @@ -99,7 +99,7 @@ task4 = Task( ) # Create and run agents manager -agents = PraisonAIAgents( +agents = Agents( agents=[researcher, writer], tasks=[task1, task2, task3, task4], verbose=False, diff --git a/examples/python/general/human_approval_example.py b/examples/python/general/human_approval_example.py index 23864fd30..86615a75c 100644 --- a/examples/python/general/human_approval_example.py +++ b/examples/python/general/human_approval_example.py @@ -24,7 +24,7 @@ import sys # Add the local development path to use the current implementation sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src', 'praisonai-agents')) -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import python_tools, file_tools, shell_tools from praisonaiagents.main import register_approval_callback from praisonaiagents.approval import ( @@ -111,7 +111,7 @@ def main(): ] # Create and run process - process = PraisonAIAgents( + process = Agents( agents=[agent], tasks=tasks, verbose=True @@ -171,7 +171,7 @@ async def async_demo(): expected_output="Async execution result" ) - process = PraisonAIAgents( + process = Agents( agents=[agent], tasks=[task], verbose=True diff --git a/examples/python/general/langchain_example.py b/examples/python/general/langchain_example.py index 486f396e0..d9727e205 100644 --- a/examples/python/general/langchain_example.py +++ b/examples/python/general/langchain_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from langchain_community.tools import YouTubeSearchTool from langchain_community.utilities import WikipediaAPIWrapper @@ -21,7 +21,7 @@ task = Task( ) # Create and start the workflow -agents = PraisonAIAgents( +agents = Agents( agents=[agent], tasks=[task], verbose=True diff --git a/examples/python/general/memory_example.py b/examples/python/general/memory_example.py index 0824c0195..5ef8ce4f8 100644 --- a/examples/python/general/memory_example.py +++ b/examples/python/general/memory_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import logging import os @@ -25,7 +25,7 @@ def main(): # else: # logger.info("Creating new memory database") - # Create task config (without memory config since it's moved to PraisonAIAgents) + # Create task config (without memory config since it's moved to Agents) task_config = {} # Create agents with different roles @@ -100,8 +100,8 @@ def main(): agent=retriever ) - # Initialize PraisonAIAgents with memory configuration - agents = PraisonAIAgents( + # Initialize Agents with memory configuration + agents = Agents( agents=[researcher, retriever], tasks=[store_task, verify_task, query_task, query_both_task], verbose=True, # Use same verbose level as memory @@ -114,7 +114,7 @@ def main(): } ) - # agents = PraisonAIAgents( + # agents = Agents( # agents=[researcher, retriever], # tasks=[store_task, verify_task, query_task, query_both_task], # verbose=True, # Use same verbose level as memory diff --git a/examples/python/general/memory_simple.py b/examples/python/general/memory_simple.py index b0bed4d52..24fe6e3b2 100644 --- a/examples/python/general/memory_simple.py +++ b/examples/python/general/memory_simple.py @@ -1,4 +1,4 @@ -from praisonaiagents.agents.agents import Agent, Task, PraisonAIAgents +from praisonaiagents.agents.agents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo # Test facts @@ -54,7 +54,7 @@ blog_task = Task( agent=blog_agent ) -agents = PraisonAIAgents( +agents = Agents( agents=[fact_agent, research_agent, blog_agent], tasks=[fact_task, research_task, research_task2, research_task3, research_task4, blog_task], memory=True diff --git a/examples/python/general/multimodal.py b/examples/python/general/multimodal.py index 585c9e3b3..b0f5c7dfb 100644 --- a/examples/python/general/multimodal.py +++ b/examples/python/general/multimodal.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create Vision Analysis Agent vision_agent = Agent( @@ -42,8 +42,8 @@ task3 = Task( images=["video.mp4"] ) -# Create PraisonAIAgents instance -agents = PraisonAIAgents( +# Create Agents instance +agents = Agents( agents=[vision_agent], tasks=[task1, task2, task3], process="sequential", diff --git a/examples/python/general/orchestrator-workers.py b/examples/python/general/orchestrator-workers.py index 45b66ad5b..c2e63a418 100644 --- a/examples/python/general/orchestrator-workers.py +++ b/examples/python/general/orchestrator-workers.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time def get_time_check(): @@ -93,7 +93,7 @@ synthesize_task = Task( ) # Create workflow manager -workflow = PraisonAIAgents( +workflow = Agents( agents=[router, worker1, worker2, worker3, synthesizer], tasks=[router_task, worker1_task, worker2_task, worker3_task, synthesize_task], process="workflow", diff --git a/examples/python/general/parallelisation.py b/examples/python/general/parallelisation.py index 0be063805..0b83ec79a 100644 --- a/examples/python/general/parallelisation.py +++ b/examples/python/general/parallelisation.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from datetime import datetime import asyncio @@ -75,7 +75,7 @@ aggregate_task = Task( async def main(): # Create workflow manager - workflow = PraisonAIAgents( + workflow = Agents( agents=[agent1, agent2, agent3, aggregator], tasks=[task1, task2, task3, aggregate_task], process="workflow" diff --git a/examples/python/general/prompt_chaining.py b/examples/python/general/prompt_chaining.py index 35696b1cc..e4b5c4850 100644 --- a/examples/python/general/prompt_chaining.py +++ b/examples/python/general/prompt_chaining.py @@ -1,6 +1,6 @@ from praisonaiagents.agent import Agent from praisonaiagents.task import Task -from praisonaiagents.agents import PraisonAIAgents +from praisonaiagents.agents import Agents from typing import List, Dict import time @@ -64,7 +64,7 @@ final_task = Task( ) # Create the workflow manager -workflow = PraisonAIAgents( +workflow = Agents( agents=[agent1, agent2, agent3], tasks=[initial_task, analysis_task, final_task], process="workflow", # Use workflow process type diff --git a/examples/python/general/structured_agents_example.py b/examples/python/general/structured_agents_example.py index dc480a382..bcbb339b1 100644 --- a/examples/python/general/structured_agents_example.py +++ b/examples/python/general/structured_agents_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents, Tools +from praisonaiagents import Agent, Task, Agents, Tools from pydantic import BaseModel class AnalysisReport(BaseModel): @@ -46,7 +46,7 @@ analysis_task = Task( ) # Initialize and run agents -agents = PraisonAIAgents( +agents = Agents( agents=[researcher, analyst], tasks=[research_task, analysis_task], process="sequential", diff --git a/examples/python/general/tools-class.py b/examples/python/general/tools-class.py index 113c02e0f..8444df9c4 100644 --- a/examples/python/general/tools-class.py +++ b/examples/python/general/tools-class.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import os import requests from typing import Any, Dict, List, Optional @@ -106,7 +106,7 @@ task = Task( ) # Create and start the workflow -agents = PraisonAIAgents( +agents = Agents( agents=[agent], tasks=[task], verbose=True diff --git a/examples/python/general/tools_example.py b/examples/python/general/tools_example.py index 84cde8ff9..782b5cc61 100644 --- a/examples/python/general/tools_example.py +++ b/examples/python/general/tools_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import get_article, get_news_sources, get_articles_from_source, get_trending_topics # Create Wikipedia agent @@ -22,7 +22,7 @@ news_task = Task( # Run agent -agents = PraisonAIAgents( +agents = Agents( agents=[news_agent], tasks=[news_task], process="sequential" diff --git a/examples/python/general/workflow_example_basic.py b/examples/python/general/workflow_example_basic.py index 6d90fc324..fb9919c4e 100644 --- a/examples/python/general/workflow_example_basic.py +++ b/examples/python/general/workflow_example_basic.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import List, Dict from duckduckgo_search import DDGS @@ -64,7 +64,7 @@ validate_task = Task( ) # 4. AI Agents Workflow -agents = PraisonAIAgents( +agents = Agents( agents=[data_agent], tasks=[collect_task, validate_task], verbose=1, diff --git a/examples/python/general/workflow_example_detailed.py b/examples/python/general/workflow_example_detailed.py index e129ae1cb..183df321d 100644 --- a/examples/python/general/workflow_example_detailed.py +++ b/examples/python/general/workflow_example_detailed.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import random from typing import List, Dict, Union import json @@ -224,8 +224,8 @@ process_task = Task( output_json=ProcessedPerson ) -# Create PraisonAIAgents instance with workflow process -workflow = PraisonAIAgents( +# Create Agents instance with workflow process +workflow = Agents( agents=[data_agent, process_agent], tasks=[collect_task, validate_task, process_task], verbose=1, diff --git a/examples/python/guardrails/comprehensive-guardrails-example.py b/examples/python/guardrails/comprehensive-guardrails-example.py index 455b8e9df..1d289ea8a 100644 --- a/examples/python/guardrails/comprehensive-guardrails-example.py +++ b/examples/python/guardrails/comprehensive-guardrails-example.py @@ -12,7 +12,7 @@ Features demonstrated: - Quality assurance workflows """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.task import TaskOutput from typing import Tuple, Any import re @@ -181,7 +181,7 @@ llm_guardrail_task = Task( ) # Execute tasks with guardrails -agents = PraisonAIAgents( +agents = Agents( agents=[email_agent, content_agent, business_agent, research_agent, llm_guardrail_agent], tasks=[email_task, content_task, business_task, research_task, llm_guardrail_task], verbose=True diff --git a/examples/python/guardrails/production-guardrails-patterns.py b/examples/python/guardrails/production-guardrails-patterns.py index a29ef096e..4b6afe029 100644 --- a/examples/python/guardrails/production-guardrails-patterns.py +++ b/examples/python/guardrails/production-guardrails-patterns.py @@ -5,7 +5,7 @@ This example demonstrates production guardrail patterns using PraisonAI's built-in validation and safety mechanisms for secure agent operations. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import internet_search print("=== Production Guardrails Patterns Example ===\n") diff --git a/examples/python/input/advanced_dynamic_input.py b/examples/python/input/advanced_dynamic_input.py index ac9c95105..44e533f9f 100644 --- a/examples/python/input/advanced_dynamic_input.py +++ b/examples/python/input/advanced_dynamic_input.py @@ -5,7 +5,7 @@ This example demonstrates an advanced system that dynamically creates agents and based on user inputs, including conditional logic, custom configurations, and file output. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo import os from typing import Dict, List @@ -137,7 +137,7 @@ class DynamicAgentSystem: # Run the system print(f"\nšŸš€ Starting {process} analysis for '{inputs['topic']}'...") - praison_agents = PraisonAIAgents( + praison_agents = Agents( agents=agents, tasks=tasks, process=process, diff --git a/examples/python/input/environment_variable_input.py b/examples/python/input/environment_variable_input.py index 116f1a374..5dbf9a60c 100644 --- a/examples/python/input/environment_variable_input.py +++ b/examples/python/input/environment_variable_input.py @@ -6,7 +6,7 @@ to create flexible agent configurations that can be pre-configured via environme """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Set via environment or use default default_topic = os.getenv("RESEARCH_TOPIC", "AI trends") @@ -46,7 +46,7 @@ print(f" - Max Retries: {max_retries}") print("\n" + "="*50 + "\n") # Run agents -agents = PraisonAIAgents(agents=[agent], tasks=[task]) +agents = Agents(agents=[agent], tasks=[task]) result = agents.start() # Save to environment-specified location if provided diff --git a/examples/python/input/medium_complexity_input.py b/examples/python/input/medium_complexity_input.py index a674910a3..acefcb73d 100644 --- a/examples/python/input/medium_complexity_input.py +++ b/examples/python/input/medium_complexity_input.py @@ -5,7 +5,7 @@ This example shows how to use multiple user inputs to create a more sophisticate agent system with tools, multiple agents, and context passing between tasks. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo # Get multiple inputs @@ -47,7 +47,7 @@ analyze_task = Task( ) # Run sequential process -agents = PraisonAIAgents( +agents = Agents( agents=[search_agent, analysis_agent], tasks=[search_task, analyze_task], process="sequential" diff --git a/examples/python/input/simple_input.py b/examples/python/input/simple_input.py index 3a33bc517..b76cfde81 100644 --- a/examples/python/input/simple_input.py +++ b/examples/python/input/simple_input.py @@ -5,7 +5,7 @@ This example demonstrates how to use basic user input to create dynamic agents a The user is prompted for a search query, and the agent searches for information about it. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Get user input user_query = input("What would you like to search for? ") @@ -26,5 +26,5 @@ task = Task( ) # Run -agents = PraisonAIAgents(agents=[agent], tasks=[task]) +agents = Agents(agents=[agent], tasks=[task]) agents.start() \ No newline at end of file diff --git a/examples/python/input/streamlit_ui_input.py b/examples/python/input/streamlit_ui_input.py index 2e83c84a7..41414d941 100644 --- a/examples/python/input/streamlit_ui_input.py +++ b/examples/python/input/streamlit_ui_input.py @@ -10,7 +10,7 @@ To run this example: """ import streamlit as st -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo # Set page configuration @@ -125,7 +125,7 @@ if st.button("šŸš€ Submit", type="primary", use_container_width=True): ) # Run agents - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process=process_type diff --git a/examples/python/memory/advanced-graph-memory-integration.py b/examples/python/memory/advanced-graph-memory-integration.py index be3932cec..49ffe39da 100644 --- a/examples/python/memory/advanced-graph-memory-integration.py +++ b/examples/python/memory/advanced-graph-memory-integration.py @@ -5,7 +5,7 @@ This example demonstrates graph memory capabilities with PraisonAI agents for knowledge graph construction and relationship-aware memory retrieval. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import internet_search print("=== Advanced Graph Memory Integration Example ===\n") @@ -59,7 +59,7 @@ query_task = Task( ) # Run with graph memory integration -agents_system = PraisonAIAgents( +agents_system = Agents( agents=[knowledge_agent], tasks=[build_task, query_task], memory=True, diff --git a/examples/python/memory/advanced-memory-search-optimization.py b/examples/python/memory/advanced-memory-search-optimization.py index 909528880..e8c2aaca2 100644 --- a/examples/python/memory/advanced-memory-search-optimization.py +++ b/examples/python/memory/advanced-memory-search-optimization.py @@ -5,7 +5,7 @@ This example demonstrates memory search optimization using PraisonAI's built-in memory capabilities with semantic search and quality filtering. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import internet_search print("=== Advanced Memory Search and Optimization Example ===\n") @@ -60,7 +60,7 @@ search_task = Task( ) # Run with memory optimization -agents_system = PraisonAIAgents( +agents_system = Agents( agents=[research_agent], tasks=[build_memory_task, search_task], memory=True, diff --git a/examples/python/memory/gemini-embedding-example.py b/examples/python/memory/gemini-embedding-example.py index 86f33e420..bd586735f 100644 --- a/examples/python/memory/gemini-embedding-example.py +++ b/examples/python/memory/gemini-embedding-example.py @@ -20,7 +20,7 @@ Prerequisites: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents def main(): """Demonstrate Gemini embedding usage""" @@ -82,7 +82,7 @@ def main(): # Configure with Gemini embeddings # Option 1: Using stable text-embedding-004 - agents = PraisonAIAgents( + agents = Agents( agents=[researcher, retriever], tasks=[store_task, retrieve_task], verbose=True, @@ -98,7 +98,7 @@ def main(): ) # Alternative: Using experimental model with advanced features - # agents = PraisonAIAgents( + # agents = Agents( # agents=[researcher, retriever], # tasks=[store_task, retrieve_task], # verbose=True, diff --git a/examples/python/memory/graph-memory-agent.py b/examples/python/memory/graph-memory-agent.py index 6e406886b..4e1e4a77e 100644 --- a/examples/python/memory/graph-memory-agent.py +++ b/examples/python/memory/graph-memory-agent.py @@ -16,7 +16,7 @@ Setup: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents def main(): # Example with Neo4j (uncomment and configure as needed) @@ -150,7 +150,7 @@ def main(): ) # Run the multi-agent system with graph memory - agents_system = PraisonAIAgents( + agents_system = Agents( agents=[researcher], tasks=[build_knowledge_task, query_knowledge_task, expand_knowledge_task], verbose=1, diff --git a/examples/python/mongodb/mongodb_comprehensive_example.py b/examples/python/mongodb/mongodb_comprehensive_example.py index 2b3280e24..c727bdd51 100644 --- a/examples/python/mongodb/mongodb_comprehensive_example.py +++ b/examples/python/mongodb/mongodb_comprehensive_example.py @@ -20,7 +20,7 @@ Features demonstrated: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import mongodb_tools # Ensure OpenAI API key is set @@ -190,7 +190,7 @@ def main(): print("šŸš€ Starting Comprehensive MongoDB Business System...") print("=" * 60) - business_system = PraisonAIAgents( + business_system = Agents( agents=[data_manager, knowledge_curator, business_analyst, customer_service], tasks=business_tasks, memory=True, diff --git a/examples/python/mongodb/mongodb_knowledge_example.py b/examples/python/mongodb/mongodb_knowledge_example.py index 77d9c2e56..f65e03a82 100644 --- a/examples/python/mongodb/mongodb_knowledge_example.py +++ b/examples/python/mongodb/mongodb_knowledge_example.py @@ -19,7 +19,7 @@ Features demonstrated: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Ensure OpenAI API key is set if not os.environ.get("OPENAI_API_KEY"): @@ -124,7 +124,7 @@ def main(): print("šŸš€ Starting MongoDB Knowledge Management System...") print("=" * 60) - knowledge_system = PraisonAIAgents( + knowledge_system = Agents( agents=[research_agent, knowledge_agent], tasks=knowledge_tasks, memory=True, diff --git a/examples/python/mongodb/mongodb_memory_example.py b/examples/python/mongodb/mongodb_memory_example.py index 8b30e58ed..2778f7d9d 100644 --- a/examples/python/mongodb/mongodb_memory_example.py +++ b/examples/python/mongodb/mongodb_memory_example.py @@ -19,7 +19,7 @@ Features demonstrated: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Ensure OpenAI API key is set if not os.environ.get("OPENAI_API_KEY"): @@ -91,7 +91,7 @@ def main(): print("šŸš€ Starting MongoDB Memory Research System...") print("=" * 60) - research_system = PraisonAIAgents( + research_system = Agents( agents=[research_agent], tasks=research_tasks, memory=True, diff --git a/examples/python/mongodb/mongodb_tools_example.py b/examples/python/mongodb/mongodb_tools_example.py index 6f0e7fa27..b2f5d6a98 100644 --- a/examples/python/mongodb/mongodb_tools_example.py +++ b/examples/python/mongodb/mongodb_tools_example.py @@ -19,7 +19,7 @@ Features demonstrated: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import mongodb_tools # Ensure OpenAI API key is set @@ -113,7 +113,7 @@ def main(): print("šŸš€ Starting MongoDB Tools Demo System...") print("=" * 60) - mongodb_system = PraisonAIAgents( + mongodb_system = Agents( agents=[db_agent, analysis_agent], tasks=mongodb_tasks, verbose=True diff --git a/examples/python/monitoring/02_multi_agent_workflow_monitoring.py b/examples/python/monitoring/02_multi_agent_workflow_monitoring.py index cab5c3789..d199a4091 100644 --- a/examples/python/monitoring/02_multi_agent_workflow_monitoring.py +++ b/examples/python/monitoring/02_multi_agent_workflow_monitoring.py @@ -10,7 +10,7 @@ Demonstrates performance monitoring in a multi-agent workflow: Shows how to monitor complex multi-agent systems. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import ( monitor_function, track_api_call, get_function_stats, analyze_function_flow, generate_comprehensive_report @@ -101,7 +101,7 @@ def main(): with track_api_call("multi_agent_workflow"): print("\nšŸš€ Starting multi-agent workflow...") - workflow = PraisonAIAgents( + workflow = Agents( agents=[researcher, analyst, writer], tasks=[research_task, analysis_task, report_task], process="sequential", diff --git a/examples/python/monitoring/07_hierarchical_agents_monitoring.py b/examples/python/monitoring/07_hierarchical_agents_monitoring.py index 1445d8217..fc73b73f7 100644 --- a/examples/python/monitoring/07_hierarchical_agents_monitoring.py +++ b/examples/python/monitoring/07_hierarchical_agents_monitoring.py @@ -11,7 +11,7 @@ Shows how to monitor complex organizational agent structures. """ import time -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import ( monitor_function, track_api_call, get_function_stats, visualize_execution_flow, generate_comprehensive_report diff --git a/examples/python/monitoring/10_comprehensive_dashboard.py b/examples/python/monitoring/10_comprehensive_dashboard.py index d8e6924a7..3f42cef97 100644 --- a/examples/python/monitoring/10_comprehensive_dashboard.py +++ b/examples/python/monitoring/10_comprehensive_dashboard.py @@ -13,7 +13,7 @@ Shows how to create a comprehensive performance monitoring solution. import time import json from datetime import datetime, timedelta -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import ( monitor_function, track_api_call, performance_monitor, get_performance_report, get_function_stats, get_api_stats, @@ -139,7 +139,7 @@ def simulate_complex_workflow(): # Execute workflow with track_api_call("complex_workflow_execution"): - workflow = PraisonAIAgents( + workflow = Agents( agents=[planner, executor, reviewer], tasks=[planning_task, execution_task, review_task], process="sequential", diff --git a/examples/python/performance_monitoring_demo.py b/examples/python/performance_monitoring_demo.py index 00cfa8925..b65eecfdb 100644 --- a/examples/python/performance_monitoring_demo.py +++ b/examples/python/performance_monitoring_demo.py @@ -21,7 +21,7 @@ Features Demonstrated: import time import random -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo from praisonaiagents.telemetry import ( monitor_function, track_api_call, performance_monitor, @@ -213,7 +213,7 @@ def execute_monitored_task(agent, task_description): agent=agent ) - agents_workflow = PraisonAIAgents( + agents_workflow = Agents( agents=[agent], tasks=[task], verbose=False diff --git a/examples/python/processes/advanced-workflow-patterns.py b/examples/python/processes/advanced-workflow-patterns.py index 02fbb58ec..5d207fc81 100644 --- a/examples/python/processes/advanced-workflow-patterns.py +++ b/examples/python/processes/advanced-workflow-patterns.py @@ -12,7 +12,7 @@ Features demonstrated: - State-based workflow management """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo import random @@ -203,7 +203,7 @@ for request in sample_requests: ) # Execute the workflow with conditional routing - workflow_agents = PraisonAIAgents( + workflow_agents = Agents( agents=[ intake_agent, specialist_agent, review_agent, coordinator_agent diff --git a/examples/python/processes/hierarchical-process-example.py b/examples/python/processes/hierarchical-process-example.py index 84abf555a..a0ad6741a 100644 --- a/examples/python/processes/hierarchical-process-example.py +++ b/examples/python/processes/hierarchical-process-example.py @@ -12,7 +12,7 @@ Features demonstrated: - Process-level orchestration """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo # Create Manager Agent @@ -83,7 +83,7 @@ coordination_task = Task( ) # Create Hierarchical Process -agents = PraisonAIAgents( +agents = Agents( agents=[manager, researcher, data_analyst, writer], tasks=[research_task, analysis_task, writing_task, coordination_task], process="hierarchical", # Hierarchical process type diff --git a/examples/python/sessions/comprehensive-session-management.py b/examples/python/sessions/comprehensive-session-management.py index c28872b70..e3628a595 100644 --- a/examples/python/sessions/comprehensive-session-management.py +++ b/examples/python/sessions/comprehensive-session-management.py @@ -12,7 +12,7 @@ Features demonstrated: - Session-specific memory and knowledge """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.session import Session from praisonaiagents.tools import duckduckgo import tempfile @@ -62,7 +62,7 @@ research_task1 = Task( ) # Create agents with session -agents_session1 = PraisonAIAgents( +agents_session1 = Agents( agents=[research_agent], tasks=[research_task1], session=session1, @@ -102,7 +102,7 @@ analysis_task = Task( context_variables={"previous_research": str(result1)} ) -agents_session2 = PraisonAIAgents( +agents_session2 = Agents( agents=[analysis_agent], tasks=[analysis_task], session=session2, @@ -153,7 +153,7 @@ synthesis_task = Task( } ) -agents_recovery = PraisonAIAgents( +agents_recovery = Agents( agents=[synthesis_agent], tasks=[synthesis_task], session=recovery_session, @@ -204,7 +204,7 @@ review_task = Task( } ) -agents_reviewer = PraisonAIAgents( +agents_reviewer = Agents( agents=[review_agent], tasks=[review_task], session=reviewer_session, diff --git a/examples/python/stateful/01_basic_state_management.py b/examples/python/stateful/01_basic_state_management.py index ef897e93c..826cbc56d 100644 --- a/examples/python/stateful/01_basic_state_management.py +++ b/examples/python/stateful/01_basic_state_management.py @@ -10,7 +10,7 @@ Run this example: python 01_basic_state_management.py """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import json from typing import Dict, Any @@ -150,7 +150,7 @@ task4 = Task( ) # Create workflow (global variable for state access in tools) -workflow = PraisonAIAgents( +workflow = Agents( agents=[project_manager, developer, finance_manager], tasks=[task1, task2, task3, task4], verbose=True, diff --git a/examples/python/stateful/02_state_in_tool_functions.py b/examples/python/stateful/02_state_in_tool_functions.py index ab018f456..874205bcc 100644 --- a/examples/python/stateful/02_state_in_tool_functions.py +++ b/examples/python/stateful/02_state_in_tool_functions.py @@ -10,7 +10,7 @@ Run this example: python 02_state_in_tool_functions.py """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time import json from typing import Dict, Any @@ -273,7 +273,7 @@ task6 = Task( ) # Create workflow (global variable for state access in tools) -workflow = PraisonAIAgents( +workflow = Agents( agents=[progress_tracker, data_processor, error_handler, config_manager], tasks=[task1, task2, task3, task4, task5, task6], verbose=True, diff --git a/examples/python/stateful/03_conditional_task_execution.py b/examples/python/stateful/03_conditional_task_execution.py index 8b97901f5..495ba6d7a 100644 --- a/examples/python/stateful/03_conditional_task_execution.py +++ b/examples/python/stateful/03_conditional_task_execution.py @@ -10,7 +10,7 @@ Run this example: python 03_conditional_task_execution.py """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import json from typing import Dict, Any @@ -376,7 +376,7 @@ report_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[finance_agent, cost_manager, development_agent, performance_agent, report_agent], tasks=[ budget_decision_task, diff --git a/examples/python/stateful/04_session_state_persistence.py b/examples/python/stateful/04_session_state_persistence.py index c0d7c7020..92dbb09d4 100644 --- a/examples/python/stateful/04_session_state_persistence.py +++ b/examples/python/stateful/04_session_state_persistence.py @@ -10,7 +10,7 @@ Run this example: python 04_session_state_persistence.py """ -from praisonaiagents import Agent, Task, PraisonAIAgents, Session +from praisonaiagents import Agent, Task, Agents, Session import json import time from datetime import datetime @@ -236,7 +236,7 @@ initial_tasks = [ ] # Create workflow with memory enabled -workflow = PraisonAIAgents( +workflow = Agents( agents=[data_processor, status_monitor, task_runner, report_generator], tasks=initial_tasks, verbose=True, @@ -309,7 +309,7 @@ resumed_tasks = [ ] # Create new workflow instance for resumed session -resumed_workflow = PraisonAIAgents( +resumed_workflow = Agents( agents=[data_processor, status_monitor, task_runner, report_generator], tasks=resumed_tasks, verbose=True, diff --git a/examples/python/stateful/05_loop_control_with_state.py b/examples/python/stateful/05_loop_control_with_state.py index 481704e31..4f45def11 100644 --- a/examples/python/stateful/05_loop_control_with_state.py +++ b/examples/python/stateful/05_loop_control_with_state.py @@ -10,7 +10,7 @@ Run this example: python 05_loop_control_with_state.py """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time import random from datetime import datetime @@ -363,7 +363,7 @@ report_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[batch_processor, data_collector, validator, reporter], tasks=[batch_loop_task, retry_loop_task, pagination_loop_task, validation_loop_task, report_task], verbose=True, diff --git a/examples/python/stateful/06_advanced_state_operations.py b/examples/python/stateful/06_advanced_state_operations.py index 1ff592908..4a6203178 100644 --- a/examples/python/stateful/06_advanced_state_operations.py +++ b/examples/python/stateful/06_advanced_state_operations.py @@ -14,7 +14,7 @@ Run this example: python 06_advanced_state_operations.py """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import json import time import hashlib @@ -548,7 +548,7 @@ tasks = [ ] # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[state_manager, cache_manager, metrics_calculator, report_generator], tasks=tasks, verbose=True, diff --git a/examples/python/stateful/advanced-state-management-patterns.py b/examples/python/stateful/advanced-state-management-patterns.py index 3e57931f5..be36dae4b 100644 --- a/examples/python/stateful/advanced-state-management-patterns.py +++ b/examples/python/stateful/advanced-state-management-patterns.py @@ -5,7 +5,7 @@ This example demonstrates state management using PraisonAI agents with session-based state tracking and persistence. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import internet_search print("=== Advanced State Management Patterns Example ===\n") @@ -65,7 +65,7 @@ finalize_task = Task( ) # Run with state management -agents_system = PraisonAIAgents( +agents_system = Agents( agents=[state_agent], tasks=[init_task, continue_task, finalize_task], memory=True, diff --git a/examples/python/stateful/workflow-state-example.py b/examples/python/stateful/workflow-state-example.py index 031bc9492..c0e390ef7 100644 --- a/examples/python/stateful/workflow-state-example.py +++ b/examples/python/stateful/workflow-state-example.py @@ -6,7 +6,7 @@ Demonstrates advanced state management in multi-agent workflows with persistence, conditional execution, and cross-task communication. """ -from praisonaiagents import PraisonAIAgents, Agent, Task +from praisonaiagents import Agents, Agent, Task def research_tool(topic: str, num_sources: int = 5): """Simulated research tool that updates workflow state""" @@ -85,7 +85,7 @@ def main(): ) # Create stateful workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[researcher, analyzer, writer], tasks=[research_task, analysis_task, report_task], memory=True, diff --git a/examples/python/tasks/advanced-task-management.py b/examples/python/tasks/advanced-task-management.py index 202b293de..7da11bfe0 100644 --- a/examples/python/tasks/advanced-task-management.py +++ b/examples/python/tasks/advanced-task-management.py @@ -12,7 +12,7 @@ Features demonstrated: - Quality assurance workflows """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.task import TaskOutput from praisonaiagents.tools import duckduckgo from typing import Tuple, Any @@ -195,7 +195,7 @@ final_report = Task( ) # Create workflow with conditional execution -workflow = PraisonAIAgents( +workflow = Agents( agents=[research_agent, quality_checker, analyst, decision_maker, report_writer], tasks=[ initial_research, diff --git a/examples/python/telemetry/production-telemetry-example.py b/examples/python/telemetry/production-telemetry-example.py index 80f3fced0..72cf685e5 100644 --- a/examples/python/telemetry/production-telemetry-example.py +++ b/examples/python/telemetry/production-telemetry-example.py @@ -13,7 +13,7 @@ Features demonstrated: - Usage analytics and reporting """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo from praisonaiagents.telemetry import enable_telemetry import time @@ -139,7 +139,7 @@ for i, request in enumerate(customer_requests): try: # Customer service response with telemetry.trace_agent_execution("CustomerServiceAgent") as agent_trace: - agents = PraisonAIAgents( + agents = Agents( agents=[customer_service_agent], tasks=[customer_task], verbose=False # Reduce verbosity for telemetry demo @@ -162,7 +162,7 @@ for i, request in enumerate(customer_requests): context=[customer_task] ) - tech_agents = PraisonAIAgents( + tech_agents = Agents( agents=[technical_support_agent], tasks=[tech_task], verbose=False @@ -183,7 +183,7 @@ for i, request in enumerate(customer_requests): agent=quality_assurance_agent ) - qa_agents = PraisonAIAgents( + qa_agents = Agents( agents=[quality_assurance_agent], tasks=[qa_task], verbose=False diff --git a/examples/python/token-metrics/01_basic_token_tracking.py b/examples/python/token-metrics/01_basic_token_tracking.py index af356b3af..6b82229e6 100644 --- a/examples/python/token-metrics/01_basic_token_tracking.py +++ b/examples/python/token-metrics/01_basic_token_tracking.py @@ -4,7 +4,7 @@ This example demonstrates the simplest way to enable token metrics tracking using just Agent(metrics=True). The token usage summary will be automatically displayed when tasks complete! """ -from praisonaiagents import PraisonAIAgents, Agent, Task +from praisonaiagents import Agents, Agent, Task def main(): # Create a simple agent with metrics=True - that's it! @@ -26,7 +26,7 @@ def main(): ) # Initialize the agents system - agents = PraisonAIAgents( + agents = Agents( agents=[research_agent], tasks=[research_task], verbose=True diff --git a/examples/python/token-metrics/02_session_metrics.py b/examples/python/token-metrics/02_session_metrics.py index 8f6098a8c..666ac6c08 100644 --- a/examples/python/token-metrics/02_session_metrics.py +++ b/examples/python/token-metrics/02_session_metrics.py @@ -4,7 +4,7 @@ This example shows how to track token usage across multiple agents with the simplified Agent(metrics=True) approach. Metrics are automatically displayed when any agent has metrics enabled! """ -from praisonaiagents import PraisonAIAgents, Agent, Task +from praisonaiagents import Agents, Agent, Task def main(): # Create multiple agents - just add metrics=True to enable tracking @@ -43,7 +43,7 @@ def main(): ) # Initialize the agents system - agents = PraisonAIAgents( + agents = Agents( agents=[analyst_agent, writer_agent], tasks=[analysis_task, writing_task], verbose=True diff --git a/examples/python/token-metrics/03_cost_estimation.py b/examples/python/token-metrics/03_cost_estimation.py index d75453a61..245c05840 100644 --- a/examples/python/token-metrics/03_cost_estimation.py +++ b/examples/python/token-metrics/03_cost_estimation.py @@ -4,7 +4,7 @@ This example demonstrates automatic token metrics and cost tracking using just Agent(metrics=True). All tracking and display is automatic! For custom cost calculations, you can still access the detailed reports. """ -from praisonaiagents import PraisonAIAgents, Agent, Task +from praisonaiagents import Agents, Agent, Task def main(): # Create agents with metrics=True for automatic cost tracking @@ -58,7 +58,7 @@ def main(): ) # Initialize and run - agents = PraisonAIAgents( + agents = Agents( agents=[research_agent, strategy_agent], tasks=[research_task, strategy_task], verbose=True diff --git a/examples/python/token-metrics/04_telemetry_integration.py b/examples/python/token-metrics/04_telemetry_integration.py index e598370ac..921eddac3 100644 --- a/examples/python/token-metrics/04_telemetry_integration.py +++ b/examples/python/token-metrics/04_telemetry_integration.py @@ -6,7 +6,7 @@ telemetry system for comprehensive monitoring and analytics. Demonstrates privacy-first tracking and export capabilities. """ -from praisonaiagents import PraisonAIAgents, Agent, Task +from praisonaiagents import Agents, Agent, Task import json def export_metrics_to_file(agents, filename="token_metrics_export.json"): @@ -128,7 +128,7 @@ def main(): ) # Initialize with telemetry awareness - agents = PraisonAIAgents( + agents = Agents( agents=[data_agent, monitor_agent], tasks=[processing_task, monitoring_task], verbose=True diff --git a/examples/python/token-metrics/05_advanced_agent_integration.py b/examples/python/token-metrics/05_advanced_agent_integration.py index f41e59845..600deae58 100644 --- a/examples/python/token-metrics/05_advanced_agent_integration.py +++ b/examples/python/token-metrics/05_advanced_agent_integration.py @@ -8,7 +8,7 @@ This example demonstrates advanced token tracking features including: - Token budget enforcement """ -from praisonaiagents import PraisonAIAgents, Agent, Task +from praisonaiagents import Agents, Agent, Task import time class TokenBudgetManager: @@ -200,7 +200,7 @@ def main(): ) # Initialize agents system - agents = PraisonAIAgents( + agents = Agents( agents=[researcher_agent, summarizer_agent, optimizer_agent], tasks=[research_task, summary_task, optimization_task], verbose=True diff --git a/examples/python/tools/cli/app.py b/examples/python/tools/cli/app.py index 8945d0284..a8f3beb56 100644 --- a/examples/python/tools/cli/app.py +++ b/examples/python/tools/cli/app.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import subprocess import os @@ -57,7 +57,7 @@ task = Task( agent=system_ops_agent, ) -agents = PraisonAIAgents( +agents = Agents( agents=[system_ops_agent], tasks=[task], process="sequential" diff --git a/examples/python/tools/e2b/app.py b/examples/python/tools/e2b/app.py index d60494363..98adfa330 100644 --- a/examples/python/tools/e2b/app.py +++ b/examples/python/tools/e2b/app.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs +from praisonaiagents import Agent, Task, Agents, error_logs import json from e2b_code_interpreter import Sandbox @@ -83,7 +83,7 @@ blog_writing_task = Task( ) # 3) Create and run Agents manager -agents_manager = PraisonAIAgents( +agents_manager = Agents( agents=[web_scraper_agent, url_data_extractor_agent, blog_writer_agent], tasks=[task_url_extraction, task_data_extraction, blog_writing_task], verbose=True, diff --git a/examples/python/tools/e2b/single_agent.py b/examples/python/tools/e2b/single_agent.py index 9f45b165f..6b3900645 100644 --- a/examples/python/tools/e2b/single_agent.py +++ b/examples/python/tools/e2b/single_agent.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs +from praisonaiagents import Agent, Task, Agents, error_logs import json, os from e2b_code_interpreter import Sandbox import subprocess @@ -66,7 +66,7 @@ task = Task( agent=web_scraper_agent, ) -agents = PraisonAIAgents( +agents = Agents( agents=[web_scraper_agent], tasks=[task], process="sequential" diff --git a/examples/python/tools/exa-tool/Finance_Market_Job_Agents/Financial_Coaching_Agent.py b/examples/python/tools/exa-tool/Finance_Market_Job_Agents/Financial_Coaching_Agent.py index 4b93438b8..52a49eb5b 100644 --- a/examples/python/tools/exa-tool/Finance_Market_Job_Agents/Financial_Coaching_Agent.py +++ b/examples/python/tools/exa-tool/Finance_Market_Job_Agents/Financial_Coaching_Agent.py @@ -2,7 +2,7 @@ # coding: utf-8 """ -News and Podcast Aggregator Agent using PraisonAIAgents +News and Podcast Aggregator Agent using Agents This script summarizes news articles and generates podcast-style discussion points. It is CI-friendly: it uses dummy data if API keys are not set. diff --git a/examples/python/tools/exa-tool/Health_Fitness_Agents/Air_Quality_Analysis_Agent.py b/examples/python/tools/exa-tool/Health_Fitness_Agents/Air_Quality_Analysis_Agent.py index c3e1c2885..94d8f6082 100644 --- a/examples/python/tools/exa-tool/Health_Fitness_Agents/Air_Quality_Analysis_Agent.py +++ b/examples/python/tools/exa-tool/Health_Fitness_Agents/Air_Quality_Analysis_Agent.py @@ -2,7 +2,7 @@ # coding: utf-8 """ -Air Quality Analysis Agent using PraisonAIAgents +Air Quality Analysis Agent using Agents This script retrieves real-time air quality data for a specified location, analyzes the results, and provides actionable health recommendations. It uses only praisonaiagents and is CI-friendly: it uses dummy data if API keys are not set. diff --git a/examples/python/tools/exa-tool/Programming_Code_Analysis_Agents/Game_Playing_Agent_Tic_Tac_Toe.py b/examples/python/tools/exa-tool/Programming_Code_Analysis_Agents/Game_Playing_Agent_Tic_Tac_Toe.py index 75aa7f234..068cbefb0 100644 --- a/examples/python/tools/exa-tool/Programming_Code_Analysis_Agents/Game_Playing_Agent_Tic_Tac_Toe.py +++ b/examples/python/tools/exa-tool/Programming_Code_Analysis_Agents/Game_Playing_Agent_Tic_Tac_Toe.py @@ -2,7 +2,7 @@ # coding: utf-8 """ -Game Playing Agent (Tic Tac Toe) using PraisonAIAgents +Game Playing Agent (Tic Tac Toe) using Agents Two AI agents play against each other, coordinated by a referee agent. This script is CI-friendly: it uses dummy moves if API keys are not set. diff --git a/examples/python/tools/exa-tool/Research_Knowledge_QA_Agents/Domain_Deep_Research_Agent.py b/examples/python/tools/exa-tool/Research_Knowledge_QA_Agents/Domain_Deep_Research_Agent.py index 1a3daed6e..9b4af035e 100644 --- a/examples/python/tools/exa-tool/Research_Knowledge_QA_Agents/Domain_Deep_Research_Agent.py +++ b/examples/python/tools/exa-tool/Research_Knowledge_QA_Agents/Domain_Deep_Research_Agent.py @@ -2,7 +2,7 @@ # coding: utf-8 """ -Domain Deep Research Agent using PraisonAIAgents +Domain Deep Research Agent using Agents This script performs deep research on a given topic and provides a structured report. It is CI-friendly: it uses dummy data if API keys are not set. diff --git a/examples/python/tools/exa-tool/SocialMedia_Content_Agents/News_And_Podcast_Aggregator_Agent.py b/examples/python/tools/exa-tool/SocialMedia_Content_Agents/News_And_Podcast_Aggregator_Agent.py index 7e45a7a0a..f900ccc68 100644 --- a/examples/python/tools/exa-tool/SocialMedia_Content_Agents/News_And_Podcast_Aggregator_Agent.py +++ b/examples/python/tools/exa-tool/SocialMedia_Content_Agents/News_And_Podcast_Aggregator_Agent.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf-8 -# # News and Podcast Aggregator Agent using PraisonAIAgents +# # News and Podcast Aggregator Agent using Agents # This notebook demonstrates a News and Podcast Aggregator Agent built with `praisonaiagents`. # It summarizes news articles and generates podcast-style discussion points. diff --git a/examples/python/tools/langchain/agentql-toolkit.py b/examples/python/tools/langchain/agentql-toolkit.py index 2b0b410a9..e57b2eaea 100644 --- a/examples/python/tools/langchain/agentql-toolkit.py +++ b/examples/python/tools/langchain/agentql-toolkit.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_agentql.tools import ExtractWebDataTool from dotenv import load_dotenv @@ -23,5 +23,5 @@ orchestration_agent = Agent( ) # Initialize and run agents -agents = PraisonAIAgents(agents=[orchestration_agent]) +agents = Agents(agents=[orchestration_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/azure-code-interpreter.py b/examples/python/tools/langchain/azure-code-interpreter.py index 8f940bb53..946b26100 100644 --- a/examples/python/tools/langchain/azure-code-interpreter.py +++ b/examples/python/tools/langchain/azure-code-interpreter.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents import getpass from langchain_azure_dynamic_sessions import SessionsPythonREPLTool @@ -8,5 +8,5 @@ coder_agent = Agent(instructions="""word = "strawberry" count = word.count("r") print(f"There are {count}'R's in the word 'Strawberry'")""", tools=[SessionsPythonREPLTool]) -agents = PraisonAIAgents(agents=[coder_agent]) +agents = Agents(agents=[coder_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/bearly-code-interpreter.py b/examples/python/tools/langchain/bearly-code-interpreter.py index 5663d1154..a9632f08f 100644 --- a/examples/python/tools/langchain/bearly-code-interpreter.py +++ b/examples/python/tools/langchain/bearly-code-interpreter.py @@ -1,8 +1,8 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.tools import BearlyInterpreterTool coder_agent = Agent(instructions="""for i in range(0,10): print(f'The number is {i}')""", tools=[BearlyInterpreterTool]) -agents = PraisonAIAgents(agents=[coder_agent]) +agents = Agents(agents=[coder_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/brave-search.py b/examples/python/tools/langchain/brave-search.py index 14d0fdb2f..a39770ba2 100644 --- a/examples/python/tools/langchain/brave-search.py +++ b/examples/python/tools/langchain/brave-search.py @@ -2,7 +2,7 @@ # export BRAVE_SEARCH_API=your_api_key_here # export OPENAI_API_KEY=your_api_key_here -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.tools import BraveSearch import os @@ -14,5 +14,5 @@ def search_brave(query: str): data_agent = Agent(instructions="Search about AI job trends in 2025", tools=[search_brave]) editor_agent = Agent(instructions="Write a blog article") -agents = PraisonAIAgents(agents=[data_agent, editor_agent]) +agents = Agents(agents=[data_agent, editor_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/duckduckgo-search.py b/examples/python/tools/langchain/duckduckgo-search.py index 87843ae2e..971f32d31 100644 --- a/examples/python/tools/langchain/duckduckgo-search.py +++ b/examples/python/tools/langchain/duckduckgo-search.py @@ -1,7 +1,7 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from praisonaiagents.tools import duckduckgo data_agent = Agent(instructions="Search and Read Research Papers on DNA Mutation", tools=[duckduckgo]) editor_agent = Agent(instructions="Write a scientifically researched outcome and findings about DNA Mutation") -agents = PraisonAIAgents(agents=[data_agent, editor_agent]) +agents = Agents(agents=[data_agent, editor_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/exa-search.py b/examples/python/tools/langchain/exa-search.py index 2e57b558c..a2821991f 100644 --- a/examples/python/tools/langchain/exa-search.py +++ b/examples/python/tools/langchain/exa-search.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from exa_py import Exa import os @@ -13,5 +13,5 @@ def search_and_contents(query: str): data_agent = Agent(instructions="Find the latest jobs for Video Editor in New York at startups", tools=[search_and_contents]) editor_agent = Agent(instructions="Curate the available jobs at startups and their email for the candidate to apply based on his skills on Canva, Adobe Premiere Pro, and Adobe After Effects") -agents = PraisonAIAgents(agents=[data_agent, editor_agent], process='hierarchical') +agents = Agents(agents=[data_agent, editor_agent], process='hierarchical') agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/google-search.py b/examples/python/tools/langchain/google-search.py index 0830b3e8c..9d0b34862 100644 --- a/examples/python/tools/langchain/google-search.py +++ b/examples/python/tools/langchain/google-search.py @@ -1,8 +1,8 @@ import os from langchain_google_community import GoogleSearchAPIWrapper -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents data_agent = Agent(instructions="Search about best places to visit in India during Summer", tools=[GoogleSearchAPIWrapper]) editor_agent = Agent(instructions="Write a blog article") -agents = PraisonAIAgents(agents=[data_agent, editor_agent], process='hierarchical') +agents = Agents(agents=[data_agent, editor_agent], process='hierarchical') agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/google-serper-search.py b/examples/python/tools/langchain/google-serper-search.py index bf2f492c3..557d9c392 100644 --- a/examples/python/tools/langchain/google-serper-search.py +++ b/examples/python/tools/langchain/google-serper-search.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.utilities import GoogleSerperAPIWrapper import os from dotenv import load_dotenv @@ -11,5 +11,5 @@ search = GoogleSerperAPIWrapper() data_agent = Agent(instructions="Suggest me top 5 most visited websites for Dosa Recipe", tools=[search]) editor_agent = Agent(instructions="List out the websites with their url and a short description") -agents = PraisonAIAgents(agents=[data_agent, editor_agent]) +agents = Agents(agents=[data_agent, editor_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/google-trends.py b/examples/python/tools/langchain/google-trends.py index 32ba7ebd8..f6abcf4fa 100644 --- a/examples/python/tools/langchain/google-trends.py +++ b/examples/python/tools/langchain/google-trends.py @@ -3,7 +3,7 @@ # export OPENAI_API_KEY=your_api_key_here from langchain_community.utilities.google_trends import GoogleTrendsAPIWrapper -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents research_agent = Agent( instructions="Research trending topics related to AI", @@ -14,5 +14,5 @@ summarise_agent = Agent( instructions="Summarise findings from the research agent", ) -agents = PraisonAIAgents(agents=[research_agent, summarise_agent]) +agents = Agents(agents=[research_agent, summarise_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/jina-code-interpreter.py b/examples/python/tools/langchain/jina-code-interpreter.py index fcede37d3..5c18259d9 100644 --- a/examples/python/tools/langchain/jina-code-interpreter.py +++ b/examples/python/tools/langchain/jina-code-interpreter.py @@ -1,9 +1,9 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.tools.riza.command import ExecPython coder_agent = Agent(instructions="""word = "strawberry" count = word.count("r") print(f"There are {count}'R's in the word 'Strawberry'")""", tools=[ExecPython]) -agents = PraisonAIAgents(agents=[coder_agent]) +agents = Agents(agents=[coder_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/jina-search.py b/examples/python/tools/langchain/jina-search.py index 13b5c1df1..46e2380bd 100644 --- a/examples/python/tools/langchain/jina-search.py +++ b/examples/python/tools/langchain/jina-search.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.tools import JinaSearch import os @@ -15,5 +15,5 @@ def invoke_jina_search(query: str): data_agent = Agent(instructions="Find 10 websites where I can learn coding for free", tools=[invoke_jina_search]) editor_agent = Agent(instructions="write a listicle blog ranking the best websites. The blog should contain a proper intro and conclusion") -agents = PraisonAIAgents(agents=[data_agent, editor_agent], process='hierarchical') +agents = Agents(agents=[data_agent, editor_agent], process='hierarchical') agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/searchapi-search.py b/examples/python/tools/langchain/searchapi-search.py index 006a7e1b8..c162e4885 100644 --- a/examples/python/tools/langchain/searchapi-search.py +++ b/examples/python/tools/langchain/searchapi-search.py @@ -1,8 +1,8 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.utilities import SearchApiAPIWrapper data_agent = Agent(instructions="I am looking for the top google searches of 2025", tools=[SearchApiAPIWrapper]) editor_agent = Agent(instructions="Analyze the data and derive insights") -agents = PraisonAIAgents(agents=[data_agent, editor_agent]) +agents = Agents(agents=[data_agent, editor_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/serp-api.py b/examples/python/tools/langchain/serp-api.py index 230a2901e..fac3b9eca 100644 --- a/examples/python/tools/langchain/serp-api.py +++ b/examples/python/tools/langchain/serp-api.py @@ -2,11 +2,11 @@ # export SERPAPI_API_KEY=your_api_key_here # export OPENAI_API_KEY=your_api_key_here -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.utilities import SerpAPIWrapper data_agent = Agent(instructions="Search about AI job trends in 2025", tools=[SerpAPIWrapper]) editor_agent = Agent(instructions="Write a blog article") -agents = PraisonAIAgents(agents=[data_agent, editor_agent]) +agents = Agents(agents=[data_agent, editor_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/serp-search.py b/examples/python/tools/langchain/serp-search.py index 272aa667e..967603952 100644 --- a/examples/python/tools/langchain/serp-search.py +++ b/examples/python/tools/langchain/serp-search.py @@ -1,7 +1,7 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.utilities import SerpAPIWrapper data_agent = Agent(instructions="Search about decline of recruitment across various industries with the rise of AI", tools=[SerpAPIWrapper]) editor_agent = Agent(instructions="Write a blog article pointing out the jobs most at rish due to the rise of AI") -agents = PraisonAIAgents(agents=[data_agent, editor_agent]) +agents = Agents(agents=[data_agent, editor_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/tavily-search.py b/examples/python/tools/langchain/tavily-search.py index 64614340c..0c17b7734 100644 --- a/examples/python/tools/langchain/tavily-search.py +++ b/examples/python/tools/langchain/tavily-search.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.tools import TavilySearchResults def search_tool(query: str): @@ -14,5 +14,5 @@ def search_tool(query: str): data_agent = Agent(instructions="I am looking for the top google searches on AI tools of 2025", tools=[search_tool]) editor_agent = Agent(instructions="Analyze the data and rank the tools based on their popularity") -agents = PraisonAIAgents(agents=[data_agent, editor_agent]) +agents = Agents(agents=[data_agent, editor_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/wikipedia-search.py b/examples/python/tools/langchain/wikipedia-search.py index f6b3f85ba..1f09fe524 100644 --- a/examples/python/tools/langchain/wikipedia-search.py +++ b/examples/python/tools/langchain/wikipedia-search.py @@ -1,7 +1,7 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.utilities import WikipediaAPIWrapper data_agent = Agent(instructions="Gather all of Messi's record in LaLiga", tools=[WikipediaAPIWrapper]) summarise_agent = Agent(instructions="Summarize the data into a well structured format") -agents = PraisonAIAgents(agents=[data_agent, summarise_agent]) +agents = Agents(agents=[data_agent, summarise_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/langchain/you-search.py b/examples/python/tools/langchain/you-search.py index 1a00cf384..246ec3be3 100644 --- a/examples/python/tools/langchain/you-search.py +++ b/examples/python/tools/langchain/you-search.py @@ -1,8 +1,8 @@ -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from langchain_community.utilities.you import YouSearchAPIWrapper data_agent = Agent(instructions="Gather the weather data for Barcelona", tools=[YouSearchAPIWrapper]) editor_agent = Agent(instructions="Breifly describe the weather in Barcelona") -agents = PraisonAIAgents(agents=[data_agent, editor_agent]) +agents = Agents(agents=[data_agent, editor_agent]) agents.start() \ No newline at end of file diff --git a/examples/python/tools/trafilatura/trafilatura_example.py b/examples/python/tools/trafilatura/trafilatura_example.py index 5165f42c9..fc8d2ea73 100644 --- a/examples/python/tools/trafilatura/trafilatura_example.py +++ b/examples/python/tools/trafilatura/trafilatura_example.py @@ -12,7 +12,7 @@ pip install trafilatura newspaper3k requests beautifulsoup4 """ import asyncio -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from custom_trafilatura_tools import TrafilaturaTools, create_trafilatura_tools # Create tools instance (global for reuse across examples) @@ -131,7 +131,7 @@ async def agent_example(): ) # Run the analysis - agents = PraisonAIAgents( + agents = Agents( agents=[research_agent], tasks=[analysis_task] ) diff --git a/examples/python/usecases/adaptive-learning.py b/examples/python/usecases/adaptive-learning.py index 23e09d443..230ed6eec 100644 --- a/examples/python/usecases/adaptive-learning.py +++ b/examples/python/usecases/adaptive-learning.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict @@ -105,7 +105,7 @@ adaptation_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[assessor, generator, evaluator, adapter], tasks=[assessment_task, generation_task, evaluation_task, adaptation_task], process="workflow", diff --git a/examples/python/usecases/analysis/code-analysis-agents.py b/examples/python/usecases/analysis/code-analysis-agents.py index 9012173d4..d80862827 100644 --- a/examples/python/usecases/analysis/code-analysis-agents.py +++ b/examples/python/usecases/analysis/code-analysis-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict from gitingest import ingest @@ -83,7 +83,7 @@ def analyze_code(code_source: str) -> CodeAnalysisReport: """ # Initialize and run analysis - agents = PraisonAIAgents( + agents = Agents( agents=[code_analyzer], tasks=[code_analysis_task] ) diff --git a/examples/python/usecases/analysis/code-analysis-streamlit.py b/examples/python/usecases/analysis/code-analysis-streamlit.py index d35163aa3..504819372 100644 --- a/examples/python/usecases/analysis/code-analysis-streamlit.py +++ b/examples/python/usecases/analysis/code-analysis-streamlit.py @@ -1,5 +1,5 @@ import streamlit as st -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict, Any from gitingest import ingest @@ -87,7 +87,7 @@ def analyze_code(code_source: str) -> CodeAnalysisReport: """ # Initialize and run analysis - agents = PraisonAIAgents( + agents = Agents( agents=[code_analyzer], tasks=[code_analysis_task] ) diff --git a/examples/python/usecases/analysis/cv-analysis.py b/examples/python/usecases/analysis/cv-analysis.py index 91be7dbee..4b4980c2a 100644 --- a/examples/python/usecases/analysis/cv-analysis.py +++ b/examples/python/usecases/analysis/cv-analysis.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict @@ -77,7 +77,7 @@ final_evaluation_task = Task( ) # Create and run the agents -agents = PraisonAIAgents( +agents = Agents( agents=[skill_analyst, experience_analyst, cv_evaluator], tasks=[skills_analysis_task, experience_analysis_task, final_evaluation_task], process="sequential", diff --git a/examples/python/usecases/analysis/hackathon-judge-agent.py b/examples/python/usecases/analysis/hackathon-judge-agent.py index b148b98ac..4139f4d0a 100644 --- a/examples/python/usecases/analysis/hackathon-judge-agent.py +++ b/examples/python/usecases/analysis/hackathon-judge-agent.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict import os @@ -64,7 +64,7 @@ def evaluate_project(video_path: str) -> ProjectEvaluation: ) # Initialize and run evaluation - agents = PraisonAIAgents( + agents = Agents( agents=[hackathon_judge], tasks=[evaluation_task], process="sequential", diff --git a/examples/python/usecases/analysis/hackathon-judge-streamlit.py b/examples/python/usecases/analysis/hackathon-judge-streamlit.py index 8e574351f..98ab8d7d7 100644 --- a/examples/python/usecases/analysis/hackathon-judge-streamlit.py +++ b/examples/python/usecases/analysis/hackathon-judge-streamlit.py @@ -1,6 +1,6 @@ import streamlit as st import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict import tempfile @@ -77,7 +77,7 @@ def evaluate_project(video_path: str) -> ProjectEvaluation: ) # Initialize and run evaluation - agents = PraisonAIAgents( + agents = Agents( agents=[hackathon_judge], tasks=[evaluation_task], process="sequential", diff --git a/examples/python/usecases/climate-impact.py b/examples/python/usecases/climate-impact.py index 635241211..d6a4c55f5 100644 --- a/examples/python/usecases/climate-impact.py +++ b/examples/python/usecases/climate-impact.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -186,7 +186,7 @@ strategy_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[environmental_monitor, urban_analyzer, climate_modeler, impact_predictor, strategy_generator], tasks=[monitoring_task, urban_task, modeling_task, diff --git a/examples/python/usecases/code-review.py b/examples/python/usecases/code-review.py index 5114f4eb6..294bfbec1 100644 --- a/examples/python/usecases/code-review.py +++ b/examples/python/usecases/code-review.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import List, Dict @@ -81,7 +81,7 @@ fix_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[analyzer, fix_suggester, fix_applier], tasks=[analysis_task, suggestion_task, fix_task], process="workflow", diff --git a/examples/python/usecases/crypto-validator.py b/examples/python/usecases/crypto-validator.py index 92d953b99..295092491 100644 --- a/examples/python/usecases/crypto-validator.py +++ b/examples/python/usecases/crypto-validator.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -204,7 +204,7 @@ compliance_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[crypto_analyzer, attack_simulator, performance_benchmarker, implementation_assessor, compliance_validator], tasks=[analysis_task, attack_task, benchmark_task, diff --git a/examples/python/usecases/customer-service.py b/examples/python/usecases/customer-service.py index 8adbe9257..c8010942d 100644 --- a/examples/python/usecases/customer-service.py +++ b/examples/python/usecases/customer-service.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List @@ -112,7 +112,7 @@ optimization_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[classifier, handler, evaluator, optimizer], tasks=[classification_task, handling_task, evaluation_task, optimization_task], process="workflow", diff --git a/examples/python/usecases/defi-market-maker.py b/examples/python/usecases/defi-market-maker.py index 58a3b543d..23a52ec62 100644 --- a/examples/python/usecases/defi-market-maker.py +++ b/examples/python/usecases/defi-market-maker.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -190,7 +190,7 @@ execution_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[market_analyzer, arbitrage_detector, liquidity_optimizer, risk_assessor, trade_executor], tasks=[market_task, arbitrage_task, liquidity_task, diff --git a/examples/python/usecases/disaster-recovery.py b/examples/python/usecases/disaster-recovery.py index 769d55426..d4410cd7c 100644 --- a/examples/python/usecases/disaster-recovery.py +++ b/examples/python/usecases/disaster-recovery.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -381,7 +381,7 @@ monitoring_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[network_monitor, emergency_assessor, resource_assessor, priority_analyzer, distribution_planner, execution_manager, effectiveness_monitor], diff --git a/examples/python/usecases/domain-context-solution.py b/examples/python/usecases/domain-context-solution.py index 842eda692..48de39e05 100644 --- a/examples/python/usecases/domain-context-solution.py +++ b/examples/python/usecases/domain-context-solution.py @@ -19,7 +19,7 @@ import json import base64 from dotenv import load_dotenv from qdrant_client import QdrantClient -from praisonaiagents import Agent, Task, PraisonAIAgents, Memory +from praisonaiagents import Agent, Task, Agents, Memory # Load environment variables from .env.local if not load_dotenv(dotenv_path=".env.local"): @@ -263,7 +263,7 @@ ciso_review_task = Task( ) # SOLUTION 4: Agents with Shared Memory Configuration -agents = PraisonAIAgents( +agents = Agents( agents=[manager_agent, tool_agent, sr_pentester_agent, ciso_agent], tasks=[tool_query_task, pentester_analysis_task, ciso_review_task], verbose=True, diff --git a/examples/python/usecases/emergency-response.py b/examples/python/usecases/emergency-response.py index c76b187e8..49f32d0c0 100644 --- a/examples/python/usecases/emergency-response.py +++ b/examples/python/usecases/emergency-response.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List @@ -105,7 +105,7 @@ coordinate_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[router, dispatcher, monitor, synthesizer], tasks=[assessment_task, dispatch_task, monitor_task, coordinate_task], process="workflow", diff --git a/examples/python/usecases/fraud-detection.py b/examples/python/usecases/fraud-detection.py index 7ea6fba2a..ccd136a96 100644 --- a/examples/python/usecases/fraud-detection.py +++ b/examples/python/usecases/fraud-detection.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -109,7 +109,7 @@ alert_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[transaction_analyzer, pattern_checker, identity_verifier, alert_generator], tasks=[analysis_task, pattern_task, verification_task, alert_task], process="workflow", diff --git a/examples/python/usecases/healthcare-diagnosis.py b/examples/python/usecases/healthcare-diagnosis.py index 2f6749e02..ea3b2f9bc 100644 --- a/examples/python/usecases/healthcare-diagnosis.py +++ b/examples/python/usecases/healthcare-diagnosis.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List @@ -136,7 +136,7 @@ treatment_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[symptom_analyzer, lab_processor, history_analyzer, diagnosis_generator, treatment_recommender], tasks=[symptom_task, lab_task, history_task, diagnosis_task, treatment_task], diff --git a/examples/python/usecases/medicine-protocol.py b/examples/python/usecases/medicine-protocol.py index 6b93c6290..d3f6580d6 100644 --- a/examples/python/usecases/medicine-protocol.py +++ b/examples/python/usecases/medicine-protocol.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -188,7 +188,7 @@ simulation_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[genetic_analyzer, history_analyzer, interaction_analyzer, protocol_generator, effectiveness_simulator], tasks=[genetic_task, history_task, interaction_task, diff --git a/examples/python/usecases/multilingual-content.py b/examples/python/usecases/multilingual-content.py index d73b5ccbc..3bcbcddfa 100644 --- a/examples/python/usecases/multilingual-content.py +++ b/examples/python/usecases/multilingual-content.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List @@ -132,7 +132,7 @@ quality_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[content_generator, translator, cultural_checker, content_adapter, quality_assessor], tasks=[generation_task, translation_task, cultural_task, diff --git a/examples/python/usecases/neural-architecture.py b/examples/python/usecases/neural-architecture.py index 8a6b01b2f..d90e8b38d 100644 --- a/examples/python/usecases/neural-architecture.py +++ b/examples/python/usecases/neural-architecture.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -173,7 +173,7 @@ deployment_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[hardware_analyzer, architecture_generator, hyperparameter_optimizer, performance_estimator, deployment_optimizer], tasks=[hardware_task, architecture_task, hyperparameter_task, diff --git a/examples/python/usecases/predictive-maintenance.py b/examples/python/usecases/predictive-maintenance.py index 7eabc5c48..ecd08e4a8 100644 --- a/examples/python/usecases/predictive-maintenance.py +++ b/examples/python/usecases/predictive-maintenance.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -151,7 +151,7 @@ scheduling_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[sensor_monitor, performance_analyzer, anomaly_detector, failure_predictor, maintenance_scheduler], tasks=[sensor_task, performance_task, anomaly_task, diff --git a/examples/python/usecases/quantum-optimiser.py b/examples/python/usecases/quantum-optimiser.py index ae1a79b5a..55f563939 100644 --- a/examples/python/usecases/quantum-optimiser.py +++ b/examples/python/usecases/quantum-optimiser.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -168,7 +168,7 @@ validation_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[circuit_analyzer, optimization_finder, optimizer, benchmarker, validator], tasks=[analysis_task, optimization_task, optimization_execution_task, diff --git a/examples/python/usecases/research-assistant.py b/examples/python/usecases/research-assistant.py index 2c42258b3..e08f67ee2 100644 --- a/examples/python/usecases/research-assistant.py +++ b/examples/python/usecases/research-assistant.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -163,7 +163,7 @@ prediction_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[paper_analyzer, gap_identifier, experiment_designer, methodology_validator, impact_predictor], tasks=[analysis_task, gap_task, design_task, diff --git a/examples/python/usecases/secondary-market-research.py b/examples/python/usecases/secondary-market-research.py index d292cd607..19d174a73 100644 --- a/examples/python/usecases/secondary-market-research.py +++ b/examples/python/usecases/secondary-market-research.py @@ -13,7 +13,7 @@ Features: - FastAPI integration ready """ -from praisonaiagents import Agent, Task, PraisonAIAgents, Tools +from praisonaiagents import Agent, Task, Agents, Tools from typing import Dict, List, Any, Optional import asyncio import json @@ -280,7 +280,7 @@ async def run_market_research(config: MarketResearchConfig) -> Dict[str, Any]: tasks = create_research_tasks(agents, config) # Create workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=list(agents.values()), tasks=tasks, process="workflow", diff --git a/examples/python/usecases/smart-city.py b/examples/python/usecases/smart-city.py index 1322b9643..f00d5d979 100644 --- a/examples/python/usecases/smart-city.py +++ b/examples/python/usecases/smart-city.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List @@ -157,7 +157,7 @@ feedback_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[utility_monitor, pattern_analyzer, resource_optimizer, implementation_agent, feedback_monitor], tasks=[monitoring_task, pattern_task, optimization_task, diff --git a/examples/python/usecases/space-mission.py b/examples/python/usecases/space-mission.py index 66d5daac1..20683de42 100644 --- a/examples/python/usecases/space-mission.py +++ b/examples/python/usecases/space-mission.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -202,7 +202,7 @@ simulation_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[mission_analyzer, resource_calculator, contingency_planner, resource_optimizer, scenario_simulator], tasks=[mission_task, resource_task, contingency_task, diff --git a/examples/python/usecases/supply-chain.py b/examples/python/usecases/supply-chain.py index 14cba9bc8..b5e83dcd3 100644 --- a/examples/python/usecases/supply-chain.py +++ b/examples/python/usecases/supply-chain.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List @@ -86,7 +86,7 @@ strategy_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[monitor_agent, impact_analyzer, strategy_generator], tasks=[monitoring_task, impact_task, strategy_task], process="workflow", diff --git a/examples/python/usecases/vulnerability-detection.py b/examples/python/usecases/vulnerability-detection.py index 439853a14..e732700a1 100644 --- a/examples/python/usecases/vulnerability-detection.py +++ b/examples/python/usecases/vulnerability-detection.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import Dict, List import asyncio @@ -166,7 +166,7 @@ validation_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[pattern_scanner, vector_analyzer, exploit_simulator, signature_generator, finding_validator], tasks=[scanning_task, vector_task, simulation_task, diff --git a/examples/python/workflows/task_callbacks.py b/examples/python/workflows/task_callbacks.py index f329d6ff0..4c604f553 100644 --- a/examples/python/workflows/task_callbacks.py +++ b/examples/python/workflows/task_callbacks.py @@ -2,10 +2,10 @@ Task Callbacks Example Demonstrates using on_task_start and on_task_complete callbacks -with PraisonAIAgents for workflow monitoring and logging. +with Agents for workflow monitoring and logging. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create an agent researcher = Agent( @@ -43,7 +43,7 @@ def on_complete(task, output): if __name__ == "__main__": # Create agents with callbacks - agents = PraisonAIAgents( + agents = Agents( agents=[researcher], tasks=[task1, task2], process="workflow", diff --git a/examples/rag/rag_multi_agent.py b/examples/rag/rag_multi_agent.py index edc0a7c1a..a141a0c22 100644 --- a/examples/rag/rag_multi_agent.py +++ b/examples/rag/rag_multi_agent.py @@ -8,7 +8,7 @@ Usage: python rag_multi_agent.py """ -from praisonaiagents import Agent, PraisonAIAgents, Task +from praisonaiagents import Agent, Agents, Task # Shared knowledge base content @@ -114,7 +114,7 @@ def main(): # Run the multi-agent workflow print("\nšŸ”„ Running multi-agent workflow...") - agents = PraisonAIAgents( + agents = Agents( agents=[researcher, summarizer, writer], tasks=[research_task, summary_task, report_task], process="sequential", diff --git a/examples/serve/agent_launch_modes.py b/examples/serve/agent_launch_modes.py index 418a4d600..1102cad5d 100644 --- a/examples/serve/agent_launch_modes.py +++ b/examples/serve/agent_launch_modes.py @@ -64,7 +64,7 @@ def demo_multi_agent_launch(): print("\n--- Multi-Agent Launch ---") try: - from praisonaiagents import Agent, PraisonAIAgents + from praisonaiagents import Agent, Agents except ImportError: print("Error: praisonaiagents not installed") return False @@ -83,7 +83,7 @@ def demo_multi_agent_launch(): llm="gpt-4o-mini" ) - agents = PraisonAIAgents(agents=[researcher, writer]) + agents = Agents(agents=[researcher, writer]) print(f"Agents: {[researcher.name, writer.name]}") print("Launching as HTTP API on port 8000...") diff --git a/examples/serve/agents_as_api_router.py b/examples/serve/agents_as_api_router.py index 00b665299..e17d3613a 100644 --- a/examples/serve/agents_as_api_router.py +++ b/examples/serve/agents_as_api_router.py @@ -35,7 +35,7 @@ def main(): print("=" * 60) try: - from praisonaiagents import Agent, PraisonAIAgents + from praisonaiagents import Agent, Agents except ImportError: print("Error: praisonaiagents not installed") print("Install with: pip install praisonaiagents") @@ -71,7 +71,7 @@ def main(): print(f"Agents: {[a.name for a in agents]}") # Create multi-agent system - praison = PraisonAIAgents(agents=agents) + praison = Agents(agents=agents) print("\nLaunching multi-agent router as HTTP API...") print("Endpoints:") diff --git a/src/praisonai-agents/01_basic_token_tracking.py b/src/praisonai-agents/01_basic_token_tracking.py index af356b3af..6b82229e6 100644 --- a/src/praisonai-agents/01_basic_token_tracking.py +++ b/src/praisonai-agents/01_basic_token_tracking.py @@ -4,7 +4,7 @@ This example demonstrates the simplest way to enable token metrics tracking using just Agent(metrics=True). The token usage summary will be automatically displayed when tasks complete! """ -from praisonaiagents import PraisonAIAgents, Agent, Task +from praisonaiagents import Agents, Agent, Task def main(): # Create a simple agent with metrics=True - that's it! @@ -26,7 +26,7 @@ def main(): ) # Initialize the agents system - agents = PraisonAIAgents( + agents = Agents( agents=[research_agent], tasks=[research_task], verbose=True diff --git a/src/praisonai-agents/02_multi_agent_workflow_monitoring.py b/src/praisonai-agents/02_multi_agent_workflow_monitoring.py index cab5c3789..d199a4091 100644 --- a/src/praisonai-agents/02_multi_agent_workflow_monitoring.py +++ b/src/praisonai-agents/02_multi_agent_workflow_monitoring.py @@ -10,7 +10,7 @@ Demonstrates performance monitoring in a multi-agent workflow: Shows how to monitor complex multi-agent systems. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import ( monitor_function, track_api_call, get_function_stats, analyze_function_flow, generate_comprehensive_report @@ -101,7 +101,7 @@ def main(): with track_api_call("multi_agent_workflow"): print("\nšŸš€ Starting multi-agent workflow...") - workflow = PraisonAIAgents( + workflow = Agents( agents=[researcher, analyst, writer], tasks=[research_task, analysis_task, report_task], process="sequential", diff --git a/src/praisonai-agents/07_hierarchical_agents_monitoring.py b/src/praisonai-agents/07_hierarchical_agents_monitoring.py index 1445d8217..fc73b73f7 100644 --- a/src/praisonai-agents/07_hierarchical_agents_monitoring.py +++ b/src/praisonai-agents/07_hierarchical_agents_monitoring.py @@ -11,7 +11,7 @@ Shows how to monitor complex organizational agent structures. """ import time -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import ( monitor_function, track_api_call, get_function_stats, visualize_execution_flow, generate_comprehensive_report diff --git a/src/praisonai-agents/10_comprehensive_dashboard.py b/src/praisonai-agents/10_comprehensive_dashboard.py index d8e6924a7..3f42cef97 100644 --- a/src/praisonai-agents/10_comprehensive_dashboard.py +++ b/src/praisonai-agents/10_comprehensive_dashboard.py @@ -13,7 +13,7 @@ Shows how to create a comprehensive performance monitoring solution. import time import json from datetime import datetime, timedelta -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import ( monitor_function, track_api_call, performance_monitor, get_performance_report, get_function_stats, get_api_stats, @@ -139,7 +139,7 @@ def simulate_complex_workflow(): # Execute workflow with track_api_call("complex_workflow_execution"): - workflow = PraisonAIAgents( + workflow = Agents( agents=[planner, executor, reviewer], tasks=[planning_task, execution_task, review_task], process="sequential", diff --git a/src/praisonai-agents/agentic_parallelisation.py b/src/praisonai-agents/agentic_parallelisation.py index 1d16a4bec..cdb8240f1 100644 --- a/src/praisonai-agents/agentic_parallelisation.py +++ b/src/praisonai-agents/agentic_parallelisation.py @@ -1,5 +1,5 @@ import asyncio -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Example tools (replace with real implementations as needed) def fetch_favorite_article(): @@ -88,7 +88,7 @@ aggregate_task = Task( ) async def main(): - workflow = PraisonAIAgents( + workflow = Agents( agents=[article_agent, news_agent, twitter_agent, aggregator], tasks=[article_task, news_task, twitter_task, aggregate_task], process="workflow", diff --git a/src/praisonai-agents/async-tavily-agents-gemini.py b/src/praisonai-agents/async-tavily-agents-gemini.py index f8618422c..3c3b9872b 100644 --- a/src/praisonai-agents/async-tavily-agents-gemini.py +++ b/src/praisonai-agents/async-tavily-agents-gemini.py @@ -2,7 +2,7 @@ import asyncio import logging from typing import List, Dict, Any from pydantic import BaseModel -from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput +from praisonaiagents import Agent, Task, Agents, TaskOutput from tavily import AsyncTavilyClient import os @@ -121,7 +121,7 @@ async def run_parallel_searches(): ) # Initialize agents manager - agents = PraisonAIAgents( + agents = Agents( agents=[search_agent, summary_agent], tasks=search_tasks + [summary_task] ) diff --git a/src/praisonai-agents/benchmarks/real_benchmark.py b/src/praisonai-agents/benchmarks/real_benchmark.py index 90dc049f4..9a8ebbfd6 100644 --- a/src/praisonai-agents/benchmarks/real_benchmark.py +++ b/src/praisonai-agents/benchmarks/real_benchmark.py @@ -119,7 +119,7 @@ def benchmark_praisonai_single(iterations: int = 3) -> ExecutionResult: def benchmark_praisonai_two_agents(iterations: int = 3) -> ExecutionResult: """Benchmark 2 PraisonAI agents working together.""" - from praisonaiagents import Agent, PraisonAIAgents + from praisonaiagents import Agent, Agents result = ExecutionResult() @@ -145,7 +145,7 @@ def benchmark_praisonai_two_agents(iterations: int = 3) -> ExecutionResult: verbose=False ) - agents = PraisonAIAgents( + agents = Agents( agents=[researcher, reporter], process="sequential", verbose=False @@ -163,7 +163,7 @@ def benchmark_praisonai_two_agents(iterations: int = 3) -> ExecutionResult: def benchmark_praisonai_three_agents(iterations: int = 3) -> ExecutionResult: """Benchmark 3 PraisonAI agents working together.""" - from praisonaiagents import Agent, PraisonAIAgents + from praisonaiagents import Agent, Agents result = ExecutionResult() @@ -199,7 +199,7 @@ def benchmark_praisonai_three_agents(iterations: int = 3) -> ExecutionResult: verbose=False ) - agents = PraisonAIAgents( + agents = Agents( agents=[weather_agent, time_agent, summarizer], process="sequential", verbose=False diff --git a/src/praisonai-agents/debug_auto_instrument.py b/src/praisonai-agents/debug_auto_instrument.py index c565a1444..3d2a871de 100644 --- a/src/praisonai-agents/debug_auto_instrument.py +++ b/src/praisonai-agents/debug_auto_instrument.py @@ -10,8 +10,8 @@ print(" Telemetry module imported") print("\n2. Check if auto_instrument_all was called...") print(f" _initialized: {praisonaiagents.telemetry._initialized}") -print("\n3. Import Agent and PraisonAIAgents...") -from praisonaiagents import Agent, PraisonAIAgents +print("\n3. Import Agent and Agents...") +from praisonaiagents import Agent, Agents print(" Classes imported") print("\n4. Check if classes are instrumented...") @@ -41,4 +41,4 @@ print(f" Telemetry enabled: {telemetry.enabled}") print(f" PostHog available: {telemetry._posthog is not None}") # The key insight: auto_instrument_all needs to be called AFTER -# the Agent and PraisonAIAgents classes are imported! \ No newline at end of file +# the Agent and Agents classes are imported! \ No newline at end of file diff --git a/src/praisonai-agents/debug_telemetry.py b/src/praisonai-agents/debug_telemetry.py index 7a063b48f..94151aaa7 100644 --- a/src/praisonai-agents/debug_telemetry.py +++ b/src/praisonai-agents/debug_telemetry.py @@ -9,7 +9,7 @@ if 'PRAISONAI_TELEMETRY_DISABLED' in os.environ: del os.environ['PRAISONAI_TELEMETRY_DISABLED'] print("1. Importing modules...") -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import get_telemetry print("\n2. Checking telemetry status...") @@ -41,7 +41,7 @@ task = Task( ) print("\n6. Creating workflow...") -workflow = PraisonAIAgents( +workflow = Agents( agents=[agent], tasks=[task], process="sequential" diff --git a/src/praisonai-agents/debug_telemetry_double.py b/src/praisonai-agents/debug_telemetry_double.py index e15b66d83..f6167791f 100644 --- a/src/praisonai-agents/debug_telemetry_double.py +++ b/src/praisonai-agents/debug_telemetry_double.py @@ -3,7 +3,7 @@ Debug double-counting in telemetry. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import get_telemetry # Get telemetry instance @@ -33,7 +33,7 @@ task = Task( # Create workflow with ONE agent and ONE task print("Creating workflow with 1 agent and 1 task...") -workflow = PraisonAIAgents( +workflow = Agents( agents=[agent], tasks=[task], process="sequential" diff --git a/src/praisonai-agents/guardrail_agents_example.py b/src/praisonai-agents/guardrail_agents_example.py index 30efbe46b..b45a1d869 100644 --- a/src/praisonai-agents/guardrail_agents_example.py +++ b/src/praisonai-agents/guardrail_agents_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, TaskOutput, PraisonAIAgents +from praisonaiagents import Agent, Task, TaskOutput, Agents from typing import Tuple, Any def validate_content(task_output: TaskOutput) -> Tuple[bool, Any]: @@ -16,6 +16,6 @@ task = Task( agent=agent ) -praison_agents = PraisonAIAgents(agents=[agent], tasks=[task]) +praison_agents = Agents(agents=[agent], tasks=[task]) praison_agents.start() diff --git a/src/praisonai-agents/langchain_example.py b/src/praisonai-agents/langchain_example.py index aeddca42c..7c5394f36 100644 --- a/src/praisonai-agents/langchain_example.py +++ b/src/praisonai-agents/langchain_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from langchain_community.tools import YouTubeSearchTool from langchain_community.utilities import WikipediaAPIWrapper @@ -21,7 +21,7 @@ task = Task( ) # Create and start the workflow -agents = PraisonAIAgents( +agents = Agents( agents=[agent], tasks=[task], verbose=True diff --git a/src/praisonai-agents/mongodb_comprehensive_example.py b/src/praisonai-agents/mongodb_comprehensive_example.py index 2b3280e24..c727bdd51 100644 --- a/src/praisonai-agents/mongodb_comprehensive_example.py +++ b/src/praisonai-agents/mongodb_comprehensive_example.py @@ -20,7 +20,7 @@ Features demonstrated: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import mongodb_tools # Ensure OpenAI API key is set @@ -190,7 +190,7 @@ def main(): print("šŸš€ Starting Comprehensive MongoDB Business System...") print("=" * 60) - business_system = PraisonAIAgents( + business_system = Agents( agents=[data_manager, knowledge_curator, business_analyst, customer_service], tasks=business_tasks, memory=True, diff --git a/src/praisonai-agents/mongodb_knowledge_basic.py b/src/praisonai-agents/mongodb_knowledge_basic.py index 94caee6f0..56c6fa436 100644 --- a/src/praisonai-agents/mongodb_knowledge_basic.py +++ b/src/praisonai-agents/mongodb_knowledge_basic.py @@ -19,7 +19,7 @@ Features demonstrated: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Ensure OpenAI API key is set if not os.environ.get("OPENAI_API_KEY"): @@ -124,7 +124,7 @@ def main(): print("šŸš€ Starting MongoDB Knowledge Management System...") print("=" * 60) - knowledge_system = PraisonAIAgents( + knowledge_system = Agents( agents=[research_agent, knowledge_agent], tasks=knowledge_tasks, memory=True, diff --git a/src/praisonai-agents/mongodb_knowledge_example.py b/src/praisonai-agents/mongodb_knowledge_example.py index 77d9c2e56..f65e03a82 100644 --- a/src/praisonai-agents/mongodb_knowledge_example.py +++ b/src/praisonai-agents/mongodb_knowledge_example.py @@ -19,7 +19,7 @@ Features demonstrated: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Ensure OpenAI API key is set if not os.environ.get("OPENAI_API_KEY"): @@ -124,7 +124,7 @@ def main(): print("šŸš€ Starting MongoDB Knowledge Management System...") print("=" * 60) - knowledge_system = PraisonAIAgents( + knowledge_system = Agents( agents=[research_agent, knowledge_agent], tasks=knowledge_tasks, memory=True, diff --git a/src/praisonai-agents/mongodb_memory_basic.py b/src/praisonai-agents/mongodb_memory_basic.py index 3bffda0ba..030bd7646 100644 --- a/src/praisonai-agents/mongodb_memory_basic.py +++ b/src/praisonai-agents/mongodb_memory_basic.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.memory import Memory from praisonaiagents.agent import ContextAgent import pymongo @@ -35,7 +35,7 @@ implementation_task = Task( context=context_output, ) -implementation_system = PraisonAIAgents( +implementation_system = Agents( agents=[implementation_agent], tasks=[implementation_task], memory=True, diff --git a/src/praisonai-agents/mongodb_memory_example.py b/src/praisonai-agents/mongodb_memory_example.py index 8b30e58ed..2778f7d9d 100644 --- a/src/praisonai-agents/mongodb_memory_example.py +++ b/src/praisonai-agents/mongodb_memory_example.py @@ -19,7 +19,7 @@ Features demonstrated: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Ensure OpenAI API key is set if not os.environ.get("OPENAI_API_KEY"): @@ -91,7 +91,7 @@ def main(): print("šŸš€ Starting MongoDB Memory Research System...") print("=" * 60) - research_system = PraisonAIAgents( + research_system = Agents( agents=[research_agent], tasks=research_tasks, memory=True, diff --git a/src/praisonai-agents/mongodb_tools_example.py b/src/praisonai-agents/mongodb_tools_example.py index 6f0e7fa27..b2f5d6a98 100644 --- a/src/praisonai-agents/mongodb_tools_example.py +++ b/src/praisonai-agents/mongodb_tools_example.py @@ -19,7 +19,7 @@ Features demonstrated: """ import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import mongodb_tools # Ensure OpenAI API key is set @@ -113,7 +113,7 @@ def main(): print("šŸš€ Starting MongoDB Tools Demo System...") print("=" * 60) - mongodb_system = PraisonAIAgents( + mongodb_system = Agents( agents=[db_agent, analysis_agent], tasks=mongodb_tasks, verbose=True diff --git a/src/praisonai-agents/performance_monitoring_demo.py b/src/praisonai-agents/performance_monitoring_demo.py index 00cfa8925..b65eecfdb 100644 --- a/src/praisonai-agents/performance_monitoring_demo.py +++ b/src/praisonai-agents/performance_monitoring_demo.py @@ -21,7 +21,7 @@ Features Demonstrated: import time import random -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo from praisonaiagents.telemetry import ( monitor_function, track_api_call, performance_monitor, @@ -213,7 +213,7 @@ def execute_monitored_task(agent, task_description): agent=agent ) - agents_workflow = PraisonAIAgents( + agents_workflow = Agents( agents=[agent], tasks=[task], verbose=False diff --git a/src/praisonai-agents/planning_simple.py b/src/praisonai-agents/planning_simple.py index b021180d6..0c62dec56 100644 --- a/src/praisonai-agents/planning_simple.py +++ b/src/praisonai-agents/planning_simple.py @@ -1,6 +1,6 @@ """Simplest Planning Mode Example - Just enable planning=True""" -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create agents researcher = Agent(name="Researcher", role="Research Analyst") @@ -11,7 +11,7 @@ task1 = Task(description="Research the benefits of meditation", agent=researcher task2 = Task(description="Write a short article about meditation benefits", agent=writer) # Run with planning enabled - that's it! -agents = PraisonAIAgents( +agents = Agents( agents=[researcher, writer], tasks=[task1, task2], planning=True, diff --git a/src/praisonai-agents/praisonaiagents/__init__.py b/src/praisonai-agents/praisonaiagents/__init__.py index b29900376..fd4efabc8 100644 --- a/src/praisonai-agents/praisonaiagents/__init__.py +++ b/src/praisonai-agents/praisonaiagents/__init__.py @@ -165,17 +165,17 @@ def __getattr__(name): _lazy_cache[name] = ExpandResult return ExpandResult - # PraisonAIAgents and Agents alias - elif name == "PraisonAIAgents": - from .agents.agents import PraisonAIAgents - _lazy_cache[name] = PraisonAIAgents - _lazy_cache["Agents"] = PraisonAIAgents # Also cache alias - return PraisonAIAgents + # Agents (canonical) and PraisonAIAgents (backward-compatible alias) elif name == "Agents": - from .agents.agents import PraisonAIAgents - _lazy_cache["PraisonAIAgents"] = PraisonAIAgents - _lazy_cache[name] = PraisonAIAgents - return PraisonAIAgents + from .agents.agents import Agents + _lazy_cache[name] = Agents + _lazy_cache["PraisonAIAgents"] = Agents # Also cache alias + return Agents + elif name == "PraisonAIAgents": + from .agents.agents import Agents + _lazy_cache["Agents"] = Agents + _lazy_cache[name] = Agents + return Agents # Task elif name == "Task": diff --git a/src/praisonai-agents/praisonaiagents/agents/__init__.py b/src/praisonai-agents/praisonaiagents/agents/__init__.py index 6d567562a..3b242a810 100644 --- a/src/praisonai-agents/praisonaiagents/agents/__init__.py +++ b/src/praisonai-agents/praisonaiagents/agents/__init__.py @@ -1,6 +1,6 @@ """Agents module for managing multiple AI agents""" -from .agents import PraisonAIAgents +from .agents import Agents, PraisonAIAgents from .autoagents import AutoAgents from .auto_rag_agent import AutoRagAgent, AutoRagConfig, RetrievalPolicy -__all__ = ['PraisonAIAgents', 'AutoAgents', 'AutoRagAgent', 'AutoRagConfig', 'RetrievalPolicy'] \ No newline at end of file +__all__ = ['Agents', 'PraisonAIAgents', 'AutoAgents', 'AutoRagAgent', 'AutoRagConfig', 'RetrievalPolicy'] diff --git a/src/praisonai-agents/praisonaiagents/agents/agents.py b/src/praisonai-agents/praisonaiagents/agents/agents.py index e254326a5..51dcb0da3 100644 --- a/src/praisonai-agents/praisonaiagents/agents/agents.py +++ b/src/praisonai-agents/praisonaiagents/agents/agents.py @@ -126,7 +126,7 @@ def process_task_context(context_item, verbose=0, user_id=None): else: return str(context_item) # Fallback for unknown types -class PraisonAIAgents: +class Agents: def __init__( self, agents, @@ -243,7 +243,7 @@ class PraisonAIAgents: tasks[i + 1].context.append(tasks[i]) logger.info("Set up sequential flow with automatic context passing") - self._state = {} # Add state storage at PraisonAIAgents level + self._state = {} # Add state storage at Agents level # Context management (single param for all context features) self._context_param = context # Store raw param for lazy init @@ -295,7 +295,7 @@ class PraisonAIAgents: # Pass verbose level to Memory self.shared_memory = Memory(config=mem_cfg, verbose=verbose) if verbose >= 5: - logger.info("Initialized shared memory for PraisonAIAgents") + logger.info("Initialized shared memory for Agents") # Distribute memory to tasks for task in tasks: if not task.memory: @@ -1661,7 +1661,7 @@ Context: ], ) - print(f"šŸš€ PraisonAIAgents MCP Workflow server starting on http://{host}:{port}") + print(f"šŸš€ Agents MCP Workflow server starting on http://{host}:{port}") print(f"šŸ“” MCP SSE endpoint available at {sse_mcp_path}") print(f"šŸ“¢ MCP messages post to {messages_mcp_path_prefix}") # Instead of trying to extract tool names, hardcode the known tool name @@ -1674,8 +1674,8 @@ Context: try: uvicorn.run(starlette_mcp_app, host=host, port=port, log_level="debug" if debug else "info") except Exception as e: - logging.error(f"Error starting PraisonAIAgents MCP server: {str(e)}", exc_info=True) - print(f"āŒ Error starting PraisonAIAgents MCP server: {str(e)}") + logging.error(f"Error starting Agents MCP server: {str(e)}", exc_info=True) + print(f"āŒ Error starting Agents MCP server: {str(e)}") mcp_server_thread = threading.Thread(target=run_praison_mcp_server, daemon=True) mcp_server_thread.start() @@ -1696,19 +1696,19 @@ Context: break if not has_more_launches: try: - print("\nPraisonAIAgents MCP server running. Press Ctrl+C to stop.") + print("\nAgents MCP server running. Press Ctrl+C to stop.") while True: time.sleep(1) except KeyboardInterrupt: - print("\nPraisonAIAgents MCP Server stopped") + print("\nAgents MCP Server stopped") except Exception as e: - logging.error(f"Error in PraisonAIAgents MCP launch detection: {e}") + logging.error(f"Error in Agents MCP launch detection: {e}") try: - print("\nKeeping PraisonAIAgents MCP server alive. Press Ctrl+C to stop.") + print("\nKeeping Agents MCP server alive. Press Ctrl+C to stop.") while True: time.sleep(1) except KeyboardInterrupt: - print("\nPraisonAIAgents MCP Server stopped") + print("\nAgents MCP Server stopped") return None else: display_error(f"Invalid protocol: {protocol}. Choose 'http' or 'mcp'.") @@ -2087,3 +2087,8 @@ Context: # Restore original tasks reference for result retrieval self._plan_tasks = self.tasks.copy() # Keep plan tasks for results but note original tasks are preserved in _plan_tasks + + +# Backward compatibility alias - Agents points to Agents +Agents = Agents +PraisonAIAgents = Agents diff --git a/src/praisonai-agents/praisonaiagents/agents/autoagents.py b/src/praisonai-agents/praisonaiagents/agents/autoagents.py index ef109f62d..a1261edd1 100644 --- a/src/praisonai-agents/praisonaiagents/agents/autoagents.py +++ b/src/praisonai-agents/praisonaiagents/agents/autoagents.py @@ -5,7 +5,7 @@ This class provides a simplified interface for creating and running AI agents wi It automatically handles agent creation, task setup, and execution flow. """ -from .agents import PraisonAIAgents +from .agents import Agents from ..agent.agent import Agent from ..task.task import Task from typing import List, Any, Optional, Dict, Tuple @@ -38,7 +38,7 @@ class AutoAgentsConfig(BaseModel): process_type: str agents: List[AgentConfig] -class AutoAgents(PraisonAIAgents): +class AutoAgents(Agents): def __init__( self, instructions: str, diff --git a/src/praisonai-agents/praisonaiagents/agents/delegator.py b/src/praisonai-agents/praisonaiagents/agents/delegator.py new file mode 100644 index 000000000..21dc32637 --- /dev/null +++ b/src/praisonai-agents/praisonaiagents/agents/delegator.py @@ -0,0 +1,463 @@ +""" +Subagent Delegator for PraisonAI Agents. + +Provides delegation primitives for spawning subagents with scoped permissions +and context. Inspired by Gemini CLI's delegate-to-agent pattern. +""" + +import logging +import asyncio +from dataclasses import dataclass, field +from typing import Any, Dict, List, Optional, Callable +from enum import Enum + +from .profiles import AgentProfile, AgentMode, get_profile, BUILTIN_PROFILES + +logger = logging.getLogger(__name__) + + +class DelegationStatus(Enum): + """Status of a delegated task.""" + PENDING = "pending" + RUNNING = "running" + COMPLETED = "completed" + FAILED = "failed" + CANCELLED = "cancelled" + TIMEOUT = "timeout" + + +@dataclass +class DelegationConfig: + """Configuration for subagent delegation.""" + # Concurrency limits + max_concurrent_subagents: int = 3 + max_total_subagents: int = 10 + + # Timeouts + default_timeout_seconds: float = 300.0 + max_timeout_seconds: float = 600.0 + + # Resource limits + max_steps_per_subagent: int = 50 + max_tokens_per_subagent: int = 50000 + + # Permissions + inherit_permissions: bool = True + allow_nested_delegation: bool = False + + # Behavior + auto_cancel_on_parent_cancel: bool = True + collect_results: bool = True + + +@dataclass +class DelegationTask: + """A task delegated to a subagent.""" + task_id: str + agent_name: str + objective: str + status: DelegationStatus = DelegationStatus.PENDING + + # Configuration + timeout_seconds: float = 300.0 + max_steps: int = 50 + + # Context + context: Dict[str, Any] = field(default_factory=dict) + parent_session_id: Optional[str] = None + + # Results + result: Optional[str] = None + error: Optional[str] = None + steps_taken: int = 0 + tokens_used: int = 0 + + # Metadata + metadata: Dict[str, Any] = field(default_factory=dict) + + +@dataclass +class DelegationResult: + """Result of a delegation operation.""" + task_id: str + agent_name: str + success: bool + result: Optional[str] = None + error: Optional[str] = None + steps_taken: int = 0 + tokens_used: int = 0 + duration_seconds: float = 0.0 + + +class SubagentDelegator: + """ + Manages delegation of tasks to subagents. + + Provides: + - Spawning subagents with scoped permissions + - Concurrency control + - Timeout management + - Result collection + - Cancellation support + + Example: + delegator = SubagentDelegator() + + # Delegate to explorer agent + result = await delegator.delegate( + agent_name="explorer", + objective="Find all authentication-related files", + context={"workspace": "/path/to/project"} + ) + + # Delegate multiple tasks + results = await delegator.delegate_parallel([ + ("explorer", "Find auth files"), + ("explorer", "Find database models"), + ]) + """ + + def __init__( + self, + config: Optional[DelegationConfig] = None, + agent_factory: Optional[Callable[[str], Any]] = None, + on_task_complete: Optional[Callable[[DelegationResult], None]] = None, + ): + """ + Initialize the delegator. + + Args: + config: Delegation configuration + agent_factory: Factory function to create agents + on_task_complete: Callback when task completes + """ + self.config = config or DelegationConfig() + self.agent_factory = agent_factory + self.on_task_complete = on_task_complete + + # State + self._tasks: Dict[str, DelegationTask] = {} + self._running_count: int = 0 + self._total_count: int = 0 + self._task_counter: int = 0 + + # Semaphore for concurrency control + self._semaphore = asyncio.Semaphore(self.config.max_concurrent_subagents) + + def get_available_agents(self) -> List[str]: + """Get list of available agent names for delegation.""" + return [ + name for name, profile in BUILTIN_PROFILES.items() + if profile.mode in (AgentMode.SUBAGENT, AgentMode.ALL) + and not profile.hidden + ] + + def get_agent_description(self, agent_name: str) -> str: + """Get description for an agent.""" + profile = get_profile(agent_name) + if profile: + return profile.description + return f"Agent: {agent_name}" + + async def delegate( + self, + agent_name: str, + objective: str, + context: Optional[Dict[str, Any]] = None, + timeout_seconds: Optional[float] = None, + max_steps: Optional[int] = None, + ) -> DelegationResult: + """ + Delegate a task to a subagent. + + Args: + agent_name: Name of the agent to delegate to + objective: Task objective/description + context: Optional context to pass to agent + timeout_seconds: Optional timeout override + max_steps: Optional max steps override + + Returns: + DelegationResult with task outcome + """ + # Check limits + if self._total_count >= self.config.max_total_subagents: + return DelegationResult( + task_id="", + agent_name=agent_name, + success=False, + error=f"Max total subagents ({self.config.max_total_subagents}) reached", + ) + + # Create task + task_id = self._generate_task_id() + task = DelegationTask( + task_id=task_id, + agent_name=agent_name, + objective=objective, + timeout_seconds=timeout_seconds or self.config.default_timeout_seconds, + max_steps=max_steps or self.config.max_steps_per_subagent, + context=context or {}, + ) + + self._tasks[task_id] = task + self._total_count += 1 + + # Execute with concurrency control + async with self._semaphore: + return await self._execute_task(task) + + async def delegate_parallel( + self, + tasks: List[tuple], + collect_all: bool = True, + ) -> List[DelegationResult]: + """ + Delegate multiple tasks in parallel. + + Args: + tasks: List of (agent_name, objective) or (agent_name, objective, context) tuples + collect_all: Wait for all tasks to complete + + Returns: + List of DelegationResults + """ + # Create coroutines + coros = [] + for task_spec in tasks: + if len(task_spec) == 2: + agent_name, objective = task_spec + context = None + else: + agent_name, objective, context = task_spec + + coros.append(self.delegate(agent_name, objective, context)) + + # Execute + if collect_all: + results = await asyncio.gather(*coros, return_exceptions=True) + # Convert exceptions to failed results + processed = [] + for i, result in enumerate(results): + if isinstance(result, Exception): + agent_name = tasks[i][0] if tasks[i] else "unknown" + processed.append(DelegationResult( + task_id="", + agent_name=agent_name, + success=False, + error=str(result), + )) + else: + processed.append(result) + return processed + else: + # Return as tasks complete + return await asyncio.gather(*coros) + + async def cancel_task(self, task_id: str) -> bool: + """ + Cancel a running task. + + Args: + task_id: ID of task to cancel + + Returns: + True if task was cancelled + """ + task = self._tasks.get(task_id) + if not task: + return False + + if task.status == DelegationStatus.RUNNING: + task.status = DelegationStatus.CANCELLED + return True + + return False + + async def cancel_all(self) -> int: + """ + Cancel all running tasks. + + Returns: + Number of tasks cancelled + """ + cancelled = 0 + for task in self._tasks.values(): + if task.status == DelegationStatus.RUNNING: + task.status = DelegationStatus.CANCELLED + cancelled += 1 + return cancelled + + def get_task_status(self, task_id: str) -> Optional[DelegationStatus]: + """Get status of a task.""" + task = self._tasks.get(task_id) + return task.status if task else None + + def get_running_tasks(self) -> List[DelegationTask]: + """Get all running tasks.""" + return [ + t for t in self._tasks.values() + if t.status == DelegationStatus.RUNNING + ] + + def get_stats(self) -> Dict[str, Any]: + """Get delegation statistics.""" + status_counts = {} + for task in self._tasks.values(): + status = task.status.value + status_counts[status] = status_counts.get(status, 0) + 1 + + return { + "total_tasks": self._total_count, + "running_tasks": self._running_count, + "status_counts": status_counts, + "max_concurrent": self.config.max_concurrent_subagents, + "max_total": self.config.max_total_subagents, + } + + async def _execute_task(self, task: DelegationTask) -> DelegationResult: + """Execute a delegation task.""" + import time + start_time = time.time() + + task.status = DelegationStatus.RUNNING + self._running_count += 1 + + try: + # Get agent profile + profile = get_profile(task.agent_name) + if not profile: + raise ValueError(f"Unknown agent: {task.agent_name}") + + # Create agent + agent = await self._create_agent(profile, task) + + # Execute with timeout + try: + result = await asyncio.wait_for( + self._run_agent(agent, task), + timeout=task.timeout_seconds, + ) + task.result = result + task.status = DelegationStatus.COMPLETED + + except asyncio.TimeoutError: + task.status = DelegationStatus.TIMEOUT + task.error = f"Task timed out after {task.timeout_seconds}s" + + except Exception as e: + task.status = DelegationStatus.FAILED + task.error = str(e) + logger.exception(f"Delegation task {task.task_id} failed") + + finally: + self._running_count -= 1 + duration = time.time() - start_time + + # Build result + result = DelegationResult( + task_id=task.task_id, + agent_name=task.agent_name, + success=task.status == DelegationStatus.COMPLETED, + result=task.result, + error=task.error, + steps_taken=task.steps_taken, + tokens_used=task.tokens_used, + duration_seconds=duration, + ) + + # Callback + if self.on_task_complete: + try: + self.on_task_complete(result) + except Exception as e: + logger.warning(f"Task complete callback error: {e}") + + return result + + async def _create_agent(self, profile: AgentProfile, task: DelegationTask) -> Any: + """Create an agent from profile.""" + if self.agent_factory: + return self.agent_factory(profile.name) + + # Default: create Agent from praisonaiagents + try: + from ..agent.agent import Agent + + # Filter tools based on profile + tools = self._get_tools_for_profile(profile) + + agent = Agent( + name=profile.name, + role=profile.name.title(), + goal=task.objective, + backstory=profile.system_prompt, + tools=tools, + verbose=False, + max_iter=min(task.max_steps, profile.max_steps), + ) + + return agent + + except ImportError: + raise RuntimeError("Could not import Agent class") + + async def _run_agent(self, agent: Any, task: DelegationTask) -> str: + """Run an agent on a task.""" + # Build prompt with context + prompt = task.objective + + if task.context: + context_str = "\n".join( + f"- {k}: {v}" for k, v in task.context.items() + ) + prompt = f"Context:\n{context_str}\n\nTask: {task.objective}" + + # Execute + if hasattr(agent, 'chat'): + result = agent.chat(prompt) + elif hasattr(agent, 'run'): + result = agent.run(prompt) + else: + raise RuntimeError("Agent has no chat or run method") + + return str(result) if result else "" + + def _get_tools_for_profile(self, profile: AgentProfile) -> List[Any]: + """Get tools for a profile, respecting restrictions.""" + # For now, return empty list - tools should be injected + # In production, this would filter available tools + return [] + + def _generate_task_id(self) -> str: + """Generate a unique task ID.""" + self._task_counter += 1 + return f"task_{self._task_counter}" + + +# Convenience function for quick delegation +async def delegate_to_agent( + agent_name: str, + objective: str, + context: Optional[Dict[str, Any]] = None, + timeout_seconds: float = 300.0, +) -> DelegationResult: + """ + Quick delegation to a subagent. + + Args: + agent_name: Name of agent to delegate to + objective: Task objective + context: Optional context + timeout_seconds: Timeout in seconds + + Returns: + DelegationResult + """ + delegator = SubagentDelegator() + return await delegator.delegate( + agent_name=agent_name, + objective=objective, + context=context, + timeout_seconds=timeout_seconds, + ) diff --git a/src/praisonai-agents/praisonaiagents/agents/profiles.py b/src/praisonai-agents/praisonaiagents/agents/profiles.py index d5620c246..7c5fd491d 100644 --- a/src/praisonai-agents/praisonaiagents/agents/profiles.py +++ b/src/praisonai-agents/praisonaiagents/agents/profiles.py @@ -147,18 +147,49 @@ BUILTIN_PROFILES: Dict[str, AgentProfile] = { "explorer": AgentProfile( name="explorer", - description="Codebase exploration and understanding agent", - mode=AgentMode.SUBAGENT, - system_prompt=( - "You are a codebase exploration agent. Your role is to understand and " - "navigate codebases. You can find relevant files, understand code " - "structure, and identify patterns. You help locate where changes need " - "to be made." + description=( + "Fast read-only agent for codebase investigation. Use for finding files, " + "searching code, understanding architecture, and answering questions about " + "the codebase. Specify thoroughness: 'quick', 'medium', or 'very thorough'." ), - tools=["read_file", "search", "grep"], - temperature=0.5, + mode=AgentMode.SUBAGENT, + system_prompt="""You are **Codebase Explorer**, a specialized read-only agent for codebase investigation. + +**PURPOSE**: Build a complete mental model of code relevant to a given task. Identify all relevant files, understand their roles, and foresee architectural consequences of potential changes. + +**CAPABILITIES** (READ-ONLY): +- Search code with grep/glob patterns +- Read and analyze files +- List directory structures +- Understand code relationships and dependencies + +**DO**: +- Find key modules, classes, and functions related to the problem +- Understand *why* code is written the way it is +- Foresee ripple effects of changes +- Provide actionable insights with file paths and key symbols + +**DO NOT**: +- Write or modify any files +- Execute commands that change state +- Stop at the first relevant file - be thorough + +**OUTPUT FORMAT**: +Provide a structured report with: +1. Summary of findings +2. Relevant file locations with reasoning +3. Key symbols and their purposes +4. Architectural insights and recommendations""", + tools=["read_file", "list_files", "grep", "glob", "search"], + temperature=0.1, + top_p=0.95, max_steps=40, color="#8B5CF6", + metadata={ + "read_only": True, + "allowed_tools": ["read_file", "list_files", "grep", "glob", "search"], + "blocked_tools": ["write_file", "edit_file", "bash", "shell", "run_command"], + }, ), "debugger": AgentProfile( diff --git a/src/praisonai-agents/praisonaiagents/escalation/__init__.py b/src/praisonai-agents/praisonaiagents/escalation/__init__.py new file mode 100644 index 000000000..cc6a6e2e1 --- /dev/null +++ b/src/praisonai-agents/praisonaiagents/escalation/__init__.py @@ -0,0 +1,93 @@ +""" +Escalation Module for PraisonAI Agents. + +Provides progressive escalation pipeline for auto-mode execution: +- Stage 0: Direct response (no tools, no planning) +- Stage 1: Heuristic tool usage (local signals, no extra LLM call) +- Stage 2: Lightweight plan (single LLM call, constrained) +- Stage 3: Full autonomous loop (tools + subagents + verification) + +Zero Performance Impact: +- All imports are lazy loaded via __getattr__ +- Escalation only triggered when signals indicate need +- No overhead for simple tasks + +Usage: + from praisonaiagents.escalation import EscalationPipeline, EscalationStage + + pipeline = EscalationPipeline() + stage = pipeline.analyze(prompt, context) + result = await pipeline.execute(prompt, stage) +""" + +__all__ = [ + # Core pipeline + "EscalationPipeline", + "EscalationStage", + "EscalationConfig", + # Signals and triggers + "EscalationSignal", + "EscalationTrigger", + # Results + "EscalationResult", + # Doom loop detection + "DoomLoopDetector", + "DoomLoopConfig", + # Observability + "ObservabilityHooks", + "EventType", + "ExecutionMetrics", +] + + +def __getattr__(name: str): + """Lazy load module components to avoid import overhead.""" + if name == "EscalationPipeline": + from .pipeline import EscalationPipeline + return EscalationPipeline + + if name == "EscalationStage": + from .types import EscalationStage + return EscalationStage + + if name == "EscalationConfig": + from .types import EscalationConfig + return EscalationConfig + + if name == "EscalationSignal": + from .types import EscalationSignal + return EscalationSignal + + if name == "EscalationTrigger": + from .triggers import EscalationTrigger + return EscalationTrigger + + if name == "EscalationResult": + from .types import EscalationResult + return EscalationResult + + if name == "DoomLoopDetector": + from .doom_loop import DoomLoopDetector + return DoomLoopDetector + + if name == "CheckpointEvent": + from .types import CheckpointEvent + return CheckpointEvent + + if name == "DoomLoopConfig": + from .doom_loop import DoomLoopConfig + return DoomLoopConfig + + if name == "ObservabilityHooks": + from .observability import ObservabilityHooks + return ObservabilityHooks + + if name == "EventType": + from .observability import EventType + return EventType + + if name == "ExecutionMetrics": + from .observability import ExecutionMetrics + return ExecutionMetrics + + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/src/praisonai-agents/praisonaiagents/escalation/doom_loop.py b/src/praisonai-agents/praisonaiagents/escalation/doom_loop.py new file mode 100644 index 000000000..e6c5c3a5b --- /dev/null +++ b/src/praisonai-agents/praisonaiagents/escalation/doom_loop.py @@ -0,0 +1,419 @@ +""" +Doom Loop Detection for PraisonAI Agents. + +Detects and prevents infinite loops, repeated failures, and stuck states. +Provides recovery strategies when loops are detected. +""" + +from dataclasses import dataclass, field +from typing import Any, Dict, List, Optional +from enum import Enum +import time +import hashlib +import logging + +logger = logging.getLogger(__name__) + + +class DoomLoopType(Enum): + """Types of doom loops that can be detected.""" + REPEATED_ACTION = "repeated_action" # Same action repeated + REPEATED_FAILURE = "repeated_failure" # Same failure repeated + NO_PROGRESS = "no_progress" # No meaningful progress + CIRCULAR_PLAN = "circular_plan" # Plan loops back to start + RESOURCE_EXHAUSTION = "resource_exhaustion" # Budget exceeded + + +class RecoveryAction(Enum): + """Actions to take when doom loop is detected.""" + CONTINUE = "continue" # Continue execution + RETRY_DIFFERENT = "retry_different" # Retry with different approach + ESCALATE_MODEL = "escalate_model" # Try stronger model + REQUEST_HELP = "request_help" # Ask user for clarification + ABORT = "abort" # Stop execution safely + + +@dataclass +class DoomLoopConfig: + """Configuration for doom loop detection.""" + # Thresholds + max_identical_actions: int = 3 # Max identical consecutive actions + max_similar_actions: int = 5 # Max similar actions (fuzzy match) + max_consecutive_failures: int = 3 # Max failures before intervention + max_no_progress_steps: int = 5 # Max steps without progress + + # Similarity threshold for fuzzy matching (0-1) + similarity_threshold: float = 0.85 + + # Time limits + max_time_per_action: float = 60.0 # Max seconds per action + max_total_time: float = 300.0 # Max total execution time + + # Recovery settings + enable_auto_recovery: bool = True # Auto-attempt recovery + max_recovery_attempts: int = 2 # Max recovery attempts + escalate_on_loop: bool = True # Escalate model on loop detection + + # Backoff settings + initial_backoff: float = 1.0 # Initial backoff in seconds + backoff_multiplier: float = 2.0 # Backoff multiplier + max_backoff: float = 30.0 # Maximum backoff + + +@dataclass +class DoomLoopEvent: + """Event representing a doom loop detection.""" + loop_type: DoomLoopType + description: str + action_history: List[str] + recovery_action: RecoveryAction + timestamp: float = field(default_factory=time.time) + metadata: Dict[str, Any] = field(default_factory=dict) + + +@dataclass +class ActionRecord: + """Record of an action for loop detection.""" + action_type: str + action_hash: str + args_hash: str + result_hash: Optional[str] + success: bool + timestamp: float + duration: float + metadata: Dict[str, Any] = field(default_factory=dict) + + +class DoomLoopDetector: + """ + Detects and prevents doom loops in agent execution. + + Monitors action history for patterns that indicate stuck states: + - Repeated identical actions + - Repeated similar actions + - Consecutive failures + - No meaningful progress + + Example: + detector = DoomLoopDetector() + + # Record actions + detector.record_action("read_file", {"path": "foo.py"}, "content", True) + detector.record_action("read_file", {"path": "foo.py"}, "content", True) + + # Check for loops + if detector.is_doom_loop(): + event = detector.get_loop_event() + recovery = detector.get_recovery_action() + """ + + def __init__(self, config: Optional[DoomLoopConfig] = None): + """Initialize detector with optional config.""" + self.config = config or DoomLoopConfig() + self._actions: List[ActionRecord] = [] + self._loop_events: List[DoomLoopEvent] = [] + self._recovery_attempts: int = 0 + self._start_time: Optional[float] = None + self._progress_markers: List[str] = [] + self._current_backoff: float = self.config.initial_backoff + + def start_session(self): + """Start a new detection session.""" + self._start_time = time.time() + self._actions.clear() + self._loop_events.clear() + self._recovery_attempts = 0 + self._progress_markers.clear() + self._current_backoff = self.config.initial_backoff + + def record_action( + self, + action_type: str, + args: Dict[str, Any], + result: Any, + success: bool, + duration: float = 0.0, + metadata: Optional[Dict[str, Any]] = None + ): + """ + Record an action for loop detection. + + Args: + action_type: Type of action (e.g., "read_file", "edit") + args: Action arguments + result: Action result + success: Whether action succeeded + duration: Action duration in seconds + metadata: Optional metadata + """ + record = ActionRecord( + action_type=action_type, + action_hash=self._hash_action(action_type, args), + args_hash=self._hash_dict(args), + result_hash=self._hash_result(result) if result else None, + success=success, + timestamp=time.time(), + duration=duration, + metadata=metadata or {} + ) + self._actions.append(record) + + # Check for loops after recording + if self.is_doom_loop(): + self._handle_loop_detection() + + def mark_progress(self, marker: str): + """ + Mark meaningful progress. + + Call this when the agent makes real progress (e.g., file modified, + test passed, user goal partially achieved). + """ + self._progress_markers.append(marker) + + def is_doom_loop(self) -> bool: + """ + Check if current state indicates a doom loop. + + Returns: + True if doom loop detected + """ + if len(self._actions) < 2: + return False + + # Check for repeated identical actions + if self._check_repeated_identical(): + return True + + # Check for repeated similar actions + if self._check_repeated_similar(): + return True + + # Check for consecutive failures + if self._check_consecutive_failures(): + return True + + # Check for no progress + if self._check_no_progress(): + return True + + # Check for resource exhaustion + if self._check_resource_exhaustion(): + return True + + return False + + def get_loop_type(self) -> Optional[DoomLoopType]: + """Get the type of doom loop detected.""" + if self._check_repeated_identical(): + return DoomLoopType.REPEATED_ACTION + if self._check_repeated_similar(): + return DoomLoopType.REPEATED_ACTION + if self._check_consecutive_failures(): + return DoomLoopType.REPEATED_FAILURE + if self._check_no_progress(): + return DoomLoopType.NO_PROGRESS + if self._check_resource_exhaustion(): + return DoomLoopType.RESOURCE_EXHAUSTION + return None + + def get_loop_event(self) -> Optional[DoomLoopEvent]: + """Get the current loop event if one exists.""" + loop_type = self.get_loop_type() + if not loop_type: + return None + + return DoomLoopEvent( + loop_type=loop_type, + description=self._get_loop_description(loop_type), + action_history=[a.action_type for a in self._actions[-10:]], + recovery_action=self._determine_recovery_action(loop_type), + metadata={ + "action_count": len(self._actions), + "recovery_attempts": self._recovery_attempts, + } + ) + + def get_recovery_action(self) -> RecoveryAction: + """ + Get recommended recovery action. + + Returns: + Recommended recovery action + """ + loop_type = self.get_loop_type() + if not loop_type: + return RecoveryAction.CONTINUE + + return self._determine_recovery_action(loop_type) + + def apply_backoff(self) -> float: + """ + Apply backoff delay and return the delay used. + + Returns: + Backoff delay in seconds + """ + delay = min(self._current_backoff, self.config.max_backoff) + self._current_backoff *= self.config.backoff_multiplier + time.sleep(delay) + return delay + + def reset_backoff(self): + """Reset backoff to initial value.""" + self._current_backoff = self.config.initial_backoff + + def increment_recovery(self) -> bool: + """ + Increment recovery attempt counter. + + Returns: + True if more recovery attempts allowed + """ + self._recovery_attempts += 1 + return self._recovery_attempts < self.config.max_recovery_attempts + + def get_stats(self) -> Dict[str, Any]: + """Get detection statistics.""" + elapsed = time.time() - self._start_time if self._start_time else 0 + + return { + "total_actions": len(self._actions), + "successful_actions": sum(1 for a in self._actions if a.success), + "failed_actions": sum(1 for a in self._actions if not a.success), + "loop_events": len(self._loop_events), + "recovery_attempts": self._recovery_attempts, + "progress_markers": len(self._progress_markers), + "elapsed_time": elapsed, + "current_backoff": self._current_backoff, + } + + # ========================================================================= + # Private Methods + # ========================================================================= + + def _hash_action(self, action_type: str, args: Dict[str, Any]) -> str: + """Create hash for action + args.""" + content = f"{action_type}:{self._hash_dict(args)}" + return hashlib.md5(content.encode()).hexdigest()[:16] + + def _hash_dict(self, d: Dict[str, Any]) -> str: + """Create hash for dictionary.""" + # Sort keys for consistent hashing + content = str(sorted(d.items())) + return hashlib.md5(content.encode()).hexdigest()[:16] + + def _hash_result(self, result: Any) -> str: + """Create hash for result.""" + content = str(result)[:1000] # Limit size + return hashlib.md5(content.encode()).hexdigest()[:16] + + def _check_repeated_identical(self) -> bool: + """Check for repeated identical actions.""" + if len(self._actions) < self.config.max_identical_actions: + return False + + recent = self._actions[-self.config.max_identical_actions:] + first_hash = recent[0].action_hash + + return all(a.action_hash == first_hash for a in recent) + + def _check_repeated_similar(self) -> bool: + """Check for repeated similar actions.""" + if len(self._actions) < self.config.max_similar_actions: + return False + + recent = self._actions[-self.config.max_similar_actions:] + action_types = [a.action_type for a in recent] + + # Check if same action type repeated + if len(set(action_types)) == 1: + return True + + return False + + def _check_consecutive_failures(self) -> bool: + """Check for consecutive failures.""" + if len(self._actions) < self.config.max_consecutive_failures: + return False + + recent = self._actions[-self.config.max_consecutive_failures:] + return all(not a.success for a in recent) + + def _check_no_progress(self) -> bool: + """Check for no meaningful progress.""" + if len(self._actions) < self.config.max_no_progress_steps: + return False + + # If we have progress markers, we're making progress + recent_markers = [ + m for m in self._progress_markers + if True # Could add timestamp filtering + ] + if recent_markers: + return False + + # Check if recent actions produced different results + recent = self._actions[-self.config.max_no_progress_steps:] + result_hashes = [a.result_hash for a in recent if a.result_hash] + + # If all results are the same, no progress + if len(set(result_hashes)) <= 1: + return True + + return False + + def _check_resource_exhaustion(self) -> bool: + """Check for resource exhaustion.""" + if not self._start_time: + return False + + elapsed = time.time() - self._start_time + return elapsed > self.config.max_total_time + + def _determine_recovery_action(self, loop_type: DoomLoopType) -> RecoveryAction: + """Determine appropriate recovery action.""" + # If max recovery attempts reached, abort + if self._recovery_attempts >= self.config.max_recovery_attempts: + return RecoveryAction.ABORT + + # Resource exhaustion always aborts + if loop_type == DoomLoopType.RESOURCE_EXHAUSTION: + return RecoveryAction.ABORT + + # First attempt: try different approach + if self._recovery_attempts == 0: + return RecoveryAction.RETRY_DIFFERENT + + # Second attempt: escalate model if configured + if self._recovery_attempts == 1 and self.config.escalate_on_loop: + return RecoveryAction.ESCALATE_MODEL + + # Otherwise request help + return RecoveryAction.REQUEST_HELP + + def _get_loop_description(self, loop_type: DoomLoopType) -> str: + """Get human-readable description of loop.""" + descriptions = { + DoomLoopType.REPEATED_ACTION: ( + f"Same action repeated {self.config.max_identical_actions} times" + ), + DoomLoopType.REPEATED_FAILURE: ( + f"Action failed {self.config.max_consecutive_failures} times consecutively" + ), + DoomLoopType.NO_PROGRESS: ( + f"No meaningful progress in {self.config.max_no_progress_steps} steps" + ), + DoomLoopType.CIRCULAR_PLAN: "Plan has looped back to a previous state", + DoomLoopType.RESOURCE_EXHAUSTION: ( + f"Exceeded time limit of {self.config.max_total_time}s" + ), + } + return descriptions.get(loop_type, "Unknown loop type") + + def _handle_loop_detection(self): + """Handle loop detection internally.""" + event = self.get_loop_event() + if event: + self._loop_events.append(event) + logger.warning(f"Doom loop detected: {event.description}") diff --git a/src/praisonai-agents/praisonaiagents/escalation/observability.py b/src/praisonai-agents/praisonaiagents/escalation/observability.py new file mode 100644 index 000000000..12a59f884 --- /dev/null +++ b/src/praisonai-agents/praisonaiagents/escalation/observability.py @@ -0,0 +1,318 @@ +""" +Observability Hooks for Escalation Pipeline. + +Provides lightweight tracing and metrics collection for escalation execution. +Opt-in only - no overhead when not enabled. +""" + +import logging +import time +from dataclasses import dataclass, field +from typing import Any, Dict, List, Optional, Callable +from enum import Enum + +from .types import EscalationStage + +logger = logging.getLogger(__name__) + + +class EventType(Enum): + """Types of observable events.""" + # Stage events + STAGE_ENTER = "stage_enter" + STAGE_EXIT = "stage_exit" + STAGE_ESCALATE = "stage_escalate" + STAGE_DEESCALATE = "stage_deescalate" + + # Execution events + EXECUTION_START = "execution_start" + EXECUTION_END = "execution_end" + STEP_START = "step_start" + STEP_END = "step_end" + + # Tool events + TOOL_CALL_START = "tool_call_start" + TOOL_CALL_END = "tool_call_end" + TOOL_CALL_ERROR = "tool_call_error" + + # Checkpoint events + CHECKPOINT_CREATE = "checkpoint_create" + CHECKPOINT_RESTORE = "checkpoint_restore" + + # Loop detection events + DOOM_LOOP_DETECTED = "doom_loop_detected" + RECOVERY_ATTEMPT = "recovery_attempt" + + # Budget events + BUDGET_WARNING = "budget_warning" + BUDGET_EXCEEDED = "budget_exceeded" + + +@dataclass +class ObservabilityEvent: + """An observable event from the escalation pipeline.""" + event_type: EventType + timestamp: float + data: Dict[str, Any] = field(default_factory=dict) + + # Context + session_id: Optional[str] = None + stage: Optional[EscalationStage] = None + step_number: int = 0 + + # Timing + duration_ms: Optional[float] = None + + def to_dict(self) -> Dict[str, Any]: + """Convert to dictionary for serialization.""" + return { + "event_type": self.event_type.value, + "timestamp": self.timestamp, + "data": self.data, + "session_id": self.session_id, + "stage": self.stage.name if self.stage else None, + "step_number": self.step_number, + "duration_ms": self.duration_ms, + } + + +@dataclass +class ExecutionMetrics: + """Metrics collected during execution.""" + # Timing + total_duration_ms: float = 0.0 + stage_durations_ms: Dict[str, float] = field(default_factory=dict) + + # Counts + total_steps: int = 0 + tool_calls: int = 0 + tool_errors: int = 0 + escalations: int = 0 + deescalations: int = 0 + + # Tokens + tokens_used: int = 0 + + # Checkpoints + checkpoints_created: int = 0 + + # Loop detection + doom_loops_detected: int = 0 + recovery_attempts: int = 0 + + def to_dict(self) -> Dict[str, Any]: + """Convert to dictionary.""" + return { + "total_duration_ms": self.total_duration_ms, + "stage_durations_ms": self.stage_durations_ms, + "total_steps": self.total_steps, + "tool_calls": self.tool_calls, + "tool_errors": self.tool_errors, + "escalations": self.escalations, + "deescalations": self.deescalations, + "tokens_used": self.tokens_used, + "checkpoints_created": self.checkpoints_created, + "doom_loops_detected": self.doom_loops_detected, + "recovery_attempts": self.recovery_attempts, + } + + +class ObservabilityHooks: + """ + Observability hooks for escalation pipeline. + + Provides: + - Event emission + - Metrics collection + - Custom handler registration + - Tracing support + + Example: + hooks = ObservabilityHooks() + + # Register handler + hooks.on(EventType.STAGE_ESCALATE, lambda e: print(f"Escalated to {e.stage}")) + + # Use with pipeline + pipeline = EscalationPipeline(observability=hooks) + """ + + def __init__(self, enabled: bool = True): + """ + Initialize observability hooks. + + Args: + enabled: Whether observability is enabled + """ + self.enabled = enabled + self._handlers: Dict[EventType, List[Callable[[ObservabilityEvent], None]]] = { + event_type: [] for event_type in EventType + } + self._events: List[ObservabilityEvent] = [] + self._metrics = ExecutionMetrics() + self._session_id: Optional[str] = None + self._current_stage: Optional[EscalationStage] = None + self._step_number: int = 0 + self._stage_start_times: Dict[str, float] = {} + + def on(self, event_type: EventType, handler: Callable[[ObservabilityEvent], None]): + """ + Register an event handler. + + Args: + event_type: Type of event to handle + handler: Handler function + """ + self._handlers[event_type].append(handler) + + def off(self, event_type: EventType, handler: Callable[[ObservabilityEvent], None]): + """ + Unregister an event handler. + + Args: + event_type: Type of event + handler: Handler to remove + """ + if handler in self._handlers[event_type]: + self._handlers[event_type].remove(handler) + + def emit(self, event_type: EventType, data: Optional[Dict[str, Any]] = None, duration_ms: Optional[float] = None): + """ + Emit an event. + + Args: + event_type: Type of event + data: Event data + duration_ms: Optional duration + """ + if not self.enabled: + return + + event = ObservabilityEvent( + event_type=event_type, + timestamp=time.time(), + data=data or {}, + session_id=self._session_id, + stage=self._current_stage, + step_number=self._step_number, + duration_ms=duration_ms, + ) + + self._events.append(event) + self._update_metrics(event) + + # Call handlers + for handler in self._handlers[event_type]: + try: + handler(event) + except Exception as e: + logger.warning(f"Event handler error: {e}") + + def _update_metrics(self, event: ObservabilityEvent): + """Update metrics based on event.""" + if event.event_type == EventType.STEP_END: + self._metrics.total_steps += 1 + elif event.event_type == EventType.TOOL_CALL_END: + self._metrics.tool_calls += 1 + elif event.event_type == EventType.TOOL_CALL_ERROR: + self._metrics.tool_errors += 1 + elif event.event_type == EventType.STAGE_ESCALATE: + self._metrics.escalations += 1 + elif event.event_type == EventType.STAGE_DEESCALATE: + self._metrics.deescalations += 1 + elif event.event_type == EventType.CHECKPOINT_CREATE: + self._metrics.checkpoints_created += 1 + elif event.event_type == EventType.DOOM_LOOP_DETECTED: + self._metrics.doom_loops_detected += 1 + elif event.event_type == EventType.RECOVERY_ATTEMPT: + self._metrics.recovery_attempts += 1 + + def set_session(self, session_id: str): + """Set current session ID.""" + self._session_id = session_id + + def set_stage(self, stage: EscalationStage): + """Set current stage.""" + old_stage = self._current_stage + self._current_stage = stage + + # Track stage timing + now = time.time() + if old_stage: + stage_key = old_stage.name + if stage_key in self._stage_start_times: + duration = (now - self._stage_start_times[stage_key]) * 1000 + self._metrics.stage_durations_ms[stage_key] = ( + self._metrics.stage_durations_ms.get(stage_key, 0) + duration + ) + + self._stage_start_times[stage.name] = now + + def increment_step(self): + """Increment step counter.""" + self._step_number += 1 + + def add_tokens(self, count: int): + """Add to token count.""" + self._metrics.tokens_used += count + + def get_events(self) -> List[ObservabilityEvent]: + """Get all recorded events.""" + return self._events.copy() + + def get_metrics(self) -> ExecutionMetrics: + """Get collected metrics.""" + return self._metrics + + def reset(self): + """Reset all state.""" + self._events.clear() + self._metrics = ExecutionMetrics() + self._session_id = None + self._current_stage = None + self._step_number = 0 + self._stage_start_times.clear() + + def start_execution(self, session_id: Optional[str] = None): + """Mark execution start.""" + self.reset() + if session_id: + self._session_id = session_id + self.emit(EventType.EXECUTION_START) + + def end_execution(self, duration_ms: float): + """Mark execution end.""" + self._metrics.total_duration_ms = duration_ms + self.emit(EventType.EXECUTION_END, {"duration_ms": duration_ms}, duration_ms) + + def get_summary(self) -> Dict[str, Any]: + """Get execution summary.""" + return { + "session_id": self._session_id, + "metrics": self._metrics.to_dict(), + "event_count": len(self._events), + "final_stage": self._current_stage.name if self._current_stage else None, + } + + +# Global hooks instance (opt-in) +_global_hooks: Optional[ObservabilityHooks] = None + + +def get_hooks() -> Optional[ObservabilityHooks]: + """Get global observability hooks.""" + return _global_hooks + + +def enable_observability() -> ObservabilityHooks: + """Enable global observability.""" + global _global_hooks + if _global_hooks is None: + _global_hooks = ObservabilityHooks(enabled=True) + return _global_hooks + + +def disable_observability(): + """Disable global observability.""" + global _global_hooks + _global_hooks = None diff --git a/src/praisonai-agents/praisonaiagents/escalation/pipeline.py b/src/praisonai-agents/praisonaiagents/escalation/pipeline.py new file mode 100644 index 000000000..1a0ad034c --- /dev/null +++ b/src/praisonai-agents/praisonaiagents/escalation/pipeline.py @@ -0,0 +1,515 @@ +""" +Escalation Pipeline for PraisonAI Agents. + +Implements progressive escalation from direct response to full autonomous mode. +""" + +import logging +import time +from typing import Any, Dict, List, Optional, Callable + +from .types import ( + EscalationStage, + EscalationConfig, + EscalationResult, + EscalationSignal, + StageContext, +) +from .triggers import EscalationTrigger +from .doom_loop import DoomLoopDetector, RecoveryAction + +logger = logging.getLogger(__name__) + + +class EscalationPipeline: + """ + Progressive escalation pipeline for agent execution. + + Implements a staged approach to task execution: + - Stage 0 (DIRECT): Immediate response without tools + - Stage 1 (HEURISTIC): Tool selection based on local signals + - Stage 2 (PLANNED): Lightweight planning with single LLM call + - Stage 3 (AUTONOMOUS): Full autonomous loop with verification + + Example: + pipeline = EscalationPipeline() + + # Analyze and execute + result = await pipeline.execute("Refactor the auth module") + + # Or analyze first, then execute + stage = pipeline.analyze("Simple question") + result = await pipeline.execute_at_stage("Simple question", stage) + """ + + def __init__( + self, + config: Optional[EscalationConfig] = None, + agent: Optional[Any] = None, + tools: Optional[List[Any]] = None, + checkpoint_service: Optional[Any] = None, + on_stage_change: Optional[Callable[[EscalationStage, EscalationStage], None]] = None, + ): + """ + Initialize the escalation pipeline. + + Args: + config: Pipeline configuration + agent: Agent instance for execution + tools: Available tools + checkpoint_service: Service for checkpoints + on_stage_change: Callback for stage transitions + """ + self.config = config or EscalationConfig() + self.agent = agent + self.tools = tools or [] + self.checkpoint_service = checkpoint_service + self.on_stage_change = on_stage_change + + # Components + self.trigger = EscalationTrigger(self.config) + self.doom_detector = DoomLoopDetector() + + # State + self._current_context: Optional[StageContext] = None + + def analyze( + self, + prompt: str, + context: Optional[Dict[str, Any]] = None + ) -> EscalationStage: + """ + Analyze prompt and recommend initial stage. + + Args: + prompt: User prompt + context: Optional context (workspace, history, etc.) + + Returns: + Recommended starting stage + """ + signals = self.trigger.analyze(prompt, context) + return self.trigger.recommend_stage(signals) + + async def execute( + self, + prompt: str, + context: Optional[Dict[str, Any]] = None, + session_id: Optional[str] = None, + ) -> EscalationResult: + """ + Execute prompt with automatic escalation. + + Args: + prompt: User prompt + context: Optional context + session_id: Optional session ID + + Returns: + Execution result + """ + # Analyze and get initial stage + signals = self.trigger.analyze(prompt, context) + initial_stage = self.trigger.recommend_stage(signals) + + return await self.execute_at_stage( + prompt, + initial_stage, + signals=signals, + context=context, + session_id=session_id, + ) + + async def execute_at_stage( + self, + prompt: str, + stage: EscalationStage, + signals: Optional[set] = None, + context: Optional[Dict[str, Any]] = None, + session_id: Optional[str] = None, + ) -> EscalationResult: + """ + Execute prompt at specific stage. + + Args: + prompt: User prompt + stage: Stage to execute at + signals: Pre-analyzed signals + context: Optional context + session_id: Optional session ID + + Returns: + Execution result + """ + start_time = time.time() + + # Initialize context + self._current_context = StageContext( + stage=stage, + prompt=prompt, + signals=signals or set(), + session_id=session_id, + ) + + # Initialize doom loop detector + self.doom_detector.start_session() + + # Track escalations + escalations = 0 + deescalations = 0 + initial_stage = stage + current_stage = stage + + response = "" + errors: List[str] = [] + warnings: List[str] = [] + + try: + while True: + # Execute at current stage + stage_result = await self._execute_stage(current_stage, prompt) + + response = stage_result.get("response", "") + success = stage_result.get("success", False) + + # Record action for doom loop detection + self.doom_detector.record_action( + action_type=f"stage_{current_stage.name}", + args={"prompt": prompt[:100]}, + result=response[:100] if response else None, + success=success, + ) + + # Check for doom loop + if self.doom_detector.is_doom_loop(): + recovery = self.doom_detector.get_recovery_action() + + if recovery == RecoveryAction.ABORT: + errors.append("Execution aborted due to doom loop") + break + elif recovery == RecoveryAction.ESCALATE_MODEL: + warnings.append("Escalating model due to loop detection") + # Model escalation would happen here + elif recovery == RecoveryAction.REQUEST_HELP: + warnings.append("Requesting user clarification") + response = "I'm having trouble completing this task. Could you provide more details?" + break + + if not self.doom_detector.increment_recovery(): + errors.append("Max recovery attempts reached") + break + + self.doom_detector.apply_backoff() + + # Check if we should escalate + if not success and self.config.auto_escalate: + if current_stage < EscalationStage.AUTONOMOUS: + new_stage = EscalationStage(current_stage + 1) + self._notify_stage_change(current_stage, new_stage) + current_stage = new_stage + escalations += 1 + self._current_context.stage = current_stage + continue + + # Check if we should de-escalate + if success and self.config.auto_deescalate: + if self._current_context.should_deescalate(self.config): + if current_stage > EscalationStage.DIRECT: + new_stage = EscalationStage(current_stage - 1) + self._notify_stage_change(current_stage, new_stage) + current_stage = new_stage + deescalations += 1 + + # Success or can't escalate further + if success or current_stage == EscalationStage.AUTONOMOUS: + break + + # Budget check + elapsed = time.time() - start_time + if elapsed > self.config.max_time_seconds: + warnings.append(f"Time budget exceeded ({elapsed:.1f}s)") + break + + if self._current_context.tool_calls > self.config.max_tool_calls: + warnings.append("Tool call budget exceeded") + break + + except Exception as e: + errors.append(str(e)) + logger.exception("Error in escalation pipeline") + + # Build result + elapsed = time.time() - start_time + + return EscalationResult( + response=response, + success=len(errors) == 0, + initial_stage=initial_stage, + final_stage=current_stage, + escalations=escalations, + deescalations=deescalations, + signals=list(self._current_context.signals), + steps_taken=len(self._current_context.steps), + tool_calls=self._current_context.tool_calls, + tokens_used=self._current_context.tokens_used, + time_seconds=elapsed, + checkpoint_id=self._current_context.checkpoint_ids[-1] if self._current_context.checkpoint_ids else None, + files_modified=list(self._current_context.files_modified), + errors=errors, + warnings=warnings, + ) + + async def _execute_stage( + self, + stage: EscalationStage, + prompt: str + ) -> Dict[str, Any]: + """ + Execute at a specific stage. + + Args: + stage: Stage to execute + prompt: User prompt + + Returns: + Stage execution result + """ + if stage == EscalationStage.DIRECT: + return await self._execute_direct(prompt) + elif stage == EscalationStage.HEURISTIC: + return await self._execute_heuristic(prompt) + elif stage == EscalationStage.PLANNED: + return await self._execute_planned(prompt) + elif stage == EscalationStage.AUTONOMOUS: + return await self._execute_autonomous(prompt) + else: + return {"response": "", "success": False} + + async def _execute_direct(self, prompt: str) -> Dict[str, Any]: + """ + Execute direct response (Stage 0). + + No tools, no planning - just direct LLM response. + """ + if not self.agent: + return { + "response": "Agent not configured", + "success": False, + } + + try: + # Direct chat without tools + response = self.agent.chat(prompt) + + self._current_context.add_step( + action="direct_response", + result=response[:100] if response else "", + success=True, + ) + + return { + "response": response, + "success": True, + } + except Exception as e: + return { + "response": str(e), + "success": False, + } + + async def _execute_heuristic(self, prompt: str) -> Dict[str, Any]: + """ + Execute with heuristic tool selection (Stage 1). + + Uses local signals to select tools without extra LLM call. + """ + if not self.agent: + return { + "response": "Agent not configured", + "success": False, + } + + try: + # Select tools based on signals + selected_tools = self._select_tools_heuristically() + + # Limit tools for heuristic stage + selected_tools = selected_tools[:self.config.heuristic_max_tools] + + # Execute with selected tools + if hasattr(self.agent, 'tools'): + original_tools = self.agent.tools + self.agent.tools = selected_tools + + try: + response = self.agent.chat(prompt) + finally: + if hasattr(self.agent, 'tools'): + self.agent.tools = original_tools + + self._current_context.add_step( + action="heuristic_response", + result=response[:100] if response else "", + success=True, + ) + + return { + "response": response, + "success": True, + } + except Exception as e: + return { + "response": str(e), + "success": False, + } + + async def _execute_planned(self, prompt: str) -> Dict[str, Any]: + """ + Execute with lightweight planning (Stage 2). + + Single LLM call to create constrained plan, then execute. + """ + if not self.agent: + return { + "response": "Agent not configured", + "success": False, + } + + try: + # Create a simple plan prompt + plan_prompt = f"""Create a brief plan (max {self.config.planned_max_steps} steps) to accomplish: +{prompt} + +Respond with numbered steps, then execute them.""" + + response = self.agent.chat(plan_prompt) + + self._current_context.add_step( + action="planned_response", + result=response[:100] if response else "", + success=True, + ) + + return { + "response": response, + "success": True, + } + except Exception as e: + return { + "response": str(e), + "success": False, + } + + async def _execute_autonomous(self, prompt: str) -> Dict[str, Any]: + """ + Execute full autonomous loop (Stage 3). + + Full tools + planning + verification + checkpoints. + """ + if not self.agent: + return { + "response": "Agent not configured", + "success": False, + } + + try: + # Create checkpoint if enabled + if self.config.enable_checkpoints and self.checkpoint_service: + try: + result = await self.checkpoint_service.save("Before autonomous execution") + if result.success: + self._current_context.checkpoint_ids.append(result.checkpoint.id) + except Exception as e: + logger.warning(f"Failed to create checkpoint: {e}") + + # Full autonomous execution with all tools + autonomous_prompt = f"""You are in autonomous mode. Complete this task thoroughly: +{prompt} + +Use all available tools as needed. Verify your work before completing.""" + + response = self.agent.chat(autonomous_prompt) + + self._current_context.add_step( + action="autonomous_response", + result=response[:100] if response else "", + success=True, + ) + + # Mark progress + self.doom_detector.mark_progress("autonomous_complete") + + return { + "response": response, + "success": True, + } + except Exception as e: + return { + "response": str(e), + "success": False, + } + + def _select_tools_heuristically(self) -> List[Any]: + """ + Select tools based on detected signals. + + Returns: + List of selected tools + """ + if not self.tools: + return [] + + signals = self._current_context.signals + selected = [] + + # Map signals to tool categories + tool_map = { + EscalationSignal.FILE_REFERENCES: ["read_file", "list_files", "glob"], + EscalationSignal.EDIT_INTENT: ["write_file", "edit_file", "patch"], + EscalationSignal.TEST_INTENT: ["run_command", "shell"], + EscalationSignal.BUILD_INTENT: ["run_command", "shell"], + EscalationSignal.CODE_BLOCKS: ["read_file", "write_file"], + EscalationSignal.REPO_CONTEXT: ["list_files", "grep", "glob"], + } + + # Collect tool names to include + tool_names = set() + for signal in signals: + if signal in tool_map: + tool_names.update(tool_map[signal]) + + # Filter tools + for tool in self.tools: + tool_name = getattr(tool, '__name__', str(tool)).lower() + if any(name in tool_name for name in tool_names): + selected.append(tool) + + # If no specific tools matched, return first few tools + if not selected and self.tools: + selected = self.tools[:3] + + return selected + + def _notify_stage_change( + self, + old_stage: EscalationStage, + new_stage: EscalationStage + ): + """Notify about stage change.""" + logger.info(f"Stage change: {old_stage.name} -> {new_stage.name}") + + if self.on_stage_change: + try: + self.on_stage_change(old_stage, new_stage) + except Exception as e: + logger.warning(f"Stage change callback error: {e}") + + def get_current_stage(self) -> Optional[EscalationStage]: + """Get current execution stage.""" + if self._current_context: + return self._current_context.stage + return None + + def get_context(self) -> Optional[StageContext]: + """Get current execution context.""" + return self._current_context diff --git a/src/praisonai-agents/praisonaiagents/escalation/triggers.py b/src/praisonai-agents/praisonaiagents/escalation/triggers.py new file mode 100644 index 000000000..185023812 --- /dev/null +++ b/src/praisonai-agents/praisonaiagents/escalation/triggers.py @@ -0,0 +1,324 @@ +""" +Escalation Triggers for PraisonAI Agents. + +Detects signals that indicate escalation or de-escalation is needed. +Uses heuristics only - no extra LLM calls for signal detection. +""" + +import re +from typing import Set, Optional, Dict, Any +from .types import EscalationSignal, EscalationStage, EscalationConfig + + +class EscalationTrigger: + """ + Detects escalation signals from prompts and context. + + Uses fast heuristics to determine task complexity without + making additional LLM calls. This ensures zero overhead + for simple tasks. + + Example: + trigger = EscalationTrigger() + signals = trigger.analyze("Refactor the auth module") + stage = trigger.recommend_stage(signals) + """ + + # Keywords indicating complex tasks + COMPLEX_KEYWORDS = [ + "analyze", "research", "comprehensive", "detailed", + "compare", "evaluate", "synthesize", "multi-step", + "code review", "architecture", "design pattern", + "optimize", "debug", "refactor", "implement", + "build", "create", "develop", "integrate", + ] + + # Keywords indicating simple tasks + SIMPLE_KEYWORDS = [ + "what is", "define", "list", "name", "when", + "where", "who", "simple", "quick", "brief", + "explain", "describe", "tell me", "show me", + ] + + # Keywords indicating edit intent + EDIT_KEYWORDS = [ + "edit", "modify", "change", "update", "fix", + "add", "remove", "delete", "replace", "rename", + "write", "create file", "save", + ] + + # Keywords indicating test intent + TEST_KEYWORDS = [ + "test", "run tests", "pytest", "unittest", + "verify", "check", "validate", "assert", + ] + + # Keywords indicating build intent + BUILD_KEYWORDS = [ + "build", "compile", "make", "npm", "pip install", + "cargo build", "go build", "mvn", "gradle", + ] + + # Keywords indicating refactor intent + REFACTOR_KEYWORDS = [ + "refactor", "restructure", "reorganize", "clean up", + "improve", "optimize", "simplify", "extract", + "move", "split", "merge", "consolidate", + ] + + # File path patterns + FILE_PATTERN = re.compile( + r'(?:^|[\s\'"(])([a-zA-Z0-9_\-./]+\.[a-zA-Z0-9]+)(?:[\s\'")]|$)', + re.MULTILINE + ) + + # Code block pattern + CODE_BLOCK_PATTERN = re.compile(r'```[\s\S]*?```|`[^`]+`') + + def __init__(self, config: Optional[EscalationConfig] = None): + """Initialize trigger with optional config.""" + self.config = config or EscalationConfig() + + def analyze( + self, + prompt: str, + context: Optional[Dict[str, Any]] = None + ) -> Set[EscalationSignal]: + """ + Analyze prompt and context for escalation signals. + + Args: + prompt: User prompt to analyze + context: Optional context (workspace, history, etc.) + + Returns: + Set of detected signals + """ + signals: Set[EscalationSignal] = set() + prompt_lower = prompt.lower() + word_count = len(prompt.split()) + + # Check prompt length + if word_count > self.config.long_prompt_threshold: + signals.add(EscalationSignal.LONG_PROMPT) + + # Check for complex keywords + complex_count = sum( + 1 for kw in self.COMPLEX_KEYWORDS + if kw in prompt_lower + ) + if complex_count >= self.config.complex_keyword_threshold: + signals.add(EscalationSignal.COMPLEX_KEYWORDS) + + # Check for simple keywords + simple_count = sum( + 1 for kw in self.SIMPLE_KEYWORDS + if kw in prompt_lower + ) + if simple_count >= 1 and complex_count == 0 and word_count < 30: + signals.add(EscalationSignal.SIMPLE_QUESTION) + + # Check for multi-step intent (multiple questions or "and then") + if self._has_multi_step_intent(prompt): + signals.add(EscalationSignal.MULTI_STEP_INTENT) + + # Check for file references + if self.FILE_PATTERN.search(prompt): + signals.add(EscalationSignal.FILE_REFERENCES) + + # Check for code blocks + if self.CODE_BLOCK_PATTERN.search(prompt): + signals.add(EscalationSignal.CODE_BLOCKS) + + # Check for edit intent + if any(kw in prompt_lower for kw in self.EDIT_KEYWORDS): + signals.add(EscalationSignal.EDIT_INTENT) + + # Check for test intent + if any(kw in prompt_lower for kw in self.TEST_KEYWORDS): + signals.add(EscalationSignal.TEST_INTENT) + + # Check for build intent + if any(kw in prompt_lower for kw in self.BUILD_KEYWORDS): + signals.add(EscalationSignal.BUILD_INTENT) + + # Check for refactor intent + if any(kw in prompt_lower for kw in self.REFACTOR_KEYWORDS): + signals.add(EscalationSignal.REFACTOR_INTENT) + + # Check context for repo signals + if context: + if context.get("is_git_repo") or context.get("workspace"): + signals.add(EscalationSignal.REPO_CONTEXT) + + return signals + + def _has_multi_step_intent(self, prompt: str) -> bool: + """Check if prompt implies multiple steps.""" + prompt_lower = prompt.lower() + + # Multiple questions + question_count = prompt.count("?") + if question_count > 1: + return True + + # Sequential indicators + sequential_patterns = [ + "and then", "after that", "next,", "finally,", + "first,", "second,", "third,", "step 1", "step 2", + "1.", "2.", "3.", + ] + if any(p in prompt_lower for p in sequential_patterns): + return True + + # Multiple action verbs + action_verbs = ["create", "update", "delete", "add", "remove", "fix", "change"] + verb_count = sum(1 for v in action_verbs if v in prompt_lower) + if verb_count > 2: + return True + + return False + + def recommend_stage( + self, + signals: Set[EscalationSignal], + current_stage: Optional[EscalationStage] = None + ) -> EscalationStage: + """ + Recommend an escalation stage based on signals. + + Args: + signals: Set of detected signals + current_stage: Current stage (for escalation/de-escalation) + + Returns: + Recommended stage + """ + # Start with direct response + stage = EscalationStage.DIRECT + + # Check for simple question (stay at DIRECT) + if EscalationSignal.SIMPLE_QUESTION in signals: + if not self._has_escalation_signals(signals): + return EscalationStage.DIRECT + + # Check for heuristic-level signals + heuristic_signals = { + EscalationSignal.FILE_REFERENCES, + EscalationSignal.CODE_BLOCKS, + EscalationSignal.REPO_CONTEXT, + } + if signals & heuristic_signals: + stage = max(stage, EscalationStage.HEURISTIC) + + # Check for planned-level signals + planned_signals = { + EscalationSignal.EDIT_INTENT, + EscalationSignal.TEST_INTENT, + EscalationSignal.BUILD_INTENT, + EscalationSignal.COMPLEX_KEYWORDS, + } + if signals & planned_signals: + stage = max(stage, EscalationStage.PLANNED) + + # Check for autonomous-level signals + autonomous_signals = { + EscalationSignal.MULTI_STEP_INTENT, + EscalationSignal.REFACTOR_INTENT, + EscalationSignal.LONG_PROMPT, + } + if signals & autonomous_signals: + stage = max(stage, EscalationStage.AUTONOMOUS) + + # Handle escalation from current stage + if current_stage is not None: + # Failure signals always escalate + failure_signals = { + EscalationSignal.TOOL_FAILURE, + EscalationSignal.INCOMPLETE_TASK, + EscalationSignal.AMBIGUOUS_RESULT, + } + if signals & failure_signals: + stage = max(stage, EscalationStage(min(current_stage + 1, 3))) + + return stage + + def _has_escalation_signals(self, signals: Set[EscalationSignal]) -> bool: + """Check if any escalation-triggering signals are present.""" + escalation_signals = { + EscalationSignal.COMPLEX_KEYWORDS, + EscalationSignal.MULTI_STEP_INTENT, + EscalationSignal.EDIT_INTENT, + EscalationSignal.REFACTOR_INTENT, + EscalationSignal.TOOL_FAILURE, + } + return bool(signals & escalation_signals) + + def should_escalate( + self, + signals: Set[EscalationSignal], + current_stage: EscalationStage, + context: Optional[Dict[str, Any]] = None + ) -> bool: + """ + Check if escalation is recommended. + + Args: + signals: Current signals + current_stage: Current execution stage + context: Optional execution context + + Returns: + True if escalation is recommended + """ + recommended = self.recommend_stage(signals, current_stage) + return recommended > current_stage + + def should_deescalate( + self, + signals: Set[EscalationSignal], + current_stage: EscalationStage, + context: Optional[Dict[str, Any]] = None + ) -> bool: + """ + Check if de-escalation is appropriate. + + Args: + signals: Current signals + current_stage: Current execution stage + context: Optional execution context + + Returns: + True if de-escalation is appropriate + """ + # Don't de-escalate from DIRECT + if current_stage == EscalationStage.DIRECT: + return False + + # De-escalate if only simple signals remain + if EscalationSignal.SIMPLE_QUESTION in signals: + if not self._has_escalation_signals(signals): + return True + + # De-escalate if task appears complete + if context: + if context.get("task_complete", False): + return True + + # De-escalate if recent steps all succeeded + recent_steps = context.get("recent_steps", []) + if len(recent_steps) >= 3: + if all(s.get("success", True) for s in recent_steps): + return True + + return False + + def get_stage_description(self, stage: EscalationStage) -> str: + """Get human-readable description of a stage.""" + descriptions = { + EscalationStage.DIRECT: "Direct response (no tools)", + EscalationStage.HEURISTIC: "Heuristic tool selection", + EscalationStage.PLANNED: "Lightweight planning", + EscalationStage.AUTONOMOUS: "Full autonomous execution", + } + return descriptions.get(stage, "Unknown stage") diff --git a/src/praisonai-agents/praisonaiagents/escalation/types.py b/src/praisonai-agents/praisonaiagents/escalation/types.py new file mode 100644 index 000000000..29d3ea00c --- /dev/null +++ b/src/praisonai-agents/praisonaiagents/escalation/types.py @@ -0,0 +1,235 @@ +""" +Types for Escalation Pipeline. + +Defines stages, signals, configs, and results for progressive escalation. +""" + +from dataclasses import dataclass, field +from enum import IntEnum, Enum +from typing import Any, Dict, List, Optional, Set + + +class EscalationStage(IntEnum): + """ + Escalation stages for progressive execution. + + Stage 0: Direct response - no tools, no planning, immediate answer + Stage 1: Heuristic tools - use tools based on local signals, no extra LLM call + Stage 2: Lightweight plan - single LLM call to create constrained plan + Stage 3: Full autonomous - tools + subagents + verification + checkpoints + """ + DIRECT = 0 # Direct response, no tools + HEURISTIC = 1 # Heuristic tool selection + PLANNED = 2 # Lightweight planning + AUTONOMOUS = 3 # Full autonomous loop + + +class EscalationSignal(Enum): + """ + Signals that indicate escalation may be needed. + + These are detected without extra LLM calls using heuristics. + """ + # Complexity signals + LONG_PROMPT = "long_prompt" # Word count > threshold + COMPLEX_KEYWORDS = "complex_keywords" # Contains analysis/design/etc keywords + MULTI_STEP_INTENT = "multi_step_intent" # Multiple questions or steps implied + + # Context signals + REPO_CONTEXT = "repo_context" # Working in a code repository + FILE_REFERENCES = "file_references" # References specific files + CODE_BLOCKS = "code_blocks" # Contains code to analyze/modify + + # Task signals + EDIT_INTENT = "edit_intent" # User wants to modify files + TEST_INTENT = "test_intent" # User wants to run tests + BUILD_INTENT = "build_intent" # User wants to build/compile + REFACTOR_INTENT = "refactor_intent" # User wants to refactor code + + # Failure signals (for escalation during execution) + TOOL_FAILURE = "tool_failure" # Tool call failed + AMBIGUOUS_RESULT = "ambiguous_result" # Result is unclear + INCOMPLETE_TASK = "incomplete_task" # Task not fully completed + + # De-escalation signals + SIMPLE_QUESTION = "simple_question" # Simple factual question + CLARIFICATION = "clarification" # User asking for clarification + ACKNOWLEDGMENT = "acknowledgment" # User acknowledging/thanking + + +@dataclass +class EscalationConfig: + """ + Configuration for escalation pipeline. + + Controls thresholds, budgets, and behavior. + """ + # Stage thresholds + long_prompt_threshold: int = 100 # Words to trigger LONG_PROMPT + complex_keyword_threshold: int = 2 # Keywords to trigger COMPLEX_KEYWORDS + + # Budgets + max_steps: int = 20 # Maximum steps in autonomous mode + max_time_seconds: int = 300 # Maximum time for task + max_tokens: int = 100000 # Maximum tokens to use + max_tool_calls: int = 50 # Maximum tool calls + + # Stage-specific limits + heuristic_max_tools: int = 3 # Max tools in heuristic stage + planned_max_steps: int = 5 # Max steps in planned stage + + # Behavior + auto_escalate: bool = True # Auto-escalate on signals + auto_deescalate: bool = True # Auto-de-escalate when resolved + require_approval_for_writes: bool = True # Require approval for file writes + enable_checkpoints: bool = True # Enable checkpoints for undo + + # Doom loop prevention + max_retries: int = 3 # Max retries per step + max_identical_actions: int = 3 # Max identical consecutive actions + backoff_factor: float = 1.5 # Backoff multiplier on retry + + # Model routing + use_router: bool = True # Use model router + escalate_model_on_failure: bool = True # Try stronger model on failure + + +@dataclass +class EscalationResult: + """ + Result of escalation pipeline execution. + + Contains the response, metadata, and any state changes. + """ + # Core result + response: str + success: bool + + # Stage info + initial_stage: EscalationStage + final_stage: EscalationStage + escalations: int = 0 + deescalations: int = 0 + + # Signals detected + signals: List[EscalationSignal] = field(default_factory=list) + + # Execution stats + steps_taken: int = 0 + tool_calls: int = 0 + tokens_used: int = 0 + time_seconds: float = 0.0 + + # Checkpoints + checkpoint_id: Optional[str] = None + files_modified: List[str] = field(default_factory=list) + + # Errors + errors: List[str] = field(default_factory=list) + warnings: List[str] = field(default_factory=list) + + # Metadata + metadata: Dict[str, Any] = field(default_factory=dict) + + @property + def was_escalated(self) -> bool: + """Check if execution was escalated.""" + return self.final_stage > self.initial_stage + + @property + def was_deescalated(self) -> bool: + """Check if execution was de-escalated.""" + return self.final_stage < self.initial_stage + + +@dataclass +class StageContext: + """ + Context passed between escalation stages. + + Maintains state across stage transitions. + """ + # Current state + stage: EscalationStage + prompt: str + signals: Set[EscalationSignal] = field(default_factory=set) + + # Execution history + steps: List[Dict[str, Any]] = field(default_factory=list) + tool_results: List[Dict[str, Any]] = field(default_factory=list) + + # Accumulated context + context_summary: str = "" + files_read: Set[str] = field(default_factory=set) + files_modified: Set[str] = field(default_factory=set) + + # Budget tracking + tokens_used: int = 0 + tool_calls: int = 0 + time_elapsed: float = 0.0 + + # Checkpoints + checkpoint_ids: List[str] = field(default_factory=list) + + # Session + session_id: Optional[str] = None + + def add_step(self, action: str, result: Any, success: bool = True): + """Add a step to history.""" + self.steps.append({ + "action": action, + "result": result, + "success": success, + "stage": self.stage.name, + }) + + def add_tool_result(self, tool: str, args: Dict, result: Any, success: bool = True): + """Add a tool result.""" + self.tool_results.append({ + "tool": tool, + "args": args, + "result": result, + "success": success, + }) + self.tool_calls += 1 + + def should_escalate(self, config: EscalationConfig) -> bool: + """Check if escalation is needed based on current state.""" + # Check for failure signals + recent_failures = sum( + 1 for step in self.steps[-3:] + if not step.get("success", True) + ) + if recent_failures >= 2: + return True + + # Check for incomplete task signals + if EscalationSignal.INCOMPLETE_TASK in self.signals: + return True + + return False + + def should_deescalate(self, config: EscalationConfig) -> bool: + """Check if de-escalation is appropriate.""" + # If task is simple and resolved + if EscalationSignal.SIMPLE_QUESTION in self.signals: + return True + + # If recent steps all succeeded and no complex signals + recent_success = all( + step.get("success", True) + for step in self.steps[-3:] + ) + if recent_success and not self._has_complex_signals(): + return True + + return False + + def _has_complex_signals(self) -> bool: + """Check if any complex signals are present.""" + complex_signals = { + EscalationSignal.COMPLEX_KEYWORDS, + EscalationSignal.MULTI_STEP_INTENT, + EscalationSignal.REFACTOR_INTENT, + } + return bool(self.signals & complex_signals) diff --git a/src/praisonai-agents/praisonaiagents/eval/accuracy.py b/src/praisonai-agents/praisonaiagents/eval/accuracy.py index bbd8d5a6c..4384e8b00 100644 --- a/src/praisonai-agents/praisonaiagents/eval/accuracy.py +++ b/src/praisonai-agents/praisonaiagents/eval/accuracy.py @@ -13,7 +13,7 @@ from .results import AccuracyResult, EvaluationScore if TYPE_CHECKING: from ..agent.agent import Agent - from ..agents.agents import PraisonAIAgents + from ..agents.agents import Agents logger = logging.getLogger(__name__) @@ -27,7 +27,7 @@ class AccuracyEvaluator(BaseEvaluator): def __init__( self, - agent: Optional[Union["Agent", "PraisonAIAgents"]] = None, + agent: Optional[Union["Agent", "Agents"]] = None, func: Optional[Callable[..., str]] = None, input_text: str = "", expected_output: str = "", @@ -41,7 +41,7 @@ class AccuracyEvaluator(BaseEvaluator): Initialize the accuracy evaluator. Args: - agent: Agent or PraisonAIAgents instance to evaluate + agent: Agent or Agents instance to evaluate func: Alternative callable that returns output string input_text: Input to provide to the agent/function expected_output: Expected output to compare against diff --git a/src/praisonai-agents/praisonaiagents/eval/criteria.py b/src/praisonai-agents/praisonaiagents/eval/criteria.py index ef94bc446..1d1dafc34 100644 --- a/src/praisonai-agents/praisonaiagents/eval/criteria.py +++ b/src/praisonai-agents/praisonaiagents/eval/criteria.py @@ -13,7 +13,7 @@ from .results import CriteriaResult, CriteriaScore if TYPE_CHECKING: from ..agent.agent import Agent - from ..agents.agents import PraisonAIAgents + from ..agents.agents import Agents logger = logging.getLogger(__name__) @@ -29,7 +29,7 @@ class CriteriaEvaluator(BaseEvaluator): def __init__( self, criteria: str, - agent: Optional[Union["Agent", "PraisonAIAgents"]] = None, + agent: Optional[Union["Agent", "Agents"]] = None, func: Optional[Callable[..., str]] = None, input_text: str = "", scoring_type: Literal["numeric", "binary"] = "numeric", @@ -46,7 +46,7 @@ class CriteriaEvaluator(BaseEvaluator): Args: criteria: The criteria to evaluate against (e.g., "Response is helpful and accurate") - agent: Agent or PraisonAIAgents instance to evaluate + agent: Agent or Agents instance to evaluate func: Alternative callable that returns output string input_text: Input to provide to the agent/function scoring_type: "numeric" (1-10 scale) or "binary" (pass/fail) diff --git a/src/praisonai-agents/praisonaiagents/eval/performance.py b/src/praisonai-agents/praisonaiagents/eval/performance.py index 44c553195..a963f7a17 100644 --- a/src/praisonai-agents/praisonaiagents/eval/performance.py +++ b/src/praisonai-agents/praisonaiagents/eval/performance.py @@ -13,7 +13,7 @@ from .results import PerformanceResult, PerformanceMetrics if TYPE_CHECKING: from ..agent.agent import Agent - from ..agents.agents import PraisonAIAgents + from ..agents.agents import Agents logger = logging.getLogger(__name__) diff --git a/src/praisonai-agents/praisonaiagents/eval/reliability.py b/src/praisonai-agents/praisonaiagents/eval/reliability.py index 60f93dd48..eaf791159 100644 --- a/src/praisonai-agents/praisonaiagents/eval/reliability.py +++ b/src/praisonai-agents/praisonaiagents/eval/reliability.py @@ -12,7 +12,7 @@ from .results import ReliabilityResult, ToolCallResult if TYPE_CHECKING: from ..agent.agent import Agent - from ..agents.agents import PraisonAIAgents + from ..agents.agents import Agents logger = logging.getLogger(__name__) diff --git a/src/praisonai-agents/praisonaiagents/memory/workflows.py b/src/praisonai-agents/praisonaiagents/memory/workflows.py index 9929a74c3..5a73dd4e6 100644 --- a/src/praisonai-agents/praisonaiagents/memory/workflows.py +++ b/src/praisonai-agents/praisonaiagents/memory/workflows.py @@ -775,7 +775,7 @@ class Workflow: return {"steps": results, "output": output, "variables": all_variables} def start(self, input: str = "", **kwargs) -> Dict[str, Any]: - """Alias for run() for consistency with PraisonAIAgents.""" + """Alias for run() for consistency with Agents.""" return self.run(input, **kwargs) diff --git a/src/praisonai-agents/praisonaiagents/planning/__init__.py b/src/praisonai-agents/praisonaiagents/planning/__init__.py index 9a932e2b9..076e79b85 100644 --- a/src/praisonai-agents/praisonaiagents/planning/__init__.py +++ b/src/praisonai-agents/praisonaiagents/planning/__init__.py @@ -17,9 +17,9 @@ Features: - Read-only mode for safe research Usage: - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents - agents = PraisonAIAgents( + agents = Agents( agents=[agent1, agent2], tasks=[task1, task2], planning=True, # Enable planning mode diff --git a/src/praisonai-agents/praisonaiagents/telemetry/integration.py b/src/praisonai-agents/praisonaiagents/telemetry/integration.py index 69373d9cf..e7356ffaf 100644 --- a/src/praisonai-agents/praisonaiagents/telemetry/integration.py +++ b/src/praisonai-agents/praisonaiagents/telemetry/integration.py @@ -16,7 +16,7 @@ if TYPE_CHECKING: from .telemetry import MinimalTelemetry from ..agent.agent import Agent from ..task.task import Task - from ..agents.agents import PraisonAIAgents + from ..agents.agents import Agents # Performance mode flag for auto-instrumentation (define early to avoid NameError) _performance_mode_enabled = False @@ -351,12 +351,12 @@ def instrument_agent(agent: 'Agent', telemetry: Optional['MinimalTelemetry'] = N return agent -def instrument_workflow(workflow: 'PraisonAIAgents', telemetry: Optional['MinimalTelemetry'] = None, performance_mode: bool = False): +def instrument_workflow(workflow: 'Agents', telemetry: Optional['MinimalTelemetry'] = None, performance_mode: bool = False): """ - Instrument a PraisonAIAgents workflow with performance-optimized telemetry. + Instrument a Agents workflow with performance-optimized telemetry. Args: - workflow: The PraisonAIAgents instance to instrument + workflow: The Agents instance to instrument telemetry: Optional telemetry instance (uses global if not provided) performance_mode: If True, uses minimal overhead tracking """ @@ -479,7 +479,7 @@ def instrument_workflow(workflow: 'PraisonAIAgents', telemetry: Optional['Minima # Auto-instrumentation helper def auto_instrument_all(telemetry: Optional['MinimalTelemetry'] = None, performance_mode: bool = False): """ - Automatically instrument all new instances of Agent and PraisonAIAgents with optimized telemetry. + Automatically instrument all new instances of Agent and Agents with optimized telemetry. This should be called after enabling telemetry. Args: @@ -527,11 +527,11 @@ def auto_instrument_all(telemetry: Optional['MinimalTelemetry'] = None, performa try: # Import the classes from ..agent.agent import Agent - from ..agents.agents import PraisonAIAgents + from ..agents.agents import Agents # Store original __init__ methods original_agent_init = Agent.__init__ - original_workflow_init = PraisonAIAgents.__init__ + original_workflow_init = Agents.__init__ # Wrap Agent.__init__ @wraps(original_agent_init) @@ -539,7 +539,7 @@ def auto_instrument_all(telemetry: Optional['MinimalTelemetry'] = None, performa original_agent_init(self, *args, **kwargs) instrument_agent(self, telemetry, performance_mode) - # Wrap PraisonAIAgents.__init__ + # Wrap Agents.__init__ @wraps(original_workflow_init) def workflow_init_wrapper(self, *args, **kwargs): original_workflow_init(self, *args, **kwargs) @@ -547,7 +547,7 @@ def auto_instrument_all(telemetry: Optional['MinimalTelemetry'] = None, performa # Apply wrapped constructors Agent.__init__ = agent_init_wrapper - PraisonAIAgents.__init__ = workflow_init_wrapper + Agents.__init__ = workflow_init_wrapper except ImportError: # Classes not available, skip auto-instrumentation diff --git a/src/praisonai-agents/praisonaiagents/ui/a2a/a2a.py b/src/praisonai-agents/praisonaiagents/ui/a2a/a2a.py index 9268d1c12..e6089c9c7 100644 --- a/src/praisonai-agents/praisonaiagents/ui/a2a/a2a.py +++ b/src/praisonai-agents/praisonaiagents/ui/a2a/a2a.py @@ -12,7 +12,7 @@ from praisonaiagents.ui.a2a.agent_card import generate_agent_card from praisonaiagents.ui.a2a.task_store import TaskStore if TYPE_CHECKING: - from praisonaiagents import Agent, PraisonAIAgents + from praisonaiagents import Agent, Agents from fastapi import APIRouter logger = logging.getLogger(__name__) @@ -22,7 +22,7 @@ class A2A: """ A2A Interface for PraisonAI Agents. - Exposes a PraisonAI Agent or PraisonAIAgents workflow via the A2A protocol, + Exposes a PraisonAI Agent or Agents workflow via the A2A protocol, enabling agent-to-agent communication with other A2A-compatible systems. Usage: @@ -41,7 +41,7 @@ class A2A: Args: agent: Single PraisonAI Agent instance - agents: PraisonAIAgents instance for multi-agent workflows + agents: Agents instance for multi-agent workflows name: Name for the A2A endpoint (defaults to agent name) description: Description of the agent url: URL where the A2A endpoint is hosted @@ -53,7 +53,7 @@ class A2A: def __init__( self, agent: Optional["Agent"] = None, - agents: Optional["PraisonAIAgents"] = None, + agents: Optional["Agents"] = None, name: Optional[str] = None, description: Optional[str] = None, url: str = "http://localhost:8000/a2a", diff --git a/src/praisonai-agents/praisonaiagents/ui/agui/agui.py b/src/praisonai-agents/praisonaiagents/ui/agui/agui.py index 459670ea9..932db24e7 100644 --- a/src/praisonai-agents/praisonaiagents/ui/agui/agui.py +++ b/src/praisonai-agents/praisonaiagents/ui/agui/agui.py @@ -25,7 +25,7 @@ from praisonaiagents.ui.agui.streaming import ( from praisonaiagents.ui.agui.encoder import EventEncoder if TYPE_CHECKING: - from praisonaiagents import Agent, PraisonAIAgents + from praisonaiagents import Agent, Agents from fastapi import APIRouter logger = logging.getLogger(__name__) @@ -35,7 +35,7 @@ class AGUI: """ AG-UI Interface for PraisonAI Agents. - Exposes a PraisonAI Agent or PraisonAIAgents workflow via the AG-UI protocol, + Exposes a PraisonAI Agent or Agents workflow via the AG-UI protocol, enabling integration with CopilotKit and other AG-UI compatible frontends. Usage: @@ -51,7 +51,7 @@ class AGUI: Args: agent: Single PraisonAI Agent instance - agents: PraisonAIAgents instance for multi-agent workflows + agents: Agents instance for multi-agent workflows name: Name for the AG-UI endpoint (defaults to agent name) description: Description of the agent prefix: URL prefix for the router (e.g., "/api/v1") @@ -61,7 +61,7 @@ class AGUI: def __init__( self, agent: Optional["Agent"] = None, - agents: Optional["PraisonAIAgents"] = None, + agents: Optional["Agents"] = None, name: Optional[str] = None, description: Optional[str] = None, prefix: str = "", diff --git a/src/praisonai-agents/praisonaiagents/ui/agui/streaming.py b/src/praisonai-agents/praisonaiagents/ui/agui/streaming.py index 6b9e37f4d..b9d978226 100644 --- a/src/praisonai-agents/praisonaiagents/ui/agui/streaming.py +++ b/src/praisonai-agents/praisonaiagents/ui/agui/streaming.py @@ -319,10 +319,10 @@ async def async_stream_agents_response( session_state: Optional[Dict[str, Any]] = None ) -> AsyncIterator[BaseEvent]: """ - Stream a PraisonAIAgents workflow response as AG-UI events. + Stream a Agents workflow response as AG-UI events. Args: - agents: PraisonAIAgents instance + agents: Agents instance user_input: User input string thread_id: Thread ID run_id: Run ID diff --git a/src/praisonai-agents/praisonaiagents/workflows/workflows.py b/src/praisonai-agents/praisonaiagents/workflows/workflows.py index e24a7567c..59cb5b0db 100644 --- a/src/praisonai-agents/praisonaiagents/workflows/workflows.py +++ b/src/praisonai-agents/praisonaiagents/workflows/workflows.py @@ -286,7 +286,7 @@ class Workflow: planning_llm: Optional[str] = None # LLM for planning reasoning: bool = False # Enable chain-of-thought reasoning verbose: bool = False # Enable verbose output - stream: bool = True # Enable streaming responses (default True like PraisonAIAgents) + stream: bool = True # Enable streaming responses (default True like Agents) # Callbacks (like process="workflow") on_workflow_start: Optional[Callable[['Workflow', str], None]] = None # (workflow, input) @@ -1180,7 +1180,7 @@ Create a brief execution plan (2-3 sentences) describing how to best accomplish return {"steps": results, "output": output, "variables": all_variables} def start(self, input: str = "", **kwargs) -> Dict[str, Any]: - """Alias for run() for consistency with PraisonAIAgents.""" + """Alias for run() for consistency with Agents.""" return self.run(input, **kwargs) diff --git a/src/praisonai-agents/pyproject.toml b/src/praisonai-agents/pyproject.toml index fefd74500..033db0292 100644 --- a/src/praisonai-agents/pyproject.toml +++ b/src/praisonai-agents/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "praisonaiagents" -version = "0.9.0" +version = "0.9.1" description = "Praison AI agents for completing complex tasks with Self Reflection Agents" readme = "README.md" requires-python = ">=3.10" diff --git a/src/praisonai-agents/telemetry_minimal.py b/src/praisonai-agents/telemetry_minimal.py index 2ce49f1e4..0d66cdfbd 100644 --- a/src/praisonai-agents/telemetry_minimal.py +++ b/src/praisonai-agents/telemetry_minimal.py @@ -7,7 +7,7 @@ import os # Uncomment to disable telemetry # os.environ['PRAISONAI_TELEMETRY_DISABLED'] = 'true' -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import get_telemetry # Create a simple agent @@ -26,7 +26,7 @@ task = Task( ) # Create and run workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[agent], tasks=[task], process="sequential" diff --git a/src/praisonai-agents/test_async_sequential.py b/src/praisonai-agents/test_async_sequential.py index 9299f91e6..98894e1d3 100644 --- a/src/praisonai-agents/test_async_sequential.py +++ b/src/praisonai-agents/test_async_sequential.py @@ -10,7 +10,7 @@ from datetime import datetime import sys sys.path.insert(0, '/home/runner/work/PraisonAI/PraisonAI/src/praisonai-agents') -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create test agents async_agent = Agent( @@ -147,7 +147,7 @@ async def test_sequential_async_execution(): try: # Create workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[async_agent, sync_agent], tasks=tasks, process="sequential", diff --git a/src/praisonai-agents/test_auto_telemetry_final.py b/src/praisonai-agents/test_auto_telemetry_final.py index 173a24435..6029a35e9 100644 --- a/src/praisonai-agents/test_auto_telemetry_final.py +++ b/src/praisonai-agents/test_auto_telemetry_final.py @@ -4,7 +4,7 @@ Final test of automatic telemetry. """ print("Step 1: Import praisonaiagents...") -from praisonaiagents import Agent, Task, PraisonAIAgents, get_telemetry +from praisonaiagents import Agent, Task, Agents, get_telemetry print("\nStep 2: Check if telemetry is initialized...") telemetry = get_telemetry() @@ -20,7 +20,7 @@ print(f" agent.chat wrapped: {hasattr(agent.chat, '__wrapped__')}") print("\nStep 5: Create and run a simple workflow...") task = Task(description="Say hello", expected_output="A greeting", agent=agent) -workflow = PraisonAIAgents(agents=[agent], tasks=[task], process="sequential") +workflow = Agents(agents=[agent], tasks=[task], process="sequential") # Check workflow instrumentation print(f" workflow.execute_task wrapped: {hasattr(workflow.execute_task, '__wrapped__')}") diff --git a/src/praisonai-agents/test_callback_enhancement.py b/src/praisonai-agents/test_callback_enhancement.py index 6e04faa61..81fa4a777 100644 --- a/src/praisonai-agents/test_callback_enhancement.py +++ b/src/praisonai-agents/test_callback_enhancement.py @@ -10,7 +10,7 @@ from praisonaiagents import ( register_display_callback, Agent, Task, - PraisonAIAgents + Agents ) def enhanced_callback(message=None, response=None, agent_name=None, agent_role=None, agent_tools=None, task_name=None, task_description=None, task_id=None, **kwargs): @@ -56,7 +56,7 @@ def test_callback_enhancement(): # Run the agents try: - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], verbose=True diff --git a/src/praisonai-agents/test_callback_fix.py b/src/praisonai-agents/test_callback_fix.py index c76bf6756..89a3207a2 100644 --- a/src/praisonai-agents/test_callback_fix.py +++ b/src/praisonai-agents/test_callback_fix.py @@ -8,7 +8,7 @@ from praisonaiagents import ( register_display_callback, Agent, Task, - PraisonAIAgents + Agents ) # Track if callback was executed @@ -51,7 +51,7 @@ with open('callback_test_log.txt', 'w') as f: # Run the agent try: - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task] ) diff --git a/src/praisonai-agents/test_fix_verification.py b/src/praisonai-agents/test_fix_verification.py index 83b30a703..31985b985 100644 --- a/src/praisonai-agents/test_fix_verification.py +++ b/src/praisonai-agents/test_fix_verification.py @@ -2,7 +2,7 @@ """Test the issue fix with a simple callback that expects task_name.""" import asyncio -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Simple callback that expects task_name - this would trigger the error before the fix def test_callback(**kwargs): @@ -40,7 +40,7 @@ async def main(): print("Testing the fix...") # This should work without the "name 'task_name' is not defined" error - workflow = PraisonAIAgents( + workflow = Agents( agents=[test_agent], tasks=[test_task], process="sequential", diff --git a/src/praisonai-agents/test_gemini_embedding.py b/src/praisonai-agents/test_gemini_embedding.py index 317b66938..83f065642 100644 --- a/src/praisonai-agents/test_gemini_embedding.py +++ b/src/praisonai-agents/test_gemini_embedding.py @@ -9,7 +9,7 @@ import logging # Add the source directory to Python path sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src/praisonai-agents')) -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Set up logging logging.basicConfig(level=logging.INFO) @@ -40,7 +40,7 @@ def test_gemini_embedding(): ) # Test with default OpenAI embeddings - agents_openai = PraisonAIAgents( + agents_openai = Agents( agents=[agent], tasks=[task], verbose=5, @@ -69,7 +69,7 @@ def test_gemini_embedding(): agent=agent2 ) - agents_openai_explicit = PraisonAIAgents( + agents_openai_explicit = Agents( agents=[agent2], tasks=[task2], verbose=5, @@ -105,7 +105,7 @@ def test_gemini_embedding(): ) # Configure with Gemini embeddings - agents_gemini = PraisonAIAgents( + agents_gemini = Agents( agents=[agent3], tasks=[task3], verbose=5, diff --git a/src/praisonai-agents/test_import_conversion.py b/src/praisonai-agents/test_import_conversion.py index 6a8a98aeb..604d02c8e 100644 --- a/src/praisonai-agents/test_import_conversion.py +++ b/src/praisonai-agents/test_import_conversion.py @@ -18,20 +18,20 @@ def test_new_import_pattern(): try: # Test importing from PraisonAI (note: this is actually importing from praisonai package) - from praisonai import Agent, Task, PraisonAIAgents - print("āœ“ Successfully imported Agent, Task, PraisonAIAgents from praisonai") + from praisonai import Agent, Task, Agents + print("āœ“ Successfully imported Agent, Task, Agents from praisonai") # Test that the classes are available assert Agent is not None, "Agent class should be available" assert Task is not None, "Task class should be available" - assert PraisonAIAgents is not None, "PraisonAIAgents class should be available" + assert Agents is not None, "Agents class should be available" print("āœ“ All classes are properly available") # Test that we can access the class names print(f"āœ“ Agent class: {Agent.__name__}") print(f"āœ“ Task class: {Task.__name__}") - print(f"āœ“ PraisonAIAgents class: {PraisonAIAgents.__name__}") + print(f"āœ“ Agents class: {Agents.__name__}") return True @@ -45,13 +45,13 @@ def test_backward_compatibility(): try: # Test the old import pattern still works - from praisonaiagents import Agent, Task, PraisonAIAgents - print("āœ“ Successfully imported Agent, Task, PraisonAIAgents from praisonaiagents") + from praisonaiagents import Agent, Task, Agents + print("āœ“ Successfully imported Agent, Task, Agents from praisonaiagents") # Test that the classes are available assert Agent is not None, "Agent class should be available" assert Task is not None, "Task class should be available" - assert PraisonAIAgents is not None, "PraisonAIAgents class should be available" + assert Agents is not None, "Agents class should be available" print("āœ“ All classes are properly available") @@ -68,11 +68,11 @@ def test_class_identity(): try: # Import from both packages from praisonai import Agent as PraisonAIAgent, Task as PraisonAITask - from praisonaiagents import Agent as PraisonAIAgentsAgent, Task as PraisonAIAgentsTask + from praisonaiagents import Agent as AgentsAgent, Task as AgentsTask # They should be the same class - assert PraisonAIAgent is PraisonAIAgentsAgent, "Agent classes should be identical" - assert PraisonAITask is PraisonAIAgentsTask, "Task classes should be identical" + assert PraisonAIAgent is AgentsAgent, "Agent classes should be identical" + assert PraisonAITask is AgentsTask, "Task classes should be identical" print("āœ“ Both import patterns reference the same classes") diff --git a/src/praisonai-agents/test_import_debug.py b/src/praisonai-agents/test_import_debug.py index 97c9a859c..0c00fcc1c 100644 --- a/src/praisonai-agents/test_import_debug.py +++ b/src/praisonai-agents/test_import_debug.py @@ -15,8 +15,8 @@ try: # Test importing specific classes try: - from praisonaiagents import Agent, Task, PraisonAIAgents - print("āœ“ Successfully imported Agent, Task, PraisonAIAgents from praisonaiagents") + from praisonaiagents import Agent, Task, Agents + print("āœ“ Successfully imported Agent, Task, Agents from praisonaiagents") except ImportError as e: print(f"āŒ Failed to import specific classes: {e}") @@ -30,8 +30,8 @@ try: # Test importing from praisonai try: - from praisonai import Agent, Task, PraisonAIAgents - print("āœ“ Successfully imported Agent, Task, PraisonAIAgents from praisonai") + from praisonai import Agent, Task, Agents + print("āœ“ Successfully imported Agent, Task, Agents from praisonai") except ImportError as e: print(f"āŒ Failed to import from praisonai: {e}") @@ -47,7 +47,7 @@ try: # Check what we can actually import print("\nTesting actual imports:") - for symbol in ['PraisonAI', '__version__', 'Agent', 'Task', 'PraisonAIAgents']: + for symbol in ['PraisonAI', '__version__', 'Agent', 'Task', 'Agents']: if hasattr(praisonai, symbol): print(f"āœ“ {symbol} is available") else: diff --git a/src/praisonai-agents/test_issue_877.py b/src/praisonai-agents/test_issue_877.py index c834ec25e..9d580ddc3 100644 --- a/src/praisonai-agents/test_issue_877.py +++ b/src/praisonai-agents/test_issue_877.py @@ -11,7 +11,7 @@ from praisonaiagents import ( register_display_callback, Agent, Task, - PraisonAIAgents + Agents ) # Track callback execution @@ -61,7 +61,7 @@ task1 = Task( ) try: - agents1 = PraisonAIAgents( + agents1 = Agents( agents=[agent1], tasks=[task1] ) @@ -99,7 +99,7 @@ task2 = Task( ) try: - agents2 = PraisonAIAgents( + agents2 = Agents( agents=[agent2], tasks=[task2] ) diff --git a/src/praisonai-agents/test_issue_947.py b/src/praisonai-agents/test_issue_947.py index 041162879..aa452d27a 100644 --- a/src/praisonai-agents/test_issue_947.py +++ b/src/praisonai-agents/test_issue_947.py @@ -1,7 +1,7 @@ # agentic_parallelization_varied_tasks.py import asyncio -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Example tools (replace with real implementations as needed) def fetch_favorite_article(): @@ -90,7 +90,7 @@ aggregate_task = Task( ) async def main(): - workflow = PraisonAIAgents( + workflow = Agents( agents=[article_agent, news_agent, twitter_agent, aggregator], tasks=[article_task, news_task, twitter_task, aggregate_task], process="workflow", diff --git a/src/praisonai-agents/test_issue_950.py b/src/praisonai-agents/test_issue_950.py index f8a385f0e..efe5da88c 100644 --- a/src/praisonai-agents/test_issue_950.py +++ b/src/praisonai-agents/test_issue_950.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ Test for issue #950: Convert praisonaiagents to praisonai imports -The goal is to enable: from PraisonAI import Agent instead of from PraisonAIAgents import Agent +The goal is to enable: from PraisonAI import Agent instead of from Agents import Agent """ import sys @@ -31,14 +31,14 @@ def test_issue_950_goal(): print(f"āœ… Agent class is properly available: {Agent}") # Test that we can also import other common classes mentioned in the issue - from praisonai import Task, PraisonAIAgents - print("āœ… SUCCESS: `from praisonai import Task, PraisonAIAgents` works!") + from praisonai import Task, Agents + print("āœ… SUCCESS: `from praisonai import Task, Agents` works!") assert Task is not None, "Task class should be available" - assert PraisonAIAgents is not None, "PraisonAIAgents class should be available" + assert Agents is not None, "Agents class should be available" print(f"āœ… Task class: {Task}") - print(f"āœ… PraisonAIAgents class: {PraisonAIAgents}") + print(f"āœ… Agents class: {Agents}") return True diff --git a/src/praisonai-agents/test_manual_instrumentation.py b/src/praisonai-agents/test_manual_instrumentation.py index ff0311831..e7dcd5007 100644 --- a/src/praisonai-agents/test_manual_instrumentation.py +++ b/src/praisonai-agents/test_manual_instrumentation.py @@ -3,7 +3,7 @@ Test manual instrumentation to verify it works. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import get_telemetry from praisonaiagents.telemetry.integration import auto_instrument_all @@ -26,7 +26,7 @@ task = Task( ) print("\n3. Creating workflow...") -workflow = PraisonAIAgents( +workflow = Agents( agents=[agent], tasks=[task], process="sequential" diff --git a/src/praisonai-agents/test_multi_provider.py b/src/praisonai-agents/test_multi_provider.py index 93f8bf882..2042f492e 100644 --- a/src/praisonai-agents/test_multi_provider.py +++ b/src/praisonai-agents/test_multi_provider.py @@ -7,7 +7,7 @@ import os import sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.agent import RouterAgent from praisonaiagents.llm import ModelRouter, TaskComplexity @@ -78,7 +78,7 @@ def test_router_agent(): def test_integration(): - """Test integration with PraisonAIAgents""" + """Test integration with Agents""" print("\n=== Testing Integration ===\n") # Create a simple router agent @@ -100,14 +100,14 @@ def test_integration(): ) # Create agents system - agents_system = PraisonAIAgents( + agents_system = Agents( agents=[agent], tasks=[task], process="sequential", verbose=False ) - print("Created PraisonAIAgents with RouterAgent") + print("Created Agents with RouterAgent") print("āœ“ Integration test setup completed") # Note: Actual execution would require API keys @@ -127,7 +127,7 @@ def main(): print("- ModelRouter can analyze task complexity") print("- ModelRouter can select appropriate models") print("- RouterAgent can be created and configured") - print("- Integration with PraisonAIAgents works") + print("- Integration with Agents works") print("\nšŸŽ‰ Multi-provider support is ready to use!") except Exception as e: diff --git a/src/praisonai-agents/test_planning_modes_clean.py b/src/praisonai-agents/test_planning_modes_clean.py index 18e1b7b65..7c4c09553 100644 --- a/src/praisonai-agents/test_planning_modes_clean.py +++ b/src/praisonai-agents/test_planning_modes_clean.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents def search_web(query: str) -> str: return f"Results: AI trends include LLMs, multimodal AI, autonomous agents" @@ -9,7 +9,7 @@ writer = Agent(name="Writer", role="Content Writer", llm="gpt-4o-mini") task1 = Task(description="Research AI trends in 2025", agent=researcher) task2 = Task(description="Write a 2 sentence summary", agent=writer) -agents = PraisonAIAgents( +agents = Agents( agents=[researcher, writer], tasks=[task1, task2], planning=True, diff --git a/src/praisonai-agents/test_planning_simple.py b/src/praisonai-agents/test_planning_simple.py index a8b5f785e..add149e02 100644 --- a/src/praisonai-agents/test_planning_simple.py +++ b/src/praisonai-agents/test_planning_simple.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents def search_web(query: str) -> str: return "AI trends: LLMs, multimodal AI, autonomous agents" @@ -15,7 +15,7 @@ task = Task( agent=agent ) -agents = PraisonAIAgents( +agents = Agents( agents=[agent], tasks=[task], planning=True, diff --git a/src/praisonai-agents/test_self_reflection_fix.py b/src/praisonai-agents/test_self_reflection_fix.py index 20d0e6e44..8d1f2a1ab 100644 --- a/src/praisonai-agents/test_self_reflection_fix.py +++ b/src/praisonai-agents/test_self_reflection_fix.py @@ -10,7 +10,7 @@ from pathlib import Path # Add the src directory to the path sys.path.insert(0, str(Path(__file__).parent / "src" / "praisonai-agents")) -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents def create_mock_tool(): """Create a mock tool that mimics the user's custom search tool""" @@ -52,7 +52,7 @@ def test_self_reflection_with_tools(): # Create and start the agents try: - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" @@ -91,7 +91,7 @@ def test_self_reflection_without_tools(): # Create and start the agents try: - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" diff --git a/src/praisonai-agents/test_self_reflection_with_tools.py b/src/praisonai-agents/test_self_reflection_with_tools.py index f62c632d2..3a573f475 100644 --- a/src/praisonai-agents/test_self_reflection_with_tools.py +++ b/src/praisonai-agents/test_self_reflection_with_tools.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Test script to verify self-reflection works with tools after the fix""" -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo_search def test_self_reflection_with_tools(): @@ -27,7 +27,7 @@ def test_self_reflection_with_tools(): ) # Create and start the agents - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" @@ -60,7 +60,7 @@ def test_self_reflection_without_tools(): ) # Create and start the agents - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" diff --git a/src/praisonai-agents/test_telemetry_automatic.py b/src/praisonai-agents/test_telemetry_automatic.py index abf4aa23c..a45306918 100644 --- a/src/praisonai-agents/test_telemetry_automatic.py +++ b/src/praisonai-agents/test_telemetry_automatic.py @@ -4,7 +4,7 @@ Test that telemetry works automatically without manual instrumentation. """ # NO manual telemetry setup - it should work automatically! -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create a simple agent agent = Agent( @@ -22,7 +22,7 @@ task = Task( ) # Create and run workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[agent], tasks=[task], process="sequential" diff --git a/src/praisonai-agents/test_telemetry_integration.py b/src/praisonai-agents/test_telemetry_integration.py index e28ffbcc1..53e4492e1 100644 --- a/src/praisonai-agents/test_telemetry_integration.py +++ b/src/praisonai-agents/test_telemetry_integration.py @@ -83,7 +83,7 @@ print(" āœ“ Manual flush called - events sent to PostHog") # Test 6: Workflow integration print("\n7. Testing workflow integration:") -from praisonaiagents import PraisonAIAgents +from praisonaiagents import Agents agents = [ Agent(name="Agent1", role="First", goal="Do first task", backstory="I'm first"), @@ -95,7 +95,7 @@ tasks = [ Task(description="Task 2", expected_output="Output 2", agent=agents[1]) ] -workflow = PraisonAIAgents( +workflow = Agents( agents=agents, tasks=tasks, process="sequential" @@ -105,7 +105,7 @@ print(f" Workflow has telemetry integration: {hasattr(workflow.start, '__wrappe print("\n=== Summary of Issues ===") print("\n1. No automatic integration:") -print(" - Agent and PraisonAIAgents classes don't automatically use telemetry") +print(" - Agent and Agents classes don't automatically use telemetry") print(" - Need to manually call instrument_agent() or auto_instrument_all()") print("\n2. No automatic flush:") @@ -116,11 +116,11 @@ print(" - No automatic flush on program exit or periodic flush") print("\n3. Missing integration points:") print(" - Agent.__init__ doesn't initialize telemetry") print(" - Agent.execute() doesn't track execution") -print(" - PraisonAIAgents doesn't track workflow execution") +print(" - Agents doesn't track workflow execution") print(" - No atexit handler to flush on program termination") print("\n=== Recommendations ===") -print("\n1. Add automatic integration in Agent.__init__ and PraisonAIAgents.__init__") +print("\n1. Add automatic integration in Agent.__init__ and Agents.__init__") print("2. Add atexit handler to flush telemetry on program exit") print("3. Add periodic flush (e.g., every 100 events or 60 seconds)") print("4. Document telemetry behavior clearly for users") \ No newline at end of file diff --git a/src/praisonai-agents/test_telemetry_performance.py b/src/praisonai-agents/test_telemetry_performance.py index 30fb261c5..e00b49854 100644 --- a/src/praisonai-agents/test_telemetry_performance.py +++ b/src/praisonai-agents/test_telemetry_performance.py @@ -15,7 +15,7 @@ def test_optimized_telemetry(): print("Testing optimized telemetry performance...") try: - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import get_telemetry, enable_performance_mode, disable_performance_mode # Enable telemetry for testing diff --git a/src/praisonai-agents/test_telemetry_simple.py b/src/praisonai-agents/test_telemetry_simple.py index 136795876..948a496e0 100644 --- a/src/praisonai-agents/test_telemetry_simple.py +++ b/src/praisonai-agents/test_telemetry_simple.py @@ -3,13 +3,13 @@ Simple test to check telemetry. """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.telemetry import get_telemetry # Create workflow agent = Agent(name="Test", role="Tester", goal="Test", instructions="Test") task = Task(description="Test", expected_output="Test", agent=agent) -workflow = PraisonAIAgents(agents=[agent], tasks=[task], process="sequential") +workflow = Agents(agents=[agent], tasks=[task], process="sequential") # Run workflow print("Running workflow...") diff --git a/src/praisonai-agents/test_user_code_pattern.py b/src/praisonai-agents/test_user_code_pattern.py index dab21c5d8..49f800d7f 100644 --- a/src/praisonai-agents/test_user_code_pattern.py +++ b/src/praisonai-agents/test_user_code_pattern.py @@ -9,7 +9,7 @@ from pathlib import Path # Add the src directory to the path sys.path.insert(0, str(Path(__file__).parent / "src" / "praisonai-agents")) -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents def google_web_search_llm(query: str) -> str: """Mock implementation of the user's custom search tool""" @@ -39,7 +39,7 @@ def test_user_code_pattern_with_tools(): # Create and start the agents try: - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" @@ -80,7 +80,7 @@ def test_user_code_pattern_without_tools(): # Create and start the agents try: - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" diff --git a/src/praisonai-agents/test_validation_feedback.py b/src/praisonai-agents/test_validation_feedback.py index f8bd218e8..bbba20f1a 100644 --- a/src/praisonai-agents/test_validation_feedback.py +++ b/src/praisonai-agents/test_validation_feedback.py @@ -5,7 +5,7 @@ import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src/praisonai-agents')) -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents def test_example_one(): """Test the philosopher quotes example""" @@ -54,7 +54,7 @@ def test_example_one(): ) # Workflow - agents = PraisonAIAgents( + agents = Agents( agents=[quote_agent, validator_agent], tasks=[collect_task, validate_task], verbose=1, @@ -126,7 +126,7 @@ def test_example_two(): ) # Workflow - agents = PraisonAIAgents( + agents = Agents( agents=[web_search_agent, agent], tasks=[collect_task, validate_task], verbose=1, diff --git a/src/praisonai-agents/tests/agui/test_agui.py b/src/praisonai-agents/tests/agui/test_agui.py index f9bc33e0c..031d78cd1 100644 --- a/src/praisonai-agents/tests/agui/test_agui.py +++ b/src/praisonai-agents/tests/agui/test_agui.py @@ -3,7 +3,7 @@ Test AGUI Class - TDD Tests for Main Interface Class Phase 5: AGUI Class Tests - Test AGUI initialization with Agent -- Test AGUI initialization with PraisonAIAgents +- Test AGUI initialization with Agents - Test get_router returns FastAPI router - Test validation errors """ @@ -24,13 +24,13 @@ class TestAGUIInitialization: assert agui.agents is None def test_agui_init_with_agents(self): - """Test AGUI initialization with PraisonAIAgents.""" + """Test AGUI initialization with Agents.""" from praisonaiagents.ui.agui import AGUI - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents agent = Agent(name="Test", role="Tester", goal="Test things") task = Task(description="Test task", expected_output="Result", agent=agent) - agents = PraisonAIAgents(agents=[agent], tasks=[task]) + agents = Agents(agents=[agent], tasks=[task]) agui = AGUI(agents=agents) diff --git a/src/praisonai-agents/tests/agui/test_integration.py b/src/praisonai-agents/tests/agui/test_integration.py index 0f9fc797e..6fc773878 100644 --- a/src/praisonai-agents/tests/agui/test_integration.py +++ b/src/praisonai-agents/tests/agui/test_integration.py @@ -3,7 +3,7 @@ Test AG-UI Integration - TDD Tests for End-to-End Integration Phase 7: Integration Tests - Test full flow with single Agent -- Test full flow with PraisonAIAgents +- Test full flow with Agents - Test tool calling flow - Test error recovery - Test state persistence @@ -55,13 +55,13 @@ class TestSingleAgentIntegration: class TestMultiAgentIntegration: - """Test integration with PraisonAIAgents.""" + """Test integration with Agents.""" def test_multi_agent_workflow_flow(self): """Test complete workflow with multiple agents.""" from fastapi.testclient import TestClient from praisonaiagents.ui.agui import AGUI - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents from fastapi import FastAPI import json @@ -91,8 +91,8 @@ class TestMultiAgentIntegration: agent=writer ) - # Create PraisonAIAgents - agents = PraisonAIAgents( + # Create Agents + agents = Agents( agents=[researcher, writer], tasks=[research_task, write_task] ) diff --git a/src/praisonai-agents/tests/async-tavily-agents-gemini.py b/src/praisonai-agents/tests/async-tavily-agents-gemini.py index 94cd3fc64..45837fcee 100644 --- a/src/praisonai-agents/tests/async-tavily-agents-gemini.py +++ b/src/praisonai-agents/tests/async-tavily-agents-gemini.py @@ -2,7 +2,7 @@ import asyncio import logging from typing import List, Dict, Any from pydantic import BaseModel -from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput +from praisonaiagents import Agent, Task, Agents, TaskOutput from tavily import AsyncTavilyClient # Configure logging @@ -98,7 +98,7 @@ async def run_parallel_searches(): ) # Initialize agents manager - agents = PraisonAIAgents( + agents = Agents( agents=[search_agent, summary_agent], tasks=search_tasks + [summary_task] ) diff --git a/src/praisonai-agents/tests/async-tavily-agents.py b/src/praisonai-agents/tests/async-tavily-agents.py index c4b3ab0c4..36a0d6fe1 100644 --- a/src/praisonai-agents/tests/async-tavily-agents.py +++ b/src/praisonai-agents/tests/async-tavily-agents.py @@ -2,7 +2,7 @@ import asyncio import logging from typing import List, Dict, Any from pydantic import BaseModel -from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput +from praisonaiagents import Agent, Task, Agents, TaskOutput from tavily import AsyncTavilyClient # Configure logging @@ -90,7 +90,7 @@ async def run_parallel_searches(): ) # Initialize agents manager - agents = PraisonAIAgents( + agents = Agents( agents=[search_agent, summary_agent], tasks=search_tasks + [summary_task] ) diff --git a/src/praisonai-agents/tests/async_example.py b/src/praisonai-agents/tests/async_example.py index 538c0d9af..a4e0ffdea 100644 --- a/src/praisonai-agents/tests/async_example.py +++ b/src/praisonai-agents/tests/async_example.py @@ -1,7 +1,7 @@ import asyncio import time from typing import List, Dict -from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput +from praisonaiagents import Agent, Task, Agents, TaskOutput from praisonaiagents.main import ( display_error, display_interaction, @@ -181,7 +181,7 @@ workflow_async_task = Task( def run_sync_example(): """Run synchronous example""" display_instruction("\nRunning Synchronous Example...", console) - agents = PraisonAIAgents( + agents = Agents( agents=[sync_agent], tasks=[sync_task], verbose=1, @@ -193,7 +193,7 @@ def run_sync_example(): async def run_async_example(): """Run asynchronous example""" display_instruction("\nRunning Asynchronous Example...", console) - agents = PraisonAIAgents( + agents = Agents( agents=[async_agent], tasks=[async_task], verbose=1, @@ -205,7 +205,7 @@ async def run_async_example(): async def run_mixed_example(): """Run mixed sync/async example""" display_instruction("\nRunning Mixed Sync/Async Example...", console) - agents = PraisonAIAgents( + agents = Agents( agents=[sync_agent, async_agent], tasks=[sync_task, async_task], verbose=1, @@ -217,7 +217,7 @@ async def run_mixed_example(): async def run_workflow_example(): """Run workflow example with both sync and async tasks""" display_instruction("\nRunning Workflow Example...", console) - agents = PraisonAIAgents( + agents = Agents( agents=[sync_agent, async_agent], tasks=[workflow_sync_task, workflow_async_task], verbose=1, diff --git a/src/praisonai-agents/tests/async_example_full.py b/src/praisonai-agents/tests/async_example_full.py index 52f1ca406..3933ace5a 100644 --- a/src/praisonai-agents/tests/async_example_full.py +++ b/src/praisonai-agents/tests/async_example_full.py @@ -1,7 +1,7 @@ import asyncio import time from typing import List, Dict -from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput +from praisonaiagents import Agent, Task, Agents, TaskOutput from duckduckgo_search import DDGS from pydantic import BaseModel import logging @@ -121,8 +121,8 @@ async def run_parallel_tasks(): context=parallel_tasks ) - # Create a single PraisonAIAgents instance with both agents - agents = PraisonAIAgents( + # Create a single Agents instance with both agents + agents = Agents( agents=[async_agent, summary_agent], tasks=parallel_tasks + [summary_task], verbose=1, diff --git a/src/praisonai-agents/tests/async_example_full_multigroups.py b/src/praisonai-agents/tests/async_example_full_multigroups.py index 5d4275c3e..56cd1235d 100644 --- a/src/praisonai-agents/tests/async_example_full_multigroups.py +++ b/src/praisonai-agents/tests/async_example_full_multigroups.py @@ -1,7 +1,7 @@ import asyncio import time from typing import List, Dict -from praisonaiagents import Agent, Task, PraisonAIAgents, TaskOutput +from praisonaiagents import Agent, Task, Agents, TaskOutput from duckduckgo_search import DDGS from pydantic import BaseModel @@ -103,7 +103,7 @@ async_task = Task( async def run_single_task(): """Run single async task""" print("\nRunning Single Async Task...") - agents = PraisonAIAgents( + agents = Agents( agents=[async_agent], tasks=[async_task], verbose=1, @@ -187,7 +187,7 @@ Present the summary in a clear, structured format with sections for findings, pa ) # First run parallel search tasks - agents = PraisonAIAgents( + agents = Agents( agents=[async_agent], tasks=parallel_tasks, # Only run search tasks first verbose=1, @@ -212,7 +212,7 @@ Present the summary in a clear, structured format with sections for findings, pa summary_task.context = completed_tasks # Run summarization task with summary agent - summary_agents = PraisonAIAgents( + summary_agents = Agents( agents=[summary_agent], # Use summary agent for synthesis tasks=[summary_task], verbose=1, diff --git a/src/praisonai-agents/tests/autonomous-agent.py b/src/praisonai-agents/tests/autonomous-agent.py index cb18de012..cc5b8c306 100644 --- a/src/praisonai-agents/tests/autonomous-agent.py +++ b/src/praisonai-agents/tests/autonomous-agent.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time def get_environment_state(): @@ -86,7 +86,7 @@ feedback_task = Task( ) # Create workflow manager -workflow = PraisonAIAgents( +workflow = Agents( agents=[llm_caller, action_agent, feedback_agent], tasks=[monitor_task, action_task, feedback_task], process="workflow", diff --git a/src/praisonai-agents/tests/basic-agents-simple-token-demo.py b/src/praisonai-agents/tests/basic-agents-simple-token-demo.py index 5db8d49e5..f50c07e5e 100644 --- a/src/praisonai-agents/tests/basic-agents-simple-token-demo.py +++ b/src/praisonai-agents/tests/basic-agents-simple-token-demo.py @@ -7,7 +7,7 @@ after running a PraisonAI agent. Shows how to get token usage information from your agent workflows. """ -from praisonaiagents import PraisonAIAgents, Agent, Task +from praisonaiagents import Agents, Agent, Task def main(): # Create an agent to answer questions @@ -29,7 +29,7 @@ def main(): ) # Initialize the agents system - agents = PraisonAIAgents( + agents = Agents( agents=[question_agent], tasks=[answer_task], verbose=True diff --git a/src/praisonai-agents/tests/code-analysis-agents.py b/src/praisonai-agents/tests/code-analysis-agents.py index 9012173d4..d80862827 100644 --- a/src/praisonai-agents/tests/code-analysis-agents.py +++ b/src/praisonai-agents/tests/code-analysis-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict from gitingest import ingest @@ -83,7 +83,7 @@ def analyze_code(code_source: str) -> CodeAnalysisReport: """ # Initialize and run analysis - agents = PraisonAIAgents( + agents = Agents( agents=[code_analyzer], tasks=[code_analysis_task] ) diff --git a/src/praisonai-agents/tests/code-analysis-streamlit.py b/src/praisonai-agents/tests/code-analysis-streamlit.py index d35163aa3..504819372 100644 --- a/src/praisonai-agents/tests/code-analysis-streamlit.py +++ b/src/praisonai-agents/tests/code-analysis-streamlit.py @@ -1,5 +1,5 @@ import streamlit as st -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict, Any from gitingest import ingest @@ -87,7 +87,7 @@ def analyze_code(code_source: str) -> CodeAnalysisReport: """ # Initialize and run analysis - agents = PraisonAIAgents( + agents = Agents( agents=[code_analyzer], tasks=[code_analysis_task] ) diff --git a/src/praisonai-agents/tests/code_agents_example.py b/src/praisonai-agents/tests/code_agents_example.py index f4656950a..9644e98fa 100644 --- a/src/praisonai-agents/tests/code_agents_example.py +++ b/src/praisonai-agents/tests/code_agents_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import json from e2b_code_interpreter import Sandbox @@ -46,5 +46,5 @@ execution_agent_task = Task( agent=execution_agent ) -agents = PraisonAIAgents(agents=[code_agent, execution_agent], tasks=[code_agent_task, execution_agent_task]) +agents = Agents(agents=[code_agent, execution_agent], tasks=[code_agent_task, execution_agent_task]) agents.start() \ No newline at end of file diff --git a/src/praisonai-agents/tests/code_review.py b/src/praisonai-agents/tests/code_review.py index 31b81a335..1a2f28cd2 100644 --- a/src/praisonai-agents/tests/code_review.py +++ b/src/praisonai-agents/tests/code_review.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time from typing import List, Dict @@ -97,7 +97,7 @@ fix_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[analyzer, fix_suggester, fix_applier], tasks=[analysis_task, suggestion_task, fix_task], process="workflow", diff --git a/src/praisonai-agents/tests/context-agents-code.py b/src/praisonai-agents/tests/context-agents-code.py index e8afd13c1..f67790d20 100644 --- a/src/praisonai-agents/tests/context-agents-code.py +++ b/src/praisonai-agents/tests/context-agents-code.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict @@ -83,7 +83,7 @@ cv_analysis_task = Task( ) # Create and run the agent -agents = PraisonAIAgents( +agents = Agents( agents=[cv_analyzer], tasks=[cv_analysis_task] ) diff --git a/src/praisonai-agents/tests/context-agents.py b/src/praisonai-agents/tests/context-agents.py index b1292ddfb..9eb31d913 100644 --- a/src/praisonai-agents/tests/context-agents.py +++ b/src/praisonai-agents/tests/context-agents.py @@ -1,5 +1,5 @@ import streamlit as st -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict import json @@ -77,7 +77,7 @@ async def analyze_cv_async(cv_content): output_pydantic=CVAnalysisReport ) - agents = PraisonAIAgents( + agents = Agents( agents=[cv_analyzer], tasks=[cv_analysis_task] ) diff --git a/src/praisonai-agents/tests/context-multi-tasks.py b/src/praisonai-agents/tests/context-multi-tasks.py index 0209b12c1..bba432db7 100644 --- a/src/praisonai-agents/tests/context-multi-tasks.py +++ b/src/praisonai-agents/tests/context-multi-tasks.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict @@ -49,7 +49,7 @@ cv_analysis_task = Task( ) # Create and run the agent -agents = PraisonAIAgents( +agents = Agents( agents=[cv_analyzer], tasks=[cv_key_strengths,cv_analysis_task], process="sequential" diff --git a/src/praisonai-agents/tests/cot-agents-batch.py b/src/praisonai-agents/tests/cot-agents-batch.py index aa125646b..2a2f46d99 100644 --- a/src/praisonai-agents/tests/cot-agents-batch.py +++ b/src/praisonai-agents/tests/cot-agents-batch.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import cot_save, cot_upload_to_huggingface # Create a COT agent for generating and managing chain of thought solutions @@ -63,7 +63,7 @@ for i in range(0, len(qa_pairs), batch_size): ) # Initialize and run the agent - agents = PraisonAIAgents( + agents = Agents( agents=[cot_agent, save_to_huggingface_agent], tasks=[cot_task, save_to_huggingface_task] ) diff --git a/src/praisonai-agents/tests/cot-agents.py b/src/praisonai-agents/tests/cot-agents.py index 61836e622..323a3a0d3 100644 --- a/src/praisonai-agents/tests/cot-agents.py +++ b/src/praisonai-agents/tests/cot-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import cot_save, cot_upload_to_huggingface from pydantic import BaseModel import os @@ -131,7 +131,7 @@ upload_to_huggingface_task = Task( ) # Initialize workflow -agents = PraisonAIAgents( +agents = Agents( agents=[qa_generator, total_questions_evaluator, cot_generator, upload_to_huggingface], tasks=[generate_task, evaluate_total_questions_task, generate_cot_task, upload_to_huggingface_task], process="workflow", diff --git a/src/praisonai-agents/tests/crewai-tools-example.py b/src/praisonai-agents/tests/crewai-tools-example.py index 2e3246d72..b26c91c81 100644 --- a/src/praisonai-agents/tests/crewai-tools-example.py +++ b/src/praisonai-agents/tests/crewai-tools-example.py @@ -13,7 +13,7 @@ class InternetSearchTool(BaseTool): # Example agent from praisonaiagents import Agent -from praisonaiagents import PraisonAIAgents +from praisonaiagents import Agents agent = Agent( name="Internet Search Agent", tools=[InternetSearchTool], @@ -23,5 +23,5 @@ agent = Agent( ) # Run the agent -result = PraisonAIAgents(agents=[agent], verbose=10).start() +result = Agents(agents=[agent], verbose=10).start() print(result) diff --git a/src/praisonai-agents/tests/deepseek-cot-agents.py b/src/praisonai-agents/tests/deepseek-cot-agents.py index b3b38700a..573626f6b 100644 --- a/src/praisonai-agents/tests/deepseek-cot-agents.py +++ b/src/praisonai-agents/tests/deepseek-cot-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import cot_save, cot_upload_to_huggingface from pydantic import BaseModel import os @@ -131,7 +131,7 @@ upload_to_huggingface_task = Task( ) # Initialize workflow -agents = PraisonAIAgents( +agents = Agents( agents=[qa_generator, total_questions_evaluator, cot_generator, upload_to_huggingface], tasks=[generate_task, evaluate_total_questions_task, generate_cot_task, upload_to_huggingface_task], process="workflow", diff --git a/src/praisonai-agents/tests/deepseek-rag-agents-task.py b/src/praisonai-agents/tests/deepseek-rag-agents-task.py index 654172f4b..95c91adbf 100644 --- a/src/praisonai-agents/tests/deepseek-rag-agents-task.py +++ b/src/praisonai-agents/tests/deepseek-rag-agents-task.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents config = { "vector_store": { @@ -44,7 +44,7 @@ rag_task = Task( ) # Build Agents -agents = PraisonAIAgents( +agents = Agents( agents=[rag_agent], tasks=[rag_task], user_id="user1" diff --git a/src/praisonai-agents/tests/deepseek-reasoning-multi-agents.py b/src/praisonai-agents/tests/deepseek-reasoning-multi-agents.py index bc2d06d71..fc444144c 100644 --- a/src/praisonai-agents/tests/deepseek-reasoning-multi-agents.py +++ b/src/praisonai-agents/tests/deepseek-reasoning-multi-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents reasoning_agent = Agent(role="Helpful Assistant", reasoning_steps=True, llm="deepseek/deepseek-reasoner") small_agent = Agent(role="Helpful Assistant", llm="gpt-3.5-turbo") @@ -6,7 +6,7 @@ small_agent = Agent(role="Helpful Assistant", llm="gpt-3.5-turbo") reasoning_task = Task(description="How many r's in the word 'Strawberry'?", agent=reasoning_agent) small_task = Task(description="With the provided reasoning tell me how many r's in the word 'Strawberry'?", agent=small_agent) -agents = PraisonAIAgents( +agents = Agents( agents=[reasoning_agent, small_agent], tasks=[reasoning_task, small_task] ) diff --git a/src/praisonai-agents/tests/deepseek-reasoning-output-tokens.py b/src/praisonai-agents/tests/deepseek-reasoning-output-tokens.py index 95dd0a64f..cc520bcbd 100644 --- a/src/praisonai-agents/tests/deepseek-reasoning-output-tokens.py +++ b/src/praisonai-agents/tests/deepseek-reasoning-output-tokens.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents llm_config = { "model": "deepseek/deepseek-reasoner", @@ -11,7 +11,7 @@ small_agent = Agent(role="Helpful Assistant", llm="openai/gpt-3.5-turbo") reasoning_task = Task(description="How many r's in the word 'Strawberry'?", agent=reasoning_agent) small_task = Task(description="With the provided reasoning tell me how many r's in the word 'Strawberry'?", agent=small_agent) -agents = PraisonAIAgents( +agents = Agents( agents=[reasoning_agent, small_agent], tasks=[reasoning_task, small_task] ) diff --git a/src/praisonai-agents/tests/evaluator-optimiser.py b/src/praisonai-agents/tests/evaluator-optimiser.py index bfd974358..139480ab0 100644 --- a/src/praisonai-agents/tests/evaluator-optimiser.py +++ b/src/praisonai-agents/tests/evaluator-optimiser.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create generator and evaluator agents generator = Agent( @@ -52,7 +52,7 @@ evaluate_task = Task( ) # Create workflow manager -workflow = PraisonAIAgents( +workflow = Agents( agents=[generator, evaluator], tasks=[generate_task, evaluate_task], process="workflow", diff --git a/src/praisonai-agents/tests/example_callback.py b/src/praisonai-agents/tests/example_callback.py index f9b49b063..182ed49b9 100644 --- a/src/praisonai-agents/tests/example_callback.py +++ b/src/praisonai-agents/tests/example_callback.py @@ -1,7 +1,7 @@ from praisonaiagents import ( Agent, Task, - PraisonAIAgents, + Agents, error_logs, register_display_callback, sync_display_callbacks, @@ -190,7 +190,7 @@ def main(): ) # Create and run agents manager - agents = PraisonAIAgents( + agents = Agents( agents=[researcher, writer], tasks=[task1, task2, task3, task4], verbose=True, diff --git a/src/praisonai-agents/tests/example_custom_tools.py b/src/praisonai-agents/tests/example_custom_tools.py index 969faf19b..c0d680695 100644 --- a/src/praisonai-agents/tests/example_custom_tools.py +++ b/src/praisonai-agents/tests/example_custom_tools.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import List, Dict, Union from duckduckgo_search import DDGS from langchain_community.tools import YouTubeSearchTool @@ -141,7 +141,7 @@ validate_task = Task( ) # 4. Workflow -agents = PraisonAIAgents( +agents = Agents( agents=[data_agent], tasks=[collect_task, validate_task], verbose=1, diff --git a/src/praisonai-agents/tests/example_sequential.py b/src/praisonai-agents/tests/example_sequential.py index a11c62b88..b6f4213f5 100644 --- a/src/praisonai-agents/tests/example_sequential.py +++ b/src/praisonai-agents/tests/example_sequential.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents, error_logs +from praisonaiagents import Agent, Task, Agents, error_logs from duckduckgo_search import DDGS def my_callback(output): @@ -99,7 +99,7 @@ task4 = Task( ) # Create and run agents manager -agents = PraisonAIAgents( +agents = Agents( agents=[researcher, writer], tasks=[task1, task2, task3, task4], verbose=False, diff --git a/src/praisonai-agents/tests/hackathon-judge-agent-code.py b/src/praisonai-agents/tests/hackathon-judge-agent-code.py index d6055c000..73c758030 100644 --- a/src/praisonai-agents/tests/hackathon-judge-agent-code.py +++ b/src/praisonai-agents/tests/hackathon-judge-agent-code.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict import os @@ -64,7 +64,7 @@ def evaluate_project(video_path: str) -> ProjectEvaluation: ) # Initialize and run evaluation - agents = PraisonAIAgents( + agents = Agents( agents=[hackathon_judge], tasks=[evaluation_task], process="sequential", diff --git a/src/praisonai-agents/tests/hackathon-judge-agent.py b/src/praisonai-agents/tests/hackathon-judge-agent.py index d6055c000..73c758030 100644 --- a/src/praisonai-agents/tests/hackathon-judge-agent.py +++ b/src/praisonai-agents/tests/hackathon-judge-agent.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict import os @@ -64,7 +64,7 @@ def evaluate_project(video_path: str) -> ProjectEvaluation: ) # Initialize and run evaluation - agents = PraisonAIAgents( + agents = Agents( agents=[hackathon_judge], tasks=[evaluation_task], process="sequential", diff --git a/src/praisonai-agents/tests/hackathon-judge-streamlit.py b/src/praisonai-agents/tests/hackathon-judge-streamlit.py index 4e694f8c3..2ce487299 100644 --- a/src/praisonai-agents/tests/hackathon-judge-streamlit.py +++ b/src/praisonai-agents/tests/hackathon-judge-streamlit.py @@ -1,6 +1,6 @@ import streamlit as st import os -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from pydantic import BaseModel from typing import List, Dict import tempfile @@ -77,7 +77,7 @@ def evaluate_project(video_path: str) -> ProjectEvaluation: ) # Initialize and run evaluation - agents = PraisonAIAgents( + agents = Agents( agents=[hackathon_judge], tasks=[evaluation_task], process="sequential", diff --git a/src/praisonai-agents/tests/image-to-text-agent.py b/src/praisonai-agents/tests/image-to-text-agent.py index 6f873b141..b847b4c54 100644 --- a/src/praisonai-agents/tests/image-to-text-agent.py +++ b/src/praisonai-agents/tests/image-to-text-agent.py @@ -4,7 +4,7 @@ from praisonaiagents.tools import duckduckgo agent = Agent(instructions="You are a Image Analysis Agent", tools=[duckduckgo]) agent.start("I want to go London next week, find me a good hotel and flight") -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create Image Analysis Agent image_agent = Agent( @@ -35,8 +35,8 @@ task2 = Task( images=["image.jpg"] ) -# Create PraisonAIAgents instance -agents = PraisonAIAgents( +# Create Agents instance +agents = Agents( agents=[image_agent], tasks=[task1, task2], process="sequential", diff --git a/src/praisonai-agents/tests/image-understanding-agent.py b/src/praisonai-agents/tests/image-understanding-agent.py index 6f873b141..b847b4c54 100644 --- a/src/praisonai-agents/tests/image-understanding-agent.py +++ b/src/praisonai-agents/tests/image-understanding-agent.py @@ -4,7 +4,7 @@ from praisonaiagents.tools import duckduckgo agent = Agent(instructions="You are a Image Analysis Agent", tools=[duckduckgo]) agent.start("I want to go London next week, find me a good hotel and flight") -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create Image Analysis Agent image_agent = Agent( @@ -35,8 +35,8 @@ task2 = Task( images=["image.jpg"] ) -# Create PraisonAIAgents instance -agents = PraisonAIAgents( +# Create Agents instance +agents = Agents( agents=[image_agent], tasks=[task1, task2], process="sequential", diff --git a/src/praisonai-agents/tests/knowledge-agents-task.py b/src/praisonai-agents/tests/knowledge-agents-task.py index db683c710..fec8745a1 100644 --- a/src/praisonai-agents/tests/knowledge-agents-task.py +++ b/src/praisonai-agents/tests/knowledge-agents-task.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import logging import os import json @@ -59,7 +59,7 @@ knowledge_task = Task( ) # Create and start the agents -agents = PraisonAIAgents( +agents = Agents( agents=[knowledge_agent], tasks=[knowledge_task], process="sequential", diff --git a/src/praisonai-agents/tests/langchain_example.py b/src/praisonai-agents/tests/langchain_example.py index aeddca42c..7c5394f36 100644 --- a/src/praisonai-agents/tests/langchain_example.py +++ b/src/praisonai-agents/tests/langchain_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from langchain_community.tools import YouTubeSearchTool from langchain_community.utilities import WikipediaAPIWrapper @@ -21,7 +21,7 @@ task = Task( ) # Create and start the workflow -agents = PraisonAIAgents( +agents = Agents( agents=[agent], tasks=[task], verbose=True diff --git a/src/praisonai-agents/tests/llm-anthropic.py b/src/praisonai-agents/tests/llm-anthropic.py index ea4044199..1125b0869 100644 --- a/src/praisonai-agents/tests/llm-anthropic.py +++ b/src/praisonai-agents/tests/llm-anthropic.py @@ -17,7 +17,7 @@ agent = Agent( ) agent.start("What is Praison AI?") -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents from praisonaiagents.tools import internet_search @@ -32,6 +32,6 @@ editor_agent = Agent( llm="anthropic/claude-3-7-sonnet-20250219" ) -agents = PraisonAIAgents(agents=[research_agent, editor_agent]) +agents = Agents(agents=[research_agent, editor_agent]) result = agents.start() print(result) \ No newline at end of file diff --git a/src/praisonai-agents/tests/llm-deepseek-reasoning-steps.py b/src/praisonai-agents/tests/llm-deepseek-reasoning-steps.py index a289c171b..d29abf2ff 100644 --- a/src/praisonai-agents/tests/llm-deepseek-reasoning-steps.py +++ b/src/praisonai-agents/tests/llm-deepseek-reasoning-steps.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents reasoning_agent = Agent(role="Helpful Assistant", reasoning_steps=True, llm="deepseek/deepseek-reasoner") small_agent = Agent(role="Helpful Assistant", llm="openai/gpt-3.5-turbo") @@ -6,7 +6,7 @@ small_agent = Agent(role="Helpful Assistant", llm="openai/gpt-3.5-turbo") reasoning_task = Task(description="How many r's in the word 'Strawberry'?", agent=reasoning_agent) small_task = Task(description="With the provided reasoning tell me how many r's in the word 'Strawberry'?", agent=small_agent) -agents = PraisonAIAgents( +agents = Agents( agents=[reasoning_agent, small_agent], tasks=[reasoning_task, small_task] ) diff --git a/src/praisonai-agents/tests/llm-langchain-toolcall.py b/src/praisonai-agents/tests/llm-langchain-toolcall.py index 154dc6a91..e81f3af54 100644 --- a/src/praisonai-agents/tests/llm-langchain-toolcall.py +++ b/src/praisonai-agents/tests/llm-langchain-toolcall.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from langchain_community.tools import YouTubeSearchTool from langchain_community.utilities import WikipediaAPIWrapper @@ -21,7 +21,7 @@ task = Task( ) # Create and start the workflow -agents = PraisonAIAgents( +agents = Agents( agents=[agent], tasks=[task], verbose=True diff --git a/src/praisonai-agents/tests/memory_example.py b/src/praisonai-agents/tests/memory_example.py index be4d245a6..b5c131035 100644 --- a/src/praisonai-agents/tests/memory_example.py +++ b/src/praisonai-agents/tests/memory_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import logging import os @@ -25,7 +25,7 @@ def main(): # else: # logger.info("Creating new memory database") - # Create task config (without memory config since it's moved to PraisonAIAgents) + # Create task config (without memory config since it's moved to Agents) task_config = {} # Create agents with different roles @@ -100,9 +100,9 @@ def main(): agent=retriever ) - # Initialize PraisonAIAgents with memory configuration + # Initialize Agents with memory configuration # Option 1: Use default OpenAI embeddings - # agents = PraisonAIAgents( + # agents = Agents( # agents=[researcher, retriever], # tasks=[store_task, verify_task, query_task, query_both_task], # verbose=True, @@ -110,7 +110,7 @@ def main(): # ) # Option 2: Explicitly configure OpenAI embeddings - agents = PraisonAIAgents( + agents = Agents( agents=[researcher, retriever], tasks=[store_task, verify_task, query_task, query_both_task], verbose=True, # Use same verbose level as memory @@ -124,7 +124,7 @@ def main(): ) # Option 3: Use Gemini embeddings - # agents = PraisonAIAgents( + # agents = Agents( # agents=[researcher, retriever], # tasks=[store_task, verify_task, query_task, query_both_task], # verbose=True, diff --git a/src/praisonai-agents/tests/memory_simple.py b/src/praisonai-agents/tests/memory_simple.py index b0bed4d52..24fe6e3b2 100644 --- a/src/praisonai-agents/tests/memory_simple.py +++ b/src/praisonai-agents/tests/memory_simple.py @@ -1,4 +1,4 @@ -from praisonaiagents.agents.agents import Agent, Task, PraisonAIAgents +from praisonaiagents.agents.agents import Agent, Task, Agents from praisonaiagents.tools import duckduckgo # Test facts @@ -54,7 +54,7 @@ blog_task = Task( agent=blog_agent ) -agents = PraisonAIAgents( +agents = Agents( agents=[fact_agent, research_agent, blog_agent], tasks=[fact_task, research_task, research_task2, research_task3, research_task4, blog_task], memory=True diff --git a/src/praisonai-agents/tests/multimodal.py b/src/praisonai-agents/tests/multimodal.py index 42b44a92d..f82d95568 100644 --- a/src/praisonai-agents/tests/multimodal.py +++ b/src/praisonai-agents/tests/multimodal.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create Vision Analysis Agent vision_agent = Agent( @@ -42,8 +42,8 @@ task3 = Task( images=["video.mp4"] ) -# Create PraisonAIAgents instance -agents = PraisonAIAgents( +# Create Agents instance +agents = Agents( agents=[vision_agent], tasks=[task1, task2, task3], process="sequential", diff --git a/src/praisonai-agents/tests/orchestrator-workers.py b/src/praisonai-agents/tests/orchestrator-workers.py index 32cfbc3f2..9588539fa 100644 --- a/src/praisonai-agents/tests/orchestrator-workers.py +++ b/src/praisonai-agents/tests/orchestrator-workers.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time def get_time_check(): @@ -93,7 +93,7 @@ synthesize_task = Task( ) # Create workflow manager -workflow = PraisonAIAgents( +workflow = Agents( agents=[router, worker1, worker2, worker3, synthesizer], tasks=[router_task, worker1_task, worker2_task, worker3_task, synthesize_task], process="workflow", diff --git a/src/praisonai-agents/tests/parallelisation.py b/src/praisonai-agents/tests/parallelisation.py index 0be063805..0b83ec79a 100644 --- a/src/praisonai-agents/tests/parallelisation.py +++ b/src/praisonai-agents/tests/parallelisation.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from datetime import datetime import asyncio @@ -75,7 +75,7 @@ aggregate_task = Task( async def main(): # Create workflow manager - workflow = PraisonAIAgents( + workflow = Agents( agents=[agent1, agent2, agent3, aggregator], tasks=[task1, task2, task3, aggregate_task], process="workflow" diff --git a/src/praisonai-agents/tests/pdf_agents_example.py b/src/praisonai-agents/tests/pdf_agents_example.py index 9f09a81fe..75de6b7de 100644 --- a/src/praisonai-agents/tests/pdf_agents_example.py +++ b/src/praisonai-agents/tests/pdf_agents_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create PDF Analysis Agent pdf_agent = Agent( @@ -29,8 +29,8 @@ task2 = Task( input=["document.pdf"] ) -# Create PraisonAIAgents instance -agents = PraisonAIAgents( +# Create Agents instance +agents = Agents( agents=[pdf_agent], tasks=[task1, task2], process="sequential", diff --git a/src/praisonai-agents/tests/prompt_chaining copy.py b/src/praisonai-agents/tests/prompt_chaining copy.py index 185ee30dc..c3e855edd 100644 --- a/src/praisonai-agents/tests/prompt_chaining copy.py +++ b/src/praisonai-agents/tests/prompt_chaining copy.py @@ -1,6 +1,6 @@ from praisonaiagents.agent import Agent from praisonaiagents.task import Task -from praisonaiagents.agents import PraisonAIAgents +from praisonaiagents.agents import Agents from typing import List, Dict import time @@ -65,7 +65,7 @@ def create_prompt_chain(): ) # Create the workflow manager - workflow = PraisonAIAgents( + workflow = Agents( agents=[agent1, agent2, agent3], tasks=[initial_task, analysis_task, final_task], process="workflow", # Use workflow process type diff --git a/src/praisonai-agents/tests/prompt_chaining.py b/src/praisonai-agents/tests/prompt_chaining.py index f00464e01..697473c3e 100644 --- a/src/praisonai-agents/tests/prompt_chaining.py +++ b/src/praisonai-agents/tests/prompt_chaining.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import time def get_time_check(): @@ -61,7 +61,7 @@ final_task = Task( ) # Create the workflow manager -workflow = PraisonAIAgents( +workflow = Agents( agents=[agent1, agent2, agent3], tasks=[initial_task, analysis_task, final_task], process="workflow", # Use workflow process type diff --git a/src/praisonai-agents/tests/repetitive-agents.py b/src/praisonai-agents/tests/repetitive-agents.py index ce2ec676a..fa9087404 100644 --- a/src/praisonai-agents/tests/repetitive-agents.py +++ b/src/praisonai-agents/tests/repetitive-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents agent = Agent( instructions="You are a loop agent that creating a loop of tasks.", @@ -13,7 +13,7 @@ task = Task( input_file="tasks.csv" ) -agents = PraisonAIAgents( +agents = Agents( agents=[agent], tasks=[task], process="workflow", diff --git a/src/praisonai-agents/tests/repetitive-manual-agents.py b/src/praisonai-agents/tests/repetitive-manual-agents.py index 9274f9776..c09e67104 100644 --- a/src/praisonai-agents/tests/repetitive-manual-agents.py +++ b/src/praisonai-agents/tests/repetitive-manual-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import read_csv, write_csv import pandas as pd @@ -130,7 +130,7 @@ update_task = Task( ) # Create and run agents manager -agents = PraisonAIAgents( +agents = Agents( agents=[identify_agent, repetitive_agent], tasks=[identify_task, process_task, update_task], process="workflow" diff --git a/src/praisonai-agents/tests/routing copy.py b/src/praisonai-agents/tests/routing copy.py index 9cc3befce..7ecb66d35 100644 --- a/src/praisonai-agents/tests/routing copy.py +++ b/src/praisonai-agents/tests/routing copy.py @@ -1,6 +1,6 @@ from praisonaiagents.agent import Agent from praisonaiagents.task import Task -from praisonaiagents.agents import PraisonAIAgents +from praisonaiagents.agents import Agents import time current_time = int(time.time()) @@ -60,7 +60,7 @@ final_task = Task( ) # Create and run workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[router, processor1, processor2], tasks=[routing_task, processing_task, final_task], process="workflow", diff --git a/src/praisonai-agents/tests/routing.py b/src/praisonai-agents/tests/routing.py index 06a5299b5..fb3c35072 100644 --- a/src/praisonai-agents/tests/routing.py +++ b/src/praisonai-agents/tests/routing.py @@ -1,6 +1,6 @@ from praisonaiagents.agent import Agent from praisonaiagents.task import Task -from praisonaiagents.agents import PraisonAIAgents +from praisonaiagents.agents import Agents import time def get_time_check(): @@ -61,7 +61,7 @@ final_task = Task( ) # Create and run workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[router, processor1, processor2], tasks=[routing_task, processing_task, final_task], process="workflow", diff --git a/src/praisonai-agents/tests/state_based_workflow_example.py b/src/praisonai-agents/tests/state_based_workflow_example.py index e4a09db9c..01626034c 100644 --- a/src/praisonai-agents/tests/state_based_workflow_example.py +++ b/src/praisonai-agents/tests/state_based_workflow_example.py @@ -9,7 +9,7 @@ This example shows how to use state for: 4. State-based error handling and recovery """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import Dict, Any, List import random import json @@ -260,7 +260,7 @@ report_task = Task( ) # Create workflow -workflow = PraisonAIAgents( +workflow = Agents( agents=[data_analyst, data_engineer, report_generator], tasks=[analyze_task, decision_task, clean_task, process_task, report_task], verbose=1, diff --git a/src/praisonai-agents/tests/state_management_example.py b/src/praisonai-agents/tests/state_management_example.py index c98309777..27bdb08d2 100644 --- a/src/praisonai-agents/tests/state_management_example.py +++ b/src/praisonai-agents/tests/state_management_example.py @@ -9,7 +9,7 @@ This example demonstrates various state management features: 4. State-based decision making """ -from praisonaiagents import Agent, Task, PraisonAIAgents, Session +from praisonaiagents import Agent, Task, Agents, Session from typing import Dict, Any import json import time @@ -211,7 +211,7 @@ analyze_project_task = Task( ) # Create workflow with state management -workflow = PraisonAIAgents( +workflow = Agents( agents=[project_manager, developer, analyst], tasks=[init_task, plan_features_task, implement_features_task, analyze_project_task], verbose=1, diff --git a/src/praisonai-agents/tests/state_with_memory_example.py b/src/praisonai-agents/tests/state_with_memory_example.py index 00c0c940c..43fc8ad90 100644 --- a/src/praisonai-agents/tests/state_with_memory_example.py +++ b/src/praisonai-agents/tests/state_with_memory_example.py @@ -9,7 +9,7 @@ This example demonstrates: 4. Historical state tracking """ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.memory import Memory from typing import Dict, Any, List import json @@ -325,7 +325,7 @@ save_state_task = Task( ) # Create workflow with shared memory -workflow = PraisonAIAgents( +workflow = Agents( agents=[conversation_manager, memory_analyst], tasks=[ init_conversation_task, @@ -382,7 +382,7 @@ test_task = Task( tools=[search_conversation_memory] ) -test_workflow = PraisonAIAgents( +test_workflow = Agents( agents=[test_agent], tasks=[test_task], memory=memory_config, diff --git a/src/praisonai-agents/tests/structured_agents_example.py b/src/praisonai-agents/tests/structured_agents_example.py index 957911626..43bf72028 100644 --- a/src/praisonai-agents/tests/structured_agents_example.py +++ b/src/praisonai-agents/tests/structured_agents_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents, Tools +from praisonaiagents import Agent, Task, Agents, Tools from pydantic import BaseModel class AnalysisReport(BaseModel): @@ -46,7 +46,7 @@ analysis_task = Task( ) # Initialize and run agents -agents = PraisonAIAgents( +agents = Agents( agents=[researcher, analyst], tasks=[research_task, analysis_task], process="sequential", diff --git a/src/praisonai-agents/tests/telemetry_example.py b/src/praisonai-agents/tests/telemetry_example.py index 00abb071a..3b2798242 100644 --- a/src/praisonai-agents/tests/telemetry_example.py +++ b/src/praisonai-agents/tests/telemetry_example.py @@ -10,7 +10,7 @@ This example shows how to: import os from praisonaiagents import ( - Agent, Task, PraisonAIAgents, + Agent, Task, Agents, enable_telemetry, disable_telemetry, get_telemetry_collector ) from praisonaiagents.tools import DuckDuckGoSearchTool @@ -72,7 +72,7 @@ def basic_telemetry_example(): ) # Create workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[researcher, writer], tasks=[research_task, writing_task], process="sequential", diff --git a/src/praisonai-agents/tests/test.py b/src/praisonai-agents/tests/test.py index a74f15567..5f4802c96 100644 --- a/src/praisonai-agents/tests/test.py +++ b/src/praisonai-agents/tests/test.py @@ -1,6 +1,6 @@ from typing import List, Dict from pydantic import BaseModel -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.main import TaskOutput # Pydantic models for structured output @@ -73,7 +73,7 @@ outline_task = Task( ) # Create initial workflow for outline -outline_workflow = PraisonAIAgents( +outline_workflow = Agents( agents=[planner_agent], tasks=[outline_task], verbose=True, @@ -111,7 +111,7 @@ for chapter in story_outline.chapters: chapter_tasks.append(chapter_task) # Create sequential workflow for chapters -chapter_workflow = PraisonAIAgents( +chapter_workflow = Agents( agents=[writer_agent], tasks=chapter_tasks, verbose=True, diff --git a/src/praisonai-agents/tests/test_context_agent.py b/src/praisonai-agents/tests/test_context_agent.py index b9d4ea3e5..01f41ed20 100644 --- a/src/praisonai-agents/tests/test_context_agent.py +++ b/src/praisonai-agents/tests/test_context_agent.py @@ -220,14 +220,14 @@ def test_backward_compatibility(): print("āœ… ImageAgent still works") # Test that we can import other PraisonAI components - from praisonaiagents import Task, PraisonAIAgents - print("āœ… Task and PraisonAIAgents can still be imported") + from praisonaiagents import Task, Agents + print("āœ… Task and Agents can still be imported") # Test that __all__ exports are working import praisonaiagents expected_exports = [ 'Agent', 'ImageAgent', 'ContextAgent', 'create_context_agent', - 'PraisonAIAgents', 'Task' + 'Agents', 'Task' ] for export in expected_exports: diff --git a/src/praisonai-agents/tests/test_ollama_async_fix.py b/src/praisonai-agents/tests/test_ollama_async_fix.py index c9a5e1964..4ca2841a7 100644 --- a/src/praisonai-agents/tests/test_ollama_async_fix.py +++ b/src/praisonai-agents/tests/test_ollama_async_fix.py @@ -7,7 +7,7 @@ import asyncio import logging import os import pytest -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import Dict, Any # Enable debug logging @@ -53,7 +53,7 @@ async def _test_model_async_helper(model_name: str): ) # Create and run the workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[agent], tasks=[task], verbose=True @@ -105,7 +105,7 @@ def _test_model_sync_helper(model_name: str): ) # Create and run the workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[agent], tasks=[task], verbose=True diff --git a/src/praisonai-agents/tests/test_ollama_fix.py b/src/praisonai-agents/tests/test_ollama_fix.py index bc358eabb..0e3695441 100644 --- a/src/praisonai-agents/tests/test_ollama_fix.py +++ b/src/praisonai-agents/tests/test_ollama_fix.py @@ -6,7 +6,7 @@ Test script to verify Ollama empty response fix. import logging import os import pytest -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import Dict, Any # Enable debug logging @@ -52,7 +52,7 @@ def _test_model_helper(model_name: str): ) # Create and run the workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[agent], tasks=[task], verbose=True diff --git a/src/praisonai-agents/tests/test_planning.py b/src/praisonai-agents/tests/test_planning.py index 93c8b73dc..ada9c1b13 100644 --- a/src/praisonai-agents/tests/test_planning.py +++ b/src/praisonai-agents/tests/test_planning.py @@ -6,7 +6,7 @@ This module contains comprehensive tests for: - TodoList and TodoItem classes - PlanStorage for persistence - PlanningAgent for plan creation -- PraisonAIAgents planning integration +- Agents planning integration - Read-only mode - Approval flow """ @@ -797,31 +797,31 @@ class TestPlanningAgent: # ============================================================================= -# SECTION 5: PraisonAIAgents Planning Integration Tests +# SECTION 5: Agents Planning Integration Tests # ============================================================================= -class TestPraisonAIAgentsPlanningIntegration: - """Tests for planning integration in PraisonAIAgents.""" +class TestAgentsPlanningIntegration: + """Tests for planning integration in Agents.""" def test_agents_planning_disabled_by_default(self): """Test that planning is disabled by default.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents(agents=[agent], tasks=[task]) + agents = Agents(agents=[agent], tasks=[task]) assert agents.planning is False def test_agents_planning_enabled(self): """Test enabling planning mode.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True @@ -831,12 +831,12 @@ class TestPraisonAIAgentsPlanningIntegration: def test_agents_planning_custom_llm(self): """Test custom planning LLM.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True, @@ -847,12 +847,12 @@ class TestPraisonAIAgentsPlanningIntegration: def test_agents_auto_approve_plan(self): """Test auto-approve plan option.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True, @@ -864,13 +864,13 @@ class TestPraisonAIAgentsPlanningIntegration: @pytest.mark.asyncio async def test_agents_start_with_planning(self): """Test starting agents with planning enabled.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents from praisonaiagents.planning import Plan, PlanStep agent = Agent(name="Test", role="Tester", llm="gpt-5-nano") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True, @@ -886,13 +886,13 @@ class TestPraisonAIAgentsPlanningIntegration: def test_agents_get_current_plan(self): """Test getting current plan.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents from praisonaiagents.planning import Plan agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True @@ -903,12 +903,12 @@ class TestPraisonAIAgentsPlanningIntegration: def test_agents_get_todo_list(self): """Test getting todo list.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True diff --git a/src/praisonai-agents/tests/test_planning_tools.py b/src/praisonai-agents/tests/test_planning_tools.py index 2cd5b1232..e7ee464b6 100644 --- a/src/praisonai-agents/tests/test_planning_tools.py +++ b/src/praisonai-agents/tests/test_planning_tools.py @@ -4,7 +4,7 @@ Test-Driven Development tests for Planning Mode with Tools Support. This module contains tests for: - PlanningAgent with tools parameter - PlanningAgent with reasoning mode -- PraisonAIAgents with planning_tools parameter +- Agents with planning_tools parameter - Research-enabled planning """ @@ -177,15 +177,15 @@ class TestPlanningAgentCreatePlanWithTools: # ============================================================================= -# SECTION 4: PraisonAIAgents planning_tools Parameter Tests +# SECTION 4: Agents planning_tools Parameter Tests # ============================================================================= -class TestPraisonAIAgentsPlanningTools: - """Tests for PraisonAIAgents planning_tools parameter.""" +class TestAgentsPlanningTools: + """Tests for Agents planning_tools parameter.""" def test_praisonaiagents_accepts_planning_tools(self): - """Test that PraisonAIAgents accepts planning_tools parameter.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + """Test that Agents accepts planning_tools parameter.""" + from praisonaiagents import Agent, Task, Agents def search_tool(query: str) -> str: return "results" @@ -193,7 +193,7 @@ class TestPraisonAIAgentsPlanningTools: agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True, @@ -205,12 +205,12 @@ class TestPraisonAIAgentsPlanningTools: def test_praisonaiagents_planning_tools_default_none(self): """Test that planning_tools defaults to None.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True @@ -220,7 +220,7 @@ class TestPraisonAIAgentsPlanningTools: def test_praisonaiagents_passes_tools_to_planning_agent(self): """Test that planning_tools are passed to PlanningAgent.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents def search_tool(query: str) -> str: return "results" @@ -228,7 +228,7 @@ class TestPraisonAIAgentsPlanningTools: agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True, @@ -284,20 +284,20 @@ class TestPlanningAgentReasoningMode: # ============================================================================= -# SECTION 6: PraisonAIAgents planning_reasoning Parameter Tests +# SECTION 6: Agents planning_reasoning Parameter Tests # ============================================================================= -class TestPraisonAIAgentsPlanningReasoning: - """Tests for PraisonAIAgents planning_reasoning parameter.""" +class TestAgentsPlanningReasoning: + """Tests for Agents planning_reasoning parameter.""" def test_praisonaiagents_accepts_planning_reasoning(self): - """Test that PraisonAIAgents accepts planning_reasoning parameter.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + """Test that Agents accepts planning_reasoning parameter.""" + from praisonaiagents import Agent, Task, Agents agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True, @@ -308,12 +308,12 @@ class TestPraisonAIAgentsPlanningReasoning: def test_praisonaiagents_planning_reasoning_default_false(self): """Test that planning_reasoning defaults to False.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True @@ -323,12 +323,12 @@ class TestPraisonAIAgentsPlanningReasoning: def test_praisonaiagents_passes_reasoning_to_planning_agent(self): """Test that planning_reasoning is passed to PlanningAgent.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents agent = Agent(name="Test", role="Tester") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True, @@ -349,7 +349,7 @@ class TestPlanningToolsIntegration: def test_planning_with_tools_and_reasoning(self): """Test planning with both tools and reasoning enabled.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents def search_tool(query: str) -> str: return "search results" @@ -357,7 +357,7 @@ class TestPlanningToolsIntegration: agent = Agent(name="Researcher", role="Research Analyst") task = Task(description="Research AI trends", agent=agent) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], planning=True, diff --git a/src/praisonai-agents/tests/test_self_reflection_comprehensive.py b/src/praisonai-agents/tests/test_self_reflection_comprehensive.py index 86f0af202..b8fb44001 100644 --- a/src/praisonai-agents/tests/test_self_reflection_comprehensive.py +++ b/src/praisonai-agents/tests/test_self_reflection_comprehensive.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Comprehensive test script to verify self-reflection works with tools after the fix""" -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Define duckduckgo_search tool locally to avoid import issues def duckduckgo_search(query: str) -> str: @@ -49,7 +49,7 @@ def test_self_reflection_with_tools(): ) # Create and start the agents - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" @@ -90,7 +90,7 @@ def test_self_reflection_without_tools(): ) # Create and start the agents - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" diff --git a/src/praisonai-agents/tests/test_self_reflection_fix_verification.py b/src/praisonai-agents/tests/test_self_reflection_fix_verification.py index 59c4da861..e59c58f54 100644 --- a/src/praisonai-agents/tests/test_self_reflection_fix_verification.py +++ b/src/praisonai-agents/tests/test_self_reflection_fix_verification.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Test to verify the self-reflection fix works with tools""" -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Define calculator tool locally to avoid import issues def calculator(expression: str) -> str: @@ -46,7 +46,7 @@ def test_self_reflection_fix_verification(): ) # Create and run the agents - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" diff --git a/src/praisonai-agents/tests/tools-class.py b/src/praisonai-agents/tests/tools-class.py index 1f4f15c7c..4eea823cc 100644 --- a/src/praisonai-agents/tests/tools-class.py +++ b/src/praisonai-agents/tests/tools-class.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import os import requests from typing import Any, Dict, List, Optional @@ -106,7 +106,7 @@ task = Task( ) # Create and start the workflow -agents = PraisonAIAgents( +agents = Agents( agents=[agent], tasks=[task], verbose=True diff --git a/src/praisonai-agents/tests/tools_example.py b/src/praisonai-agents/tests/tools_example.py index 891ea56ba..4f836d1f4 100644 --- a/src/praisonai-agents/tests/tools_example.py +++ b/src/praisonai-agents/tests/tools_example.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import get_article, get_news_sources, get_articles_from_source, get_trending_topics # Create Wikipedia agent @@ -22,7 +22,7 @@ news_task = Task( # Run agent -agents = PraisonAIAgents( +agents = Agents( agents=[news_agent], tasks=[news_task], process="sequential" diff --git a/src/praisonai-agents/tests/unit/context/test_context_param.py b/src/praisonai-agents/tests/unit/context/test_context_param.py index 4e65cf9b6..d4a9006d2 100644 --- a/src/praisonai-agents/tests/unit/context/test_context_param.py +++ b/src/praisonai-agents/tests/unit/context/test_context_param.py @@ -1,5 +1,5 @@ """ -Unit tests for the context= parameter in Agent, Workflow, and PraisonAIAgents. +Unit tests for the context= parameter in Agent, Workflow, and Agents. Tests cover: - Parameter types (False, True, ManagerConfig, ContextManager) @@ -148,30 +148,30 @@ class TestWorkflowContextParam: assert workflow.context is True -class TestPraisonAIAgentsContextParam: - """Tests for PraisonAIAgents context= parameter.""" +class TestAgentsContextParam: + """Tests for Agents context= parameter.""" def test_agents_context_false_default(self): - """PraisonAIAgents context=False should have zero overhead.""" - from praisonaiagents import Agent, PraisonAIAgents, Task + """Agents context=False should have zero overhead.""" + from praisonaiagents import Agent, Agents, Task agent = Agent(instructions="Test agent") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents(agents=[agent], tasks=[task], context=False) + agents = Agents(agents=[agent], tasks=[task], context=False) assert agents._context_param is False assert agents._context_manager is None assert agents._context_manager_initialized is False def test_agents_context_true_lazy_init(self): - """PraisonAIAgents context=True should lazy-init MultiAgentContextManager.""" - from praisonaiagents import Agent, PraisonAIAgents, Task + """Agents context=True should lazy-init MultiAgentContextManager.""" + from praisonaiagents import Agent, Agents, Task agent = Agent(instructions="Test agent") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents(agents=[agent], tasks=[task], context=True) + agents = Agents(agents=[agent], tasks=[task], context=True) # Not initialized until first access assert agents._context_manager_initialized is False @@ -182,8 +182,8 @@ class TestPraisonAIAgentsContextParam: assert manager is not None def test_agents_context_manager_config(self): - """PraisonAIAgents context=ManagerConfig should use provided config.""" - from praisonaiagents import Agent, PraisonAIAgents, Task + """Agents context=ManagerConfig should use provided config.""" + from praisonaiagents import Agent, Agents, Task from praisonaiagents.context import ManagerConfig config = ManagerConfig( @@ -194,7 +194,7 @@ class TestPraisonAIAgentsContextParam: agent = Agent(instructions="Test agent") task = Task(description="Test task", agent=agent) - agents = PraisonAIAgents(agents=[agent], tasks=[task], context=config) + agents = Agents(agents=[agent], tasks=[task], context=config) manager = agents.context_manager assert manager is not None diff --git a/src/praisonai-agents/tests/vector-db-agents.py b/src/praisonai-agents/tests/vector-db-agents.py index e8111cf99..9baab2a2c 100644 --- a/src/praisonai-agents/tests/vector-db-agents.py +++ b/src/praisonai-agents/tests/vector-db-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Define the configuration for the Knowledge instance config = { @@ -29,7 +29,7 @@ rag_task = Task( ) # Build Agents -agents = PraisonAIAgents( +agents = Agents( agents=[rag_agent], tasks=[rag_task], user_id="user1" diff --git a/src/praisonai-agents/tests/video-agent.py b/src/praisonai-agents/tests/video-agent.py index f0a9894c6..f8cf30514 100644 --- a/src/praisonai-agents/tests/video-agent.py +++ b/src/praisonai-agents/tests/video-agent.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Create Video Analysis Agent video_agent = Agent( @@ -24,8 +24,8 @@ task1 = Task( images=["video.mp4"] ) -# Create PraisonAIAgents instance -agents = PraisonAIAgents( +# Create Agents instance +agents = Agents( agents=[video_agent], tasks=[task1], process="sequential", diff --git a/src/praisonai-agents/tests/wikipedia-agent.py b/src/praisonai-agents/tests/wikipedia-agent.py index debe7faa0..eba04ca4b 100644 --- a/src/praisonai-agents/tests/wikipedia-agent.py +++ b/src/praisonai-agents/tests/wikipedia-agent.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import wiki_search, wiki_summary, wiki_page, wiki_random, wiki_language agent = Agent( diff --git a/src/praisonai-agents/tests/workflow-test-agents.py b/src/praisonai-agents/tests/workflow-test-agents.py index 1060e735b..b9f366c1a 100644 --- a/src/praisonai-agents/tests/workflow-test-agents.py +++ b/src/praisonai-agents/tests/workflow-test-agents.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from praisonaiagents.tools import cot_save, cot_upload_to_huggingface from pydantic import BaseModel import os @@ -113,7 +113,7 @@ upload_to_huggingface_task = Task( ) # Initialize workflow -agents = PraisonAIAgents( +agents = Agents( agents=[qa_generator, cot_generator, upload_to_huggingface], tasks=[generate_task, generate_cot_task, upload_to_huggingface_task], process="workflow", diff --git a/src/praisonai-agents/tests/workflow_example_basic.py b/src/praisonai-agents/tests/workflow_example_basic.py index d76b84c6a..2c9eabeae 100644 --- a/src/praisonai-agents/tests/workflow_example_basic.py +++ b/src/praisonai-agents/tests/workflow_example_basic.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents from typing import List, Dict from duckduckgo_search import DDGS @@ -64,7 +64,7 @@ validate_task = Task( ) # 4. AI Agents Workflow -agents = PraisonAIAgents( +agents = Agents( agents=[data_agent], tasks=[collect_task, validate_task], verbose=1, diff --git a/src/praisonai-agents/tests/workflow_example_detailed.py b/src/praisonai-agents/tests/workflow_example_detailed.py index 6dbab2a37..2bc2696ca 100644 --- a/src/praisonai-agents/tests/workflow_example_detailed.py +++ b/src/praisonai-agents/tests/workflow_example_detailed.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import random from typing import List, Dict, Union import json @@ -224,8 +224,8 @@ process_task = Task( output_json=ProcessedPerson ) -# Create PraisonAIAgents instance with workflow process -workflow = PraisonAIAgents( +# Create Agents instance with workflow process +workflow = Agents( agents=[data_agent, process_agent], tasks=[collect_task, validate_task, process_task], verbose=1, diff --git a/src/praisonai-agents/uv.lock b/src/praisonai-agents/uv.lock index 24dc7d914..be342157e 100644 --- a/src/praisonai-agents/uv.lock +++ b/src/praisonai-agents/uv.lock @@ -2422,7 +2422,7 @@ wheels = [ [[package]] name = "praisonaiagents" -version = "0.9.0" +version = "0.9.1" source = { editable = "." } dependencies = [ { name = "aiohttp" }, diff --git a/src/praisonai/README.md b/src/praisonai/README.md index 63e4ff625..08b993428 100644 --- a/src/praisonai/README.md +++ b/src/praisonai/README.md @@ -538,11 +538,11 @@ python app.py Create app.py file and add the code below: ```python -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents research_agent = Agent(instructions="Research about AI") summarise_agent = Agent(instructions="Summarise research agent's findings") -agents = PraisonAIAgents(agents=[research_agent, summarise_agent]) +agents = Agents(agents=[research_agent, summarise_agent]) agents.start() ``` @@ -3380,11 +3380,11 @@ See [Agent Memory](#6-agent-memory-zero-dependencies) for more options. How do I run multiple agents together? ```python -from praisonaiagents import Agent, PraisonAIAgents +from praisonaiagents import Agent, Agents agent1 = Agent(instructions="Research topics") agent2 = Agent(instructions="Summarize findings") -agents = PraisonAIAgents(agents=[agent1, agent2]) +agents = Agents(agents=[agent1, agent2]) agents.start() ``` diff --git a/src/praisonai/praisonai.rb b/src/praisonai/praisonai.rb index 8d9fdb16b..3d5022b68 100644 --- a/src/praisonai/praisonai.rb +++ b/src/praisonai/praisonai.rb @@ -3,8 +3,8 @@ class Praisonai < Formula desc "AI tools for various AI applications" homepage "https://github.com/MervinPraison/PraisonAI" - url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.4.0.tar.gz" - sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.4.0.tar.gz | shasum -a 256`.split.first + url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.4.1.tar.gz" + sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.4.1.tar.gz | shasum -a 256`.split.first license "MIT" depends_on "python@3.11" diff --git a/src/praisonai/praisonai/acp/server.py b/src/praisonai/praisonai/acp/server.py index 892cd1238..b90f2e888 100644 --- a/src/praisonai/praisonai/acp/server.py +++ b/src/praisonai/praisonai/acp/server.py @@ -50,7 +50,7 @@ class ACPServer: Args: config: ACP configuration agent: Optional pre-configured Agent instance - agents: Optional pre-configured PraisonAIAgents instance + agents: Optional pre-configured Agents instance """ self.config = config or ACPConfig() self._agent = agent diff --git a/src/praisonai/praisonai/agents_generator.py b/src/praisonai/praisonai/agents_generator.py index 650a66079..a5335a73f 100644 --- a/src/praisonai/praisonai/agents_generator.py +++ b/src/praisonai/praisonai/agents_generator.py @@ -26,7 +26,7 @@ AGENTOPS_AVAILABLE = False PRAISONAI_AVAILABLE = False try: - from praisonaiagents import Agent as PraisonAgent, Task as PraisonTask, PraisonAIAgents + from praisonaiagents import Agent as PraisonAgent, Task as PraisonTask, Agents PRAISONAI_AVAILABLE = True except ImportError: pass @@ -873,7 +873,7 @@ class AgentsGenerator: memory = config.get('memory', False) self.logger.debug(f"Memory: {memory}") if config.get('process') == 'hierarchical': - agents = PraisonAIAgents( + agents = Agents( agents=list(agents.values()), tasks=tasks, verbose=True, @@ -882,7 +882,7 @@ class AgentsGenerator: memory=memory ) else: - agents = PraisonAIAgents( + agents = Agents( agents=list(agents.values()), tasks=tasks, verbose=True, diff --git a/src/praisonai/praisonai/auto.py b/src/praisonai/praisonai/auto.py index 46a463e2c..b5059d3dc 100644 --- a/src/praisonai/praisonai/auto.py +++ b/src/praisonai/praisonai/auto.py @@ -15,7 +15,7 @@ PRAISONAI_TOOLS_AVAILABLE = False PRAISONAI_AVAILABLE = False try: - from praisonaiagents import Agent as PraisonAgent, Task as PraisonTask, PraisonAIAgents + from praisonaiagents import Agent as PraisonAgent, Task as PraisonTask, Agents PRAISONAI_AVAILABLE = True except ImportError: pass diff --git a/src/praisonai/praisonai/cli/features/agents.py b/src/praisonai/praisonai/cli/features/agents.py index b40082150..3ad99e688 100644 --- a/src/praisonai/praisonai/cli/features/agents.py +++ b/src/praisonai/praisonai/cli/features/agents.py @@ -179,7 +179,7 @@ class MultiAgentHandler: Execution result """ try: - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents # Create Agent objects agents = [] @@ -217,7 +217,7 @@ class MultiAgentHandler: print(f" - {agent.name}: {agent.role}") print() - praison_agents = PraisonAIAgents( + praison_agents = Agents( agents=agents, tasks=tasks, process=process, diff --git a/src/praisonai/praisonai/cli/features/auto_mode.py b/src/praisonai/praisonai/cli/features/auto_mode.py new file mode 100644 index 000000000..12ba75899 --- /dev/null +++ b/src/praisonai/praisonai/cli/features/auto_mode.py @@ -0,0 +1,552 @@ +""" +Auto Mode Handler for PraisonAI CLI. + +Provides CLI flags and controls for auto-mode execution with progressive escalation. +Implements the "advanced-by-default, fast-by-default" strategy. + +CLI Flags: + --auto / --no-auto Enable/disable auto mode (default: auto) + --dry-run Show what would be done without executing + --apply Apply changes (opposite of dry-run) + --budget-steps N Maximum steps budget + --budget-time N Maximum time budget in seconds + --budget-tokens N Maximum tokens budget + --allow-tools TOOLS Comma-separated list of allowed tools + --deny-tools TOOLS Comma-separated list of denied tools + --checkpoint / --no-checkpoint Enable/disable checkpoints + --router MODE Router mode: heuristic, trained, off +""" + +import logging +from dataclasses import dataclass, field +from typing import Any, Dict, List, Optional, Set, Callable +from enum import Enum + +logger = logging.getLogger(__name__) + + +class AutoModeLevel(Enum): + """Auto mode levels for CLI.""" + OFF = "off" # Manual mode - ask for everything + SUGGEST = "suggest" # Suggest actions, require approval + AUTO = "auto" # Auto-approve safe actions + FULL_AUTO = "full_auto" # Auto-approve everything (YOLO) + + +class RouterMode(Enum): + """Router modes for model selection.""" + HEURISTIC = "heuristic" # Fast keyword-based routing (default) + TRAINED = "trained" # ML-based routing (optional plugin) + OFF = "off" # No routing, use default model + + +@dataclass +class AutoModeConfig: + """Configuration for auto mode execution.""" + # Mode settings + mode: AutoModeLevel = AutoModeLevel.AUTO + dry_run: bool = False + + # Budgets + budget_steps: int = 50 + budget_time_seconds: int = 300 + budget_tokens: int = 100000 + budget_tool_calls: int = 100 + + # Tool controls + allow_tools: Set[str] = field(default_factory=set) + deny_tools: Set[str] = field(default_factory=set) + + # Checkpoint settings + enable_checkpoints: bool = True + auto_checkpoint_on_write: bool = True + + # Router settings + router_mode: RouterMode = RouterMode.HEURISTIC + + # Escalation settings + auto_escalate: bool = True + auto_deescalate: bool = True + + # Approval settings + require_approval_for_writes: bool = True + require_approval_for_commands: bool = True + require_approval_for_deletes: bool = True + + # Display settings + show_stage: bool = True + show_budgets: bool = True + show_checkpoints: bool = True + verbose: bool = False + + @classmethod + def from_cli_args(cls, **kwargs) -> "AutoModeConfig": + """Create config from CLI arguments.""" + config = cls() + + # Mode + if kwargs.get("auto") is False: + config.mode = AutoModeLevel.OFF + elif kwargs.get("full_auto"): + config.mode = AutoModeLevel.FULL_AUTO + elif kwargs.get("suggest"): + config.mode = AutoModeLevel.SUGGEST + + # Dry run + if kwargs.get("dry_run"): + config.dry_run = True + elif kwargs.get("apply"): + config.dry_run = False + + # Budgets + if kwargs.get("budget_steps"): + config.budget_steps = kwargs["budget_steps"] + if kwargs.get("budget_time"): + config.budget_time_seconds = kwargs["budget_time"] + if kwargs.get("budget_tokens"): + config.budget_tokens = kwargs["budget_tokens"] + + # Tools + if kwargs.get("allow_tools"): + config.allow_tools = set(kwargs["allow_tools"].split(",")) + if kwargs.get("deny_tools"): + config.deny_tools = set(kwargs["deny_tools"].split(",")) + + # Checkpoints + if kwargs.get("checkpoint") is False: + config.enable_checkpoints = False + elif kwargs.get("no_checkpoint"): + config.enable_checkpoints = False + + # Router + if kwargs.get("router"): + try: + config.router_mode = RouterMode(kwargs["router"]) + except ValueError: + logger.warning(f"Unknown router mode: {kwargs['router']}") + + # Verbose + config.verbose = kwargs.get("verbose", False) + + return config + + +@dataclass +class AutoModeState: + """Runtime state for auto mode execution.""" + # Current execution + current_stage: int = 0 + steps_taken: int = 0 + tokens_used: int = 0 + tool_calls: int = 0 + time_elapsed: float = 0.0 + + # Checkpoints + checkpoint_ids: List[str] = field(default_factory=list) + files_modified: Set[str] = field(default_factory=set) + + # Approvals + pending_approvals: List[Dict[str, Any]] = field(default_factory=list) + approved_actions: int = 0 + denied_actions: int = 0 + + # Errors + errors: List[str] = field(default_factory=list) + warnings: List[str] = field(default_factory=list) + + def is_within_budget(self, config: AutoModeConfig) -> bool: + """Check if execution is within budget.""" + if self.steps_taken >= config.budget_steps: + return False + if self.time_elapsed >= config.budget_time_seconds: + return False + if self.tokens_used >= config.budget_tokens: + return False + if self.tool_calls >= config.budget_tool_calls: + return False + return True + + def get_budget_status(self, config: AutoModeConfig) -> Dict[str, Any]: + """Get budget utilization status.""" + return { + "steps": { + "used": self.steps_taken, + "limit": config.budget_steps, + "percent": (self.steps_taken / config.budget_steps * 100) if config.budget_steps > 0 else 0, + }, + "time": { + "used": self.time_elapsed, + "limit": config.budget_time_seconds, + "percent": (self.time_elapsed / config.budget_time_seconds * 100) if config.budget_time_seconds > 0 else 0, + }, + "tokens": { + "used": self.tokens_used, + "limit": config.budget_tokens, + "percent": (self.tokens_used / config.budget_tokens * 100) if config.budget_tokens > 0 else 0, + }, + "tool_calls": { + "used": self.tool_calls, + "limit": config.budget_tool_calls, + "percent": (self.tool_calls / config.budget_tool_calls * 100) if config.budget_tool_calls > 0 else 0, + }, + } + + +class AutoModeHandler: + """ + Handler for auto mode CLI integration. + + Provides: + - CLI flag parsing + - Escalation pipeline integration + - Budget tracking + - Checkpoint management + - Status display + + Example: + handler = AutoModeHandler() + config = handler.parse_args(auto=True, budget_steps=20) + + # Execute with auto mode + result = await handler.execute(prompt, config) + """ + + def __init__( + self, + verbose: bool = False, + on_stage_change: Optional[Callable[[int, int], None]] = None, + on_checkpoint: Optional[Callable[[str], None]] = None, + ): + """ + Initialize the handler. + + Args: + verbose: Enable verbose output + on_stage_change: Callback for stage transitions + on_checkpoint: Callback for checkpoint creation + """ + self.verbose = verbose + self.on_stage_change = on_stage_change + self.on_checkpoint = on_checkpoint + + self._config: Optional[AutoModeConfig] = None + self._state: Optional[AutoModeState] = None + self._pipeline = None + self._checkpoint_service = None + + @property + def feature_name(self) -> str: + return "auto_mode" + + def parse_args(self, **kwargs) -> AutoModeConfig: + """ + Parse CLI arguments into config. + + Args: + **kwargs: CLI arguments + + Returns: + AutoModeConfig + """ + self._config = AutoModeConfig.from_cli_args(**kwargs) + self._state = AutoModeState() + return self._config + + def get_config(self) -> Optional[AutoModeConfig]: + """Get current configuration.""" + return self._config + + def get_state(self) -> Optional[AutoModeState]: + """Get current state.""" + return self._state + + async def execute( + self, + prompt: str, + agent: Optional[Any] = None, + tools: Optional[List[Any]] = None, + context: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + """ + Execute prompt with auto mode. + + Args: + prompt: User prompt + agent: Agent instance + tools: Available tools + context: Execution context + + Returns: + Execution result + """ + if not self._config: + self._config = AutoModeConfig() + if not self._state: + self._state = AutoModeState() + + import time + start_time = time.time() + + # Filter tools based on config + filtered_tools = self._filter_tools(tools or []) + + # Initialize escalation pipeline + try: + from praisonaiagents.escalation import EscalationPipeline, EscalationConfig + + escalation_config = EscalationConfig( + max_steps=self._config.budget_steps, + max_time_seconds=self._config.budget_time_seconds, + max_tokens=self._config.budget_tokens, + auto_escalate=self._config.auto_escalate, + auto_deescalate=self._config.auto_deescalate, + enable_checkpoints=self._config.enable_checkpoints, + require_approval_for_writes=self._config.require_approval_for_writes, + ) + + self._pipeline = EscalationPipeline( + config=escalation_config, + agent=agent, + tools=filtered_tools, + checkpoint_service=self._checkpoint_service, + on_stage_change=self._handle_stage_change, + ) + + # Execute + result = await self._pipeline.execute(prompt, context) + + # Update state + self._state.steps_taken = result.steps_taken + self._state.tokens_used = result.tokens_used + self._state.tool_calls = result.tool_calls + self._state.time_elapsed = time.time() - start_time + self._state.current_stage = result.final_stage.value + + if result.checkpoint_id: + self._state.checkpoint_ids.append(result.checkpoint_id) + + self._state.files_modified.update(result.files_modified) + self._state.errors.extend(result.errors) + self._state.warnings.extend(result.warnings) + + return { + "success": result.success, + "response": result.response, + "stage": result.final_stage.name, + "escalations": result.escalations, + "state": self._state, + } + + except ImportError: + # Fallback if escalation module not available + logger.warning("Escalation module not available, using basic execution") + + if agent and hasattr(agent, 'chat'): + response = agent.chat(prompt) + self._state.time_elapsed = time.time() - start_time + + return { + "success": True, + "response": response, + "stage": "DIRECT", + "escalations": 0, + "state": self._state, + } + + return { + "success": False, + "response": "No agent available", + "stage": "DIRECT", + "escalations": 0, + "state": self._state, + } + + def _filter_tools(self, tools: List[Any]) -> List[Any]: + """Filter tools based on allow/deny lists.""" + if not self._config: + return tools + + filtered = [] + for tool in tools: + tool_name = getattr(tool, '__name__', str(tool)).lower() + + # Check deny list first + if self._config.deny_tools: + if any(d.lower() in tool_name for d in self._config.deny_tools): + continue + + # Check allow list + if self._config.allow_tools: + if not any(a.lower() in tool_name for a in self._config.allow_tools): + continue + + filtered.append(tool) + + return filtered + + def _handle_stage_change(self, old_stage, new_stage): + """Handle stage change event.""" + if self._state: + self._state.current_stage = new_stage.value + + if self.on_stage_change: + self.on_stage_change(old_stage.value, new_stage.value) + + if self.verbose: + self._display_stage_change(old_stage, new_stage) + + def _display_stage_change(self, old_stage, new_stage): + """Display stage change to user.""" + try: + from rich import print as rprint + + direction = "ā¬†ļø" if new_stage > old_stage else "ā¬‡ļø" + rprint(f"[cyan]{direction} Stage: {old_stage.name} → {new_stage.name}[/cyan]") + except ImportError: + print(f"Stage: {old_stage.name} -> {new_stage.name}") + + def display_status(self): + """Display current status.""" + if not self._config or not self._state: + return + + try: + from rich.console import Console + from rich.table import Table + from rich.panel import Panel + + console = Console() + + # Budget table + budget = self._state.get_budget_status(self._config) + + table = Table(title="Auto Mode Status") + table.add_column("Metric", style="cyan") + table.add_column("Used", style="green") + table.add_column("Limit", style="yellow") + table.add_column("Usage", style="magenta") + + for name, data in budget.items(): + table.add_row( + name.replace("_", " ").title(), + str(data["used"]), + str(data["limit"]), + f"{data['percent']:.1f}%" + ) + + console.print(table) + + # Stage info + stage_names = ["DIRECT", "HEURISTIC", "PLANNED", "AUTONOMOUS"] + current = stage_names[self._state.current_stage] if self._state.current_stage < len(stage_names) else "UNKNOWN" + console.print(f"\n[bold]Current Stage:[/bold] {current}") + + # Checkpoints + if self._state.checkpoint_ids: + console.print(f"[bold]Checkpoints:[/bold] {len(self._state.checkpoint_ids)}") + + # Files modified + if self._state.files_modified: + console.print(f"[bold]Files Modified:[/bold] {len(self._state.files_modified)}") + + except ImportError: + # Fallback to basic output + print(f"Steps: {self._state.steps_taken}/{self._config.budget_steps}") + print(f"Time: {self._state.time_elapsed:.1f}s/{self._config.budget_time_seconds}s") + + def get_cli_options(self) -> List[Dict[str, Any]]: + """ + Get CLI option definitions for integration. + + Returns: + List of option definitions + """ + return [ + { + "name": "--auto/--no-auto", + "default": True, + "help": "Enable/disable auto mode", + }, + { + "name": "--dry-run", + "is_flag": True, + "help": "Show what would be done without executing", + }, + { + "name": "--apply", + "is_flag": True, + "help": "Apply changes (opposite of dry-run)", + }, + { + "name": "--budget-steps", + "type": int, + "default": 50, + "help": "Maximum steps budget", + }, + { + "name": "--budget-time", + "type": int, + "default": 300, + "help": "Maximum time budget in seconds", + }, + { + "name": "--budget-tokens", + "type": int, + "default": 100000, + "help": "Maximum tokens budget", + }, + { + "name": "--allow-tools", + "type": str, + "help": "Comma-separated list of allowed tools", + }, + { + "name": "--deny-tools", + "type": str, + "help": "Comma-separated list of denied tools", + }, + { + "name": "--checkpoint/--no-checkpoint", + "default": True, + "help": "Enable/disable checkpoints", + }, + { + "name": "--router", + "type": str, + "default": "heuristic", + "help": "Router mode: heuristic, trained, off", + }, + ] + + +# Convenience function for quick auto mode execution +async def auto_execute( + prompt: str, + agent: Optional[Any] = None, + budget_steps: int = 50, + budget_time: int = 300, + dry_run: bool = False, + verbose: bool = False, +) -> Dict[str, Any]: + """ + Quick auto mode execution. + + Args: + prompt: User prompt + agent: Agent instance + budget_steps: Max steps + budget_time: Max time in seconds + dry_run: Dry run mode + verbose: Verbose output + + Returns: + Execution result + """ + handler = AutoModeHandler(verbose=verbose) + handler.parse_args( + budget_steps=budget_steps, + budget_time=budget_time, + dry_run=dry_run, + ) + + return await handler.execute(prompt, agent=agent) diff --git a/src/praisonai/praisonai/cli/features/benchmark.py b/src/praisonai/praisonai/cli/features/benchmark.py index bee11badb..283e89c05 100644 --- a/src/praisonai/praisonai/cli/features/benchmark.py +++ b/src/praisonai/praisonai/cli/features/benchmark.py @@ -792,12 +792,12 @@ import sys sys.path.insert(0, "{self._get_project_root()}/src/praisonai") t0 = time.perf_counter() -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents t_import = time.perf_counter() agent = Agent(name="Helper", instructions="You are helpful", llm="{self.DEFAULT_MODEL}", verbose=False) task = Task(name="respond", description="{prompt}", expected_output="response", agent=agent) -agents = PraisonAIAgents(agents=[agent], tasks=[task], verbose=0) +agents = Agents(agents=[agent], tasks=[task], verbose=0) t_init = time.perf_counter() result = agents.start() @@ -838,14 +838,14 @@ import sys sys.path.insert(0, "{self._get_project_root()}/src/praisonai") t0 = time.perf_counter() -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents t_import = time.perf_counter() agent1 = Agent(name="Analyzer", instructions="Analyze the request", llm="{self.DEFAULT_MODEL}", verbose=False) agent2 = Agent(name="Responder", instructions="Provide a response", llm="{self.DEFAULT_MODEL}", verbose=False) task1 = Task(name="analyze", description="Analyze: {prompt}", expected_output="analysis", agent=agent1) task2 = Task(name="respond", description="Respond based on analysis", expected_output="response", agent=agent2) -agents = PraisonAIAgents(agents=[agent1, agent2], tasks=[task1, task2], verbose=0) +agents = Agents(agents=[agent1, agent2], tasks=[task1, task2], verbose=0) t_init = time.perf_counter() result = agents.start() diff --git a/src/praisonai/praisonai/cli/features/templates.py b/src/praisonai/praisonai/cli/features/templates.py index 205fb19d3..16163d9f1 100644 --- a/src/praisonai/praisonai/cli/features/templates.py +++ b/src/praisonai/praisonai/cli/features/templates.py @@ -591,8 +591,8 @@ class TemplatesHandler: # Run workflow - determine which class to use based on config structure if "agents" in workflow_config and "tasks" in workflow_config: - # PraisonAIAgents format (agents + tasks) - from praisonaiagents import Agent, Task, PraisonAIAgents + # Agents format (agents + tasks) + from praisonaiagents import Agent, Task, Agents # Build agents agents_config = workflow_config.get("agents", []) @@ -637,7 +637,7 @@ class TemplatesHandler: tasks.append(task) # Run - praison_agents = PraisonAIAgents( + praison_agents = Agents( agents=agents, tasks=tasks, process=workflow_config.get("process", "sequential"), diff --git a/src/praisonai/praisonai/cli/main.py b/src/praisonai/praisonai/cli/main.py index bb9b48e9b..7ee8aa09c 100644 --- a/src/praisonai/praisonai/cli/main.py +++ b/src/praisonai/praisonai/cli/main.py @@ -1513,7 +1513,7 @@ class PraisonAI: print("\npip install \"praisonai\\[crewai]\" # For CrewAI") print("pip install \"praisonai\\[autogen]\" # For AutoGen") print("pip install \"praisonai\\[crewai,autogen]\" # For both frameworks\n") - print("pip install praisonaiagents # For PraisonAIAgents\n") + print("pip install praisonaiagents # For Agents\n") sys.exit(1) # Handle direct prompt if command is not a special command or file @@ -4022,7 +4022,7 @@ Now, {final_instruction.lower()}:""" print("\npip install \"praisonai\\[crewai]\" # For CrewAI") print("pip install \"praisonai\\[autogen]\" # For AutoGen") print("pip install \"praisonai\\[crewai,autogen]\" # For both frameworks\n") - print("pip install praisonaiagents # For PraisonAIAgents\n") + print("pip install praisonaiagents # For Agents\n") sys.exit(1) def _handle_profiled_prompt(self, prompt): @@ -4315,7 +4315,7 @@ Now, {final_instruction.lower()}:""" praisonai agents.yaml --serve """ import yaml - from praisonaiagents import Agent, PraisonAIAgents + from praisonaiagents import Agent, Agents # Determine the YAML file path yaml_file = None @@ -4490,14 +4490,14 @@ Now, {final_instruction.lower()}:""" # Create and launch - with tasks if defined if tasks_list: - praison = PraisonAIAgents( + praison = Agents( agents=agents_list, tasks=tasks_list, process=process_type, verbose=1 if verbose else 0 ) else: - praison = PraisonAIAgents( + praison = Agents( agents=agents_list, process=process_type, verbose=1 if verbose else 0 @@ -4753,7 +4753,7 @@ Now, {final_instruction.lower()}:""" # If tools are provided, use Agent with tools first, then DeepResearchAgent if tools_list: - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents # Create a research assistant agent with tools research_assistant = Agent( @@ -4774,7 +4774,7 @@ Now, {final_instruction.lower()}:""" ) print("[cyan]Gathering information with tools...[/cyan]") - agents = PraisonAIAgents(agents=[research_assistant], tasks=[gather_task], verbose=0) + agents = Agents(agents=[research_assistant], tasks=[gather_task], verbose=0) tool_results = agents.start() # Enhance query with tool results diff --git a/src/praisonai/praisonai/deploy.py b/src/praisonai/praisonai/deploy.py index c10a55a51..b21c39184 100644 --- a/src/praisonai/praisonai/deploy.py +++ b/src/praisonai/praisonai/deploy.py @@ -57,7 +57,7 @@ class CloudDeployer: file.write("FROM python:3.11-slim\n") file.write("WORKDIR /app\n") file.write("COPY . .\n") - file.write("RUN pip install flask praisonai==3.4.0 gunicorn markdown\n") + file.write("RUN pip install flask praisonai==3.4.1 gunicorn markdown\n") file.write("EXPOSE 8080\n") file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n') diff --git a/src/praisonai/praisonai/recipe/core.py b/src/praisonai/praisonai/recipe/core.py index e077fa240..0c5185daa 100644 --- a/src/praisonai/praisonai/recipe/core.py +++ b/src/praisonai/praisonai/recipe/core.py @@ -804,7 +804,7 @@ def _execute_praisonai_workflow( options: Dict[str, Any], ) -> Any: """Execute a PraisonAI agents/tasks workflow.""" - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents from praisonai.templates.tool_override import resolve_tools agents = [] @@ -848,7 +848,7 @@ def _execute_praisonai_workflow( ) tasks.append(task) - praison = PraisonAIAgents( + praison = Agents( agents=agents, tasks=tasks, process=workflow_config.get("process", "sequential"), diff --git a/src/praisonai/praisonai/templates/loader.py b/src/praisonai/praisonai/templates/loader.py index beeca6e02..e7820a1f0 100644 --- a/src/praisonai/praisonai/templates/loader.py +++ b/src/praisonai/praisonai/templates/loader.py @@ -538,16 +538,16 @@ def create_agents_from_template( **agents_kwargs ): """ - Create a PraisonAIAgents team from a template. + Create a Agents team from a template. Args: uri: Template URI config: Optional config overrides offline: If True, only use cache - **agents_kwargs: Additional PraisonAIAgents constructor arguments + **agents_kwargs: Additional Agents constructor arguments Returns: - Configured PraisonAIAgents instance + Configured Agents instance """ loader = TemplateLoader(offline=offline) template = loader.load(uri, config=config, offline=offline) @@ -555,10 +555,10 @@ def create_agents_from_template( # Load workflow config (contains agents and tasks) workflow_config = loader.load_workflow_config(template) - # Import PraisonAIAgents lazily - from praisonaiagents import PraisonAIAgents + # Import Agents lazily + from praisonaiagents import Agents # Merge with kwargs final_config = {**workflow_config, **agents_kwargs} - return PraisonAIAgents(**final_config) + return Agents(**final_config) diff --git a/src/praisonai/praisonai/ui/agents.py b/src/praisonai/praisonai/ui/agents.py index 3b81a2acc..4cc3177b7 100644 --- a/src/praisonai/praisonai/ui/agents.py +++ b/src/praisonai/praisonai/ui/agents.py @@ -5,7 +5,7 @@ import yaml import logging import inspect import chainlit as cl -from praisonaiagents import Agent, Task, PraisonAIAgents, register_display_callback +from praisonaiagents import Agent, Task, Agents, register_display_callback framework = "praisonai" config_list = [ @@ -521,7 +521,7 @@ async def ui_run_praisonai(config, topic, tools_dict): # Decide how to process tasks if config.get('process') == 'hierarchical': - prai_agents = PraisonAIAgents( + prai_agents = Agents( agents=list(agents_map.values()), tasks=tasks, verbose=True, @@ -529,7 +529,7 @@ async def ui_run_praisonai(config, topic, tools_dict): manager_llm=config.get('manager_llm', 'gpt-5-nano') ) else: - prai_agents = PraisonAIAgents( + prai_agents = Agents( agents=list(agents_map.values()), tasks=tasks, verbose=2 diff --git a/src/praisonai/praisonai/ui/colab.py b/src/praisonai/praisonai/ui/colab.py index 3b1363f80..b0b01cb55 100644 --- a/src/praisonai/praisonai/ui/colab.py +++ b/src/praisonai/praisonai/ui/colab.py @@ -1,4 +1,4 @@ -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents import os import importlib import inspect @@ -421,7 +421,7 @@ async def ui_run_praisonai(config, topic, tools_dict): # Create and run the PraisonAI agents if config.get('process') == 'hierarchical': - crew = PraisonAIAgents( + crew = Agents( agents=list(agents.values()), tasks=tasks, verbose=True, @@ -429,7 +429,7 @@ async def ui_run_praisonai(config, topic, tools_dict): manager_llm=config.get('manager_llm', 'gpt-5-nano') ) else: - crew = PraisonAIAgents( + crew = Agents( agents=list(agents.values()), tasks=tasks, verbose=2 diff --git a/src/praisonai/praisonai/version.py b/src/praisonai/praisonai/version.py index 7f556eb0d..5d5369e50 100644 --- a/src/praisonai/praisonai/version.py +++ b/src/praisonai/praisonai/version.py @@ -1 +1 @@ -__version__ = "3.4.0" \ No newline at end of file +__version__ = "3.4.1" \ No newline at end of file diff --git a/src/praisonai/pyproject.toml b/src/praisonai/pyproject.toml index d3a002cf5..b54c883b7 100644 --- a/src/praisonai/pyproject.toml +++ b/src/praisonai/pyproject.toml @@ -12,7 +12,7 @@ dependencies = [ "rich>=13.7", "markdown>=3.5", "pyparsing>=3.0.0", - "praisonaiagents>=0.9.0", + "praisonaiagents>=0.9.1", "python-dotenv>=0.19.0", "instructor>=1.3.3", "PyYAML>=6.0", diff --git a/src/praisonai/tests/unit/cli/test_auto_mode.py b/src/praisonai/tests/unit/cli/test_auto_mode.py new file mode 100644 index 000000000..75044a569 --- /dev/null +++ b/src/praisonai/tests/unit/cli/test_auto_mode.py @@ -0,0 +1,319 @@ +""" +Tests for Auto Mode Handler. + +TDD tests for CLI auto mode integration with escalation pipeline. +""" + +import pytest +from unittest.mock import Mock +import sys +import os + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) + +from praisonai.cli.features.auto_mode import ( + AutoModeHandler, + AutoModeConfig, + AutoModeState, + AutoModeLevel, + RouterMode, + auto_execute, +) + + +class TestAutoModeLevel: + """Tests for AutoModeLevel enum.""" + + def test_mode_values(self): + """Test mode enum values.""" + assert AutoModeLevel.OFF.value == "off" + assert AutoModeLevel.SUGGEST.value == "suggest" + assert AutoModeLevel.AUTO.value == "auto" + assert AutoModeLevel.FULL_AUTO.value == "full_auto" + + +class TestRouterMode: + """Tests for RouterMode enum.""" + + def test_router_mode_values(self): + """Test router mode values.""" + assert RouterMode.HEURISTIC.value == "heuristic" + assert RouterMode.TRAINED.value == "trained" + assert RouterMode.OFF.value == "off" + + +class TestAutoModeConfig: + """Tests for AutoModeConfig.""" + + def test_default_config(self): + """Test default configuration.""" + config = AutoModeConfig() + + assert config.mode == AutoModeLevel.AUTO + assert config.dry_run is False + assert config.budget_steps == 50 + assert config.budget_time_seconds == 300 + assert config.budget_tokens == 100000 + assert config.enable_checkpoints is True + assert config.router_mode == RouterMode.HEURISTIC + + def test_from_cli_args_basic(self): + """Test config from basic CLI args.""" + config = AutoModeConfig.from_cli_args( + budget_steps=20, + budget_time=60, + ) + + assert config.budget_steps == 20 + assert config.budget_time_seconds == 60 + + def test_from_cli_args_dry_run(self): + """Test config with dry run.""" + config = AutoModeConfig.from_cli_args(dry_run=True) + assert config.dry_run is True + + config = AutoModeConfig.from_cli_args(apply=True) + assert config.dry_run is False + + def test_from_cli_args_mode(self): + """Test config with different modes.""" + config = AutoModeConfig.from_cli_args(auto=False) + assert config.mode == AutoModeLevel.OFF + + config = AutoModeConfig.from_cli_args(full_auto=True) + assert config.mode == AutoModeLevel.FULL_AUTO + + config = AutoModeConfig.from_cli_args(suggest=True) + assert config.mode == AutoModeLevel.SUGGEST + + def test_from_cli_args_tools(self): + """Test config with tool filters.""" + config = AutoModeConfig.from_cli_args( + allow_tools="read_file,grep", + deny_tools="write_file,bash", + ) + + assert "read_file" in config.allow_tools + assert "grep" in config.allow_tools + assert "write_file" in config.deny_tools + assert "bash" in config.deny_tools + + def test_from_cli_args_checkpoint(self): + """Test config with checkpoint settings.""" + config = AutoModeConfig.from_cli_args(checkpoint=False) + assert config.enable_checkpoints is False + + config = AutoModeConfig.from_cli_args(no_checkpoint=True) + assert config.enable_checkpoints is False + + def test_from_cli_args_router(self): + """Test config with router mode.""" + config = AutoModeConfig.from_cli_args(router="off") + assert config.router_mode == RouterMode.OFF + + config = AutoModeConfig.from_cli_args(router="trained") + assert config.router_mode == RouterMode.TRAINED + + +class TestAutoModeState: + """Tests for AutoModeState.""" + + def test_initial_state(self): + """Test initial state values.""" + state = AutoModeState() + + assert state.current_stage == 0 + assert state.steps_taken == 0 + assert state.tokens_used == 0 + assert state.tool_calls == 0 + assert len(state.errors) == 0 + + def test_is_within_budget(self): + """Test budget checking.""" + config = AutoModeConfig( + budget_steps=10, + budget_time_seconds=60, + budget_tokens=1000, + ) + state = AutoModeState() + + # Initially within budget + assert state.is_within_budget(config) + + # Exceed steps + state.steps_taken = 15 + assert not state.is_within_budget(config) + + # Reset and exceed time + state.steps_taken = 5 + state.time_elapsed = 120 + assert not state.is_within_budget(config) + + def test_get_budget_status(self): + """Test budget status reporting.""" + config = AutoModeConfig( + budget_steps=100, + budget_time_seconds=300, + ) + state = AutoModeState( + steps_taken=50, + time_elapsed=150, + ) + + status = state.get_budget_status(config) + + assert status["steps"]["used"] == 50 + assert status["steps"]["limit"] == 100 + assert status["steps"]["percent"] == 50.0 + + assert status["time"]["used"] == 150 + assert status["time"]["percent"] == 50.0 + + +class TestAutoModeHandler: + """Tests for AutoModeHandler.""" + + def test_handler_creation(self): + """Test handler creation.""" + handler = AutoModeHandler() + + assert handler.feature_name == "auto_mode" + assert handler.get_config() is None + assert handler.get_state() is None + + def test_parse_args(self): + """Test argument parsing.""" + handler = AutoModeHandler() + + config = handler.parse_args( + budget_steps=30, + dry_run=True, + ) + + assert config.budget_steps == 30 + assert config.dry_run is True + assert handler.get_config() is config + assert handler.get_state() is not None + + def test_filter_tools_allow_list(self): + """Test tool filtering with allow list.""" + handler = AutoModeHandler() + handler.parse_args(allow_tools="read_file,grep") + + mock_tools = [ + Mock(__name__="read_file"), + Mock(__name__="write_file"), + Mock(__name__="grep"), + Mock(__name__="bash"), + ] + + filtered = handler._filter_tools(mock_tools) + + names = [t.__name__ for t in filtered] + assert "read_file" in names + assert "grep" in names + assert "write_file" not in names + assert "bash" not in names + + def test_filter_tools_deny_list(self): + """Test tool filtering with deny list.""" + handler = AutoModeHandler() + handler.parse_args(deny_tools="bash,write_file") + + mock_tools = [ + Mock(__name__="read_file"), + Mock(__name__="write_file"), + Mock(__name__="grep"), + Mock(__name__="bash"), + ] + + filtered = handler._filter_tools(mock_tools) + + names = [t.__name__ for t in filtered] + assert "read_file" in names + assert "grep" in names + assert "write_file" not in names + assert "bash" not in names + + def test_get_cli_options(self): + """Test CLI option definitions.""" + handler = AutoModeHandler() + + options = handler.get_cli_options() + + assert len(options) > 0 + option_names = [o["name"] for o in options] + assert "--auto/--no-auto" in option_names + assert "--dry-run" in option_names + assert "--budget-steps" in option_names + + @pytest.mark.asyncio + async def test_execute_without_agent(self): + """Test execution without agent.""" + handler = AutoModeHandler() + handler.parse_args() + + result = await handler.execute("Test prompt") + + # Should fail gracefully without agent + assert "success" in result + + @pytest.mark.asyncio + async def test_execute_with_mock_agent(self): + """Test execution with mock agent.""" + handler = AutoModeHandler() + handler.parse_args() + + mock_agent = Mock() + mock_agent.chat = Mock(return_value="Hello!") + + result = await handler.execute("Test prompt", agent=mock_agent) + + assert result["success"] + assert "Hello" in result["response"] + + def test_stage_change_callback(self): + """Test stage change callback.""" + callback_calls = [] + + def on_change(old, new): + callback_calls.append((old, new)) + + handler = AutoModeHandler(on_stage_change=on_change) + + # Simulate stage change + class MockStage: + def __init__(self, val, name): + self.value = val + self.name = name + + handler._state = AutoModeState() + handler._handle_stage_change( + MockStage(0, "DIRECT"), + MockStage(1, "HEURISTIC") + ) + + assert len(callback_calls) == 1 + assert callback_calls[0] == (0, 1) + + +class TestAutoExecuteFunction: + """Tests for auto_execute convenience function.""" + + @pytest.mark.asyncio + async def test_auto_execute_basic(self): + """Test basic auto_execute call.""" + mock_agent = Mock() + mock_agent.chat = Mock(return_value="Done") + + result = await auto_execute( + "Test prompt", + agent=mock_agent, + budget_steps=10, + ) + + assert "success" in result + + +if __name__ == "__main__": + pytest.main([__file__, "-v"]) diff --git a/src/praisonai/tests/unit/escalation/__init__.py b/src/praisonai/tests/unit/escalation/__init__.py new file mode 100644 index 000000000..4e086f176 --- /dev/null +++ b/src/praisonai/tests/unit/escalation/__init__.py @@ -0,0 +1 @@ +"""Tests for escalation module.""" diff --git a/src/praisonai/tests/unit/escalation/test_escalation_pipeline.py b/src/praisonai/tests/unit/escalation/test_escalation_pipeline.py new file mode 100644 index 000000000..72fa6185d --- /dev/null +++ b/src/praisonai/tests/unit/escalation/test_escalation_pipeline.py @@ -0,0 +1,531 @@ +""" +Tests for Escalation Pipeline. + +TDD tests for progressive escalation from direct response to autonomous mode. +""" + +import pytest +from unittest.mock import Mock, AsyncMock, patch +import sys +import os + +# Add the praisonai-agents path +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'praisonai-agents')) + +from praisonaiagents.escalation.types import ( + EscalationStage, + EscalationConfig, + EscalationResult, + EscalationSignal, + StageContext, +) +from praisonaiagents.escalation.triggers import EscalationTrigger +from praisonaiagents.escalation.doom_loop import ( + DoomLoopDetector, + DoomLoopConfig, + DoomLoopType, + RecoveryAction, +) +from praisonaiagents.escalation.pipeline import EscalationPipeline + + +class TestEscalationStage: + """Tests for EscalationStage enum.""" + + def test_stage_ordering(self): + """Test that stages are ordered correctly.""" + assert EscalationStage.DIRECT < EscalationStage.HEURISTIC + assert EscalationStage.HEURISTIC < EscalationStage.PLANNED + assert EscalationStage.PLANNED < EscalationStage.AUTONOMOUS + + def test_stage_values(self): + """Test stage integer values.""" + assert EscalationStage.DIRECT == 0 + assert EscalationStage.HEURISTIC == 1 + assert EscalationStage.PLANNED == 2 + assert EscalationStage.AUTONOMOUS == 3 + + +class TestEscalationConfig: + """Tests for EscalationConfig.""" + + def test_default_config(self): + """Test default configuration values.""" + config = EscalationConfig() + + assert config.long_prompt_threshold == 100 + assert config.complex_keyword_threshold == 2 + assert config.max_steps == 20 + assert config.max_time_seconds == 300 + assert config.auto_escalate is True + assert config.auto_deescalate is True + + def test_custom_config(self): + """Test custom configuration.""" + config = EscalationConfig( + long_prompt_threshold=50, + max_steps=10, + auto_escalate=False, + ) + + assert config.long_prompt_threshold == 50 + assert config.max_steps == 10 + assert config.auto_escalate is False + + +class TestEscalationTrigger: + """Tests for EscalationTrigger signal detection.""" + + def test_simple_question_detection(self): + """Test detection of simple questions.""" + trigger = EscalationTrigger() + + signals = trigger.analyze("What is Python?") + assert EscalationSignal.SIMPLE_QUESTION in signals + + signals = trigger.analyze("Define machine learning") + assert EscalationSignal.SIMPLE_QUESTION in signals + + def test_complex_keywords_detection(self): + """Test detection of complex task keywords.""" + trigger = EscalationTrigger() + + signals = trigger.analyze("Analyze and refactor the authentication module") + assert EscalationSignal.COMPLEX_KEYWORDS in signals + + signals = trigger.analyze("Debug and optimize the database queries") + assert EscalationSignal.COMPLEX_KEYWORDS in signals + + def test_long_prompt_detection(self): + """Test detection of long prompts.""" + trigger = EscalationTrigger() + + # Short prompt + signals = trigger.analyze("Hello world") + assert EscalationSignal.LONG_PROMPT not in signals + + # Long prompt (>100 words) + long_prompt = " ".join(["word"] * 150) + signals = trigger.analyze(long_prompt) + assert EscalationSignal.LONG_PROMPT in signals + + def test_file_references_detection(self): + """Test detection of file references.""" + trigger = EscalationTrigger() + + signals = trigger.analyze("Read the file src/main.py") + assert EscalationSignal.FILE_REFERENCES in signals + + signals = trigger.analyze("Check config.yaml for settings") + assert EscalationSignal.FILE_REFERENCES in signals + + def test_edit_intent_detection(self): + """Test detection of edit intent.""" + trigger = EscalationTrigger() + + signals = trigger.analyze("Edit the config file") + assert EscalationSignal.EDIT_INTENT in signals + + signals = trigger.analyze("Modify the user model") + assert EscalationSignal.EDIT_INTENT in signals + + signals = trigger.analyze("Fix the bug in auth.py") + assert EscalationSignal.EDIT_INTENT in signals + + def test_multi_step_intent_detection(self): + """Test detection of multi-step tasks.""" + trigger = EscalationTrigger() + + signals = trigger.analyze("First, read the file. Then, update it. Finally, test it.") + assert EscalationSignal.MULTI_STEP_INTENT in signals + + signals = trigger.analyze("What is this? How does it work? Why is it needed?") + assert EscalationSignal.MULTI_STEP_INTENT in signals + + def test_code_blocks_detection(self): + """Test detection of code blocks.""" + trigger = EscalationTrigger() + + signals = trigger.analyze("Fix this code: ```python\nprint('hello')\n```") + assert EscalationSignal.CODE_BLOCKS in signals + + signals = trigger.analyze("The function `main()` is broken") + assert EscalationSignal.CODE_BLOCKS in signals + + def test_repo_context_detection(self): + """Test detection of repo context.""" + trigger = EscalationTrigger() + + signals = trigger.analyze("Hello", context={"is_git_repo": True}) + assert EscalationSignal.REPO_CONTEXT in signals + + signals = trigger.analyze("Hello", context={"workspace": "/path/to/project"}) + assert EscalationSignal.REPO_CONTEXT in signals + + +class TestEscalationTriggerStageRecommendation: + """Tests for stage recommendation based on signals.""" + + def test_direct_stage_for_simple_question(self): + """Test DIRECT stage for simple questions.""" + trigger = EscalationTrigger() + + signals = trigger.analyze("What is Python?") + stage = trigger.recommend_stage(signals) + assert stage == EscalationStage.DIRECT + + def test_heuristic_stage_for_file_references(self): + """Test HEURISTIC stage for file references.""" + trigger = EscalationTrigger() + + signals = {EscalationSignal.FILE_REFERENCES} + stage = trigger.recommend_stage(signals) + assert stage == EscalationStage.HEURISTIC + + def test_planned_stage_for_edit_intent(self): + """Test PLANNED stage for edit intent.""" + trigger = EscalationTrigger() + + signals = {EscalationSignal.EDIT_INTENT} + stage = trigger.recommend_stage(signals) + assert stage == EscalationStage.PLANNED + + def test_autonomous_stage_for_multi_step(self): + """Test AUTONOMOUS stage for multi-step tasks.""" + trigger = EscalationTrigger() + + signals = {EscalationSignal.MULTI_STEP_INTENT} + stage = trigger.recommend_stage(signals) + assert stage == EscalationStage.AUTONOMOUS + + def test_autonomous_stage_for_refactor(self): + """Test AUTONOMOUS stage for refactoring.""" + trigger = EscalationTrigger() + + signals = {EscalationSignal.REFACTOR_INTENT} + stage = trigger.recommend_stage(signals) + assert stage == EscalationStage.AUTONOMOUS + + def test_escalation_on_failure(self): + """Test escalation when failure signal is present.""" + trigger = EscalationTrigger() + + signals = {EscalationSignal.TOOL_FAILURE} + stage = trigger.recommend_stage(signals, current_stage=EscalationStage.HEURISTIC) + assert stage > EscalationStage.HEURISTIC + + +class TestDoomLoopDetector: + """Tests for DoomLoopDetector.""" + + def test_no_loop_initially(self): + """Test no loop detected initially.""" + detector = DoomLoopDetector() + detector.start_session() + + assert not detector.is_doom_loop() + + def test_repeated_identical_actions(self): + """Test detection of repeated identical actions.""" + config = DoomLoopConfig(max_identical_actions=3) + detector = DoomLoopDetector(config) + detector.start_session() + + # Record same action 3 times + for _ in range(3): + detector.record_action( + action_type="read_file", + args={"path": "foo.py"}, + result="content", + success=True, + ) + + assert detector.is_doom_loop() + assert detector.get_loop_type() == DoomLoopType.REPEATED_ACTION + + def test_consecutive_failures(self): + """Test detection of consecutive failures.""" + config = DoomLoopConfig(max_consecutive_failures=3) + detector = DoomLoopDetector(config) + detector.start_session() + + # Record 3 failures + for i in range(3): + detector.record_action( + action_type=f"action_{i}", + args={}, + result=None, + success=False, + ) + + assert detector.is_doom_loop() + assert detector.get_loop_type() == DoomLoopType.REPEATED_FAILURE + + def test_no_loop_with_varied_actions(self): + """Test no loop with varied actions.""" + detector = DoomLoopDetector() + detector.start_session() + + # Record different actions + detector.record_action("read_file", {"path": "a.py"}, "content_a", True) + detector.record_action("write_file", {"path": "b.py"}, "ok", True) + detector.record_action("run_command", {"cmd": "test"}, "passed", True) + + assert not detector.is_doom_loop() + + def test_progress_markers_prevent_no_progress_detection(self): + """Test that progress markers prevent no-progress detection.""" + config = DoomLoopConfig(max_no_progress_steps=3) + detector = DoomLoopDetector(config) + detector.start_session() + + # Record actions with same result + for i in range(5): + detector.record_action("action", {}, "same_result", True) + if i == 2: + detector.mark_progress("made_progress") + + # Should not detect no-progress because we marked progress + loop_type = detector.get_loop_type() + assert loop_type != DoomLoopType.NO_PROGRESS or not detector.is_doom_loop() + + def test_recovery_action_progression(self): + """Test recovery action progression.""" + detector = DoomLoopDetector() + detector.start_session() + + # First recovery: retry different + detector._recovery_attempts = 0 + action = detector._determine_recovery_action(DoomLoopType.REPEATED_ACTION) + assert action == RecoveryAction.RETRY_DIFFERENT + + # Second recovery: escalate model + detector._recovery_attempts = 1 + action = detector._determine_recovery_action(DoomLoopType.REPEATED_ACTION) + assert action == RecoveryAction.ESCALATE_MODEL + + # Max reached: abort + detector._recovery_attempts = 2 + action = detector._determine_recovery_action(DoomLoopType.REPEATED_ACTION) + assert action == RecoveryAction.ABORT + + def test_backoff_increases(self): + """Test that backoff increases on each call.""" + config = DoomLoopConfig(initial_backoff=0.01, backoff_multiplier=2.0, max_backoff=1.0) + detector = DoomLoopDetector(config) + + initial = detector._current_backoff + detector.apply_backoff() + assert detector._current_backoff > initial + + def test_stats_tracking(self): + """Test statistics tracking.""" + detector = DoomLoopDetector() + detector.start_session() + + detector.record_action("a", {}, "r", True) + detector.record_action("b", {}, "r", False) + detector.mark_progress("p1") + + stats = detector.get_stats() + assert stats["total_actions"] == 2 + assert stats["successful_actions"] == 1 + assert stats["failed_actions"] == 1 + assert stats["progress_markers"] == 1 + + +class TestStageContext: + """Tests for StageContext.""" + + def test_add_step(self): + """Test adding steps to context.""" + context = StageContext( + stage=EscalationStage.HEURISTIC, + prompt="test", + ) + + context.add_step("read_file", "content", success=True) + + assert len(context.steps) == 1 + assert context.steps[0]["action"] == "read_file" + assert context.steps[0]["success"] is True + + def test_add_tool_result(self): + """Test adding tool results.""" + context = StageContext( + stage=EscalationStage.HEURISTIC, + prompt="test", + ) + + context.add_tool_result("read_file", {"path": "a.py"}, "content", True) + + assert len(context.tool_results) == 1 + assert context.tool_calls == 1 + + def test_should_escalate_on_failures(self): + """Test escalation recommendation on failures.""" + config = EscalationConfig() + context = StageContext( + stage=EscalationStage.HEURISTIC, + prompt="test", + ) + + # Add failures + context.add_step("a", "fail", success=False) + context.add_step("b", "fail", success=False) + + assert context.should_escalate(config) + + def test_should_deescalate_on_simple(self): + """Test de-escalation for simple questions.""" + config = EscalationConfig() + context = StageContext( + stage=EscalationStage.PLANNED, + prompt="test", + signals={EscalationSignal.SIMPLE_QUESTION}, + ) + + assert context.should_deescalate(config) + + +class TestEscalationPipeline: + """Tests for EscalationPipeline.""" + + def test_analyze_simple_prompt(self): + """Test analysis of simple prompt.""" + pipeline = EscalationPipeline() + + stage = pipeline.analyze("What is Python?") + assert stage == EscalationStage.DIRECT + + def test_analyze_complex_prompt(self): + """Test analysis of complex prompt.""" + pipeline = EscalationPipeline() + + stage = pipeline.analyze("Refactor the authentication module and add tests") + assert stage >= EscalationStage.PLANNED + + @pytest.mark.asyncio + async def test_execute_direct_stage(self): + """Test execution at DIRECT stage.""" + mock_agent = Mock() + mock_agent.chat = Mock(return_value="Hello!") + + pipeline = EscalationPipeline(agent=mock_agent) + + result = await pipeline.execute_at_stage( + "Hello", + EscalationStage.DIRECT, + ) + + assert result.success + assert result.initial_stage == EscalationStage.DIRECT + assert "Hello" in result.response + + @pytest.mark.asyncio + async def test_execute_with_escalation(self): + """Test execution with automatic escalation.""" + mock_agent = Mock() + # First call fails, second succeeds + mock_agent.chat = Mock(side_effect=[Exception("fail"), "Success!"]) + + config = EscalationConfig(auto_escalate=True) + pipeline = EscalationPipeline(config=config, agent=mock_agent) + + result = await pipeline.execute_at_stage( + "Do something", + EscalationStage.DIRECT, + ) + + # Should have escalated + assert result.escalations >= 0 # May or may not escalate depending on error handling + + @pytest.mark.asyncio + async def test_execute_respects_time_budget(self): + """Test that execution respects time budget.""" + mock_agent = Mock() + mock_agent.chat = Mock(return_value="ok") + + config = EscalationConfig(max_time_seconds=1) + pipeline = EscalationPipeline(config=config, agent=mock_agent) + + result = await pipeline.execute_at_stage( + "Quick task", + EscalationStage.DIRECT, + ) + + assert result.time_seconds < 2 # Should complete quickly + + @pytest.mark.asyncio + async def test_stage_change_callback(self): + """Test stage change callback is called.""" + mock_agent = Mock() + mock_agent.chat = Mock(side_effect=[Exception("fail"), "ok"]) + + callback_called = [] + def on_change(old, new): + callback_called.append((old, new)) + + config = EscalationConfig(auto_escalate=True) + pipeline = EscalationPipeline( + config=config, + agent=mock_agent, + on_stage_change=on_change, + ) + + await pipeline.execute_at_stage( + "Task", + EscalationStage.DIRECT, + ) + + # Callback may or may not be called depending on escalation + # Just verify it doesn't crash + + def test_get_current_stage(self): + """Test getting current stage.""" + pipeline = EscalationPipeline() + + # Initially None + assert pipeline.get_current_stage() is None + + +class TestEscalationResult: + """Tests for EscalationResult.""" + + def test_was_escalated(self): + """Test was_escalated property.""" + result = EscalationResult( + response="ok", + success=True, + initial_stage=EscalationStage.DIRECT, + final_stage=EscalationStage.PLANNED, + ) + + assert result.was_escalated + + def test_was_deescalated(self): + """Test was_deescalated property.""" + result = EscalationResult( + response="ok", + success=True, + initial_stage=EscalationStage.AUTONOMOUS, + final_stage=EscalationStage.HEURISTIC, + ) + + assert result.was_deescalated + + def test_no_escalation(self): + """Test no escalation case.""" + result = EscalationResult( + response="ok", + success=True, + initial_stage=EscalationStage.DIRECT, + final_stage=EscalationStage.DIRECT, + ) + + assert not result.was_escalated + assert not result.was_deescalated + + +if __name__ == "__main__": + pytest.main([__file__, "-v"]) diff --git a/src/praisonai/tests/unit/escalation/test_subagent_delegator.py b/src/praisonai/tests/unit/escalation/test_subagent_delegator.py new file mode 100644 index 000000000..05a2d51ec --- /dev/null +++ b/src/praisonai/tests/unit/escalation/test_subagent_delegator.py @@ -0,0 +1,390 @@ +""" +Tests for Subagent Delegator. + +TDD tests for subagent delegation framework. +""" + +import pytest +from unittest.mock import Mock, AsyncMock +import sys +import os + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'praisonai-agents')) + +from praisonaiagents.agents.delegator import ( + SubagentDelegator, + DelegationConfig, + DelegationTask, + DelegationResult, + DelegationStatus, + delegate_to_agent, +) +from praisonaiagents.agents.profiles import ( + AgentProfile, + AgentMode, + get_profile, + list_profiles, +) + + +class TestDelegationConfig: + """Tests for DelegationConfig.""" + + def test_default_config(self): + """Test default configuration values.""" + config = DelegationConfig() + + assert config.max_concurrent_subagents == 3 + assert config.max_total_subagents == 10 + assert config.default_timeout_seconds == 300.0 + assert config.inherit_permissions is True + + def test_custom_config(self): + """Test custom configuration.""" + config = DelegationConfig( + max_concurrent_subagents=5, + max_total_subagents=20, + default_timeout_seconds=600.0, + ) + + assert config.max_concurrent_subagents == 5 + assert config.max_total_subagents == 20 + assert config.default_timeout_seconds == 600.0 + + +class TestDelegationTask: + """Tests for DelegationTask.""" + + def test_task_creation(self): + """Test task creation with defaults.""" + task = DelegationTask( + task_id="test_1", + agent_name="explorer", + objective="Find files", + ) + + assert task.task_id == "test_1" + assert task.agent_name == "explorer" + assert task.status == DelegationStatus.PENDING + assert task.result is None + + def test_task_with_context(self): + """Test task with context.""" + task = DelegationTask( + task_id="test_2", + agent_name="explorer", + objective="Find auth files", + context={"workspace": "/path/to/project"}, + ) + + assert task.context["workspace"] == "/path/to/project" + + +class TestDelegationResult: + """Tests for DelegationResult.""" + + def test_successful_result(self): + """Test successful result.""" + result = DelegationResult( + task_id="test_1", + agent_name="explorer", + success=True, + result="Found 5 files", + ) + + assert result.success + assert result.result == "Found 5 files" + assert result.error is None + + def test_failed_result(self): + """Test failed result.""" + result = DelegationResult( + task_id="test_1", + agent_name="explorer", + success=False, + error="Agent not found", + ) + + assert not result.success + assert result.error == "Agent not found" + + +class TestAgentProfiles: + """Tests for agent profiles.""" + + def test_explorer_profile_exists(self): + """Test explorer profile exists.""" + profile = get_profile("explorer") + + assert profile is not None + assert profile.name == "explorer" + assert profile.mode == AgentMode.SUBAGENT + + def test_explorer_is_read_only(self): + """Test explorer profile is read-only.""" + profile = get_profile("explorer") + + assert profile is not None + assert profile.metadata.get("read_only") is True + assert "write_file" in profile.metadata.get("blocked_tools", []) + + def test_list_profiles(self): + """Test listing profiles.""" + profiles = list_profiles() + + assert len(profiles) > 0 + names = [p.name for p in profiles] + assert "explorer" in names + assert "general" in names + + def test_profile_to_dict(self): + """Test profile serialization.""" + profile = get_profile("explorer") + + data = profile.to_dict() + assert data["name"] == "explorer" + assert data["mode"] == "subagent" + assert "tools" in data + + +class TestSubagentDelegator: + """Tests for SubagentDelegator.""" + + def test_delegator_creation(self): + """Test delegator creation.""" + delegator = SubagentDelegator() + + assert delegator.config is not None + assert delegator._running_count == 0 + assert delegator._total_count == 0 + + def test_get_available_agents(self): + """Test getting available agents.""" + delegator = SubagentDelegator() + + agents = delegator.get_available_agents() + assert "explorer" in agents + # Hidden agents should not be included + assert "compaction" not in agents + + def test_get_agent_description(self): + """Test getting agent description.""" + delegator = SubagentDelegator() + + desc = delegator.get_agent_description("explorer") + assert "read-only" in desc.lower() or "codebase" in desc.lower() + + def test_generate_task_id(self): + """Test task ID generation.""" + delegator = SubagentDelegator() + + id1 = delegator._generate_task_id() + id2 = delegator._generate_task_id() + + assert id1 != id2 + assert id1.startswith("task_") + + def test_get_stats(self): + """Test getting statistics.""" + delegator = SubagentDelegator() + + stats = delegator.get_stats() + assert stats["total_tasks"] == 0 + assert stats["running_tasks"] == 0 + assert "max_concurrent" in stats + + @pytest.mark.asyncio + async def test_delegate_unknown_agent(self): + """Test delegation to unknown agent fails gracefully.""" + delegator = SubagentDelegator() + + result = await delegator.delegate( + agent_name="nonexistent_agent", + objective="Do something", + ) + + assert not result.success + assert "Unknown agent" in result.error or result.error is not None + + @pytest.mark.asyncio + async def test_delegate_with_mock_factory(self): + """Test delegation with mock agent factory.""" + mock_agent = Mock() + mock_agent.chat = Mock(return_value="Task completed") + + def factory(name): + return mock_agent + + delegator = SubagentDelegator(agent_factory=factory) + + result = await delegator.delegate( + agent_name="explorer", + objective="Find files", + ) + + assert result.success + assert result.result == "Task completed" + + @pytest.mark.asyncio + async def test_delegate_respects_max_total(self): + """Test delegation respects max total limit.""" + config = DelegationConfig(max_total_subagents=1) + delegator = SubagentDelegator(config=config) + delegator._total_count = 1 # Simulate already at limit + + result = await delegator.delegate( + agent_name="explorer", + objective="Find files", + ) + + assert not result.success + assert "Max total" in result.error + + @pytest.mark.asyncio + async def test_task_complete_callback(self): + """Test task complete callback is called.""" + callback_results = [] + + def on_complete(result): + callback_results.append(result) + + mock_agent = Mock() + mock_agent.chat = Mock(return_value="Done") + + delegator = SubagentDelegator( + agent_factory=lambda n: mock_agent, + on_task_complete=on_complete, + ) + + await delegator.delegate("explorer", "Find files") + + assert len(callback_results) == 1 + assert callback_results[0].success + + @pytest.mark.asyncio + async def test_cancel_task(self): + """Test task cancellation.""" + delegator = SubagentDelegator() + + # Create a task manually + task = DelegationTask( + task_id="test_cancel", + agent_name="explorer", + objective="Long task", + status=DelegationStatus.RUNNING, + ) + delegator._tasks["test_cancel"] = task + + result = await delegator.cancel_task("test_cancel") + + assert result is True + assert task.status == DelegationStatus.CANCELLED + + @pytest.mark.asyncio + async def test_cancel_nonexistent_task(self): + """Test cancelling nonexistent task.""" + delegator = SubagentDelegator() + + result = await delegator.cancel_task("nonexistent") + + assert result is False + + def test_get_running_tasks(self): + """Test getting running tasks.""" + delegator = SubagentDelegator() + + # Add some tasks + delegator._tasks["t1"] = DelegationTask( + task_id="t1", + agent_name="explorer", + objective="Task 1", + status=DelegationStatus.RUNNING, + ) + delegator._tasks["t2"] = DelegationTask( + task_id="t2", + agent_name="explorer", + objective="Task 2", + status=DelegationStatus.COMPLETED, + ) + + running = delegator.get_running_tasks() + + assert len(running) == 1 + assert running[0].task_id == "t1" + + def test_get_task_status(self): + """Test getting task status.""" + delegator = SubagentDelegator() + + delegator._tasks["t1"] = DelegationTask( + task_id="t1", + agent_name="explorer", + objective="Task 1", + status=DelegationStatus.COMPLETED, + ) + + status = delegator.get_task_status("t1") + assert status == DelegationStatus.COMPLETED + + status = delegator.get_task_status("nonexistent") + assert status is None + + +class TestDelegateParallel: + """Tests for parallel delegation.""" + + @pytest.mark.asyncio + async def test_delegate_parallel_basic(self): + """Test basic parallel delegation.""" + mock_agent = Mock() + mock_agent.chat = Mock(return_value="Done") + + delegator = SubagentDelegator( + agent_factory=lambda n: mock_agent, + ) + + results = await delegator.delegate_parallel([ + ("explorer", "Task 1"), + ("explorer", "Task 2"), + ]) + + assert len(results) == 2 + assert all(r.success for r in results) + + @pytest.mark.asyncio + async def test_delegate_parallel_with_context(self): + """Test parallel delegation with context.""" + mock_agent = Mock() + mock_agent.chat = Mock(return_value="Done") + + delegator = SubagentDelegator( + agent_factory=lambda n: mock_agent, + ) + + results = await delegator.delegate_parallel([ + ("explorer", "Task 1", {"key": "value1"}), + ("explorer", "Task 2", {"key": "value2"}), + ]) + + assert len(results) == 2 + + +class TestDelegateToAgentFunction: + """Tests for convenience function.""" + + @pytest.mark.asyncio + async def test_delegate_to_agent_basic(self): + """Test delegate_to_agent convenience function.""" + # This will fail without a real agent, but tests the interface + result = await delegate_to_agent( + agent_name="nonexistent", + objective="Test", + timeout_seconds=1.0, + ) + + # Should return a result (even if failed) + assert isinstance(result, DelegationResult) + + +if __name__ == "__main__": + pytest.main([__file__, "-v"]) diff --git a/src/praisonai/tests/unit/test_async_agents.py b/src/praisonai/tests/unit/test_async_agents.py index 918a19217..42ce53c33 100644 --- a/src/praisonai/tests/unit/test_async_agents.py +++ b/src/praisonai/tests/unit/test_async_agents.py @@ -8,7 +8,7 @@ from unittest.mock import Mock, patch, AsyncMock sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'src', 'praisonai-agents')) try: - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents except ImportError as e: pytest.skip(f"Could not import required modules: {e}", allow_module_level=True) @@ -80,7 +80,7 @@ class TestAsyncAgents: **sample_task_config ) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" @@ -112,7 +112,7 @@ class TestAsyncAgents: **{k: v for k, v in sample_task_config.items() if k != 'name'} ) - agents = PraisonAIAgents( + agents = Agents( agents=[sync_agent, async_agent], tasks=[sync_task, async_task], process="sequential" @@ -147,7 +147,7 @@ class TestAsyncAgents: async_execution=True ) - agents = PraisonAIAgents( + agents = Agents( agents=[agent1, agent2], tasks=[task1, task2], process="workflow" diff --git a/src/praisonai/tests/unit/test_async_gemini_fix.py b/src/praisonai/tests/unit/test_async_gemini_fix.py index 7f118bd34..284cfe38e 100644 --- a/src/praisonai/tests/unit/test_async_gemini_fix.py +++ b/src/praisonai/tests/unit/test_async_gemini_fix.py @@ -4,7 +4,7 @@ after the fix for issue #818 """ import asyncio import logging -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Enable logging to see tool calls logging.basicConfig(level=logging.INFO) @@ -73,7 +73,7 @@ async def test_async_gemini_tools(): ) # Create workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[search_agent, analysis_agent], tasks=[search_task, analysis_task], verbose=True @@ -129,7 +129,7 @@ async def test_multiple_async_agents(): tasks.append(task) # Execute all in parallel - workflow = PraisonAIAgents(agents=agents, tasks=tasks) + workflow = Agents(agents=agents, tasks=tasks) print("\nšŸš€ Testing multiple async agents in parallel...") results = await workflow.astart() diff --git a/src/praisonai/tests/unit/test_autoagents.py b/src/praisonai/tests/unit/test_autoagents.py index 6ee02a4f6..80e04e3f8 100644 --- a/src/praisonai/tests/unit/test_autoagents.py +++ b/src/praisonai/tests/unit/test_autoagents.py @@ -234,7 +234,7 @@ class TestAutoAgents: with patch.object(AutoAgents, '_create_agents_and_tasks') as mock_create, \ patch.object(AutoAgents, '_display_agents_and_tasks') as mock_display, \ - patch('praisonaiagents.agents.agents.PraisonAIAgents.__init__') as mock_super_init: + patch('praisonaiagents.agents.agents.Agents.__init__') as mock_super_init: # Mock the return value of _create_agents_and_tasks mock_create.return_value = ([], []) # Empty agents and tasks lists @@ -265,7 +265,7 @@ class TestAutoAgents: with patch.object(AutoAgents, '_create_agents_and_tasks') as mock_create, \ patch.object(AutoAgents, '_display_agents_and_tasks') as mock_display, \ - patch('praisonaiagents.agents.agents.PraisonAIAgents.__init__') as mock_super_init: + patch('praisonaiagents.agents.agents.Agents.__init__') as mock_super_init: # Mock the return value of _create_agents_and_tasks mock_create.return_value = ([], []) # Empty agents and tasks lists @@ -298,7 +298,7 @@ class TestAutoAgents: with patch.object(AutoAgents, '_create_agents_and_tasks') as mock_create, \ patch.object(AutoAgents, '_display_agents_and_tasks') as mock_display, \ - patch('praisonaiagents.agents.agents.PraisonAIAgents.__init__') as mock_super_init: + patch('praisonaiagents.agents.agents.Agents.__init__') as mock_super_init: # Mock the return value of _create_agents_and_tasks mock_create.return_value = ([], []) # Empty agents and tasks lists @@ -348,7 +348,7 @@ class TestAutoAgents: with patch.object(AutoAgents, '_create_agents_and_tasks') as mock_create, \ patch.object(AutoAgents, '_display_agents_and_tasks') as mock_display, \ - patch('praisonaiagents.agents.agents.PraisonAIAgents.__init__') as mock_super_init, \ + patch('praisonaiagents.agents.agents.Agents.__init__') as mock_super_init, \ patch('logging.warning') as mock_warning: # Mock the return value of _create_agents_and_tasks @@ -447,7 +447,7 @@ class TestAutoAgents: with patch.object(AutoAgents, '_create_agents_and_tasks') as mock_create, \ patch.object(AutoAgents, '_display_agents_and_tasks') as mock_display, \ - patch('praisonaiagents.agents.agents.PraisonAIAgents.__init__') as mock_super_init: + patch('praisonaiagents.agents.agents.Agents.__init__') as mock_super_init: # Mock the return value of _create_agents_and_tasks mock_agents = [Mock() for _ in range(2)] # Only 2 agents after truncation @@ -506,7 +506,7 @@ class TestAutoAgents: with patch.object(AutoAgents, '_create_agents_and_tasks') as mock_create, \ patch.object(AutoAgents, '_display_agents_and_tasks') as mock_display, \ - patch('praisonaiagents.agents.agents.PraisonAIAgents.__init__') as mock_super_init, \ + patch('praisonaiagents.agents.agents.Agents.__init__') as mock_super_init, \ patch('logging.warning') as mock_warning: # Mock the return value of _create_agents_and_tasks @@ -581,7 +581,7 @@ class TestAutoAgents: with patch.object(AutoAgents, '_create_agents_and_tasks') as mock_create, \ patch.object(AutoAgents, '_display_agents_and_tasks') as mock_display, \ - patch('praisonaiagents.agents.agents.PraisonAIAgents.__init__') as mock_super_init: + patch('praisonaiagents.agents.agents.Agents.__init__') as mock_super_init: # Mock the return value of _create_agents_and_tasks mock_create.return_value = ([], []) # Empty agents and tasks lists @@ -626,7 +626,7 @@ class TestAutoAgents: with patch.object(AutoAgents, '_create_agents_and_tasks') as mock_create, \ patch.object(AutoAgents, '_display_agents_and_tasks') as mock_display, \ - patch('praisonaiagents.agents.agents.PraisonAIAgents.__init__') as mock_super_init: + patch('praisonaiagents.agents.agents.Agents.__init__') as mock_super_init: # Mock the return value of _create_agents_and_tasks mock_create.return_value = ([], []) # Empty agents and tasks lists diff --git a/src/praisonai/tests/unit/test_comprehensive_import.py b/src/praisonai/tests/unit/test_comprehensive_import.py index b28d02193..0101fb1e2 100644 --- a/src/praisonai/tests/unit/test_comprehensive_import.py +++ b/src/praisonai/tests/unit/test_comprehensive_import.py @@ -14,8 +14,8 @@ def test_original_failing_import(): """Test the exact import that was failing in the GitHub issue""" print("=== Testing Original Failing Import ===") try: - from praisonaiagents.agents.agents import Agent, Task, PraisonAIAgents - print('āœ… SUCCESS: from praisonaiagents.agents.agents import Agent, Task, PraisonAIAgents') + from praisonaiagents.agents.agents import Agent, Task, Agents + print('āœ… SUCCESS: from praisonaiagents.agents.agents import Agent, Task, Agents') return True except ImportError as e: print(f'āŒ ERROR: {e}') diff --git a/src/praisonai/tests/unit/test_core_agents.py b/src/praisonai/tests/unit/test_core_agents.py index 433ed8f0a..0c48ba99d 100644 --- a/src/praisonai/tests/unit/test_core_agents.py +++ b/src/praisonai/tests/unit/test_core_agents.py @@ -7,7 +7,7 @@ from unittest.mock import Mock, patch, MagicMock sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'src', 'praisonai-agents')) try: - from praisonaiagents import Agent, Task, PraisonAIAgents + from praisonaiagents import Agent, Task, Agents from praisonaiagents.llm.llm import LLM except ImportError as e: pytest.skip(f"Could not import required modules: {e}", allow_module_level=True) @@ -148,15 +148,15 @@ class TestTask: assert task.async_execution is True -class TestPraisonAIAgents: - """Test PraisonAIAgents orchestration.""" +class TestAgents: + """Test Agents orchestration.""" def test_agents_creation(self, sample_agent_config, sample_task_config): - """Test PraisonAIAgents creation.""" + """Test Agents creation.""" agent = Agent(**sample_agent_config) task = Task(agent=agent, **sample_task_config) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" @@ -174,7 +174,7 @@ class TestPraisonAIAgents: agent = Agent(**sample_agent_config) task = Task(agent=agent, **sample_task_config) - agents = PraisonAIAgents( + agents = Agents( agents=[agent], tasks=[task], process="sequential" @@ -194,7 +194,7 @@ class TestPraisonAIAgents: task1 = Task(agent=agent1, name="task1", **{k: v for k, v in sample_task_config.items() if k != 'name'}) task2 = Task(agent=agent2, name="task2", **{k: v for k, v in sample_task_config.items() if k != 'name'}) - agents = PraisonAIAgents( + agents = Agents( agents=[agent1, agent2], tasks=[task1, task2], process="hierarchical" diff --git a/src/praisonai/tests/unit/test_enhanced_auto.py b/src/praisonai/tests/unit/test_enhanced_auto.py index 846a02ec0..faf89cb76 100644 --- a/src/praisonai/tests/unit/test_enhanced_auto.py +++ b/src/praisonai/tests/unit/test_enhanced_auto.py @@ -136,7 +136,7 @@ class TestEnhancedYAMLGeneration: assert any('search' in name.lower() for name in tool_names) -class TestIntegrationWithPraisonAIAgentsTools: +class TestIntegrationWithAgentsTools: """Tests for integration with praisonaiagents.tools.""" def test_can_import_praisonaiagents_tools(self): diff --git a/src/praisonai/tests/unit/test_session_import.py b/src/praisonai/tests/unit/test_session_import.py index 756746ad7..1be28b7a1 100644 --- a/src/praisonai/tests/unit/test_session_import.py +++ b/src/praisonai/tests/unit/test_session_import.py @@ -15,8 +15,8 @@ try: print('Session class found:', Session) # This was the failing import chain - from praisonaiagents.agents.agents import Agent, Task, PraisonAIAgents - print('SUCCESS: Agent, Task, PraisonAIAgents import works correctly') + from praisonaiagents.agents.agents import Agent, Task, Agents + print('SUCCESS: Agent, Task, Agents import works correctly') except ImportError as e: print('ERROR:', e) diff --git a/src/praisonai/tests/unit/test_tool_fix_example.py b/src/praisonai/tests/unit/test_tool_fix_example.py index f67c92477..76530c0fb 100644 --- a/src/praisonai/tests/unit/test_tool_fix_example.py +++ b/src/praisonai/tests/unit/test_tool_fix_example.py @@ -5,7 +5,7 @@ This example shows how agents now properly use tools instead of saying "I do not have access to the internet". """ import logging -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Enable debug logging to see tool processing logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') @@ -48,7 +48,7 @@ def test_tool_usage(): print("=" * 60) # Create workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[search_agent], tasks=[search_task], verbose=True diff --git a/src/praisonai/tests/unit/test_tool_fix_improved.py b/src/praisonai/tests/unit/test_tool_fix_improved.py index cf32273c7..9d5a35691 100644 --- a/src/praisonai/tests/unit/test_tool_fix_improved.py +++ b/src/praisonai/tests/unit/test_tool_fix_improved.py @@ -3,7 +3,7 @@ Enhanced test example demonstrating the improved tool call fix for Gemini models This test includes edge cases and error handling scenarios. """ import logging -from praisonaiagents import Agent, Task, PraisonAIAgents +from praisonaiagents import Agent, Task, Agents # Enable info logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') @@ -81,7 +81,7 @@ def test_improved_implementation(): try: # Create workflow - workflow = PraisonAIAgents( + workflow = Agents( agents=[test_agent], tasks=[test_task], verbose=True diff --git a/src/praisonai/uv.lock b/src/praisonai/uv.lock index c9bb929f0..4b23e2f99 100644 --- a/src/praisonai/uv.lock +++ b/src/praisonai/uv.lock @@ -4276,7 +4276,7 @@ requires-dist = [ { name = "praisonai-tools", marker = "extra == 'autogen'", specifier = ">=0.1.0" }, { name = "praisonai-tools", marker = "extra == 'autogen-v4'", specifier = ">=0.1.0" }, { name = "praisonai-tools", marker = "extra == 'crewai'", specifier = ">=0.1.0" }, - { name = "praisonaiagents", specifier = ">=0.9.0" }, + { name = "praisonaiagents", specifier = ">=0.9.1" }, { name = "pyautogen", marker = "extra == 'autogen'", specifier = "==0.2.29" }, { name = "pydantic", marker = "extra == 'chat'", specifier = "<=2.10.1" }, { name = "pydantic", marker = "extra == 'code'", specifier = "<=2.10.1" }, @@ -4324,7 +4324,7 @@ wheels = [ [[package]] name = "praisonaiagents" -version = "0.9.0" +version = "0.9.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, @@ -4333,9 +4333,9 @@ dependencies = [ { name = "pydantic" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f5/a8/c2e09f15cc54dec0afe91c69ad75fc8a1634de9ae2701d08c1e7cd64a4b5/praisonaiagents-0.9.0.tar.gz", hash = "sha256:a1f1e38676f723e7fbc1d8fa9314e63d1884fb8a069fbafa5ea028ec4fb9bf66", size = 902419, upload-time = "2026-01-08T13:23:10.826Z" } +sdist = { url = "https://files.pythonhosted.org/packages/29/89/ba70de29280fd2a2be360194160b7f16f0c74f13eb91f12161fdef3aac59/praisonaiagents-0.9.1.tar.gz", hash = "sha256:004cda4d27fdb9143a93bee3fb33a16c4b04ee3fcaa4c1ec6ac0af0f05a2e37a", size = 920258, upload-time = "2026-01-08T14:31:02.708Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/da/341d32c829f9928ad858ffaf736e10a84ca3710fe3811e714a0d2cd576a2/praisonaiagents-0.9.0-py3-none-any.whl", hash = "sha256:1de58782b547ef5f2ec9df1ab3a41a9fb7b990fd3b0769eea5a47d9544ecf7f8", size = 871844, upload-time = "2026-01-08T13:23:08.584Z" }, + { url = "https://files.pythonhosted.org/packages/6d/33/7707794dc73a72b90809afe34375613c5f3bee5c51c283a19f163f35b921/praisonaiagents-0.9.1-py3-none-any.whl", hash = "sha256:3805c23942a43e7a95edc6057b23b1a53c9f8e306b1f95cddd4d857fe2f387d0", size = 894156, upload-time = "2026-01-08T14:31:00.795Z" }, ] [[package]]