また MCP を発明している。
Agent2Agent Protocol(略称 A2A)は、独立した AI エージェントアプリケーション間の通信を実現するオープンプロトコルです。あるエージェントが別のエージェントの能力を発見し、作業を依頼し、複数ターンの対話を継続し、長時間実行されるタスクを追跡し、リモートエージェントの実装方法を知らずに構造化された結果を受け取れるようにします。
A2A は Google によって開始され、Linux Foundation に寄贈されました。フレームワーク、モデル、言語、ベンダーに依存しません。Java で構築された A2A クライアントは、異なるモデルとエージェントフレームワークを使用して Python で構築されたリモートエージェントと連携できます。
重要な境界は次のとおりです。
Agent A は Agent B が提供するものと、その通信方法を知っている。
Agent A は Agent B のプロンプト、メモリ、ツール、モデル、ソースコードを知る必要がない。この記事では、公開された A2A v1.0 のデータモデルを説明します。仕様は現在も発展しているため、本番実装では、リモートの Agent Card に示されたプロトコルバージョンをネゴシエートし、検証する必要があります。
A2A が解決する問題 #
汎用アシスタントが出張を手配する必要があるとします。次のエージェントと連携する必要があるかもしれません。
- 航空券エージェント
- ホテルエージェント
- 雇用主の出張ポリシーエージェント
- 地上交通エージェント
- 経費管理エージェント
共通プロトコルがなければ、組み合わせごとにカスタム統合が必要です。
オーケストレーター -> 航空会社ベンダーの非公開 API
オーケストレーター -> ホテルベンダーの非公開 API
オーケストレーター -> ポリシーエージェントのカスタム WebSocket
オーケストレーター -> 経費エージェントのメッセージキュー各統合は、次の要素を独自に定義します。
- 能力の記述
- リクエストとレスポンスのスキーマ
- 認証メタデータ
- 進捗イベント
- キャンセル動作
- ファイル処理
- 会話識別子
- 長時間実行ジョブのモデル
- エラー表現
独立して開発されたエージェントの数が増えると、こうしたポイントツーポイントのアダプターは、構築とガバナンスのコストが高くなります。
従来の REST API は、リモート操作が決定論的で完全に仕様化されている場合、この問題の一部を解決します。しかし、エージェントとの対話は、多くの場合それほど固定的ではありません。
クライアント: 会社のポリシーに従って出張を手配してください。
エージェント: 従業員 ID と、希望する出発時間帯が必要です。
クライアント: 従業員 E-1042、18:00 以降です。
エージェント: ポリシーに準拠する唯一の便では、ホテルのチェックイン後に到着します。
例外申請を行ってもよいですか?
クライアント: はい。ただし、何も購入せず、例外申請を準備してください。作業は状態を持ち、明確化や認可を必要とする場合があり、長時間続くこともあります。また、複数の成果物が段階的に生成される場合もあります。A2A はこの対話のエンベロープを標準化し、ドメイン固有の推論は各エージェントに委ねます。
統合マトリックスから単一プロトコルへ #
各エージェントが専用インターフェースを持つ場合、\(N\) 個のエージェントを接続するには、最大で \(N \times (N - 1)\) 個の方向付き統合が必要になります。A2A では、各実装が共有プロトコルを対象にします。
Agent A --\
Agent B ----> A2A データモデルと操作
Agent C --/これはドメインの違いをなくすものではありません。航空券予約スキルとセキュリティレビューのスキルは、依然として異なる情報を受け取ります。A2A は、能力の広告方法と、作業、状態、コンテンツ、結果の交換方法を標準化します。
A2A ではないもの #
A2A は次のものです。
- エージェント型アプリケーション間のワイヤプロトコルおよび対話モデル
- プロセス、フレームワーク、チーム、組織の境界を越えて利用できるもの
- 内部が不透明で、長時間実行される可能性のあるエージェント向けに設計されたもの
A2A は次のものではありません。
- LLM
- エージェントフレームワーク
- オーケストレーションアルゴリズム
- プロンプト形式
- ワークフローエンジン
- モデルルーティングシステム
- アイデンティティプロバイダー
- レジストリ API 標準
- 広告されたエージェントが信頼できることの保証
- 明確に定義された通常の API の代替
リモートの能力が単に getExchangeRate(from, to) である場合、通常の API またはツールプロトコルのほうが明快です。A2A は、リモート側が自律的な協働者であり、推論、交渉、タスク状態の維持、追加情報の要求、複雑な成果物の返却を行う場合に価値があります。
A2A と MCP #
A2A と Model Context Protocol は異なる問題を解決します。
| プロトコル | 関係 | 代表的なリモート能力 |
|---|---|---|
| MCP | エージェントからツールまたはリソース | データベースへの問い合わせ、ファイルの読み取り、API の呼び出し |
| A2A | エージェントからエージェント | 調査、交渉、計画、委任、結果の提供 |
エージェントは両方を使用できます。
出張オーケストレーター
|
| A2A: 「ポリシーに準拠する航空券の候補を探す」
v
航空券エージェント
|
| MCP: 在庫および価格ツールを呼び出す
v
航空会社システムMCP は、比較的限定されたプリミティブをエージェントに公開します。A2A は、独立したエージェントを不透明な協働者として公開します。すべてのエージェントを単一の巨大なツールとしてラップすると、タスクのライフサイクル、明確化、成果物、非同期動作といった有用な特性が隠れます。一方、単純なツールをすべてエージェントとして扱うと、不要な自律性と複雑性が加わります。
3 つのプロトコル層 #
A2A v1.0 は、次の 3 つの層を分離します。
- 標準データモデル: Agent Card、Message、Task、Part、Artifact、イベント、セキュリティ宣言、拡張。
- 抽象操作: Message の送信、Message のストリーミング、Task の取得・一覧表示・キャンセル、Task 更新の購読、プッシュ通知設定の管理、拡張 Agent Card の取得。
- バインディング: JSON-RPC、gRPC、HTTP+JSON、または管理されたカスタムバインディングへの具体的なマッピング。
標準 Protocol Buffer 定義が規範となります。バインディングは同じ概念を異なる形式でシリアライズします。クライアントは、1 つの JSON-RPC 例がすべてのバインディングを表すと仮定せず、保守されている SDK を使用する必要があります。
公式プロジェクトは、Python、Go、Java、JavaScript、.NET、Rust 向けの SDK と、別個のサンプルリポジトリを提供しています。
アクター #
対話には、次の 3 つの概念的なアクターが存在します。
- ユーザー: リクエストの目的となる人間または自動化システム。
- A2A クライアント: ユーザーに代わってプロトコル操作を開始するアプリケーションまたはクライアントエージェント。
- A2A サーバー: A2A インターフェースを公開し、作業を実行するリモートエージェント。
同じアプリケーションがサーバーとクライアントの両方になることもあります。出張オーケストレーターはユーザーのリクエストを処理しながら、航空券エージェントとホテルエージェントのクライアントとして動作します。
ユーザー
-> A2A サーバー: 出張オーケストレーター
-> A2A クライアント: 航空券エージェント
-> A2A クライアント: ホテルエージェント
-> A2A クライアント: ポリシーエージェントA2A はオーケストレーターの計画ロジックを標準化しません。固定ワークフロー、ルールエンジン、LLM プランナー、人間による判断などを使用できます。
エージェントの発見 #
A2A サーバーは、Agent Card という JSON ドキュメントによって自身を記述します。Agent Card には次の情報が含まれます。
- エージェント名、説明、プロバイダー、バージョン
- 1 つ以上のサポート対象インターフェースと A2A プロトコルバージョン
- サポート対象プロトコルバインディング
- デフォルトの入力および出力メディアタイプ
- ストリーミング、プッシュ通知、拡張カードのオプション機能
- セキュリティスキームと要件
- スキル、説明、タグ、例、メディアタイプ
- オプションの署名と拡張
簡略化した v1.0 Agent Card は次のとおりです。
{
"name": "Corporate Travel Agent",
"description": "Plans policy-compliant business travel",
"version": "3.4.0",
"provider": {
"organization": "Example Travel",
"url": "https://travel.example"
},
"supportedInterfaces": [
{
"url": "https://agents.example/a2a/travel",
"protocolBinding": "HTTP+JSON",
"protocolVersion": "1.0"
}
],
"capabilities": {
"streaming": true,
"pushNotifications": true,
"extendedAgentCard": true
},
"defaultInputModes": [
"text/plain",
"application/json"
],
"defaultOutputModes": [
"text/plain",
"application/json"
],
"skills": [
{
"id": "plan-business-trip",
"name": "Plan a Business Trip",
"description": "Finds policy-compliant flight and hotel options",
"tags": ["travel", "flight", "hotel", "corporate-policy"],
"examples": [
"Plan a trip from Singapore to Helsinki for 12-16 October"
],
"inputModes": ["text/plain", "application/json"],
"outputModes": ["application/json"]
}
]
}正確な JSON フィールド名は v1.0 の標準モデルから導出されます。任意の JSON を受け入れるのではなく、SDK または生成されたスキーマを通じてカードを検証してください。
発見戦略 #
ドメインベースの発見では、標準の well-known URL は次のとおりです。
https://agent.example/.well-known/agent-card.jsonその他の実用的なアプローチは次のとおりです。
- キュレーション済みレジストリ: エンタープライズカタログまたはマーケットプレイスが、スキル、プロバイダー、地域、信頼ポリシーに基づいて承認済みの Agent Card を返します。
- 直接設定: デプロイメントマニフェストが、閉じたエージェント集合の既知のカード URL を指定します。
- 認証済み拡張カード: 公開カードが基本能力を広告し、認証済み操作が呼び出し元で利用可能な機密性の高いスキルやインターフェースを返します。
A2A が標準化するのはカードであり、集中型レジストリの API ではありません。
発見結果は自動的な信頼ではなく、ポリシーへの入力として扱ってください。エージェントを呼び出す前に、クライアントは次の項目を確認する必要がある場合があります。
- 信頼できる発行者またはレジストリ
- カード署名
- 許可されたドメインと TLS アイデンティティ
- プロトコルバージョン
- 必須バインディング
- サポート対象メディアタイプ
- 承認済みプロバイダー
- データレジデンシー
- セキュリティスキーム
- 契約関係
- 現在のユーザーに対してスキルが認可されているか
Agent Card は Task よりも変更頻度が低いため、Cache-Control、ETag、条件付きリクエストを含む通常の HTTP キャッシュを使用する必要があります。
Agent Card が交換されるタイミング #
Agent Card は発見時に使用するコントロールプレーンのメタデータであり、通常は最初の A2A 操作より前に取得されます。
クライアント -> Agent Card を発見または受信
クライアント -> 信頼、バージョン、バインディング、セキュリティ、メディアタイプを検証
クライアント -> supportedInterfaces からインターフェース URL を選択
クライアント -> そのインターフェースに A2A 操作を送信Agent Card が各 Message に添付されることは通常ありません。クライアントはカードをキャッシュし、通常の HTTP キャッシュ規則またはローカルポリシーに従って更新できます。
A2A サーバーは Agent Card を利用可能にしなければなりません。ただし v1.0 では、標準の well-known URI、レジストリまたはカタログ、直接設定されたカード URL またはカード内容など、複数の発見メカニズムが許可されています。したがって、/.well-known/agent-card.json は相互運用性のための標準的な場所ですが、カード交換に準拠する唯一の方法ではありません。
公開カードが extendedAgentCard を広告している場合、認可されたクライアントは後から Get Extended Agent Card を呼び出せます。この認証済みカードは、匿名の発見時には公開すべきでない、呼び出し元固有のスキルやインターフェースを明らかにできます。
Message と Part #
Message は 1 回の通信ターンです。次の要素を持ちます。
- 呼び出し元が生成する
messageId ROLE_USERまたはROLE_AGENTのロール- 1 つ以上の Part
- オプションの
contextIdとtaskId - 過去の Task へのオプションの参照
- オプションのメタデータ
- 宣言された拡張
Part は、次のいずれか 1 つのコンテンツ表現を正確に含みます。
| コンテンツ | 用途 |
|---|---|
text | プレーンテキストコンテンツ |
data | 構造化された JSON 値 |
url | 外部コンテンツへの参照 |
raw | Base64 として JSON に表現されるインラインバイト |
Part には MIME の mediaType、ファイル名、メタデータを付加することもできます。
{
"messageId": "msg-01JZ8P...",
"role": "ROLE_USER",
"parts": [
{
"text": "Review the attached contract for renewal risk.",
"mediaType": "text/plain"
},
{
"url": "https://files.example/contracts/42",
"filename": "contract.pdf",
"mediaType": "application/pdf",
"metadata": {
"sha256": "..."
}
},
{
"data": {
"jurisdiction": "Singapore",
"riskTolerance": "low"
},
"mediaType": "application/json"
}
]
}大きなファイルの場合、すべてのプロトコルホップに Base64 データを含めるのではなく、URL を使用してください。URL は短期間だけ有効で、対象エージェントに限定され、整合性が検証され、混乱した代理人によるアクセスから保護される必要があります。
メディアネゴシエーションは重要です。クライアントは受け入れ可能な出力メディアタイプを宣言し、Agent Card はエージェントがサポートするものを記述します。スキルが application/json を提供する場合、機械的なオーケストレーターは散文を解析するのではなく、構造化データを要求する必要があります。
直接 Message とステートフル Task #
Send Message 操作は、次のいずれかを返します。
- 即時かつ自己完結した応答を表す Message
- ステートフルまたは長時間実行される作業を表す Task
たとえば、エージェントは能力に関する質問へ直接回答できます。
クライアント: シンガポール法が適用される契約をレビューできますか?
エージェント: はい。300 ページの契約書のレビューでは、追跡、割り込み、キャンセル、出力 Artifact との関連付けが可能な Task を作成する必要があります。
Task モデル #
Task には次の要素があります。
- サーバーが生成する Task ID
- サーバーが生成するコンテキスト ID
- 現在の状態とタイムスタンプ
- オプションのステータス Message
- Message 履歴
- 0 個以上の Artifact
- メタデータ
ライフサイクル状態は次のとおりです。
| 状態 | 意味 |
|---|---|
TASK_STATE_SUBMITTED | 受け付けられたが、まだアクティブに処理されていない |
TASK_STATE_WORKING | 処理中 |
TASK_STATE_INPUT_REQUIRED | ユーザーまたはクライアントから追加情報が必要 |
TASK_STATE_AUTH_REQUIRED | 帯域外の追加認証が必要 |
TASK_STATE_COMPLETED | 成功した終端結果 |
TASK_STATE_FAILED | 終端処理エラー |
TASK_STATE_CANCELED | 終端キャンセル |
TASK_STATE_REJECTED | エージェントが作業を拒否 |
INPUT_REQUIRED と AUTH_REQUIRED は処理を中断しますが、終端状態ではありません。クライアントは、Task に関連付けた別の Message を送信して処理を継続できます。
終端 Task は不変です。修正や改善では、同じコンテキストに新しい Task を作成し、過去の Task を参照します。
コンテキスト C
Task T1: 旅程を生成 -> 完了 -> Artifact A1
Task T2: 午前の便を変更 -> 完了 -> Artifact A2
T1 を参照これにより監査可能性が得られます。各 Task は、入力、状態、出力の安定した単位として保持されます。
コンテキスト ID と Task ID #
contextId は関連する Task と Message をグループ化します。taskId は 1 つの作業単位を識別します。
コンテキスト: 「ヘルシンキ旅行を計画」
Task: 航空券を検索
Task: ホテルを予約
Task: ポリシー例外を申請コンテキスト ID を認証、認可、テナント識別子と混同しないでください。コンテキスト ID はサーバーが割り当てる不透明な相関ハンドルです。サーバーは、認証済みの呼び出し元が参照されたすべてのコンテキスト、Task、Artifact にアクセスできることを引き続き検証する必要があります。
Artifact #
Artifact は、会話上のステータス Message ではなく、具体的な Task 出力です。例として次のものがあります。
- 旅程
- セキュリティレポート
- 生成されたソースコード
- PDF 契約分析
- 画像
- 構造化されたオファー一覧
- デプロイメントマニフェスト
Artifact には、Task 内で一意の ID、名前、説明、Part、メタデータ、オプションの拡張があります。
{
"artifactId": "offers-v1",
"name": "flight-offers.json",
"description": "Policy-compliant flight options",
"parts": [
{
"mediaType": "application/json",
"data": {
"currency": "SGD",
"offers": [
{
"offerId": "F-812",
"price": 1420.30,
"refundable": true
}
]
}
}
],
"metadata": {
"expiresAt": "2026-07-20T10:15:00Z"
}
}Artifact は自動的に永続化されるものでも、信頼できるものでもありません。クライアントは、そのスキーマ、メディアタイプ、サイズ、整合性、出所、有効期限、ビジネス上の意味を検証する必要があります。
コア操作 #
バインディングに依存しない v1.0 の操作には、次のものがあります。
| 操作 | 目的 |
|---|---|
| Send Message | 対話の開始または継続 |
| Send Streaming Message | 対話を開始し、増分イベントを受信 |
| Get Task | 現在の Task 状態、履歴、Artifact を取得 |
| List Tasks | フィルターとページネーションを使用して認可済み Task を一覧表示 |
| Cancel Task | 実行中の作業のキャンセルをエージェントに要求 |
| Subscribe to Task | アクティブな Task の更新に再接続 |
| Manage Task Push Notification Config | Webhook 設定の作成、読み取り、一覧表示、削除 |
| Get Extended Agent Card | 呼び出し元固有の Agent Card 詳細を取得 |
バインディングとエンドポイントの対応 #
Agent Card のインターフェース URL と protocolBinding によって、これらの抽象操作がワイヤ上でどのように表現されるかが決まります。
JSON-RPC では、広告されたインターフェース URL がすべての操作に対する 1 つの HTTP エンドポイントになります。/a2a のような URL は実装上の選択にすぎず、A2A 仕様はそのパスを要求しません。クライアントは JSON-RPC 本文を持つ通常の HTTP リクエストを送信し、method フィールドが A2A 操作を選択します。
POST /a2a HTTP/1.1
Host: agents.example
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": "request-17",
"method": "SendMessage",
"params": {
"message": {
"messageId": "msg-01JZ8P...",
"role": "ROLE_USER",
"parts": [{"text": "Hello"}]
}
}
}ここで JSON-RPC は HTTP 上に重ねられたプロトコル規約であり、HTTP の代替ではありません。HTTP はトランスポート、ヘッダー、認証、ステータスコードを提供し、JSON-RPC は method、params、id、result、error という本文フィールドに加え、リクエスト相関、通知、プロトコルエラーの意味論を標準化します。ほかのプロトコルも WebSocket や標準入出力などのトランスポート上で JSON-RPC を使用できますが、A2A の JSON-RPC バインディングは特に HTTP(S) を使用し、ストリーミングには Server-Sent Events を使用します。
すべての JSON-RPC A2A メソッドは、同じ広告済み URL に送信されます。
| A2A 操作 | JSON-RPC メソッド |
|---|---|
| Send Message | SendMessage |
| Send Streaming Message | SendStreamingMessage |
| Get Task | GetTask |
| List Tasks | ListTasks |
| Cancel Task | CancelTask |
| Subscribe to Task | SubscribeToTask |
| プッシュ設定の作成 | CreateTaskPushNotificationConfig |
| プッシュ設定の取得 | GetTaskPushNotificationConfig |
| プッシュ設定の一覧表示 | ListTaskPushNotificationConfigs |
| プッシュ設定の削除 | DeleteTaskPushNotificationConfig |
| Get Extended Agent Card | GetExtendedAgentCard |
HTTP+JSON バインディングでは、広告されたインターフェースのベース URL に対して相対的な、リソース指向の個別パスを使用します。
| HTTP エンドポイント | A2A 操作 |
|---|---|
POST /message:send | Send Message |
POST /message:stream | SSE を使用する Send Streaming Message |
GET /tasks/{id} | Get Task |
GET /tasks | List Tasks |
POST /tasks/{id}:cancel | Cancel Task |
POST /tasks/{id}:subscribe | SSE を使用する Subscribe to Task |
POST /tasks/{id}/pushNotificationConfigs | プッシュ設定の作成 |
GET /tasks/{id}/pushNotificationConfigs/{configId} | プッシュ設定の取得 |
GET /tasks/{id}/pushNotificationConfigs | プッシュ設定の一覧表示 |
DELETE /tasks/{id}/pushNotificationConfigs/{configId} | プッシュ設定の削除 |
GET /extendedAgentCard | Get Extended Agent Card |
これらのパスは HTTP+JSON バインディングに属します。JSON-RPC 実装は操作ごとに 1 つの HTTP ルートを公開しません。gRPC バインディングも、これらの REST パスではなく RPC メソッドを公開します。
ブロッキング送信とノンブロッキング送信 #
Send Message の設定は、呼び出しが待機するかどうかを制御します。
returnImmediatelyが false または省略されている場合、Task が終端状態または中断状態に達するまで待機します。returnImmediatelyが true の場合、Task の作成後に返ります。クライアントはポーリング、購読、またはプッシュ通知を待機します。
簡略化した HTTP+JSON リクエストは次のとおりです。
POST /message:send HTTP/1.1
Host: agents.example
Authorization: Bearer eyJ...
Content-Type: application/json
{
"message": {
"messageId": "msg-01JZ8P...",
"role": "ROLE_USER",
"parts": [
{
"text": "Review repository example/payments for critical vulnerabilities",
"mediaType": "text/plain"
}
]
},
"configuration": {
"acceptedOutputModes": [
"application/json",
"text/markdown"
],
"historyLength": 10,
"returnImmediately": true
}
}即時レスポンスには、次のような内容が含まれる場合があります。
{
"task": {
"id": "task-sec-2048",
"contextId": "ctx-release-91",
"status": {
"state": "TASK_STATE_SUBMITTED",
"timestamp": "2026-07-20T08:30:00Z"
}
}
}この例は v1.0 HTTP+JSON バインディングを対象としています。正確なリクエストとレスポンスのラッパーについては SDK を使用してください。
ストリーミングと非同期作業 #
エージェントの作業は、通常のリクエストタイムアウトより長く続くことがよくあります。A2A は 3 つの更新パターンを提供します。
ポーリング #
クライアントはノンブロッキングリクエストを送信し、Get Task を定期的に呼び出します。
Send Message -> Task(submitted)
Get Task -> Task(working)
Get Task -> Task(completed, artifacts=[...])ポーリングは単純で、プロセスの再起動後も継続できます。数ミリ秒ごとにポーリングするのではなく、指数バックオフ、ジッター、サーバーのヒントを使用してください。
ストリーミング #
Agent Card がストリーミングを広告している場合、Send Streaming Message はストリームを返します。バインディングに応じて、HTTP は Server-Sent Events を使用し、gRPC はサーバーストリームを使用できます。
Task ライフサイクルのストリームは Task から始まり、次のイベントを発行します。
- 状態変更または中間ステータス Message の
TaskStatusUpdateEvent - 新規または増分更新された Artifact の
TaskArtifactUpdateEvent
Task(submitted)
Status(working: "依存関係をスキャン中")
Artifact(report, append=true, chunk=1)
Status(working: "到達可能な呼び出しパスを分析中")
Artifact(report, append=true, chunk=2, lastChunk=true)
Status(completed)Artifact 更新では、データが既存 Artifact に追加されるかどうか、および最後のチャンクが到着したかどうかを示します。クライアントは Task ID と Artifact ID でチャンクを組み立て、サイズ制限を適用し、コンテンツを重複させずに再接続を処理する必要があります。
Task がアクティブな間にストリームが切断された場合、Subscribe to Task によって今後の更新の受信を再開できます。ストリーミングデータを処理する前に Task ID を永続化し、復旧可能な状態を維持してください。
プッシュ通知 #
数分、数時間、数日続く作業では、エージェントがプッシュ通知をサポートしている場合、クライアントは HTTPS Webhook を登録できます。
クライアント -> エージェント: Task を開始し、コールバックを登録
クライアントが切断
エージェントが作業を実行
エージェント -> クライアント Webhook: Task 完了
クライアント -> エージェント: Get Task通知は状態が変化したことをクライアントに伝えます。通常、クライアントはその後に権威ある Task を取得します。
Webhook のサポートには、次のような重大なリスクがあります。
- SSRF: 悪意のある呼び出し元が、内部 URL またはクラウドメタデータ URL を指定する。
- なりすまし: 攻撃者が偽の完了イベントを送信する。
- リプレイ: 有効な過去のイベントが再度処理される。
- 増幅: サーバーが第三者へ大量送信するよう誘導される。
- 重複配信: ネットワーク再試行によって同じイベントが複数回配信される。
サーバーはコールバックの所有権を許可リストまたは検証し、送信先ネットワークを制限する必要があります。受信側は送信者を認証し、発行者、対象者、有効期限、Task ID、一意のイベント ID を検証し、古いイベントを拒否し、通知を冪等に処理する必要があります。
入力と認証による中断 #
長時間実行される作業では、別のユーザー判断が必要になる場合があります。
クライアント -> エージェント: 「最適なポリシー準拠オプションを予約してください」
エージェント -> クライアント: Task(INPUT_REQUIRED)
「2 つの候補のポリシースコアが同じです。価格の低さと返金可能運賃の
どちらを優先しますか?」
クライアント -> エージェント: Message(taskId=T1, 「返金可能運賃を優先」)
エージェント -> クライアント: Task(WORKING)
エージェント -> クライアント: Task(COMPLETED, artifact=booking)AUTH_REQUIRED は、作業中に追加認可が必要であることを示します。たとえば、出張エージェントが航空会社アカウントに対するユーザーの認可を必要とする場合です。
クライアントは OAuth または同意フローを帯域外で実行し、その後 Task を継続する必要があります。エージェントが認証を要求したからといって、パスワード、リフレッシュトークン、再利用可能なシークレットを通常の Message テキストとして送信しないでください。
詳細な例: 法人出張 #
独立して運用されるエージェントを調整する企業アシスタントを考えます。
参加者 #
出張オーケストレーター
-> ポリシーエージェント
-> 航空券エージェント
-> ホテルエージェント
-> 経費エージェント各リモートシステムは Agent Card を公開します。オーケストレーターの承認済みレジストリには、各プロバイダーの信頼済みカードと OAuth audience が含まれます。
フロー #
ユーザーが次のように依頼します。
text10 月 12 日から 16 日まで、シンガポールからヘルシンキへの旅行を計画してください。 月曜日の 09:00 の会議までに到着する必要があります。 まだ購入は行わないでください。オーケストレーターは、従業員等級、コストセンター、経路、日付を構造化された Part としてポリシーエージェントに送信します。
ポリシーエージェントは、ポリシー Artifact を含む完了済み Task を返します。
json{ "cabin": "economy", "maxNightlyHotelRate": 240, "currency": "EUR", "approvalRequiredAbove": 1800 }オーケストレーターは、自身のワークフロー内で航空券 Task とホテル Task を並列に開始します。各エージェントには、必要なポリシーフィールドだけを送信します。
航空券エージェントは状態をストリーミングします。
textworking: 直行ルートを検索中 working: 直行ルートは到着制約に違反 working: 乗り継ぎルートを検索中 completed: artifact flight-offers.jsonホテルエージェントは、オフィス所在地が 2 つあるため
INPUT_REQUIREDに到達します。オーケストレーターはユーザーに確認し、選択されたオフィスで同じ Task を継続します。オーケストレーターは、2 つの構造化 Artifact を結合し、完全な旅程候補を計算してユーザーに提示します。
ユーザーが 1 つの候補を選択します。これにより同じオーケストレーションコンテキスト内で新しい予約 Task が作成されます。完了済みの検索 Task は変更されません。
合計額がポリシーのしきい値を超えるため、経費エージェントが承認 Task を作成し、プッシュ通知を設定します。数時間後にマネージャーが承認します。
オーケストレーターは認証済み通知を受け取り、Task を取得し、承認額と有効期限を確認してから予約 Task を継続します。
A2A が役立つ理由 #
航空券とホテルのプロバイダーは、それぞれ独自のモデル、ツール、価格システム、計画ロジックを保持します。オーケストレーターが見るのは、宣言されたスキル、Task 状態、Message、Artifact です。プロバイダーは、連携契約を変更せずに内部フレームワークを置き換えられます。
A2A はトランザクションの原子性を解決しません。航空券の予約が成功してホテルが失敗した場合、オーケストレーターには依然として補償ロジック、期限付き予約、ドメイン固有のトランザクションワークフローが必要です。
詳細な例: ソフトウェアデリバリー #
異なるエンジニアリングチームが所有するエージェントを、リリースオーケストレーターが調整します。
コーディングエージェント -> テストエージェント -> セキュリティエージェント -> デプロイメントエージェントフロー #
コーディングエージェントが Task
T1を完了し、次のものを出力します。- Git commit 参照
- patch Artifact
- change-summary Artifact
- 予想されるテスト範囲
オーケストレーターはテストエージェントとセキュリティエージェントに別々の Message を送信します。各 Message は
T1を参照しますが、そのリポジトリと操作に対して認可された短期間のリポジトリ資格情報だけを含みます。テストエージェントは次のようにストリーミングします。
textTask submitted payments モジュールをコンパイル中 1,842 件の単体テストを実行中 37 件の統合テストを実行中 Artifact: junit-results.xml Task completedセキュリティエージェントは
INPUT_REQUIREDを返します。textこのパッチは認可動作を変更しています。エンドポイントはサービス ID、エンドユーザー、 それとも両方を対象としていますか?オーケストレーターはコードオーナーから回答を取得し、同じセキュリティ Task を継続します。
セキュリティエージェントは構造化された検出結果を伴って完了します。
json{ "decision": "block", "findings": [ { "severity": "high", "file": "AuthorizationService.java", "line": 118, "summary": "Tenant constraint omitted" } ] }オーケストレーターはデプロイを実行しません。コーディングエージェント用に修正を要求する refinement Task
T4を作成し、T1とセキュリティ Task を参照します。新しいパッチに対して、新しいテスト Task とレビュー Task が作成されます。完了済み Task は不変の監査記録として残ります。
デプロイを許可するかどうかは、LLM の散文ではなく、決定論的なリリースポリシーによって、必要なチェックがすべて満たされているかに基づいて判断されます。
A2A が役立つ理由 #
各チームは異なるフレームワークでエージェントを構築できます。結果はチャットのスクレイピングではなく、型付き Artifact として保持されます。ストリーミングは高コストなテストスイートの進捗を公開し、中断された Task は過去の作業を破棄せずに質問を受け付けられます。
このプロトコルは、生成されたコードを安全にするものではありません。ブランチ保護、認可、再現可能なビルド、署名、隔離実行、人間による承認は引き続き必要です。
詳細な例: 保険請求 #
請求受付エージェントが、モバイルアプリケーションからテキスト、画像、ドキュメントを受信します。
請求受付エージェント
-> 損害評価エージェント
-> 補償範囲エージェント
-> 不正レビューエージェント
-> 修理ネットワークエージェントマルチモーダル交換 #
受付 Message には次のものが含まれます。
- 事故を説明するテキスト
- スコープを限定した URL で参照される画像 Part
- PDF の警察報告書
- 構造化された車両および保険契約データ
- 整合性検証用のハッシュ
損害評価エージェントは次のものを返します。
- 人間が読める要約
- 損傷したコンポーネントの構造化リスト
- 注釈付き画像 Artifact
- 不確実性スコア
補償範囲エージェントにはポリシー条項が表示されますが、不要な事故画像は表示されません。不正エージェントには、その役割に適した編集済み証拠だけが渡されます。各 A2A 呼び出しの前にオーケストレーターがデータを最小化します。
Human in the Loop #
評価信頼度が低い場合、Task は INPUT_REQUIRED に入ります。
地面の高さから撮影した左後輪の写真を提供してください。モバイルユーザーが別の画像をアップロードし、受付エージェントが同じ Task を継続します。
推定損害額がしきい値を超える場合、ワークフローは人間の損害査定担当者用に別の Task を作成します。A2A は連携を追跡しますが、法的に重要な判断は決定論的な保険金請求ポリシーと資格を持つ人間が行います。
A2A が役立つ理由 #
Part により、テキスト、構造化データ、ファイル参照を 1 つの対話で扱えます。Task は断続的なモバイル接続をまたいで存続します。Artifact は永続的な成果物を表し、リモートの専門エージェントの内部は不透明なままです。
実装では、同意、保持期間、地域処理、医療データ規則、各 Artifact URL に対する厳格な認可も引き続き適用する必要があります。
詳細な例: 調達と交渉 #
調達エージェントが、複数のサプライヤーエージェントから 500 台のノートパソコンの見積もりを必要としているとします。これは、エージェントがステートレスな価格ツール以上のものである理由を示します。
フロー #
クライアントは、必要な仕様、納品場所、サービス条件、回答期限を 3 つの承認済みサプライヤーエージェントに送信します。
各サプライヤーは Task を作成し、明確化の質問を行う場合があります。
サプライヤーは、価格、在庫、保証、有効期限、商取引条件を含む見積もり Artifact を返します。
調達エージェントは、新しい Task で改善を要求します。
textハードウェアと納品日は同じにしてください。3 年保証を付け、価格差を見積もってください。各改善は、過去の Task と見積もり Artifact を参照します。
クライアントは Artifact の系譜と受諾を担当するため、見積もりのバージョンを追跡します。
決定論的なポリシーエンジンが必須条件を比較します。モデルはトレードオフを要約できますが、要件を免除することはできません。
人間が選択した見積もりを承認します。
狭い認可と冪等性キーを使用して、別の購入 Task が注文を実行します。
A2A が役立つ理由 #
交渉は複数ターンで行われ、各サプライヤーが推論と在庫ツールを所有します。Task と Artifact は、すべてのサプライヤーに 1 つの専用エージェント SDK を強制せずに、一貫した仕組みを提供します。
A2A は見積もりスキーマを標準化しません。購入者とサプライヤーは、機械比較可能な商取引条件のために、共有ドメインスキーマまたは拡張を引き続き必要とします。
セキュリティモデル #
A2A は、認証情報をプロトコル Message に配置するのではなく、標準的な Web セキュリティを再利用します。
Agent Card は、サポートするセキュリティスキームと要件を宣言します。クライアントは帯域外で認証情報を取得し、トランスポートヘッダーを通じて送信します。
Authorization: Bearer eyJ...本番の A2A インターフェースは HTTPS を使用し、サーバーのアイデンティティを検証する必要があります。組織間デプロイメントでは、OAuth 2.0/OIDC、ワークロードアイデンティティ、mTLS、またはそれらの組み合わせが一般的です。
認証は呼び出し元が誰であるかに答えます。すべての操作には引き続き認可が必要です。
- この呼び出し元はスキルを呼び出せるか。
- この呼び出し元は Task とコンテキストにアクセスできるか。
- Artifact を参照できるか。
- この出力モダリティを要求できるか。
- この作業をキャンセルできるか。
- リモートエージェントは、このエンドユーザーのために基礎となる操作を実行できるか。
不透明な実行は実装の詳細を保護しますが、ユーザーを保護するものではありません。悪意のあるエージェントや侵害されたエージェントは、有害なコンテンツを返したり、委任された認証情報を悪用したり、実際には成功していない作業を成功したと主張したりできます。
委任 #
あるエージェントが別のエージェント境界を越えてユーザーのために動作する場合、次の情報を保持します。
- ポリシー上必要な場合のエンドユーザー ID
- 呼び出し元ワークロードの ID
- テナント
- audience
- 認可されたスコープ
- 目的と同意
- トークンの有効期限
- トレースコンテキスト
両方のエージェントが技術的に受け入れられるからといって、広範な bearer token を転送しないでください。リモートスキルに必要なスコープだけを持つ、短期間で audience にバインドされたトークンに交換してください。
信頼できないコンテンツ #
すべての Message、Part、Artifact、Agent Card、参照ファイルは信頼できない入力です。次を適用してください。
- JSON とメディアタイプの検証
- バイト数、履歴、ネストの制限
- マルウェアスキャン
- 展開サイズの制限
- URL スキームと宛先の制限
- レンダリング出力に対するコンテンツセキュリティポリシー
- プロンプトインジェクション防御
- 出力スキーマ検証
- エージェントのテキストとは独立したドメイン認可
特権アプリケーションのオリジンで HTML Artifact を直接レンダリングしないでください。
信頼性とワークフローの意味論 #
A2A は Task 状態を提供しますが、分散トランザクションコーディネーターではありません。クライアントとサーバーには、引き続き次のものが必要です。
- 永続的な Task ストレージ
- 冪等なビジネス操作
- リクエストの重複排除
- ジッター付きの上限付き再試行
- デッドラインと有効期限
- キャンセルの伝播
- 部分的成功に対する補償
- Artifact の整合性と保持
- バックプレッシャー
- 同時実行数の制限
- プロセス再起動後の復旧
キャンセルされた Task は、外部副作用が取り消されたことを証明しません。航空券がすでに発券されていたり、メールがすでに送信されていたりする可能性があります。キャンセルとビジネス上の補償を別々にモデル化してください。
ネットワーク障害は曖昧性を生みます。
クライアントが「購入」を送信
サーバーが購入を実行
レスポンスが失われる
クライアントは購入が実行されたか分からない重大な操作には、ドメインの冪等性キーと照会可能なビジネス参照を使用してください。messageId はプロトコル Message を識別しますが、実装がその動作を明示的に定義して永続化していない限り、ビジネス上の唯一の保証にしてはいけません。
Task と Artifact には保持ポリシーが必要です。サービス契約で保証されていない限り、完了済み Task を永久に取得できるとは仮定しないでください。
可観測性 #
A2A 呼び出し間で W3C Trace Context ヘッダーを伝播させます。有用なスパン属性とログには、次のものがあります。
- リモートエージェントの ID とバージョン
- プロトコルとバインディングのバージョン
- 操作
- Task ID とコンテキスト ID
- スキル
- 状態遷移
- メディアタイプ
- Artifact サイズ
- 再試行回数
- レイテンシ
- 認証済みクライアントアプリケーション
プロンプトテキスト、ドキュメントコンテンツ、アクセストークン、個人データをメトリクスラベルに入れないでください。Message または Artifact を含むログには、編集、アクセス制御、保持期間の制限が必要です。
重要なメトリクスには次のものがあります。
- 操作別のリクエスト率とエラー率
- Task キューと実行レイテンシ
- 状態別の Task 数
- 入力または認証の待機時間
- ストリーム切断率と再購読率
- プッシュ通知配信失敗
- キャンセルレイテンシ
- Artifact のバイト数
- 下流モデルとツールのコスト
重大な操作の監査は、診断ログとは別に記録してください。
拡張 #
拡張は、コアプロトコルを変更せずに動作またはデータを追加します。Agent Card は、各拡張を安定した URI、説明、パラメーター、クライアントが理解する必要があるかどうかとともに宣言します。
必須拡張がサポートされていない場合、クライアントはエージェントを呼び出してはいけません。オプション拡張は適切に機能を縮退させる必要があります。
単一アプリケーションの非公開メタデータを運ぶだけではなく、複数の独立実装が相互運用可能な意味論を必要とする場合に拡張を使用してください。ベンダー拡張は、A2A が削減しようとしているロックインを再現する可能性があるため、可能な限りコアの対話を利用可能にし、準拠内容を正確に文書化してください。
A2A サーバーの実装 #
実用的なサーバー実装は、次のように進めます。
- 限定されたスキルと、その入力および出力メディアタイプを定義する。
- 最小限の公開 Agent Card を公開する。
- まず公式バインディングと SDK を 1 つ選択する。
- HTTP またはトランスポート境界で認証する。
- スキル、Task、コンテキスト、Artifact を認可する。
- Message を検証し、安全にファイルを参照する。
- 直接 Message を返すか Task を作成するかを決定する。
- ノンブロッキング作業を確認する前に Task を永続化する。
- 有効な状態遷移と不変の終端状態を発行する。
- 整合性および保持メタデータとともに Artifact を保存または参照する。
- 中間更新に価値がある場合にのみストリーミングを追加する。
- SSRF 対策と認証済み配信を備える場合にのみプッシュ通知を追加する。
- トレースを伝播し、監査イベントを記録する。
- 互換性と保持の保証を公開する。
エージェントの内部実装には、LLM、決定論的ワークフロー、人間のキュー、ツール、その他の A2A エージェントを使用できます。Chain of Thought や内部認証情報をステータス Message として公開しないでください。
A2A クライアントの実装 #
堅牢なクライアントは、次のことを行う必要があります。
- 信頼できるソースから Agent Card を発見する。
- 検証してキャッシュする。
- 相互にサポートされるプロトコルバージョン、バインディング、メディアタイプを選択する。
- ローカルの信頼ポリシーとデータ共有ポリシーを適用する。
- audience にバインドされた認証情報を取得する。
- Message の相関データを生成して永続化する。
- 必要最小限のコンテキストを送信する。
- 返された Task ID とコンテキスト ID を直ちに永続化する。
- 直接 Message と Task のレスポンスを処理する。
- 拒否と認証を含む、すべての Task 状態を処理する。
- 再接続、ポーリング、またはプッシュ通知を冪等に処理する。
- Artifact を使用前に検証する。
- 結果に重大な影響を与える後続操作の前に、決定論的なポリシーを適用する。
- 委任された Task 間のトレースと監査の関係を記録する。
LLM に任意の Agent Card URL を選択させ、直ちに認証情報や非公開データを送信させないでください。発見と呼び出しには、許可リストまたは信頼ポリシーが必要です。
A2A を使用する場合 #
次の場合に A2A を使用します。
- 独立して所有されるエージェント間で相互運用が必要
- リモートシステムが単一関数ではなく、真にエージェント型
- 能力の発見が有用
- 対話に明確化または交渉が必要になる可能性
- 作業が長時間実行または再開可能
- リッチな、または増分的な Artifact が必要
- 内部エージェント実装を不透明に保つ必要
- 複数の言語とフレームワークで 1 つの契約を共有する必要
次の場合は、通常の API、イベントスキーマ、ワークフローアクティビティ、または MCP ツールを優先します。
- 入出力が完全に決定論的
- 短い 1 回のリクエストで常に処理が完了
- 意味のある会話または Task ライフサイクルが存在しない
- 両者が緊密に結合された 1 つのアプリケーション
- エージェントの柔軟性より強い静的ドメインスキーマが重要
- 自律的な動作の追加が、ユーザー価値なしにリスクを生む
よくある間違い #
- 発見を信頼とみなす。 Agent Card は主張を記述するものであり、信頼するかどうかはポリシーが決定する。
- Message に認証情報を入れる。 トランスポートレベルの認証と帯域外認可を使用する。
- コンテキスト ID を認可に使う。 これは不透明なグループ化識別子にすぎない。
- すべてのユーザーコンテキストをすべてのエージェントに送信する。 委任されたスキルごとにデータを最小化する。
- 構造化出力があるのに散文を解析する。 適切なメディアタイプをネゴシエートする。
- 終端 Task を再起動する。 同じコンテキストに新しい Task を作成し、過去の Task を参照する。
- キャンセルが副作用を取り消すと仮定する。 ドメイン補償を実装する。
- 任意のプッシュ URL を信頼する。 SSRF を防止し、コールバックを認証する。
- ストリーミングが永続的だと仮定する。 ID を永続化し、再購読またはポーリングをサポートする。
- A2A とオーケストレーションを混同する。 クライアントはワークフローと障害ポリシーを引き続き所有する。
- A2A と MCP を混同する。 エージェントは A2A で協働し、MCP で限定されたツールを使用する。
- オーケストレーションモデルに最終権限を与える。 決定論的コードが権限、予算、承認ルールを適用する必要がある。
- プロトコルネゴシエーションを無視する。 Card は複数のバインディングとバージョンを公開できます。
- 1.0 より前の古い例を変更せずに使う。 v1.0 の標準モデルでは、フィールド名、列挙型、バインディング構造が変更されています。
A2A の価値は、エージェント同士が JSON を送信できることではありません。通常の HTTP でもすでに実現できます。その価値は、不透明なエージェントの発見、ステートフルな作業の委任、モダリティのネゴシエーション、中断への対応、増分または永続的な結果の取得を実現する共有モデルにあります。この共通層により、クロスフレームワークの協働が可能になります。一方で、ビジネススキーマ、オーケストレーション、信頼、安全性は、それらを理解するアプリケーションに委ねられます。
コメント
GitHub で閲覧・コメントする(投稿にはログインが必要です)