A2A vs ADK — 등록 모드 비교
Gemini Enterprise 에 에이전트를 등록할 때 자주 받는 질문: 이미 Agent Engine 에 deploy 한 ADK 에이전트를 A2A 모드로도 등록할 수 있나? 결론부터: 그대로는 안 됩니다. 두 모드는 호스팅·API·호출 메서드가 모두 다릅니다.
목차
1. 두 모드의 차이
| 구분 | ADK / Agent Engine | A2A |
|---|---|---|
| 호스팅 | Vertex AI 관리형 (reasoning engine) | Cloud Run / GKE / 자체 호스팅 |
| 호출 인터페이스 | Google 내부 메서드 (streaming_agent_run_with_events, stream_query) |
HTTPS + JSON-RPC 2.0 |
| Endpoint 형태 | projects/.../reasoningEngines/<ID> resource name |
일반 HTTPS URL + agent card (/.well-known/agent.json) |
| GE 등록 입력값 | resource name | HTTPS endpoint URL |
| 인증 | IAM (GE 서비스 에이전트 → Vertex AI) | OAuth / API key / mTLS |
| 빌드 | vertexai.agent_engines.create(AdkApp(agent)) |
A2A SDK 가 export 한 FastAPI 앱 |
| 표준 외부 클라이언트 호환 | ❌ (Google 전용) | ✅ (다른 회사 / open A2A 클라이언트가 호출 가능) |
같은 reasoning engine ID 를 GE 에 A2A 로 또 등록해도 API 스펙이 안 맞아서 실패 합니다.
2. 언제 어떤 모드를 쓰는가
🅐 ADK / Agent Engine 모드를 선택
- GE 안에서만 호출됨 (외부 시스템 호출 없음)
- Vertex AI 관리형의 운영 편의 (자동 스케일, 로깅, 모니터링) 가 중요
- 모델 / Vertex AI Search / RAG 와 같은 GCP 자원을 가까이서 호출
- 대부분의 PoC / 사내 에이전트는 이 모드
🅑 A2A 모드를 선택
- 외부 시스템 (다른 회사 / 표준 클라이언트) 이 같은 에이전트를 호출해야 함
- 다른 LLM 에이전트가 본 에이전트를 sub-agent / 협업 agent 로 호출
- Cloud Run / GKE 같은 컨테이너 플랫폼에서 이미 운영 중인 자원과 동거
- 인증을 OAuth / mTLS 등 표준 HTTP 패턴으로 통제하고 싶음
3. 같은 ADK 코드를 A2A 로도 노출하기
같은 root_agent 정의를 두 모드 모두에 노출하려면 두 가지 옵션:
🥇 옵션 A: to_a2a() 헬퍼 (권장)
google-adk 1.30+ 에서 ADK 에이전트를 A2A 호환 FastAPI 앱으로 export 하는 헬퍼 제공 (정확한 API 이름은 SDK 버전에 따라 to_a2a / A2aAdapter / a2a_server 중 하나 — python -c "from google.adk import a2a; print(dir(a2a))" 로 확인):
# scripts/deploy_a2a.py (개념)
from google.adk.a2a import to_a2a # 또는 A2aAdapter / a2a_server
# root_agent 는 deploy_agent.py 와 동일하게 정의
a2a_app = to_a2a(root_agent) # FastAPI 인스턴스 반환
# uvicorn 서버
if __name__ == "__main__":
import uvicorn
uvicorn.run(a2a_app, host="0.0.0.0", port=8080)
Cloud Run 배포:
gcloud run deploy my-agent-a2a \
--source . \
--region=<LOCATION> \
--no-allow-unauthenticated \
--service-account=<YOUR_SA>
GE 등록: A2A 모드 선택 → Cloud Run URL 입력.
장점: Agent Engine deploy 와 같은 코드 재사용. ADK feature (callback / planner / memory) 그대로 동작.
🥈 옵션 B: 얇은 A2A wrapper 가 Agent Engine 호출
이미 Agent Engine 에 deploy 한 reasoning engine 을 그대로 두고, 앞에 A2A 호환 FastAPI 서버를 띄워서 내부에서 reasoning engine 의 stream_query 를 호출:
# Cloud Run 컨테이너 내부
from fastapi import FastAPI
import vertexai
from vertexai import agent_engines
REASONING_ENGINE = "projects/.../reasoningEngines/<ID>"
engine = agent_engines.get(REASONING_ENGINE)
app = FastAPI()
@app.post("/")
async def a2a_invoke(req: dict):
# A2A JSON-RPC → reasoning engine query 변환 로직
user_text = extract_message(req)
chunks = []
for event in engine.stream_query(input=user_text, user_id="..."):
chunks.append(event)
return to_a2a_response(chunks)
장점: 기존 reasoning engine 자원 재활용 단점: 호출 hop 2단계 (A2A → wrapper → Agent Engine), latency 와 비용 증가, A2A spec 변환 코드 직접 작성
4. 선택 가이드
graph TD
Q[에이전트를 GE 에 등록하려고 함]
Q --> A{외부 시스템도 호출하나?}
A -->|아니오 — GE 만| ADK[ADK / Agent Engine 모드<br/>vertexai.agent_engines.create + AdkApp]
A -->|예| B{이미 Agent Engine 에 deploy 했나?}
B -->|예| C{비용 / latency 민감?}
C -->|예 — 단순한 게 좋음| OptA[옵션 A: to_a2a 로 별도 Cloud Run 배포]
C -->|아니오 — 자원 재활용 우선| OptB[옵션 B: A2A wrapper + 기존 reasoning engine]
B -->|아니오 — 처음부터 만듦| OptA
대부분의 시나리오에서 가장 단순한 선택은 옵션 A — 같은 ADK 코드를 Agent Engine 과 Cloud Run 두 곳에 deploy 하는 것입니다. 운영 자원이 두 배가 되지만 디버깅과 코드 관리가 가장 깔끔합니다.