---
title: "A2A（Agent2Agent）プロトコルとは？v1.0の仕組み・MCPとの違い・実装手順"
url: "https://www.issoh.co.jp/tech/details/6732/"
published: 2025-05-13
updated: 2026-10-12
categories: ["AIエージェント・MCP"]
publisher: "株式会社一創"
---

# A2A（Agent2Agent）プロトコルとは？v1.0の仕組み・MCPとの違い・実装手順

A2A（Agent2Agent）プロトコルは、別々のベンダーやフレームワークで作られたAIエージェント同士が、互いの内部実装を見せないまま仕事を依頼し合うためのオープン仕様です。Googleが2025年4月に公開し、現在はLinux Foundationのプロジェクトとして運営されています。2026年3月に初の安定版であるv1.0.0が出て、メソッド名や列挙値の表記が0.3系から大きく変わりました。

この記事では、v1.0.1の仕様書を一次情報として、Agent Card・Task・3つのプロトコルバインディングの仕組み、MCPとの役割分担、0.3からの移行で詰まる点を整理します。後半では公式Python SDK（a2a-sdk 1.1.2）で最小のA2Aサーバーを起動し、実際に返ってきたレスポンスも載せています。

## まとめ：A2A v1.0の要点と採用判断

- A2Aは「エージェント同士」の通信規格です。エージェントがツールやデータにつなぐ規格であるMCPとは担当範囲が異なり、公式は「MCPはエージェントの内側、A2Aはエージェントの間」で併用する構成を示しています。
- 相手の能力は `/.well-known/agent-card.json` に置くAgent Cardで知り、仕事はTaskとして受け渡します。Taskの状態は8種類で、完了・失敗・キャンセル・拒否の4つが終端状態です。
- v1.0ではJSON-RPC 2.0・gRPC・HTTP+JSON（REST）の3方式が同じ11操作を持ちます。`message/send` は `SendMessage` に、`"completed"` は `"TASK_STATE_COMPLETED"` に変わりました。
- クライアントは `A2A-Version` ヘッダを送る必要があります。省略すると0.3として扱われ、v1.0専用のサーバーからはエラー `-32009` が返ります（a2a-sdk 1.1.2で確認）。
- 組織やベンダーをまたいでエージェントに仕事を任せる場合は、採用する価値があります。1つのアプリの中で関数を呼ぶだけなら、MCPか通常の関数呼び出しで足ります。

## A2Aプロトコルの定義と策定の経緯

仕様書は、A2Aの目的を「独立した、場合によっては内部が見えないAIエージェント同士の通信と相互運用」としています。A2Aでできることは、相手の能力の発見、やり取りする形式（テキスト・ファイル・構造化データ）の取り決め、共同作業するタスクの管理、そして**相手の内部状態・記憶・ツールにアクセスしないままの**情報交換です。最後の条件は仕様で「Opaque Execution」と呼ばれており、A2Aの設計の中心にあります。

| 時期         | 出来事                              |
| ---------- | -------------------------------- |
| 2025年4月    | GoogleがA2Aを公開                    |
| 2025年6月23日 | Linux FoundationがA2Aプロジェクトの発足を発表 |
| 2025年7月30日 | v0.3.0リリース                       |
| 2026年3月12日 | v1.0.0リリース（初の安定版）                |
| 2026年4月9日  | LFが1周年の発表で支持組織150超と公表            |
| 2026年5月28日 | v1.0.1リリース                       |

日付は[GitHubのA2Aリリース一覧](https://github.com/a2aproject/A2A/releases)と、Linux Foundationのプレスリリース（[2025年6月23日のプロジェクト発足発表](https://www.linuxfoundation.org/press/linux-foundation-launches-the-agent2agent-protocol-project-to-enable-secure-intelligent-communication-between-ai-agents)、[2026年4月9日の1周年発表](https://www.linuxfoundation.org/press/a2a-protocol-surpasses-150-organizations-lands-in-major-cloud-platforms-and-sees-enterprise-production-use-in-first-year)）に基づきます。Linux Foundationの発足時の発表では、創設メンバーはAWS・Cisco・Google・Microsoft・Salesforce・SAP・ServiceNowの7社でした。v1.0の発表文では、技術運営委員会（TSC）はこの7社にIBM Researchを加えた8社の代表で構成されると書かれています。2026年4月のLF発表は、MicrosoftがAzure AI FoundryとCopilot StudioにA2Aを組み込み、AWSがAmazon Bedrock AgentCore Runtimeで対応したことを挙げています。AgentCore側の使い方は[Amazon Bedrock AgentCore APIの使い方｜SDK・CLIでAIエージェントを本番デプロイ【2026年最新】](/tech/details/8230/)で扱っています。

## A2AとMCPの違いと併用の考え方

公式ドキュメント「A2A and MCP: Detailed Comparison」は、2つの違いを「エージェントが何とやり取りするか」で説明しています。入出力が決まっていて、多くは状態を持たないもの（計算機、DB検索API、天気取得）が相手ならMCPを使います。自分で推論・計画し、複数のツールを使い、長いやり取りの間状態を保つエージェントが相手ならA2Aを使います。

| 観点    | A2A             | MCP         |
| ----- | --------------- | ----------- |
| 接続先   | 他のエージェント        | ツール・データ・API |
| 作業の単位 | 状態を持つTask       | ツール呼び出し     |
| 相手の中身 | 見えない前提          | 入出力スキーマを公開  |
| 長時間処理 | ストリーミング・Webhook | 拡張で対応       |
| 代表例   | 窓口→請求担当エージェント   | エージェント→DB検索 |

公式の例は自動車整備工場です。顧客と店長エージェントの会話、店長と整備士エージェントの間の診断のやり取り、部品業者エージェントへの発注はA2Aで行います。整備士エージェントが診断スキャナーや整備マニュアルDBを呼ぶ部分はMCPです。v1.0の発表文も「MCPは個々のエージェントのツール・コンテキスト統合、A2Aはエージェント間の通信と調整」と述べ、置き換えではなく補完の関係だとしています。

MCP側の設計は[AIエージェントにMCPで外部ツールを接続する実装手順とは？tool定義・権限・認可の設計を解説【2026年版】](/tech/details/15365/)で解説しています。なお、A2Aサーバーのスキルのうち状態を持たない呼び出しに近いものは、MCP互換のリソースとして公開する構成も公式ドキュメントで紹介されています。

## A2Aの構成要素：Agent Card・Task・Message・Artifact

### Agent Cardによるエージェントの発見

A2Aサーバーは、Agent Cardを必ず公開しなければなりません。取得方法は3つあり、`https://{ドメイン}/.well-known/agent-card.json` へのアクセス、カタログやレジストリの検索、URLや中身を直接設定する方法です。カードには名前・説明・スキル一覧・入出力のメディアタイプ・認証方式、そして接続先の `supportedInterfaces` を書きます。

- `supportedInterfaces` は優先順に並べ、各要素に `url`・`protocolBinding`・`protocolVersion` を持たせます。クライアントは先頭から、自分が対応している方式を選びます。
- カードにはJWS（RFC 7515）で署名できます。署名の前に、RFC 8785（JSON Canonicalization Scheme）でJSONを正規化する手順が定められています。
- 認証済みのクライアントにだけ見せる拡張カードは `GetExtendedAgentCard` で返します。`capabilities.extendedAgentCard` が `false` または未指定のとき、この操作は `UnsupportedOperationError` を返します。
- サーバーは `Cache-Control` と `ETag` を付けることが推奨されています（SHOULD）。クライアントは期限切れ後に `If-None-Match` で再検証します。

拡張カードに社内サービスのURLや認証情報を載せないよう、仕様のセキュリティ章は明記しています。公開カードと拡張カードに何を載せるかは、最初に決めておく必要があります。

### Taskの8つの状態と終端条件

Taskは、サーバーが発行するIDを持ち、ライフサイクルのある作業単位です。v1.0の `TaskState` は、未指定の `TASK_STATE_UNSPECIFIED` を除いて8つの値を持ちます。

| 値                            | 区分  | 意味           |
| ---------------------------- | --- | ------------ |
| 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        | 終端  | エージェントが実行を拒否 |

終端状態のTaskにはメッセージを追加できません。送ると `UnsupportedOperationError` になり、購読（`SubscribeToTask`）も同じエラーになります。続きをやらせたいときは、同じ `contextId` で新しいTaskを作ります。入力待ち（`TASK_STATE_INPUT_REQUIRED`）のTaskには、同じ `taskId` と `contextId` を付けてメッセージを送り、処理を続けさせます。認可待ち（`TASK_STATE_AUTH_REQUIRED`）の場合は、エージェントが資格情報をA2Aの外で受け取った時点で、クライアントの追加メッセージなしに処理を再開してよいことになっています。

### Message・Part・Artifactと会話の継続

Messageは1回分の発言で、`role`（`ROLE_USER` または `ROLE_AGENT`）と、中身を入れる `parts` を持ちます。Partにはテキスト、ファイル、JSONのような構造化データを入れられます。エージェントの成果物はArtifactとしてTaskに付き、これもPartの集まりです。

会話の単位は `contextId` です。`taskId` だけを指定した場合、サーバーはそのTaskから `contextId` を補います。両方を指定して、その組み合わせが食い違っている場合は、サーバーが拒否しなければなりません（MUST）。`contextId` を自前で採番して送る場合は、仕様にある「サーバー側の扱いを理解していない限り送るべきでない」という注意に従ってください。

## v1.0の3つのプロトコルバインディングと操作一覧

v1.0では、`a2a.proto` が正式な定義の出所になりました。JSON-RPC 2.0・gRPC・HTTP+JSON（REST）の3方式は、同じ操作を同じ意味で提供することが求められています。JSON-RPCのストリーミングはServer-Sent Events（`text/event-stream`）で送ります。

| JSON-RPC / gRPC                  | REST                                                  |
| -------------------------------- | ----------------------------------------------------- |
| SendMessage                      | POST /message:send                                    |
| SendStreamingMessage             | POST /message:stream                                  |
| GetTask                          | GET /tasks/{id}                                       |
| ListTasks                        | GET /tasks                                            |
| CancelTask                       | POST /tasks/{id}:cancel                               |
| SubscribeToTask                  | POST /tasks/{id}:subscribe                            |
| CreateTaskPushNotificationConfig | POST /tasks/{id}/pushNotificationConfigs              |
| GetTaskPushNotificationConfig    | GET /tasks/{id}/pushNotificationConfigs/{configId}    |
| ListTaskPushNotificationConfigs  | GET /tasks/{id}/pushNotificationConfigs               |
| DeleteTaskPushNotificationConfig | DELETE /tasks/{id}/pushNotificationConfigs/{configId} |
| GetExtendedAgentCard             | GET /extendedAgentCard                                |

エラーも3方式で対応が決まっています。たとえば `TaskNotFoundError` は、JSON-RPCでは `-32001`、gRPCでは `NOT_FOUND`、HTTPでは404です。JSONのフィールド名はcamelCaseで、列挙値はprotoで定義した名前（`TASK_STATE_INPUT_REQUIRED` など）をそのまま文字列にします。

### 結果の受け取り方：ポーリング・ストリーミング・プッシュ通知

- **ポーリング**：`GetTask` を定期的に呼びます。すべての方式で使え、ファイアウォールが厳しい環境でも動きますが、遅延と無駄なリクエストが増えます。
- **ストリーミング**：`SendStreamingMessage` と `SubscribeToTask` を使います。Agent Cardで `capabilities.streaming` を `true` にしておく必要があります。1つのTaskに複数のストリームを張れて、全ストリームに同じイベントが同じ順で届きます。
- **プッシュ通知**：クライアントが登録したWebhookに、エージェントがHTTP POSTを送ります。gRPCで通信していても、Webhookは素のHTTPとHTTPバインディングのJSONで送られます。`capabilities.pushNotifications` を `true` にしておく必要があります。

数時間かかるバッチ処理や、人の承認を挟む処理はプッシュ通知が向いています。チャット画面の進捗表示のように、すぐ反映したい用途はストリーミングを選びます。MCP側にも長時間処理の仕組みがあり、比較する場合は[MCP Tasks拡張とは？tasks/getポーリングとサーバ主導の非同期設計を解説](/tech/details/16919/)が参考になります。

## v0.3からv1.0への主な破壊的変更

公式の「What’s New in A2A Protocol v1.0」に載っている変更のうち、既存の実装がそのままでは動かなくなるものを挙げます。

| 項目              | v0.3                               | v1.0                           |
| --------------- | ---------------------------------- | ------------------------------ |
| 送信メソッド          | message/send                       | SendMessage                    |
| 再購読             | tasks/resubscribe                  | SubscribeToTask                |
| 拡張カード取得         | agent/getAuthenticatedExtendedCard | GetExtendedAgentCard           |
| 状態の値            | “input-required”                   | “TASK\_STATE\_INPUT\_REQUIRED” |
| 役割の値            | “user”                             | “ROLE\_USER”                   |
| 型の判別            | kind フィールド                         | JSONのメンバー名                     |
| 接続先の宣言          | preferredTransport ほか              | supportedInterfaces\[\]        |
| protocolVersion | カード直下                              | 各インターフェース                      |
| OAuthフロー        | implicit・password あり               | 削除、Device Code追加               |

ほかにも、ストリームイベントから `final` が消えたこと（終了はストリームを閉じることで伝える）、`tasks/{id}` のような複合IDをやめて単純なUUIDにしたこと、Authorization CodeフローにPKCE必須を示す `pkce_required` が加わったことが変更点です。新しく加わった `ListTasks` はカーソル方式のページングに対応しました。

移行は一度に切り替える必要はありません。発表文によると、Agent Cardは後方互換の形で拡張されており、1枚のカードで0.3とv1.0の両方の対応を示せます。`supportedInterfaces` に `protocolVersion` が異なるエントリを並べれば、古いクライアントを残したまま段階的に移せます。

### A2A-Versionヘッダの付け忘れで起きる-32009エラー

仕様3.6では、クライアントは毎回 `A2A-Version` を送らなければならず（MUST）、サーバーは値が空なら0.3として扱うことになっています。下の最小サーバー（v1.0だけに対応）で、同じ `SendMessage` リクエストをヘッダありとヘッダなしで送り比べました。ヘッダなしでは、次のエラーが返りました。

```
{"error":{"code":-32009,"message":"A2A version '0.3' is not supported by this handler. Expected version '1.0'.","data":[{"@type":"type.googleapis.com/google.rpc.ErrorInfo","reason":"VERSION_NOT_SUPPORTED","domain":"a2a-protocol.org","metadata":{}}]},"id":1,"jsonrpc":"2.0"}
```

メソッド名を旧名の `message/send` にした場合は、バージョンの不一致ではなく `-32601 Method not found` が返ります。v1.0へ移行した直後に「メソッドが見つからない」「バージョン非対応」と言われたら、まずこの2点を確認してください。仕様は、SDKが古い版へ黙って切り替えると新機能が消えることにも触れており、最新機能が必要なクライアントでは要求するバージョンを固定するよう勧めています。

## A2Aの認証・認可とセキュリティ設計

A2Aは、IDや資格情報をメッセージの中身ではなく、HTTPヘッダやgRPCメタデータといったトランスポート層で扱います。本番環境ではHTTPSまたはTLSが必須（MUST）で、TLS 1.3以上が推奨されています。サーバーはリクエストごとに認証しなければなりません。

- **宣言できる認証方式**：APIキー、HTTP認証（Bearerなど）、OAuth 2.0（Authorization Code・Client Credentials・Device Code）、OpenID Connect、相互TLSの5種類です。Agent Cardの `securitySchemes` と `securityRequirements` に書きます。正式定義の `a2a.proto` ではこの名前ですが、仕様書のAgent Cardサンプル（8.5節）には旧名の `security` が残っているので、サンプルを写すときは注意してください。
- **資格情報の取得**：クライアントはカードで要件を確認し、A2Aの外（OAuthフローなど）でトークンを取ってから、毎回のリクエストに付けます。
- **タスク途中の認可**：処理中に別APIのトークンや人の承認が必要になったら、エージェントはTaskを `TASK_STATE_AUTH_REQUIRED` にします。上流のクライアントがA2Aエージェントであれば、自分のTaskも同じ状態にして、さらに上流へ認可を依頼できます。
- **取得範囲の制限**：`ListTasks` と `GetTask` は、呼び出し元が見てよいTaskだけを返さなければなりません。権限チェックは、範囲外のリソースがあるかどうかが漏れるDB問い合わせよりも先に行うことが求められています。
- **Webhookの保護**：エージェントは、SSRF対策として、ループバック（127.0.0.0/8）、プライベートIP（10.0.0.0/8など）、localhost、リンクローカル宛てのURLを拒否することが推奨されています。受信側は認証情報を検証して2xxを返し、重複して届く前提で冪等に処理します。

タスク途中の認可で資格情報をA2Aメッセージの中に入れて渡すと、連鎖するすべてのエージェントにその資格情報が見えてしまいます。仕様がHTTPSなどの別経路で渡すことを基本にしているのはこのためです。エージェントに委譲する認可をIdP側で管理する考え方は、[Okta Cross App Access（XAA）とは？AIエージェントの認可を統制する新標準を2026年動向で解説](/tech/details/12774/)で紹介しています。

## Python SDKで最小のA2Aサーバーを動かす手順

公式のhelloworldサンプルを1ファイル（`server.py`）にまとめ、受け取ったテキストを返すだけのサーバーにしました。キャンセルは実装しておらず（`cancel` は例外を投げます）、Taskはメモリ上の `InMemoryTaskStore` に置くので、再起動すると消えます。Python 3.12とa2a-sdk 1.1.2（PyPIの最新版、2026年9月17日時点）で動作を確認しています。

```
pip install "a2a-sdk[http-server]==1.1.2" uvicorn
```

```
import uvicorn
from starlette.applications import Starlette

from a2a.helpers import get_message_text, new_task_from_user_message, new_text_part
from a2a.server.agent_execution import AgentExecutor, RequestContext
from a2a.server.events import EventQueue
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes
from a2a.server.tasks import InMemoryTaskStore, TaskUpdater
from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill, TaskState


class EchoExecutor(AgentExecutor):
    async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
        task = context.current_task or new_task_from_user_message(context.message)
        if not context.current_task:
            await event_queue.enqueue_event(task)
        updater = TaskUpdater(event_queue=event_queue, task_id=task.id, context_id=task.context_id)
        await updater.update_status(state=TaskState.TASK_STATE_WORKING)
        text = get_message_text(context.message)
        await updater.add_artifact(parts=[new_text_part(text=f"受信: {text}", media_type="text/plain")])
        await updater.update_status(state=TaskState.TASK_STATE_COMPLETED)

    async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
        raise NotImplementedError


card = AgentCard(
    name="Echo Agent",
    description="受け取ったテキストをそのまま返す検証用エージェント",
    version="0.1.0",
    default_input_modes=["text/plain"],
    default_output_modes=["text/plain"],
    capabilities=AgentCapabilities(streaming=True),
    supported_interfaces=[
        AgentInterface(protocol_binding="JSONRPC", url="http://127.0.0.1:9999", protocol_version="1.0")
    ],
    skills=[AgentSkill(id="echo", name="Echo", description="テキストを返す", tags=["demo"])],
)

handler = DefaultRequestHandler(
    agent_executor=EchoExecutor(), task_store=InMemoryTaskStore(), agent_card=card
)
routes = create_agent_card_routes(card) + create_jsonrpc_routes(handler, "/")
app = Starlette(routes=routes)

if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1", port=9999)
```

`python server.py` で起動し、別のターミナルからAgent Cardを取得します。

```
curl -s http://127.0.0.1:9999/.well-known/agent-card.json
```

```
{"name":"Echo Agent","description":"受け取ったテキストをそのまま返す検証用エージェント","supportedInterfaces":[{"url":"http://127.0.0.1:9999","protocolBinding":"JSONRPC","protocolVersion":"1.0"}],"version":"0.1.0","capabilities":{"streaming":true},"defaultInputModes":["text/plain"],"defaultOutputModes":["text/plain"],"skills":[{"id":"echo","name":"Echo","description":"テキストを返す","tags":["demo"]}]}
```

Pythonでは `supported_interfaces` のようにsnake\_caseで書いた属性が、JSONでは `supportedInterfaces` のようにcamelCaseで出力されています。次に、`req.json` に `SendMessage` のリクエストを保存して送ります。

```
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "SendMessage",
  "params": {
    "message": {
      "role": "ROLE_USER",
      "messageId": "msg-001",
      "parts": [{"text": "こんにちは"}]
    }
  }
}
```

```
curl -s -X POST http://127.0.0.1:9999/ \
  -H "Content-Type: application/json" \
  -H "A2A-Version: 1.0" \
  -d @req.json
```

```
{"result":{"task":{"id":"cc2aeca3-8c5e-4b9a-9c82-f4c4aee8e4c7","contextId":"220aecc8-5236-4ffc-b137-ef5774c4c549","status":{"state":"TASK_STATE_COMPLETED","timestamp":"2026-09-16T19:53:32.651042Z"},"artifacts":[{"artifactId":"49a75002-a5a1-4345-aa87-39c3555a0908","parts":[{"text":"受信: こんにちは","mediaType":"text/plain"}]}],"history":[{"messageId":"msg-001","contextId":"220aecc8-5236-4ffc-b137-ef5774c4c549","taskId":"cc2aeca3-8c5e-4b9a-9c82-f4c4aee8e4c7","role":"ROLE_USER","parts":[{"text":"こんにちは"}]}]}},"id":1,"jsonrpc":"2.0"}
```

`SendMessage` は、`params.configuration.returnImmediately` を `true` にしない限り、終端状態か中断状態になるまで待ってから結果を返します。そのため、このレスポンスには完了したTaskとArtifactが入っています。返ってきた `id` を `GetTask` の `params.id` に渡すと、同じTaskを取り直せます。IDとタイムスタンプは実行するたびに変わります。Javaで同じ構成を組む場合は[A2A Javaの仕組みと主要コンポーネントを体系的に理解する](/tech/details/7234/)を参照してください。

公式SDKは5言語あります。インストール方法はそれぞれ、Pythonが `pip install a2a-sdk`、Goが `go get github.com/a2aproject/a2a-go`、JavaScriptが `npm install @a2a-js/sdk`、JavaがMaven、.NETが `dotnet add package A2A --prerelease` です（.NETは安定版が無いため `--prerelease` が必要です）。2026年9月17日時点で、npmの最新は1.1.0、NuGetの最新は1.0.0-preview2（プレビュー版）です。版は頻繁に上がるため、導入時は各レジストリで確認してください。

## A2Aを採用すべき場面と見送るべき場面

A2Aが役に立つのは、**相手のエージェントの中身を自分で管理できない**場合です。他社のエージェントや、別チームが別のフレームワークで作ったエージェントに仕事を任せるなら、Agent Cardでの発見、Taskによる状態管理、`TASK_STATE_AUTH_REQUIRED` での認可の委譲を自前で設計し直さずに済みます。窓口エージェントがリモートのエージェントに委譲する構成はA2Aリモートエージェントとは？ AIエージェント連携の基礎概念と役割を詳しく解説し、利点や事例を紹介するで扱っています。

一方、次の場合は見送ってかまいません。

- **1つのプロセス内で動くマルチエージェント**：LangGraphやCrewAIのように同じフレームワーク内で役割を分けるだけなら、関数呼び出しで済みます。A2Aを挟むと、HTTP通信、Taskの保存、認証が余分に増えます。構成の選び方は[マルチエージェントとは？仕組み・構成パターンと採用判断を実装者視点で解説【2026年版】](/tech/details/13604/)を参照してください。
- **相手が状態を持たないAPIの場合**：入出力が決まっている処理は、公式ドキュメントの整理どおりMCPのツールとして公開するほうが簡単です。A2AのTask管理やAgent Cardを用意する必要がありません。
- **.NETで本番運用する場合**：2026年9月時点でNuGetのA2Aパッケージはプレビュー版しかありません。プレビュー版のAPIは変わる可能性があるため、本番で使うなら、安定版が出るのを待つか、安定版のあるSDK（Python・Java・Goなど）で窓口を作る選択肢を検討してください。

採用する場合は、最初にAgent Cardの `supportedInterfaces` を1方式に絞り、`A2A-Version` を固定するところから始めてください。3方式すべてに対応するのは、相手先が増えてからで十分です。決済を扱う拡張は[AP2 (Agent Payments Protocol)とは何か？ 新たな決済プロトコルの概要と意義と背景](/tech/details/9716/)、画面との連携は[AG-UIとは？AIエージェントとフロントエンドをつなぐプロトコルの仕組みと実装](/tech/details/7196/)が別の記事になっています。

## よくある質問

### A2Aは何の略ですか？

Agent2Agent（Agent-to-Agent）の略です。AIエージェント同士の通信を標準化するオープンプロトコルの名前で、仕様とSDKはApache License 2.0で公開されています。

### A2AとMCPの違いは何ですか？

A2Aはエージェントとエージェントをつなぎ、MCPはエージェントとツールやデータをつなぎます。公式はどちらか一方を選ぶものではなく、エージェントの内側でMCP、エージェントの間でA2Aを使う併用構成を示しています。

### エージェントカード（Agent Card）とは何ですか？

エージェントの名前、スキル、接続先、認証方式を書いたJSONです。通常は `/.well-known/agent-card.json` に置き、JWSで署名することもできます。v1.0では接続先を `supportedInterfaces` にまとめて書きます。

### A2Aのセキュリティはどう確保しますか？

本番ではHTTPSまたはTLSが必須で、認証はAgent Cardで宣言したAPIキー・HTTP認証・OAuth 2.0・OpenID Connect・相互TLSのいずれかで行います。処理の途中で認可が必要になったときは、Taskを `TASK_STATE_AUTH_REQUIRED` にしてクライアントに依頼します。

### v0.3のクライアントはv1.0のサーバーと通信できますか？

サーバーが0.3のインターフェースも公開していれば通信できます。v1.0だけに対応したサーバーでは、`A2A-Version` ヘッダのないリクエストは0.3扱いになり、`VersionNotSupportedError`（JSON-RPCでは `-32009`）が返ります。

## 関連記事

- A2Aリモートエージェントとは？ AIエージェント連携の基礎概念と役割を詳しく解説し、利点や事例を紹介する
- [A2A Javaの仕組みと主要コンポーネントを体系的に理解する](/tech/details/7234/)
- [AIエージェントにMCPで外部ツールを接続する実装手順とは？tool定義・権限・認可の設計を解説【2026年版】](/tech/details/15365/)
- [マルチエージェントとは？仕組み・構成パターンと採用判断を実装者視点で解説【2026年版】](/tech/details/13604/)
- [AG-UIとは？AIエージェントとフロントエンドをつなぐプロトコルの仕組みと実装](/tech/details/7196/)

---

出典: [A2A（Agent2Agent）プロトコルとは？v1.0の仕組み・MCPとの違い・実装手順](<https://www.issoh.co.jp/tech/details/6732/>)（株式会社一創）
