6. 서버와 상호 작용하기¶
Helloworld A2A 서버가 실행 중이므로, 이제 몇 가지 요청을 보내보겠습니다. SDK에는 이러한 상호 작용을 단순화하는 클라이언트(A2AClient
)가 포함되어 있습니다.
Helloworld 테스트 클라이언트¶
test_client.py
스크립트는 다음 방법을 보여줍니다:
- 서버에서 에이전트 카드를 가져옵니다.
A2AClient
인스턴스를 생성합니다.- 비스트리밍(
message/send
) 및 스트리밍(message/stream
) 요청을 모두 보냅니다.
새 터미널 창을 열고, 가상 환경을 활성화한 후, a2a-samples
디렉토리로 이동합니다.
가상 환경 활성화 (가상 환경을 생성한 동일한 디렉토리에서 이 작업을 수행해야 합니다):
테스트 클라이언트를 실행합니다:
클라이언트 코드 이해하기¶
test_client.py
의 주요 부분을 살펴보겠습니다:
-
에이전트 카드 가져오기 및 클라이언트 초기화:
base_url = 'http://localhost:9999' async with httpx.AsyncClient() as httpx_client: # Initialize A2ACardResolver resolver = A2ACardResolver( httpx_client=httpx_client, base_url=base_url, # agent_card_path uses default, extended_agent_card_path also uses default )
A2ACardResolver
클래스는 편의를 위한 것입니다. 먼저 (제공된 기본 URL을 기반으로) 서버의/.well-known/agent.json
엔드포인트에서AgentCard
를 가져온 다음, 이를 사용하여 클라이언트를 초기화합니다. -
비스트리밍 메시지 보내기 (
send_message
):client = A2AClient( httpx_client=httpx_client, agent_card=final_agent_card_to_use ) logger.info('A2AClient initialized.') send_message_payload: dict[str, Any] = { 'message': { 'role': 'user', 'parts': [ {'kind': 'text', 'text': 'how much is 10 USD in INR?'} ], 'messageId': uuid4().hex, }, } request = SendMessageRequest( id=str(uuid4()), params=MessageSendParams(**send_message_payload) ) response = await client.send_message(request) print(response.model_dump(mode='json', exclude_none=True))
send_message_payload
는MessageSendParams
를 위한 데이터를 구성합니다.- 이것은
SendMessageRequest
로 래핑됩니다. role
이 "user"로 설정되고parts
에 내용이 포함된message
객체를 포함합니다.- Helloworld 에이전트의
execute
메서드는 단일 "Hello World" 메시지를 큐에 넣습니다.DefaultRequestHandler
는 이를 검색하여 응답으로 보냅니다. response
는SendMessageResponse
객체가 되며, 여기에는SendMessageSuccessResponse
(에이전트의Message
가 결과로 포함됨) 또는JSONRPCErrorResponse
가 포함됩니다.
-
작업 ID 처리 (Helloworld를 위한 설명 참고):
Helloworld 클라이언트 (
test_client.py
)는get_task
또는cancel_task
를 직접 시도하지 않습니다. 왜냐하면 단순한 Helloworld 에이전트의execute
메서드가message/send
를 통해 호출될 때,DefaultRequestHandler
가Task
객체 대신 직접적인Message
응답을 반환하기 때문입니다. (LangGraph 예제와 같이) 명시적으로 작업을 관리하는 더 복잡한 에이전트는message/send
로부터Task
객체를 반환하며, 이 객체의id
는get_task
또는cancel_task
에 사용될 수 있습니다. -
스트리밍 메시지 보내기 (
send_message_streaming
):streaming_request = SendStreamingMessageRequest( id=str(uuid4()), params=MessageSendParams(**send_message_payload) ) stream_response = client.send_message_streaming(streaming_request) async for chunk in stream_response: print(chunk.model_dump(mode='json', exclude_none=True))
- 이 메서드는 에이전트의
message/stream
엔드포인트를 호출합니다.DefaultRequestHandler
는HelloWorldAgentExecutor.execute
메서드를 호출합니다. execute
메서드는 "Hello World" 메시지 하나를 큐에 넣고, 그 후 이벤트 큐가 닫힙니다.- 클라이언트는 이 단일 메시지를 하나의
SendStreamingMessageResponse
이벤트로 수신한 다음 스트림이 종료됩니다. stream_response
는AsyncGenerator
입니다.
- 이 메서드는 에이전트의
예상 출력¶
test_client.py
를 실행하면 다음에 대한 JSON 출력을 볼 수 있습니다:
- 비스트리밍 응답 (단일 "Hello World" 메시지).
- 스트리밍 응답 (하나의 청크로 된 단일 "Hello World" 메시지, 그 후 스트림 종료).
출력의 id
필드는 실행할 때마다 달라집니다.
// 비스트리밍 응답
{"jsonrpc":"2.0","id":"xxxxxxxx","result":{"type":"message","role":"agent","parts":[{"type":"text","text":"Hello World"}],"messageId":"yyyyyyyy"}}
// 스트리밍 응답 (하나의 청크)
{"jsonrpc":"2.0","id":"zzzzzzzz","result":{"type":"message","role":"agent","parts":[{"type":"text","text":"Hello World"}],"messageId":"wwwwwwww","final":true}}
(실제 ID xxxxxxxx
, yyyyyyyy
, zzzzzzzz
, wwwwwwww
등은 다른 UUID/요청 ID가 됩니다)
이는 여러분의 서버가 업데이트된 SDK 구조로 기본적인 A2A 상호 작용을 올바르게 처리하고 있음을 확인시켜 줍니다!
이제 __main__.py
가 실행 중인 터미널 창에서 Ctrl+C를 입력하여 서버를 종료할 수 있습니다.