微软技术栈多智能体系统设计:基于Semantic Kernel的协作架构与生产实战
发布时间:2026/9/8 20:20:58 作者:尧图编辑部 阅读量:1,286

最近被问到最多的一个问题就是用 Microsoft 技术栈做多智能体系统到底怎么设计这不是一句把多个 Agent 塞进同一个对话里就能回答的。我前后折腾了两三套方案从纯开源框架到微软系全家桶踩了不少坑也把不少看似花哨的设计打回重做过。这篇就把我实际验证过的方案、架构决策和那些文档里不会写的细节一次性写清楚。需要说明的是这篇文章主要面向两类人一是准备用微软生态Azure OpenAI、Semantic Kernel、AutoGen 等落地多智能体系统的开发者和架构师二是已经被各种框架名搞晕、想搞清楚到底该用哪个、该怎么搭的团队负责人。我会尽量把选型理由、协作模式设计和踩坑链路讲透而不是只给一个能跑通的 Demo。1. 为什么是微软这套方案选型时我对比过的几条路1.1 开源框架与微软技术栈的真实差异多智能体这个词这两年被炒得厉害但本质上它解决的是单一模型一次对话搞不定复杂任务的问题。市面上可选的方案大致分三类纯手工编排自己写状态机调大模型、通用Agent框架LangChain、CrewAI 等、微软系框架Semantic Kernel、AutoGen、Agent Framework。我最早用过通用开源框架做原型。LangChain 的 Agent 概念灵活生态大但问题也明显抽象层次太多底层依赖更新频繁经常出现昨天还能跑的代码今天升级一个小版本就废了。而且多智能体的核心——智能体之间的通信和协作机制——这类框架更多是提供原语真正的协作逻辑还得自己设计。CrewAI 上手快角色扮演体验好但生产级的有状态流程、监控和权限控制能力偏弱适合 Demo 和中小型内部工具。微软系的优势不在算法更强而在工程闭环模型层有 Azure OpenAI编排层有 Semantic Kernel 和 Agent Framework部署层有 Azure Container Apps/AKS监控有 Application Insights。同一个团队可以在一套技术栈里把模型调用—智能体编排—部署运维全部串起来省掉大量胶水代码。如果你所在的团队已经重度使用 Azure 或 .NET这个优势会非常明显。1.2 Microsoft 生态里容易搞混的几个组件这块我要专门拎出来说因为太容易混淆了。微软系里至少有四个东西都跟多智能体相关名字还都带Agent组件定位适合场景Semantic Kernel轻量级编排 SDK提供 Agent 原语和 Process 框架需要深度定制协作逻辑、希望代码可控的团队AutoGen多智能体对话与研究型框架支持灵活对话模式研究原型、需要复杂对话协商的团队Microsoft Agent Framework更上层的多智能体应用框架把 SK 和 AutoGen 的能力做了统一从一开始就想做生产级应用、不想自己拼装底层Azure AI Foundry Agent Service云上的托管式智能体服务不直接编写编排代码快速验证、免运维、需要服务化输出我自己的体会是如果项目周期紧、要快速上生产可以直接基于 Agent Framework 或 Azure AI Foundry 起步如果核心业务逻辑复杂、需要深度控制对话流程和数据流向那就用 Semantic Kernel把 Process 框架和 Agent 组合用起来。AutoGen 更适合偏研究性质的多智能体协作探索比如你要让两个模型反复辩论、动态协商出结果这种场景 AutoGen 的对话驱动模型很舒服。1.3 我为什么最终选了 Semantic Kernel我这边的实际场景是做一个文档生成 审校 风险检查的内部系统需要三个角色协作写作 Agent、审校 Agent、风险审计 Agent。AutoGen 也能做但我需要把流程嵌入现有的 .NET 后端服务并且对接 Azure OpenAI 的企业认证和监控体系。综合比较下来Semantic Kernel 的控制粒度最合适它不强制你使用某种固定的对话模式而是提供ChatCompletionAgent、AgentGroupChat、ProcessFramework等构件让我能像搭积木一样搭出自己想要的协作结构。还有一点很实际Semantic Kernel 对 C# 支持极好这对我这种主要写后端服务的团队来说意味着智能体逻辑可以直接复用已有的服务层代码不用为了一个 Agent 单独起一个 Python 服务。下面的实践内容我都是以 Semantic Kernel 1.x 版本为例来说的。2. 多智能体不是多个 Agent 排队干活协作模式与系统架构2.1 先想清楚你的问题真的需要多智能体吗这是最容易被跳过、也最致命的问题。很多人一上来就设计三个 Agent、五个 Agent结果做出来的系统既慢又贵效果还不如一个精心调过 Prompt 的单 Agent。我的判断标准只有一个这个任务是否存在天然的、可被不同角色拆分的子目标并且角色之间需要协商或监督。举个例子写一份市场分析报告这种任务听起来可以分成市场研究员 Agent和文案撰写 Agent但实际上大模型一次调用就能完成拆分成多智能体反而引入额外的 token 消耗和协调失败风险。而写技术方案 → 代码审查 → 安全审计这种任务每一步的输出是下一步的输入并且每步都有独立的验证标准这种才是多智能体的主场。我经历过一次失败的教训最开始把生成周报也做成了写手 Agent 汇总 Agent两个角色结果两个 Agent 经常在格式细节上反复拉扯输出还不如单个 Agent 稳定。后来我砍掉了汇总 Agent让写手 Agent 直接从数据源读取结构化信息、按模板生成效果立刻稳定下来。所以架构设计第一步不是怎么拆角色而是确认拆了以后真的能降低复杂度而不是增加复杂度。2.2 三种主流协作模式轮转、对话、分层多智能体系统的协作模式决定了 Agent 之间谁先说话、谁听谁的、怎么结束。用微软生态落地时我实际用到三种模式对应不同的框架机制。第一种是轮转Round-robin模式多个 Agent 按顺序依次发言或者由协调者Conductor指定下一个发言人。这种模式结构简单适合流程相对固定的场景比如写作 Agent 先产出初稿 → 审校 Agent 修改 → 风险 Agent 检查。在 Semantic Kernel 里AgentGroupChat天然支持轮转式的对话流只要为每个 Agent 写上明确的职责说明系统会自动按顺序让它们接力。第二种是对话Conversation模式两个或多个 Agent 针对一个问题反复交流、互相质疑直到达成一致或满足结束条件。这种模式适合需要深度分析、多角度验证的场景比如方案设计 Agent 和成本审计 Agent 反复讨论一个技术选型是否值得。但也最容易出问题——如果两个 Agent 都觉得自己是对的就会陷入无限循环。我后面会专门讲这个坑怎么治。第三种是分层Hierarchical模式有一个主管 Agent负责拆解任务、分派给多个执行 Agent再回收结果做汇总和决策。这种模式适合任务并发度高、需要任务管理的复杂系统。Semantic Kernel 里有对应的 Process 机制可以把不同的 Agent 封装成步骤由流程框架统一推进。2.3 角色设计与共享上下文的边界多智能体系统里角色设计不只是给 Agent 起个名字加一段 System Prompt而是要明确三件事职责边界、知识边界、能力边界。职责边界指这个 Agent 管什么、不管什么。我的做法是每个 Agent 的 Instructions 里明确列出你负责/你不负责/发现不属于你职责的内容时怎么办。这能大幅减少 Agent 越权处理导致的协作混乱。知识边界指每个 Agent 能看到什么数据。并不是所有 Agent 都要访问全部业务数据比如风险审计 Agent 只需要读文本和合规规则不需要连接数据库去查用户信息。能力边界指它能调用哪些工具Function/Tool。Semantic Kernel 里可以给每个 Agent 绑定不同的 Kernel不同插件集实现能力隔离。还有一个关键点是共享上下文。同一组 Agent 协作时它们共享同一个聊天历史但这既是优势也是负担。聊天历史太长时后面 Agent 的上下文会被前面一堆无关对话稀释导致判断质量下降。我常用的手段是在关键步骤之间插入总结 Agent把当前会话压缩成结构化摘要再传给下一个阶段而不是让所有 Agent 一直摊开所有对话历史。2.4 进程内编排和进程外编排怎么选这是我后来才搞明白的一个点。多智能体协作里的编排分两种进程内编排是智能体在同一个进程内互相调用适合对话式协作响应快、实现简单但整个流程在建状态和故障恢复上偏弱进程外编排是把每个智能体或每个流程步骤封装成独立的工作流任务通过 Framework/Process 在后台推进适合长时间运行、需要持久化状态和人工审批的业务流。Semantic Kernel 里这两套机制都提供AgentGroupChat属于进程内ProcessFramework属于进程外。我现在的做法是混合编排需要快速迭代、频繁互评的阶段用AgentGroupChat需要稳定推进、断电恢复的阶段用ProcessFramework。比如文档生成系统里前期创意讨论用对话模式后期审校流程用 Process 模式两者各司其职。3. 基于 Semantic Kernel 落地一个三智能体协作系统3.1 模型配置和内核构建跑通一个多智能体系统第一步不是写 Agent而是把底座配好。以 Azure OpenAI 为例核心配置项包括DeploymentName、Endpoint、ApiKey或托管身份认证。Semantic Kernel 中通过Kernel.CreateBuilder()注册模型。var builder Kernel.CreateBuilder(); builder.AddAzureOpenAIChatCompletion( deploymentName: gpt-4o, endpoint: https://your-resource.openai.azure.com/, apiKey: your-api-key ); // 也可以使用托管身份生产环境推荐避免密钥硬编码 // builder.AddAzureOpenAIChatCompletion(deploymentName, endpoint, new DefaultAzureCredential()); var kernel builder.Build();这里有两个容易踩的坑。第一个是DeploymentName必须是 Azure OpenAI 资源里实际创建的部署名不是模型名gpt-4o本身。如果部署名是my-gpt4o-dep填gpt-4o会直接报 404。第二个是如果做多智能体不同 Agent 可能要用不同模型或不同温度参数这时建议每个 Agent 构建独立的Kernel实例而不是共用同一个 Kernel否则很难单独调整某个角色的行为。3.2 定义角色Writer、Reviewer、RiskAuditor我的三智能体模型里三个角色的职责划分是这样的Writer写作 Agent负责生成初稿理解需求组织结构和语言表达。Reviewer审校 Agent检查逻辑漏洞、事实错误、表达不清晰和格式问题直接输出修改意见。RiskAuditor风险审计 Agent站在合规和风险角度检查内容比如合同条款里的责任边界、宣传文案里的极限用词等。用 Semantic Kernel 定义时核心是设置好Name和Instructions并把对应插件注册到各自的 Kernel。var writerKernel kernel.Clone(); var writer new ChatCompletionAgent { Name Writer, Instructions 你是一名资深技术文档撰写专家。 你的任务是根据用户需求生成结构化初稿。 你负责内容组织和表达但不负责合规审核。 输出请使用 Markdown 格式。 , Kernel writerKernel }; var reviewerKernel kernel.Clone(); var reviewer new ChatCompletionAgent { Name Reviewer, Instructions 你是一名严格的审校编辑。 你会收到一篇文章需要检查逻辑、事实、表达和格式问题。 输出修改意见并明确指出需要修改的位置和理由。 只输出修改意见不要重写整篇文章。 , Kernel reviewerKernel }; var auditorKernel kernel.Clone(); var auditor new ChatCompletionAgent { Name RiskAuditor, Instructions 你是一名合规与风险审计专家。 你会收到一篇文章需要对照合规规则和风险清单进行检查。 重点识别夸大宣传、责任模糊、数据引用无来源、敏感表述。 输出风险等级高/中/低和具体风险描述。 , Kernel auditorKernel };Instructions的写法直接影响协作质量。我的经验是不要只写你是专家要写清楚你的任务边界你收到什么、输出什么你不该做什么。特别是不该做什么这一点很多角色冲突都源于职责范围不清晰。比如 Reviewer 如果觉得自己也能改稿就会输出一堆重写后的全文把审校结果变得很难合并所以我在指令里明确要求只输出修改意见不要重写整篇文章。3.3 AgentGroupChat 协作协议与终止条件把三个 Agent 放进同一个AgentGroupChat让它们按写稿 → 审校 → 审计的顺序接力核心代码并不复杂var chat new AgentGroupChat(writer, reviewer, auditor) { ExecutionSettings new AgentGroupChatSettings { TerminationStrategy new MaxIterationTerminationStrategy { MaximumIterations 6, MaxTotalTokens 8000 } } }; // 用户输入需求 chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, 请生成一份关于XX产品的发布公告强调技术创新并注意合规风险)); await foreach (var response in chat.InvokeAsync()) { Console.WriteLine(${response.Author.Name}: {response.Content}); }这段代码背后有几个设计决策值得展开。第一个是终止策略。AgentGroupChat默认会一直让 Agent 轮流发言如果你不设置终止条件它真的可能一直聊下去。我自定义了MaxIterationTerminationStrategy限制最大迭代次数和最大 token 数。实际生产里我还根据任务类型设置了不同的上限文档生成类任务6 轮基本够用代码检查类任务因为要反复修改验证我放到 10 轮。轮次上限不要设得太小否则系统会在任务没完成时就被强行截断也不要太大否则一旦 Agent 陷入循环token 消耗会失控。第二个是发言顺序。AgentGroupChat在默认情况下会根据对话历史和每个 Agent 的Instructions让最合适的 Agent 发言并不严格按注册顺序。如果你需要严格的写→审→审计流程我建议在调用InvokeAsync之前先主动调用指定 Agent 来引导流程或者用chat.AddChatMessage插入一条系统消息来指定下一发言人。更稳妥的做法是使用下面要说的 Process 机制来做固定流程。第三个是并发问题。AgentGroupChat的多个 Agent 在协作时某些版本下并行调用可能会互相覆盖聊天历史的状态。我的建议是同一个AgentGroupChat实例不要在多线程下并发使用如果系统需要同时处理多个用户请求就为每个会话创建独立的AgentGroupChat实例避免会话数据串场。3.4 Process Framework 做有状态流程AgentGroupChat适合交流式协作但如果你要做的是类似先生成 → 再审校 → 再人工确认 → 再发布这种顺序分明、需要中途等待和恢复的流程用ProcessFramework更合适。Process 的思路是把你系统中的各个步骤封装成ProcessStep步骤之间通过事件驱动流转。比如我可以定义一个DocumentGenerationProcess包含CreateDraftStep、ReviewStep、AuditStep、HumanApprovalStep四个步骤每个步骤内部可以调用对应的 Agent 或普通服务方法。Process 框架会持久化每个步骤的状态即使服务重启也能从断点继续执行。var processBuilder new ProcessBuilder(DocumentGenerationProcess); var createDraftStep processBuilder.AddStepFromTypeCreateDraftStep(); var reviewStep processBuilder.AddStepFromTypeReviewStep(); var auditStep processBuilder.AddStepFromTypeAuditStep(); var approvalStep processBuilder.AddStepFromTypeHumanApprovalStep(); createDraftStep.OnEvent(DraftCreated).SendEventTo(reviewStep); reviewStep.OnEvent(ReviewCompleted).SendEventTo(auditStep); auditStep.OnEvent(AuditCompleted).SendEventTo(approvalStep);Process 方式和AgentGroupChat最大的区别是它不再强依赖多轮对话这种形态而是把每个 Agent 当成一个可独立调用的处理器流程由一个显式的状态机来驱动。这样做的好处是流程可控、可观测、可恢复坏处是失去了对话式协作的灵活性和自适应性。我的经验是凡是流程可以提前确定的用 Process凡是流程需要动态演化的用 AgentGroupChat。两者不是替代关系而是配合关系。4. 从原型到生产我踩过的五个大坑4.1 迭代不收敛Reviewer 和 Writer 无限互怼这是多智能体系统最常见、也最让人抓狂的问题。我第一次跑通原型时Writer 生成了一版初稿Reviewer 挑出一堆问题Writer 修改后Reviewer 又觉得新问题更大双方你来我往直到MaximumIterations被触顶强行截断输出结果还是乱糟糟的。排查链路是这样的我先去看了每轮对话的完整日志发现 Review 的意见其实已经收敛了后两轮 Review 说的修改意见和第三轮基本一致但 Writer 每轮都会顺带调整一下文章结构于是 Review 又会对新结构提出新的意见形成了死循环。根因不是模型不够聪明而是Reviewer 没有区分必须修改和建议优化Writer 也没有没有重大问题时就停止修改的意识。修复方案是双管齐下一是在 Reviewer 的 Instructions 里明确如果以上一轮意见已满足回复 APPROVED 并停止提新意见二是把终止策略改成当连续两轮 Reviewer 回复包含 APPROVED 时强制结束流程。我在TerminationStrategy里自定义了针对APPROVED标记的判定逻辑效果立竿见影一个任务的平均迭代轮数从 9 轮降到了 4 轮左右。protected override async Taskbool ShouldTerminateAsync( AgentGroupChat chat, CancellationToken cancellationToken) { // 如果同一审校者连续两次发出 APPROVED则终止 var history await chat.GetChatMessagesAsync().ToListAsync(cancellationToken); var reviewerApprovals history .Where(m m.Author?.Name Reviewer) .TakeLast(2) .Count(m m.Content.Contains(APPROVED)); return reviewerApprovals 2 || history.Count MaximumIterations; }4.2 token 消耗失控一次协作烧掉 20 万 token对话式协作最大的隐性成本就是 token。我当时做一个方案评审任务三个 Agent 旁征博引地讨论最后账单一出吓了我一跳一次任务消耗了接近 20 万 token其中至少 60% 是历史对话重复暴露给了每个 Agent。原因在于AgentGroupChat每次让新 Agent 发言时默认都会带上完整聊天上下文Agent 越多、轮次越多token 消耗呈指数级增长。我做了三个调整。第一给每个 Agent 的 Instructions 里明确要求只输出与职责直接相关的内容不总结、不复述、不客套减少无意义输出。第二在关键步骤之间插入上下文压缩节点用一个小模型或者指定 Agent 把前面多轮对话总结成结构化摘要把摘要注入后续 Agent 的上下文而不是直接堆积全部对话历史。第三对每个 Agent 设置独立的 token 上限在调用模型时通过OpenAIPromptExecutionSettings限制MaxTokens。这三个调整叠加之后同样任务的平均 token 消耗下降了差不多一半。4.3 工具权限与人工审批多智能体系统一旦接上工具查数据库、发邮件、改代码风险就从模型输出升级为真实操作。比如我的 RiskAuditor 如果发现高风险内容系统会自动调用内部通知服务发告警但如果模型误判就会产生误报甚至误操作。我的做法分两层。第一层是能力隔离每个 Agent 只能调用分配给它的插件。Semantic Kernel 里可以为不同的Kernel注册不同的IFunctionInvocationFilter在工具调用前做校验。第二层是人工审批断点凡是涉及对外部系统产生副作用的步骤我都会在 Process 流程里插入一个HumanApprovalStep由人工确认后才继续执行。这一步会拖慢自动化速度但生产环境的安全不能让步。具体设计中我把所有工具调用按风险分成了三级只读查询类自动放行、内部写入类规则拦截后放行、外部操作类必须人工审批。4.4 可观测性缺失调 BUG 像在排查黑洞多智能体系统里一个结果背后是一长串的 Agent 调用链如果没有任何日志出了问题根本不知道是哪一环的锅。我一开始只打了几个Console.WriteLine结果遇到某个 Agent 突然不按指令走的问题时只能靠猜。后来我把可观测性分成了三个层面调用链路日志记录每个 Agent 的输入、输出、token 消耗、耗时。Semantic Kernel 里可以通过SetLoggerFactory接上ILogger把每个ChatCompletionAgent的调用都打出来。会话状态快照在关键节点如每次InvokeAsync返回后把当前AgentGroupChat的完整消息列表持久化到存储方便事后回放对话过程。指标监控统计每轮迭代的平均次数、最大 token 消耗、终止原因正常完成/超轮次/超 token。这些指标能直接反映系统健康度也是调优参数的重要依据。一开始我以为这只是加分项后来发现没有这套监控调参基本靠运气。特别是终止策略和 token 上限没有数据支撑的话你根本不知道设多少才合适。4.5 数据格式与序列化问题多智能体协作里Agent 之间传递的不仅是文本还可能包含结构化数据。比如 Reviewer 输出的修改意见如果带上{articleId, position, suggestion}这样的结构后端的合并逻辑就更好处理。但实际调用中模型很容易输出格式不稳定的 JSON或者夹带多余文字导致解析失败。我的方案是强制结构化输出宽容解析。用 Semantic Kernel 的 function calling 机制把输出修改意见定义成一个函数让模型按函数定义的 JSON Schema 返回而不是从对话文本里提取。同时写了一层容忍解析JSON 解析失败时尝试从 Markdown 代码块中提取再失败就退回原文匹配。这套组合目前在生产环境里稳定运行格式解析失败率低于 1%。5. 实测参数与调优记录5.1 模型温度和 Top P 的实测选择多智能体比单 Agent 更怕创造性太强的模型输出。写作 Agent 的创造性和审校 Agent 的严谨性需求不同所以温度参数必须分开设。我跑了多组对比实验结果显示Agent 角色温度Top P说明Writer0.70.9保持一定的表达多样性Reviewer0.20.5追求稳定、一致的评审结果RiskAuditor0.10.3合规检查需要严格标准低随机性这组参数不是一拍脑袋定的。我在同样 20 个测试用例下做了几次对比温度超过 0.8 后 Writer 开始出现结构漂移标题层级混乱审校 Agent 温度超过 0.4 后会出现两次评审意见互相矛盾的情况。当然这只是我的业务场景下的数据不同领域可能差异很大但思路可以参考需要发散创造的角色用高温度需要严谨验证的角色用低温度。5.2 终止策略与最大迭代的实测值关于MaximumIterations的设定我整理过一组自己的实测数据任务类型建议最大迭代实际完成轮次终止原因分布技术文档生成 审校63~5正常完成95%代码生成 审查 修复105~9正常完成82%超轮次截断18%方案讨论 风险协商127~11正常完成71%超轮次截断29%我后来给代码生成审查这类任务加上了一个额外策略如果审校 Agent 连续两轮给出的修改意见没有实质性变化就判定已收敛提前终止。这个策略把平均 token 消耗又降了不少。终止策略的判定条件不能只数轮次要结合内容相似度。5.3 结果评测与回归测试最后是有多少团队会忽略的一点多智能体系统的输出质量怎么量化。我搭建了一套回归测试集包含 30 个典型任务每次修改 Prompt 或调参之后都会对整个测试集跑一遍用几个固定指标评估输出质量任务完成率结果是否存在未完成或直接放弃的标记。评审通过率输出的内容能否通过 RiskAuditor 的检查即自己审自己看是否能闭环。协议覆盖率输出是否包含所有必须要素比如文档是否有背景、结论、风险提示。资源消耗总 token 数、总耗时、迭代轮数。实践证明多智能体系统里一次调好基本不存在每一次参数调整都一定要用回归测试去验证仅仅看一两个样例根本发现不了退化问题。这也是我建议团队搭这套系统时把评测环节作为基础设施同步建设的原因。我在实际使用中还有一个体会多智能体系统的上限其实不取决于模型的推理能力而取决于你把协作规则设计得多清楚。角色边界、通信协议、终止条件、异常降级这些工程细节才是决定系统能不能稳定跑生产的关键。如果你正打算用微软技术栈搭多智能体系统我的建议是从最小的两智能体场景入手先把协作流程跑通再加上复杂的编排和工具调用逐步扩展而不是一开始就把场面铺得很大。