🐈

A2A のエージェントは「人や1件のレコード」ではなく、能力を提供する窓口

に公開

背景

A2A を学び始めると、かなり早い段階で次の疑問に行き当たります。

1 つのエージェントが 1 つの URL やポートしか持っていないのに、どうして多数の対象を扱えるのか。
購入者ごと、出品者ごと、商品ごとに別のエージェントを立てなくてよいのか。

エージェント という言葉には、どうしても「誰かの代理」や「何かの専属窓口」という響きがあります。そのため、購入者 100 人がいれば購入者エージェントも 100 個、出品者 50 人がいれば出品者エージェントも 50 個、という対応を思い描きやすい。

しかし、A2A の仕様や実装の実態は、ふつうそうなっていません。A2A のエージェントは、個々の人やレコードの分身というより、ある能力や責務を持ったサービスの窓口 と捉えたほうが実態に近いです。

この記事では、この点を A2A の仕様に沿って整理します。主な例としては EC マーケットプレイス を使います。購入者と出品者という 2 種類のエンティティがそれぞれ多数存在し、しかも組み合わせが増えるため、エージェントの粒度を考える題材として分かりやすいからです。そのあとで、補助として 図書館の司書 の比喩と、マイクロサービスとのアナロジー も使います。

この記事の位置付け

この記事で整理したいのは、主に次の 4 点です。

  1. Agent Card は何を表しているのか
  2. エージェントはエンティティそのものではない、というのはどういう意味か
  3. 1 つのエージェントが多数の対象を扱えるのはなぜか
  4. N × M の組み合わせを、少数のエージェントでどう扱うのか

この記事では、A2A 仕様が直接定めている内容と、そこから自然に導かれる実装上の考え方を混同しないようにします。仕様に書かれていることはそのまま述べ、実装上そのように設計するのが自然だという話は、推論として区別して書きます。


1. ありがちな誤解

ここからしばらくは、例として EC マーケットプレイス を使います。購入者と出品者がそれぞれ多数存在し、しかも両者の組み合わせが増えるため、エージェントの粒度を考える題材として分かりやすいからです。

最初に出てくる誤解は、だいたい次の形です。

  • 購入者 A さんには A さん専用のエージェントがいる
  • 購入者 B さんには B さん専用のエージェントがいる
  • 出品者 X 商店には X 商店専用のエージェントがいる
  • 出品者 Y 商店には Y 商店専用のエージェントがいる

図にすると、こういうイメージです。

ふだん使う言葉としての「エージェント」に引きずられると、この発想はとても自然です。

しかし、A2A におけるエージェントは通常この粒度ではありません。現実の実装では、たとえば

  • 購入者側の処理を扱うエージェントが 1 つ
  • 出品者側の処理を扱うエージェントが 1 つ

という形で動いていて、その 2 つが多数の取引案件を処理する、という構造のほうが一般的です。

つまり、疑問は次のように言い換えられます。

なぜ 1 つのエージェントで、何百人もの購入者や出品者に関わる処理を扱えるのか。

これがこの記事の中心テーマです。


2. Agent Card とは何か

まず、用語の意味をはっきりさせます。

A2A 仕様における Agent Card は、エージェントの自己記述メタデータです。仕様上、Agent Card は JSON 文書として公開され、そのエージェントの

  • identity
  • capabilities
  • skills
  • supported interfaces
  • authentication requirements

などを示します。

ローカル開発では、たとえば購入者エージェントを http://localhost:8001、出品者エージェントを http://localhost:8002 で動かす、と考えると分かりやすいです。

well-known URI で Agent Card を公開するなら、それぞれ次の位置に Agent Card がある、という想定になります。

  • http://localhost:8001/.well-known/agent-card.json
  • http://localhost:8002/.well-known/agent-card.json

この意味で、ローカル開発ではポートでエージェントを区別して考えてもかまいません。ただし、A2A として重要なのはポート番号そのものではありません。重要なのは、どの URL でどの Agent Card を公開しているか、そして その URL にどう到達するか です。Discovery の方法はいくつかありますが、well-known URI を使う場合の推奨位置として /.well-known/agent-card.json が定義されています。

ここで重要なのは、Agent Card が「そのエージェントは何ができるか」と「そのエージェントにどう接続するか」を表している、ということです。

EC マーケットプレイスの例なら、購入者エージェントについて Agent Card から読み取りたいのは、たとえば次の 2 種類の情報です。

  • 何ができるか
    • 購入者情報を参照できる
    • 購入意向や条件を扱える
    • 交渉タスクを進められる
  • どう接続するか
    • どの URL で公開されているか
    • どのインターフェースや認証方式を使うか

出品者エージェントについても同様です。

  • 何ができるか
    • 商品情報を参照できる
    • 出品条件を扱える
    • 交渉タスクを進められる
  • どう接続するか
    • どの URL で公開されているか
    • どのインターフェースや認証方式を使うか

反対に、Agent Card が直接表しているわけではないものもあります。

  • 購入者 A さんそのもの
  • 出品者 B 商店そのもの
  • 商品 X そのもの

これらは、アプリケーションの中で管理される購入者情報、出品者情報、商品情報です。Agent Card が直接表している対象ではありません。

型とインスタンスの関係をどう考えるか

実装の感触を具体化するために、a2a-python SDK の例で考えます。a2a-python では、Agent Card は Python の型として表現され、起動時にそのインスタンスを生成して公開します。

from a2a.types import AgentCard, AgentSkill, AgentCapabilities

agent_card = AgentCard(
    name="buyer-agent",
    description="Handles buyer profile and negotiation intents",
    url="http://localhost:8001",
    version="0.1.0",
    skills=[
        AgentSkill(
            id="profile.get_summary",
            name="Get buyer summary",
            description="Returns summary information for a buyer",
        )
    ],
    capabilities=AgentCapabilities(streaming=True),
)

この見え方に沿うと、「Agent Card には型があり、起動時にそのインスタンスを作って公開する」と理解するのは自然です。

ただし、その次にもう一段区別が必要です。

a2a-pythonAgentCard は、あくまで Agent Card という文書を表す型 です。
その型から生成した agent_card = AgentCard(...) は、起動中のサービスが自分を説明するための 1 枚の文書 です。

一方で、

  • 購入者
  • 出品者
  • 商品
  • 取引レコード

は、アプリケーションの中で管理されるデータです。

つまり、関係はこうです。

  1. AgentCard という型がある
  2. その型から、サービスの自己記述として Agent Card を 1 枚生成する
  3. そのサービスは、多数の購入者、出品者、商品、取引に関するデータを扱う

ここで重要なのは、Agent Card のインスタンスは「サービスの自己紹介」であって、「購入者 1 人の分身」ではない という点です。


3. 「エージェント = データの分身」ではない

ここからが本題です。A2A のエージェントは、通常は エンティティの分身 ではありません。

購入者が 1,000 人いても、購入者エージェントが 1,000 個あるとは限りません。出品者が 200 人いても、出品者エージェントが 200 個あるとは限りません。

実際の構造は、むしろこう理解したほうが近いです。

ここでの意図は、購入者エージェントが何でも抱える、ということではありません。購入者エージェントが主に扱うのは、購入者自身の属性や希望条件です。商品データや出品条件は、ふつうは出品者エージェント側が扱います。

このときエージェントは、

  • 「購入者 A さんそのもの」
  • 「出品者 B 商店そのもの」

ではなく、

  • 「購入者に関する情報や希望条件を扱うサービス」
  • 「出品者情報、商品情報、交渉の進行を扱うサービス」

です。

この違いが見えてくると、A2A の設計はかなりすっきりします。購入者や商品の件数が増えても、サービスの個数は役割の数に引っ張られるだけで、データ件数には直接連動しません。

この点は、a2a-python SDK のスキル定義の見え方でも確認できます。たとえば購入者エージェント側に、次のようなスキルがあるとします。

from a2a.types import AgentSkill

buyer_summary_skill = AgentSkill(
    id="profile.get_summary",
    name="Get buyer summary",
    description="Returns summary information for a buyer",
)

ここで定義されているのは、「購入者 1 人に専属のスキル」ではありません。定義されているのは、購入者情報を取得する能力 です。

どの購入者を対象にするかは、スキル定義そのものではなく、呼び出し時に渡す入力で決まります。たとえば、購入者エージェントに「buyer-123 の概要と希望条件を返してください」と依頼するなら、概念的には次のような入力を渡すことになります。

{
  "buyer_id": "buyer-123",
  "fields": ["summary", "preferences"]
}

この JSON は、呼び出し時に渡す入力の例です。buyer_id で対象の購入者を指定し、fields でどの情報がほしいかを指定しています。

つまり、SDK の見え方でも、

  • スキルは能力として定義される
  • 対象の違いは呼び出し時のパラメータで与える
  • エージェントはその能力をまとめて提供する

という構造になっています。ここでもやはり、エージェントは「特定の購入者の分身」ではなく、「購入者に関する情報を扱う窓口」として理解するほうが自然です。


4. 図書館の司書という比喩

この点を理解するときは、エージェントを「個人の分身」ではなく「窓口」として考えると整理しやすくなります。

図書館を思い浮かべてください。蔵書が 1 万冊あったとして、本 1 冊ごとに専属の司書が立っているわけではありません。司書は数人でも、多数の蔵書を扱えます。

図書館 A2A エージェント
蔵書 1 万冊 購入者 1000 人、商品 M 件
司書 購入者エージェント / 出品者エージェント
利用者が本を指定して依頼する 呼び出し側が ID を指定して依頼する
司書が書架から対象を取り出す エージェントがストアから対象を取り出す

司書の役割は「特定の本の分身」ではなく、「本を扱える窓口」です。A2A のエージェントも同じで、特定の購入者や出品者の分身ではなく、対象を扱う能力を持った窓口として考えると無理がありません。


5. 全体像の例 — EC マーケットプレイス

ここで、EC マーケットプレイスの全体像を具体化します。

登場するのは次の 2 種類です。

  • 購入者: 多数いる。条件をもとに商品を探し、交渉する
  • 出品者: 多数いる。商品を出品し、条件に応じて応答する

これに対応して、A2A のサービスとしては次の 2 エージェントを置きます。

  • 購入者エージェント
  • 出品者エージェント

このとき、

  • 購入者 100 人だから購入者エージェントが 100 個
  • 出品者 50 人だから出品者エージェントが 50 個

とはなりません。

増えるのは、あくまで

  • 購入者データ
  • 出品者データ
  • 商品や交渉案件
  • 進行中のタスク

です。サービス本体は役割単位のままです。


6. なぜ 2 エージェントで足りるのか

ここで重要になるのは、A2A が タスクとメッセージを中心にしたプロトコル だという点です。

A2A 仕様では、Task は stateful な work unit として定義され、ID と lifecycle を持ちます。Message はそのタスクを進めるための入力や応答の基本単位です。単純なやり取りならメッセージで完結し、継続が必要ならタスクが作られます。

このモデルに乗せると、エージェントが毎回受け取るのは

  • 購入者 ID
  • 商品 ID
  • 出品者 ID
  • 現在のタスク ID
  • 必要な追加情報

のような 対象識別子つきのメッセージ です。

したがって、エージェントは「この購入者専用のサービス」である必要がありません。1 つのエージェントが、到着したメッセージごとに対象を識別して処理すれば足ります。

購入者 A さんの案件も、購入者 B さんの案件も、同じ購入者エージェントが扱えます。出品者 X 商店の案件も、出品者 Y 商店の案件も、同じ出品者エージェントが扱えます。


7. N × M の組み合わせが少数のエージェントで処理できる理由

この話がいちばん効いてくるのは、組み合わせが増える場面です。

たとえば、

  • 購入者 500 人
  • 出品者 80 人
  • 進行中の取引案件 3,000 件

のような状況を考えます。

一見すると、購入者と出品者の組み合わせごとに独立したエージェントが必要に見えるかもしれません。しかし実際には、そうはなりません。

理由は 3 つあります。

7.1 エンティティの識別情報はメッセージに入る

対象はエージェントの数で区別するのではなく、メッセージのペイロードやタスク継続情報に入れる識別子で区別します。

たとえば購入者エージェントや出品者エージェントに届くメッセージには、

  • buyer_id
  • item_id
  • context_id

などが含まれます。

これにより、エージェントは「誰のどの取引案件か」をメッセージごとに判定できます。

7.2 状態はタスクと外部ストアに置ける

A2A のタスク自体が lifecycle を持ちますが、実際の業務状態はアプリケーション側のストアにも置かれます。たとえば、

  • 現在の提示価格
  • どちらの応答待ちか
  • 担当する出品者
  • 過去の交渉履歴

といった情報は、タスク ID や取引 ID をキーにして外部ストアに保存できます。

つまり、組み合わせの数だけ増えるのは 状態データ であって、エージェントのプロセス数ではありません。

7.3 エージェントは処理装置として並行に動く

1 つのエージェントは、同時に多数のタスクを処理できます。これは Web API サーバが多数のリクエストを扱えるのと同じです。

そのため、

  • 購入者 A の取引 1
  • 購入者 B の取引 2
  • 購入者 C の取引 3

が同時に進んでいても、サービスとしては 1 つの購入者エージェントで扱えます。

7.4 まとめ

組み合わせの数とサービスの数は、別のものです。

  • 組み合わせの数 = データとタスクの数
  • サービスの数 = 役割や責務の数

この分離があるから、N × M の案件があっても、エージェントを同じ比率で増やす必要はありません。


8. 「1 エンティティ 1 エージェント」設計はあり得るか

理論上は可能です。

たとえば、

  • 購入者 A 専用エージェント
  • 購入者 B 専用エージェント
  • 出品者 X 商店専用エージェント
  • 出品者 Y 商店専用エージェント

のように立てることはできます。

ただし、それは A2A の標準的な理解というより、かなり特殊な設計です。現実には次の負担が急激に増えます。

問題 内容
起動コスト エンティティ数に比例してサービス数が増える
発見の複雑さ どの対象がどのエージェント URL を持つかを別途管理する必要がある
スキル定義の重複 同種のエージェントが同じ skills を大量に再公開することになる
運用負荷 追加・削除・監視・認証設定がエンティティ数に比例して膨らむ
スケール 件数増加がそのままサービス管理コストになる

したがって、学習の出発点としては

A2A のエージェントは、個々のエンティティではなく、ドメイン能力を持つサービスである

と理解しておくほうが、ほとんどのケースで適切です。


9. マイクロサービスとの対比

ここまでの話は、マイクロサービスを思い浮かべると整理しやすくなります。A2A のエージェントも、対象 1 件ごとに増やすのではなく、責務ごとに分けたサービスとして考えると見通しがよくなるからです。

マイクロサービス A2A エージェント
ドメインごとに責務を分ける スキル / capability ごとに責務を分ける
API 定義を公開する Agent Card を公開する
リクエストで対象 ID を渡す メッセージ / タスクで対象を識別する
状態は DB やストアに置く タスク状態や業務状態も外部に置く

もちろん、A2A には task lifecycle、streaming、push notifications、artifacts など、通常の単純な REST API より強い協調モデルがあります。それでも、「1 サービスが多数の対象を扱う」という基本感覚は共通しています。A2A のエージェントを「人やレコードの分身」と考えるより、「能力を持った協調サービス」と理解したほうが、全体像に無理がありません。


10. まとめ

  • A2A のエージェントは、通常は個々のエンティティの分身ではない
  • Agent Card は、「そのエージェントは何ができるか」と「そのエージェントにどう接続するか」を示す自己記述文書である
  • 多数の対象は、エージェント数ではなくメッセージ / タスク / context と、アプリケーション側で持つデータで区別する
  • N × M の組み合わせが増えても、増えるのはタスクと状態データであって、必ずしもサービス数ではない
  • 実務上は、エージェントを「責務を持った窓口」として設計するほうが自然である

エージェント という語感に引きずられると、どうしても「対象 1 件につき 1 エージェント」という発想に寄りやすくなります。A2A の仕様に沿って考えるなら、まず見るべきなのはエンティティの個数ではなく、どの能力をどのサービス境界で公開するか です。

参考

Discussion