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.toml—features = ["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.json | Agent カード(機能、スキル、メタデータ) |
| POST | /a2a | JSON-RPC エンドポイント(message/send、message/get など) |
| POST | /a2a/stream | ストリーミング JSON-RPC (message/stream) |
次のステップ
- A2A クイックスタートの例 — 最小限の動作例
- ツール統合 — A2A エージェントにカスタムツールを追加
- セッション — リクエスト間で会話状態を永続化
- デプロイ — A2A エージェントを本番環境にデプロイ