<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Orchestration | The .NET Blog</title><link>https://thedotnetblog.com/ja/tags/orchestration/</link><description>Articles, tutorials and insights from the .NET community.</description><generator>Hugo</generator><language>ja</language><managingEditor>@thedotnetblog (The .NET Blog)</managingEditor><webMaster>@thedotnetblog</webMaster><lastBuildDate>Mon, 01 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/ja/tags/orchestration/index.xml" rel="self" type="application/rss+xml"/><item><title>ハンドオフパターン：1つのエージェントでは不十分な時</title><link>https://thedotnetblog.com/ja/news/emiliano-montesdeoca/maf-handoff-orchestration-pattern-tour/</link><pubDate>Mon, 01 Jun 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ja/news/emiliano-montesdeoca/maf-handoff-orchestration-pattern-tour/</guid><description>Microsoft Agent FrameworkのHandoffオーケストレーションパターンにより、エージェントは会話コンテキストを失ったりトポロジルールを破ったりすることなく、次のターンを誰が処理するかを決定できます。</description><content:encoded>&lt;p&gt;どのマルチエージェントシステムも、いつかはシンプルなルーターを超えます。最初のサインは、専門エージェントがフォローアップの質問をする必要があるとき、またはターンの途中で別のエージェントが続けるべきだと気付くときです。固定パイプラインはそこで失敗します。ワンショットルーターもそこで失敗します。&lt;/p&gt;
&lt;p&gt;それこそがMicrosoft Agent FrameworkのHandoffオーケストレーションパターンが対処するために設計された問題です。&lt;/p&gt;
&lt;h2 id="handoffの仕組み"&gt;Handoffの仕組み&lt;/h2&gt;
&lt;p&gt;開発者がグラフを宣言します：エージェントはこれで、エージェント間のエッジはこれです。フレームワークが残りを行います — 各出力エッジにハンドオフツールを合成して各エージェントに注入します。エージェントが制御を渡すと決めたらツールを呼び出します。フレームワークがトポロジを強制します。&lt;/p&gt;
&lt;p&gt;これをエージェントが互いを呼び出すことと異なるものにする3つのこと：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;1つの共有トランスクリプト&lt;/strong&gt; — 受信エージェントは完全な会話履歴を見ます。ゼロから始まることはありません。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;トポロジの強制&lt;/strong&gt; — エージェントは宣言されたターゲットにのみハンドオフできます。ルーティングのバグは作成時に検出され、プロダクションでは検出されません。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自然な終了&lt;/strong&gt; — アクティブエージェントがハンドオフツールを呼び出さずにターンを終えると、ワークフローはユーザーに譲ります。ポーリングなし、明示的な終了条件なし。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="最小限の例"&gt;最小限の例&lt;/h2&gt;
&lt;p&gt;.NETでhandoffワークフローを構築するとこのようになります：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Agents.AI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Agents.AI.Workflows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AIAgent&lt;/span&gt; &lt;span class="n"&gt;triage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chatClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsAIAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Route to the right specialist.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Triage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AIAgent&lt;/span&gt; &lt;span class="n"&gt;billing&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chatClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsAIAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Handle billing questions.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Billing&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AIAgent&lt;/span&gt; &lt;span class="n"&gt;tech&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chatClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsAIAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Handle technical support.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Tech&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HandoffWorkflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;triage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;billing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tech&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;billing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;triage&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tech&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;triage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;billing&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Triageはどちらの専門家にも送れます。両方の専門家がtriageに戻せます。グラフは非巡回対応ですが、必要なとき(&amp;ldquo;もっと情報が必要&amp;rdquo; → 調査に戻る)にバックエッジをサポートします。&lt;/p&gt;
&lt;h2 id="handoffを使う時と使わない時"&gt;Handoffを使う時（と使わない時）&lt;/h2&gt;
&lt;p&gt;Handoffが適している場面：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;所有権が会話の途中で変わりうる&lt;/strong&gt; — エージェントが自分が間違った専門家だと気付く場合&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;バックエッジが重要&lt;/strong&gt; — 再起動なしに前のステップを再訪する必要がある場合&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ルーティング決定が曖昧&lt;/strong&gt; — ハンドオフするかどうかの決定が文脈的で、型付きの述語よりモデルが判断した方が良い場合&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;適していない&lt;/em&gt;場面：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;パイプラインが固定で順次的 — その場合は&lt;code&gt;Sequential&lt;/code&gt;ワークフローを使用&lt;/li&gt;
&lt;li&gt;各ステップが独立 — 1つしか必要としていないのに全員がトランスクリプトを共有するのは雑音&lt;/li&gt;
&lt;li&gt;厳格な処理保証が必要 — モデル駆動ルーティングの非決定論は望むものではない&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="バックエッジとhuman-in-the-loop"&gt;バックエッジとHuman-in-the-Loop&lt;/h2&gt;
&lt;p&gt;Handoffが可能にする最も興味深い形の一つは、本物のバックエッジです。エージェントは「情報が不十分」と判断して研究ステップに戻るルーティングをすることができます — ハードコードされたループではなく、モデルがそれが正しい判断だと決めるからです。&lt;/p&gt;
&lt;p&gt;Human-in-the-loopのインタラクションも自然に構成されます。専門家がユーザー入力を必要とするとき、ワークフローはデフォルトのターンループを通じてユーザーに戻し、応答を収集し、完全なコンテキストで再開します。エージェントは会話を失いません。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;p&gt;Handoffは内面化すると多くを可能にするシンプルに見えるパターンの一つです：分散ルーティング、共有コンテキスト、強制されたトポロジ、自然な終了。エージェントが「実際は他の誰かがこれを処理すべきだ」と言い始めたときの次のステップです。&lt;/p&gt;
&lt;p&gt;元の投稿で完全なウォークスルーを読む: &lt;a href="https://devblogs.microsoft.com/agent-framework/a-tour-of-handoff-orchestration-pattern/"&gt;A Tour of the Handoff Orchestration Pattern&lt;/a&gt;&lt;/p&gt;</content:encoded></item></channel></rss>