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]]