Python에서 A2A를 사용하여 결정론적 멀티 에이전트 파이프라인 구축하기
요약
A2A Orchestration Lab을 사용하여 Python 환경에서 결정론적 멀티 에이전트 파이프라인을 구축하는 방법을 설명합니다. 모델의 동작과 통신 흐름을 분리하여 A2A와 MCP의 관계를 명확히 이해할 수 있는 튜토리얼을 제공합니다.
핵심 포인트
- A2A를 활용한 오케스트레이터, 리서처, 라이터 간의 에이전트 통신 흐름 학습
- 결정론적 스텁을 사용하여 모델 동작과 프로토콜을 분리하여 검증 가능
- uv를 이용한 간편한 환경 설정 및 엔드-투-엔드 데모 실행 방법 안내
- Model Context Protocol(MCP)과 A2A의 역할 차이 이해
멀티 에이전트 (Multi-agent) 예제들은 종종 모델, 도구, 그리고 프로덕션(production)에 대한 주장으로 곧장 건너뛰곤 합니다. 이로 인해 프로토콜이 실제로 무엇을 하고 있는지 파악하기 어렵게 만듭니다. LLM (Large Language Model)을 추가하기 전에, 작은 시스템이 전문가를 발견하고, 작업을 위임하며, 검사 가능한 결과를 반환하는 과정을 지켜보는 것이 유용합니다.
이 튜토리얼은 Fernando Paladini가 만든 오픈 소스 Python 프로젝트인 A2A Orchestration Lab을 사용합니다. 이 프로젝트는 오케스트레이터 (orchestrator), 리서처 (researcher), 라이터 (writer)라는 세 개의 로컬 에이전트를 시작합니다. 리서처와 라이터는 결정론적 스텁 (deterministic stubs)이므로, 이 예제는 모델의 동작으로부터 Agent2Agent (A2A) 통신 흐름을 분리하여 보여줍니다.
그 결과, A2A가 Model Context Protocol (MCP) 옆에서 어떤 역할을 하는지 설명하는 데 도움이 되는 실행 가능한 '리서치-투-라이트 (research-to-write)' 파이프라인이 완성됩니다.
요약 (TL;DR)
uv로 랩(lab)을 설치하고, demo 명령어를 실행한 뒤, 세 개의 로컬 에이전트 카드 (Agent Cards)와 위임된 결과를 확인하세요. 이 프로젝트는 학습용 랩이며, 프로덕션 런타임 (production runtime)이 아닙니다. 모든 움직이는 구성 요소가 가시적으로 유지된다는 점이 이 튜토리얼에서는 오히려 특징이 됩니다.
사전 요구 사항
다음이 필요합니다:
- Python 3.12 이상.
- 환경 및 의존성 관리를 위한 uv.
- 초기 의존성 다운로드를 위한 네트워크 접속이 가능한 터미널.
해당 저장소는 버전 0.1.0을 선언하며, Python >=3.12를 요구하고, A2A Python SDK, httpx, 그리고 uvicorn에 의존합니다. 라이선스는 MIT입니다.
랩 생성 및 실행
공개 저장소를 클론(clone)하고 uv가 잠긴 의존성(locked dependencies)으로부터 환경을 생성하도록 합니다:
git clone https://github.com/paladini/a2a-orchestration-lab.git
cd a2a-orchestration-lab
uv sync
번들로 제공되는 엔드-투-엔드 (end-to-end) 데모를 실행합니다:
uv run a2a-lab demo "Explain A2A and how it relates to MCP"
CLI는 세 개의 에이전트를 서브프로세스 (subprocesses)로 시작하고, 이들의 에이전트 카드 (Agent Cards)를 기다린 다음, 오케스트레이터 (orchestrator)에 메시지를 보내고, 응답을 출력한 뒤 자식 프로세스들을 종료합니다. 기본 프롬프트 (prompt)는 리포지토리 README에서 사용된 것과 동일한 설명이지만, 자신만의 프롬프트를 사용하면 위임 (delegation) 과정을 더 쉽게 인식할 수 있습니다.
실행에 성공하면 출력 결과에 다음과 유사한 섹션들이 포함됩니다:
[demo] asking orchestrator: 'Explain A2A and how it relates to MCP'
## Orchestrator result
...
정확한 문구는 로컬 스텁 (stubs)에 의해 생성되며 리포지토리 업데이트에 따라 변경될 수 있습니다. 중요한 결과는 다음과 같은 시퀀스 (sequence)입니다: 오케스트레이터가 프롬프트를 수신하고, 조사를 위임한 다음, 조사 결과를 작성자 (writer)에게 전달합니다.
세 개의 에이전트 조사하기
이 랩 (lab)은 각 서비스를 독립적으로 실행할 수도 있습니다. 리포지토리에서 터미널 세 개를 열고 각각 다음 명령어를 실행하세요:
uv run a2a-lab run researcher
uv run a2a-lab run writer
uv run a2a-lab run orchestrator
서비스들은 루프백 주소 (loopback addresses)에서 대기합니다:
- Orchestrator:
http://127.0.0.1:9100 - Researcher:
http://127.0.0.1:9101 - Writer:
http://127.0.0.1:9102
각 서비스는 /.well-known/agent-card.json에서 에이전트 카드 (Agent Card)를 노출합니다. 예시는 다음과 같습니다:
에이전트 카드는 디스커버리 표면 (discovery surface)입니다. 이는 클라이언트에게 에이전트가 무엇인지, 어디에서 사용 가능한지, 그리고 어떤 기술 (skills)이나 인터페이스 (interfaces)를 광고하는지를 알려줍니다. 이 랩에서 카드를 열어보는 것은 프로토콜 개념을 실제 HTTP 응답과 연결하는 실질적인 방법입니다.
작업이 끝나면 Ctrl+C로 세 프로세스를 중단하세요. 일회성 demo 명령어는 finally 블록에서 자식 프로세스 정리를 처리합니다.
소스 코드에서 위임 경로 따라가기
가장 유용한 소스 코드 읽기 경로는 짧습니다:
src/a2a_lab/cli.py에서 시작하세요.cmd_demo함수는 에이전트들을 시작하고 그들의 카드(cards)를 기다립니다._ask_orchestrator는 오케스트레이터 카드(orchestrator card)를 확인(resolve)하고, A2A 클라이언트(client)를 생성하며, 텍스트 메시지를 전송합니다.- 에이전트 서버(agent server) 및 실행기(executor) 모듈을 읽어 로컬 프로세스가 어떻게 A2A 서비스가 되는지, 그리고 작업 생명주기 상태(task lifecycle states)가 어떻게 처리되는지 확인하세요.
- 오케스트레이터 에이전트(orchestrator agent)를 읽어 리서처(researcher)와 라이터(writer)로의 클라이언트 측 위임(client-side delegation)을 확인하세요.
CLI는 SendMessageRequest를 위해 A2A Python SDK 타입을 사용한 다음, 응답 스트림(response stream)을 텍스트로 수집합니다. 이는 유용한 분리 방식입니다. CLI는 데모의 생명주기(lifecycle)를 관리하고, 에이전트 모듈은 역할을 구현합니다.
A2A와 MCP는 서로 다른 경계를 해결합니다
A2A는 에이전트 발견(agent discovery) 및 작업 지향 통신(task-oriented communication)을 위한 프로토콜로 스스로를 정의합니다. 핵심 개념에는 메시지(messages), 작업(tasks), 아티팩트(artifacts), 에이전트 카드(Agent Cards), 그리고 작업 업데이트(task updates)가 포함됩니다. 이 랩(lab)에서 A2A는 오케스트레이터와 전문 에이전트(specialist agents) 사이의 수평적 연결입니다.
MCP는 LLM 애플리케이션과 외부 데이터 소스 또는 도구 간의 연결을 표준화합니다. 서버 기능에는 리소스(resources), 프롬프트(prompts), 도구(tools)가 포함됩니다. 따라서 MCP는 에이전트가 파일 시스템 액세스, 검색 또는 코드 분석 도구와 같은 기능(capability)이 필요할 때 자연스러운 경계가 됩니다.
간단한 멘탈 모델(mental model)은 다음과 같습니다:
사용자(user) -> A2A 오케스트레이터(orchestrator) -> A2A 리서처(researcher)
-> A2A 라이터(writer)
|
...
이 랩은 MCP를 구현하지 않습니다. README에서는 MCP를 A2A 학습 경로 이후의 추가 사항으로 명시적으로 다루고 있습니다. 이는 이 프로젝트가 다른 프로토콜을 도입하기 전에 에이전트 간 위임(agent-to-agent delegation)을 이해하기에 좋은 장소임을 의미합니다.
데모가 증명하는 것과 증명하지 못하는 것
스모크 테스트 (smoke test)는 선언된 Python 환경이 해결되고, 세 가지 서비스가 시작되며, Agent Cards에 접근할 수 있게 되고, 클라이언트가 오케스트레이터 (orchestrator)로 메시지를 보낼 수 있으며, 파이프라인이 결과를 반환한다는 것을 증명합니다. 이는 모델의 품질, 분산 신뢰성 (distributed reliability), 인증 (authentication), 또는 프로덕션 준비 상태 (production readiness)를 증명하는 것은 아닙니다.
이 프로젝트는 의도적으로 몇 가지 누락된 프로덕션 관련 사항들을 나열하고 있습니다: 이식 가능한 작업 체크포인팅 (portable task checkpointing), 기능 토큰 (capability tokens), 강력한 샌드박싱 (strong sandboxing), 멀티 벤더 ID 및 신뢰 (multi-vendor identity and trust), 예산 (budgets), 기본 요소로서의 감사 (audit as a primitive), 그리고 관리되는 비즈니스 컨텍스트 (governed business context)입니다. 해당 목록을 로드맵에 대한 약속이 아닌, 구현 경계 (implementation boundary)로 취급하십시오.
또한 이 실습은 루프백 (loopback) HTTP 서비스와 로컬 지식 베이스 스텁 (knowledge-base stubs)을 사용합니다. 세 개의 포트를 네트워크에 노출하고 localhost가 권한 부여를 의미한다고 가정하지 마십시오. 스텁을 실제 도구나 모델로 교체하는 경우, 민감한 입력을 처리하기 전에 인증 (authentication), 권한 부여 (authorization), 타임아웃 (timeouts), 속도 제한 (rate limits), 구조화된 로그 (structured logs), 그리고 명시적인 데이터 처리 규칙을 추가하십시오.
실패 모드 및 문제 해결 (Failure modes and troubleshooting)
uv sync가 실패하면, python --version으로 Python 버전을 확인하고 uv --version으로 도구 버전을 확인하십시오. 이 프로젝트는 Python 3.12 이상을 요구합니다.
데모에서 에이전트가 준비되지 않았다고 보고하면, 9100, 9101 또는 9102 포트가 이미 사용 중인지 확인하십시오. CLI는 각 Agent Card에 대해 최대 15초 동안 대기합니다. 오래된 프로세스를 중지하고 다시 시도하십시오.
데모가 결과를 출력하지만 내용이 예상외로 짧다면, 연구자 (researcher)와 작성자 (writer)가 결정론적 스텁 (deterministic stubs)임을 기억하십시오. 흐름을 탐색하려면 로컬 지식 베이스나 프롬프트를 변경하십시오. LLM을 추가하는 것은 별도의 실험이며, A2A를 이해하기 위한 전제 조건은 아닙니다.
FAQ
이 실습에 API 키가 필요한가요?
아니요. README에서는 첫날의 워크플로우를 API 키가 없는 로컬 환경으로 설명합니다. 현재의 에이전트들은 결정론적 스텁을 사용합니다.
A2A가 MCP를 대체하는 것인가요?
아니요. A2A는 에이전트와 에이전트를 연결합니다. MCP는 AI 애플리케이션을 도구(tools) 및 데이터 소스(data sources)와 연결합니다. 하나의 시스템이 두 가지를 모두 사용할 수 있으며, A2A 전문가(specialist)가 해당 기능이 전문가 경계(specialist boundary) 내에 속할 때 MCP 도구를 호출하는 방식으로 작동합니다.
데모가 계속 실행되나요?
아니요. uv run a2a-lab demo는 에이전트를 시작하고, 하나의 태스크(task)를 실행한 뒤, 결과를 출력하고 에이전트들을 종료합니다. 서비스를 수동으로 점검하고 싶을 때는 별도의 run 명령어를 사용하세요.
이것을 프로덕션(production) 환경에서 사용할 수 있나요?
아니요. 이 프로젝트는 스스로를 학습용 랩(learning lab)이라고 명시적으로 설명하고 있으며, 여전히 남아 있는 라이프사이클(lifecycle), 정체성(identity), 역량(capability), 예산(budget), 감사(audit), 거버넌스(governance)의 격차를 언급하고 있습니다.
핵심 요약 (Takeaway)
A2A는 첫 번째 예시가 결정론적(deterministic)일 때 추론하기가 더 쉬워집니다. 오케스트레이션 랩(Orchestration Lab)은 점검 가능한 세 개의 로컬 서비스, 발견 가능한 에이전트 카드(Agent Cards), 실제 위임 경로(delegation path), 그리고 나중에 MCP를 추가할 수 있는 명확한 위치를 제공합니다.
저는 이 튜토리얼을 정리하고 편집하는 데 AI의 도움을 받았습니다. 리포지토리(repository)의 README, pyproject.toml, 학습 노트, CLI 소스, MIT 라이선스, 공식 A2A 명세(specification), 공식 MCP 명세, 그리고 실제 uv sync 및 데모 실행 결과는 별도로 검증되었습니다.
이 랩에서 가장 먼저 무엇을 교체하시겠습니까: 연구자 스텁(researcher stub), 작성자 스텁(writer stub), 아니면 오케스트레이터(orchestrator)의 라우팅 로직(routing logic)인가요?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기