5. 서버 시작하기
5. 서버 시작하기
이제 Agent Card와 Agent Executor가 있으니, A2A 서버를 설정하고 시작할 수 있어요. A2A 서버를 설정하기 위해 Python SDK는 라우트 팩토리와 헬퍼 함수(create_agent_card_routes, create_jsonrpc_routes, create_rest_routes)를 제공해요. 라우트 팩토리를 사용해 A2A 서버의 서비스용 라우트를 만들어요. 이 라우트들은 Starlette와 FastAPI 같은 인기 프레임워크에 기본적으로 연결할 수 있어서, 인증, 로깅, 기타 기능을 더 잘 제어할 수 있어요. 이 튜토리얼에서는 Uvicorn과 함께 Starlette를 사용할게요.
출처: 문서
본문
Helloworld의 서버 설정
__main__.py를 다시 보면서 서버가 어떻게 초기화되고 시작되는지 살펴볼게요.
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 a2a.types import (
AgentCapabilities,
AgentCard,
AgentInterface,
AgentSkill,
)
from agent_executor import (
HelloWorldAgentExecutor, # type: ignore[import-untyped]
)
from starlette.applications import Starlette
if __name__ == '__main__':
# Defines the abilities or functions that agent can perform.
skill = AgentSkill(
id='echo_bot',
name='Echo Bot',
description='An example agent that acknowledges client request and responds with a "Hello World" message.',
input_modes=['text/plain'],
output_modes=['text/plain'],
tags=['a2a', 'echo-example'],
examples=['hi', 'how are you'],
)
# Defines an optional additional skill for the agent that is not visible in the public card.
extended_skill = AgentSkill(
id='echo_bot_super_mode',
name='Echo Bot (Super Mode)',
description='An extended version of Echo Bot that responds with extra enthusiasm!',
tags=['a2a', 'echo-example', 'extended'],
examples=['super hi', 'give me a super hello'],
)
# Define a public-facing agent card that allows clients to discover your agent's capabilities.
public_agent_card = AgentCard(
# Basic identity information of A2A server
name='Hello World Agent', # Identity
description='Just a hello world agent',
version='0.0.1',
# Default Media Types for the agent's interactions
default_input_modes=['text/plain'], # Supported media types
default_output_modes=['text/plain'],
# Supported A2A features (like streaming or extended config)
capabilities=AgentCapabilities(streaming=True, extended_agent_card=True),
# Ordered list of endpoints and protocols where the service can be reached
supported_interfaces=[
AgentInterface(
protocol_binding='JSONRPC',
url='http://127.0.0.1:9999',
protocol_version='1.0',
)
],
# The list of AgentSkill objects that this agent offers
skills=[skill],
# Optional attributes (omitted here for simplicity):
# icon_url -> A URL to an icon representing the agent
)
# Defines the authenticated extended agent card with
# extended skills that are visible only to authenticated users
extended_agent_card = AgentCard(
name='Hello World Agent - Extended Edition',
description='The full-featured hello world agent for authenticated users.',
version='0.0.2',
default_input_modes=['text/plain'],
default_output_modes=['text/plain'],
capabilities=AgentCapabilities(streaming=True, extended_agent_card=True),
supported_interfaces=[
AgentInterface(
protocol_binding='JSONRPC',
url='http://127.0.0.1:9999',
protocol_version='1.0',
)
],
skills=[
skill,
extended_skill,
], # Both skills for the extended card
)
# The RequestHandler processes incoming requests and manages tasks
request_handler = DefaultRequestHandler(
# Agent executor handles the execution of the client requests
agent_executor=HelloWorldAgentExecutor(),
# The task_store is used to store and manage tasks
task_store=InMemoryTaskStore(),
# Public agent card for unauthenticated users
agent_card=public_agent_card,
# Extended agent card for authenticated users
extended_agent_card=extended_agent_card,
)
# Creating the routes for the A2A server
# These routes handle the incoming requests from the clients
# and the outgoing responses to the clients
routes = []
# Create routes for the agent card
routes.extend(create_agent_card_routes(public_agent_card))
# Create routes for the JSONRPC protocol
# Alternatively, you can choose GRPC or HTTP_JSON as protocol bindings
# based on your requirements
routes.extend(create_jsonrpc_routes(request_handler, '/'))
# Create a web app with the defined routes
# Here we are using Starlette, a lightweight ASGI web framework to serve the agent
# Alternatively, you can choose FastAPI or other ASGI frameworks
app = Starlette(routes=routes)
# Run the app
# Uvicorn is a production-ready ASGI HTTP server
uvicorn.run(app, host='127.0.0.1', port=9999)
하나씩 풀어볼게요.
DefaultRequestHandler:
- SDK는
DefaultRequestHandler를 제공해요. 이 핸들러는 여러분의AgentExecutor구현(HelloWorldAgentExecutor),TaskStore(InMemoryTaskStore), 그리고 공개·확장AgentCard객체를 받아요. - 들어오는 A2A RPC 호출을 실행기의 적절한 메서드(예:
execute또는cancel)로 라우팅해요. TaskStore는DefaultRequestHandler가 태스크의 수명주기를 관리하는 데 사용해요. 특히 상태를 가진 상호작용, 스트리밍, 재구독에 필요하죠. 실행기가 단순해도 핸들러는 태스크 저장소가 필요해요.agent_card는 요청을 처리할 때 에이전트의 선언된 역량을 검증할 수 있도록 핸들러에 전달돼요. 예를 들어 스트리밍이나 푸시 알림이 지원되는지 처리 전에 확인해요.extended_agent_card는 인증된 클라이언트에게GetExtendedAgentCardRPC 메서드로 서빙할 수 있도록 전달돼요.
create_agent_card_routes와 create_jsonrpc_routes:
create_agent_card_routes(public_agent_card)는 공개 발견을 위해/.well-known/agent-card.json엔드포인트에 Agent Card를 노출하는 Starlette 라우트를 반환해요.create_jsonrpc_routes(request_handler, '/')는 들어오는 모든 A2A JSON-RPC 메서드 호출을request_handler에 위임해 처리하는 Starlette 라우트를 반환해요.- 이 라우트 목록들은 결합되어 표준
Starlette애플리케이션에 전달돼요.
uvicorn.run(app, ...):
- 구성된
Starlette앱은uvicorn.run()으로 실행되어 에이전트를 HTTP로 접근 가능하게 해요. host='127.0.0.1'은 서버를 로컬 머신에서만 접근 가능하게 해요.port=9999는 리슨할 포트를 지정해요. 이는AgentCard의supported_interfaces에 정의된 엔드포인트와 일치해요.
Helloworld 서버 실행하기
터미널에서 a2a-samples 디렉터리로 이동하고(아직 거기에 없다면) 가상 환경이 활성화되어 있는지 확인해요. Helloworld 서버를 실행하려면:
# from the a2a-samples directory
python samples/python/agents/helloworld/__main__.py
서버가 실행 중임을 나타내는 다음과 유사한 출력이 보여야 해요:
INFO: Started server process [xxxxx]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:9999 (Press CTRL+C to quit)
여러분의 A2A Helloworld 에이전트가 이제 실행되어 요청을 기다리고 있어요! 다음 단계에서는 그와 상호작용해 볼게요.
더 알아보기 (Learn more)
- 서버와 상호작용하는 다음 단계는 6. Interacting with the Server를 참고하세요.
- 라우트 팩토리가 쓰는 핵심 모듈은 Agent Executor 문서에서 다뤄요.