15장 — 에이전트 간 통신

개별 AI 에이전트는 역량이 뛰어나더라도 복잡하고 다면적인 문제를 혼자 해결할 때 한계에 부딪히는 경우가 많습니다. 이를 극복하기 위해 에이전트 간 통신(Inter-Agent Communication, A2A) 은 서로 다른 프레임워크로 구축된 다양한 AI 에이전트가 효과적으로 협업할 수 있게 합니다. 이 과정에서 자연스러운 조율, 작업 위임, 정보 교환이 이루어집니다.

패턴 개요

A2A 프로토콜은 상호운용성을 보장하므로, LangGraph, CrewAI, 구글 ADK 같은 서로 다른 프레임워크로 개발된 AI 에이전트도 출처나 구현 방식에 관계없이 함께 작동할 수 있습니다.

지지 기반이 넓습니다. Atlassian, Box, LangChain, MongoDB, Salesforce, SAP, ServiceNow를 비롯한 다양한 기업이 지원하고, 마이크로소프트는 Azure AI Foundry와 Copilot Studio에 A2A를 통합했으며(옮긴이 주에 따르면 현재는 도입이 완료되어 외부 에이전트와의 통합 구성이 가능합니다), Auth0와 SAP도 자사 플랫폼에 지원을 통합하고 있습니다.

A2A의 목표는 복잡한 멀티 에이전트 AI 시스템을 개발할 때 효율성을 높이고 통합 비용을 줄이며, 혁신과 상호운용성을 높이는 것이다.

A2A의 핵심 개념

기반을 이루는 축은 핵심 주체, 에이전트 카드, 에이전트 탐색, 통신과 작업 관리, 상호작용 메커니즘, 보안 여섯 가지입니다.

① 핵심 주체 세 가지

주체 역할
사용자 에이전트에게 도움을 요청한다
A2A 클라이언트(클라이언트 에이전트) 사용자를 대신하여 작업이나 정보를 요청하는 애플리케이션 또는 AI 에이전트
A2A 서버(원격 에이전트) 클라이언트 요청을 처리하고 결과를 반환하는 HTTP 엔드포인트를 제공하는 AI 에이전트 또는 시스템. 내부 구현을 드러내지 않는 시스템처럼 동작하므로, 클라이언트는 그 내부 동작 방식까지 알 필요가 없다

② 에이전트 카드 — 디지털 신원

에이전트를 식별하는 고유 정보는 에이전트 카드로 정의되며, 보통 JSON 파일 형태입니다. 신원, 엔드포인트 URL, 버전 정보, 지원 기능(스트리밍·푸시 알림), 구체적인 스킬, 기본 입출력 모드, 인증 요구사항이 담깁니다.

{
  "name": "WeatherBot",
  "description": "Provides accurate weather forecasts and historical data.",
  "url": "http://weather-service.example.com/a2a",
  "version": "1.0.0",
  "capabilities": {
    "streaming": true,
    "pushNotifications": false,
    "stateTransitionHistory": true
  },
  "authentication": { "schemes": ["apiKey"] },
  "defaultInputModes": ["text"],
  "defaultOutputModes": ["text"],
  "skills": [
    {
      "id": "get_current_weather",
      "name": "Get Current Weather",
      "description": "Retrieve real-time weather for any location.",
      "inputModes": ["text"],
      "outputModes": ["text"],
      "examples": ["What's the weather in Paris?", "Current conditions in Tokyo"],
      "tags": ["weather", "current", "real-time"]
    },
    {
      "id": "get_forecast",
      "name": "Get Forecast",
      "description": "Get 5-day weather predictions.",
      "examples": ["5-day forecast for New York", "Will it rain in London this weekend?"],
      "tags": ["weather", "forecast", "prediction"]
    }
  ]
}

examples 필드가 눈에 띕니다. 스킬이 어떤 질문에 쓰이는지 예시로 보여 주는 것인데, 10장에서 MCP 도구에 namedescription을 명시하라고 한 것과 같은 맥락입니다.

③ 에이전트 탐색 세 가지 방식

방식 내용 적합한 환경
Well-Known URI 표준화된 경로(예: /.well-known/agent.json)에 에이전트 카드를 호스팅 공개용이든 특정 도메인용이든 다양한 환경. 접근 절차 자체도 자동화되는 경우가 많다
선별 등록소(Curated Registries) 에이전트 카드를 등록해 두고 특정 기준에 따라 검색할 수 있는 중앙 집중형 카탈로그 중앙 집중식 관리와 접근 제어가 필요한 기업 환경
직접 구성(Direct Configuration) 에이전트 카드 정보를 내장하거나 비공개로 공유 실시간 탐색이 중요하지 않은 긴밀 결합 시스템이나 비공개 시스템

어떤 방식을 선택하든 에이전트 카드 엔드포인트의 보안을 확보하는 것이 중요합니다. 접근 제어, 상호 TLS(mTLS), 네트워크 차원의 접근 제한 등으로 구현할 수 있으며, 특히 카드에 민감한(비밀은 아니지만) 정보가 포함된 경우 더욱 그렇습니다.

④ 통신과 작업 관리

A2A에서 에이전트 간 통신은 비동기 작업을 중심으로 이뤄집니다. 각 작업에는 고유 식별자가 부여되며 제출됨 · 처리 중 · 완료 같은 일련의 상태를 거칩니다.

  • 메시지: 속성(메시지를 설명하는 키-값 메타데이터, 예: 우선순위·생성 시각)과 하나 이상의 파트(일반 텍스트, 파일, 구조화된 JSON 데이터 등 실제로 전달되는 내용)로 구성된다.
  • 아티팩트: 작업 수행 중 에이전트가 생성하는 실제 결과물. 메시지와 마찬가지로 하나 이상의 파트로 구성되며, 결과가 나오는 대로 차례차례 순차적으로 스트리밍할 수 있다.
  • 모든 통신은 HTTP(S) 를 통해 이뤄지고, 페이로드에는 JSON-RPC 2.0 프로토콜을 사용한다.
  • 여러 상호작용 전반에서 연속성을 유지하기 위해 서버가 생성하는 contextId 로 관련 작업을 묶고 컨텍스트를 보존한다.

⑤ 상호작용 메커니즘 네 가지

방식 언제 쓰나 동작
동기 요청/응답 빠르고 즉각적인 작업 클라이언트가 요청을 보내고, 서버가 처리를 완료해 단일 동기 교환으로 응답을 돌려줄 때까지 기다린다 (sendTask)
비동기 폴링 처리에 시간이 더 걸리는 작업 서버가 즉시 “처리 중(working)” 상태와 작업 ID로 응답한다. 클라이언트는 기다리는 동안 다른 작업을 하면서 주기적으로 상태를 확인한다
스트리밍 업데이트(SSE) 실시간으로 증분 결과를 받기에 적합 서버에서 클라이언트로 이어지는 지속적인 단방향 연결을 유지해, 클라이언트가 반복 요청하지 않아도 상태 변경이나 부분 결과를 계속 푸시한다 (sendTaskSubscribe)
푸시 알림(웹훅) 매우 오래 걸리거나 자원 집약적인 작업에서 상시 연결이나 빈번한 폴링이 비효율적일 때 클라이언트가 웹훅 URL을 등록하면, 작업 상태가 크게 변할 때 서버가 해당 URL로 비동기 알림을 보낸다
// 동기 요청 예시
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "sendTask",
  "params": {
    "id": "task-001",
    "sessionId": "session-001",
    "message": {
      "role": "user",
      "parts": [{ "type": "text", "text": "What is the exchange rate from USD to EUR?" }]
    },
    "acceptedOutputModes": ["text/plain"],
    "historyLength": 5
  }
}

스트리밍 요청은 methodsendTaskSubscribe 로 바뀝니다. A2A는 입력·출력 형태에 구애받지 않는 프로토콜이어서, 텍스트뿐 아니라 오디오나 비디오 같은 데이터에도 이러한 상호작용 패턴을 적용할 수 있습니다.

⑥ 보안

  • 상호 전송 계층 보안(mTLS): 암호화되고 인증된 연결을 맺어 무단 접근과 데이터 가로채기를 방지한다.
  • 종합 감사 로그: 모든 에이전트 간 통신을 정보 흐름, 관여 에이전트, 수행된 작업까지 꼼꼼히 기록한다. 책임 소재 파악, 문제 해결, 보안 분석에 중요하다.
  • 에이전트 카드 선언: 인증 요구사항을 에이전트 카드에 명시적으로 선언해 인증을 한 곳에서 관리한다.
  • 자격 증명 처리: OAuth 2.0 토큰이나 API 키를 HTTP 헤더를 통해 전달한다. 자격 증명이 URL이나 메시지 본문에 노출되는 것을 방지한다.

A2A와 MCP는 경쟁 관계가 아니다

A2A는 앤스로픽의 모델 컨텍스트 프로토콜을 보완하는 프로토콜이다. MCP가 에이전트의 컨텍스트를 구조화하고 외부 데이터·도구와 상호작용하는 데 초점을 맞춘다면, A2A는 에이전트 간 조율과 통신을 담당하여 작업을 위임하고 협업하도록 해 준다.

[A2A]  출발 에이전트 ⇄ Agent2Agent 프로토콜 ⇄ 에이전트 1 / 에이전트 2
[MCP]  출발 에이전트 ⇄ 모델 컨텍스트 프로토콜 ⇄ 브라우저 / 파일 시스템 / 벡터 DB / API

축이 다릅니다. MCP는 에이전트와 도구 사이의 세로축, A2A는 에이전트와 에이전트 사이의 가로축입니다.

실제 적용과 활용 사례

  • 멀티 프레임워크 협업: 가장 대표적인 사례로, 기반 프레임워크(ADK, LangChain, CrewAI)에 관계없이 독립적인 AI 에이전트가 서로 통신하고 협업한다.
  • 자동화된 워크플로 오케스트레이션: 한 에이전트가 초기 데이터 수집을 맡고, 다음 에이전트에게 분석을 위임하고, 세 번째 에이전트에게 보고서 생성을 맡기는 식으로 모든 통신이 A2A 프로토콜을 통해 이루어진다.
  • 실시간 정보 검색: 주 에이전트가 전문 “데이터 수집 에이전트” 에 실시간 시장 데이터를 요청하면, 해당 에이전트가 외부 API를 사용해 정보를 수집하여 돌려준다.

실습 — ADK로 A2A 서버 세우기

a2a-samples 저장소(github.com/google-a2a/a2a-samples)에는 Java, Go, 파이썬 예제가 있으며 LangGraph, CrewAI, Azure AI Foundry, AG2 같은 다양한 에이전트 프레임워크가 A2A로 통신하는 방법을 보여 줍니다. 모든 코드는 Apache 2.0 라이선스로 공개되어 있습니다.

에이전트 만들기

import datetime
from google.adk.agents import LlmAgent
from google.adk.tools.google_api_tool import CalendarToolset

async def create_agent(client_id, client_secret) -> LlmAgent:
    """ADK 에이전트를 생성한다."""
    toolset = CalendarToolset(client_id=client_id, client_secret=client_secret)
    return LlmAgent(
        model='gemini-2.0-flash-001',
        name='calendar_agent',
        description="An agent that can help manage a user's calendar",
        instruction=f"""
You are an agent that can help manage a user's calendar.
Users will request information about the state of their calendar
or to make changes to their calendar. Use the provided tools for
interacting with the calendar API.
If not specified, assume the calendar the user wants is the 'primary' calendar.
When using the Calendar API tools, use well-formed RFC3339 timestamps.
Today is {datetime.datetime.now()}.
""",
        tools=await toolset.get_tools(),
    )

지시문에 현재 시점을 알 수 있도록 날짜가 실행 시점에 자동으로 삽입되는 것이 포인트입니다.

에이전트 카드 정의와 서버 실행

def main(host: str, port: int):
    # API 키가 설정되어 있는지 확인한다.
    # Vertex AI API를 사용하는 경우에는 필요하지 않다.
    if os.getenv('GOOGLE_GENAI_USE_VERTEXAI') != 'TRUE' and not os.getenv('GOOGLE_API_KEY'):
        raise ValueError(
            'GOOGLE_API_KEY environment variable not set and '
            'GOOGLE_GENAI_USE_VERTEXAI is not TRUE.'
        )

    skill = AgentSkill(
        id='check_availability',
        name='Check Availability',
        description="Checks a user's availability for a time using their Google Calendar",
        tags=['calendar'],
        examples=['Am I free from 10am to 11am tomorrow?'],
    )
    agent_card = AgentCard(
        name='Calendar Agent',
        description="An agent that can manage a user's calendar",
        url=f'http://{host}:{port}/',
        version='1.0.0',
        defaultInputModes=['text'],
        defaultOutputModes=['text'],
        capabilities=AgentCapabilities(streaming=True),
        skills=[skill],
    )

    adk_agent = asyncio.run(create_agent(
        client_id=os.getenv('GOOGLE_CLIENT_ID'),
        client_secret=os.getenv('GOOGLE_CLIENT_SECRET'),
    ))
    runner = Runner(
        app_name=agent_card.name,
        agent=adk_agent,
        artifact_service=InMemoryArtifactService(),
        session_service=InMemorySessionService(),
        memory_service=InMemoryMemoryService(),
    )
    agent_executor = ADKAgentExecutor(runner, agent_card)

    async def handle_auth(request: Request) -> PlainTextResponse:
        await agent_executor.on_auth_callback(
            str(request.query_params.get('state')), str(request.url)
        )
        return PlainTextResponse('Authentication successful.')

    request_handler = DefaultRequestHandler(
        agent_executor=agent_executor, task_store=InMemoryTaskStore()
    )
    a2a_app = A2AStarletteApplication(
        agent_card=agent_card, http_handler=request_handler
    )
    routes = a2a_app.routes()
    routes.append(Route(path='/authenticate', methods=['GET'], endpoint=handle_auth))

    app = Starlette(routes=routes)
    uvicorn.run(app, host=host, port=port)

이 예제는 에이전트의 기능 정의부터 웹 서비스로 실행하기까지, A2A 호환 에이전트를 구축하는 전 과정을 보여 준다.

check_availability 스킬이 에이전트 카드에 정의되고, 에이전트의 네트워크 주소도 명시된다는 점, 그리고 A2AStarletteApplication이 제공하는 라우트에 인증 콜백 라우트를 덧붙이는 구조가 핵심입니다.

정리

에이전트 간 통신이란 무엇인가

개별 AI 에이전트는, 특히 서로 다른 프레임워크로 구축된 경우, 복잡하고 다면적인 문제를 독자적으로 해결하기 어려운 경우가 많습니다. 핵심 문제는 에이전트가 효과적으로 소통하고 협업할 수 있는 공통 언어, 즉 프로토콜이 없다는 점입니다. 표준화된 접근법이 없으면 서로 다른 에이전트를 통합하는 데 비용과 시간이 많이 들고, 더 강력하고 응집력 있는 AI 솔루션 발전도 어려워집니다.

왜 사용하는가?

A2A는 HTTP 기반 프로토콜로 상호운용성을 보장하여, 기반 기술에 관계없이 서로 다른 AI 에이전트가 매끄럽게 조율하고, 작업을 위임하며, 정보를 공유할 수 있도록 합니다. 핵심 구성요소인 에이전트 카드는 에이전트의 기능, 스킬, 통신 엔드포인트를 기술하는 디지털 신원 파일로, 탐색과 상호작용을 수월하게 합니다.

언제 사용해야 하는가?

두 개 이상의 AI 에이전트 간 협업을 오케스트레이션해야 할 때, 특히 서로 다른 프레임워크(구글 ADK, LangGraph, CrewAI)로 구축된 경우에 이 패턴을 사용한다. 전문 에이전트가 워크플로의 특정 부분을 담당하는 복잡한 모듈형 애플리케이션을 구축할 때 특히 적합하며, 에이전트가 작업 완수를 위해 다른 에이전트의 기능을 그때그때 탐색하고 활용해야 할 때도 유용하다.

핵심 정리

  • 구글 A2A 프로토콜은 서로 다른 프레임워크로 구축된 AI 에이전트 간 통신과 협업을 촉진하는 개방형 HTTP 기반 표준이다.
  • 에이전트 카드는 에이전트의 디지털 식별자 역할을 하며, 다른 에이전트가 그 기능을 자동으로 탐색하고 파악할 수 있게 한다.
  • A2A는 동기 요청-응답(tasks/send)스트리밍 업데이트(tasks/sendSubscribe) 를 모두 제공한다.
  • input-required 상태를 포함해 여러 턴에 걸친 대화를 지원하며, 에이전트가 추가 정보를 요청하고 상호작용 중에 컨텍스트를 유지할 수 있게 한다.
  • 전문 에이전트가 서로 다른 포트에서 독립적으로 운영될 수 있는 모듈형 아키텍처를 권장하며, 이를 통해 시스템 확장성과 분산 배치가 가능해진다.
  • Trickle AI 같은 도구는 A2A 통신을 시각화하고 추적하는 데 도움이 되며, 개발자가 멀티 에이전트 시스템을 모니터링하고 디버깅하며 최적화하는 데 기여한다.
  • A2A가 에이전트 간 작업과 워크플로를 관리하는 상위 수준 프로토콜인 반면, MCP는 LLM이 외부 리소스와 상호작용하기 위한 표준화된 인터페이스를 제공한다.

마치며

A2A 프로토콜은 개별 AI 에이전트의 고립 문제를 극복하기 위한 핵심 개방형 표준을 마련합니다. 공통 HTTP 기반 프레임워크를 제공하여, 구글 ADK나 LangGraph, CrewAI 같은 서로 다른 플랫폼에서 구축된 에이전트 간에도 매끄러운 협업과 상호운용성을 보장합니다.

이로써 전문 에이전트를 조합해 복잡한 자동화 워크플로를 오케스트레이션하는 모듈형이자 확장 가능한 아키텍처를 구현할 수 있다. 보안은 핵심 요소이며, mTLS와 명시적 인증 요구사항 같은 내장 메커니즘이 통신을 보호한다. 결국 A2A는 협업 AI의 혁신적이고 상호운용 가능한 생태계를 이끄는 핵심 기반이다.

참고 문헌