<?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/zh/tags/orchestration/</link><description>Articles, tutorials and insights from the .NET community.</description><generator>Hugo</generator><language>zh</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/zh/tags/orchestration/index.xml" rel="self" type="application/rss+xml"/><item><title>Handoff 模式：当一个智能体不够用时</title><link>https://thedotnetblog.com/zh/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/zh/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;开发者声明一个图：这些是智能体，这些是它们之间的边。框架完成其余工作——为每条出边合成一个 handoff 工具并将其注入每个智能体。当智能体决定交出控制权时，它调用该工具。框架强制执行拓扑结构。&lt;/p&gt;
&lt;p&gt;三件事使这与简单地让智能体互相调用不同：&lt;/p&gt;
&lt;ol&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; — 当活跃智能体在没有调用 handoff 工具的情况下结束其轮次时，工作流让位给用户。无需轮询，无需显式退出条件。&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; — handoff 的决定是上下文相关的，最好由模型而不是类型化谓词来做出&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;每个步骤都是独立的 — 智能体共享一个只有一个需要的转录只是噪音&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 允许的最有趣的形式之一是真正的后向边。智能体可以决定&amp;quot;我没有足够的信息&amp;quot;并路由回研究步骤——不是使用硬编码循环，而是因为模型决定这是正确的决定。&lt;/p&gt;
&lt;p&gt;Human-in-the-loop 交互也自然地组合。当专家需要用户输入时，工作流通过默认的轮次循环让位给用户，收集响应，并以完整上下文恢复。智能体从未丢失对话。&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;Handoff 是那些看起来简单但一旦内化就能实现很多功能的模式之一：分散路由、共享上下文、强制拓扑、自然终止。当你的智能体开始说&amp;quot;实际上，应该由其他人来处理这个&amp;quot;时，这是正确的下一步。&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>