A2A Protocol
A2A Java 샘플

코드 복제

git clone https://github.com/google-a2a/a2a-samples
cd a2a-samples/samples/java

이 프로젝트는 Agent-to-Agent (A2A) 프로토콜의 Java 구현 예제로, 완전한 클라이언트 및 서버 SDK와 AI 기반 번역 서비스 데모 애플리케이션을 제공합니다.

프로젝트 아키텍처

이 프로젝트는 Maven 멀티 모듈 아키텍처를 사용하며, 다음 세 가지 핵심 모듈을 포함합니다:

samples/java/
├── model/          # A2A 프로토콜 데이터 모델
├── server/         # A2A 서버 SDK 및 번역 서비스
├── client/         # A2A 클라이언트 SDK 및 예제 코드
└── pom.xml         # 부모 Maven 구성 파일

모듈 세부사항

🎯 모델 모듈 (model/)

A2A 프로토콜의 핵심 데이터 모델로, JSON-RPC 2.0 및 A2A 프로토콜을 위한 완전한 데이터 구조를 제공합니다:

  • 메시지 모델: Message, Part, TextPart, Artifact
  • 작업 모델: Task, TaskStatus, TaskState
  • 에이전트 모델: AgentCard, AgentCapabilities, AgentSkill
  • JSON-RPC 모델: JSONRPCRequest, JSONRPCResponse, JSONRPCError
  • 이벤트 모델: TaskStatusUpdateEvent, TaskArtifactUpdateEvent

🚀 서버 모듈 (server/)

Spring Boot 기반 A2A 서버 SDK로, Spring AI 프레임워크와 통합되어 있습니다:

  • 핵심 구성요소:

    • A2AServer: 에이전트 동작을 관리하는 메인 서버 클래스
    • A2AController: A2A 프로토콜 엔드포인트를 구현하는 REST 컨트롤러
    • TaskHandler: 작업 처리 인터페이스
    • A2AServerConfiguration: AI 번역 봇 구성
  • 주요 기능:

    • 완전한 JSON-RPC 2.0 지원
    • 에이전트 카드 게시 (/.well-known/agent-card)
    • 작업 관리 (전송, 조회, 취소)
    • 스트리밍 응답 지원 (Server-Sent Events)
    • OpenAI 및 기타 모델을 지원하는 Spring AI 통합

📱 클라이언트 모듈 (client/)

번역 클라이언트 예제가 포함된 순수 Java A2A 클라이언트 SDK:

  • 핵심 구성요소:

    • A2AClient: 모든 A2A 작업을 처리하는 메인 클라이언트 클래스
    • StreamingEventListener: 스트리밍 이벤트 리스너 인터페이스
    • A2AClientException: A2A 전용 예외 처리
    • A2AClientExample: 완전한 번역 클라이언트 예제
  • 주요 기능:

    • JSON-RPC 2.0 클라이언트 구현
    • 에이전트 발견 및 기능 조회
    • 동기/비동기 작업 처리
    • 스트리밍 응답 처리
    • 연결 풀링 및 오류 복구

핵심 기능 구현

🤖 AI 번역 서비스

이 프로젝트는 다국어 번역을 지원하는 지능형 번역 에이전트를 구현합니다:

번역 로직:

  • 중국어 → 영어
  • 영어 → 중국어
  • 기타 언어 → 영어

기술적 특징:

  • Spring AI ChatClient 기반
  • OpenAI, Azure OpenAI 및 기타 모델 지원
  • 컨텍스트 인식 자연어 번역
  • 실시간 스트리밍 응답

🔄 A2A 프로토콜 구현

A2A 프로토콜 사양의 완전한 구현:

핵심 작업:

  • tasks/send: 작업 메시지 전송
  • tasks/get: 작업 상태 조회
  • tasks/cancel: 작업 실행 취소

프로토콜 기능:

  • JSON-RPC 2.0 통신
  • 에이전트 기능 발견
  • 작업 상태 추적
  • 스트리밍 이벤트 푸시
  • 표준화된 오류 코드

📡 통신 메커니즘

동기 통신:

  • HTTP POST /a2a - 표준 JSON-RPC 요청
  • HTTP GET /.well-known/agent-card - 에이전트 정보 검색

스트리밍 통신:

  • HTTP POST /a2a/stream - Server-Sent Events
  • 실시간 작업 상태 업데이트
  • 자동 재연결 및 오류 복구

실행 방법

요구사항

  • Java: 17 이상

1단계: 프로젝트 컴파일

프로젝트 루트 디렉토리에서 컴파일을 실행합니다:

cd samples/java
./mvnw clean install -DskipTests

2단계: 환경 변수 구성

AI 모델 관련 환경 변수를 설정합니다 (번역 기능에 필요):

# OpenAI 구성
export OPENAI_API_KEY="your-openai-api-key"
export OPENAI_BASE_URL="https://api.openai.com"
export OPENAI_CHAT_MODEL="gpt-4o"

# 또는 GCP OpenAI 구성
export OPENAI_API_KEY="your-gcp-api-key"
export OPENAI_BASE_URL="https://{location}-aiplatform.googleapis.com/v1/projects/{project_id}/locations/{location}/endpoints/openapi"
export OPENAI_CHAT_MODEL="gemini-2.5-pro-preview-05-06"

OpenRouter 구성

export OPENAI_API_KEY="sk-or-v1-"
export OPENAI_BASE_URL="https://openrouter.ai/api"
export OPENAI_CHAT_MODEL="openai/gpt-4o-2024-11-20"

OPENAI_BASE_URL에 주의하세요. URL에 /v1이 없습니다.

3단계: 번역 서버 시작

A2A 번역 서버를 시작합니다:

cd server
../mvnw spring-boot:run

서버는 http://localhost:8080에서 시작되며, 다음 엔드포인트를 제공합니다:

  • http://localhost:8080/.well-known/agent-card - 에이전트 정보
  • http://localhost:8080/a2a - A2A 프로토콜 엔드포인트
  • http://localhost:8080/a2a/stream - 스트리밍 엔드포인트

에이전트 카드 검증:

4단계: 번역 클라이언트 실행

새 터미널 창에서 클라이언트 예제를 실행합니다:

cd client
../mvnw exec:java -Dexec.mainClass="com.google.a2a.client.A2AClientExample"

시퀀스 다이어그램

다음 시퀀스 다이어그램은 A2AClientExample.java를 기반으로 한 A2A Java 샘플 애플리케이션의 완전한 상호작용 흐름을 보여줍니다:

sequenceDiagram
    participant Example as A2AClientExample
    participant Client as A2AClient
    participant Server as A2A Server<br/>(localhost:8080)
    
    Note over Example,Server: A2A Java 샘플 시퀀스 다이어그램
    
    %% 1. 클라이언트 초기화
    Example->>Client: new A2AClient("http://localhost:8080")
    activate Client
    
    %% 2. 에이전트 카드 가져오기
    Example->>Client: getAgentCard()
    Client->>Server: GET /.well-known/agent-card
    Server-->>Client: AgentCard (name, description, version, skills)
    Client-->>Example: AgentCard
    Note over Example: 에이전트 정보 출력
    
    %% 3. 프랑스어에서 중국어로 번역
    Example->>Client: sendTask(frenchToChineseParams)
    Note right of Example: TextPart: "Bonjour le monde!<br/>Comment allez-vous?"
    Client->>Server: POST /a2a<br/>JSON-RPC: tasks/send
    Server-->>Client: Task (id, status, history)
    Client-->>Example: JSONRPCResponse<Task>
    Note over Example: 번역 결과 출력
    
    %% 4. 중국어에서 영어로 번역
    Example->>Client: sendTask(chineseParams)
    Note right of Example: TextPart: "你好,世界!<br/>欢迎使用AI翻译机器人。"
    Client->>Server: POST /a2a<br/>JSON-RPC: tasks/send
    Server-->>Client: Task (id, status, history)
    Client-->>Example: JSONRPCResponse<Task>
    Note over Example: 번역 결과 출력
    
    %% 5. 스트리밍 번역
    Example->>Client: sendTaskStreaming(frenchParams, StreamingEventListener)
    Note right of Example: TextPart: "Bonjour le monde!<br/>Comment allez-vous?"
    Client->>Server: POST /a2a/stream<br/>Server-Sent Events
    activate Server
    
    loop 스트리밍 응답
        Server-->>Client: SSE Event (번역 진행상황)
        Client-->>Example: onEvent(event)
        Note over Example: 실시간 번역 이벤트 출력
    end
    
    Server-->>Client: SSE Complete
    deactivate Server
    Client-->>Example: onComplete()
    Note over Example: 스트리밍 번역 완료
    
    %% 6. 작업 상태 조회
    Example->>Client: getTask(queryParams)
    Note right of Example: 프랑스어 번역 작업 상태 조회
    Client->>Server: POST /a2a<br/>JSON-RPC: tasks/get
    Server-->>Client: Task (업데이트된 상태)
    Client-->>Example: JSONRPCResponse<Task>
    Note over Example: 작업 상태 출력
    
    %% 7. 취소할 작업 전송
    Example->>Client: sendTask(cancelParams)
    Note right of Example: TextPart: "Diese Übersetzung<br/>wird abgebrochen." (독일어)
    Client->>Server: POST /a2a<br/>JSON-RPC: tasks/send
    Server-->>Client: Task (id, status)
    Client-->>Example: JSONRPCResponse<Task>
    
    %% 8. 작업 취소
    Example->>Client: cancelTask(cancelTaskParams)
    Client->>Server: POST /a2a<br/>JSON-RPC: tasks/cancel
    Server-->>Client: Task (취소된 상태)
    Client-->>Example: JSONRPCResponse<Task>
    Note over Example: 취소 결과 출력
    
    deactivate Client
    Note over Example,Server: 예제 프로그램 실행 완료

주요 상호작용 패턴

시퀀스 다이어그램은 다음과 같은 핵심 상호작용 패턴을 보여줍니다:

  1. 클라이언트 초기화: 로컬 서버에 연결된 A2AClient 인스턴스 생성
  2. 에이전트 발견: /.well-known/agent-card 엔드포인트를 통한 에이전트 정보 검색
  3. 다국어 번역 예제:
    • 프랑스어 → 중국어 번역
    • 중국어 → 영어 번역
    • 독일어 → 영어 스트리밍 번역
  4. 작업 관리:
    • 작업 상태 조회
    • 작업 실행 취소

통신 메커니즘

  • 동기 번역: JSON-RPC 요청과 함께 POST /a2a 엔드포인트 사용
  • 스트리밍 번역: Server-Sent Events (SSE)와 함께 POST /a2a/stream 엔드포인트 사용
  • 상태 조회: 작업 실행 상태를 확인하기 위한 tasks/get 메서드 사용
  • 작업 취소: 실행 중인 작업을 취소하기 위한 tasks/cancel 메서드 사용

API 사용 예제

에이전트 정보 가져오기

curl -X GET http://localhost:8080/.well-known/agent-card \
  -H "Accept: application/json"

번역 작업 전송

curl -X POST http://localhost:8080/a2a \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "request-1",
    "method": "tasks/send",
    "params": {
      "id": "translation-task-1",
      "message": {
        "messageId": "msg-1",
        "kind": "message",
        "role": "user",
        "parts": [
          {
            "kind": "text",
            "text": "Hello, world!"
          }
        ]
      }
    }
  }'

스트리밍 번역

curl -X POST http://localhost:8080/a2a/stream \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": "stream-request-1",
    "method": "tasks/send",
    "params": {
      "id": "streaming-translation-task",
      "message": {
        "messageId": "stream-msg-1",
        "kind": "message",
        "role": "user",
        "parts": [
          {
            "kind": "text",
            "text": "Hello world!"
          }
        ]
      }
    }
  }'