チュートリアル

AI Agent はどうやって別の Agent を見つけるか:Agent Registry、A2A Agent Card、JSON Capability Discovery

発見が失敗したら、先にどのホップかを問え。カタログ検索か、名刺の取得か、ドメインは握っているのに GET の経路が違うのか。

前回の Agent Card フィールド解説 は 1.0 の必須表を開いた。今日はフィールドを埋め直さない。Registry がカタログである理由 も繰り返さない。オーケストレータの次の問いは、「返品を分類できる同僚が要る」から呼び出し可能な Card まで、どう進むか。公式の答えは A2A Agent Discovery:戦略は三つ、Card は一つ。仕様はキュレーションカタログの問い合わせ API を定めない。同ページの Considerations を見よ。Google Cloud のカタログは実装の一つ。形は Registry JSON schemas と照合する。本稿はホップを辿る。横への委譲と下へのツール呼び出しの層分けは A2A vs MCP。今日は繰り返さない。

発見はプロトコルではない。見つかるのは Card

A2A が標準化するのは自己記述であり、電話帳ではない。遠隔の Agent は能力を JSON の名刺に書く。クライアントはそのカードで向き不向き、つなぎ方、送る Task を決める。方法は環境で変わる。公開網、企業カタログ、開発機への直書き。三つとも同じ Card に着ける。「発見」を別の会話プロトコルと呼ぶと、レビューは先に逸れる。プロトコルは依然 A2A。変わるのは well-known やカタログへ入る扉だ。

公式の発見ページの「Role of the Agent Card」は、まだ 0.3 の口調でトップレベル url に触れる。新しいカードは 1.0:エンドポイントは supportedInterfaces。変更点は v1.0 の変更。発見ホップが古いフィールドを読んでも、それを 1.0 の主契約にするな。フィールドの書き方は前回書いた。今日問うのは、このカードがどのホップで手元に来たか、来たあと先にどのキーを確かめるか、だけだ。

発見の成功は tools/call の許可ではない。向こうは不透明な Agent のまま。skill を選び、インタフェースを選び、送るのは Task。検索の命中を関数表だと思うと、複数回の確認で arguments が壊れる。MCP のホップで引数をどう確かめるかは、サイト内の Schema 稿。今日は「誰を見つけたか、なぜその仕事を任せられると判断したか」で止まる。

戦略 すでに知っていること 次のホップ
Well-known URIドメインまたはホストGET /.well-known/agent-card.json
キュレーションカタログスキルのキーワード / タグカタログを問い合わせ、Card か参照を取る
直接設定URL かカード一式検索を飛ばし、カードを読む

公式の三戦略:道を選んでから歩く

Well-known は公開 Agent、あるいはホスト名を支配できる発見に向く。経路は RFC 8615:https://{agent-server-domain}/.well-known/agent-card.json。クライアントはドメインを知っているか、導き出せる。HTTP GET を出し、JSON を受ける。実装は単純で、自動化しやすい。名刺に機微なスキルや社内 URL があるなら、その GET 自体に認証が要る。社内エンドポイントを公開網に裸で掲げてはいけない。

キュレーションカタログは企業や市場向き。中間サービスが Card を集め、クライアントは skills、tags、provider、capabilities で問い合わせ、カタログは一致するカードか参照を返す。得られるのは統治と、能力での検索。代価はカタログを養うこと。A2A はカタログ API を定めない。Google Agent Registry、コミュニティの registry、自前のカタログは、問い合わせの形を各自が書く。「汎用 discover JSON」一枚で三社を検証するな。

直接設定は密結合、私有 Agent、開発機向き。カード URL は環境変数、設定ファイル、独自 API に置く。関係が静的なら一番安い。Card が動けば、クライアントも追随しなければならない。本番で「開発機への直書き」を唯一の発見面にするのは、2025 年の住所録だ。三路は共存できる。カタログは誰かを探し、well-known はカタログが落ちても名刺を読み、設定は起動時の種ホストを持つ。

ホスト名がある:GET well-known

いちばんきれいなホップは三手。(1) ドメインを得る。例は returns.agents.example.com。(2) GET https://returns.agents.example.com/.well-known/agent-card.json。(3) 応答は 1.0 Schema を通る Card。経路を誤り、HTTP を内部エイリアスに替え、証明書のホスト名が合わないと、障害票は「発見失敗」と書く。Card は健全でも、GET が届いていない。

仕様は Card のエンドポイントにキャッシュヘッダを勧める。Cache-Control: max-age=… で中間層とクライアントは全文を毎回取らない。ETag は version でも内容ハッシュでもよい。期限後は条件付き要求(If-None-Match)。無条件の全文取得を毎回するな。サーバがヘッダを出さなくても、クライアントは短い既定を置いてよい。skills が変わりうるカードを永久にキャッシュしてはいけない。

公開カードはオーケストレータが選べる分量で足りる。機微なスキルと社内の第二エンドポイントは、認証後の拡張カードへ。capabilities.extendedAgentCard が真のときだけ、二枚目を取る。発見ホップは未認証の段階で拡張カードがあると仮定するな。カタログが身元に応じて別の Card を返すことと、well-known の一枚が全員に同じであることとは、開示の型が違う。レビューでは文を分けて書け。

カタログがある:tags を探し、Card を取る

ホスト名がなく、「返品を分類できる同僚を探せ」という一文だけのときは、キュレーションカタログを歩く。問い合わせが食べるのは Card 上の skills[].tags とスキル名であり、スライドのトポロジではない。Google プロジェクト内のオーケストレータ、Gemini Enterprise、Agent Gateway はスキルのキーワードで登録項を探す。それは製品の振る舞いであり、A2A の標準 RPC ではない。コミュニティや他クラウドは各自の search を持つ。検査データが断言すべきは「問い合わせ → 命中一覧 → 各行に cardUrl か埋め込み Card」。一社の経路を仕様にするな。

カタログが参照を返すなら、次のホップは依然 well-known、またはカタログが出した Card URL。埋め込み Card を返すなら、それでも 1.0 Schema で確かめる。登録の成功はフィールドの適法ではない。ホストだけで skills のない NO_SPEC 項目は、検索面が空だ——#5 で書いた。今日の注意は一つ。空の索引へキーワードホップを打っても、プロトコルは壊れていない。

カタログが落ちても、発見が自動で終わらない。ホスト名をすでに握っているなら、クライアントは well-known を GET すべきだ。カタログを唯一の真実にすると、発見面が単一点になる。種設定に安定ホストを一つか二つ残し、カタログが戻ってからキーワード検索を再開する。「カタログ 500 で止まる」より、仕様の三路共存に近い。

命中のあと:skills を合わせ、インタフェースを選び、Task を送る

検索の命中は「彼かもしれない」だけを意味する。オーケストレータはなお skills[] を見る。id は委譲したい仕事か、tags は問い合わせ語に本当に当たるか、description の境界は受け入れるか。MCP の inputSchema で skill を包むな。1.0 の手がかりは examples と MIME。skill を誤って Task を送れば、失敗は委譲であり発見ではない。ただし検査データは「命中 ≠ 選定」を二段で書け。

選定のあと supportedInterfaces を読む。先頭が優先。クライアントは話せるバインディングを選ぶ。JSONRPC、GRPC、HTTP+JSON。共通のバインディングがなければ、発見は成功し通話は失敗する。0.3 のトップレベル url を 1.0 の主エンドポイントにするな。能力フラグも見る。streaming が偽なのにストリームを購読すれば、仕様は能力エラーを求める。黙って unary へ落とすな。

下は走査用のデータであり、どのカタログの公式 API でもない。問い合わせ、命中、優先インタフェースを一つの JSON に畳む。倉庫の Card と並べて diff しやすい。次の動詞は message/send。検証の点検表と署名は、後の稿へ残す。

{
  "kind": "discovery-trace",
  "note": "CI/review fixture — not an official A2A or Google Registry API",
  "query": {
    "tags": ["returns", "classify"]
  },
  "strategy": "curated-registry",
  "hits": [
    {
      "name": "Returns Specialist",
      "cardUrl": "https://returns.agents.example.com/.well-known/agent-card.json",
      "matchedTags": ["returns", "classify"],
      "skillId": "classify-return"
    }
  ],
  "selected": {
    "skillId": "classify-return",
    "preferredInterface": {
      "url": "https://agents.example.com/returns/a2a",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    },
    "next": "message/send"
  }
}
このホップ 入力 断言すべきこと
カタログを探すtags またはスキル名命中一覧が空でなく、参照を持つ
well-known を取るホスト名または cardUrlJSON が parse でき、1.0 Schema を通る
選定 / インタフェースを選ぶ完全な 1.0 Cardskill id が合い、クライアントがそのインタフェースを話せる

キャッシュ、古い索引、検査用データ

Card は頻繁には動かない。スキルを足す、認証を変える、そのとき動く。発見面はそれでも古くなる。カタログの索引が遅れ、well-known は新しい version を出し、検索は古い tags を指す。検査データは少なくとも二組。カタログ命中のスナップショットと、いま GET した Card。キーワードが外れたら、先に tags と索引の遅れを見る。1.0 クライアントが 0.3 のカードを読んだ疑いはその次だ。

{
  "hop": "well-known",
  "method": "GET",
  "url": "https://returns.agents.example.com/.well-known/agent-card.json",
  "requestHeaders": {
    "If-None-Match": "1.0.3"
  },
  "response": {
    "status": 304,
    "etag": "1.0.3",
    "cacheControl": "max-age=3600"
  }
}

仕様ははっきり書く。機微なデータには認証が要る。帯域外の動的な資格情報を勧め、静的な秘密を Card に書くな。発見用データに token や社内パスワードがあれば、レビューはその場で戻す。公開カードは取られる前提で書け。拡張カードのキャッシュはセッションに従う。公開カードの max-age と同じ桶に流し込むな。

Plugin の SKILL.md や MCP の tools/list を発見源にするな。同じ倉庫の Coding Agent がスキルを伸ばすのは箱の話。別チームの返品 Agent が見つかるのは Card の話。一つの capability.json に押し込めば、三つの失敗したホップが同じ票の一行に落ちる。

ブラウザで足りる:JSON 整形で走査データと Card が parse できるか見る。JSON Schema 検証で命中後の 1.0 Card を確かめる。JSON Diffでカタログのスナップショットと今取った Card を比べ、tags / インタフェースのずれを拾う。データは手元を出ない。続きは Agent Card フィールド解説、Registry の概観。署名と検証の点検表は次の実戦稿。

関連:A2A Agent Card JSON Schema、Google Agent Registry、A2A vs MCP。

よくある質問

カタログがあれば、well-known は GET しなくてよいか

否。カタログは Card を消費する。Card を置き換えない。仕様は公開発見の標準経路として well-known を書く。カタログが落ちても、ホスト名を握るクライアントは名刺を読むべきだ。

A2A に「Agent を探す」標準 RPC はあるか

ない。発見ページは明示する。現行仕様はキュレーションカタログの API を定めない。問い合わせは各カタログが自分で定義する。標準なのは Card の形と well-known の経路だ。

見つけたら tools/call してよいか

いけない。命中は発見の結果。向こうは不透明な Agent。送るのは Task。確定的な引数は MCP ツールに残す。発見ホップに書くな。

キャッシュはどれくらいが妥当か

先にサーバの Cache-Control と ETag に従う。ヘッダがなければ短い既定と、期限後の条件付き要求。スキルや認証が変われば version も動く。クライアントは古い tags で本番を回してはいけない。

まとめと次の一手

2026 年の「別の Agent を自動で見つける」は三ホップに畳める。戦略を選び、Card を得て、skills とインタフェースで委譲するかを決める。カタログはその扉の一つであり、プロトコルそのものではない。

出荷の順。公開 Agent は先に well-known を正しく掲げる。キーワードで探すなら、一社のカタログを繋ぎ、問い合わせ用データを自前で持つ。命中したら 1.0 Card を確かめてから Task を送る。フィールドの書き方は前回。カタログが何かは #5。検証と署名は後の稿。走査 JSON と倉庫の Card は JSONVue で対照せよ。