Agent2Agent (A2A) は、AI エージェント間のシームレスなコミュニケーションとコラボレーションを可能にするために設計されたオープン標準です。Knative で A2A サーバーをデプロイすると、ゼロへのスケールインを含む自動スケーリングなどの特徴を活用して、オンデマンドのリソース使用量と迅速なバージョンの反復が可能になります。
仕組み
AI エージェントは推論、計画、メモリの能力を持ち、自律的に学習してユーザーに代わってタスクを完了することができます。MCP が LLM のためのデータアクセス標準を提供するのと同様に、Agent2Agent (A2A) プロトコルはエージェント間の相互運用性のための標準化されたフレームワークを定義します。
Knative で A2A サーバーをデプロイするには、以下のコアとなる対話が含まれます:
-
ディスカバリー:デプロイ後、サービスは標準のエージェントカードを介してインターフェイスを公開し、他のエージェントがそのスキル (AgentSkill) と機能 (AgentCapabilities) をクエリできるようにします。
-
コミュニケーション:Knative のゲートウェイとサービスルーティング機能を使用して、HTTP または gRPC を介した標準的なメッセージ交換を処理します。
-
コラボレーション:エージェントは API を通じてタスクをデリゲートし、アクションを調整します。
プロトコルアーキテクチャについては A2A 仕様を、エージェントコミュニケーションの基本概念についてはそちらをご参照ください。
事前準備
-
クラスターに Knative をデプロイします。詳細については、「Knative コンポーネントをデプロイおよび管理する」をご参照ください。
-
Container Service for Kubernetes (ACK) クラスターに Knative をデプロイ済みであること。
-
ゲートウェイアクセスアドレスを取得済みであること。
アドオン管理 ページまたは サービス管理 ページで確認できます。以下にその確認方法を示します。
サービス管理ページの下部で、アクセスゲートウェイのアドレスを確認します。フォーマットは
alb-<instance ID>.cn-hangzhou.alb.aliyuncsslb.comです。
手順1:A2A サーバーのデプロイ
この例では、helloworld-agent-server という名前の基本的なエージェントサービスをデプロイします。
-
a2a-service.yamlを作成します。apiVersion: serving.knative.dev/v1 kind: Service metadata: name: helloworld-agent-server # 必要に応じて名前空間を更新します namespace: default annotations: # 迅速な検証のためにワイルドカードドメインを使用します knative.aliyun.com/serving-ingress: / spec: template: spec: containers: # {region} を実際のリージョン (例: cn-hangzhou) に置き換えます - image: registry-{region}-vpc.ack.aliyuncs.com/acs/knative-samples-a2a:v1.0-952c112 name: user-container env: # INVOKE はエージェントカードで返される呼び出し URL を定義します。ご利用のゲートウェイアドレスに置き換えてください。 - name: INVOKE value: http://<YOUR_GATEWAY_ADDRESS>/invoke ports: - containerPort: 9001 name: http1 protocol: TCP -
サービスをデプロイします。
kubectl apply -f a2a-service.yaml -
Knative サービス のステータスを確認します。
kubectl get ksvc helloworld-agent-server想定される出力:
NAME URL LATESTCREATED LATESTREADY READY REASON helloworld-agent-server http://helloworld-agent-server.default.example.com helloworld-agent-server-00001 helloworld-agent-server-00001 True
手順2:サービスの検証とエージェントカードの取得
デプロイ後、サービスが A2A プロトコルに準拠したエージェントカードを正しく返すことを確認します。
-
ゲートウェイアドレスとサービスのデフォルトドメイン名を取得します。
ACK クラスターページで、ご利用のクラスターの名前をクリックします。左側のナビゲーションウィンドウで、 をクリックします。
-
ACK コンソールにログインします。左側のナビゲーションウィンドウで、クラスターリスト をクリックします。
-
クラスターリスト ページで、対象のクラスターの名前をクリックします。 左側のナビゲーションウィンドウで、 を選択します。
-
サービス管理 ページで、サービスの デフォルトドメイン を取得します。
以下はゲートウェイとデフォルトドメインを示します。
ゲートウェイアドレスのフォーマットは
alb-<instance ID>.cn-hangzhou.alb.aliyuncsslb.comです。サービス helloworld-agent-server は成功状態で、そのデフォルトドメイン名はhelloworld-agent-server.default.example.comです。
-
サービスのメタデータエンドポイントにアクセスします。
# <GATEWAY_ADDRESS> を実際のゲートウェイアドレスに置き換えます curl http://<GATEWAY_ADDRESS>/.well-known/agent-card.json | jq .想定される出力を確認します。
出力には、エージェントの機能 (capabilities)、説明 (description)、およびスキルの一覧 (skills) が含まれている必要があります。{ "capabilities": { "streaming": true }, "defaultInputModes": [ "text" ], "defaultOutputModes": [ "text" ], "description": "Just a hello world agent", "name": "Hello World Agent", "preferredTransport": "JSONRPC", "protocolVersion": "", "skills": [ { "description": "Returns a 'Hello, world!'", "examples": [ "hi", "hello" ], "id": "hello_world", "name": "Hello, world!", "tags": [ "hello world" ] } ], "url": "http://XXX/invoke", "version": "" }
手順3:A2A クライアントを使用したサービスの呼び出し
Golang でクライアントコードを記述し、デプロイされた A2A サーバーと通信する別のエージェントをシミュレートします。
-
開発環境をセットアップし、Go をインストールします。
-
main.go という名前のファイルを作成し、次のコードを追加します。
package main import ( "context" "flag" "log" // A2A プロトコルのコアライブラリをインポートします "github.com/a2aproject/a2a-go/a2a" "github.com/a2aproject/a2a-go/a2aclient" "github.com/a2aproject/a2a-go/a2aclient/agentcard" // gRPC 関連のライブラリをインポートします "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) // <GATEWAY_ADDRESS> を実際のゲートウェイアドレスに置き換えます var cardURL = flag.String("card-url", "http://<GATEWAY_ADDRESS>", "Base URL of AgentCard client.") func main() { flag.Parse() ctx := context.Background() // サービスディスカバリー card, err := agentcard.DefaultResolver.Resolve(ctx, *cardURL) if err != nil { log.Fatalf("Failed to resolve an AgentCard: %v", err) } // トランスポートレイヤーを設定します withInsecureGRPC := a2aclient.WithGRPCTransport(grpc.WithTransportCredentials(insecure.NewCredentials())) // クライアントを作成します client, err := a2aclient.NewFromCard(ctx, card, withInsecureGRPC) if err != nil { log.Fatalf("Failed to create a client: %v", err) } // メッセージを構築します msg := a2a.NewMessage(a2a.MessageRoleUser, a2a.TextPart{Text: "Hello, world"}) resp, err := client.SendMessage(ctx, &a2a.MessageSendParams{Message: msg}) if err != nil { log.Fatalf("Failed to send a message: %v", err) } log.Printf("Server responded with: %+v", resp) } -
コードを実行してテストします。
go mod init a2a-demo go mod tidy go run main.go次の出力は、クライアントが正常に Knative サービスに接続し、サーバーから応答を受信したことを示しています。
2025/11/27 17:24:21 Server responded with: &{ID:019ac4a0-c386-7cdc-9aad-d40fb8f98ae2 ContextID: Extensions:[] Metadata:map[] Parts:[{Text:Hello, world! Metadata:map[]}] ReferenceTasks:[] Role:agent TaskID:}
本番環境に関する推奨事項
-
カスタムドメインと HTTPS:本番環境ではテストドメインを使用しないでください。カスタムドメイン名を設定し、HTTPS 証明書を有効にして、エージェント間の通信を保護してください。
-
コールドスタートの最適化:エージェントの呼び出しが頻繁でない場合、Knative はインスタンスをゼロにスケールダウンします。最初のリクエストでのコールドスタートのレイテンシーを避けるために、最小インスタンス数 (MinScale) を設定するか、リザーブドインスタンスを設定してください。
課金
Knative 自体に追加料金は発生しません。ただし、コンピューティングやネットワークリソースなど、使用するクラウドサービスに対して課金されます。詳細については、「クラウドサービスのコスト」および「課金」をご参照ください。