Skip to content

Commit 5c98c68

Browse files
committed
Refactor agent launch functionality in multi-agent-api.py to remove blocking parameters, update version to 0.0.79 in pyproject.toml and uv.lock, and enhance server startup logic in agent.py with healthcheck endpoint and improved thread management.
1 parent 3fbaa6d commit 5c98c68

File tree

4 files changed

+63
-46
lines changed

4 files changed

+63
-46
lines changed
Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,20 @@
11
from praisonaiagents import Agent
22

3-
# Create a weather agent
43
weather_agent = Agent(
54
instructions="""You are a weather agent that can provide weather information for a given city.""",
65
llm="gpt-4o-mini"
76
)
87

9-
# Create a stock market agent
108
stock_agent = Agent(
119
instructions="""You are a stock market agent that can provide information about stock prices and market trends.""",
1210
llm="gpt-4o-mini"
1311
)
1412

15-
# Create a travel agent
1613
travel_agent = Agent(
1714
instructions="""You are a travel agent that can provide recommendations for destinations, hotels, and activities.""",
1815
llm="gpt-4o-mini"
1916
)
2017

21-
# Register the first two agents with blocking=False so they don't block execution
22-
weather_agent.launch(path="/weather", port=3030, blocking=False)
23-
stock_agent.launch(path="/stock", port=3030, blocking=False)
24-
25-
# Register the last agent with blocking=True to keep the server running
26-
# This must be the last launch() call
27-
travel_agent.launch(path="/travel", port=3030, blocking=True)
28-
29-
# The script will block at the last launch() call until the user presses Ctrl+C
18+
weather_agent.launch(path="/weather", port=3030)
19+
stock_agent.launch(path="/stock", port=3030)
20+
travel_agent.launch(path="/travel", port=3030)

src/praisonai-agents/praisonaiagents/agent/agent.py

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@
2222
import uuid
2323
from dataclasses import dataclass
2424

25+
# Global variables for API server
26+
_server_started = False
27+
_registered_agents = {}
28+
_shared_app = None
29+
2530
# Don't import FastAPI dependencies here - use lazy loading instead
2631

2732
if TYPE_CHECKING:
2833
from ..task.task import Task
2934

30-
# Shared variables for API server
31-
_shared_app = None
32-
_server_started = False
33-
_registered_agents = {}
34-
3535
@dataclass
3636
class ChatCompletionMessage:
3737
content: str
@@ -1408,17 +1408,15 @@ async def execute_tool_async(self, function_name: str, arguments: Dict[str, Any]
14081408
logging.error(f"Error in execute_tool_async: {str(e)}", exc_info=True)
14091409
return {"error": f"Error in execute_tool_async: {str(e)}"}
14101410

1411-
def launch(self, path: str = '/', port: int = 8000, host: str = '0.0.0.0', autostart: bool = True, debug: bool = False, blocking: bool = True):
1411+
def launch(self, path: str = '/', port: int = 8000, host: str = '0.0.0.0', debug: bool = False):
14121412
"""
14131413
Launch the agent as an HTTP API endpoint.
14141414
14151415
Args:
14161416
path: API endpoint path (default: '/')
14171417
port: Server port (default: 8000)
14181418
host: Server host (default: '0.0.0.0')
1419-
autostart: Whether to start the server automatically (default: True)
14201419
debug: Enable debug mode for uvicorn (default: False)
1421-
blocking: If True, blocks the main thread to keep the server running (default: True)
14221420
14231421
Returns:
14241422
None
@@ -1431,6 +1429,8 @@ def launch(self, path: str = '/', port: int = 8000, host: str = '0.0.0.0', autos
14311429
from fastapi import FastAPI, HTTPException, Request
14321430
from fastapi.responses import JSONResponse
14331431
from pydantic import BaseModel
1432+
import threading
1433+
import time
14341434

14351435
# Define the request model here since we need pydantic
14361436
class AgentQuery(BaseModel):
@@ -1458,6 +1458,11 @@ class AgentQuery(BaseModel):
14581458
@_shared_app.get("/")
14591459
async def root():
14601460
return {"message": "Welcome to PraisonAI Agents API. See /docs for usage."}
1461+
1462+
# Add healthcheck endpoint
1463+
@_shared_app.get("/health")
1464+
async def healthcheck():
1465+
return {"status": "ok", "agents": list(_registered_agents.keys())}
14611466

14621467
# Normalize path to ensure it starts with /
14631468
if not path.startswith('/'):
@@ -1516,47 +1521,68 @@ async def handle_agent_query(request: Request, query_data: Optional[AgentQuery]
15161521

15171522
print(f"🚀 Agent '{self.name}' available at http://{host}:{port}{path}")
15181523

1519-
# Start the server if this is the first launch call and autostart is True
1520-
if autostart and not _server_started:
1524+
# Start the server if it's not already running
1525+
if not _server_started:
15211526
_server_started = True
15221527

1523-
# Add healthcheck endpoint
1524-
@_shared_app.get("/health")
1525-
async def healthcheck():
1526-
return {"status": "ok", "agents": list(_registered_agents.keys())}
1527-
1528-
# Start the server in a separate thread to not block execution
1529-
import threading
1528+
# Start the server in a separate thread
15301529
def run_server():
15311530
try:
1531+
print(f"✅ FastAPI server started at http://{host}:{port}")
1532+
print(f"📚 API documentation available at http://{host}:{port}/docs")
1533+
print(f"🔌 Available endpoints: {', '.join(list(_registered_agents.keys()))}")
15321534
uvicorn.run(_shared_app, host=host, port=port, log_level="debug" if debug else "info")
15331535
except Exception as e:
15341536
logging.error(f"Error starting server: {str(e)}", exc_info=True)
15351537
print(f"❌ Error starting server: {str(e)}")
15361538

1539+
# Run server in a background thread
15371540
server_thread = threading.Thread(target=run_server, daemon=True)
15381541
server_thread.start()
15391542

1540-
# Give the server a moment to start up
1541-
import time
1543+
# Wait for a moment to allow the server to start and register endpoints
15421544
time.sleep(0.5)
1545+
else:
1546+
# If server is already running, wait a moment to make sure the endpoint is registered
1547+
time.sleep(0.1)
1548+
print(f"🔌 Available endpoints: {', '.join(list(_registered_agents.keys()))}")
1549+
1550+
# Get the stack frame to check if this is the last launch() call in the script
1551+
import inspect
1552+
stack = inspect.stack()
1553+
1554+
# If this is called from a Python script (not interactive), try to detect if it's the last launch call
1555+
if len(stack) > 1 and stack[1].filename.endswith('.py'):
1556+
caller_frame = stack[1]
1557+
caller_line = caller_frame.lineno
15431558

1544-
print(f"✅ FastAPI server started at http://{host}:{port}")
1545-
print(f"📚 API documentation available at http://{host}:{port}/docs")
1546-
1547-
# If blocking is True, keep the main thread alive
1548-
if blocking:
1549-
print("\nServer is running in blocking mode. Press Ctrl+C to stop...")
1559+
try:
1560+
# Read the file to check if there are more launch calls after this one
1561+
with open(caller_frame.filename, 'r') as f:
1562+
lines = f.readlines()
1563+
1564+
# Check if there are more launch() calls after the current line
1565+
has_more_launches = False
1566+
for line in lines[caller_line:]:
1567+
if '.launch(' in line and not line.strip().startswith('#'):
1568+
has_more_launches = True
1569+
break
1570+
1571+
# If this is the last launch call, block the main thread
1572+
if not has_more_launches:
1573+
try:
1574+
print("\nAll agents registered. Press Ctrl+C to stop the server.")
1575+
while True:
1576+
time.sleep(1)
1577+
except KeyboardInterrupt:
1578+
print("\nServer stopped")
1579+
except Exception as e:
1580+
# If something goes wrong with detection, block anyway to be safe
1581+
logging.error(f"Error in launch detection: {e}")
15501582
try:
15511583
while True:
15521584
time.sleep(1)
15531585
except KeyboardInterrupt:
15541586
print("\nServer stopped")
1555-
else:
1556-
# Note for non-blocking mode
1557-
print("\nNote: Server is running in a background thread. To keep it alive, either:")
1558-
print("1. Set blocking=True when calling launch()")
1559-
print("2. Keep your main application running")
1560-
print("3. Use a loop in your code to prevent the program from exiting")
1561-
1587+
15621588
return None

src/praisonai-agents/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "praisonaiagents"
7-
version = "0.0.78"
7+
version = "0.0.79"
88
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
99
authors = [
1010
{ name="Mervin Praison" }

src/praisonai-agents/uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)