A2Aと既存エージェントフレームワークの統合:Hermes Agentによる実証
エージェントオーケストレーションにおいてA2Aが重要な理由
Agent2Agent Protocol(A2A)は、Googleが2025年4月に導入したエージェント間通信のためのオープン標準です。AIエージェントが他のエージェントのケーパビリティを発見し、タスクを送信し、ストリーミング出力を受信し、タスクのライフサイクルを通じて追跡する方法を定義します — すべてJSON-RPC 2.0上で、両方のエージェントが同じフレームワーク、同じモデルプロバイダー、同じデプロイトポロジーを共有していることを前提としません。
A2AはMCPがカバーしないギャップを埋めます。MCPはエージェントをツールやデータソースに接続するもので — ツール呼び出しプロトコルです。A2Aはエージェントとエージェントを接続します。特化したケーパビリティ(価格ロジック、カタログ検索、RFQ処理)を必要とするエージェントは、そのケーパビリティをA2Aエンドポイント経由で公開するリモートエージェントに処理を委任し、結果をA2Aタスクとして受信し、自身のワークフローを継続できます。2つのプロトコルは補完的です — MCPはエージェントに手を与え、A2Aは同僚を与えます。
A2A仕様は3つのコアプリミティブを定義します:
- Agent Card —
/.well-known/agent-card.jsonにあるJSONドキュメントで、エージェントのアイデンティティ、ケーパビリティ、スキル、サービスエンドポイントを記述します。エージェントが互いを発見する方法です。 - Task — 作業の単位。クライアントは
message/send(非ストリーミング)またはmessage/stream(ストリーミング)でタスクを送信します。タスクは状態遷移します:submitted、working、input-required、completed、failed、canceled。 - Artifact — タスク実行中に生成される構造化された出力で、利用可能になり次第クライアントにストリーミングされます。
B2Bデプロイにとって、価値提案は具体的です:すべてを行う1つのモノリシックなエージェントを構築する代わりに、それぞれがドメインを所有する特化したエージェントを構成し — それらが共有メモリやハードコードされた関数呼び出しではなく、プロトコルを通じて協調します。
統合の問題
ほとんどの既存エージェントフレームワークはA2Aを話しません。独自のネイティブAPIサーフェス、独自のタスクモデル、独自のストリーミングメカニズムを持っています。Hermes Agent(Nous Researchによる)はOpenAI互換のAPI Serverを/v1/chat/completionsで公開し、runsベースのSSEストリーミングインターフェースを/v1/runsおよび/v1/runs/{id}/eventsで提供します。OpenClawはOpenResponses互換APIをPOST /v1/responsesで提供します。LangGraphは独自のグラフ実行モデルを持ちます。CrewAIは独自のクルーディスパッチを持ちます。
これらのフレームワークはどれも、A2Aをサポートするために内部を書き直すことはありません。書き直すべきでもありません — ネイティブAPIはそれぞれのエコシステムにうまく機能しています。問題は — コードを変更することなく、A2Aエージェントネットワークに参加できるか — ということです。
答えはブリッジ層です — A2AプロトコルとフレームワークのネイティブAPIの間に位置するコンポーネントです。ブリッジは一方の側でA2AのJSON-RPCサーフェス(Agent Card、タスクライフサイクル、ストリーミング)を実装し、もう一方の側でフレームワークのネイティブ呼び出しに変換します。フレームワークは自分がA2A経由で呼び出されていることを知りません。A2Aクライアントはどのフレームワークがタスクを実行しているかを知りません。
本稿ではHermes Agentを実証例として、ブリッジパターンを解説します。同じパターンはOpenClawや他のフレームワークにも適用されます — 変わるのはブリッジハンドラだけです。
ブリッジアーキテクチャ
このパターンの動作する参照実装がa2a_daemon_engineです — ゲートウェイモジュールとして動作し、実行をプラグ可能なハンドラにルーティングするA2Aプロトコルデーモンです。アーキテクチャは以下の通りです:
A2A Client (any agent or application)
│
POST /{endpoint_id}/a2a (message/send | message/stream)
│
▼
Gateway (auth, routing, SSE client management)
│
▼
A2A Daemon Executor
│
resolve_agent(uuid) → Database lookup
load_agent_handler() ← data-driven, metadata-based routing
│
├── HermesAgentHandler
│ → POST /v1/runs → GET /v1/runs/{id}/events → SSE streaming
│ → POST /v1/chat/completions (non-streaming)
│
└── [AnyFrameworkHandler] ← same interface, different translation
→ framework's native API
ブリッジは3つの層で構成されます:
A2Aプロトコル層 — JSON-RPCディスパッチ、Agent Cardの提供、タスクステートマシン、A2A SDK EventQueueを処理します。フレームワーク非依存です。すべての統合で同じです。
ゲートウェイトランスポート層 — HTTP、認証、SSEクライアントライフサイクル、ルーティングを処理します。これもフレームワーク非依存です。ゲートウェイはワイヤを所有し、ブリッジは変換を所有します。
フレームワークハンドラ — 唯一のフレームワーク固有のコードです。
ask_model()インターフェースを実装します:A2Aメッセージパーツとコンテキストを受け取り、フレームワークのネイティブAPIを呼び出し、レスポンスをA2Aメッセージパーツに変換し、(ストリーミングの場合)トークンデルタをSSEチャネルに転送します。
新しいフレームワークを追加するとは、1つのハンドラクラスを書くことを意味します。それ以外すべて — プロトコルサーフェス、ゲートウェイディスパッチ、SSE管理、タスク永続化 — は共有インフラです。
実証:Hermes Agentブリッジ
HermesAgentHandlerが実証例です。A2AタスクセマンティクスをHermes Agent API Serverにブリッジします。ハンドラは2つの実行モードをサポートします:
非ストリーミング:message/sendによるmessage_response
ハンドラはHermes API ServerのPOST /v1/chat/completions — OpenAI互換エンドポイント — を呼び出します。リクエストは変換されたA2Aメッセージパーツをチャットコンプリーションのペイロードとして送ります。Hermesはリクエストを処理し(モデル推論、ツール呼び出し、エージェント推論)、単一のレスポンスを返します。ハンドラはレスポンスをROLE_AGENTのA2A Messageに変換し、SDK EventQueueに送出します。
クライアントはエージェントのテキスト全体を含む単一のJSON-RPCレスポンスを受け取ります。中間のステータスイベントもストリーミングチャンクもありません — リクエストはHermesが完了するまでブロックします。
ストリーミング:message/sendによるtask_executionとstream: true
ハンドラはPOST /v1/runsを呼び出してrunを作成し、GET /v1/runs/{id}/eventsへのSSE接続を開きます。Hermesはイベントが発生するたびにストリーミングします:トークンデルタ、推論メタデータ、ツール呼び出し/結果通知、承認リクエスト、ライフサイクルイベント(run.created、run.completed、run.failed)。
ハンドラはバックグラウンドスレッドでドレインループを動かします。各message.deltaイベントは、接続されたクライアントにリアルタイムで届けるためゲートウェイのSSEマネージャーにプッシュされます。ハンドラはトークンを単一のバッファに蓄積します。run.completedが到着すると、蓄積されたテキストはSDK EventQueueへの単一のA2A Messageとして送出され、COMPLETEDステータスイベントがSSEのみにプッシュされます。
この二重経路設計 — リアルタイムチャンク用のSSE、最終蓄積メッセージ用のSDK EventQueue — は、後述するA2A SDK v2の制約への対応です。
エージェント境界をまたぐヒューマンインザループ承認
Hermesはヒューマンインザループ承認ゲートをサポートします — エージェントが機密性の高いアクションを実行する許可を必要とするとき、一時停止して承認リクエストを送出します。ブリッジはこれをA2AのINPUT_REQUIRED状態に変換し、呼び出し側のエージェント(または人間のオペレーター)に入力が必要であることを通知します。レスポンスはPOST /v1/runs/{id}/approvalを通じて戻り、runが継続します。
ここがブリッジパターンの価値が示される場所です。A2AはINPUT_REQUIREDをファーストクラスのタスク状態として定義します。Hermesは独自の承認メカニズムを持ちます。ブリッジが一方を他方にマッピングし、呼び出し側エージェント — それ自体が完全に異なるフレームワークで動くA2Aクライアントかもしれない — はHermes固有の詳細ではなく標準プロトコルの状態遷移を見ます。エージェント委任チェーンに人間の承認を必要とするステップ(購入承認、データアクセスの決定、見積もり承認)を含めることができ、A2Aプロトコルがそのゲートをフレームワーク境界をまたいで透過的に運びます。
A2A状態マッピング
A2Aはタスクステートマシンを定義します:submitted → working → input-required | completed | failed | canceled。各フレームワークは独自のイベント語彙を持ちます。ブリッジが両者の間をマッピングします。
Hermesのイベントと状態のマッピング:
| Hermes SSE Event | A2A Task State | Bridge Action |
|---|---|---|
run.created |
WORKING |
キャンセルサポートのためにrun_idを登録 |
message.delta |
WORKING |
トークンを蓄積;チャンクごとにSSEに送出 |
reasoning.available |
WORKING |
推論メタデータ — トークン送出なし |
tool.call / tool.result |
WORKING |
ツール実行メタデータのみ |
approval.required |
INPUT_REQUIRED |
承認チャンクを送出;pending_approvalを保存 |
run.completed |
COMPLETED |
ストリームイベントを設定;最終テキストを蓄積 |
run.failed |
FAILED |
エラーチャンクを送出;FAILED状態を設定 |
POST /v1/runs/{id}/stop |
CANCELED |
tasks/cancel経由の外部キャンセル |
POST /v1/runs/{id}/approval |
(runを継続) | operation="approval_response"経由で解決 |
このテーブルがブリッジの核心です。すべてのフレームワーク統合は同等のテーブルを生成します — 左にフレームワークのネイティブイベント、右にA2A状態、中央にブリッジアクション。参照実装のHERMES_INTEGRATION.mdドキュメントは、Hermesイベントの正確なフォーマット、設定キー、エンドツーエンドのフロー詳細を記録しています。
A2A SDK v2の制約と二重経路の修正
A2A SDK v2(a2a-sdk==1.0.2)は、on_message_sendパスに2つの制約を課し、それがすべてのブリッジ実装の設計を形作りました:
- 単一のMessageのみ。 複数の
MessageオブジェクトをSDK EventQueueに送出するとInvalidAgentResponseError: Multiple Message objects received.が発生します。 - TaskStatusUpdateEventは不可。 ステータスイベントは
InvalidAgentResponseError: Received TaskStatusUpdateEvent in message mode.を発生させます。
素朴なブリッジはトークンデルタごとに1つのMessageを送出するでしょう — 自然なストリーミングパターンです。SDKはこれを拒否します。message/sendパス上のステータスイベント(WORKING、COMPLETED)も拒否します。
修正は二重経路の出力チャネルです:
- SSE(ゲートウェイ管理): トークンチャンクはリアルタイムでSSEにプッシュされます。接続されたクライアントはストリーミング出力をそのまま見ます。ステータスイベント(WORKING、COMPLETED、FAILED)もSSEのみに行きます。
- SDK EventQueue: ストリーム完了後、完全なレスポンステキストを含む単一の蓄積された
MessageがSDK EventQueueに送出されます。これがJSON-RPCmessage/sendレスポンスが返すものです。
クライアントはSSE経由でリアルタイムストリーミングを、SDK経由でクリーンな単一メッセージのJSON-RPCレスポンスを受け取ります。両方のチャネルが機能し、どちらもSDKの制約に違反しません。このパターンはフレームワーク非依存です — バックエンドがHermes、OpenClaw、または将来の任意のハンドラであっても適用されます。
同じパターンをOpenClawに適用する
OpenClawのGateway APIはHermesとは異なるネイティブサーフェスを公開しますが、ブリッジパターンは同一です。OpenClawHandlerは同じask_model()インターフェースを実装し、A2AタスクセマンティクスをOpenClaw Gateway呼び出しに変換します:
- 非ストリーミングは
POST /v1/responsesにマッピングされ、A2AメッセージパーツはOpenResponses入力アイテムに変換されます。レスポンスはA2AMessageに変換し戻されます。 - ストリーミングは
POST /v1/responsesにstream: trueでマッピングされ、SSEイベントストリームを消費し、トークンデルタをA2AのSSEチャネルに転送します。OpenResponsesのストリーミングフォーマットはトークンチャンクにresponse.output_text.deltaを、完了にresponse.completedを使います — イベント名は異なりますが、ブリッジ構造は同じです。 - エージェント選択は
modelフィールド(openclaw/<agentId>)またはx-openclaw-agent-idヘッダーを使い、A2Aエージェントメタデータからマッピングされます。 - セッション継続性はOpenClawの
previous_response_idまたはuserフィールドを安定したセッションルーティングのために活用し、A2Aタスク永続化に自然にマッピングされます。
OpenClawの状態マッピングテーブルは以下のようになります:
| OpenClaw Event | A2A Task State | Bridge Action |
|---|---|---|
response.created |
WORKING |
レスポンスIDを登録 |
response.output_text.delta |
WORKING |
トークンを蓄積;SSEに送出 |
response.completed |
COMPLETED |
最終テキストを蓄積;Messageを送出 |
response.failed |
FAILED |
エラーを送出;FAILEDを設定 |
同じカラム、同じ構造、異なるイベント名です。フレームワーク間で変わるのはブリッジハンドラだけです。
設定:メタデータ駆動ルーティング
エージェントルーティングはメタデータ駆動であり、環境変数駆動ではありません。データベース内の各エージェントレコードは、ハンドラ設定をmetadata JSONカラムに保持します。Hermesをバックエンドとするエージェントの場合:
{
"module_name": "a2a_daemon_engine.handlers.a2a_hermes_handler",
"class_name": "HermesAgentHandler",
"hermes_api_url": "http://127.0.0.1:8642",
"hermes_api_key": "hermes-local-key",
"hermes_model": "hermes-agent",
"hermes_timeout": 300.0
}
OpenClawをバックエンドとするエージェントの場合、メタデータはOpenClawハンドラを指します:
{
"module_name": "a2a_daemon_engine.handlers.a2a_openclaw_handler",
"class_name": "OpenClawHandler",
"openclaw_api_url": "http://127.0.0.1:3000",
"openclaw_api_key": "openclaw-key",
"openclaw_agent_id": "pricing-agent",
"openclaw_timeout": 300.0
}
設定解決は優先度チェーンに従います:エージェントメタデータ(DB)→ 設定辞書 → Configデフォルト(環境変数)。エージェントごとのオーバーライドがグローバルデフォルトに優先します。2つのエージェントを異なるフレームワークに向けることができます — 一方は推論中心のタスクにHermesへ、もう一方はワークフロー編成のタスクにOpenClawへ — そしてA2Aプロトコルサーフェスは呼び出し側エージェントにとって同一に見えます。
これがもたらすもの
ブリッジパターンは、ゼロから組み立てるのが難しい3つのケーパビリティをもたらします:
1. ストリーミングを伴うエージェント間委任。 A2AクライアントエージェントはHermesをバックエンドとするエージェントにタスクを送信し、SSE経由でリアルタイムのトークンストリーミングを受け取れます。呼び出し側エージェントはリモートエージェントがHermesで動いていることを知る必要がありません — Agent CardとJSON-RPCインターフェースを持つA2Aエンドポイントを見ます。
2. エージェント境界をまたぐヒューマンインザループ承認。 フレームワーク固有の承認ゲート(Hermesの承認リクエスト、OpenClawのオペレーター承認)はA2AのINPUT_REQUIRED状態にマッピングされます。エージェント委任チェーンに人間の承認を必要とするステップを含めることができ、A2Aプロトコルがその状態遷移を起点のエージェントまたはオペレーターに戻します — チェーン内の各エージェントがどのフレームワークで動いているかにかかわらず。
3. 単一ゲートウェイからのマルチフレームワークルーティング。 同じゲートウェイ、同じエグゼキューター、同じA2Aプロトコルサーフェスが異なるフレームワークのハンドラを提供します。新しいフレームワークの追加は1つのハンドラクラスを書き、1つのエージェントレコードを挿入することです — 新しいデプロイでも、新しいプロトコル実装でもありません。
参照実装はさらに、サーバーレスA2AのためのAWS Lambdaディスパッチ、双方向ストリーミングを伴う実験的gRPCトランスポート、複合パーティションキーによるマルチテナント分離を備えたデュアルバックエンド永続化(DynamoDBまたはPostgreSQL)をサポートしています。a2a_daemon_engineリポジトリおよびそのHermes統合ガイドに完全な実装、設定リファレンス、状態マッピングの詳細が含まれています。
中堅のディストリビューターは、カタログエージェントと話す見積もりエージェントが在庫エージェントと話す — それぞれ異なるフレームワークに裏打ちされ、それぞれ異なるチームが所有する — エージェントを必要とします。A2Aはそれらのエージェントに共有プロトコルを与えます。ブリッジ層はHermes Agent、OpenClaw、その他のフレームワークが内部を書き直すことなく参加できるようにします。a2a_daemon_engineは、Hermes Agentで実証されたそのブリッジパターンの動作する参照実装です。
スコープ済みの構築を依頼する
1週間のディスカバリー。システムインベントリ、ワークフローマップ、確定スコープを入手 — 私たちと構築するかどうかにかかわらず。
あなたのシステムのためにこれを構築したいですか?
ここの各ドキュメントは実際の本番作業から来ています。ターゲットシステムとワークフローがあれば、1週間でスコープを定義できます。
スコープ付き構築を依頼1週間のディスカバリ。システムインベントリ、ワークフローマップ、固定スコープを提供します — 私たちと構築するかどうかにかかわらず。