調査エージェントは顧客のアカウントを見つけ、プランを確認し、過去4件の請求書を取得しました。そして、「顧客は返金を求めている」という一行の要約とともに、請求エージェントに引き渡しました。この請求エージェントは、アカウント、プラン、請求書について何も知らないため、まずアカウントIDを尋ねることから始めます。
最初のエージェントが収集したすべての事実は、境界で破棄されました。これが引き継ぎの問題であり、二重のコストがかかります。一度は重複するAPI呼び出しで、もう一度は、2番目のエージェントが最初のエージェントよりも少ない情報で作業することによるエラーです。
このガイドでは、引き継ぎ時に何を残すべきか、チームが状態を渡す3つの方法とそれぞれの機能、なぜ要約が予想以上に多くの情報を失うのか、そして引き継ぎが主張する情報を伝達したことをどのようにテストするかについて説明します。エージェントが本番環境で故障する理由に関する当社の投稿では、状態の喪失を中核的な故障モードとして扱っていますが、これはそのマルチエージェント版です。
Apidogが登場するのは、最も安価な解決策が通常、データ自体を渡すのをやめて識別子を渡すことだからです。これは、すべてのエージェントが同じ方法で同じレコードを取得できる場合にのみ機能します。
実際に境界を越える必要があるもの
すべてではありません。会話全体をコピーする引き継ぎは、何もコピーしない引き継ぎと同じくらい機能不全に陥ります。ただし、逆の方向で。2番目のエージェントは完全なコンテキストウィンドウを継承し、どの部分が重要かを判断しなければなりません。
4つのカテゴリに分けて考える価値があります。
識別子。 アカウントID、注文ID、ジョブID、チケット番号など。これらは小さく、安定しており、受信エージェントが必要なものを取得できるようにします。これらは渡すべき最も価値のあるものであり、最も頻繁に失われるものです。
既になされた決定。 「顧客はポリシー3に基づき返金対象である。」受信エージェントはこれを再検討してはなりません。もしそうすれば、一つのタスク内で2つのエージェントが意見の相違を起こすことになります。
制約。 予算制限、承認された事項、既に実行されたアクションなど。これを失うと、タスクが二重に請求されたり、同じ承認を2度求めたりすることになります。これは、AIエージェントのべき等性に関する当社の投稿と直接関連しています。
未解決の質問。 最初のエージェントが解決できなかったこと。これを明示的に渡すことで、2番目のエージェントが黙って仮定することを防ぎます。
渡す必要がないもの:生のAPI応答、推論のトランスクリプト、そして受信エージェントが1回の呼び出しで自分で取得できるものすべて。
状態を渡す3つの方法
会話全体を渡す。 シンプルで、1つの短いタスクで2つのエージェントに対して機能します。トランスクリプトが長くなるとすぐに失敗します。なぜなら、受信エージェントがその予算のほとんどを履歴の読みに費やし、関連する事実が途中に埋もれてしまうからです。ツール応答をコンテキストウィンドウから外すに関する当社の投稿は、その中間がモデルが情報を失うまさにその場所である理由を説明しています。
要約を渡す。 最初のエージェントが引き継ぎメッセージを書き、2番目のエージェントがそれから開始します。これはほとんどのフレームワークのデフォルトであり、特定の点で損失を伴います。モデルは物語性に向けて要約し、識別子から離れてしまいます。要約を求めると、「アカウント8812、プランプロ、請求書4件、請求書inv_44の返金承認済み」ではなく、「顧客は2年間購読しており、不満を抱いている」といった内容が得られます。
構造化された引き継ぎオブジェクトを渡す。 最初のエージェントがスキーマを埋めます。2番目のエージェントは散文ではなくフィールドを読み取ります。これは設定により多くの作業が必要ですが、最も持続可能な方法です。
{
"task_id": "task_2026_08_26_0031",
"from_agent": "research",
"to_agent": "billing",
"entities": {
"customer_id": "cus_8812",
"invoice_ids": ["inv_41", "inv_42", "inv_43", "inv_44"],
"subscription_id": "sub_119"
},
"decisions": [
{ "decision": "refund_eligible", "value": true, "basis": "policy 3.2, charged twice in one cycle" }
],
"constraints": {
"max_refund_cents": 4900,
"human_approval_granted": false,
"actions_taken": ["read_invoices"]
},
"open_questions": ["Customer has not confirmed which invoice to refund"],
"summary": "Customer cus_8812 was double-charged in August. Refund of one invoice is approved under policy 3.2, up to 4900 cents. Awaiting the customer's choice of invoice."
}
`summary`フィールドには依然として散文が含まれています。これは、スキーマが捉えきれないニュアンスを伝えるためです。構造化されたフィールドを置き換えるのではなく、それと並んで存在することが重要な点です。
引き継ぎが実行される前にオブジェクトを検証してください。もし`customer_id`が欠落している場合、2番目のエージェントが3回呼び出した後に発見するのではなく、境界で大きなエラーを発生させてください。
ペイロードではなく参照を渡す
引き継ぎの最も強力なバージョンは、ほとんどデータを渡しません。IDを渡し、受信エージェントが必要なものを取得します。
これが機能する理由は3つあります。状態が常に最新に保たれるため、2つのエージェント間で何かが変更されても、2番目のエージェントは古いコピーではなく現在の値を見ます。引き継ぎは数万トークンではなく数百バイトと小さく保たれます。そして、すべての読み取りがプロンプト間でコピーされたテキストとしてではなく、API呼び出しとして表示されるため、監査証跡が改善されます。
これには1つの要件があります。すべてのエージェントが適切な権限で同じAPIにアクセスできることです。これは無料ではありません。各エージェントは、その役割に合わせた独自の認証情報を持つ必要があります。これは、エージェントのための最小権限APIキーに関する当社の投稿で述べられている議論です。読み取り専用の研究トークンを持つ請求エージェントは返金を発行できず、請求トークンを持つ研究エージェントは被害範囲の問題を引き起こします。
再取得が高価または遅い場合、オーケストレーターにレコードをキャッシュし、キャッシュエントリへの参照を渡します。受信エージェントは依然としてデータを明示的に要求するため、パターンは同じですが、2回目の読み取りは安価になります。
引き継ぎが実際に破綻する場所
4つの失敗がほとんどのインシデントを網羅しています。
失われた識別子。 要約が「顧客」と述べ、IDを与えないため、2番目のエージェントは名前で検索し、2つの候補を見つけて間違った方を選択します。引き継ぎを進める前に、必要なエンティティIDが存在することを検証することで、これを防ぎます。
繰り返されるアクション。 最初のエージェントはすでにメールを送信しました。引き継ぎはそのことを記録していません。2番目のエージェントは再度送信します。引き継ぎオブジェクトに`actions_taken`を記録し、書き込みを行う前にそれを確認してください。繰り返しても無害にするべき等性キーによって支えられます。
失われた承認。 最初のエージェントが実行中に、人間が返金を承認しました。2番目のエージェントはこれを知らず、再度尋ねます。ユーザーは2番目のプロンプトを、聞き入れないシステムと認識します。承認を明示的な制約として引き継ぎ、エージェントではなくタスクにスコープされたものとして扱ってください。
自信のあるでっち上げ。 受信エージェントは引き継ぎで伝達されなかった値を必要とし、尋ねる代わりに物語に合うものをでっち上げます。これは、完了したタスクのように見えるため、最も危険な失敗です。防御策は、`open_questions`フィールドと、受信エージェントのプロンプトにおける厳格なルールです。必須の識別子が欠落している場合は、停止して尋ねることです。
ループはこれら4つすべてを悪化させます。エージェントAがBに引き継ぎ、BがAに引き継ぎを戻すとき、状態は各パスで劣化し、まるでコピーのコピーのように薄れていきます。ホップの数を制限し、各境界で再構築するのではなく、元のタスクオブジェクトをすべてのホップで引き継ぐようにしてください。
エージェントだけでなく、境界をテストする
引き継ぎは統合ポイントであるため、統合ポイントとしてテストしてください。
引き継ぎオブジェクトをアサートします。固定されたシナリオに対して最初のエージェントを実行し、それが生成するオブジェクト(必須の識別子の存在、記録された決定、リストされたアクションなど)をチェックします。これは、それを生成したエージェントが非決定論的であるにもかかわらず、構造化されたペイロードに対する決定論的なアサートであり、これがテストとして使用可能である理由です。非決定論的AIエージェントのテストに関する当社のガイドに一般的なアプローチが記載されています。
受信側を単独でテストします。手作業で作成した引き継ぎオブジェクトを請求エージェントに渡し、その動作を確認します。次に、顧客IDが削除された意図的に壊れたオブジェクトを渡し、推測する代わりに質問することを確認します。この2番目のテストが、でっち上げを検出するものです。
両方をモックに対して実行します。実際の返金を発行する引き継ぎテストは、一度だけ実行するテストです。両方のエージェントをモックエンドポイントに向け、すべての変更でスイートが実行できるようにします。本番環境ではなくモックに対してエージェントを実行するに関する当社の投稿に従ってください。Apidogでは、モックは両方のエージェントが呼び出すのと同じAPI定義から来るため、両者が乖離することはありません。
すべての引き継ぎをログに記録します。各境界でタスクIDとともに完全なオブジェクトを記録します。マルチエージェントの実行がうまくいかない場合、引き継ぎログはどのエージェントが情報を持っていて、どのエージェントがそれを失ったかを教えてくれます。これが通常、調査全体になります。エージェントツール呼び出しのトレースに関する当社の投稿では、そのレコードに他に何を含めるべきかについて説明しています。
フレームワークが提供するもの
ほとんどのオーケストレーションフレームワークは引き継ぎプリミティブを提供しており、それに依存する前に、それぞれが実際に境界を越えて何を移動させるのかを知っておくと役立ちます。
OpenAI Agents SDKの引き継ぎドキュメントでは、引き継ぎをエージェントが呼び出すことができるツールとしてモデル化しており、これによりモデルが制御の転送時期を決定します。これは便利ですが、システムの最も非決定論的な部分に決定を委ねることになるため、出力時に検証と組み合わせてください。
LangGraphのマルチエージェントガイダンスは逆のアプローチを取ります。状態はすべてのノードが読み書きする明示的なグラフオブジェクトです。これは上記の構造化された引き継ぎと密接に一致しており、残された主な作業はどのフィールドが必須であるかを決定することです。
Anthropicによるマルチエージェント研究システムの構築に関する記事は、運用上の詳細、特にサブエージェントが単独で有用に機能するためにどの程度の指示が必要かについて、一読の価値があります。
共通のテーマ:どのフレームワークも何らかの情報を移動させます。しかし、どの事実が重要であるかを決定してくれるものはありません。そのリストを作成するのはあなたであり、実行がうまくいかないときに確認する価値のあるものです。
タスクオブジェクトを会話の外に保つ
一つの構造的な変更で、多くのバグを防ぐことができます。タスクの状態をタスクIDをキーとして永続的な場所に保存し、メッセージを介して渡すのではなく、すべてのエージェントがそれを読み書きするようにします。
会話は状態を保持するのに不十分なコンテナです。要約によって圧縮され、切り詰められ、書き換えられますが、これらの操作のいずれも、あなたが失うわけにはいかないフィールドを知りません。データベースの行にはその問題はありません。
パターンは小さいです。ターンが開始されると、エージェントはタスクオブジェクトをロードします。アクションを実行すると、`actions_taken`に追加して保存します。引き継ぎ時に、タスクIDを渡し、受信エージェントは同じオブジェクトをロードします。重要なことはプロンプト内を移動しないため、重要なことが要約で失われることはありません。
これにより、再開ポイントも得られます。実行がステップ4で停止した場合でも、タスクオブジェクトには最初の3ステップで確立されたすべてが保持されており、再試行はそこから開始され、最初からやり直す必要はありません。
プラットフォームが状態を保持できる場所
エージェントが開発者のマシン上でCLIランタイムとして実行される場合、上記の永続的なタスクオブジェクトはあなたが構築するものです。一部のエージェント作業管理プラットフォームはすでにこれをモデル化しており、独自のものを書く前にそれがどのようなものかを知っておく価値があります。
Sharklyは、まさにこの単位を中心に構築された、人々とエージェントのための作業管理システムです。タスクは、目標、ステータス、責任者、実行を割り当てられたエージェントまたはクルー、コメント、およびエージェントの実行状態と結果を保持します。クルーはリーダーエージェントと他のエージェントおよび人々を組み合わせており、複数の専門家を必要とするタスクは、プロンプトを介して手渡しされるのではなく、再利用可能なグループに割り当てられます。状態が会話ではなくタスク上に存在するため、2つのエージェント間の引き継ぎは、どちらかがうまく要約することに依存しません。
ランタイムは、あなたがすでに使用しているものでそのままです。Claude Code、Codexなどは、あなたが登録したコンピューター上で作業を実行します。プラットフォームは、タスクレコード、割り当て、およびそれらをめぐるレビューサイクルを提供します。もしあなたが永続タスクパターンを自分で構築する場合、Sharklyのドキュメントは、どのフィールドが重要になるかを知る上で役立つ参照となります。
引き継ぎのチェックリスト
- 引き継ぎには定義されたスキーマが存在し、境界で検証される。
- エンティティ識別子は必須フィールドであり、オプションではない。
- 決定にはその根拠が含まれており、受信側が推論をやり直す必要がない。
- 既に行われたアクションは記録され、書き込みの前にチェックされる。
- 承認と予算はエージェントではなくタスクとともに移動する。
- 未解決の質問は明確であり、受信側は仮定するのではなく質問する。
- 再取得が安価な場合、データは参照によって渡される。
- ホップ数は制限され、元のタスクオブジェクトはすべてのホップを乗り越える。
- すべての引き継ぎはタスクIDとともにログに記録される。
- 境界テストは、意図的に不完全な引き継ぎを含むモックに対してCIで実行される。
ほとんどのマルチエージェントの失敗は推論の失敗ではありません。それは、あるエージェントには存在したが次のエージェントには存在しなかった事実によるものです。境界をスキーマとテストを備えたインターフェースとして設計することで、2番目のエージェントは最初のエージェントがすでに回答した質問を尋ねるのをやめます。両方のエージェントが依存するAPIの隣にモックと境界テストを保持するには、Apidogをダウンロードしてください。
よくある質問
2つのエージェントにとって構造化された引き継ぎは価値があるか? 短いタスクで2つのエージェントの場合、会話を渡すことで通常は問題ありません。構造化されたオブジェクトがその価値を発揮するのは、3つ以上のエージェント、長いタスク、または引き継ぎがプロセスや実行の境界を越えるあらゆる場所です。
モデルが引き継ぎオブジェクトを作成すべきか、コードが構築すべきか? 可能な限りコードで行うべきです。識別子、実行されたアクション、および承認は、モデルの記憶からではなく、実際に起こったことからオーケストレーターによって入力されるべきです。モデルには`summary`と未解決の質問のみを作成させましょう。
ループでのコンテキスト劣化をどう防ぐか? 各境界で再生成するのではなく、1つのタスクオブジェクト全体を実行中に運び、それを更新します。次にホップ数を制限します。タスクが少数をはるかに超えるホップを必要とする場合、分解が誤っている可能性があります。
組み込みの引き継ぎサポートがあるフレームワークについてはどうか? それらを使用し、実際に何が転送されるかを確認してください。多くはメッセージ履歴のみを渡し、他には何も渡しません。これは、識別子がテキストに現れた場合にのみ生き残ることを意味します。フレームワークが運ぶものに加えて、構造化されたペイロードを追加してください。
サブエージェントは個別のAPI認証情報を必要とするか? はい、それぞれの役割に合わせたスコープで必要です。強力なキーを複数のエージェント間で共有すると、損害を制限する能力や、どのエージェントが呼び出しを行ったかを判断する能力が失われます。エージェントのための最小権限APIキーに関する当社の投稿で設定方法を説明しています。
要約フィールドにはどの程度の情報を含めるべきか? 構造化されたフィールドでは表現できない意図やニュアンスをカバーする数文程度です。IDや金額をリストし始めた場合、それらは検証可能な構造化フィールドに含めるべきです。
