Agent2Agent 入門 (8) - 拡張機能
「Agent2Agent」の「エクステンション」についてまとめました。
前回
1. はじめに
「A2A」は、エージェント間の通信を可能にする堅固な基盤です。しかしながら、一部ドメインでは、プロトコルの汎用メソッドが提供する以上の構造が必要となることは明らかです。こうしたケースをサポートするために、プロトコルに「拡張機能」が追加されています。「拡張機能」を使用することで、エージェントとクライアントは、コアプロトコルの上に重ねる追加のカスタムロジックをネゴシエートできます。
2. 拡張機能の適用範囲
「拡張機能」の具体的な使用方法は、意図的に定義されていません。これは、「拡張機能」を使用することで、現在知られているユースケース以外にも「A2A」を拡張できるようにするためです。ただし、以下のようなユースケースは明確に予測可能です。
・「AgentCard」に新しい情報を公開
「拡張機能」はリクエスト/レスポンスフローに全く影響を与えない場合もあります。「AgentCard」を介してクライアントに追加の構造化情報を伝達する手段としてのみ使用できます。これをデータのみの拡張機能と呼びます。例えば、拡張機能によって、エージェントの GDPR コンプライアンスに関する構造化データを「AgentCard」に追加できます。
・コアのリクエスト/レスポンスメッセージに追加の構造および状態変更要件をオーバーレイ
例えば、「拡張機能」によって、すべてのメッセージで特定のスキーマに準拠した DataPart を使用することを要求できます。この種の拡張機能は、実質的にコア A2A プロトコルのプロファイルとして機能し、許容される値の空間を絞り込みます。これをプロファイル拡張機能と呼びます。例えば、ヘルスケア分野の拡張機能では、患者情報を含むすべての「Message Part」を暗号化し、FHIR 標準に準拠した DataPart に配置することを義務付けることができます。
・新しい RPC メソッドを完全に追加
「拡張機能」によって、エージェントがコアプロトコルメソッドセット以上のものを実装することが定義される場合があります。これをメソッド拡張機能と呼びます。たとえば、「task-history」拡張機能では、以前のタスクのリストを取得するための tasks/search RPC メソッドが追加されることがあります。
「拡張機能」では許可されないプロトコルの変更がいくつかあります。以下がその例です。
・コアデータ構造の定義の変更。プロトコル定義のデータ構造への新しいフィールドの追加や必須フィールドの削除はサポートされていません。拡張機能は、コアデータ構造に存在するメタデータマップにカスタム属性を配置することが期待されています。
・列挙型への新しい値の追加。代わりに、拡張機能は既存の列挙値を使用し、メタデータフィールドに追加の意味を注釈付けする必要があります。
これらの制限は、「拡張機能」によってクライアントとエージェントが実行するコアタイプ検証が壊れるのを防ぐために存在します。
3. 拡張機能の宣言
3-1. 拡張機能の宣言
エージェントは、AgentCapabilities オブジェクトに AgentExtension オブジェクトを含めることで、AgentCard 内で拡張機能のサポートを宣言します。
・uri (string)
拡張機能のURI。これは拡張機能仕様で定義された任意の識別子です。拡張機能の実装では、このURIを使用してアクティベートするタイミングを識別し、クライアントは拡張機能の互換性を判断するためにこのURIを使用します。
・required (boolean)
エージェントがクライアントにこの拡張機能の使用を要求するかどうか。
・description (string)
エージェントが宣言された拡張機能をどのように使用するかを説明します。拡張機能の詳細は拡張機能仕様に記載されます。このフィールドは、エージェントと拡張機能の関係を説明するのに役立ちます。
・params (object)
拡張機能固有の設定。このフィールドに入力する値は、拡張機能仕様によって定義されます。このフィールドは、拡張機能のパラメータを指定したり、エージェント固有の追加データを宣言したりするために使用できます。
・拡張機能を表示する AgentCard の例
{
"name": "Magic 8-ball",
"description": "An agent that can tell your future... maybe.",
"version": "0.1.0",
"url": "https://example.com/agents/eightball",
"capabilities": {
"streaming": true,
"extensions": [
{
"uri": "https://example.com/ext/konami-code/v1",
"description": "Provide cheat codes to unlock new fortunes",
"required": false,
"params": {
"hints": [
"When your sims need extra cash fast",
"You might deny it, but we've seen the evidence of those cows."
]
}
}
]
},
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
"skills": [
{
"id": "fortune",
"name": "Fortune teller",
"description": "Seek advice from the mystical magic 8-ball",
"tags": ["mystical", "untrustworthy"]
}
]
}3-2. 必須拡張機能
「拡張機能」は追加機能を実現する手段ですが、一部のエージェントはコアA2Aプロトコルで表現可能な要件よりも厳しい要件を持つことが予想されます。例えば、エージェントはすべての受信メッセージに作成者による暗号署名を要求する場合があります。必須と宣言された拡張機能は、このようなユースケースをサポートすることを目的としています。
「AgentCard」が必須拡張機能を宣言した場合、これはクライアントに対して、拡張機能の一部がリクエストの構造化に影響を与えることを通知するものです。エージェントへのリクエストの送信方法に直接影響を与えないため、エージェントはデータのみの拡張機能を必須としてマークすべきではありません。
「AgentCard」が必須拡張機能を宣言し、クライアントがその必須拡張機能の有効化を要求しない場合、エージェントは受信リクエストを拒否し、適切なエラーコードを返す必要があります。
クライアントが拡張機能の有効化を要求したが、拡張機能で定義されたプロトコルに従っていない場合、エージェントはリクエストを拒否し、適切な検証失敗メッセージを返す必要があります。
4. 拡張機能仕様
4-1. 拡張機能仕様
拡張機能の詳細は仕様によって定義されます。このドキュメントの正確な形式は規定されていませんが、少なくとも以下の内容が含まれている必要があります。
・拡張機能の実装が識別および応答する特定のURI。仕様書のバージョン管理や場所の変更に対応するため、複数のURIが同じ拡張機能を識別する場合があります。拡張機能の作成者は、URLの過密化を避けるため、w3idなどの永続的な識別子サービスを使用することが推奨されます。
・「AgentCard」で公開されるAgentExtensionオブジェクトのparamsフィールドに指定されるオブジェクトのスキーマと意味。
・クライアントとエージェント間で通信される追加のデータ構造のスキーマ。
・拡張機能の実装に必要なリクエスト/レスポンスフロー、追加のエンドポイント、その他のロジックの詳細。
4-2. 拡張機能の依存関係
拡張機能は他の拡張機能に依存する場合があります。この依存関係は、拡張機能のコア機能が依存する拡張機能がないと実行できない場合は必須、別の拡張機能が存在すると追加機能が有効になる場合はオプションとなります。拡張機能の仕様では、依存関係とその種類を文書化する必要があります。
依存関係は、AgentExtension オブジェクト内ではなく、拡張機能の仕様内で宣言されます。拡張機能の仕様に記載されているすべての必要な依存関係と拡張機能を有効化するのは、クライアントの責任です。
5. 拡張機能のアクティベーション
拡張機能はデフォルトで非アクティブにする必要があります。これにより、「デフォルトがベースライン」のエクスペリエンスが提供され、拡張機能を認識しないクライアントは、拡張機能によって提供される詳細情報やデータに煩わされることはありません。代わりに、クライアントとエージェントは、リクエストに対してどの拡張機能がアクティブであるかを決定するためのネゴシエーションを実行します。このネゴシエーションは、クライアントがエージェントへのHTTPリクエストにX-A2A-Extensionsヘッダーを含めることで開始されます。このヘッダーの値は、クライアントがアクティベートしようとしている拡張機能URIのリストである必要があります。
クライアントは任意の拡張機能のアクティベーションを要求できます。エージェントは、リクエスト内でサポートされている拡張機能を識別し、アクティベーションを実行する責任があります。エージェントがサポートしていない拡張機能が要求された場合は無視できます。
すべての拡張機能がアクティベートできるわけではありません。データのみの拡張機能は、AgentCardを介して追加情報を提供するためだけに存在します。クライアントはこれらの拡張機能のアクティベーションを要求できます。拡張機能はアクティベーション時に追加のロジックを実行しないため、リクエストには影響しません。
一部の拡張機能には、アクティベーションに追加の前提条件がある場合があります。例えば、機密性の高い拡張機能の中には、その拡張機能を有効化できるユーザーを規定するアクセス制御リストが存在する場合があります。要求された拡張機能のうち、どの拡張機能を有効化するかはエージェントが決定します。
クライアントが依存関係のある拡張機能の有効化を要求した場合、そのクライアントは依存関係のある拡張機能の有効化も要求し、その要件を遵守する必要があります。クライアントが要求された拡張機能に必要な依存関係をすべて要求していない場合、サーバーは適切なエラーを返してリクエストを失敗させる可能性があります。
エージェントが有効化されたすべての拡張機能を特定したら、レスポンスには有効化されたすべての拡張機能を識別する X-A2A-Extensions ヘッダーを含める必要があります。
・拡張機能の有効化を示すリクエストの例
POST /agents/eightball HTTP/1.1
Host: example.com
Content-Type: application/json
X-A2A-Extensions: https://example.com/ext/konami-code/v1
Content-Length: 519
{
"jsonrpc": "2.0",
"method": "message/send",
"id": "1",
"params": {
"message": {
"kind": "message",
"messageId": "1",
"role": "user",
"parts": [{"kind": "text", "text": "Oh magic 8-ball, will it rain today?"}]
},
"metadata": {
"https://example.com/ext/konami-code/v1/code": "motherlode",
}
}
}・アクティブ化された拡張機能を反映する対応する応答
HTTP/1.1 200 OK
Content-Type: application/json
X-A2A-Extensions: https://example.com/ext/konami-code/v1
Content-Length: 338
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"kind": "message",
"messageId": "2",
"role": "agent",
"parts": [{"kind": "text", "text": "That's a bingo!"}],
}
}6. 実装に関する考慮事項
A2A プロトコルは拡張機能の「内容」を定義しますが、このセクションでは拡張機能の実装の作成、バージョン管理、配布に関するベストプラクティスである「方法」に関するガイダンスを提供します。
6-1. バージョン管理
拡張機能の仕様は必然的に進化します。クライアントとエージェントが互換性のある実装をネゴシエートできるようにするために、明確なバージョン管理戦略を策定することが重要です。
・推奨事項
拡張機能のURIを主要なバージョン識別子として使用してください。https://example.com/ext/my-extension/v1 や https://example.com/ext/my-extension/v2 のように、URIパスにバージョン番号を直接含めることをお勧めします。
・互換性のない変更
拡張機能のロジック、データ構造、または必須パラメータに互換性のない変更を加える場合は、新しいURIを使用する必要があります。これにより、曖昧さが回避され、/v1をサポートするエージェントが/v2リクエストを誤って処理することがなくなります。
・不一致の処理
クライアントがエージェントがサポートしていない拡張機能のバージョンを要求した場合(例: クライアントが/v2を要求したが、エージェントが/v1のみをサポートしている場合)、エージェントはその拡張機能のアクティベーション要求を無視する必要があります(SHOULD)。クライアントのロジックは要求されたバージョンに明示的に結び付けられているため、エージェントは別のバージョンへの「フォールバック」を試みてはいけません(MUST NOT)。
6-2. 発見可能性と公開
拡張機能が有用であるためには、他の開発者がその仕様を見つけ、使い方を理解できる必要があります。
・仕様のホスティング
拡張機能の仕様書は、拡張機能のURIでホスティングされるべきです。これにより、開発者は識別子を解決するだけで簡単にドキュメントにアクセスできます。
・永続的な識別子
リンク切れやドメイン変更による問題を防ぐため、開発者は拡張機能のURIにw3id.orgなどの永続的な識別子サービスを使用することが推奨されます。
・コミュニティレジストリ (将来)
将来、A2Aコミュニティは利用可能な拡張機能を発見および閲覧するための中央レジストリを設立する可能性があります。
6-3. パッケージングと再利用性
導入を促進するために、拡張機能のロジックは、既存の A2A クライアントおよびサーバーアプリケーションに簡単に統合できる再利用可能なライブラリにパッケージ化する必要があります。
・配布
拡張機能の実装は、その言語エコシステムの標準パッケージとして配布する必要があります(例:Python の場合は PyPI パッケージ、TypeScript/JavaScript の場合は npm パッケージ)。
・統合の簡素化
開発者にとってほぼ「プラグアンドプレイ」のエクスペリエンスを提供することを目指します。適切に設計された拡張機能パッケージは、開発者が最小限のコードでサーバーに追加できるものでなければなりません。例えば、次のようなものです。
# Hypothetical Python Server Integration
from konami_code_extension import CheatCodeHandler
from a2a.server import A2AServer, DefaultRequestHandler
# The extension hooks into the request handler to process its logic
extension = CheatCodeHandler(description="")
extension.add_cheat(
code="motherlode",
hint="When your sims need extra cash fast",
)
extension.add_cheat(
code="thereisnocowlevel",
hint="You might deny it, but we've seen the evidence of those cows.",
)
request_handler = DefaultRequestHandler(
agent_executor=MyAgentExecutor(extension),
task_store=InMemoryTaskStore(),
extensions=[extension]
)
server = A2AServer(agent_card, request_handler)
server.run()6-4. セキュリティ
拡張機能はA2Aプロトコルのコア動作を変更するため、新たなセキュリティ上の考慮事項が生じます。
・入力検証
拡張機能によって導入される新しいデータフィールド、パラメータ、またはメソッドは、実装によって厳密に検証されなければなりません(MUST)。プロトコルで定義された信頼を確立する手段がない限り、外部からの拡張機能関連データはすべて、信頼できない入力として扱ってください。
・必須拡張機能の適用範囲
AgentCardで拡張機能を「必須: true」とマークする際には注意が必要です。これは、すべてのクライアントに強い依存関係を作成します。この設定は、エージェントのコア機能とセキュリティ体制に不可欠な拡張機能 (例 : メッセージ署名拡張機能) にのみ使用してください。
・認証と認可
拡張機能によって新しいメソッドが追加された場合、実装はこれらのメソッドがコアA2Aメソッドと同じ認証および認可チェックの対象となることを保証しなければなりません (MUST)。拡張機能は、エージェントの主要なセキュリティ制御をバイパスする方法を提供してはなりません(MUST NOT)。
