Agent API Launch

Deploy AI agents as HTTP APIs or MCP servers for integration with external applications.

PraisonAI Agents can be deployed as HTTP APIs or MCP (Model Context Protocol) servers, enabling seamless integration with web applications, microservices, and other systems.

python
from praisonaiagents import Agent

agent = Agent(name="api-agent", instructions="Answer HTTP API requests.")
agent.launch(port=8000)

The user deploys an agent as an HTTP or MCP service; external apps call the API instead of importing the SDK directly.

Diagram

Agent API Launch

🤖 Agent

🚀 agent.launch

🌐 HTTP API

🔌 MCP Server

📱 Web Client

🤖 MCP Client

📤 Response

How It Works

An external client calls the launched endpoint, and the agent runs the request before returning the response.

Diagram
AgentAgentServerClientUserAgentAgentServerClientUserSend messagePOST /pathRun taskResultJSON responseAnswer

Choose a Protocol

Pick the launch protocol that matches the caller.

Diagram

Web app / cURL / REST

MCP-compatible host

Who calls the agent?

protocol=http

protocol=mcp

Authentication

.launch() binds to 127.0.0.1 by default and enforces a bearer token the moment you expose it beyond localhost.

Diagram

Yes

No

Yes 127.0.0.1 / ::1 / localhost

No 0.0.0.0 / LAN IP

.launch called

PRAISONAI_LAUNCH_AUTH_TOKEN set?

Every request needs the token, 401 otherwise

host is loopback?

Keyless dev flow

Auto-generate one-time token, print to stdout, enforce it

.launch() has three authentication states:

StateTriggerBehaviour
Keyless devNo token + loopback hostNo auth needed. agent.launch(port=8000) just works locally.
EnforcedPRAISONAI_LAUNCH_AUTH_TOKEN setEvery request must send the token or gets 401 Unauthorized.
Fail-closedNo token + non-loopback hostThe SDK auto-generates a one-time bearer token, prints it once to stdout, and enforces it.

Loopback hosts are 127.0.0.1, ::1, and localhost. Anything else (0.0.0.0, a LAN IP) is treated as non-loopback.

Local dev (keyless)

Loopback is the default, so no token is needed:

python
from praisonaiagents import Agent

agent = Agent(name="dev", instructions="Answer.")
agent.launch(port=8000)   # binds 127.0.0.1, no token needed
bash
curl -X POST http://localhost:8000/ \
  -H "Content-Type: application/json" \
  -d '{"message": "hi"}'

Public bind (preset token)

Set a token before binding to a public host:

bash
export PRAISONAI_LAUNCH_AUTH_TOKEN=$(openssl rand -base64 32)
python
from praisonaiagents import Agent

agent = Agent(name="public", instructions="Answer.")
agent.launch(host="0.0.0.0", port=8000)   # enforces the token above
bash
curl -X POST http://SERVER:8000/ \
  -H "Authorization: Bearer $PRAISONAI_LAUNCH_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message": "hi"}'

Public bind (auto-token)

Bind publicly without a preset token and the SDK prints a one-time token:

python
from praisonaiagents import Agent

agent = Agent(name="public", instructions="Answer.")
agent.launch(host="0.0.0.0", port=8000)
# Prints once to stdout:
#   \U0001F510 launch() bound to non-loopback host '0.0.0.0' without
#   PRAISONAI_LAUNCH_AUTH_TOKEN set. Generated a one-time bearer token
#   (set PRAISONAI_LAUNCH_AUTH_TOKEN to override): <TOKEN>

Capture the printed `

and send it on every request as the Authorization: Bearer` header.

Quick Start

  1. Install Package

    Install PraisonAI Agents:

    bash
    pip install praisonaiagents

    For MCP support, also install:

    bash
    pip install praison-mcp
  2. Create an Agent

    Create an agent to deploy as an API:

    python
    from praisonaiagents import Agent
    
    # Create your agent
    agent = Agent(
        name="API Assistant",
        role="API helper",
        goal="Answer questions and perform tasks via API",
        backstory="An AI assistant accessible through HTTP endpoints",
        llm="gpt-4o-mini"
    )
  3. Launch as API

    Deploy the agent as an HTTP API:

    python
    # Launch as HTTP API
    agent.launch(
        protocol="http",  # Default protocol
        host="127.0.0.1",  # Loopback default; set "0.0.0.0" to expose (requires a token)
        port=8000,
        path="/assistant"  # Available at http://localhost:8000/assistant
    )
  4. Test the API

    Test your deployed agent API:

    bash
    curl -X POST http://localhost:8000/assistant \
      -H "Content-Type: application/json" \
      -d '{"message": "Hello, how can you help me?"}'

Launch Methods

HTTP API Server

The most common deployment method is as an HTTP API server using FastAPI:

python
from praisonaiagents import Agent

# Create agent
agent = Agent(
    name="Customer Support",
    role="Support specialist", 
    goal="Help customers with their inquiries",
    tools=["web_search", "knowledge_base"]  # Optional tools
)

# Launch as HTTP API
agent.launch(
    protocol="http",     # Protocol type (default: "http")
    host="127.0.0.1",    # Loopback default; set "0.0.0.0" to expose (requires a token)
    port=8000,           # Port number
    path="/support",     # API endpoint path
    debug=False          # Debug mode for development
)

# API will be available at:
# POST http://localhost:8000/support

MCP Server

For Model Context Protocol integration:

python
from praisonaiagents import Agent

# Create agent
agent = Agent(
    name="SearchAgent",
    instructions="Search the internet for information",
    llm="gpt-4o-mini"
)

# Launch as MCP server
agent.launch(
    protocol="mcp",      # MCP protocol
    port=8080,           # Port number
    host="127.0.0.1"     # Loopback default; set "0.0.0.0" to expose (requires a token)
)

# MCP server will create SSE endpoints
# Tool will be named: execute_SearchAgent_task

Lifecycle: when does launch() return and when does the script exit?

In HTTP mode, launch() returns immediately; a script stays alive at exit until Ctrl+C. REPLs and notebooks never block.

Diagram
Interpreter exitServer thread.launch()ScriptInterpreter exitServer thread.launch()Scriptagent.launch(port=8000)start (daemon)returns immediatelyruns remaining codeend of scriptkeep-alive waits (“Agent servers running. Press Ctrl+C to stop.”)Ctrl+C → servers stopped

A single keep-alive hook is registered once, the first time launch() runs in a non-interactive script. The behaviour no longer depends on any text in your file — a string such as "call team.launch(port=1)" later in the script no longer makes it exit early.

Multiple launches

Every .launch() call runs, the code after them runs, and the script waits once at exit.

python
from praisonaiagents import Agent

sales = Agent(name="Sales", instructions="You help with sales")
support = Agent(name="Support", instructions="You help with support")

sales.launch(path="/sales", port=8000)      # returns immediately
support.launch(path="/support", port=8001)  # also runs

print("Both servers are up")                # runs too
# Script end: waits here until Ctrl+C

REPL / notebook

In an interactive session or Jupyter notebook, agent.launch(...) returns immediately and nothing waits at exit — the running kernel keeps the server threads alive.

API Usage

When launched as an HTTP API, agents expose a single endpoint that accepts POST requests:

HTTP API Endpoint

POST /path

Send messages to the agent and receive responses.

python
# Request
{
    "message": "What's the weather like?"
}

# Response
{
    "response": "I'd be happy to help with weather information..."
}

The endpoint also supports form data:

bash
curl -X POST http://localhost:8000/assistant \
  -F "message=Hello, how are you?"

Complete Examples

Example 1: Single Agent HTTP API

python
from praisonaiagents import Agent

# Create an agent with specific instructions
agent = Agent(
    name="Research Assistant",
    instructions="You are a helpful research assistant. Help users find and summarize information.",
    llm="gpt-4o-mini"
)

# Launch the agent
agent.launch(
    path="/research",
    port=3030,
    host="127.0.0.1"  # Loopback default; set "0.0.0.0" to expose (requires a token)
)

# The agent is now available at http://localhost:3030/research

Example 2: Multi-Agent HTTP API System

python
from praisonaiagents import Agent, AgentTeam

# Create multiple specialized agents
research_agent = Agent(
    name="Research",
    instructions="Research and gather information on topics"
)

summarize_agent = Agent(
    name="Summarize", 
    instructions="Create concise summaries of provided information"
)

# Create an agents collection
agents = AgentTeam(
    name="ResearchTeam",
    agents=[research_agent, summarize_agent]
)

# Launch all agents on the same endpoint
agents.launch(
    path="/team",
    port=8000,
    host="127.0.0.1"  # Loopback default; set "0.0.0.0" to expose (requires a token)
)

# All agents available at http://localhost:8000/team

Example 3: MCP Server with Tools

python
from praisonaiagents import Agent

# Create agent with tools
agent = Agent(
    name="TweetAgent",
    instructions="Create engaging tweets based on the topic provided",
    tools=["web_search"]  # Can include tools
)

# Launch as MCP server
agent.launch(
    protocol="mcp",
    port=8080,
    host="127.0.0.1"
)

# MCP tool available as: execute_TweetAgent_task

Example 4: Multiple Endpoints on Same Port

python
from praisonaiagents import Agent

# Create different agents
sales_agent = Agent(
    name="Sales",
    instructions="Help with product information and sales"
)

support_agent = Agent(
    name="Support",
    instructions="Provide technical support"
)

# Launch on different paths but same port
sales_agent.launch(
    path="/sales",
    port=8000
)

support_agent.launch(
    path="/support", 
    port=8000
)

# Both available on port 8000:
# - http://localhost:8000/sales
# - http://localhost:8000/support

Mix Agent.launch() and AgentTeam.launch() on One Port

Agent.launch() and AgentTeam.launch() (aka PraisonAIAgents.launch()) share a single process-wide server registry.

In one process, a standalone agent and a team launched on the same port bind the same FastAPI app and the same uvicorn server — one / endpoint that lists both sets of routes, one /health, one /docs. You no longer get Address already in use when both call sites target the same port, and endpoints registered through one launcher are visible from the other.

python
from praisonaiagents import Agent, AgentTeam

assistant = Agent(name="Assistant", instructions="Answer.")
research = Agent(name="Research", instructions="Research topics.")
team = AgentTeam(name="Team", agents=[research])

# Same port — same FastAPI app / uvicorn server / route table
assistant.launch(path="/assistant", port=8000)
team.launch(path="/team", port=8000)

# curl http://localhost:8000/       # lists /assistant and /team
# curl http://localhost:8000/health

Example 5: Debug Mode for Development

python
from praisonaiagents import Agent

# Create agent
agent = Agent(
    name="Dev Assistant",
    instructions="Help with development tasks",
    llm="gpt-4o-mini"
)

# Launch with debug mode enabled
agent.launch(
    path="/dev",
    port=8000,
    debug=True  # Enables auto-reload and detailed logging
)

Launch Parameters

ParameterTypeDescriptionDefault
protocolstrLaunch protocol: “http” or “mcp”“http”
hoststrHost to bind to. Loopback by default; set "0.0.0.0" to expose (then a token is required).“127.0.0.1”
portintPort number8000
pathstrAPI endpoint path (HTTP) or base path (MCP)“/”
debugboolEnable debug mode with auto-reloadFalse

Environment Variables

VariableDefaultDescription
PRAISONAI_SERVER_READY_TIMEOUT5.0Seconds .launch() waits for the shared HTTP server to become ready — used by both Agent.launch() and AgentTeam.launch(). Readiness is signalled only after uvicorn reports the socket is bound; on timeout, a warning is logged and execution continues.
PRAISONAI_LAUNCH_AUTH_TOKEN(unset)Bearer token required by every request when set. Unset + loopback = keyless dev flow; unset + non-loopback = a one-time token is auto-generated, printed to stdout, and required on every request. See Authentication.

Client Integration

Python Client

python
import requests
from typing import Dict, Any

class AgentAPIClient:
    def __init__(self, base_url: str):
        self.base_url = base_url.rstrip('/')
        self.headers = {"Content-Type": "application/json"}

    def chat(self, message: str) -> Dict[str, Any]:
        response = requests.post(
            self.base_url,
            headers=self.headers,
            json={"message": message}
        )
        response.raise_for_status()
        return response.json()

# Usage
client = AgentAPIClient("http://localhost:8000/assistant")
response = client.chat("Hello!")
print(response["response"])

JavaScript Client

javascript
class AgentAPIClient {
    constructor(baseUrl) {
        this.baseUrl = baseUrl.replace(/\/$/, '');
    }

    async chat(message) {
        const response = await fetch(this.baseUrl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ message })
        });

        if (!response.ok) {
            throw new Error(`API error: ${response.statusText}`);
        }

        return response.json();
    }
}

// Usage
const client = new AgentAPIClient('http://localhost:8000/assistant');
const response = await client.chat('Hello!');
console.log(response.response);

MCP Client Integration

For MCP servers, use an MCP-compatible client:

python
from mcp import Client

# Connect to MCP server
client = Client("http://localhost:8080")

# Call the agent tool
result = await client.call_tool(
    "execute_TweetAgent_task",
    arguments={"input": "Create a tweet about AI"}
)

Deployment Best Practices

Production Deployment

Docker Deployment

dockerfile
# Dockerfile
FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install praisonaiagents

# Copy agent code
COPY agent.py .

# Expose port
EXPOSE 8000

# Run agent API
CMD ["python", "agent.py"]
yaml
# docker-compose.yml
version: '3.8'
services:
  agent-api:
    build: .
    ports:
      - "8000:8000"
    environment:
      - OPENAI_API_KEY=${OPENAI_API_KEY}
    restart: unless-stopped

Systemd Service

ini
# /etc/systemd/system/agent-api.service
[Unit]
Description=PraisonAI Agent API
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/agent-api
Environment="OPENAI_API_KEY=%OPENAI_API_KEY%"
ExecStart=/usr/bin/python3 /opt/agent-api/agent.py
Restart=always

[Install]
WantedBy=multi-user.target

Nginx Reverse Proxy

nginx
server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://localhost:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Important Notes

  1. Threading: The launch() method uses threading to run servers in the background
  2. Lifecycle: launch() returns immediately; in a script, the process stays alive at exit until Ctrl+C (see Lifecycle)
  3. Multiple Agents: You can run multiple agents and teams on the same port with different paths (HTTP mode only). All .launch() call sites — Agent.launch(), AgentTeam.launch(), PraisonAIAgents.launch() — share one FastAPI app and one uvicorn server per port.
  4. Dependencies: HTTP mode requires FastAPI and uvicorn, MCP mode requires praison-mcp
  5. API Documentation: HTTP APIs automatically get FastAPI documentation at /docs

Troubleshooting

Port already in use
  • Check if another process is using the port: lsof -i :8000
  • Kill the process or use a different port
  • Ensure previous agent instances are properly stopped
Missing dependencies
  • For HTTP: pip install fastapi uvicorn
  • For MCP: pip install praison-mcp mcp
  • Check error messages for specific missing packages
Agent not responding
  • Check console for error messages
  • Verify API key is set correctly
  • Test with debug=True for more detailed logs
  • Ensure agent initialization is successful
Connection refused
  • Verify the host and port settings
  • Check firewall rules
  • Ensure the agent is actually running
  • Try connecting from localhost first
Agent server slow to start

If you see Agent server on port N did not become ready within 5.0s in the logs, the FastAPI server took longer than the default 5s to come up. This is usually safe (.launch() still returns and the server keeps starting), but you can raise the wait:

bash
export PRAISONAI_SERVER_READY_TIMEOUT=15  # seconds

Common causes: slow imports, cold-start on resource-constrained machines, blocking startup hooks.

If a bind fails (Address already in use, missing dependency), the SDK logs a warning and clears the port’s readiness flag so the next .launch() call on that port re-attempts the bind. You do not need to restart the process.

Next Steps

Best Practices

Pick the protocol that matches your caller

Use protocol="http" for web apps, cURL, and microservices that speak REST, and protocol="mcp" when the caller is an MCP-compatible agent host. HTTP is the default, so agent.launch(port=8000) gives you a POST endpoint with automatic FastAPI docs at /docs. Switch only when the consumer requires MCP tools.

Share a port with distinct paths, not duplicate ones

Multiple agents can run on the same port when each uses a unique path. Registration is atomic across threads, but if two .launch() calls reuse the same path on the same port the second is auto-suffixed (/path_abc123) and a warning is logged. Assign explicit, distinct paths (/sales, /support) so clients always hit the agent they expect.

Tune the readiness timeout for slow cold starts

.launch() returns only after the port accepts connections, waiting up to 5 seconds by default. On resource-constrained machines or with heavy imports, raise the wait so startup logs aren’t misread as failures:

bash
export PRAISONAI_SERVER_READY_TIMEOUT=15

A timeout logs a warning but does not abort — the server keeps starting in the background.

Set a token before exposing, and terminate TLS at the edge

The launch server now enforces its own bearer auth: set PRAISONAI_LAUNCH_AUTH_TOKEN before binding to a non-loopback host, or the SDK auto-generates a one-time token and prints it. A reverse proxy (nginx) is still recommended for HTTPS and rate limiting, but it is no longer the only thing standing between the internet and your agent. Bind to 127.0.0.1 (the default) when the proxy runs on the same host.

Related