ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

企业级多Agent系统设计:三类角色协作与工程落地全解析

企业级多Agent系统设计:三类角色协作与工程落地全解析 项目标题“企业级 Agent 系统设计”拿到手我先给你交个底这不是又要讲一遍“怎么调 Prompt、怎么接大模型 API”的入门文章。真正做过企业内部智能体落地的人都知道单个 Agent 在 Demo 里跑通是起步放到生产环境里能扛住并发、不出乱子、出了乱子能查清责任这才是核心。本篇就围绕一个支持三种角色的多 Agent 协作系统拆解我实际推进这类项目时的设计思路、踩坑记录和可复用的工程方案。不管你是技术负责人、架构师还是正在做 Agent 应用开发的工程师这篇内容都能帮你少走几周弯路。1. 为什么企业级 Agent 需要三类角色而不是一个“超级 Agent”1.1 一个超级 Agent 的幻想与现实很多人一开始会想与其搞三个 Agent 互相通信不如把推理、调用工具、检查结果的能力全部塞进一个 Agent 里让它自己闭环。这个想法在实验室里完全可行但在企业级场景里几乎必翻车。原因不复杂。企业环境里任务的复杂度往往是“广度”大于“深度”——一个真实任务可能横跨客户数据查询、订单状态变更、邮件通知、财务对账四个系统而且每一步都要理解不同的业务语义。你让一个 Agent 从头管到尾它的上下文窗口很快会被塞满前面处理过的结论会被后面新引入的信息冲淡最后要么答非所问要么干脆“一本正经地胡说八道”。我在项目里见过最典型的一个翻车现场让单 Agent 处理批量退款请求它前面的确能正确调用退款接口但处理到第 20 条时因为上下文里积压了太多订单记录和日志它突然“忘了”自己在批量退款转而开始回答客户咨询问题。这个问题不是模型能力不够而是职责过载导致的状态混乱。所以企业级系统第一步不是选模型而是拆分职责。1.2 三类角色的职责边界在这个系统里我把 Agent 分成三种角色类型执行 AgentWorker、编排 AgentOrchestrator、质检 AgentInspector。执行 Agent负责具体干活比如查数据库、调API、生成文档、发消息。它只接受已经被分解好的、边界清晰的任务单元不承担决策职责。编排 Agent负责拆解目标、分配任务、汇总结果。它是“包工头”拿到一个模糊的上级意图后把它转化为可执行的子任务队列并决定任务之间的依赖顺序。质检 Agent负责验收结果。执行 Agent 交付的东西先过它这一关校验格式、校验业务规则、校验是否满足原始诉求不合格就退回重做。这个分工看起来简单但它解决了一个非常关键的问题每一类 Agent 的能力都可以被独立测试和优化。执行 Agent 只需要保证“给定明确指令时执行得准确”编排 Agent 只需要保证“拆解的步骤能覆盖原意并且顺序合理”质检 Agent 只需要保证“验收标准不被漏判”。出了问题你能很快定位是哪个环节的薄弱点而不是对着一个黑盒干瞪眼。1.3 职责分区带来的工程红利用表格能更清楚地说明三类 Agent 的设计差异。维度执行 Agent编排 Agent质检 Agent核心能力工具调用准确率、信息提取完整性任务拆解、依赖规划、目标理解规则引擎、交叉验证、标准制定输入单一明确的任务单元模糊的业务目标执行结果 原始任务单输出结构化结果、工具调用记录子任务 DAG有向无环图通过/驳回 修改意见失败处理重试或上报异常动态调整任务队列打回并附理由可测试性高单任务可覆盖中依赖 LLM 推理质量高规则可枚举这个对比表在我做项目评审时帮了大忙因为老板和技术团队都能一眼看明白每类 Agent 的关注点是什么、该怎么验收。以前总有人说“Agent 系统上线了不知道怎么测”其实你只要把角色拆开每个角色的测试标准是能明确写出来的。这比在一个单体智能体里“靠感觉测”要靠谱得多。2. 协作机制设计让三个 Agent 真正“协作”而不只是“堆积”2.1 通信协议任务单比自然语言聊天更可靠多 Agent 之间最忌讳的直接拿自然语言对话跟人一样你一言我一语聊着聊着就跑偏了。企业级系统必须在一开始就定义清楚的**任务单Task Ticket**通信协议。任务单是一个结构化的 JSON 对象包含几个关键字段task_id全局唯一任务编号用来串联后续所有日志和结果。intent原始诉求描述由用户或上游系统传入整个流转过程中不可修改。context_refs上下文引用指向共享记忆中的具体片段 ID而不是直接拷贝大段文本。constraints必须遵守的硬性约束比如“金额必须精确到分”“日期格式固定为 ISO8601”。expected_output_schema期望输出结构的 JSON Schema执行 Agent 必须按这个结构返回。为什么不用自然语言对话因为自然语言有大量省略和指代A Agent 说一句“把刚才那个订单取消掉”B Agent 根本不知道“刚才”是多久之前、“那个订单”指的是哪个。任务单用字段把歧义全部消掉A 只需要说“订单号 20241118-088 状态改为已取消”B 不需要猜。这个设计参考了实际项目中“接口文档先于代码”的实践数据契约写清楚了后面所有环节都顺。2.2 记忆与上下文私有记忆和共享记忆必须分开记忆设计是我踩坑最多的地方。一开始我把所有对话记录、任务结果都塞进一个向量库三个 Agent 共享读写结果很快就乱了。执行 Agent 查自己的历史操作时会检索到编排 Agent 的思考过程上下文被严重污染回答质量直线下降。后来的方案是分层记忆架构私有记忆每个 Agent 实例独享存自己的历史任务、踩坑经验、常用工具用法。其他 Agent 不可读。共享记忆存任务单、业务事实、跨 Agent 流转的中间产物。所有 Agent 可读但写入需要经过质检 Agent 审核防止垃圾信息沉淀。消息总线日志所有 Agent 之间的通信都留痕按 trace_id 可以回溯完整链路但不参与实时推理。这个设计可以类比团队协作每个成员都有自己的笔记本私有记忆开会时共享的投影白板共享记忆所有会议记录有专人存档消息总线日志。你不希望张三拿起李四的笔记本看也不希望有人在白板上乱涂不被发现。2.3 编排与调度DAG 比流程引擎更灵活但要防死锁编排 Agent 拆解完任务后产出的不是一条线性队列而是一个DAG有向无环图。这个选择是经过考量的真实业务流程往往不是“做完 A 再做 B”而是“A 和 B 可以并行但 C 必须等 A、B 都完成”。DAG 天然支持并行而且可以用拓扑排序决定执行顺序。我用networkx或graphviz来建模和可视化这个 DAG编排 Agent 每拆解一步就动态加节点执行 Agent 完成一个节点就标记完成。系统里有一个调度器负责监控哪些节点已就绪、哪些节点正在运行、哪些节点因为依赖阻塞。这里有个关键坑动态加节点时一定要做循环检测。有一次编排 Agent 在生成节点时因为目标理解偏差给任务 A 添加了一个依赖任务 B 的边而 B 本身又依赖 A整个队列瞬间死锁所有执行 Agent 停在原地等待。后来我在调度器里强制了每新增一条依赖边就做一次环检测检测不过就拒绝并让编排 Agent 重新规划这个死锁问题就再没出现过。3. 系统架构落地从逻辑设计到工程实现3.1 分层架构控制流与数据流分离这个系统不能做成“三个 Agent 互相直连”的网状结构否则系统复杂度会随 Agent 数量指数上升。我采用的是分层架构核心原则是控制流和数据流分离。系统从上到下分为四层接入层接收用户请求鉴权、限流生成任务单交给编排层。编排层运行编排 Agent负责任务拆解、DAG 构建、节点调度、状态管理。执行层运行执行 Agent根据任务单调用具体工具产出结构化结果。质检层运行质检 Agent对执行结果做校验、评分决定放行或打回。数据流走共享记忆和消息总线控制流走调度器两层之间没有交叉依赖。这样做的最大好处是你可以单独替换任何一层而不影响其他层。比如后来我们把执行 Agent 的底层模型从 A 换成 B只需要改执行层的调用配置编排层和质检层完全不动。这在单体智能体架构里是做不到的只要换模型整个系统都要重新测。3.2 消息队列与并发控制多实例跑起来不打架企业级系统一定会有并发不能假设每个时刻只有一个任务在跑。我引入消息队列RabbitMQ / Kafka来当 Agent 之间的“信箱”每种任务类型一个队列执行 Agent 实例从队列里取任务处理完发到结果队列。并发控制这块有一个需要重点注意的问题同一业务实体的多任务冲突。比如两个执行 Agent 同时处理同一批库存数据的更新A 先把库存改成 50B 又把它改回 80最后数据莫名其妙变了。这属于典型的并发写冲突。解决方案是两层防护在任务单里声明资源锁比如resource_lock: order_20241118_088调度器保证同一资源的任务永远不会并行执行。在数据库层面用乐观锁更新时校验版本号冲突则退回重做。我见过不少团队忽略这个问题等到上线后数据对不上了才开始补补的过程非常痛苦。这个坑没必要踩设计阶段就规划好资源锁成本低收益高。3.3 工具层与权限Agent 调 API 比人调 API 更需要管控执行 Agent 干活靠的是工具层也就是封装的 API、数据库操作、文件读写能力。这一层的设计直接决定系统能不能过企业安全审计。我的经验是不要给 Agent 开放裸数据库连接也不要让它直接调内部系统的原始 API。每个工具都应该封装成“一问一答”的格式输入输出都有严格的 Schema 校验并且在上层加两道控制权限控制编排 Agent 在生成任务单时会检查执行 Agent 是否有调用该工具的权限。权限矩阵写在配置文件里Agent 本身没有资格改自己的权限。审计日志工具层记录每一次调用的入参、出参、调用者 Agent ID、发起时间、耗时。这不仅是安全要求也是后面排查故障的关键线索。有一个真实教训早期系统里执行 Agent 可以直接调“批量删除客户数据”的工具虽然单个任务没问题但有一次编排 Agent 拆任务时把这个工具拆进了错误的分支导致了一批测试数据的误删。后来我把所有“危险操作”类工具都加了二次确认机制——执行 Agent 调用时质检 Agent 必须先行审批审批通过才真正执行。这种“设计上防御错误”的思路比事后补救要有效得多。4. 核心流程实操从任务下发到结果回收4.1 一个完整任务的生命周期下面用一个具体场景走一遍完整流程。假设有个业务目标“统计上个月所有高价值客户的订单总额并生成一份周报发给管理层。”第一步用户把目标提交到接入层系统生成任务单{ task_id: Task-20241118-001, intent: 统计上个月高价值客户订单总额生成周报并发送管理层, constraints: [高价值客户定义为年消费超过50万的客户, 统计范围是上月1日到上月最后一日], expected_output_schema: report_markdown send_log }第二步编排 Agent 拿到任务单开始拆解 DAG节点 1从 CRM 系统查询高价值客户列表无依赖节点 2从订单系统查询这些客户的订单记录依赖节点 1节点 3汇总计算订单总额生成周报 Markdown依赖节点 2节点 4发送邮件给管理层依赖节点 3这四个节点里节点 1 和节点 2 是串行依赖节点 3 和节点 4 也是串行依赖但整体是个线性链没有并行空间。如果业务复杂一些比如还要同时查退款数据那节点 2 和查退款的节点就能并行。4.2 各角色 Agent 的实际处理逻辑执行 Agent 处理节点 1 时它会这么做读取任务单中的 constraints识别出“高价值客户”的业务定义然后调用 CRM 查询工具。工具层执行 SQL 查询返回结果后执行 Agent 将结果压缩为结构化摘要写回共享记忆并在任务单上标记“节点 1 完成”。编排 Agent 监测到节点 1 完成后将节点 2 的状态改为“可执行”调度器把它投递到执行队列。这里有一个我后来才加上的重要设计执行 Agent 每次只处理一个节点的任务不跨节点。这个约束一开始看起来是浪费好像不够“智能”但它保证了每个节点的输出都能被独立验证一旦出问题能精准定位到具体步骤。质检 Agent 的介入时机是每个节点完成后。执行 Agent 交回来的结果质检 Agent 会做三件事字段完整性校验expected_output_schema 里要求的字段是否都存在。业务规则校验比如“订单总额是否没有负数”、“客户 ID 是否在刚才查出的列表内”。语义合理性校验LLM 生成的内容是否和原始意图一致有没有答非所问。任何一项不通过质检 Agent 就会生成一个“驳回 修改意见”的结果发回给对应的执行 Agent附带错误清单。执行 Agent 根据修改意见纠正后重新提交。这个循环默认最多三次超过三次就需要人工介入——这个兜底非常重要否则系统会在一个问题里空转。4.3 状态机设计别用 if-else 管理 Agent 状态任务单在不同 Agent 之间流转状态变化需要一个清晰的状态机来管理。我用了enum 状态转换表的方式而不是散落的 if-else 判断。状态流转如下PENDING(待处理) → IN_PROGRESS(执行中) → REVIEWING(质检中) → APPROVED(已通过) ↓ (失败) REJECTED(已驳回) → IN_PROGRESS(重新执行)每个状态变更都必须记录操作者 Agent、时间戳、变更原因写入消息总线日志。这样在任何时间点你都能回答三个问题这个任务现在在哪个环节、是谁处理的、处理了多少次。我见过有的团队没做状态机全靠执行 Agent 在结果字段里写“完成”或“失败”时间一长日志根本没法看。状态机和任务单是配套的没有状态机的任务单就只是一张“便签”起不到管理作用。4.4 结果回收与置信度评估最后一个环节是结果回收。质检 Agent 通过后结果会被写入结果库同时有一个置信度评分——这是后来进一步完善时加的我认为是企业级系统必须有的能力。置信度包含几个维度执行成功节点的比例质检第一次通过率是否有过驳回和修改记录整个流程是否有过人工介入评分低于阈值的结果不会自动发送给下游而是进入“人工复核队列”。这样设计是为了防止“所有环节都跑通了但最终结果其实不准确”的情况。比如执行 Agent 查错了数据源但质检 Agent 的规则校验没有覆盖到数据源合法性如果直接自动发送周报那后果不堪设想。置信度评估机制相当于给整个系统加了一道“安全气囊”。5. 常见问题与排查技巧实录5.1 Agent 之间互相“甩锅”错误归因难多 Agent 系统上线后第一个头疼的问题就是出了错A Agent 说是 B Agent 给的输入有问题B Agent 说是 C Agent 的任务拆得不对C Agent 又说是 A Agent 执行得不行。这个问题没办法靠“开会讨论”解决工程上的解法是全链路 TraceID。项目一开始就要约定同一个任务单从生成到结束所有日志、工具调用、Agent 回复都必须携带同一个 TraceID。排查问题时用 TraceID 一把梭导出一条完整的日志链按时间顺序看每个环节到底发生了什么事。另外一个实践经验是每个 Agent 的输出都要附带“依据段”。执行 Agent 返回结果时除了结果本身还要附上“这个结果是从哪份数据、哪个工具、哪个时间点得到的”。质检 Agent 驳回时也要附上“基于哪条规则驳回”。这样无论怎么甩锅最后都能查到源头是哪一行代码、哪一条记录。5.2 上下文污染共享记忆里混入了错误信息共享记忆是把双刃剑用得好是团队协作白板用不好就是垃圾堆。最常见的故障是执行 Agent A 在完成节点时向共享记忆写了一条“客户 12345 是 VIP”但这条信息其实是错的后面的执行 Agent B 读到了这条信息基于这个错误前提做了进一步计算最终结果完全跑偏。治理方案有三个层次写入原子性任何 Agent 写入共享记忆前必须经过质检 Agent 的验证验证通过的才允许落库。来源追踪共享记忆每条记录都带source_agent_id和timestamp一旦发现错误信息能追溯到是谁写的同时把这条记录标记为废弃。独立信息版本当不同 Agent 对同一业务实体的描述不一致时系统不走“覆盖写”而是生成两个版本并存由编排 Agent 或人工判断哪个更可信。第三点是我后来从代码版本管理那里得到的启发——Agent 系统也一样共享记忆要能回滚。5.3 死循环和“看似在干活其实在空转”Agent 系统另一个常见故障是死循环任务被驳回后重新执行执行完又被驳回来回折腾十几次日志看过去一片繁忙但根本没有进展。我在前文提到过用“最多重试三次”兜底这里补充一个更精细的方案在任务单里加入动态预算字段。{ task_id: Task-20241118-001, budget: { max_retries: 3, max_execution_seconds: 300, max_tool_calls: 20 } }每一次重试和每一次工具调用都会扣减预算预算耗尽无论结果如何都强制转入“人工处理”。和人的工作量考核一样干活的资源有限不能无限重来。这个机制看上去很朴素但它真正挡住了很多“难以预料的边缘情况”。另外我还会监控一个指标叫“有效进展轨迹”——每次重新执行的新结果和上一次结果之间的差异变化。如果连续两次修改意见完全相同说明执行 Agent 根本没有理解问题这时候就不再自动重试了直接要求人工介入。5.4 并发冲突分布式锁与幂等设计前面提到过资源锁解决并发更新冲突这里再说一个更容易被忽略的点幂等性。执行 Agent 在调用工具时如果因为网络超时导致工具调用结果未知它会选择重试。但如果这个工具不是幂等的——比如“创建订单”“发送邮件”——重试就会造成重复创建或重复发送。我在工具层强制要求所有写操作必须支持幂等键执行 Agent 每次调用时携带任务 ID 作为幂等键工具层去重。其实这就是分布系统里的经典问题延伸到 Agent 系统里依然成立。别因为是“AI 应用”就忽略了这些基础工程能力Agent 本质上还是软件系统基础功不扎实一样会翻车。5.5 质检 Agent 的“过度严防死守”最后一个问题来自内部一开始质量要求高是好事但质检 Agent 如果设置得太严格就会把大量本可以放行的结果打回重做整个系统吞吐量大幅下降。这其实是精度和召回的权衡。我的做法是质检 Agent 不做“一刀切”而是把校验分成两个级别硬性校验格式错误、字段缺失、业务规则冲突这些必须打回。软性校验表达不精确、可读性不高、建议优化这些只记录提醒不强制打回。硬性校验不通过结果不能进入下一环软性校验不通过结果正常流转但会记录到该执行 Agent 的长期评估表里作为后续调整模型参数的依据。加了这一层之后系统整体的吞吐和人类判断的“可接受范围”更匹配了。写在最后的经验总结这个三角色多 Agent 系统我从概念设计到落地迭代最深的三点体会分享给正在做同类项目的人。第一角色边界比模型能力强弱更重要。三个通用模型各自守住职责边界比一个“万能 Agent”什么都管要稳定得多。设计系统时先画清角色职责和通信协议然后再选模型、调 Prompt顺序反过来会陷入无穷无尽的修补。第二可观测性要从第一天建起。多 Agent 系统的调试难度不是线性增长而是指数增长TraceID、状态机、审计日志这些能力必须在第一个版本就存在不要等到出事了再补。补的成本很高而且你永远不知道前面有多少错误信息已经污染了共享记忆。第三不要为了多 Agent 而多 Agent。如果你的业务目标一个 Agent 就能干好别硬拆成三个。角色拆分是为了解决复杂度和可靠性的问题不是为了在简历上多一行“多 Agent 系统经验”。如果业务场景是简单的问答、单步查询一个 Agent 加一层工具调用足够了。最后再分享一个扩展思路这套三角色架构不是定死的你可以根据业务需要在执行 Agent 下面再划分子类型比如“数据查询 Agent”“内容生成 Agent”“邮件发送 Agent”它们都遵循同一个执行 Agent 接口。扩展角色类型、新增能力都不需要改动系统骨架这才叫一个能真正用于企业级环境的架构。
返回列表