Server: A2A

Deploy agents as A2A (Agent-to-Agent) protocol servers

Deploy agents as A2A servers for agent-to-agent communication.

CLI

bash
pip install "praisonai[serve]"
export OPENAI_API_KEY="your-key"

# Start A2A server — runs the workflow in agents.yaml
praisonai serve a2a --file agents.yaml

praisonai serve a2a runs the agents YAML workflow in --file for every message/send request (the same YAML path praisonai serve agents uses). The message text becomes the workflow topic.

OptionDefaultDescription
--host127.0.0.1Host to bind to
--port8082Server port
--fileagents.yamlAgents YAML file to run
--api-key–API key. Required when --host is not 127.0.0.1 / localhost / ::1. Can also be set via PRAISONAI_SERVE_API_KEY. Enforces Authorization: Bearer / X-API-Key on every route except /, /status, /.well-known/agent.json.

Expected Output:

✓ Starting A2A server on 127.0.0.1:8082
  Agents file: agents.yaml
  Agent Card: /.well-known/agent.json
  Discovery: /__praisonai__/discovery
Diagram

message/send

reply text

A2A client

POST /a2a

agents.yaml workflow

Security

praisonai serve a2a runs your agents (and their tools) for every request, so binding it to a non-localhost interface without authentication is refused.

bash
# Localhost — no key required
praisonai serve a2a

# Remote — key required (via env var)
export PRAISONAI_SERVE_API_KEY="your-secret"
praisonai serve a2a --host 0.0.0.0

# Or via flag
praisonai serve a2a --host 0.0.0.0 --api-key "your-secret"

Clients send the key in Authorization: Bearer … or X-API-Key: …. Only /, /status and /.well-known/agent.json are public; POST /a2a always needs the key when one is set.

Diagram

Yes

No

Set

Missing

praisonai serve a2a

Host is
localhost?

Start — no key needed

–api-key or
PRAISONAI_SERVE_API_KEY?

Start — Bearer / X-API-Key enforced

SystemExit — refuse to bind

Python

python
from praisonaiagents import Agent, A2A

agent = Agent(
    name="Assistant",
    role="Helpful AI Assistant",
    goal="Help users with their questions",
    llm="gpt-4o-mini"
)

a2a = A2A(agent=agent)
a2a.serve(host="0.0.0.0", port=8000)

Expected Output:

INFO:     Started server process
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000

Verify:

bash
curl http://localhost:8000/.well-known/agent.json

Response:

json
{
  "name": "Assistant",
  "description": "Helpful AI Assistant",
  "url": "http://localhost:8000/a2a",
  "version": "1.0.0",
  "capabilities": {
    "streaming": true,
    "pushNotifications": false,
    "stateTransitionHistory": false
  }
}

agents.yaml

The CLI command praisonai serve a2a --file agents.yaml runs the YAML workflow via praisonai.arun(...) for each message/send request. The Python A2A(agent=...) path above serves a single in-process Agent and does not read YAML.

A2A Endpoints

EndpointMethodDescription
/.well-known/agent.jsonGETAgent Card for discovery
/a2aPOSTJSON-RPC messages
/statusGETServer status

A2A Parameters

ParameterTypeDefaultDescription
agentAgent—PraisonAI Agent instance
agentsAgentTeam—Multi-agent team (agents.start() is called)
namestragent.nameA2A endpoint name
descriptionstragent.roleAgent description
urlstrhttp://localhost:8000/a2aA2A endpoint URL
versionstr1.0.0Version string
prefixstr""URL prefix
auth_tokenstrNoneBearer token for POST /a2a auth

Authentication

python
a2a = A2A(agent=agent, auth_token="sk-my-secret-key")
a2a.serve(port=8000)

Clients must send Authorization: Bearer sk-my-secret-key. Discovery (/.well-known/agent.json) stays public per A2A spec.

Send A2A Message

bash
curl -X POST http://localhost:8000/a2a \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "message/send",
    "id": "1",
    "params": {
      "message": {
        "role": "user",
        "parts": [{"type": "text", "text": "Hello!"}]
      }
    }
  }'

Response:

json
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "message": {
      "role": "agent",
      "parts": [{"type": "text", "text": "Hello! How can I help you?"}]
    }
  }
}

JSON-RPC Errors

CodeMeaningWhen
-32601Method not foundAny method other than message/send
-32602Invalid paramsmessage/send without a usable text part
-32603Internal errorAgent execution raised; the exception message is included
json
{
  "jsonrpc": "2.0",
  "id": "1",
  "error": {"code": -32602, "message": "message/send requires a text part"}
}

Python Client

python
import requests

# Get Agent Card
response = requests.get("http://localhost:8000/.well-known/agent.json")
agent_card = response.json()
print(f"Agent: {agent_card['name']}")

# Send Message
message = {
    "jsonrpc": "2.0",
    "method": "message/send",
    "id": "1",
    "params": {
        "message": {
            "role": "user",
            "parts": [{"type": "text", "text": "Hello!"}]
        }
    }
}
response = requests.post("http://localhost:8000/a2a", json=message)
print(response.json())

Troubleshooting

IssueFix
Port in uselsof -i :8000
Missing depspip install "praisonai[serve]" (CLI) or pip install "praisonaiagents[os]" (Python)
No API keyexport OPENAI_API_KEY="your-key"
Agent Card 404Check router is included in app
Agents file not found: <path> at startupPass an existing YAML with --file, or create agents.yaml in the working directory.
--api-key ... is required when binding to a non-localhost host at startupSet PRAISONAI_SERVE_API_KEY=... (or --api-key ...), or bind to 127.0.0.1 / localhost for a private-only server.
401 on POST /a2aSend Authorization: Bearer <key> or X-API-Key: <key>.

Related