Weather Agent 서버 구축부터 Consuming Agent(클라이언트) 호출까지
이번 실습은 상당히 중요한 단계입니다.
앞서 만든 Weather Agent를 단순히 하나의 AI 에이전트로 실행하는 데서 끝나는 것이 아니라, 독립적인 서버에서 실행되는 에이전트를 다른 AI 에이전트가 원격으로 발견하고 호출하여 자신의 업무에 활용하는 구조를 완성한 것입니다.
이번 실습의 전체 주제는 다음과 같습니다.
Google ADK로 Weather Agent를 만들고, A2A 프로토콜을 통해 독립적인 원격 에이전트로 공개한 다음, 별도의 Travel Agent가 이를 호출하여 여행 안내 업무를 수행하도록 만든다.
이 과정을 서버, Agent Card, Skill, Client, RemoteA2aAgent, Manager Agent의 관점에서 차근차근 정리하겠습니다.
1. 먼저 전체 시스템 구조 이해하기
우리가 구축한 시스템에는 크게 두 개의 에이전트가 있습니다.
-
Weather Agent: 날씨 정보를 전문적으로 검색하고 분석하는 원격 에이전트
-
Travel Agent: 사용자와 대화하며 여행 정보를 제공하고, 날씨 정보가 필요할 때 Weather Agent를 호출하는 클라이언트 에이전트
전체 구조를 그림으로 표현하면 다음과 같습니다.

여기서 가장 중요한 개념은 Travel Agent와 Weather Agent가 서로 다른 프로세스에서 독립적으로 실행될 수 있다는 것입니다.
Travel Agent는 Weather Agent의 내부 Python 코드를 직접 실행하지 않습니다. A2A 통신을 통해 원격 에이전트에게 작업을 요청합니다. 이것이 A2A의 핵심입니다.
2. 전체 실습 환경과 디렉터리 구성
현재 사용하고 있는 프로젝트 경로를 기준으로 설명하겠습니다.
C:\Dev\book_agentic_ai\
│
├── venv\
│
└── adk_\
│
├── remote_weather_agent\
│ ├── __init__.py
│ └── agent.py
│
└── travel_agent\
├── __init__.py
└── agent.py
각 디렉터리의 역할은 다음과 같습니다.
| 디렉터리 및 파일 | 역할 |
| venv | Python 가상환경 |
| remote_weather_agent | 원격 날씨 에이전트 패키지 |
| remote_weather_agent/agent.py | 날씨 에이전트 및 A2A 서버 정의 |
| travel_agent | 여행 안내 에이전트 패키지 |
| travel_agent/agent.py | 원격 에이전트를 소비하는 클라이언트 정의 |
__init__.py는 Python이 해당 디렉터리를 패키지로 인식하도록 하는 파일입니다.
두 에이전트는 같은 가상환경을 사용해도 되지만, 실행 프로세스는 별도로 구동합니다.

3. 서버 에이전트 구축: Weather Agent
이제 첫 번째 에이전트인 Weather Agent를 살펴보겠습니다.
3-1. 서버 에이전트의 역할
Weather Agent는 다음 업무를 담당합니다.
-
사용자가 요청한 도시를 파악합니다.
-
Google Search를 사용하여 최신 날씨 정보를 검색합니다.
-
기온, 습도, 풍속, 강수 확률 등을 분석합니다.
-
날씨에 적합한 옷차림 정보를 제공합니다.
-
A2A 프로토콜을 통해 외부 에이전트에 결과를 전달합니다.
여기서 중요한 점은 Weather Agent가 사용자와 직접 대화하는 주 에이전트가 아니라, 특정 전문 업무를 수행하고 다른 에이전트에 서비스를 제공하는 전문 에이전트라는 것입니다.
3-2. Agent 정의
기본적인 에이전트 코드는 다음과 같습니다.
weather_agent = Agent(
model=os.getenv("GOOGLE_MODEL", "gemini-3.5-flash"),
name="weather_agent",
tools=[google_search],
description="""
이 에이전트는 실시간 Google 검색을 통해
전 세계 도시의 최신 날씨 정보를 제공합니다.
현재 기온, 습도, 풍속 및 향후 일기 예보를 제공합니다.
""",
instruction="""
너는 기상 정보 전문가야.
1. 사용자가 요청한 도시의 날씨를 google_search를 사용하여 검색해.
2. 검색 결과에서 현재 기온, 강수 확률, 옷차림 권장 사항을 요약해서 알려줘.
3. 항상 친절하고 신뢰감 있는 톤으로 답변해.
"""
)
각 항목을 살펴보겠습니다.
| 코드 | 의미 |
| model | 에이전트가 사용하는 LLM |
| name | 에이전트의 내부 식별 이름 |
| tools | 에이전트가 사용할 수 있는 도구 |
| description | 에이전트의 역할 설명 |
| instruction | 에이전트가 업무를 수행하는 구체적인 지침 |
특히 tools=[google_search]가 중요합니다.
Gemini 모델 자체가 실시간 날씨 데이터를 가지고 있는 것은 아닙니다. Google Search Tool을 사용하여 최신 정보를 검색하도록 구성한 것입니다.
또한 description과 instruction은 서로 역할이 다릅니다.
-
description: 다른 에이전트나 ADK가 이 에이전트의 용도를 이해하는 데 도움을 주는 설명
-
instruction: 실제 에이전트의 행동과 업무 수행 방식을 지시하는 내용
3-3. Agent Skill 정의
이번 실습에서 한 단계 더 발전시킨 부분입니다.
우리는 Weather Agent에 두 가지 Skill을 부여했습니다.
from a2a.types import AgentSkill
weather_skill = AgentSkill(
id="realtime_weather_lookup",
name="실시간 기상 관측",
description="Google Search를 활용하여 특정 지역의 현재 기온, 습도, 풍속 정보를 실시간으로 추출합니다.",
tags=["weather", "realtime", "search"]
)
clothing_skill = AgentSkill(
id="clothing_recommendation",
name="기온별 의복 추천",
description="현재 기상 조건에 최적화된 옷차림과 여행 준비물 리스트를 제안합니다.",
tags=["lifestyle", "travel_tips"]
)
AgentSkill은 에이전트가 제공하는 전문 기능을 선언하는 명세입니다.
각 항목의 의미는 다음과 같습니다.
| 필드 | 의미 | 예시 |
| id | Skill의 고유 식별자 | realtime_weather_lookup |
| name | 사람이 이해하기 쉬운 이름 | 실시간 기상 관측 |
| description | 구체적인 업무 설명 | 현재 기온과 습도 검색 |
| tags | 검색과 분류를 위한 키워드 | weather, realtime |
여기서 중요한 사실이 하나 있습니다.
AgentSkill을 두 개 정의했다고 해서 실제 기능이 자동으로 두 개 생성되는 것은 아닙니다.
실제 기능은 ADK Agent의 instruction과 tools가 수행합니다. AgentSkill은 다른 에이전트에게 해당 전문 기능을 알리는 메타데이터입니다.
따라서 실제 구현 기능과 Agent Card의 Skill 명세가 서로 일치하도록 관리해야 합니다.
3-4. Custom Agent Card 구성
Agent Card는 이번 실습의 핵심 중 하나입니다.
쉽게 말하면 다른 에이전트가 Weather Agent를 이해하기 위해 참조하는 에이전트 종합 명세서입니다.
우리가 만든 Agent Card에는 다음 정보가 들어갑니다.
-
에이전트 이름
-
에이전트 설명
-
버전
-
통신 인터페이스
-
지원하는 기능
-
입출력 데이터 형식
-
전문 Skill
A2A SDK 1.0의 구조를 기준으로 살펴보겠습니다.
먼저 AgentInterface입니다.
from a2a.types import AgentInterface
weather_interface = AgentInterface(
url="http://localhost:10000/",
protocol_binding="JSONRPC",
protocol_version="1.0",
)
이 부분은 원격 에이전트와 통신하는 방법을 정의합니다.
| 항목 | 의미 |
| url | A2A 요청을 전달할 서버 주소 |
| protocol_binding | 통신 프로토콜 |
| protocol_version | 사용하는 A2A 프로토콜 버전 |
JSONRPC는 JSON 형식의 요청과 응답을 사용하는 RPC 통신 방식입니다.
다음은 Capabilities입니다.
from a2a.types import AgentCapabilities
weather_capabilities = AgentCapabilities(
streaming=False,
push_notifications=False,
extended_agent_card=False,
)
각 항목은 다음과 같습니다.
-
streaming=False: 실시간 스트리밍 방식의 응답을 지원하지 않는다고 선언
-
push_notifications=False: 푸시 알림 기능을 사용하지 않는다고 선언
-
extended_agent_card=False: 인증된 확장 Agent Card 기능을 사용하지 않는다고 선언
여기서 extended_agent_card는 일반적인 Agent Card 자체를 제공하지 않는다는 뜻이 아닙니다. 일반 Agent Card는 그대로 제공됩니다.
마지막으로 전체 Agent Card를 구성합니다.
custom_card = AgentCard(
name="AdvancedWeatherExpert",
version="1.0.0",
description="검색 기반의 실시간 날씨 분석 및 라이프스타일 큐레이션 전문 에이전트입니다.",
supported_interfaces=[weather_interface],
capabilities=weather_capabilities,
skills=[
weather_skill,
clothing_skill,
],
default_input_modes=["text/plain"],
default_output_modes=["text/plain"],
)
A2A SDK 1.0에서 중요한 변화는 기존 url 필드가 supported_interfaces로 이동했다는 것입니다. 또한 기존 supports_authenticated_extended_card가 capabilities.extended_agent_card로 변경되었습니다.
3-5. A2A 서버로 공개하기
이제 완성된 ADK 에이전트를 A2A 서버로 변환합니다.
from google.adk.a2a.utils.agent_to_a2a import to_a2a
root_agent = weather_agent
a2a_app = to_a2a(
root_agent,
port=10000,
agent_card=custom_card,
)
여기서 핵심은 to_a2a()입니다.
일반 ADK Agent를 다른 에이전트가 A2A 프로토콜로 호출할 수 있도록 변환하는 역할을 합니다.
내부적으로는 다음과 같은 작업을 처리합니다.
-
ADK Agent를 A2A Executor와 연결합니다.
-
A2A 요청을 ADK Agent의 실행 과정으로 전달합니다.
-
Task 처리와 상태 관리를 위한 구성 요소를 준비합니다.
-
Agent Card와 A2A 통신 라우트를 제공하는 애플리케이션을 구성합니다.
즉, 직접 JSON-RPC 서버를 모두 구현하지 않아도 됩니다.
a2a_app은 서버 애플리케이션 객체입니다. 이 코드만 실행한다고 네트워크 서버가 시작되는 것은 아닙니다.
실제 서버 실행은 Uvicorn이 담당합니다.
3-6. 서버 전체 코드 정리
지금까지 설명한 내용을 하나의 파일로 정리하면 다음과 같습니다.
# remote_weather_agent/agent.py
import os
from dotenv import load_dotenv
# 1. 환경변수 로드
load_dotenv(override=True)
# 2. ADK 모듈
from google.adk import Agent
from google.adk.tools import google_search
from google.adk.a2a.utils.agent_to_a2a import to_a2a
# 3. A2A 모듈
from a2a.types import (
AgentCard,
AgentSkill,
AgentInterface,
AgentCapabilities,
)
# =========================================================
# 4. Agent Skill 정의
# =========================================================
weather_skill = AgentSkill(
id="realtime_weather_lookup",
name="실시간 기상 관측",
description=(
"Google Search를 활용하여 특정 지역의 "
"현재 기온, 습도, 풍속 정보를 추출합니다."
),
tags=["weather", "realtime", "search"],
)
clothing_skill = AgentSkill(
id="clothing_recommendation",
name="기온별 의복 추천",
description=(
"현재 기상 조건에 최적화된 옷차림과 "
"여행 준비물 리스트를 제안합니다."
),
tags=["lifestyle", "travel_tips"],
)
# =========================================================
# 5. Agent Interface 정의
# =========================================================
weather_interface = AgentInterface(
url="http://localhost:10000/",
protocol_binding="JSONRPC",
protocol_version="1.0",
)
# =========================================================
# 6. Agent Capabilities 정의
# =========================================================
weather_capabilities = AgentCapabilities(
streaming=False,
push_notifications=False,
extended_agent_card=False,
)
# =========================================================
# 7. Agent Card 정의
# =========================================================
custom_card = AgentCard(
name="AdvancedWeatherExpert",
version="1.0.0",
description=(
"검색 기반의 실시간 날씨 분석 및 "
"라이프스타일 큐레이션 전문 에이전트입니다."
),
supported_interfaces=[weather_interface],
capabilities=weather_capabilities,
skills=[weather_skill, clothing_skill],
default_input_modes=["text/plain"],
default_output_modes=["text/plain"],
)
# =========================================================
# 8. ADK Weather Agent 정의
# =========================================================
weather_agent = Agent(
model=os.getenv("GOOGLE_MODEL", "gemini-3.5-flash"),
name="weather_agent",
tools=[google_search],
description="""
실시간 Google 검색을 통해 전 세계 도시의
최신 날씨 정보를 제공하는 전문 에이전트입니다.
""",
instruction="""
너는 기상 정보 전문가야.
1. 사용자가 요청한 도시의 날씨를 google_search로 검색해.
2. 현재 기온, 습도, 풍속, 강수 확률을 확인해.
3. 옷차림과 여행 준비물도 추천해.
4. 친절하고 신뢰감 있는 톤으로 답변해.
"""
)
# =========================================================
# 9. A2A Root Agent
# =========================================================
root_agent = weather_agent
# =========================================================
# 10. A2A 서버 애플리케이션 생성
# =========================================================
a2a_app = to_a2a(
root_agent,
port=10000,
agent_card=custom_card,
)
3-7. 서버 실행
PowerShell 터미널에서 다음 명령을 실행합니다.
cd C:\Dev\book_agentic_ai\adk_
uvicorn remote_weather_agent.agent:a2a_app --host localhost --port 10000
여기서 명령어를 해석해 보겠습니다.
| 명령어 | 의미 |
| uvicorn | ASGI 서버 실행 |
| remote_weather_agent.agent | Python 패키지와 모듈 |
| :a2a_app | 해당 모듈에서 가져올 애플리케이션 객체 |
| --host localhost | 로컬 호스트에서 실행 |
| --port 10000 | 10000번 포트 사용 |
서버가 정상적으로 시작되면 다음과 비슷한 메시지가 나타납니다.
INFO: Started server process
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on
http://localhost:10000
이제 Weather Agent는 원격 호출을 받을 준비가 된 것입니다.
4. Agent Card 확인: 원격 에이전트의 명함
서버가 실행되면 브라우저에서 다음 주소를 열어봅니다.
http://localhost:10000/.well-known/agent-card.json
이 주소가 중요한 이유는 A2A Client가 원격 에이전트의 정보를 자동으로 확인하는 데 활용되기 때문입니다.
우리가 만든 Agent Card의 핵심 내용은 다음과 같습니다.

위는 실제 JSON의 내용을 이해하기 위한 요약 화면입니다.
여기서 기억할 것은 다음과 같습니다.
Agent Card는 에이전트의 기능을 설명하지만, 실제 업무 수행 로직을 담고 있는 것은 아닙니다.
실제 업무 로직은 Weather Agent의 Python 코드에 있습니다.
5. 클라이언트 에이전트 구축: Travel Agent
이제 두 번째 에이전트인 Travel Agent를 살펴보겠습니다.
여기서부터가 이번 실습의 가장 중요한 부분입니다.
앞에서는 Weather Agent를 외부에서 호출할 수 있도록 서버로 공개했습니다. 이제 그 서버를 다른 에이전트가 실제로 사용하도록 만드는 것입니다.
5-1. Consuming Agent란?
Consuming Agent는 말 그대로 다른 에이전트가 제공하는 기능을 소비하는 에이전트입니다.
우리 실습에서는 다음과 같습니다.
| 구분 | Weather Agent | Travel Agent |
| 역할 | 날씨 전문 업무 수행 | 여행 안내 업무 수행 |
| 위치 | 원격 서버 | 클라이언트 측 |
| 실행 포트 | 10000 | ADK Web 기본 8000 |
| 주요 기능 | 날씨 검색 및 분석 | 여행 관련 질문 응답 |
| 통신 관계 | 요청을 받는 측 | 요청을 보내는 측 |
| ADK 구성 | Agent | Agent + RemoteA2aAgent |
여기서 중요한 개념은 Travel Agent가 Weather Agent의 내부 구현을 알 필요가 없다는 점입니다.
Travel Agent는 Agent Card를 통해 상대방의 정보를 확인하고, A2A 프로토콜로 업무를 요청하면 됩니다.
5-2. RemoteA2aAgent란?
먼저 가장 중요한 코드를 살펴보겠습니다.
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
remote_weather = RemoteA2aAgent(
name="remote_weather_agent",
description="Google Search를 통해 실시간 기상 정보를 가져오는 원격 에이전트",
agent_card="http://localhost:10000/.well-known/agent-card.json",
)
RemoteA2aAgent는 Google ADK에서 제공하는 원격 A2A 에이전트 연결 기능입니다.
쉽게 설명하면 다음과 같습니다.
일반적인 ADK 에이전트는 로컬에 정의된 다른 에이전트를 sub_agents로 등록할 수 있습니다.
그런데 상대방이 다른 서버에서 실행되고 있다면 어떻게 해야 할까요?
이때 사용하는 것이 RemoteA2aAgent입니다.
이를 통해 원격 에이전트를 마치 로컬 하위 에이전트처럼 ADK의 멀티 에이전트 구조에 편입할 수 있습니다.
각 항목을 하나씩 살펴보겠습니다.
① name
name="remote_weather_agent"
Travel Agent 내부에서 사용할 원격 에이전트의 이름입니다.
이 이름은 원격 서버에 있는 weather_agent라는 이름과 반드시 같을 필요는 없습니다.
즉, 다음과 같이 구분됩니다.
-
서버 내부 ADK 이름: weather_agent
-
클라이언트에서 사용하는 이름: remote_weather_agent
-
Agent Card에 표시되는 이름: AdvancedWeatherExpert
세 이름은 각각 다른 목적을 가지고 있습니다.
② description
description="Google Search를 통해 실시간 기상 정보를 가져오는 원격 에이전트"
Travel Agent가 이 하위 에이전트의 역할을 이해하도록 설명하는 부분입니다.
여행과 관련된 질문 중 날씨 정보가 필요한 경우 이 에이전트를 선택하도록 유도하는 데 도움이 됩니다.
③ agent_card
agent_card="http://localhost:10000/.well-known/agent-card.json"
이 부분이 가장 중요합니다.
원격 에이전트의 Agent Card가 제공되는 주소입니다.
RemoteA2aAgent는 이 정보를 바탕으로 원격 에이전트의 명세를 확인하고 통신할 수 있도록 구성됩니다.
즉, 클라이언트가 상대방의 접속 주소와 능력을 알아내는 출발점입니다.
여기서 Agent Card는 미리 작성한 종합 명세서이고, RemoteA2aAgent는 그 명세서를 이용해 실제 원격 에이전트와 연결하는 ADK 구성 요소라고 이해하면 됩니다.
5-3. Travel Agent 정의
이제 실제 사용자와 대화할 Travel Agent를 만듭니다.
travel_agent = Agent(
model=os.getenv("GOOGLE_MODEL", "gemini-3.5-flash"),
name="root_agent",
instruction="""
너는 여행 가이드 비서야.
1. 사용자가 특정 지역의 날씨나 여행 적합성을 물어보면
remote_weather_agent 에게 물어봐.
2. 해당 에이전트가 검색해 온 날씨 정보를 바탕으로
여행 짐 싸기 팁을 제공해줘.
""",
sub_agents=[remote_weather]
)
이 코드에서 중요한 것은 sub_agents입니다.
sub_agents=[remote_weather]
이것은 Travel Agent에게 RemoteA2aAgent를 하위 에이전트로 등록하는 것입니다.
즉, Travel Agent는 이제 자신이 직접 수행하는 여행 안내 업무와 원격 Weather Agent에게 위임하는 날씨 검색 업무를 함께 수행할 수 있습니다.
부모 에이전트와 자식 에이전트

여기서 한 가지 중요한 점이 있습니다.
sub_agents에 등록했다고 해서 모든 질문을 무조건 Weather Agent에게 전달하는 것은 아닙니다.
Travel Agent의 LLM이 사용자 질문과 각 하위 에이전트의 설명, instruction 등을 바탕으로 어떤 에이전트에게 위임할지 판단합니다.
따라서 instruction을 잘 작성해야 합니다.
예를 들어 다음과 같이 역할을 명확히 구분하면 좋습니다.
-
날씨 정보가 필요하면 Weather Agent에 위임한다.
-
여행 준비물이나 일정 구성은 Travel Agent가 담당한다.
-
날씨 검색 결과를 받은 뒤 여행 목적에 맞게 종합해서 답변한다.
이러한 방식이 ADK의 계층형 멀티 에이전트 구조입니다.
5-4. 클라이언트 전체 코드
이제 작성하신 코드를 조금 정리해 보겠습니다.
기존 코드에서 .env를 사용하는 경우에는 load_dotenv()도 먼저 실행하도록 추가하는 것이 좋습니다.
# travel_agent/agent.py
# =========================================================
# 1. 기본 모듈 및 환경변수
# =========================================================
import os
from dotenv import load_dotenv
load_dotenv(override=True)
# =========================================================
# 2. Google ADK 모듈
# =========================================================
from google.adk import Agent
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
# =========================================================
# 3. 원격 Weather Agent 연결
# =========================================================
remote_weather = RemoteA2aAgent(
name="remote_weather_agent",
description=(
"Google Search를 통해 실시간 기상 정보를 "
"가져오는 원격 에이전트"
),
agent_card=(
"http://localhost:10000/"
".well-known/agent-card.json"
),
)
# =========================================================
# 4. Travel Agent 정의
# =========================================================
travel_agent = Agent(
model=os.getenv("GOOGLE_MODEL", "gemini-3.5-flash"),
name="root_agent",
description=(
"여행지의 날씨 정보를 확인하고 "
"여행 준비와 옷차림을 안내하는 여행 가이드 에이전트"
),
instruction="""
너는 전문 여행 가이드 비서야.
[업무 지침]
1. 사용자가 특정 지역의 날씨, 기온, 강수 확률,
여행 적합성을 물어보면 반드시
remote_weather_agent에게 정보를 요청해.
2. 원격 에이전트가 검색해 온 날씨 정보를 바탕으로
여행지의 기상 조건을 설명해.
3. 날씨에 적합한 옷차림과 여행 짐 싸기 팁을 제공해.
4. 날씨 정보가 필요하지 않은 일반적인 여행 질문은
직접 답변해.
5. 검색된 정보와 확인되지 않은 정보를 구분하고
친절하고 실용적으로 답변해.
""",
sub_agents=[remote_weather],
)
# =========================================================
# 5. ADK 진입점
# =========================================================
root_agent = travel_agent
여기서 root_agent는 ADK가 실행할 진입점입니다.
앞서 서버 코드에서도 root_agent라는 이름을 사용했고, 이번 클라이언트 코드에서도 동일하게 사용했습니다.
하지만 두 파일은 서로 다른 Python 모듈이기 때문에 이름이 같아도 충돌하지 않습니다.
-
remote_weather_agent.agent.root_agent
-
travel_agent.agent.root_agent
각각 독립된 에이전트의 진입점입니다.
6. 실제 실행 과정: 서버와 클라이언트 구동
이제 실제로 어떻게 실행하는지 살펴보겠습니다.
이번 실습에서는 반드시 두 개의 터미널을 사용해야 합니다.
터미널 1 — Weather Agent 서버
cd C:\Dev\book_agentic_ai\adk_
uvicorn remote_weather_agent.agent:a2a_app --host localhost --port 10000
터미널 2 — Travel Agent 클라이언트
cd C:\Dev\book_agentic_ai\adk_
adk web --port 8000
두 서버를 별도로 실행하는 이유가 있습니다.
-
Uvicorn은 원격 Weather Agent의 A2A 요청을 받습니다.
-
ADK Web은 사용자가 Travel Agent와 대화할 수 있는 인터페이스를 제공합니다.
ADK Web을 실행하면 브라우저에서 다음 주소로 접속합니다.
http://localhost:8000
앱 선택 화면에서 travel_agent를 선택합니다.
Google ADK 공식 A2A 실습에서도 원격 에이전트 서버와 Consuming Agent를 서로 다른 포트에서 실행하는 방식을 사용합니다.
실행 순서가 중요합니다.
-
먼저 Weather Agent 서버를 실행합니다.
-
Agent Card 주소가 정상적으로 열리는지 확인합니다.
-
그다음 Travel Agent를 실행합니다.
-
ADK Web에서 Travel Agent와 대화합니다.
참고로 현재 localhost 주소는 동일 PC에서만 통신할 수 있는 테스트용입니다. 나중에 서버를 서로 다른 PC나 클라우드에 배포할 때는 Agent Card의 URL을 실제 접근 가능한 서버 주소로 변경해야 합니다.
7. 실제 동작 원리: 사용자가 질문하면 어떤 일이 벌어질까?
이제 이번 실습의 가장 중요한 부분입니다.
사용자가 Travel Agent에게 다음과 같이 질문했다고 가정하겠습니다.
이번 주말 제주도 여행을 가려고 해. 날씨가 어떨까? 어떤 옷을 준비해야 할까?
이 질문을 받은 후 내부적으로 어떤 일이 일어나는지 순서대로 살펴보겠습니다.
-
사용자가 Travel Agent에 질문
이번 주말 제주도 날씨와 여행 옷차림을 알려줘.Travel Agent가 사용자 질문을 전달받습니다.
-
Travel Agent가 업무를 판단
Gemini 모델은 instruction을 참고하여 날씨 정보가 필요하다고 판단합니다.
자신의 하위 에이전트인 remote_weather_agent에 업무를 위임합니다.
-
RemoteA2aAgent가 원격 서버와 통신
A2A 클라이언트는 Agent Card에 기재된 인터페이스를 확인하고 원격 Weather Agent에 요청을 전달합니다.
이때 HTTP 기반 JSON-RPC 통신이 사용됩니다.
-
Weather Agent가 요청을 처리
원격 서버에서 실행 중인 Weather Agent가 요청을 받아 Gemini 모델과 Google Search Tool을 활용하여 제주도 날씨를 검색합니다.
-
Weather Agent가 결과 반환
검색 결과를 바탕으로 날씨 정보를 정리하여 A2A 응답으로 반환합니다.
요청이 Task로 처리되는 경우 Task 상태와 최종 응답 메시지 등을 통해 처리 결과를 전달합니다.
-
Travel Agent가 결과를 종합
Travel Agent는 반환된 날씨 정보를 활용하여 옷차림, 우산, 여행 준비물 등을 종합합니다.
-
최종 결과를 사용자에게 전달
사용자는 Weather Agent와 직접 통신하지 않았지만, Travel Agent를 통해 전문 날씨 에이전트의 정보를 활용한 답변을 받게 됩니다.
여기서 꼭 이해해야 할 것은 Travel Agent가 Weather Agent의 응답을 받아 자신의 업무에 활용한다는 점입니다.
Weather Agent가 단순히 검색 결과만 반환하고 끝나는 것이 아니라, Travel Agent가 그 결과를 활용하여 새로운 가치를 만들어 내는 것입니다.
7-1. 통신 흐름을 기술적으로 이해하기
조금 더 기술적인 관점에서 보면 다음과 같습니다.
| 순서 | 통신 및 처리 | 담당 |
| 1 | Agent Card 조회 | A2A Client |
| 2 | 사용자 질문 분석 | Travel Agent |
| 3 | 원격 에이전트 선택 | ADK LLM |
| 4 | JSON-RPC 요청 | RemoteA2aAgent |
| 5 | 요청 수신 및 Task 실행 | A2A Server |
| 6 | Google Search 실행 | Weather Agent |
| 7 | Task 결과 반환 | A2A Server |
| 8 | 결과 종합 및 응답 | Travel Agent |
여기서 주의할 점은 Agent Card 조회와 실제 날씨 요청이 서로 다른 과정이라는 것입니다.
-
Agent Card 조회: 원격 에이전트가 누구인지, 무엇을 할 수 있는지 확인
-
A2A 요청: 실제 업무를 수행하도록 요청
또한 Agent Card에 기록된 Skill은 기능을 설명하는 메타데이터이지, 그 자체가 실행 명령은 아닙니다.
8. 직접 테스트해 볼 질문 5가지
이제 Travel Agent가 실제로 원격 Weather Agent를 호출하는지 확인해 봅시다.
다음 질문들을 순서대로 입력해 보세요.
테스트 1. 날씨 조회
목적: 원격 에이전트 호출 확인
"오늘 서울 날씨가 어때?"
테스트 2. 여행 적합성 판단
목적: 날씨 검색 결과를 이용한 종합 판단
"이번 주말 제주도 여행하기 좋을까?"
테스트 3. 옷차림 추천
목적: 원격 에이전트 결과를 활용한 후속 업무
"내일 부산에 가는데 어떤 옷을 입으면 좋을까?"
테스트 4. 여러 도시 비교
목적: 복수 지역에 대한 원격 검색과 종합
"서울과 제주도의 날씨를 비교하고 여행 준비물을 추천해줘."
테스트 5. 원격 에이전트가 필요 없는 질문
목적: Travel Agent의 자체 응답 능력 확인
"여행 가방을 효율적으로 싸는 방법을 알려줘."
테스트 1~4에서는 원격 에이전트 호출이 이루어지는지 확인하고, 테스트 5에서는 원격 호출 없이 Travel Agent가 자체적으로 답변하는지 확인합니다.
다만 LLM의 위임 판단은 확률적이므로, 실제로 호출했는지는 ADK 실행 로그와 원격 서버 로그를 함께 확인하는 것이 좋습니다.
9. 이번 실습에서 반드시 이해해야 할 핵심 기술 6가지
이번 과정을 공부하면서 다음 개념들을 정리해 두면 앞으로 MCP, A2A, 멀티 에이전트 시스템을 공부하는 데 큰 도움이 됩니다.
| 기술 및 개념 | 이번 실습에서의 역할 |
| Google ADK Agent | 개별 AI 에이전트 구현 |
| AgentSkill | 에이전트의 전문 업무 명세 |
| AgentCard | 에이전트의 종합 정보 및 통신 명세 |
| A2A Protocol | 서로 다른 에이전트 간 통신 표준 |
| to_a2a() | ADK 에이전트를 A2A 서버로 공개 |
| RemoteA2aAgent | 원격 A2A 에이전트를 ADK 하위 에이전트로 연결 |
특히 to_a2a()와 RemoteA2aAgent의 차이를 확실하게 이해해야 합니다.

이것이 이번 A2A 실습의 가장 중요한 학습 포인트입니다.
10. MCP와 A2A의 차이도 함께 이해하기
앞으로 만들 Manager Agent → Weather Agent → Research Agent → Document Agent 구조를 생각하면 MCP와 A2A의 차이를 이해하는 것이 중요합니다.
| 구분 | MCP | A2A |
| 핵심 목적 | AI와 외부 도구 및 데이터 연결 | AI 에이전트 간 협업 |
| 연결 대상 | Tool, Resource, Prompt | 다른 AI Agent |
| 상대방의 역할 | 특정 기능 제공 | 독립적인 업무 수행 |
| 통신 및 구조 | MCP Client/Server | A2A Client/Server |
| 대표 사례 | 날씨 API 호출 | 날씨 전문 에이전트 호출 |
예를 들어 다음과 같은 구조가 가능합니다.

이 구조에서 A2A는 에이전트끼리 협업하는 통신 계층이고, MCP는 각 에이전트가 외부 도구와 데이터를 활용하는 연결 계층으로 생각할 수 있습니다.
물론 이것은 대표적인 아키텍처 패턴이며, 모든 시스템이 반드시 이 구조를 따라야 하는 것은 아닙니다.
11. 이번 실습의 최종 정리
이번 과정을 통해 다음과 같은 기술적 성과를 얻었습니다.
A2A 실습 완료 항목
1. A2A 서버 구축
ADK Agent + to_a2a() + Uvicorn
2. AgentSkill 정의
실시간 기상 관측 및 의복 추천
3. Custom Agent Card 작성
AgentCard + AgentInterface + Capabilities
4. Agent Card 공개
Well-Known Agent Card Endpoint
5. Consuming Agent 구축
RemoteA2aAgent + Travel Agent
6. 에이전트 간 통신
A2A 기반 원격 업무 위임 및 응답
* 참고 공식 문서:
'Agentic AI > Google ADK' 카테고리의 다른 글
| 29. 평가(4.x)- OpenTelemetry 패키지와 Google ADK 사이의 버전 의존성 충돌(Dependency Conflict) (0) | 2026.11.10 |
|---|---|
| 28. 평가(4)- 중앙집중형 관측 체계(Observability) (0) | 2026.11.10 |
| 27. 평가(3)- logging 모듈을 이용한 에이전트 실행과정 기록 (0) | 2026.11.08 |
| 26. 평가(2)- Evalset. ADK Web UI에서 평가 실행 통합테스트 (0) | 2026.11.08 |
| 25. 평가(1)- 테스트 파일(*.test.json) 단위 테스트(Unit Test) (0) | 2026.11.07 |