AI エージェント向け: ドキュメントインデックスは https://www.mongodb.com/ja-jp/docs/llms.txt で利用できます。すべてのページの markdown バージョンは、いずれかの URL パスに .md を追加することで利用できます。
See how MongoDB 9.0 delivers up to 2x higher throughput.
MongoDB Branding Shape
Register now >
Docs Menu

エージェント間通信の使用

エージェント間(A2A)通信により、1 つのエージェントが実行時に同じプロジェクト内の他のエージェントを検出し、呼び出すことができます。クエリを実行することで、すべての呼び出しを中断します。

  • アクセスを検証します

  • 子実行を作成します

  • リクエストをターゲットエージェントにディスパッチします

  • 結果を返します

人間が開発したループ(HITL)での保証はエンドツーエンドで適用されます。人間のレビューのために一時停止するターゲットエージェントは、失敗を返す代わりに呼び出しを一時停止します。

有効にすると、A2A は次のシーケンスに従います。

  1. agent.yamlファイルに a2a: ブロックを追加します。最初の実行で、プラットフォームはエージェントの構成を OA に登録し、同じプロジェクト内の他のエージェントによってエージェントを検出し、呼び出せるようにします。

  2. OA がエージェントに実行をディスパッチすると、有効期間の短いトークンが実行コンテキストに挿入されます。エージェントは、他のエージェントを呼び出すときにそのトークンを透過的に使用します。

  3. エージェントコードから、app.a2a_tools() を使用して A2A を LM ツールとして公開するか(推奨)、または決定的なルーティングのために app._runtime.a2a を介して A2Aクライアントを直接呼び出します。

  4. OA はアクセス制御を強制し、子の実行を親にリンクし、ターゲットにディスパッチして結果を返します。

agent.yamlファイルに a2a: セクションを追加して、エージェントを検出し、呼び出せるようにします。このセクションを省略するか、a2a.enabled を false に設定すると、エージェントはA2A 呼び出し元では表示されず、既存の配置と完全に下位互換性があります。

注意

A2A をローカルでテストするには、A2A を呼び出す、または呼び出されるすべてのエージェントの .envファイルで、A2A_JWT_SECRET 環境変数を同じ値に設定します。

次の例では、完全に構成された a2a: セクションを示しています。

name: insurance-agent
entrypoint: insurance_agent.main:app
a2a:
enabled: true
allowed_callers:
- "ws-router-002"
skills:
- name: policy-lookup
description: Look up insurance policy details
example_input: '{"policy_id": "POL-123"}'
example_output: '{"status": "active", "premium": 240}'
- name: get-quote
description: Generate an insurance quote
input_modes:
- "text/plain"
output_modes:
- "text/plain"

次の表は、agent.yamlファイルの a2a: セクション内のフィールドを説明したものです。

フィールド
タイプ
default
説明

a2a.enabled

ブール

false

A2A を通じてエージェントを検出し、呼び出せるようにします。 false の場合、他のすべての a2a フィールドは無視されます。

a2a.allowed_callers

list[str]

[]

このエージェントを呼び出すために許可されたワークスペース ID。空のリストでは、同じプロジェクトで任意の A2A 有効エージェントが許可されます。空でないリストは許可リストとして機能します。

a2a.skills

list[object]

[]

エージェントが検出のために公開するスキーム。各エントリには name と description が必要です。 example_input と example_output フィールドは任意です。明確で具体的な説明は、このエージェントがニーズと一致するかどうかを他のエージェントが判断するのに役立ちます。

a2a.input_modes

list[str]

[]

エージェントが受け入れる多目的インターネットメール拡張機能( MIME )の例(text/plain や application/json など)。検出フィルターとして使用されます。

a2a.output_modes

list[str]

[]

エージェントが生成するMIMEタイプ。検出フィルターとして使用されます。

注意

エージェントの name、skills、input_modes、output_modes、allowed_callers は、スタートアップ時に自動的に OA にプッシュされます。検出結果に表示される無料テキストの説明と機能タグは、agent.yaml ではなく、 API Gateway ワークスペース エンドポイントを通じて構成するワークスペースの Agentcard から取得されます。

エージェントコードから他のエージェントを呼び出すには、A2A を LM ツールとして公開する(推奨)方法と、A2Aクライアントを直接使用する方法の 2 通りがあります。どちらも同じ 基礎となるクライアントを使用します。 LM を使用してルーティングの決定を行うか、決定的な制御が必要かに基づいてアプローチを選択します。

app.a2a_tools() メソッドは、2 つの Lgachein StructuredTool オブジェクト(discover_available_agents と invoke_a2a_agent )を返します。これらのオブジェクトを使用すると、LM は他のエージェントを単独で検出し、呼び出すことができます。既存のツールと一緒にこれらをバインドすることで、モデルは単独で他のエージェントにルーティングできます。

agent.yamlファイルで a2a.enabled が false の場合、app.a2a_tools() メソッドでは空のリストが返されるため、すべてのエージェントに を含めても安全です。

次の例では、A2A ツールを既存のツールと並行してバインドします。

from agent_engine_sdk_langgraph import App
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph
from langgraph.prebuilt import ToolNode
app = App(app_name="router-agent")
@app.entrypoint
def build_agent():
llm = app.llm(ChatOpenAI(model="gpt-5.4"))
a2a = app.a2a_tools()
llm_with_tools = llm.bind_tools(
app.get_tool_schemas() + a2a
)
tool_node = ToolNode(app.get_tools() + a2a)
graph = StateGraph(...)
return graph.compile(checkpointer=app.checkpointer())

LM にバインドされると、モデルは 2 つのツールを名前で呼び出します。これらのツールは次の関数シグネチャを公開します。

  • discover_available_agents() は、呼び出しエージェントに表示されるエージェントのJSONリストを返します。各エントリには、agent_id、name、description、skills、capabilities が含まれます。呼び出しエージェントは、それ自体の結果からフィルタリングされます。

  • invoke_a2a_agent(agent_id, message, custom_headers="") は、ターゲットエージェントを呼び出し、結果をJSONとして返します。 custom_headers を指定する場合は、それらをJSON文字列(例: '{"x-tenant": "acme"}')として渡します。

決定的なルーティングを使用する場合、クライアントを公開する属性である runtime.a2a を介して AgentToAgentクライアントに直接アクセスできます。

次の例では、能力によってエージェントを検出し、最初の一致を呼び出します。

agents = app._runtime.a2a.discover_agents(
skills=["policy-lookup"],
limit=10,
)
if agents:
resp = app._runtime.a2a.invoke_agent(
agent_id=agents[0].agent_id,
message="Look up policy POL-123",
skill="policy-lookup",
timeout=120,
)
if resp.status == "completed":
print(resp.result)

runtime.a2aNone属性は、A2 A が利用できない場合に を返します。これがいつ発生するかについては、「 考慮事項 」を参照してください。次の例に示すように、クライアントメソッドを呼び出す前に、必ずこのケースを確認してください。

a2a = app._runtime.a2a
if a2a is None:
...

注意

エージェントコード内の app._runtime.a2a を介して runtime.a2a にアクセスします。公開 app.a2a または app.runtime アクセス権は存在しません。ほとんどのユースケースでは、プライベート属性に依存しないため、代替として app.a2a_tools() が推奨されます。

このセクションでは、エージェントコードからプログラムによってエージェントを検出して呼び出すメソッドを提供する A2AクライアントSDK について説明します。

クライアントSDK を使用するには、次の例に示すように、agent_engine_runner_shared.a2a から A2A タイプをインポートします。

from agent_engine_runner_shared.a2a import (
AgentToAgent,
DiscoveredAgent,
AgentSkill,
AgentResponse,
)

AgentToAgent は、OU の /a2a/discover および /a2a/invoke エンドポイントと通信するHTTPクライアントです。エージェントコードでは、このクラスを直接構築するのではなく、runtime.a2a の事前認証済みインスタンスを使用します。

次の例は、 コンストラクターとそのパラメーターを示しています。

AgentToAgent(oe_url: str, auth_token: str = "")

以下の表では、AgentToAgent コンストラクター パラメーターを説明しています。

Argument
説明

oe_url

OA HTTPベースURL(例: http://localhost:8000)。

auth_token

A2Authorization: Bearer <token> として送信されたJSON Web Token(JWT) runtime.a2a を使用すると自動的に提供されます。

discover_agents() メソッドは、呼び出し元が表示を許可されているエージェントを返します。 1 つのフィルター パラメーターに複数の値を渡すと、エージェントはそれらの値のいずれか 1 つを満たす場合は一致します。例、skills=["a", "b"] はいずれかの特権を紹介するエージェントを返します。複数のフィルターパラメーターを渡す場合、エージェントはそれらのすべてを満たす必要があります。 A2A が有効になっておらず、allowed_callers を通じて呼び出し元を除外しているエージェントは返されません。

次の例は、このメソッドとそのパラメーターを示しています。

discover_agents(
project_id: str = "",
skills: list[str] | None = None,
capabilities: list[str] | None = None,
input_modes: list[str] | None = None,
limit: int = 50,
) -> list[DiscoveredAgent]

次の表では、discover_agents() メソッドのパラメータを説明しています。

Parameter
タイプ
説明

project_id

str

検索するプロジェクト。空の string は呼び出し元のプロジェクトを使用します。

skills

list[str]

ルール名でフィルタリングします。リストされている特権のいずれかを持つエージェントを返します。

capabilities

list[str]

機能タグでフィルタリングします。リストされている機能のいずれかを持つエージェントを返します。

input_modes

list[str]

許容されるMIMEタイプでフィルタリングします。リストされているMIMEタイプのいずれかを受け入れるエージェントを返します。

limit

整数

返される結果の最大数。デフォルトは 50 です。

invoke_agent() メソッドは、ターゲットエージェントを呼び出し、結果を待ちます。 OA は、トークンを検証し、アクセス制御をチェックし、子実行を作成し、エージェントが完了するまでポーリングします。

次の例は、このメソッドとそのパラメーターを示しています。

invoke_agent(
agent_id: str,
message: str,
skill: str = "",
timeout: float | None = None,
custom_headers: dict[str, str] | None = None,
) -> AgentResponse

次の表では、invoke_agent() メソッドのパラメータを説明しています。

Parameter
タイプ
説明

agent_id

str

ターゲット ワークスペースID。 discover_agents() から取得します。

message

str

ターゲットエージェントに送信するプロンプトまたはメッセージ。

skill

str

多くの特権を紹介するエージェントの、任意の特権のヒント。

timeout

浮動小数点数 |なし

タイムアウトするまでの待ち時間。 None は UE のデフォルトである 300 秒を使用します。 300 秒が最大タイムアウトです。

custom_headers

dict[str, str] | None

ターゲット エージェントの実行コンテキストに転送されるキー値ヘッダー。キーでは予約されたa2a- プレフィックスは使用できません。詳細については、「 カスタム ヘッダーの転送 」を参照してください。

次の表は、すべて不変のデータクラスである応答タイプを示しています。

クラス
フィールド

DiscoveredAgent

agent_id, name, description, project_id, skills: list[AgentSkill], capabilities: list[str], input_modes: list[str], output_modes: list[str]

AgentSkill

name、description、example_input(任意)、example_output(任意)

AgentResponse

status、result(任意)、error(任意)、execution_id

次の表は、AgentResponse.statusフィールドの各値について説明したものです。

ステータス
意味
何をする

completed

ターゲットエージェントが正常に終了しました。

result を読み取る。

failed

ターゲットエージェントがエラーを返しました。

error を読み取る。

input-required

ターゲットエージェントは人間によるレビューのために一時停止されました。

一時停止をユーザーまたはフローに表示します。これを失敗として扱わないでください。

タイムアウトや OA からの 4x および 5x 応答などのネットワークおよびHTTPレベルのエラーでは、discover_agents() メソッドと invoke_agent() メソッドから httpx.HTTPError が発生します。 status 値が failed である AgentResponse は、呼び出しは OA に到達したが、ターゲットエージェント自体が失敗したことを示します。ネットワークエラーとエージェントの障害の両方を処理するには、呼び出しを try/except ブロックでラップし、status 値を確認します。

次の例では、3 つのステータス値がすべて処理されています。

resp = app._runtime.a2a.invoke_agent(
agent_id="ws-billing-001",
message="Process the payment",
)
if resp.status == "completed":
handle(resp.result)
elif resp.status == "input-required":
notify_user(
"The billing agent needs human approval before continuing."
)
else:
log.error("A2A call failed: %s", resp.error)

A2A を使用して、テナントID 、トレース タグ、委任された OAuth トークンなど、リクエスト スコープのコンテキストを伝達するエージェント呼び出しに任意のキー値ヘッダーをアタッチできます。

呼び出されるエージェントにヘッダーをアタッチするには、invoke_agent() の custom_headers パラメータを使用して dict を渡します。 invoke_a2a_agent LM ツールを使用する場合は、ヘッダーをJSON string として渡します。

次の例では、ダイレクトクライアントを使用してカスタム ヘッダーを渡します。

app._runtime.a2a.invoke_agent(
agent_id="ws-billing-001",
message="Charge the customer",
custom_headers={
"x-tenant": "acme",
"oauth-token": "<delegated-token>",
},
)

次の例では、 LM ツールを使用してカスタム ヘッダーを渡します。

invoke_a2a_agent(
agent_id="ws-billing-001",
message="Charge the customer",
custom_headers='{"x-tenant": "acme"}',
)

ヘッダーキーでは、予約された a2a- 大文字と小文字を区別しない プレフィックスは使用できません。 UE は、いずれかのキーが a2a- で始まる場合、400 Bad Request 応答でリクエストを拒否します。 a2a- プレフィックスは、a2a-tokenや a2a-caller-workspace などのプラットフォーム ルーティングと ID ヘッダー用に予約されています。

呼び出しエージェントによって転送されたカスタム ヘッダーを読み取るには、agent_engine_runner_shared.contextクラスの get_current_custom_headers() メソッドを使用します。次の例では、このメソッドを呼び出します。

from agent_engine_runner_shared.context import get_current_custom_headers
headers = get_current_custom_headers()
tenant = headers.get("x-tenant")

get_current_custom_headers() は dict[str, str] を返します。メソッドは返される前にすべての a2a- プラットフォームのヘッダーを処理するため、エージェントコードでは A2A トークンやルーティングメタデータが表示されることはありません。呼び出し元がカスタム ヘッダーを送信しない場合、メソッドは空の辞書を返します。

agent.yamlファイルの a2a.allowed_callersフィールドは、次の動作を通じて を検出できるエージェントを制御します。

  • 空のリスト(デフォルト):2 同じプロジェクト内の任意の A A 対応エージェントがエージェントを呼び出し、検出結果で確認できます。

  • 空でないリスト: リストされているワークスペース ID のみがエージェントを呼び出すことができます。他のすべてのエージェントは403 応答を受け取り、検出結果にエージェントを表示できません。

プライマリは、ディスパッチする前に、呼び出し元のエージェントの ID を allowed_callers リストと照合します。エージェントではコードの変更は必要ありません。次の例では、呼び出しを単一の ルーターエージェントに制限しています。

a2a:
enabled: true
allowed_callers:
- "ws-router-002"

すべての A2A 呼び出しはセッションのトレース パネルに自動的に表示されます。ツールは必要ありません。ターゲットエージェントのアクティビティは同じセッショントレース内にネストされて表示されるため、エージェント間の完全な呼び出しツリーを1つの場所で追跡できます。

各呼び出しは A2A: <target agent name> というラベルの付いたサブエージェントノードとしてレンダリングされ、表示名がない場合はターゲットのワークスペースIDにフォールバックします。ノードには、呼び出しのステータスと期間が表示されます。ステータスは running として始まり、成功すると done、失敗すると error に変わります。ノードを選択すると、名前、ステータス、期間、ディスパッチの説明、ストリーム出力、およびエラーが表示される詳細パネルが開きます。

ターゲット エージェント独自のツール呼び出し、LM ステップ、メモリ操作は サブエージェントノードの下にネストされ、エージェント間で完全な呼び出しツリーが再構築されます。

runtime.a2a では、次の条件が すべて 当てはまる場合にのみクライアントが返されます。

  1. エージェントコードはエージェントサンドボックスで実行中。 A2A は、 ツール サンドボックスで実行されるコードからは使用できません。

  2. UE URL が実行コンテキストに存在する。

  3. 受信ヘッダーに a2a-token が存在する。 UE は、A2A が設定されている場合、すべてのディスパッチでこのトークンを自動的に挿入します。

いずれの条件も満たされない場合、runtime.a2a は None を返します。 app.a2a_tools() を使用する場合、例外が発生する代わりにツールは構造化エラーJSONを返します。

A2A トークンは、デフォルトで 5 後に期限切れになります。一般的なリクエストと応答のフローでは、これが十分です。トークンの有効期間よりも長く実行されるエージェントは、A2A 呼び出しで 401 応答を受け取る場合があります。自動トークン更新はまだ実装されていません。長時間実行される呼び出しからの 401 応答を一時的な障害として扱います。

discover_available_agents LM ツールは、呼び出しエージェントの独自のワークスペースの結果をフィルタリングして、モデルが自分自身を呼び出さないようにします。未加工の discover_agents()クライアントメソッドを使用する場合、OA は結果に独自のエージェントを含める可能性があります。必要に応じて、自分でフィルタリングします。

現在のリリースでは、 A2A の検出と呼び出しは、 同じプロジェクト内のエージェントに制限されています。プロジェクト間のルーティングはまだ実装されていません。

プラットフォームはすべての A2A 呼び出しを自動的にログに記録し、リンクします。ツールを追加する必要はありません。ターゲットは、parent_execution_id を介して呼び出し元にリンクされた子実行として実行されます。共有 root_session_id は、元のユーザー セッションの下に完全なクロスエージェント呼び出しツリーをグループ化します。

次の例では、LVM を使用して検索し、専用エージェントに委任するルーターエージェントを示します。 agent.yamlファイルはA2A を有効にし、route 特権を宣言します。

agent.yaml
name: router-agent
entrypoint: router_agent.main:app
a2a:
enabled: true
skills:
- name: route
description: Route a user request to the best specialist agent

次のエージェントコードは、A2A ツールを独自のツールとともにバインドし、LM がルーティングを処理できるようにします。

main.py
from agent_engine_sdk_langgraph import App
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, MessagesState
from langgraph.prebuilt import ToolNode
app = App(app_name="router-agent")
@app.entrypoint
def build_agent():
llm = app.llm(ChatOpenAI(model="gpt-5.4"))
a2a = app.a2a_tools()
llm_with_tools = llm.bind_tools(
app.get_tool_schemas() + a2a
)
def call_model(state: MessagesState):
return {
"messages": [llm_with_tools.invoke(state["messages"])]
}
graph = StateGraph(MessagesState)
graph.add_node("model", call_model)
graph.add_node("tools", ToolNode(app.get_tools() + a2a))
graph.set_entry_point("model")
graph.add_conditional_edges(
"model",
lambda s: (
"tools"
if s["messages"][-1].tool_calls
else "__end__"
),
)
graph.add_edge("tools", "model")
return graph.compile(checkpointer=app.checkpointer())

実行時に、LM は一致する特権特権エージェントを検出し、invoke_a2a_agent を通じてそれを呼び出し、アクセス制御を強制し、呼び出しの両方をログに記録しながら、呼び出しを中断します。

LM に依存するのではなく、明確にルーティングするには、グラフノード内でクライアントを直接呼び出します。

def delegate(state):
a2a = app._runtime.a2a
if a2a is None:
return {"messages": [("ai", "A2A is unavailable.")]}
resp = a2a.invoke_agent(
agent_id="ws-insurance-001",
message=state["messages"][-1].content,
skill="policy-lookup",
custom_headers={"x-request-source": "router-agent"},
)
text = (
resp.result
if resp.status == "completed"
else f"({resp.status}) {resp.error}"
)
return {"messages": [("ai", text)]}

エージェント間通信を有効にしたら、次のガイドを確認して、関連するタスクの詳細を学習できます。

このページを評価