- カテゴリー
- A2A・エージェント認証
- 公開日
- 2026.09.10
はじめに
A2AのAgent Cardは、エージェントの名前、接続先、対応プロトコル、スキル、認証方式を伝える「機械可読の名刺」です。しかし、社内スキルや契約者限定機能まで公開カードへ書くと、利用できない相手にも内部情報を見せてしまいます。
A2A v1.0のExtended Agent Cardは、公開カードで対応を宣言し、認証・認可されたクライアントへ詳細版を返す仕組みです。
この記事は、JSONとHTTPの基本を知り、Agent Cardの公開範囲を設計したい方を対象にしています。公開用・認証後用のカードの違いと、取得・キャッシュの注意点を学びます。認可サーバーの構築やトークン取得そのものは扱いません。例中のexample.com配下のURLは説明用で、実行時には自分が管理する接続先へ置き換えます。
公開カードに載せる情報
{
"name": "Document Assistant",
"description": "公開文書を検索するエージェント",
"version": "1.0.0",
"supportedInterfaces": [{
"url": "https://agent.example.com/a2a",
"protocolBinding": "HTTP+JSON",
"protocolVersion": "1.0"
}],
"capabilities": {
"streaming": false,
"extendedAgentCard": true
},
"securitySchemes": {
"oauth": {
"oauth2SecurityScheme": {
"flows": {
"authorizationCode": {
"authorizationUrl": "https://auth.example.com/authorize",
"tokenUrl": "https://auth.example.com/token",
"scopes": { "agent.read": "エージェントを利用" }
}
}
}
}
},
"securityRequirements": [{
"schemes": { "oauth": { "list": ["agent.read"] } }
}],
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
"skills": [{
"id": "public-search",
"name": "公開文書検索",
"description": "公開済み文書を検索します",
"tags": ["search"]
}]
}
v1.0ではprotocolVersionはカード直下ではなく各AgentInterfaceにあります。旧版のsupportsAuthenticatedExtendedCardではなく、capabilities.extendedAgentCardを使います。
認証方式の定義はsecuritySchemes、利用時に要求する方式とスコープはsecurityRequirementsです。v1.0ではschemesの下に方式名を置き、必要なスコープをlist配列に入れます。旧形式のsecurity配列とは構造が異なります。
認証後カードを取得する
HTTP+JSON bindingでは、選んだinterfaceのbase URLに対して次の操作を行います。
GET /a2a/extendedAgentCard HTTP/1.1
Host: agent.example.com
Authorization: Bearer <access-token>
Accept: application/a2a+json
実際のURLはinterfaceのbase URL解決規則に従います。固定文字列を公開カードとは無関係なhostへ向けないでください。
簡略化したクライアント例です。
async function getExtendedCard(baseUrl, token) {
const url = new URL("extendedAgentCard", `${baseUrl.replace(/\/?$/, "/")}`);
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/a2a+json",
},
});
if (response.status === 401) throw new Error("認証が必要です");
if (response.status === 403) throw new Error("カードを読む権限がありません");
if (!response.ok) throw new Error(`取得失敗: HTTP ${response.status}`);
return response.json();
}
Bearer tokenはサンプルへ直書きせず、Agent Cardが宣言する方式に従いA2A外の認証フローで取得します。
Extended Cardの例
認証後のカードは公開カード全体を置き換えられる完全なAgent Cardとして返します。差分だけを返さないでください。
{
"name": "Document Assistant",
"description": "社内文書にもアクセスできるエージェント",
"version": "1.0.0",
"supportedInterfaces": [{
"url": "https://agent.example.com/a2a",
"protocolBinding": "HTTP+JSON",
"protocolVersion": "1.0"
}],
"capabilities": { "extendedAgentCard": true },
"securitySchemes": {
"oauth": {
"oauth2SecurityScheme": {
"flows": {
"authorizationCode": {
"authorizationUrl": "https://auth.example.com/authorize",
"tokenUrl": "https://auth.example.com/token",
"scopes": { "agent.read": "エージェントを利用" }
}
}
}
}
},
"securityRequirements": [{
"schemes": { "oauth": { "list": ["agent.read"] } }
}],
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
"skills": [
{ "id": "public-search", "name": "公開文書検索", "description": "公開済み文書を検索します", "tags": ["search"] },
{ "id": "internal-search", "name": "社内文書検索", "description": "許可された社内文書を検索します", "tags": ["internal"] }
]
}
権限レベルに応じて異なる完全版を返せます。ただしカードに秘密鍵、token、内部ホスト名、悪用可能なデバッグ情報を載せません。Extendedだから秘密を何でも返してよいわけではありません。
キャッシュの注意
クライアントは認証セッション中、公開カードをExtended Cardで置き換えられます。サーバーはCache-Control: private、適切なmax-age、ETagを検討します。共有キャッシュにユーザー別カードを保存させません。ログアウト時には認証後カードを破棄します。
動作確認
- 公開カードだけで認証方式と対応interfaceを判断できる
- tokenなしは401、権限不足は403
- 有効な権限で完全なExtended Cardが返る
- 他ユーザーの限定スキルが混ざらない
- 応答とログにtokenや内部秘密がない
extendedAgentCard: falseなら操作を呼ばない- カードの
version変更とキャッシュ更新を確認する
トラブル対処
- 404:選択したHTTP+JSON interfaceのbase URLとextendedAgentCard URLを確認します。
- UnsupportedOperationError:公開カードのcapabilities.extendedAgentCardがtrueか確認します。
- 別利用者の情報が出る:共有キャッシュを避け、認証主体ごとの認可を確認します。
まとめ
Extended Agent Cardは、A2Aエージェントの公開情報と認証後情報を分ける仕組みです。公開カードで能力と認証方式を宣言し、認証後は権限に合う完全なカードを返します。アクセス制御、キャッシュ分離、秘密情報の最小化までが実装範囲です。
