-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy patha2a_server.py
More file actions
124 lines (102 loc) · 3.67 KB
/
a2a_server.py
File metadata and controls
124 lines (102 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# Copyright (c) Microsoft. All rights reserved.
import argparse
import os
import sys
import uvicorn
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes
from a2a.server.tasks import InMemoryTaskStore
from agent_definitions import AGENT_CARD_FACTORIES, AGENT_FACTORIES
from agent_executor import AgentFrameworkExecutor
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
from starlette.applications import Starlette
# Load environment variables from .env file
load_dotenv()
"""
A2A Server Sample — Host an Agent Framework agent as an A2A endpoint
This sample creates a Python-based A2A-compliant server that wraps an Agent
Framework agent. The server uses the a2a-sdk's Starlette application to handle
JSON-RPC requests and serves the AgentCard at /.well-known/agent.json.
Three agent types are available:
- invoice — Answers invoice queries using mock data and function tools.
- policy — Returns a fixed policy response.
- logistics — Returns a fixed logistics response.
Usage:
uv run python a2a_server.py --agent-type policy --port 5001
uv run python a2a_server.py --agent-type invoice --port 5000
uv run python a2a_server.py --agent-type logistics --port 5002
Environment variables:
FOUNDRY_PROJECT_ENDPOINT — Your Azure AI Foundry project endpoint
FOUNDRY_MODEL — Model deployment name (e.g. gpt-4o)
"""
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="A2A Agent Server")
parser.add_argument(
"--agent-type",
choices=["invoice", "policy", "logistics"],
default="policy",
help="Type of agent to host (default: policy)",
)
parser.add_argument(
"--host",
default="localhost",
help="Host to bind to (default: localhost)",
)
parser.add_argument(
"--port",
type=int,
default=5001,
help="Port to listen on (default: 5001)",
)
return parser.parse_args()
def main() -> None:
args = parse_args()
# Validate environment
project_endpoint = os.getenv("FOUNDRY_PROJECT_ENDPOINT")
model = os.getenv("FOUNDRY_MODEL")
if not project_endpoint:
print("Error: FOUNDRY_PROJECT_ENDPOINT environment variable is not set.")
sys.exit(1)
if not model:
print("Error: FOUNDRY_MODEL environment variable is not set.")
sys.exit(1)
# Create the LLM client
credential = AzureCliCredential()
client = FoundryChatClient(
project_endpoint=project_endpoint,
model=model,
credential=credential,
)
# Create the Agent Framework agent for the chosen type
agent_factory = AGENT_FACTORIES[args.agent_type]
agent = agent_factory(client)
# Build the A2A server components
url = f"http://{args.host}:{args.port}/"
agent_card = AGENT_CARD_FACTORIES[args.agent_type](url)
executor = AgentFrameworkExecutor(agent)
task_store = InMemoryTaskStore()
request_handler = DefaultRequestHandler(
agent_executor=executor,
task_store=task_store,
agent_card=agent_card,
)
app = Starlette(
routes=[
*create_agent_card_routes(agent_card),
*create_jsonrpc_routes(request_handler, "/"),
]
)
print(f"Starting A2A server: {agent_card.name}")
print(f" Agent type : {args.agent_type}")
print(f" Listening : {url}")
print(f" Agent card : {url}.well-known/agent.json")
print()
uvicorn.run(
app,
host=args.host,
port=args.port,
)
if __name__ == "__main__":
main()