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マルチモジュールアーキテクチャを使用し、以下の3つのコアモジュールを含んでいます:

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!"
          }
        ]
      }
    }
  }'