A2A はじめに

5分以内に A2A(Agent-to-Agent)プロトコルエージェントを作成して実行します。

前提条件

  • Rust 1.95.0以降(rustup update stable
  • cargo-adk がインストール済み(cargo install cargo-adk
  • Google API キー(こちらから取得

A2A プロジェクトをスキャフォールドする

始める最も簡単な方法は、a2a テンプレートを使用することです。

cargo adk new my-a2a-agent --template a2a
cd my-a2a-agent

これにより、以下を含む完全なプロジェクトが生成されます。

  • Cargo.tomlfeatures = ["standard"] を備えた adk-rust(A2A のサポートを含む)
  • src/main.rs — ビルダー API を使用する A2A サーバー
  • .env.example — API キーのプレースホルダー

API キーを追加します。

cp .env.example .env
# Edit .env and set GOOGLE_API_KEY=your-key-here

実行します。

cargo run

これで A2A エージェントが http://localhost:8080 でサービスを提供しています。

その他のプロバイダー

# OpenAI
cargo adk new my-agent --template a2a --provider openai

# Anthropic
cargo adk new my-agent --template a2a --provider anthropic

便利な API

ADK-Rust は、手動でルートを構成せずに、A2A プロトコル経由で任意のエージェントを公開するための A2aServer を提供します。

ゼロ設定: quick_start

最も簡単な方法です。1回の関数呼び出しで、適切なデフォルト値が使用されます。

use adk_rust::prelude::*;
use adk_rust::server::A2aServer;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();
    let api_key = std::env::var("GOOGLE_API_KEY")?;

    let model = GeminiModel::new(api_key, "gemini-3.7-flash")?;

    let agent: Arc<dyn Agent> = Arc::new(
        LlmAgentBuilder::new("my-agent")
            .description("A helpful AI assistant")
            .instruction("You are a helpful assistant exposed via A2A.")
            .model(Arc::new(model))
            .build()?,
    );

    let app = A2aServer::quick_start(agent);
    let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await?;
    axum::serve(listener, app).await?;
    Ok(())
}

quick_start は以下を構成します。

  • インメモリセッションサービス
  • GET /.well-known/agent.json のエージェントカード
  • POST /a2a の JSON-RPC エンドポイント
  • ストリーミングを有効化

カスタム設定: ビルダー

ポート、メタデータ、またはセッションバックエンドを制御する必要がある場合は、ビルダーを使用します。

use adk_rust::prelude::*;
use adk_rust::server::A2aServer;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = GeminiModel::new(api_key, "gemini-3.7-flash")?;

    let agent: Arc<dyn Agent> = Arc::new(
        LlmAgentBuilder::new("my-agent")
            .description("Production A2A agent")
            .instruction("You are a helpful assistant.")
            .model(Arc::new(model))
            .build()?,
    );

    let server = A2aServer::builder()
        .agent(agent)
        .bind_addr("0.0.0.0:9090")
        .agent_card_name("My Production Agent")
        .agent_card_description("Handles customer queries via A2A")
        .agent_card_version("2.0.0")
        .streaming(true)
        .push_notifications(false)
        .build()?;

    server.serve().await?;
    Ok(())
}
ビルダーメソッドデフォルト説明
.agent(agent)必須公開するエージェント
.bind_addr(addr)0.0.0.0:8080サーバーのバインドアドレス
.session_service(svc)インメモリセッションバックエンド
.agent_card_name(name)agent.name()エージェントカードの表示名
.agent_card_description(desc)agent.description()エージェントカードの説明
.agent_card_version(ver)"1.0.0"エージェントカードのバージョン
.agent_card_url(url)http://localhost:{port}エージェント用の公開 URL
.streaming(bool)trueストリーミング応答を有効化
.push_notifications(bool)falseプッシュ通知を有効化

curl を使ったテスト

エージェントが起動したら、次のコマンドで動作を確認します。

エージェントカードを取得する

curl http://localhost:8080/.well-known/agent.json | jq .

期待されるレスポンス:

{
  "name": "my-agent",
  "description": "A helpful AI assistant",
  "url": "http://localhost:8080",
  "version": "1.0.0",
  "capabilities": {
    "streaming": true,
    "pushNotifications": false,
    "stateTransitionHistory": true
  },
  "skills": []
}

メッセージを送信する(JSON-RPC)

curl -X POST http://localhost:8080/a2a \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "message/send",
    "params": {
      "message": {
        "role": "user",
        "parts": [{"kind": "text", "text": "What is the A2A protocol?"}],
        "messageId": "msg-1"
      }
    },
    "id": "req-1"
  }'

期待されるレスポンス:

{
  "jsonrpc": "2.0",
  "id": "req-1",
  "result": {
    "id": "task-uuid",
    "status": {"state": "completed"},
    "artifacts": [
      {
        "parts": [{"kind": "text", "text": "The A2A protocol is..."}]
      }
    ]
  }
}

レスポンスをストリーミングする

curl -X POST http://localhost:8080/a2a/stream \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "message/stream",
    "params": {
      "message": {
        "role": "user",
        "parts": [{"kind": "text", "text": "Explain Rust in 3 sentences."}],
        "messageId": "msg-2"
      }
    },
    "id": "req-2"
  }'

これにより、タスクステータスの更新が増分で送信される Server-Sent Events が返されます。


MCP と A2A の境界を明確に分ける

MCP は、エージェントアプリケーションをツール、リソース、その他の公開された機能に接続します。A2A は、独立してデプロイされたエージェントを接続し、リモート作業のライフサイクルを担います。ブリッジによってプロトコル間を変換できますが、そのブリッジは独自のアイデンティティ、認可、スキーママッピング、タスク状態マッピング、障害時の動作を持つ、別途デプロイされたコンポーネントです。

ADK-Rust は mcp-a2a-server という名前のバイナリを同梱していません。デプロイメントでそのようなブリッジを別途提供し、テストしている場合を除き、そのコマンドを MCP の設定に記述しないでください。両側がエージェントの場合は、A2A クライアントを直接使用してください。

別の ADK-Rust エージェントから接続する

RemoteA2aAgent を使用すると、別の ADK-Rust アプリケーションから A2A エージェントを呼び出せます。

use adk_rust::server::RemoteA2aAgent;

let remote = RemoteA2aAgent::new(
    "my-remote-agent",
    "http://localhost:8080",
);

これにより、ネットワーク経由で A2A サーバーにリクエストを転送するエージェントが作成されます。


エンドポイントリファレンス

メソッドパス説明
GET/.well-known/agent.jsonAgent カード(機能、スキル、メタデータ)
POST/a2aJSON-RPC エンドポイント(message/sendmessage/get など)
POST/a2a/streamストリーミング JSON-RPC (message/stream)

次のステップ


前へ: クイックスタート | 次へ: LlmAgent