본문으로 건너뛰기

A2A: 에이전트 간 프로토콜

고급

2026년 중반에는 사소하지 않은 에이전트 작업 대부분이 여러 에이전트의 협업으로 이루어집니다 — 리서치 에이전트가 라이터에게 넘기고, 결제 에이전트가 다른 벤더의 지원 에이전트와 대화하며, 오케스트레이터가 다른 조직의 클라우드 안 전문 에이전트에게 위임합니다. A2A(Agent-to-Agent) 는 그 에이전트들이 서로를 발견 하고, 자신이 할 수 있는 것을 설명 하고, 태스크를 주고받게 해주는 개방형 프로토콜입니다 — 서로 다른 팀이 서로 다른 프레임워크로 만들었을 때조차. MCP 가 에이전트를 그 도구와 데이터 에 연결한다면, A2A 는 에이전트를 다른 에이전트 에 연결합니다. 이들은 결합합니다; 경쟁하지 않습니다.

What you'll learn
  • A2A가 무엇을 위한 것인지 정확히 진술 — 그리고 MCP 경계가 어디에 있는지
  • Agent Card를 읽고 받는 에이전트가 그것으로 무엇을 할지 알기
  • 종결이 아닌 인터럽트인 두 상태를 포함한 여덟 라이프사이클 상태 전체를 태스크로 걸어보기
  • 장시간 실행 태스크에 SSE 스트리밍과 웹훅 푸시 중에서 선택하기
  • 덜 명확한 기능들을 알아보기: 서명된 카드, 멀티테넌트 엔드포인트, 구조화된 데이터 파트

왜 A2A가 존재하는가​

모든 에이전트 프레임워크 — LangGraph, CrewAI, Claude Agent SDK, OpenAI Agents SDK, Microsoft의 Agent Framework, 사내 커스텀 루프 — 는 도구 사용 을 모델의 네이티브 도구 호출과, 점점 더 보편적 도구-및-데이터 커넥터로서의 MCP 에 기대어 해결했습니다. 그것이 우리에게 agent ↔ tool을 주었습니다.

어느 것도 스스로 해결하지 못한 것은 경계를 가로지르는 agent ↔ agent 였습니다. 두 가지 문제가 계속 등장했습니다:

  • 발견. 에이전트 A가 에이전트 B가 존재한다는 것, 무엇을 할 수 있는지, 어떻게 인증하는지, 스트리밍을 지원하는지를 어떻게 알까요? 손으로 굴린 README는 프로토콜이 아닙니다.
  • 태스크 인계. A가 B에게 무언가를 시키고 싶어지면, 어떻게 작업 을 (모델의 채팅이 아니라) 교환할까요 — 파일, 구조화된 데이터, 진행 업데이트, 그리고 B가 A에게 입력을 물어보기 위해 일시 정지해야 할 수도 있다는 사실을 포함해서?

프레임워크별 답 (LangGraph 서브그래프, CrewAI 크루, 한 런타임 안의 서브에이전트) 은 한 프로세스 안 에서는 훌륭하게 작동합니다. 조직 경계에서는 멈춥니다. A2A는 당신의 제품 안 에이전트가 어느 쪽도 내부를 유출하지 않고 다른 사람 제품의 에이전트에게 위임할 수 있게 해주는 조각입니다 — 구글의 Todd Segal은 이를 "개인, 팀, 도메인 특화 에이전트가 어떤 플랫폼에서든 매끄럽게 함께 작동하기 위한 안전한 토대"라고 부릅니다. 거버넌스는 Linux Foundation에 있고, 2026년 4월까지 이 프로젝트는 AWS, Microsoft, Salesforce, SAP, ServiceNow, IBM을 포함해 150개 이상의 지원 조직 을 보고했습니다.

MCP vs. A2A — 멘탈 모델​

둘 다 개방형 프로토콜입니다. 둘 다 HTTP 위 JSON을 사용합니다. 이들은 서로 다른 문제를 해결하며 결합되도록 설계 되었습니다:

  • MCP = 에이전트 대 도구. MCP 서버는 도구(search, read_file, run_query)와 리소스(문서, 프롬프트)를 모델 주도 클라이언트에게 노출합니다. 클라이언트는 에이전트이고; 서버는 수동적 기능 제공자입니다. Claude가 이를 어떻게 사용하는지는 MCP & connecting to tools 를 보세요.
  • A2A = 에이전트 대 에이전트. A2A 엔드포인트는 에이전트 를 노출합니다 — 위임된 태스크를 어떻게 해결할지 결정 할 자신의 추론 루프를 가진 개체. 양쪽 모두 에이전트이며; 어느 쪽이든 상대를 호출할 수 있습니다.

구체적인 차이는 와이어 포맷에서 드러납니다. MCP tools/call은 결과를 반환하고 닫습니다. A2A SendMessage는 태스크 를 엽니다 — 업데이트를 스트리밍하거나, 명확화를 요청하거나, 백그라운드에서 몇 시간 동안 실행될 수 있는 자신의 라이프사이클을 가진 상태 있는 것. 만약 당신의 엔드포인트의 답이 항상 "여기 하나의 함수의 결과가 있다"라면, 그것은 도구입니다 — MCP로 게시하세요. 만약 "그것에 대해 생각해보고 다시 알려주겠다, 그리고 후속 질문을 해야 할 수도 있다"라면, 그것은 에이전트입니다 — A2A로 게시하세요.

대부분의 진지한 시스템은 둘 다 실행할 것입니다: 내부 는 MCP로 도구에 도달하고, 외부 는 피어가 작업을 넘길 수 있도록 A2A를 말하는 에이전트.

Agent Card — 스펙에서 가장 중요한 조각​

Agent Card 는 잠재적 호출자에게 당신의 에이전트와 대화하는 데 필요한 모든 것을 알려주는, 잘 알려진 URL에서 제공되는 JSON 문서입니다. 에이전트를 위한 OpenAPI + robots.txt 라고 생각하세요. 모든 A2A 상호작용은 하나를 가져오는 것으로 시작합니다.

카드에는 다음이 포함됩니다:

  • 정체성 — id, name, description, provider(조직 세부사항).
  • 엔드포인트 — 서비스 URL과 어떤 프로토콜 바인딩(JSON-RPC, gRPC, REST)이 사용 가능한지.
  • 기능 — 기능 플래그: streaming, pushNotifications, extendedAgentCard.
  • 스킬 — 입력/출력 스키마를 가진 선언된 에이전트 함수(B가 할 수 있다고 말하는 것).
  • 보안 스킴 — APIKey, HTTPAuth(Basic/Bearer), OAuth2(Authorization Code, Client Credentials, Device Code), OpenIdConnect, MutualTLS 중 하나 이상. 호출자는 첫 번째 호출 전에 어떤 자격 증명을 가져와야 하는지 알기 위해 이것을 읽습니다.
  • 서명 — 카드에 대한 선택적 암호화 서명.

그 마지막 필드가 잠시 멈춰볼 가치가 있는 것입니다. Signed Agent Card 는 받는 에이전트가 카드가 실제로 도메인 소유자에 의해 발급되었는지 검증할 수 있게 해줍니다 — "예, 이것은 정말로 agents.acme.com이지 공격자가 심은 것이 아니다"의 DNS/PKI 등가물입니다. mTLS 인증과 결합되면, 스푸핑된 호스트에서 서비스되는 악성 Agent Card의 문을 닫습니다. 그러지 않으면 그것이 바로 발견 계층의 프롬프트 인젝션 을 얻는 방식입니다: 공격자의 Agent Card가 어떤 도구를 노출하고 어떤 데이터를 원하는지에 대해 거짓말합니다.

여덟 태스크 라이프사이클 상태​

A2A 에이전트에게 SendMessage를 하면, 그 작업은 Task 가 됩니다 — 폴링, 구독, 취소, 나열할 수 있는 ID를 가진 일급 객체. 태스크는 여덟 상태를 거치며, 다섯만이 종결적 이라는 점에 주목할 가치가 있습니다:

  • SUBMITTED — 서버가 태스크를 인지했습니다.
  • WORKING — 활성 처리 중.
  • INPUT_REQUIRED — 인터럽트: 에이전트가 호출자로부터 더 많은 정보를 필요로 합니다. 오류가 아니라; 실제 워크플로에서 예상됩니다.
  • AUTH_REQUIRED — 인터럽트: 에이전트가 계속하기 전에 호출자가 인증(또는 재인증)해야 합니다.
  • COMPLETED — 성공. 종결.
  • FAILED — 오류. 종결.
  • CANCELED — 호출자가 시작한 취소. 종결.
  • REJECTED — 에이전트가 태스크를 거절(정책, 능력, 할당량). 종결.

인터럽트 상태가 요점입니다. 레거시 RPC는 한 호출 → 한 결과를 가정합니다. 실제 에이전트 작업은 "분석을 시작하고, 한 시간 뒤에 돌아오고, 명확화 질문을 해야 함을 알아채고, 답을 기다리고, 재개하고, 마무리한다" 처럼 보입니다. A2A는 이것을 네이티브로 모델링합니다. 당신의 호출 코드는 동기 await가 아니라 작은 상태 기계여야 합니다.

스트리밍 vs. 푸시 알림​

장시간 실행 태스크는 업데이트를 전달할 방법이 필요합니다. A2A는 두 가지 비동기 모델을 줍니다 — 에이전트가 아닌 태스크마다 고르세요:

  • 스트리밍(SendStreamingMessage / SubscribeToTask). 열린 HTTP 연결 위의 Server-Sent Events. 클라이언트는 연결된 상태로 남아 TaskStatusUpdateEvent와 TaskArtifactUpdateEvent를 순서대로 받습니다. 인터랙티브 UI와 단중기 태스크에 좋습니다. 클라이언트가 연결을 유지할 수 없으면(모바일, 서버리스, 잠자기 상태로 가는 브라우저 탭) 무너집니다.
  • 푸시 알림(웹훅 구성). 클라이언트가 CreateTaskPushNotificationConfig를 통해 웹훅을 등록합니다. 서버가 업데이트가 일어날 때 그 URL로 POST합니다. 클라이언트는 그 사이에 완전히 오프라인일 수 있습니다. 이것이 HTTP 연결보다 오래 지속되는 태스크의 모드입니다 — "밤새 실행하기"나 "배치 작업이 끝나면 다시 연락"을 생각하세요.

둘 다 에이전트가 자신의 Agent Card에서 지원을 광고해야 합니다(capabilities.streaming: true 및/또는 capabilities.pushNotifications: true). 순응하는 호출자는 먼저 확인하고 깨끗하게 다운그레이드합니다.

메시지 파트 — 채팅만이 아님​

A2A Message 는 하나 이상의 Part 로 구성됩니다. 각 Part는 다음 중 하나일 수 있습니다:

  • text — 문자열 콘텐츠(채팅스러운 부분).
  • raw — 바이너리 파일, JSON 안에 base64로 인코딩됨.
  • url — 외부 파일에 대한 참조(거대한 blob을 인라인하는 것을 피함).
  • data — 구조화된 JSON 객체 또는 배열, 선택적 metadata 맵과 함께.

data 파트가 A2A를 기계 대 기계 작업에 유용하게 만드는 것입니다. 두 에이전트는 그것에 대해 자연어 대화를 하는 척하지 않고 타입 있는 페이로드를 교환할 수 있습니다 — 주문, 구매 스펙, JSON diff. 이것이 또한 Agent Payments(AP2) 같은 프로토콜이 A2A 위에 깨끗하게 적층되게 만드는 것입니다: 결제 의도가 알려진 스키마의 data 파트에 실려 갑니다.

멀티테넌트 엔드포인트 — 하나의 URL, 많은 에이전트​

이것은 놓치기 쉽습니다. 단일 A2A 엔드포인트는 많은 에이전트 를 호스팅할 수 있으며, 인증 후 GetExtendedAgentCard 메서드를 통해 서비스됩니다. SaaS 벤더는 하나의 URL을 제공하고 호출자가 어떤 API 키나 OAuth 스코프를 제시하는지에 따라 다른, 테넌트별 Agent Card를 반환할 수 있습니다. 호출자 측에서는 에이전트당 하나의 엔드포인트처럼 보입니다; 벤더 측에서는 하나의 배포입니다. 에이전트 제공 인프라를 구축한다면, 이것이 테넌트당 하나의 호스트명 없이 확장하게 해주는 패턴입니다.

최소 엔드투엔드 상호작용​

전체 프로토콜은 표면이 많지만, 해피 패스 플로우는 짧습니다:

Guided walkthrough1 of 5
  1. 잘 알려진 URL에서 Agent Card를 가져옵니다. 서명이 있으면 검증합니다. `capabilities`, `skills`, `securitySchemes`를 읽어 이 에이전트가 당신이 필요로 하는 것을 할 수 있는지, 어떤 인증을 가져올지 결정합니다.

Agent Card 가져오기 (개념)​

발견은 그저 HTTP GET입니다. 클라이언트가 후보 에이전트에게 작업을 보내기 전에 검사하기 위해 만들 요청의 형태는 이렇습니다:

Agent Card 가져오기와 검사

GET https://agents.example.com/.well-known/agent.json
Accept: application/json

# Response (abbreviated):
# {
#   "id": "acme/support-router",
#   "name": "Acme Support Router",
#   "provider": {"organization": "Acme, Inc."},
#   "endpoints": [
#     {"url": "https://agents.example.com/a2a", "protocol": "jsonrpc"}
#   ],
#   "capabilities": {
#     "streaming": true,
#     "pushNotifications": true,
#     "extendedAgentCard": true
#   },
#   "skills": [
#     {"id": "route_ticket", "inputSchema": {...}, "outputSchema": {...}}
#   ],
#   "securitySchemes": {
#     "primary": {"type": "oauth2", "flows": {...}}
#   },
#   "signature": {"alg": "EdDSA", "value": "..."}
# }

카드에 없는 것에 주목하세요: 에이전트 뒤의 모델, 그 프롬프트, 도구, 사설 상태에 대한 어떤 것도. 그 불투명함은 의도적입니다 — A2A는 피어 에이전트를 검사하는 시스템이 아니라 작업을 위임하는 블랙박스로 취급합니다.

흔한 함정​

  • INPUT_REQUIRED를 오류로 취급. 그것은 오류가 아닙니다; 프로토콜이 당신의 코드에게 응답을 요청하는 것입니다. 호출자 코드가 "성공했는가 실패했는가"에만 분기하면 모든 인터랙티브 워크플로가 깨집니다.
  • Agent Card의 capabilities를 무시. streaming: true를 광고하지 않은 에이전트에게 스트리밍 요청을 보내면 UnsupportedOperationError를 얻습니다. 카드를 읽고 깨끗하게 다운그레이드하세요.
  • 스트리밍 연결이 견고하다고 가정. 모바일 클라이언트, 서버리스 런타임, 브라우저 탭 — 모두 SSE 연결을 떨어뜨립니다. "채팅 한 턴"보다 긴 것이라면 푸시 알림을 선호하세요.
  • 선택적이라는 이유로 서명 검증 생략. 조직 외부에서 Agent Card를 소비한다면 서명을 검증하세요 — 그렇지 않으면 발견 계층 프롬프트 인젝션 벡터를 만든 것입니다.
  • A2A와 MCP를 혼동. 상태 없는 단발 함수를 위해 A2A 엔드포인트를 게시하는 것은 과잉입니다; 그것은 도구이고, MCP가 맞는 프로토콜입니다. 몇 분 걸리고 명확화 질문을 해야 하는 것을 위해 MCP 도구를 게시하는 것은 저설계입니다; 그것은 에이전트이고, A2A가 맞는 프로토콜입니다.

Check yourself

0/4
  1. MCP가 설계되지 *않은* 것 — A2A의 일은 이 중 어느 것입니까?
  2. A2A는 여덟 태스크 상태를 정의합니다. 종결이 아닌 *인터럽트* 인 두 가지는?
  3. 한 시간이 걸리는 A2A 태스크를 실행해야 합니다. 클라이언트는 열린 HTTP 연결을 유지할 수 없는 서버리스 함수입니다. 올바른 전달 모델은?
  4. *서명된* Agent Card는 무엇으로부터 당신을 보호합니까?

A2A가 당신의 스택에서 어디에 있는가​

나머지 에이전트 그림과 함께 놓으면:

  • 에이전트 내부에서, MCP는 도구와 데이터 에 도달하는 방법입니다 — 당신이 작성하지 않은 원격 MCP 서버를 포함해서.
  • 한 프레임워크 안의 에이전트 사이에서, 프레임워크가 주는 것이라면 무엇이든 사용합니다 — Claude Code의 서브에이전트, LangGraph 서브그래프, CrewAI 크루 등. 이것이 가장 빠르지만 한 런타임에 잠깁니다.
  • 프레임워크, 팀, 벤더를 넘나드는 에이전트 사이에서는 A2A로 손을 뻗습니다. 런타임 측은 Open-Source AI Agent Frameworks 를 읽으세요; A2A는 그 런타임들 사이의 와이어입니다.

경험 법칙: 경계가 프로세스 경계라면, 프레임워크 네이티브 인계가 괜찮습니다. 조직, 클라우드, 신뢰 경계라면 A2A를 사용하세요.

출처 및 추가 자료​