首页 / 资讯中心 / 文章详情

多智能体协作系统Agency Agents:编排层架构与落地实践

多智能体协作系统Agency Agents:编排层架构与落地实践 ★ FEATURED ARTICLE
1. 从一个人扛所有到一群Agent各司其职这套协作系统到底在解决什么如果你带过三人以上的开发团队大概率经历过这种场面需求评审时大家点头如捣蒜真到排期落地前端等后端接口、后端等数据库设计、测试等前后端联调一条链路上任何一环卡住整条线就停摆。更麻烦的是很多决策散落在不同人的脑子里没人说得清这个字段当初为什么这么设计。Agency Agents 这套多智能体协作系统本质上就是把上面这套人类团队协作的痛点搬到软件系统里用一组职责明确的智能体Agent来模拟一个开发团队的运转方式。它不是那种一个大模型包打天下的方案而是把需求分析、架构设计、编码实现、测试验证、代码审查这些环节拆开每个环节交给一个专门的 Agent再通过一套调度机制把它们串起来。我第一次接触这类系统的时候直觉反应是这不就是把 prompt 拆成几段分别调用吗。但真正跑起来才发现难点根本不在单个 Agent 的能力而在于它们之间怎么传递上下文、怎么处理冲突、怎么在某个环节失败时优雅降级。这跟带团队是一模一样的道理——单兵作战能力强的人凑在一起如果没有好的协作机制产出可能还不如一个中等水平但配合默契的小组。这篇文章适合三类人看一是正在做 AI 应用落地、想把单点能力扩展成流水线的开发者二是对多智能体架构感兴趣、想搞清楚编排层到底在做什么的技术负责人三是单纯好奇AI 团队协作这件事到底靠不靠谱的从业者。我会从架构分层、Agent 角色设计、上下文传递、冲突消解、落地踩坑几个角度把这套系统拆开讲透尽量给到可以直接参考复现的细节。需要先说明一点多智能体协作目前还没有标准答案不同团队的实现差异很大。下面讲到的很多设计选择是基于我在实际项目中反复试错后总结出的常见实践不代表唯一正确路径但至少是踩过坑之后相对稳的那条路。2. 编排层才是真正的核心Agency Agents 的分层架构拆解2.1 为什么不能把所有逻辑塞进一个 Agent很多人做多智能体第一步就走偏了把系统提示词写得巨长试图让一个 Agent 同时干需求分析、写代码、做测试。结果就是它在每个环节都表现平平而且一旦某一步出错你根本不知道是哪段逻辑出了问题。Agency Agents 的做法是分层解耦。整个系统大致分成四层从下往上依次是层级职责典型组件模型接入层统一封装不同模型的调用、重试、限流模型适配器、Token 计数器Agent 能力层定义单个 Agent 的角色、工具、输出格式角色定义、工具绑定、输出解析器编排调度层决定谁先谁后、任务怎么分发、结果怎么汇总调度器、状态机、消息总线应用接口层对外暴露 API、Webhook、可视化面板任务提交接口、进度查询、日志这个分层最大的好处是每一层可以独立替换。比如你今天用某个模型明天想换另一个只需要改模型接入层今天用线性流程明天想改成带反馈回路的流程只需要改编排调度层Agent 本身的定义不用动。我见过不少项目把调用哪个模型硬编码在 Agent 逻辑里结果想换个模型要改十几个文件这就是分层没做好的典型症状。2.2 编排调度层的三种常见形态编排层是整个系统的大脑它的设计直接决定了系统的灵活性和复杂度。实践中主要有三种形态复杂度依次递增第一种是线性流水线Pipeline。需求 Agent 输出交给架构 Agent架构 Agent 输出交给编码 Agent一路往下。优点是简单、可预测、好调试缺点是没有任何反馈前面错了后面只能跟着错。适合流程固定、容错要求不高的场景。第二种是带反馈的状态机State Machine。每个 Agent 完成后调度器根据输出质量决定是继续下一步还是打回上一步重做。比如测试 Agent 发现代码有 bug就把任务退回给编码 Agent并附上失败原因。这种形态能显著提升最终产出质量但需要设计好状态转移条件和最大重试次数否则容易陷入死循环。第三种是黑板模式Blackboard。所有 Agent 共享一块黑板通常是结构化的共享内存或数据库每个 Agent 读取自己需要的信息、写入自己的产出调度器根据黑板上的状态决定激活哪个 Agent。这种模式最灵活适合任务边界模糊、需要多个 Agent 反复协作的场景但实现复杂度也最高调试起来相当痛苦。我的建议是从线性流水线起步跑通之后再逐步引入反馈。一上来就上黑板模式大概率会在调试阶段耗光耐心。2.3 状态管理被低估的记忆问题多智能体系统里状态管理是最容易被忽视、又最容易出问题的地方。每个 Agent 执行时都需要知道之前发生了什么这个之前包括原始需求是什么、上一个 Agent 产出了什么、有没有失败记录、当前是第几次重试。常见的做法是维护一个任务上下文对象Task Context结构大致如下{ task_id: task-20240101-001, original_requirement: 用户原始需求文本, current_stage: coding, retry_count: 1, artifacts: { requirement_spec: 需求分析产出, architecture_doc: 架构设计产出, code_files: [file1.py, file2.py], test_report: null }, history: [ {agent: requirement_agent, status: success, timestamp: ...}, {agent: coding_agent, status: failed, reason: ...} ] }这个对象在每次 Agent 调用时被传入Agent 执行完再把更新后的版本写回。关键点在于不是所有历史都要塞给每个 Agent。给编码 Agent 传需求文档和架构文档就够了把测试报告也塞进去只会浪费 Token 还干扰判断。所以上下文需要做按需裁剪这也是编排层的一个重要职责。提示上下文裁剪策略建议做成可配置的不同 Agent 配置不同的可见字段。硬编码裁剪逻辑后期改起来会很痛苦。3. 角色设计每个 Agent 该配什么人设和工具箱3.1 角色定义的三要素职责、输入、输出一个 Agent 的定义本质上就是回答三个问题它负责什么、它需要什么、它产出什么。这三要素必须写得极其明确含糊一点都会导致协作出问题。以需求分析 Agent 为例它的定义大致是这样职责把用户模糊的自然语言需求拆解成结构化的功能点列表标注优先级和依赖关系。输入用户原始需求文本、可选的业务背景说明。输出固定格式的 JSON包含功能点数组每个功能点有 id、描述、优先级、依赖项。这里有个关键经验输出格式一定要强制结构化。如果你让 Agent 自由发挥输出一段文字下游 Agent 解析起来会非常痛苦而且容易解析失败。用 JSON Schema 约束输出配合模型的结构化输出能力稳定性会高很多。我踩过的一个坑是早期让架构 Agent 输出 Markdown 格式的设计文档结果编码 Agent 解析时经常把标题层级搞错导致模块划分混乱。后来改成 JSON 描述模块和接口问题立刻消失。3.2 工具绑定给 Agent 装上手光有大脑没有手Agent 只能纸上谈兵。工具绑定就是给 Agent 装上能实际操作的手。常见的工具包括文件读写工具让编码 Agent 能真正创建、修改文件。命令执行工具让测试 Agent 能跑测试命令、看结果。检索工具让所有 Agent 能查文档、查历史代码。代码分析工具让审查 Agent 能做静态检查。工具绑定的原则是最小权限。编码 Agent 需要写文件权限但需求 Agent 完全不需要测试 Agent 需要执行命令但最好限制在测试命令白名单内。权限给太大一个 Agent 出错可能污染整个工作区。# 工具注册的简化示意 agent_tools { requirement_agent: [read_file, search_docs], coding_agent: [read_file, write_file, search_docs], test_agent: [read_file, run_command], review_agent: [read_file, static_analyze] }3.3 角色之间的接口契约多智能体协作最容易出问题的地方就是角色之间的接口没定义清楚。A Agent 以为输出的是列表B Agent 以为收到的是字典一跑就崩。解决办法是给每对相邻的 Agent 定义明确的接口契约上游输出什么结构、下游期望什么结构、字段含义是什么、必填还是选填。这个契约最好用代码里的数据类dataclass或 Schema 固化下来而不是靠文档约定。上游 Agent下游 Agent传递字段格式要求需求 Agent架构 Agent功能点列表JSON 数组每项含 id/desc/priority架构 Agent编码 Agent模块与接口定义JSON含 modules 和 interfaces编码 Agent测试 Agent文件路径列表字符串数组测试 Agent审查 Agent测试报告JSON含 passed/failed/errors这张表看起来简单但真正落地时很多团队就是缺了这么一张表导致联调阶段反复扯皮。4. 上下文如何在 Agent 之间流转而不失真4.1 信息衰减为什么传着传着就变味了多智能体系统有个隐蔽但致命的问题信息在传递过程中会衰减。原始需求里一句要支持批量操作传到架构 Agent 变成支持批量接口传到编码 Agent 变成实现一个批量方法传到测试 Agent 可能就只剩测试批量功能——具体批量多少条、要不要分页、失败怎么处理全丢了。这跟人类团队里传话游戏是一个道理。解决办法有两个方向一是关键信息不靠传递靠共享。把原始需求、核心约束放在共享上下文里每个 Agent 都能直接读到原文而不是读上游的转述。这样即使中间环节有损耗源头信息始终在。二是传递时附带不可省略字段。在接口契约里明确规定哪些字段必须原样传递、不允许改写。比如需求 ID、约束条件、验收标准这些字段在每一跳都必须保留。4.2 上下文窗口的取舍策略上下文窗口是有限资源不可能把所有历史都塞进去。实践中我总结了一个优先级排序原始需求永远保留这是宪法。当前阶段的直接输入必须保留。最近一次失败的原因如果处于重试状态必须保留。更早的历史产出按需保留能摘要就摘要。无关 Agent 的产出直接丢弃。具体操作上可以给每个 Agent 配置一个上下文模板明确它能看到哪些字段。这样既控制了 Token 消耗又避免了信息干扰。注意不要用把历史全部摘要成一段话这种偷懒做法。摘要会丢失细节而很多 bug 恰恰藏在细节里。宁可精确裁剪不要粗暴摘要。4.3 失败重试时的上下文处理重试是最考验上下文设计的场景。当测试 Agent 发现 bug 打回给编码 Agent 时编码 Agent 需要知道上次写了什么、这次哪里错了、错误信息是什么。如果只是简单地把测试失败四个字传回去编码 Agent 根本不知道该改什么。正确的做法是传递结构化的失败信息{ retry_reason: test_failure, failed_cases: [ {case: 批量插入1000条, error: 超时, expected: 5s, actual: 12s} ], previous_code_ref: commit-abc123, suggestion: 考虑分批提交或加索引 }有了这些信息编码 Agent 才能有针对性地修改而不是盲目重写。这也是为什么我一直强调失败信息要结构化——它是重试能否成功的关键。5. 冲突消解当两个 Agent 意见不一致时听谁的5.1 冲突的三种典型来源多智能体系统里Agent 之间产生冲突是常态不是异常。常见的冲突来源有三类第一类是目标冲突。架构 Agent 追求设计优雅、扩展性好编码 Agent 追求快速实现、少写代码两者天然有张力。架构 Agent 说这里要抽象一个接口层编码 Agent 觉得直接写死不就完了。第二类是事实冲突。两个 Agent 对同一个事实的判断不一致。比如需求 Agent 认为用户要的是 A 功能架构 Agent 理解成用户要的是 B 功能。第三类是资源冲突。多个 Agent 想同时修改同一个文件或者都想占用同一个工具资源。5.2 优先级裁决机制解决冲突最直接的办法是预设优先级。在系统设计阶段就明确当架构 Agent 和编码 Agent 意见不一致时以架构 Agent 为准当需求 Agent 和架构 Agent 冲突时以需求 Agent 为准因为需求是源头。这个优先级链本质上是谁更接近原始需求谁的话语权更大。听起来简单但落地时必须写进调度逻辑里不能靠希望它们自己协商。冲突类型裁决规则兜底方案需求 vs 架构需求优先人工介入架构 vs 编码架构优先记录分歧人工复核编码 vs 测试测试优先有 bug 就得改重试上限后人工介入任意 vs 审查审查优先质量红线人工介入5.3 引入仲裁 Agent的时机当冲突频繁发生、且优先级规则无法覆盖时可以考虑引入一个专门的仲裁 Agent。它的职责是读取冲突双方的论据结合原始需求做出裁决。但我要泼盆冷水仲裁 Agent 不是万能药。它本身也是模型也会犯错而且引入它会让系统复杂度再上一个台阶。我的经验是只有当冲突模式稳定、可枚举时才值得引入仲裁如果冲突五花八门不如老老实实加人工介入点。一个折中方案是让仲裁 Agent 只做分类不做裁决。它判断冲突属于哪一类然后按预设规则处理处理不了的才升级给人工。这样既降低了仲裁的难度又保留了灵活性。6. 落地实录从 Demo 到稳定运行踩过的五个坑6.1 坑一Agent 输出格式不稳定最开始跑 Demo 时编码 Agent 十次里有三次输出的 JSON 解析失败——要么多了个逗号要么字段名拼错要么干脆输出了一段解释文字。下游 Agent 直接崩。根因模型的结构化输出能力不是 100% 可靠的尤其是输出内容较长时。解决三层防护。第一层用模型原生的结构化输出能力如 JSON mode第二层加输出校验和自动修复比如用 JSON 修复库第三层解析失败时自动重试并在重试提示里附上上次输出格式错误的说明。三层下来解析成功率从 70% 提到了 99% 以上。6.2 坑二无限重试烧光预算有一次测试 Agent 和编码 Agent 陷入了改-测-改-测的死循环一晚上跑了上百轮Token 消耗直接爆表。根因没有设置重试上限而且失败原因没有收敛——每次都是同一个 bug 换个说法。解决设置双重上限。一是单个任务的最大重试次数比如 3 次二是整个任务的最大 Token 预算。任一超限就终止并转人工。另外重试时要检测失败原因是否重复如果连续两次失败原因相同说明 Agent 卡住了直接终止。6.3 坑三上下文越传越乱跑到后期编码 Agent 收到的上下文里混进了大量无关信息导致它开始自由发挥改了一堆不该改的文件。根因上下文裁剪策略太粗糙把历史产出全塞进去了。解决给每个 Agent 定义精确的可见字段白名单白名单之外的字段一律不传。同时给上下文加版本号确保 Agent 读到的是最新版本避免读到过期数据。6.4 坑四工具调用权限失控测试 Agent 有一次执行了一条删除命令把工作区里的文件删了。根因命令执行工具没有做白名单限制Agent 可以执行任意命令。解决所有工具调用走白名单 沙箱。命令执行只允许特定前缀如pytest、npm test文件操作限制在指定目录内。这个坑的教训是永远不要相信 Agent 会自觉权限必须从系统层面卡死。6.5 坑五日志缺失导致无法复盘系统跑挂了几次但因为没有详细日志根本不知道是哪一步出的问题只能重跑浪费大量时间。解决给每个 Agent 的每次调用都记录完整日志输入上下文、输出内容、耗时、Token 消耗、工具调用记录、状态转移。日志按 task_id 聚合出问题时能完整回放整个执行链路。这个投入在后期排查问题时回报巨大。7. 性能与成本多智能体系统的现实账本7.1 Token 消耗的构成分析多智能体系统的成本主要来自 Token 消耗。它的构成和单 Agent 系统很不一样重复上下文消耗每个 Agent 都要读一遍原始需求这部分是重复的。传递消耗Agent 之间的产出传递本身也是 Token。重试消耗失败重试会成倍放大消耗。工具调用消耗检索、分析类工具也会消耗 Token。实测下来一个五 Agent 的流水线完成一个中等复杂度任务Token 消耗大约是单 Agent 方案的 3 到 5 倍。这个账要提前算清楚别等账单出来才后悔。7.2 降低成本的四个实操手段手段一模型分级。不是所有 Agent 都需要用最强的模型。需求分析和架构设计用强模型格式转换、简单校验用轻量模型成本能降一大截。手段二上下文缓存。原始需求这类不变的内容可以用上下文缓存机制避免每次都重新计算。手段三并行化。没有依赖关系的 Agent 可以并行执行比如多个模块的编码可以同时进行缩短总耗时。手段四结果复用。相似任务的产出可以缓存复用比如同一类需求的架构设计模板。优化手段成本降幅实测实现难度模型分级30%-50%低上下文缓存15%-25%中并行化不降成本降耗时中结果复用20%-40%高7.3 延迟与吞吐的权衡多智能体系统天然比单 Agent 慢因为要串行经过多个环节。如果对延迟敏感可以考虑把非关键环节如审查做成异步把可以并行的环节并行对简单任务走快速通道跳过部分 Agent。但要注意不要为了降延迟牺牲质量。审查环节省掉短期看是快了长期看是技术债。8. 这套系统适合谁用以及我个人的几点体会多智能体协作系统不是银弹。它适合的场景是任务复杂度高、环节多、对产出质量有要求、且能接受较高成本。如果只是简单的单点任务用单 Agent 甚至直接调模型就够了上多智能体纯属杀鸡用牛刀。我在实际项目里最大的体会是这套系统的成败八成取决于编排层和接口契约的设计而不是单个 Agent 有多聪明。很多团队把精力全花在调 prompt 上结果协作机制一塌糊涂产出自然好不了。反过来即使单个 Agent 能力一般只要协作机制设计得好整体产出也能达到可用水平。另一个体会是人工介入点必须预留。不要指望系统全自动跑通所有任务在关键节点如架构定稿、最终验收设置人工确认既能保证质量又能在系统出错时及时止损。全自动听起来很美但真出了问题是灾难性的。最后分享一个实用技巧从最小的两 Agent 系统开始。先做需求 编码两个 Agent 的流水线跑通、跑稳再逐步加 Agent。一上来就搭五六个 Agent 的复杂系统调试成本会让你怀疑人生。多智能体这东西是长出来的不是设计出来的。
阅读完成 · 觉得有帮助?
咨询建站