Skip to main content
Summary

발견 다음에는 업무 표현이 필요하다

앞 장에서 Agent Card를 에이전트의 명함이자 서비스 메뉴판으로 보았다. 이제 클라이언트 에이전트는 이런 질문을 할 수 있다. "이 에이전트가 무엇을 할 수 있는지는 알겠다. 그렇다면 실제 업무는 어떤 모양으로 맡겨야 할까?"

A2A의 답은 단순한 채팅 로그가 아니다. A2A는 일을 Task, 대화를 Message, 결과물을 Artifact로 나누어 표현한다. 세 가지를 쉬운 비유로 보면 이렇다.

  • Task는 업무 티켓이다. "시장 조사 보고서 작성", "고객 불만 원인 분석", "구매 가능 여부 확인"처럼 완료 여부를 추적해야 하는 하나의 일이다.

  • Message는 업무 티켓 안에서 오가는 대화 메모다. 요청, 질문, 답변, 중간 설명이 여기에 담긴다.

  • Artifact는 납품물이다. 최종 보고서, JSON 데이터, 파일, 이미지, 분석 결과처럼 업무가 만들어 낸 결과다.

이 구분이 중요한 이유는 명확하다. 에이전트 협업에서는 "말을 주고받았다"보다 "일이 어디까지 진행됐고, 무엇이 결과로 남았는가"가 더 중요하다. A2A의 공식 모델에서도 Message는 클라이언트와 원격 에이전트 사이의 한 번의 의사소통 단위이고, Task는 상태를 가진 기본 작업 단위이며, Artifact는 Task의 결과로 생성되는 출력물로 설명된다.1

Task, Message, Artifact로 업무를 표현하기AI 생성 이미지

Task: 오래 걸리는 일을 추적하는 업무 티켓

Task는 A2A 협업의 중심이다. 짧은 질문이라면 원격 에이전트가 바로 Message로 답하고 끝낼 수 있다. 예를 들어 "지원하는 파일 형식이 무엇인가?" 같은 질문은 상태 추적이 필요하지 않을 수 있다. 그러나 "지난 분기 고객 이탈 원인을 분석하고 보고서를 만들어 달라"는 요청은 다르다. 데이터를 확인하고, 분석하고, 중간에 조건을 물어보고, 결과물을 만들어야 한다. 이런 요청은 Task로 다루는 것이 자연스럽다.

A2A에서 클라이언트가 Message를 보내면 원격 에이전트는 크게 두 가지 방식으로 응답할 수 있다. 단순한 상호작용이면 바로 Message를 돌려줄 수 있고, 추적이 필요한 업무라면 Task를 만들어 돌려줄 수 있다. Task가 만들어지면 클라이언트는 Task ID를 기준으로 진행 상황을 조회하거나, 스트리밍 업데이트를 받거나, 필요할 때 취소를 요청할 수 있다.1

Task는 업무의 현재 위치를 보여준다. 상태 이름은 명세 버전과 바인딩에 따라 TASK_STATE_WORKING처럼 enum 형태로 보이거나, 문서 설명에서는 working처럼 사람이 읽기 쉬운 이름으로 표현될 수 있다. 개념적으로는 다음과 같이 이해하면 된다.

  1. submitted: 요청이 접수되었다.

  2. working: 원격 에이전트가 작업 중이다.

  3. input-required: 추가 입력이 필요해 잠시 멈춰 있다.

  4. auth-required: 인증이나 권한 확인이 필요하다.

  5. completed: 작업이 완료되었다.

  6. failed: 작업에 실패했다.

  7. canceled: 작업이 취소되었다.

  8. rejected: 에이전트가 요청을 받아들일 수 없어 거절했다.

여기서 input-required와 auth-required는 실패라기보다 중단 상태에 가깝다. 필요한 정보나 권한이 채워지면 같은 업무 흐름을 이어 갈 수 있다. 반대로 completed, failed, canceled, rejected는 종료 상태다. A2A의 Task 생명주기 설명에서도 Task가 종료 상태에 도달하면 그 Task를 다시 시작하지 않는다고 설명한다. 후속 수정이나 추가 요청은 같은 맥락을 유지하되 새 Task로 다루는 편이 안전하다.2

이 지점에서 중요한 설계 원칙이 나온다. Task를 "함수 호출 결과를 기다리는 포장지" 정도로 보면 부족하다. Task는 작업의 책임 경계를 만든다. 원격 에이전트는 같은 Task 안에서 자신이 어디까지 처리했는지, 무엇이 필요한지, 어떤 결과를 냈는지 표현한다. 클라이언트 에이전트는 그 상태를 보고 기다릴지, 추가 정보를 줄지, 취소할지, 다음 에이전트에게 넘길지를 판단한다.

Message: 요청과 질문, 중간 보고를 담는 대화 단위

Message는 Task 안팎에서 오가는 대화 단위다. 비유하면 업무 티켓에 붙는 댓글이나 메모에 가깝다. 클라이언트가 처음 보내는 요청도 Message이고, 원격 에이전트가 "분석 범위를 확인해 주세요"라고 묻는 것도 Message다. 작업 중간에 "현재 데이터 수집을 마쳤고, 이상치를 검토 중입니다"라고 알리는 것도 Message로 표현할 수 있다.

A2A에서 Message에는 역할이 있다. 요청하는 쪽의 메시지는 user 역할, 응답하는 에이전트의 메시지는 agent 역할로 볼 수 있다. 여기서 user는 반드시 실제 사람만 뜻하지 않는다. A2A에서는 클라이언트 에이전트가 사용자를 대신해 원격 에이전트에게 요청할 수 있으므로, user 역할은 "요청을 제시하는 쪽"에 가깝다.

Message는 하나 이상의 Part를 담을 수 있다. Part는 내용을 담는 가장 작은 조각이다. 하나의 Message 안에 텍스트 설명, 첨부 파일 참조, 구조화된 JSON 조건이 함께 들어갈 수 있다. 예를 들어 클라이언트 에이전트가 다음과 같은 요청을 보낸다고 하자.

  • 텍스트 Part: "지난 3개월 고객 이탈 원인을 분석해 주세요."

  • 파일 Part: 고객 활동 로그 CSV 파일 참조

  • JSON Part: { "region": "KR", "segment": "enterprise" }

이렇게 하면 원격 에이전트는 자연어 요청만 받는 것이 아니라, 처리에 필요한 자료와 조건을 함께 받는다. 반대로 원격 에이전트가 추가 질문을 할 때도 Message를 쓴다.

"이탈 고객의 기준을 30일 미접속으로 볼까요, 아니면 구독 해지로 볼까요?"

이 질문이 오면 Task 상태는 input-required가 될 수 있다. 클라이언트 에이전트는 사용자에게 확인하거나 자체 정책에 따라 답한 뒤, 같은 맥락 안에서 새 Message를 보낸다. 이때 이미 진행 중인 Task에 대한 답이라면 해당 Task ID를 함께 붙여 "이 답변은 이 업무 티켓을 계속 진행하기 위한 것"임을 알려 줄 수 있다. 이렇게 해야 원격 에이전트가 같은 업무 흐름을 이어서 처리하기 쉽다.2

또 하나 기억할 점은 맥락과 Task가 완전히 같은 말은 아니라는 것이다. A2A에는 관련된 Message와 Task를 묶기 위한 contextId 개념이 있다. 하나의 contextId 안에서 여러 Task가 생길 수 있고, 이미 완료된 Task를 참고해 새 Task를 시작할 수도 있다. 예를 들어 "보고서를 만들어 주세요" Task가 완료된 뒤 "방금 보고서를 임원용 한 장 요약으로 줄여 주세요"라고 요청한다면, 기존 Task를 다시 여는 것이 아니라 같은 contextId 안에서 새 Task를 만드는 식이다. 필요하면 Message의 referenceTaskIds로 이전 Task를 가리킬 수 있다.2

이 구조 덕분에 A2A 협업은 한 번의 요청-응답으로 끝나지 않는다. 필요한 만큼 확인과 보완을 거칠 수 있고, 완료된 결과를 바탕으로 새로운 후속 업무도 안전하게 이어 갈 수 있다.

Artifact: 말이 아니라 남는 결과물

Artifact는 Task가 만들어 낸 산출물이다. Message가 대화라면 Artifact는 납품물이다. 최종 보고서, 요약 문서, 생성된 이미지, 분석 결과 JSON, 변환된 파일, 추천 목록 등이 Artifact가 될 수 있다.

이 구분은 실무에서 매우 중요하다. 채팅형 시스템에서는 결과가 긴 답변 하나로 섞여 버리기 쉽다. 그러면 어느 부분이 설명이고, 어느 부분이 실제로 저장해야 할 결과인지 모호해진다. A2A는 Artifact를 별도로 다룸으로써 "이 Task의 결과로 무엇이 생성되었는가"를 명확히 남긴다.

예를 들어 고객 이탈 분석 Task의 최종 결과는 다음처럼 여러 Artifact로 나뉠 수 있다.

  • churn_report.pdf: 경영진에게 전달할 보고서

  • summary.json: 주요 원인과 지표를 담은 구조화 데이터

  • segments.csv: 위험 고객군 목록

  • recommendations.md: 후속 캠페인 제안

Artifact도 Message처럼 여러 Part로 구성될 수 있다. 간단한 텍스트 결과일 수도 있고, 파일 참조일 수도 있으며, 다른 시스템이 바로 읽을 수 있는 JSON일 수도 있다. A2A 명세는 Artifact를 문서, 이미지, 구조화 데이터 같은 Task 결과 출력으로 보고, 스트리밍 중 Artifact 업데이트로 전달하거나 Task 조회 결과에 포함할 수 있게 한다.1

Artifact는 반드시 마지막에만 나오는 것은 아니다. 긴 작업에서는 부분 결과가 먼저 나올 수 있다. 예를 들어 분석 에이전트가 먼저 "초기 통계 요약" Artifact를 보내고, 나중에 "최종 보고서" Artifact를 추가할 수 있다. 클라이언트 에이전트는 이를 이용해 사용자에게 중간 검토를 요청하거나, 다른 에이전트에게 다음 작업을 미리 맡길 수 있다.

여기서 Artifact와 Message의 차이를 다시 한 번 분명히 해 두자. "현재 70% 진행되었습니다"는 대개 Message나 상태 업데이트에 가깝다. 반면 "현재까지 계산한 위험 고객군 목록"처럼 저장하고 재사용할 수 있는 결과는 Artifact로 남기는 편이 좋다. 이렇게 나누면 나중에 사람이 검토하거나 다른 에이전트가 이어받을 때 훨씬 덜 헷갈린다.

긴 작업은 멈추고, 묻고, 다시 진행한다

A2A의 장점은 긴 작업에서 잘 드러난다. 구매 컨시어지 예시를 생각해 보자. 사용자가 "팀 행사에 필요한 점심을 주문해 줘"라고 말한다. 클라이언트 에이전트는 Agent Card를 보고 음식 주문을 처리할 수 있는 판매자 에이전트를 찾는다. 그런 다음 주문 요청 Message를 보낸다. Google의 A2A 구매 컨시어지 예제도 클라이언트가 판매자 에이전트의 Agent Card를 확인한 뒤 메시지를 보내고, 서버가 이를 완료해야 할 Task로 평가하는 흐름을 보여 준다.3

실제 흐름은 이렇게 진행될 수 있다.

  1. 클라이언트 에이전트가 Message를 보낸다.
    "20명 점심 메뉴를 추천하고 주문 가능 여부를 확인해 주세요. 예산은 1인당 15,000원입니다."

  2. 원격 판매자 에이전트가 Task를 만든다.
    상태는 submitted에서 working으로 바뀐다.

  3. 판매자 에이전트가 중간 Message를 보낸다.
    "채식 옵션 포함 여부와 알레르기 정보를 확인해야 합니다."

  4. Task 상태가 input-required가 된다.
    작업은 실패한 것이 아니다. 필요한 정보가 없어 잠시 멈춘 것이다.

  5. 클라이언트 에이전트가 사용자에게 확인한 뒤 Message를 보낸다.
    "채식 옵션 3개가 필요하고, 견과류 알레르기 1명이 있습니다." 이 Message는 같은 contextId와 진행 중인 Task ID를 통해 앞의 업무와 연결된다.

  6. 판매자 에이전트가 다시 작업한다.
    상태는 working으로 돌아간다.

  7. 판매자 에이전트가 부분 Artifact를 보낸다.
    메뉴 후보와 가격표가 JSON 또는 표 파일로 전달된다.

  8. 클라이언트 에이전트가 승인 Message를 보낸다.
    "A안으로 진행해 주세요."

  9. 판매자 에이전트가 주문을 완료하고 최종 Artifact를 보낸다.
    주문 확인서, 결제 정보, 배송 예정 시간이 결과로 남는다. Task 상태는 completed가 된다.

이 흐름에서 핵심은 추가 질문이 예외가 아니라 정상 흐름이라는 점이다. 사람끼리 일할 때도 모든 정보가 처음부터 완벽히 주어지는 경우는 드물다. 에이전트 협업도 마찬가지다. 좋은 프로토콜은 중간 질문, 승인 대기, 부분 결과, 취소 가능성을 표현할 수 있어야 한다.

또한 완료 이후의 후속 요청도 자연스럽게 이어 갈 수 있어야 한다. 예를 들어 주문이 끝난 뒤 사용자가 "같은 조건으로 다음 주 금요일에도 예약해 줘"라고 말할 수 있다. 이때는 이미 완료된 Task를 되살리는 것이 아니라, 같은 contextId 안에서 이전 Task를 참고하는 새 Task를 만드는 편이 맞다. 그래야 이전 주문의 결과와 새 주문의 결과가 서로 섞이지 않고, 각각 독립적인 업무 기록으로 남는다.

상태와 결과를 분리하면 운영이 쉬워진다

Task, Message, Artifact를 나누면 운영 관점에서도 이점이 있다. 장애가 발생했을 때 "어떤 메시지 이후에 멈췄는가", "현재 상태가 작업 중인가 입력 대기인가", "이미 생성된 결과물이 있는가"를 분리해서 볼 수 있다.

예를 들어 Task가 failed라면 클라이언트는 실패 원인을 담은 Message를 확인할 수 있다. 이미 일부 Artifact가 생성되었다면 재시도 전략도 달라진다. 처음부터 다시 실행할지, 부분 결과를 재사용할지 판단할 수 있다. Task가 canceled라면 원격 에이전트는 더 이상 외부 시스템 호출이나 비용이 큰 작업을 진행하지 않도록 정리해야 한다.

input-required도 운영 관점에서는 중요한 신호다. 이 상태를 단순 오류로 처리하면 사용자에게 "작업 실패"라고 잘못 알릴 수 있다. 실제로는 "추가 정보가 필요해 대기 중"인 상태일 뿐이다. 따라서 클라이언트 에이전트는 상태에 따라 사용자에게 질문을 표시할지, 인증 절차로 안내할지, 취소 버튼을 보여 줄지, 재시도할지를 다르게 설계해야 한다.

또한 이 구조는 멀티 에이전트 워크플로에도 유리하다. 한 에이전트가 만든 Artifact를 다른 에이전트의 Message 입력으로 넘길 수 있기 때문이다. 예를 들어 리서치 에이전트가 market_findings.json Artifact를 만들고, 보고서 작성 에이전트가 그것을 입력 Part로 받아 최종 문서를 만들 수 있다. 이때 클라이언트 에이전트는 각 Task의 상태와 결과물을 연결해 전체 흐름을 조율한다.

Task 중심으로 생각하라

A2A를 처음 구현할 때 흔한 실수는 모든 것을 Message 중심으로만 설계하는 것이다. 그러면 시스템은 채팅처럼 보이지만, 실제 업무 관리에는 약해진다. 어떤 요청이 아직 처리 중인지, 무엇이 완료되었는지, 어떤 결과가 공식 산출물인지 추적하기 어렵다.

A2A에서는 반대로 생각하는 편이 좋다.

먼저 "이 요청은 추적할 가치가 있는 업무인가?"를 판단한다. 그렇다면 Task로 다룬다. 그다음 Task 안에서 필요한 Message를 주고받는다. 마지막으로 남겨야 할 결과는 Artifact로 만든다. 그리고 업무가 끝난 뒤의 수정이나 후속 요청은 같은 contextId 안에서 새 Task로 이어 간다.

이 단순한 구분이 A2A 협업 모델의 핵심이다. Message는 대화를 가능하게 하고, Artifact는 결과를 남기며, Task는 그 모든 과정을 하나의 업무 흐름으로 묶는다. 그래서 A2A의 중심은 메시지 교환이 아니라 완료 상태를 추적할 수 있는 태스크 협업이다.

참고

1A2A Protocol Specification

2Life of a Task - A2A Protocol

3Agent2Agent Protocol Codelab: Purchasing Concierge

책 목록

Agent2Agent: Google A2A로 배우는 멀티 에이전트 상호운용성

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기