AI 에이전트 프로토콜 개발자 가이드: MCP부터 A2A, UCP, AP2, A2UI, AG-UI까지 (feat. Google)

AI Agent Protocols 소개

최근 인공지능 분야에서 에이전트(Agent) 기술이 급격히 발전함에 따라, 개발자들은 MCP, A2A, UCP, AP2, A2UI, AG-UI 등 수많은 새로운 프로토콜과 약어들을 마주하고 있습니다. 이러한 다양한 표준 기술들이 마치 경쟁하는 것처럼 보일 수 있지만, 사실 각 프로토콜은 에이전트 시스템을 구축할 때 발생하는 고유한 문제들을 해결하기 위해 설계되었습니다. 이들은 개발자가 모든 데이터베이스 도구, 외부 API, 프런트엔드 구성 요소마다 맞춤형 통합 코드를 처음부터 작성하고 유지보수해야 하는 수고를 크게 덜어줍니다. 특히 다양한 시스템이 복잡하게 얽혀 있는 엔터프라이즈 환경이나 다단계 워크플로우를 처리해야 하는 서비스에서 그 진가가 발휘됩니다. 이 글에서는 구글이 제시하는 6가지 주요 에이전트 프로토콜의 역할과 실제 코드 적용 방식을 통해 개발자들이 어떻게 파편화된 통합 작업을 줄일 수 있는지 살펴봅니다.

구글은 이러한 프로토콜들의 실제 가치와 활용 방법을 입증하기 위해 자사의 Agent Development Kit(ADK)를 활용하여 식당을 위한 다단계 공급망 에이전트를 구축하는 사례를 소개했습니다. 식자재의 도매 주문을 처리하는 과정은 재고 데이터베이스 확인, 외부 공급업체 에이전트와의 통신, 안전한 결제 트랜잭션 실행, 그리고 실시간 대화형 대시보드 렌더링 등 다양한 기술적 요구사항을 포함하고 있기 때문에 테스트 케이스로 매우 적합합니다.

초기 단계에서는 아무런 외부 도구가 연결되지 않아 환각(Hallucination) 현상을 보이는 기본 대규모 언어 모델(LLM)에서 출발하게 됩니다. 하지만 여기에 6가지의 핵심 프로토콜을 하나씩 추가해 나가면서, 실제 데이터를 기반으로 재고를 조회하고 전문가의 견적을 받으며 결제를 승인할 수 있는 강력하고 유능한 에이전트로 진화하는 과정을 보여줍니다. 이를 통해 개발자들은 각 프로토콜의 명확한 역할과 시스템 경계를 이해하고, 프로젝트의 요구사항이 커지는 시점에 필요한 표준 기술만을 선별적으로 도입하여 효율적이고 확장 가능한 아키텍처를 설계할 수 있습니다.

Model Context Protocol (MCP): 데이터 및 시스템 연결

에이전트를 구축할 때 가장 먼저 직면하는 난관은 모델을 기존 시스템 및 데이터와 연결하는 작업입니다. 만약 주방 관리 에이전트가 재고를 확인하거나 공급업체에 이메일을 보내야 한다면, 기존 방식에서는 해당 서비스의 API 엔드포인트마다 수십 개의 맞춤형 도구를 작성하고 유지보수해야 했습니다.

Model Context Protocol(MCP) 은 수백 개의 서버를 위한 단일 표준 연결 패턴을 제공하여 이러한 번거로운 반복 작업을 제거합니다. 서버 측에서 사용 가능한 도구들을 광고하면, 에이전트가 이를 자동으로 발견하고 연결합니다. 특히, MCP 서버는 해당 시스템을 구축한 팀이 직접 유지보수하므로, 개발자는 별도의 통합 코드를 수정할 필요 없이 항상 최신 상태의 도구를 사용할 수 있습니다.

구글의 ADK는 McpToolset을 통해 이를 기본적으로 지원하며, PostgreSQL과 같은 데이터베이스용 Toolbox, 메뉴 및 식자재 목록 조회를 위한 Notion MCP, 공급업체 이메일 전송을 위한 Mailgun MCP 등을 손쉽게 연동할 수 있습니다.

from google.adk.agents import Agent
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams
from google.adk.tools.toolbox_toolset import ToolboxToolset
from mcp import StdioServerParameters

# 1. Inventory database - MCP Toolbox for Databases (PostgreSQL, SQLite, BigQuery, etc.)
inventory_tools = ToolboxToolset(server_url=TOOLBOX_URL)

# 2. Kitchen SOPs and recipes - Notion MCP (read menus, ingredient lists, supplier contacts)
notion_tools = McpToolset(connection_params=StdioConnectionParams(
    server_params=StdioServerParameters(
        command="npx", args=["-y", "@notionhq/notion-mcp-server"],
        env={"NOTION_TOKEN": NOTION_TOKEN}),
    timeout=30))

# 3. Email suppliers about orders - Mailgun MCP (send confirmations, track delivery)
mailgun_tools = McpToolset(connection_params=StdioConnectionParams(
    server_params=StdioServerParameters(
        command="npx", args=["-y", "@mailgun/mcp-server"],
        env={"MAILGUN_API_KEY": MAILGUN_API_KEY}),
    timeout=30))

kitchen_agent = Agent(
    model="gemini-3-flash-preview",
    name="kitchen_manager",
    instruction="You manage a restaurant kitchen. Check inventory, look up recipes, email suppliers.",
    tools=[inventory_tools, notion_tools, mailgun_tools],
)

MCP 더 알아보기

Google ADK를 사용하여 MCP 통합하기

Agent2Agent Protocol (A2A): 에이전트 간의 통신 표준화

MCP를 통해 데이터 접근 문제를 해결했다면, 그 다음 과제는 전문 지식의 연동입니다. 주방 관리 에이전트가 자체 재고는 파악할 수 있지만, 당일 도매가나 품질 등급, 배송 가능 시간과 같은 정보는 외부 프레임워크나 다른 팀이 만든 원격 에이전트가 보유하고 있을 확률이 높습니다.

Agent2Agent(A2A) 프로토콜은 에이전트가 서로를 발견하고 소통하는 방식을 표준화하여 이 문제를 해결합니다. 각 A2A 에이전트는 /.well-known/agent-card.json이라는 잘 알려진 URL 경로를 통해 자신의 이름, 기능, 엔드포인트 등을 명세한 '에이전트 카드(Agent Card)'를 발행합니다. 주방 관리 에이전트는 이 카드를 가져와 각 원격 에이전트의 역할을 학습하고, 런타임 환경에서 쿼리를 적절한 에이전트에게 라우팅합니다.

구글의 ADK가 제공하는 RemoteA2aAgent 클래스나 a2a-sdk를 활용하면 단순히 URL을 추가하는 것만으로 새로운 에이전트를 연동할 수 있어 수동 코드 변경이나 재배포 과정을 획기적으로 줄여줍니다.

# An A2A agent serves an Agent Card at /.well-known/agent-card.json:
# {
#   "name": "pricing_agent",
#   "description": "Checks today's wholesale market prices for food items.",
#   "skills": [{"id": "pricing", "name": "Price Check",
#               "description": "Check current wholesale market prices"}],
#   "url": "http://pricing-agent:8001/",
#   "version": "1.0.0"
# }

# EXPOSE: Turn any ADK agent into an A2A service
from google.adk.a2a.utils.agent_to_a2a import to_a2a
app = to_a2a(pricing_agent, port=8001)

# DISCOVER: Resolve the Agent Card and create a client - just a URL
from a2a.client.client_factory import ClientFactory
client = await ClientFactory.connect("http://pricing-agent:8001")
card = await client.get_card()
print(f"{card.name} - {card.description}")
# -> "pricing_agent - Checks today's wholesale market prices for food items."

# CALL: Send a message via the A2A protocol
from a2a.client.helpers import create_text_message_object
msg = create_text_message_object(content="What's today's wholesale price for salmon?")
async for response in client.send_message(msg):
    ...  # response is a Task (with artifacts) or a direct Message

A2A 프로토콜 더 알아보기

A2A 예시 프로젝트 저장소

Universal Commerce Protocol (UCP): 전자상거래 수명주기 표준화

외부 에이전트로부터 공급업체를 찾고 견적을 받는 단계까지 완료한 후, 실제 주문을 체결하려면 공급업체마다 각기 다른 결제 및 체크아웃 흐름을 통합해야 하는 문제가 발생합니다.

Universal Commerce Protocol(UCP) 은 전자상거래의 쇼핑 수명주기를 모듈식 기능으로 분리하고, 전송 방식(REST, MCP, A2A, 브라우저 환경의 EP 등)에 상관없이 일관성을 유지하는 강력한 타입(Strongly typed)의 요청 및 응답 스키마를 제공합니다. UCP를 적용하면 에이전트는 A2A와 동일한 URL 패턴(/.well-known/ucp)을 사용해 공급업체의 카탈로그 프로필을 탐색할 수 있습니다.

이후 CheckoutCreateRequest, LineItemCreateRequest 등의 정형화된 모델을 통해 체크아웃 요청을 조립하고, 일반적인 HTTP 클라이언트(예: httpx)를 사용해 범용적인 상거래 트랜잭션을 완료할 수 있습니다. 이 때, 별도의 독점적인 SDK를 강제하지 않는다는 점이 큰 장점입니다.

import httpx, uuid
from ucp_sdk.models.discovery.profile_schema import UcpDiscoveryProfile
from ucp_sdk.models.schemas.shopping.checkout_create_req import CheckoutCreateRequest
from ucp_sdk.models.schemas.shopping.types.line_item_create_req import LineItemCreateRequest
from ucp_sdk.models.schemas.shopping.types.item_create_req import ItemCreateRequest
from ucp_sdk.models.schemas.shopping.payment_create_req import PaymentCreateRequest

# DISCOVER: Parse the supplier's UCP profile
async with httpx.AsyncClient() as c:
    profile = UcpDiscoveryProfile.model_validate(
        (await c.get("http://example-wholesale:8182/.well-known/ucp")).json())

# ORDER: Build a typed checkout request
checkout_req = CheckoutCreateRequest(
    currency="USD",
    line_items=[
        LineItemCreateRequest(quantity=10, item=ItemCreateRequest(id="salmon")),
        LineItemCreateRequest(quantity=3,  item=ItemCreateRequest(id="olive_oil")),
    ],
    payment=PaymentCreateRequest(),
)

# SEND: Create checkout + complete (with required UCP headers)
# UCP-Agent header should point to your agent's capability profile
headers = {"UCP-Agent": 'profile="https://kitchen.example/agent"',
           "Idempotency-Key": str(uuid.uuid4()), "Request-Id": str(uuid.uuid4())}
async with httpx.AsyncClient() as c:
    checkout = (await c.post("http://example-wholesale:8182/checkout-sessions",
        json=checkout_req.model_dump(mode="json", by_alias=True, exclude_none=True),
        headers=headers)).json()
    headers["Idempotency-Key"] = str(uuid.uuid4())  # New Idempotency-Key per operation
    order = (await c.post(
        f"http://example-wholesale:8182/checkout-sessions/{checkout['id']}/complete",
        headers=headers)).json()

UCP 더 알아보기

ADK 기반의 UCP & A2A 샘플 저장소

Agent Payments Protocol (AP2): 안전한 결제 승인 및 감사 추적

주문 시스템이 마련되었더라도, 실제 자금이 결제되는 과정에는 "누가 이 지출을 승인했는가?"라는 중요한 보안 문제가 남습니다. 한도는 얼마인지, 승인 기한은 언제인지, 어떤 가맹점이 허용되는지에 대한 제어가 필수적입니다.

Agent Payments Protocol(AP2) 은 암호화된 증명과 타입화된 위임장(Mandates)을 통해 결제 승인에 대한 부인 방지(Non-repudiatable) 증거를 제공합니다. UCP가 '무엇을 누구에게 주문할 것인가'를 처리한다면, AP2는 그 주문 과정에 암호화된 승인 증명을 결합하는 확장(Extension) 역할을 합니다.

관리자는 지정된 가맹점과 한도를 포함한 IntentMandate를 구성하여 가드레일을 설정하고, 에이전트는 이에 기반해 특정 금액에 바인딩된 PaymentMandate를 생성합니다. 한도를 초과할 경우 관리자의 암호화 서명이 있을 때까지 보류되며, 최종적으로 PaymentReceipt를 통해 전체 거래의 감사 추적(Audit trail)을 완벽하게 남깁니다.

from ap2.types.mandate import IntentMandate, PaymentMandate, PaymentMandateContents
from ap2.types.payment_request import PaymentCurrencyAmount, PaymentItem, PaymentResponse
from ap2.types.payment_receipt import PaymentReceipt, Success

# The restaurant owner configures guardrails
intent = IntentMandate(
    natural_language_description="10 lbs salmon, 3 bottles olive oil",
    merchants=["Example Wholesale"],    # ONLY these suppliers
    requires_refundability=True,            # must be refundable
    user_cart_confirmation_required=False,  # auto-approve under limit
    intent_expiry="2026-02-23T20:00:00Z",   # expires in 1 hour
)

# Agent creates a PaymentMandate binding payment to the intent
mandate = PaymentMandate(payment_mandate_contents=PaymentMandateContents(
    payment_mandate_id="abc123",
    payment_details_id="order-001",
    payment_details_total=PaymentItem(
        label="10 lbs salmon + 3 bottles olive oil",
        amount=PaymentCurrencyAmount(currency="USD", value=294.00)),
    payment_response=PaymentResponse(request_id="order-001", method_name="CARD"),
    merchant_agent="Example Wholesale",
))

# Manager signs (simulated - real AP2 uses JWT/biometric on secure device)
mandate.user_authorization = "signed_hash_abc123"

# PaymentReceipt closes the audit trail
receipt = PaymentReceipt(
    payment_mandate_id="abc123", payment_id="PAY-001",
    amount=PaymentCurrencyAmount(currency="USD", value=294.00),
    payment_status=Success(merchant_confirmation_id="ORD-A1B2C3"),
)
# IntentMandate -> PaymentMandate (signed) -> PaymentReceipt
# Full audit trail: what was intended, authorized, and paid

AP2 더 알아보기

AP2 예시 저장소

Agent-to-User Interface Protocol (A2UI): 동적 사용자 인터페이스 구성

이제 에이전트가 재고를 확인하고 주문, 결제까지 수행할 수 있게 되었지만, 이를 사용자에게 보여주기 위해 텍스트만으로는 한계가 있습니다. 주문 양식, 재고 대시보드 등을 렌더링하려면 매번 새로운 프런트엔드 코드를 작성해야 합니다.

Agent-to-User Interface Protocol(A2UI) 은 에이전트가 18개의 안전한 컴포넌트 프리미티브(예: CheckBox, TextField, Card 등) 카탈로그 내에서 새로운 형태의 레이아웃을 동적으로 구성할 수 있도록 지원합니다. UI의 '구조'와 기반 '데이터'를 분리하여 선언적인 JSON 형식으로 클라이언트 측에 전송하며, Lit, Flutter, Angular와 같은 프레임워크 렌더러가 이를 네이티브 UI로 변환합니다.

# This is what the agent sends. A renderer (Lit, Flutter, Angular) turns it into native UI.

a2ui_messages = [
    # 1. Create a rendering surface
    {"beginRendering": {"surfaceId": "default", "root": "card"}},

    # 2. Send the component tree (flat list, ID references - not nested)
    {"surfaceUpdate": {"surfaceId": "default", "components": [
        {"id": "card", "component": {"Card": {"child": "col"}}},
        {"id": "col", "component": {"Column": {"children": {"explicitList": ["title", "price", "buy"]}}}},
        {"id": "title", "component": {"Text": {"usageHint": "h3", "text": {"path": "name"}}}},
        {"id": "price", "component": {"Text": {"text": {"path": "price"}}}},
        {"id": "buy", "component": {"Button": {"child": "btn-label", "action": {"name": "purchase",
            "context": [{"key": "item", "value": {"path": "name"}}]}}}},
        {"id": "btn-label", "component": {"Text": {"text": {"literalString": "Buy Now"}}}},
    ]}},

    # 3. Send the data (separate from structure - update data without resending components)
    {"dataModelUpdate": {"surfaceId": "default", "contents": [
        {"key": "name",  "valueString": "Fresh Atlantic Salmon"},
        {"key": "price", "valueString": "$24.00/lb"},
    ]}},
]

ADK의 웹 인터페이스(adk web)는 별도의 커스텀 렌더러 구축 없이도 A2UI를 자체적으로 렌더링할 수 있어 개발 생산성을 크게 높여줍니다.

A2UI 더 알아보기

A2UI 예시 프로젝트

A2UI 위젯 빌더

Agent-User Interaction Protocol (AG-UI): 실시간 스트리밍 상호작용

에이전트 시스템은 단순히 요청에 응답하고 끝나는 전통적인 REST API와 다릅니다. 에이전트는 텍스트를 점진적으로 스트리밍하고, 도중에 도구(Tool)를 호출하며, 때로는 사람의 입력을 기다리기 위해 대기해야 합니다. 프런트엔드에서 이러한 원시 이벤트를 직접 파싱하는 코드는 변경에 취약하고 보일러플레이트가 많습니다.

Agent-User Interaction Protocol(AG-UI) 은 이러한 원시 프레임워크 이벤트를 표준화된 SSE(Server-Sent Events) 스트림으로 변환해 주는 미들웨어 프로토콜입니다. 프런트엔드는 어떤 에이전트 프레임워크가 응답을 생성했는지 알 필요 없이, TEXT_MESSAGE_CONTENT, TOOL_CALL_START와 같은 타입화된 표준 이벤트를 수신하여 처리하면 됩니다. ADK 생태계에서는 ag_ui_adk 패키지를 통해 에이전트를 래핑하고 FastAPI 애플리케이션에 손쉽게 마운트할 수 있습니다.

from ag_ui_adk import ADKAgent, add_adk_fastapi_endpoint
from fastapi import FastAPI

# Wrap the agent, create the app, mount the endpoint
ag_ui_agent = ADKAgent(adk_agent=kitchen_mgr, app_name="kitchen", user_id="chef")
app = FastAPI()
add_adk_fastapi_endpoint(app, ag_ui_agent, path="/")
# Run with: uvicorn module:app

# The SSE stream emits typed events:
#   RUN_STARTED
#   TOOL_CALL_START    toolCallName="check_inventory"
#   TOOL_CALL_RESULT   content="3 lbs in stock, REORDER NEEDED"
#   TOOL_CALL_END
#   TEXT_MESSAGE_CONTENT  delta="Based on "
#   TEXT_MESSAGE_CONTENT  delta="current inventory..."
#   RUN_FINISHED

AG-UI 더 알아보기

AG-UI 예시 프로젝트

6가지 프로토콜을 모두 통합한 에이전트의 실제 동작 모습

위에서 설명한 6가지 핵심 프로토콜이 모두 통합된 주방 관리 에이전트는 사용자의 단 한 번의 복잡한 요청을 어떻게 처리하는지 살펴보겠습니다.

사용자의 복잡한 요청 처리 흐름

사용자가 다음과 같은 요청을 보낸다고 가정합니다:

"우리 연어 재고를 확인하고, 오늘 도매 가격과 품질 등급 견적을 받아봐. 만약 재고가 부족하면 Example Wholesale에서 10파운드를 주문하고 결제까지 승인해줘."

이 단일 요청은 에이전트에 의해 다단계 워크플로우로 변환되며, 각 단계는 서로 다른 프로토콜을 활용하여 완벽하게 조정됩니다.

정보 수집 단계 (Gather Information)

  1. 재고 확인: 에이전트는 **MCP (Model Context Protocol)**를 사용하여 내부 PostgreSQL 데이터베이스에 check_inventory 쿼리를 보내 연어 재고를 확인합니다. 재고가 낮음이 확인됩니다.

  2. 외부 견적 문의: **A2A (Agent2Agent Protocol)**를 통해 원격의 가격 에이전트와 품질 에이전트에 ask_agent 쿼리를 보내 당일 연어 도매가와 품질 정보를 가져옵니다.

트랜잭션 완료 단계 (Complete Transaction)

  1. 주문 전송: 가격과 품질이 적절하다고 판단되면, 에이전트는 **UCP (Universal Commerce Protocol)**를 활용하여 정형화된 CheckoutCreateRequest를 작성하고 Example Wholesale의 UCP 엔드포인트에 place_order 트랜잭션을 실행합니다.

  2. 결제 승인: 주문 과정에 **AP2 (Agent Payments Protocol)**를 확장으로 결합하여 관리자가 미리 설정한 가드레일 내에서 암호화된 PaymentMandate를 생성하고 authorize_payment 서명을 완료합니다.

결과 표시 단계 (Present Results)

  1. 동적 UI 구성: 에이전트는 주문 완료 결과, 재고 대시보드, 그리고 최종 영수증 등을 포함한 상호작용 가능한 위젯 레이아웃을 **A2UI (Agent-to-User Interface Protocol)**의 18가지 안전한 컴포넌트 프리미티브로 동적 구성합니다.

  2. 실시간 스트리밍: 전체 처리 과정의 도구 호출 결과와 최종 UI 정의 JSON은 **AG-UI (Agent-User Interaction Protocol)**를 통해 표준화된 SSE 스트림으로 변환되어 프런트엔드에 실시간으로 배포됩니다.


지금까지 살펴본 것처럼, 각각 다른 문제를 해결하는 6개의 프로토콜이 모두 단일 에이전트를 통해 동작합니다:

에이전트 프로토콜 활용 팁

지금까지 살펴본 복잡한 에이전트 아키텍처를 성공적으로 구축하기 위한 몇 가지 조언을 공유합니다:

각 프로토콜의 문제 해결 범위를 명확히 이해하세요(Know what problem each protocol solves): MCP는 데이터와 도구 연결, A2A는 에이전트 간 통신, UCP는 상거래 표준화, AP2는 결제 승인 가드레일, A2UI는 무엇을 렌더링할지, AG-UI는 어떻게 스트리밍할지를 해결합니다. 이 경계를 이해해야 깨끗한 아키텍처를 유지할 수 있습니다.

필요한 프로토콜만 선별적으로 추가하세요(Add protocols as you need them): 첫날부터 6가지 프로토콜을 모두 사용할 필요는 없습니다. 대부분의 에이전트는 MCP를 통한 데이터 접근에서 시작합니다. 멀티 에이전트 소통, 상거래, 안전한 결제, 풍부한 UI, 또는 스트리밍이 필요해질 때 해당 문제를 해결하는 프로토콜을 하나씩 가져오면 됩니다.

처음부터 다시 만들지 마세요(Don’t start from scratch): 프로토콜을 직접 구현하기 전에 ADK 통합 기능, 공식 SDK, 그리고 샘플 코드를 확인하세요. 이 분야는 매우 빠르게 변하고 있으며, 공식 도구는 개발자가 직접 구현하고 싶지 않은 세부적인 세부사항을 처리합니다.

표준을 조기에 채택하세요(Adopt standards early): 이 프로토콜들은 아직 성숙해가는 단계이지만, 이들이 확립하는 패턴(잘 알려진 URL을 통한 발견, 정형화된 요청/응답 스키마, 표준 이벤트 스트림)은 여러분의 에이전트를 도구, 서비스, 그리고 다른 에이전트의 성장하는 생태계와 호환되게 만듭니다.

지금 시작하기 (Get Started Now)

본 가이드의 모든 코드 샘플은 구글의 Agent Development Kit (ADK)를 사용합니다. 첫 번째 에이전트를 설정하고, MCP 서버에 연결한 후, 거기서부터 필요한 프로토콜을 추가해 보세요. 연결 가능한 도구와 서비스들은 ADK 통합 문서에서 살펴볼 수 있습니다.

:scroll: AI 에이전트 프로토콜 개발자 가이드 블로그

:house: Agent Development Kit (ADK) 홈페이지

:github: Agent Development Kit 프로젝트 GitHub 저장소




이 글은 GPT 모델로 정리한 글을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 덧글로 알려주시기를 부탁드립니다. :hugs:

:pytorch:파이토치 한국 사용자 모임:south_korea:이 정리한 이 글이 유용하셨나요? 회원으로 가입하시면 주요 글들을 이메일:love_letter:로 보내드립니다! (기본은 Weekly지만 Daily로 변경도 가능합니다.)

:wrapped_gift: 아래:down_right_arrow:쪽에 좋아요:+1:를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ :star_struck:

2개의 좋아요

유용한 정보입니다!!

1개의 좋아요

앗, 서율님! 감사합니다!!