mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
68357b0250
- Fix non-streaming empty response by accumulating intermediate WORKING status updates and flushing them when an empty terminal event arrives - Fix sample agent_executor.py to enqueue Task before status events (required by v1.0 ActiveTask validation) - Fix create_jsonrpc_routes() calls to include required rpc_url param - Fix TYPE_CHECKING imports in sample agent_definitions.py - Add tests for non-streaming content accumulation behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
125 lines
3.7 KiB
Python
125 lines
3.7 KiB
Python
# 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()
|