多智能体系统实战:基于微软Agent Framework的架构与落地

发布时间:2026/9/8 19:07:35
多智能体系统实战:基于微软Agent Framework的架构与落地 2025年如果让我只挑一个方向持续加码那一定是多智能体系统。最近微软把 Agent Framework 的设计细节逐步公开之后很多朋友跑来问我这和 Semantic Kernel 到底什么关系多智能体是不是就是把好几个大模型接在一起各干各的说实话等我把一个真实项目从单 Agent 改造成多 Agent 之后最大的感触是——多智能体系统设计真正难的从来不是调用几个模型而是协作拓扑、状态传递和失败兜底。这篇文章我就围绕微软这套多智能体设计思路把我自己的理解、搭建过程、踩过的坑以及一个浏览器自动化场景里的落地方案完整拆开讲。无论你是刚接触 Agent 开发的初学者还是已经在用 LangChain、AutoGen 做原型的老手这篇文章都适合你。我会先讲清楚微软多智能体框架的设计哲学再给出一套可落地的实现路径最后用一个真实的自动化任务场景把从任务拆解到稳定性设计的完整链路串起来。1. 微软为什么要做多智能体框架先看清协作模式的地图很多人一听到多智能体系统就默认它一定比单 Agent 高级这其实是个误区。微软在 Agent Framework 的设计文档里反复强调一个观点Agent 是 Workflow 的超集而不是替代品。这句话是所有后续设计决策的起点。1.1 多智能体系统真正要解决的三类问题我自己的体会是多智能体架构不是用来炫技的它只适合解决三类问题。第一类是任务复杂度过高。单个 Agent 如果既要理解用户意图、又要检索知识库、还要调用业务系统、最后还要生成结构化报表你很快就会把提示词写成一个几千字的巨无霸。Prompt 越长模型的注意力越分散出错率越高。把不同职责拆成不同 Agent每个 Agent 只维护自己领域的 Prompt 和工具复杂度就从一个巨型系统变成了几个小系统加上一套路由逻辑。第二类是上下文窗口的限制。即使现在模型上下文已经到了百万 token 级别在实际业务中你也不可能把所有内容都塞进去。多 Agent 的天然优势是每个 Agent 只接收与自己相关的上下文比如搜索 Agent 只接收搜索指令和结果摘要审核 Agent 只接收格式化之后的结论。这让 token 使用效率高了一个量级。第三类是工具域与权限的隔离。一个系统里经常同时存在内部 API、外部服务、数据库、文件系统这些不同敏感级别的资源。单 Agent 模式下一个越权工具调用可能把整个链路带崩。多 Agent 模式下每个 Agent 的工具箱是独立配置的权限边界清晰审计也容易做——出了问题能精确到是哪个 Agent 在哪一步调的哪个工具。1.2 Workflow、Agent 与 GraphMAF 的设计取舍微软这套框架最核心的设计决策是把 Workflow 和 Agent 统一在同一个抽象里Workflow 是显式定义的控制流Agent 是让模型在运行时决定控制流。两者各有适用场景。Workflow 适合流程固定、每一步做什么都明确的场景比如用户输入 - 数据清洗 - 格式校验 - 入库 - 返回结果。这种流程写成代码每一步都确定延迟可控成本可预测。Agent 模式则适合路由逻辑会频繁变化的场景比如根据用户意图决定调用哪个专业 Agent这种意图判断用代码硬编码会非常脆弱交给语义路由反而更稳。微软在这套框架里同时提供了两种模式并且在底层用 Actor 模型支撑 Agent 之间的消息传递。每个 Agent 是一个独立执行单元有自己的状态机通过消息和其他 Agent 交互。这种设计带来的一个直接好处是同一个 Agent 可以同时被 Workflow 调用也可以被另一个 Agent 动态唤起不需要为两种模式写两套逻辑。1.3 什么场景才值得上多智能体聊完原理我直接给一份该用/不该用的清单这是我被同事问过无数次之后的总结。如果满足以下任一条件不建议上多智能体任务本身是单步调用比如把这段文本翻译成英文。调用链固定不变所有用户请求走完全相同的路径。对延迟极其敏感每增加一个 Agent 节点就增加一次模型往返。团队还处于单 Agent Prompt 都调不明白的阶段。反过来如果出现这些信号就该考虑多智能体Prompt 已经超过一千行而且还在继续膨胀。同一个模型调用里塞了多个互相冲突的角色指令。你需要把工具按权限域拆分不同角色只能访问特定资源。系统里有明显的分工诉求比如先采集再清洗再分析再生成报告。我个人判断的标准很简单如果单个 Agent 的错误率可以通过拆分子任务显著下降就值得拆如果只是把同样的复杂度从一个 Prompt 搬到了十个 Prompt那就不值得。后者正是很多团队踩坑的地方——拆完之后提示词总量反而更多了系统更不稳定了。2. 围绕 Microsoft Agent Framework 搭建系统的核心步骤明确完设计哲学接下来进入实操层面。先交代一个关键点微软的多智能体生态里目前有几套东西容易混淆我先把它们的关系理清楚。2.1 MAF、Semantic Kernel、AutoGen 的边界很多人在社区里问微软出了 Agent Framework 是不是 Semantic Kernel 就不用了这其实是个误解。根据我自己的实践三者的关系是这样Semantic Kernel 定位在单 Agent 的能力层负责模型接入、Prompt 模板、Function Calling、记忆这些基础能力AutoGen 的 GroupChat 模式解决的是多 Agent 对话编排而新出的 Agent Framework简称 MAF更像一个运行时协调层把 Agent 的创建、注册、消息路由、状态管理、生命周期统一起来。举个类比Semantic Kernel 是发动机AutoGen 是变速箱MAF 是整个底盘和控制系统。发动机决定动力上限变速箱决定动力怎么分配底盘决定整辆车怎么开、怎么转向、怎么在不同路况下保持稳定。所以你在 MAF 里写的 Agent底层完全可以依赖 Semantic Kernel 提供的模型 Abstraction 和工具调用能力两者是互补关系不是替代关系。2.2 Agent 建模名称、描述、工具与状态的最小完备集在开始写任何业务逻辑之前先想清楚你系统中的每个 Agent 需要哪四个要素Name、Description、Tools、State。Name 和 Description 的作用很多人低估了。在语义路由模式下路由 Agent 是根据其他 Agent 的 Description 来决定把任务转给谁的。Description 写得含糊路由准确率就直接下降。我见过最典型的反例是把描述写成负责处理用户请求这种描述等于没写。正确的写法是负责处理用户退款申请输入为订单号和退款原因输出为退款审核结构体依赖订单系统 Agent 验证订单状态。Tools 是 Agent 的能力边界。MAF 的设计里每个 Agent 有独立的 Tool 注册表这意味着你可以精确控制某个 Agent 能调用哪些函数。我强烈建议一开始就把工具的读写权限分清楚数据采集 Agent 只挂只读工具订单处理 Agent 才能挂写入工具。State 是经常被忽视的一块。Agent 不是无状态的尤其是跨多轮任务的时候每个 Agent 需要维护自己的状态。MAF 里每个 Agent 是独立的 Actor状态默认隔离只有通过显式消息进行传递。2.3 工作流装配把 Agent 注册进 Workflow这里我基于 MAF 的设计模式整理了一个核心的代码骨架。实际 API 细节可能随版本迭代但思想是一致的。from agent_framework import Agent, Workflow, AgentChatMessage class SearchAgent(Agent): 搜索任务执行 Agent def __init__(self, name: str, description: str, context): super().__init__(namename, descriptiondescription, contextcontext) async def add_to_workflow(self, wf: Workflow): # 把当前 Agent 的消息处理函数注册到工作流 self._delegate_to_workflow(wf, self._handle_task, AgentChatMessage) return self async def _handle_task(self, message: AgentChatMessage): # 1. 从消息中解析任务参数 # 2. 调用自己的工具执行搜索 # 3. 返回带结果的消息 pass # 创建 Workflow 并装配 Agent wf Workflow() wf.add_agent(SearchAgent( namesearch_agent, description执行必应搜索并返回结构化结果列表输入为关键词输出为标题、链接、摘要。, contextcontext )) wf.add_agent(ParseAgent( nameparse_agent, description解析搜索结果页面内容抽取正文关键信息输出为 Markdown 格式摘要。, contextcontext )) wf.add_agent(ReportAgent( namereport_agent, description汇总解析结果并生成最终报告输出为 JSON 结构。, contextcontext ))这个骨架的核心思想是Agent 之间不直接互相调用方法而是通过向 Workflow 发送消息由 Workflow 根据消息类型和内容路由给对应能力的 Agent。这样做的好处是职责收口出问题的时候只需要查消息流就能定位。2.4 语义路由让模型决定谁干活如果流程固定上面的 Workflow 装配已经够了。但实际业务里经常出现要根据用户意图动态决定走哪个子流程的情况这时候就需要语义路由。语义路由的基本逻辑是把每个 Agent 的 Description 转换成向量或者直接作为候选给模型让模型根据当前任务内容匹配最合适的 Agent。微软的做法是把语义路由组件内建在 Agent 基类中每个 Agent 都可以通过add_action_to_workflow注册自己的行为路由层自动完成匹配。我实践中的经验是语义路由的准确率高度依赖 Description 的质量。建议给每个 Agent 的 Description 至少写清楚三要素输入格式、处理方式、输出格式。比如接收一段 Python 代码使用静态分析工具检查潜在 bug输出问题列表及严重等级这种描述路由准确率就会高很多。另外一个技巧是给路由加一个兜底 Agent。当所有候选 Agent 的匹配度都不超过阈值时不直接报错而是进入一个兜底 Agent它会把任务重新拆解、尝试换一种表达方式重新路由或者请求人工介入。这套机制能显著提升系统的鲁棒性。2.5 底层模型与上下文策略Agent 框架本身不绑定具体模型你可以在不同 Agent 上用不同模型。我的建议是高频、简单、延迟敏感的任务用小模型低频、复杂、需要推理的任务用大模型。比如在浏览器自动化的场景里拆分任务和调度路由用大模型保证准确率但具体的判断页面是否加载完成提取某个元素的文本这种操作完全不需要大模型用规则和 Playwright 选择器就够了。混合模型策略能把成本压到纯大模型方案的十分之一左右。上下文策略方面每个 Agent 的消息队列不能无限膨胀。我的做法是给每个 Agent 设置一个消息保留窗口比如最近 5 轮交互记录更早的压缩成摘要存到记忆里。这既保证了长期任务的连续性又避免了 token 浪费。3. 多智能体在浏览器自动化任务中的落地以必应搜索自动任务为例理论讲完用实际场景串一遍。最近社区里很多人讨论自动化脚本处理浏览器任务这类场景我就用它来演示多智能体的设计思路。先说清楚这里的重点不是教你刷指标而是展示一个真实的、需要分治的浏览器自动化任务该怎么拆成多智能体系统。3.1 场景拆解一个浏览器自动化任务涉及的子环节假如你需要做一个浏览器自动化任务比如每天定时用必应搜索若干关键词、打开结果页、阅读内容并完成任务打卡。这类任务看似简单但如果用单脚本硬写你会发现要处理的事情相当多。拆开来看至少包含这些子任务管理浏览器配置和登录态、根据关键词列表发起搜索、判断搜索结果页是否正常加载、处理可能的弹窗验证、保存搜索结果、对结果内容做摘要分析、最后把执行状态汇总成报告。这些子任务的逻辑彼此独立但又有数据依赖关系。这正是多智能体擅长的场景。3.2 Coordinator-Crawler-Writer 三 Agent 分工我在这类任务里用的拓扑结构是经典的中心化协调模式三个 Agent 各有分工。Coordinator Agent协调者是整个任务的大脑。它读取任务配置文件把关键词列表拆成小批次逐批下发执行指令收集结果判定是否重试最后生成汇总报告。它自身不执行任何搜索动作。Crawler Agent采集者是执行层。它只做一件事接收一个搜索关键词打开必应搜索结果页提取结果列表。内部包含固定的浏览器控制逻辑和一个短 Prompt用于过滤无关广告结果。执行完后返回结构化的搜索结果。Writer Agent记录者负责结果落盘。它把 Crawler 返回的结构化结果转换成统一的 JSON 行格式写入本地文件或数据库在积累到一定数量后生成 Markdown 摘要报告。三个 Agent 之间只有 Coordinator 能主动发起消息Crawler 和 Writer 完成后必须回传状态。这个设计的好处是任何一步出错Coordinator 都可以单独重试不会影响其他 Agent 的状态。3.3 稳定性设计重试、校验与人工确认浏览器自动化最大的敌人是环境不确定性页面改版、网络超时、验证码弹出随便一个都能让脚本中断。多智能体系统在这方面的优势是可以在不同层级做容错。我在这个项目里设计了三层容错机制。第一层是工具级重试爬取失败时Crawler 自带的重试逻辑换个等待时间重新加载页面最多 3 次。第二层是消息级重试Coordinator 收到超时或不完整结果时把同一个任务换一种表达方式重新下发给 Crawler。第三层是链路级降级如果连续失败超过 5 次Coordinator 不再盲目重试而是进入人工确认流程通过通知接口发送提醒等待人工确认后再继续。三层容错搭下来整个任务的完成率从最初的不到 60% 提升到了 95% 以上。这里的关键不是每一层有多强而是错误不会从一层直接穿透到任务整体失败。4. 系统设计中最容易翻车的细节状态、记忆与容错把系统搭起来只是第一步。我在实际运行中踩过不少坑这几类是最常见的。4.1 Agent 之间共享状态时的并发陷阱多智能体系统里Agent 是并发运行的。如果你在多个 Agent 之间共享同一个可变状态对象比如一个全局字典用来保存中间结果很容易出现数据竞争问题。我踩过的一个具体坑是Coordinator 下发任务后立即读取结果文件但 Crawler 还在写入过程中导致读到半个 JSON。后面我强制规定Agent 之间不直接共享内存对象一切数据传递走消息通道结果落盘由 Writer 统一负责Coordinator 只能通过 Writer 的消息确认来感知数据是否就绪。这个约束看似损失了效率实际上让系统稳定了一个量级。并发带来的隐形 bug 排查成本远超那一点性能收益。4.2 工作流和 Agent 混用时的上下文丢失问题MAF 允许你同时使用 Workflow 和 Agent 模式但混用的时候要小心上下文丢失。我遇到过一个问题任务从一个 Workflow 步骤进入 Agent 模式后Agent 完成处理返回 Workflow 时Workflow 之前累积的上下文变量被重置了后续步骤拿不到前置结果。排查了很久才发现问题出在 Workflow 的状态管理器没有和 Agent 的状态管理器打通。解决办法是在设计阶段就明确状态归属Workflow 的上下文变量只存流程级参数Agent 的业务数据走独立的状态通道两者不混用。凡是需要跨环节传递的数据统一放在消息负载里不依赖框架的隐式状态传递。4.3 可观测性设计多 Agent 排障的唯一抓手多智能体系统最让人头疼的事情是排障。几个 Agent 互相发送消息一旦某个环节逻辑判断错误错误会被下游 Agent 当成有效输入继续处理最后产出一个完全错误的结果你很难倒推是哪一步出的问题。我对自己的项目做了一个强制要求所有 Agent 的入站消息和出站消息必须结构化记录包括消息类型、来自哪个 Agent、发往哪个 Agent、耗时、当时的工具调用列表。字段统一格式之后灌入日志系统。有了这个消息日志排障的效率完全不一样。比如任务结果不对直接按任务 ID 拉出整条消息链路看哪一步传递的数据发生了偏移基本几分钟就能定位。没有这套日志多 Agent 系统就是一个黑箱出了错只能碰运气。4.4 成本爆炸的预防多 Agent 系统的 token 消耗是单 Agent 的很多倍因为一次任务要从协调者到执行者来好几个来回。如果每个 Agent 都配大模型一个简单任务的成本可能翻 5 倍以上。我的成本控制三板斧一是 Agent 分级配模型简单代理用小模型复杂代理用大模型二是消息长度控制Agent 之间只传必要字段不把完整上下文反复转发三是路由预算Coordinator 路由失败时先尝试语义压缩而不是无条件重试。有一次我发现某个生产任务成本突然飙升查日志发现是语义路由连续 8 次匹配失败每次都触发兜底 Agent 走了一次大模型调用。后来给路由加了一个熔断机制连续失败 3 次直接进入人工确认流程成本立刻回归正常。5. 个人实测后的几条经验总结多智能体系统设计是一套组合拳框架只是基础设施真正决定系统质量的是你对任务的理解程度。我已经在这套架构上持续迭代了几个月分享几条实打实的经验。第一先做减法再做加法。不要一开始就设计六个 Agent我建议先把一个 Agent 跑通完整流程再逐步拆分。你会发现很多需要拆的想法实际上是Prompt 没写好拆开之后反而引入了不必要的通信开销。第二给每个 Agent 写清楚边界。Description 不是给人看的是给模型看的。写的时候幻想一下如果我只把这个描述给一个完全不知道上下文的大模型它能不能准确地把任务路由过来不能就继续改。第三多 Agent 系统不是银弹它只是把单点复杂度变成了协作复杂度。如果你连单 Agent 的稳定性都没调明白就先别上多 Agent。分布式系统的第一课永远是分布式不会让系统更可靠它只是让系统能够在不同的失败模式下继续运行。第四日志和追踪系统要提前做不要等出了问题再补。我见过太多项目初期觉得日志系统浪费人力上线三个月后遇到一个幽灵 bug花了整整一周才定位——那周的时间足够把日志系统做三遍。如果你现在正好在往上多智能体系统的路上我建议你把这篇文章提到的协作拓扑和状态管理优先级提到模型选择前面。模型可以随时换拓扑和状态设计一旦定型返工成本可能远比你预想的高。

相关新闻