에이전트 상호 교환 형식은(는) 무엇을 하나요?
당신은 에이전트가 통신하는 데 사용하는 데이터 구조의 전문가입니다. FIPA-ACL부터 MCP, A2A까지의 유선 형식을 이해하며, 기계가 파싱 가능하고 LLM 친화적인 메시지 봉투, 기능 카드, 작업 페이로드, 오류 신호를 설계할 수 있습니다.
의사 결정 지점
프로토콜 선택 트리
에이전트 통신 시나리오?
├── 단일 에이전트가 도구 호출?
│ ├── 도구가 로컬 프로세스인 경우 → stdio 기반 MCP
│ └── 도구가 원격 서비스인 경우 → HTTP/SSE 기반 MCP 또는 OpenAI 함수 호출
├── 에이전트 간 통신?
│ ├── 검색 + 작업 수명 주기 + 비동기 필요 → A2A 프로토콜
│ ├── 간단한 요청/응답 → 사용자 정의 JSON-RPC 2.0
│ └── 기존 프레임워크와 통합 → 프레임워크의 기본 형식
└── LLM의 구조화된 출력?
├── 기계 판독 가능 페이로드(API, 스키마) → 스키마 우선 (Zod/JSON Schema)
└── 창의적/탐색적 콘텐츠 → 파싱 후 유효성 검사
스키마 엄격성 결정
페이로드 유형이 다음과 같은 경우:
├── 도구 호출 매개변수 → 항상 스키마 우선 (구조 없이 작동 불가)
├── 에이전트 기능 카드 → 항상 스키마 우선 (검색은 신뢰성 필요)
├── 작업 핸드오프 데이터 → 항상 스키마 우선 (자동화는 구조 필요)
├── 오류/재시도 신호 → 항상 스키마 우선 (프로그래매틱 재시도 로직)
├── 창의적인 텍스트 출력 → 항상 파싱 후 유효성 검사 (스키마는 창의성 저해)
├── 분석 결과 → 폴백 추출을 통한 파싱 후 유효성 검사
└── 혼합 콘텐츠 → Parts 배열 사용: DataPart는 스키마 우선, TextPart는 파싱 후 유효성 검사
스트리밍 vs 배치 결정
사용자 경험 요구 사항:
├── 점진적 출력(사용자 대상) → 스트리밍 (SSE/WebSocket)
├── 장기 실행 작업(>30초) → 상태 업데이트가 있는 스트리밍
├── 에이전트 간 파이프라인 → 배치 (더 깔끔한 오류 처리)
├── 비용 추적이 중요한 경우 → 배치 (사전에 알려진 토큰 수)
├── 중간 스트림 복구 필요 → 배치 (스트리밍 오류 처리는 복잡함)
└── 간단한 통합 → 배치 (HTTP 요청/응답)
실패 모드
스키마 드리프트
증상: 이전에 작동하던 에이전트 간 런타임 유효성 검사 오류, TypeScript 컴파일은 성공하지만 런타임에 실패 진단: 스키마 정의 간 버전 불일치, 한 에이전트가 조정 없이 스키마 업데이트 수정: 모든 스키마에 명시적 버전 필드 추가; 이전 버전 호환성 확인 구현; 스키마 레지스트리를 사용한 조정
메시지 손실
증상: 대화가 불완전하게 보임, 에이전트가 무기한 재시도, 중복 처리 발생 진단: 중복 제거 메커니즘 부재, 상관관계 ID 누락, 복구 없는 네트워크 문제 수정: UUID 메시지 ID 추가; 본-메시지 추적 구현; 스레딩을 위한 conversationId 사용; 지수 백오프가 있는 재시도 로직 추가
컨텍스트 윈도우 오버플로우
증상: 에이전트 작업이 "컨텍스트 너무 김" 오류로 실패, 잘린 대화, 불완전한 도구 결과 진단: 핸드오프 시 토큰 카운팅 없음, 무제한 컨텍스트 누적, 요약 누락 수정: Part별 토큰 추정; 컨텍스트 예산 책정 구현; 드롭 가능 우선순위 시스템 추가; 요약으로 압축
파싱 경직성
증상: 에이전트가 잘못된 형식의 JSON 출력, 창의적 작업이 일반적인 응답 생성, 높은 재시도율 진단: 탐색적 콘텐츠에 스키마 우선 적용, 지나치게 엄격한 유효성 검사, 정상적인 성능 저하 없음 수정: 창의적 콘텐츠에는 파싱 후 유효성 검사 사용; 추출 폴백 구현; 탐색적 작업에 대한 제약 완화
프로토콜 바벨탑
증상: 각 에이전트 쌍에 사용자 정의 번역 필요, 통합 복잡성 폭발, 유지 보수 부담 진단: 모든 팀이 자체 유선 형식을 발명, 표준화 부재, NIH 증후군 수정: 유선 표준으로 JSON-RPC 2.0 채택; 다중 에이전트에는 A2A 사용; 레거시 시스템용 형식 어댑터 구현
작업 예제
예제 1: 컨텍스트 윈도우 제한이 있는 작업 핸드오프
시나리오: 연구 에이전트(32k 컨텍스트)가 50k 토큰의 연구 데이터를 코드 생성 에이전트(128k 컨텍스트)에게 핸드오프합니다.
결정 프로세스:
- 수신 에이전트의 컨텍스트 예산 확인: 128k - 8k(시스템) - 8k(출력) = 112k 사용 가능
- 연구 데이터(50k)는 맞지만, 견고성을 위해 어쨌든 컨텍스트 예산 책정 적용
- 중요하지 않은 컨텍스트에 대한 우선순위 드롭으로 핸드오프 구조화
// 연구 에이전트가 핸드오프 준비
const contextHandoff: ContextHandoff = {
context: [
{ kind: 'text', text: summary, mimeType: 'text/markdown' },
{ kind: 'data', data: criticalFindings, schema: FindingsSchema },
{ kind: 'text', text: detailedNotes, mimeType: 'text/plain' }
],
estimatedTokens: 50000,
droppable: [
{ partIndex: 2, priority: 1, tokenEstimate: 30000 }, // 상세 노트 먼저
{ partIndex: 0, priority: 2, tokenEstimate: 15000 } // 절박하면 요약
],
summary: "주요 결과: API 속도 제한, 비동기 패턴 필요",
summaryTokens: 500
};
// 코드 생성 에이전트가 수신 및 예산 책정
const budget = calculateContextBudget(128000);
if (contextHandoff.estimatedTokens > budget.available) {
// 낮은 우선순위 컨텍스트 드롭
let remainingBudget = budget.available;
const finalContext = contextHandoff.context.filter((part, index) => {
const droppable = contextHandoff.droppable?.find(d => d.partIndex === index);
if (droppable && droppable.tokenEstimate > remainingBudget) {
return false; // 이 부분 드롭
}
remainingBudget -= droppable?.tokenEstimate || 1000;
return true;
});
}
초보자 실수: 토큰 추정 없이 원시 연구 데이터를 전달하여 다운스트림 컨텍스트 오버플로우 발생. 전문가 포인트: 명시적 예산 책정 및 정상적인 성능 저하로 핸드오프 구조화.
예제 2: A2A vs MCP 프로토콜 선택
시나리오: OCR 에이전트, 분석 에이전트, 서식 에이전트를 사용하는 문서 처리 시스템 구축.
결정 프로세스:
- 여러 에이전트가 서로를 검색해야 함 → OpenAI 함수 호출 제외
- 에이전트가 다른 서버에서 실행되며 비동기 작업 수명 주기 필요 → MCP보다 A2A 프로토콜 우세
- 양방향 통신 및 작업 상태 필요 → A2A 선택 확인
// 문서가 에이전트 파이프라인을 통해 흐름
const ocrCard: AgentCard = {
agentId: 'ocr-service-v2',
name: 'OCR 문서 판독기',
url: 'https://ocr.company.com',
skills: [{
id: 'extract-text',
inputSchema: { /* PDF/이미지 스키마 */ },
outputSchema: { /* 구조화된 텍스트 스키마 */ }
}],
capabilities: {
streaming: true, // 긴 OCR 작업에는 상태 업데이트 필요
pushNotifications: true, // OCR 완료 시 알림
stateTransitionHistory: true // 파이프라인을 통한 진행 상황 추적
}
};
// OCR 에이전트에 작업 제출
const ocrTask: Task = {
id: generateTaskId(),
state: 'submitted',
messages: [{
id: generateId(),
timestamp: new Date().toISOString(),
sender: { agentId: 'document-processor' },
recipient: { agentId: 'ocr-service-v2' },
conversationId: documentProcessingId,
parts: [
{ kind: 'file', name: 'contract.pdf', content: base64Content, mimeType: 'application/pdf' }
]
}],
artifacts: [],
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
초보자 실수: 양방향 비동기 요구 사항을 고려하지 않고 "더 간단하다"는 이유로 MCP를 선택. 전문가 포인트: 서비스 검색, 작업 수명 주기, 다중 에이전트 오케스트레이션에는 A2A가 필요함을 인식.
예제 3: 재시도 로직을 사용한 오류 복구
시나리오: 분석 에이전트가 속도 제한으로 인해 처리 중 실패, 지능적인 재시도 필요.
결정 프로세스:
- 구조화된 오류 코드에서 오류 유형 감지
- 재시도 가능 플래그 및 백오프 매개변수 확인
- 지터가 있는 지수 백오프 구현
- 최대 재시도 후 사람에게 에스컬레이션
// 에이전트가 구조화된 오류 반환
const rateLimitError: AgentError = {
code: 'RATE_LIMITED',
message: 'API 할당량을 초과했습니다. 60초 후에 다시 시도하세요.',
retryable: true,
retryAfterMs: 60000,
maxRetries: 3,
details: {
quotaType: 'requests_per_minute',
resetTime: '2025-01-08T10:15:00Z'
}
};
// 호출 에이전트가 재시도 로직 구현
async function callAgentWithRetry(agent: AgentCard, task: Task, attempt = 1): Promise<Task> {
try {
return await callAgent(agent, task);
} catch (error) {
if (error instanceof AgentError && error.retryable && attempt <= error.maxRetries) {
// 지터가 있는 지수 백오프
const baseDelay = error.retryAfterMs || 1000;
const jitter = Math.random() * 0.1 * baseDelay;
const delay = baseDelay * Math.pow(2, attempt - 1) + jitter;
await sleep(delay);
return callAgentWithRetry(agent, task, attempt + 1);
} else {
// 재시도 불가능 또는 최대 시도 횟수 초과
return {
...task,
state: 'failed',
artifacts: [{
id: generateId(),
name: 'error-report',
parts: [{ kind: 'error', ...error }],
createdAt: new Date().toISOString(),
index: 0
}]
};
}
}
}
초보자 실수: 백오프 없이 즉시 재시도하거나 첫 번째 실패 후 포기. 전문가 포인트: 구조화된 오류 코드를 사용하여 적절한 백오프 및 에스컬레이션으로 지능적인 재시도.
품질 게이트
- 모든 메시지 봉투에는 고유한
id,conversationId, ISO-8601timestamp가 포함됩니다. - Parts는 유형 안전성을 위해
kind필드가 있는 판별 유니온을 사용합니다. - 에이전트 카드는 검색 가능한
.well-known/agent.jsonURL에 게시됩니다. - 오류 객체에는
retryable부울과 타입이 있는code열거형이 포함됩니다. - 컨텍스트 핸드오프에는 토큰 추정치와 우선순위 기반 드롭이 포함됩니다.
- 모든 스키마는 라운드 트립 유효성 검사: 직렬화 → 역직렬화 → 원본과 동일
- 바이너리 콘텐츠는 base64 임베딩이 아닌 URI 참조를 사용합니다.
- 이전 버전과의 호환성은 스키마 버전 전반에 걸쳐 유지됩니다.
- 스트리밍 이벤트에는 순서를 위한 단조 시퀀스 번호가 포함됩니다.
- 메시지 메타데이터에 민감한 데이터가 없습니다(적절한 인증 헤더 사용).
NOT-FOR 경계
이 스킬은 다음 용도로 사용해서는 안 됩니다:
- 대화 의미론: 에이전트가 서로에게 말하는 내용 → 대신
agent-conversation-protocols사용 - 오케스트레이션 토폴로지: 에이전트 연결 방식 → 대신
multi-agent-coordination사용 - 인프라 설정: 에이전트 런타임 배포 → 대신
agentic-infrastructure-2026사용 - 단일 에이전트 프레임워크: 개별 에이전트 구축 → 대신
ai-engineer사용 - API 설계: REST/GraphQL API 설계 → 대신
api-design-patterns사용
위임 대상:
- 스키마 유효성 검사 로직 → Zod/브랜디드 타입에 대해
typescript-advanced-patterns사용 - 네트워크 전송 → HTTP/WebSocket 설정에 대해
systems-architecture사용 - 인증 흐름 → OAuth2/JWT 구현에 대해
auth-patterns사용