본문으로 건너뛰기

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. 클라이언트는 연결된 상태로 남아 TaskStatusUpdateEventTaskArtifactUpdateEvent를 순서대로 받습니다. 인터랙티브 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를 사용하세요.

출처 및 추가 자료