ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

多智能体协作系统Agency Agents:架构设计与工程落地实践

多智能体协作系统Agency Agents:架构设计与工程落地实践

1. 从“一个人扛”到“一群Agent分工”:这个项目到底在解决什么问题

如果你带过稍微复杂一点的软件项目,一定经历过这种场面:需求文档刚定稿,前端在等接口,后端在等数据库设计,测试在等可运行版本,运维在等部署脚本。所有人都在等,所有人都在催,最后项目经理成了人肉消息总线。我过去几年里参与过好几个类似节奏的项目,最深的体会是——瓶颈往往不在某个技术难点上,而在“协作”本身。

Agency Agents这个项目,本质上就是冲着这个痛点去的。它不是又一个“让大模型帮你写代码”的玩具,而是一套多智能体协作系统:把不同职责的 AI Agent 组织成一个虚拟开发团队,让它们像真实团队一样分工、交接、评审、迭代。你可以把它理解成给一个开发团队装上了“自动驾驶”,但这个自动驾驶不是单车道巡航,而是多车道协同变道。

我第一次接触这个概念的时候,脑子里冒出来的问题是:单个 Agent 不是已经能写代码了吗,为什么还要搞多个?后来自己动手搭了一版原型才明白,单个 Agent 的问题在于“上下文过载”和“角色混淆”。你让它同时当产品经理、架构师、程序员和测试,它会在不同思维模式之间反复横跳,最后产出的东西四不像。而多智能体协作的核心价值,就是把复杂任务拆解成职责边界清晰的子任务,每个 Agent 只在自己的专业范围内工作,通过结构化协议交接。

这套系统适合谁来参考?我认为有三类人值得花时间研究:一是正在做 AI 应用落地的开发者,尤其是想把 LLM 能力嵌入到实际工程流程里的;二是技术团队负责人,想了解如何用 Agent 辅助团队提效的;三是对多智能体系统架构感兴趣、想自己动手搭一套的学习者。哪怕你暂时不打算落地,光是理解它的协作协议设计,对日常的团队协作也有启发。

接下来我会从架构设计、核心机制、实操落地和踩坑经验四个维度,把Agency Agents这套东西拆开讲清楚。不是照本宣科地念文档,而是把我自己搭原型、调参数、修 bug 的过程和思考都摊开来说。

2. 架构拆解:多智能体协作系统的骨架是怎么搭起来的

2.1 为什么是“Agency”而不是“Swarm”

名字里用Agency而不是Swarm,这个选词本身就透露了设计哲学。Swarm(蜂群)强调的是去中心化的群体涌现,个体之间没有明确的层级和职责,靠简单规则产生复杂行为。而Agency强调的是代理性和职责委托——每个 Agent 是一个有明确职责边界的“代理”,它代表团队完成某类特定工作,并且对自己的产出负责。

这个区别在实际落地时非常关键。我试过用纯 Swarm 式的思路搭过一个代码生成系统,结果就是 Agent 之间互相“踢皮球”,或者同时修改同一个文件导致冲突。而Agency Agents采用的是有向协作图:每个 Agent 有明确的输入依赖和输出目标,协作关系是预先定义好的,不是自由涌现的。

具体来说,它的架构分三层:

  • 编排层(Orchestration Layer):负责接收顶层任务,拆解成子任务,分配给对应的 Agent,并管理整个工作流的生命周期。这一层相当于“项目经理”。
  • Agent 层(Agent Layer):每个 Agent 是一个独立的执行单元,封装了特定的角色提示词、工具集和输出格式约束。常见的角色包括需求分析师、架构设计师、编码工程师、代码评审员、测试工程师等。
  • 通信层(Communication Layer):定义 Agent 之间如何传递信息,包括任务描述、上下文、产出物和反馈。这一层是整个系统能否跑通的关键。

提示:很多人在搭多智能体系统时,把 80% 的精力花在写 Agent 的提示词上,只留 20% 给通信层。我的经验恰恰相反——通信协议设计不好,再聪明的 Agent 也会因为信息丢失或格式不匹配而产出垃圾。

2.2 编排层的任务拆解逻辑

编排层的核心工作是把一个模糊的顶层需求,变成一组可执行的子任务。这个过程我称之为“任务树展开”。举个例子,你给系统的输入是“做一个用户登录功能”,编排层需要把它展开成:

  1. 需求分析 Agent:输出登录功能的需求规格说明,包括输入输出、边界条件、异常场景。
  2. 架构设计 Agent:基于需求规格,输出接口定义、数据模型、依赖关系。
  3. 编码 Agent:基于接口定义和数据模型,生成具体代码。
  4. 评审 Agent:检查代码是否符合需求规格和架构约束。
  5. 测试 Agent:基于需求规格生成测试用例并执行。

这个展开过程不是一次性的,而是递归的。如果编码 Agent 发现接口定义有歧义,它可以向编排层发起“澄清请求”,编排层再调度架构设计 Agent 补充说明。这种递归澄清机制,是保证最终产出质量的关键。

我在实际搭建时发现,任务拆解的粒度控制是个难点。拆得太粗,单个 Agent 的上下文压力大,容易跑偏;拆得太细,Agent 之间的通信开销急剧上升,整体延迟变得不可接受。经过几轮调整,我总结出一个经验值:单个子任务的预期产出控制在 500 到 1500 字(或等价代码量)之间比较合适。低于 500 字,拆解收益抵不过通信成本;高于 1500 字,Agent 的注意力开始涣散。

2.3 Agent 的角色定义与边界约束

每个 Agent 的定义包含四个核心要素:

要素说明常见坑
角色提示词定义 Agent 的身份、职责、工作方式写得太泛,Agent 什么都想干
输入规范明确 Agent 需要接收哪些信息输入格式不固定,Agent 解析失败
输出规范明确 Agent 产出物的格式和内容要求输出太自由,下游 Agent 无法消费
工具集Agent 可以调用的外部工具工具权限过大,Agent 越权操作

角色提示词的写法我踩过不少坑。最开始我写的是“你是一个资深后端工程师,请根据需求编写代码”,结果 Agent 经常自作主张地修改需求或者跳过架构设计直接写代码。后来我改成更严格的约束式写法:

你是编码工程师 Agent,职责是根据架构设计文档生成代码实现。 约束: 1. 你只能修改 src/ 目录下的文件,不得修改 docs/ 和 config/ 目录。 2. 你必须严格按照接口定义文档中的签名实现,不得自行更改接口。 3. 如果发现接口定义有歧义,你必须输出 CLARIFICATION_REQUEST 而不是自行假设。 4. 你的输出必须包含:代码文件列表、每个文件的完整内容、实现说明。

这种约束式写法的好处是,Agent 的行为变得可预测。虽然看起来限制了它的“创造力”,但在工程场景下,可预测性比创造力重要得多。

2.4 通信层的协议设计

通信层我采用的是结构化消息 + 共享工作区的混合模式。结构化消息用于 Agent 之间的直接通信,共享工作区用于存放产出物。

结构化消息的格式我定义如下:

{ "message_id": "msg-001", "from_agent": "coding_agent", "to_agent": "review_agent", "message_type": "DELIVERABLE", "payload": { "task_id": "task-003", "artifacts": ["src/login.py", "src/auth.py"], "summary": "完成登录功能代码实现", "dependencies": ["docs/api_spec.md", "docs/data_model.md"] }, "timestamp": "2024-01-15T10:30:00Z" }

共享工作区则是一个文件系统目录,所有 Agent 都可以读写,但每个 Agent 有明确的读写权限。这种设计的好处是,Agent 之间不需要传递大段内容,只需要传递文件引用,减少了通信开销。

注意:共享工作区的并发写入是个大坑。我最初没有加锁机制,结果两个 Agent 同时修改同一个文件,后写入的覆盖了先写入的。后来引入了基于文件锁的简单并发控制,问题才解决。

3. 核心机制深度解析:让 Agent 团队真正跑起来的关键细节

3.1 上下文传递:怎么让下游 Agent 知道上游干了什么

多智能体系统最容易出问题的地方,就是上下文丢失。上游 Agent 做了决策 A,下游 Agent 不知道 A 的存在,基于自己的假设做了决策 B,最后两个决策冲突。

Agency Agents采用的方案是显式上下文链。每个任务节点在执行时,会生成一个上下文快照,包含:

  • 该任务的输入(来自上游的产出物引用)
  • 该任务的决策记录(为什么这么做,考虑了哪些备选方案)
  • 该任务的输出(产出物引用和摘要)

这个上下文快照会随着任务链传递,下游 Agent 在开始工作前,会先读取所有上游的上下文快照。我在实现时,把上下文快照做成了 Markdown 格式,方便 Agent 解析,也方便人工排查问题。

## 任务上下文快照 ### 任务 ID task-003 ### 上游依赖 - task-001: 需求规格说明 (docs/requirements.md) - task-002: 架构设计文档 (docs/architecture.md) ### 关键决策记录 - 决策:采用 JWT 作为会话令牌方案 - 理由:无状态、易于水平扩展、社区成熟 - 备选方案:Session + Redis(被否决,因为增加了有状态依赖) ### 本任务产出 - src/login.py - src/auth.py - docs/implementation_notes.md

这种显式上下文链的好处是,任何一个环节出问题,都可以沿着链条回溯,定位到具体是哪个决策导致的。我在调试时经常用这招,比看日志高效得多。

3.2 评审与反馈循环:怎么保证产出质量

多智能体系统如果只是单向流水线,质量是没有保障的。Agency Agents引入了评审-反馈循环:每个关键产出物都会经过至少一个独立 Agent 的评审,评审不通过则打回重做。

评审 Agent 的工作方式不是简单地“看一眼说好不好”,而是基于检查清单逐项核对。以代码评审为例,检查清单包括:

  • 接口实现是否与架构设计文档一致
  • 是否处理了需求规格中列出的所有异常场景
  • 是否有明显的安全漏洞(如 SQL 注入、硬编码密钥)
  • 代码风格是否符合项目规范
  • 是否有足够的注释和文档

每项检查的结果分为 PASS、FAIL、WARN 三档。FAIL 必须修复,WARN 建议修复。评审 Agent 的输出是一份结构化的评审报告,包含每项检查的结果和具体说明。

我实测下来,评审循环一般跑 1 到 3 轮就能收敛。第一轮通常会有较多 FAIL,主要是接口不一致和异常场景遗漏;第二轮基本只剩 WARN;第三轮就可以通过了。如果超过 3 轮还没收敛,说明上游的需求或架构设计有问题,需要回退到更早的环节重新处理。

3.3 工具调用与权限控制

Agent 要干活,离不开工具。Agency Agents里每个 Agent 可以调用的工具是预先配置的,遵循最小权限原则。

Agent 角色可用工具权限限制
需求分析文档读写、搜索只能写 docs/requirements/ 目录
架构设计文档读写、图表生成只能写 docs/architecture/ 目录
编码代码读写、终端执行只能写 src/ 目录,终端命令白名单
评审代码读取、文档读取只读,不能修改任何文件
测试代码读取、测试执行只能写 tests/ 目录,只能执行测试命令

这种权限控制看起来繁琐,但非常必要。我踩过的坑是:编码 Agent 在调试时,为了“快速修复”,直接修改了架构设计文档里的接口定义,导致后续所有 Agent 都基于错误的接口工作。加了权限控制后,这类问题就杜绝了。

提示:终端命令白名单要仔细设计。我最初只允许python和pytest,结果 Agent 想用pip install装依赖时被卡住了。后来加了一个受限的依赖安装通道,由编排层统一管理依赖变更。

3.4 失败重试与降级策略

Agent 执行失败是常态,不是异常。失败的原因可能有很多:LLM 调用超时、输出格式不符合规范、工具调用报错、上下文超出窗口限制等。Agency Agents对每种失败类型都有对应的处理策略。

  • 格式错误:自动重试,并在重试时附上格式错误的提示,通常 1 到 2 次就能修正。
  • 工具报错:记录错误信息,尝试替代方案,如果无替代方案则上报编排层。
  • 上下文超限:触发上下文压缩,保留关键决策和产出物引用,丢弃中间过程。
  • 逻辑死循环:设置最大迭代次数,超过后强制中断并上报。

我在实际运行中遇到最多的是格式错误和上下文超限。格式错误通过重试基本能解决;上下文超限则需要优化任务拆解粒度,把大任务拆得更细。

4. 实操落地:从零搭一套可运行的多智能体开发团队

4.1 环境准备与基础依赖

动手之前,先把基础环境搭好。我用的技术栈是 Python + 异步框架 + 文件系统工作区,没有引入太重的依赖。核心依赖如下:

pip install asyncio aiofiles pydantic pyyaml

如果你打算接入具体的 LLM 服务,还需要安装对应的 SDK。我这里不绑定特定厂商,用的是一个抽象的 LLM 接口层,方便切换。

目录结构我建议这样组织:

agency_agents/ ├── config/ │ ├── agents.yaml # Agent 角色定义 │ └── workflow.yaml # 工作流定义 ├── core/ │ ├── orchestrator.py # 编排层 │ ├── agent.py # Agent 基类 │ ├── message.py # 消息协议 │ └── workspace.py # 共享工作区 ├── agents/ │ ├── analyst.py # 需求分析 Agent │ ├── architect.py # 架构设计 Agent │ ├── coder.py # 编码 Agent │ ├── reviewer.py # 评审 Agent │ └── tester.py # 测试 Agent ├── workspace/ # 运行时工作区 │ ├── docs/ │ ├── src/ │ └── tests/ └── main.py # 入口

这个结构的好处是职责清晰,每个 Agent 的实现独立,方便单独调试和替换。

4.2 Agent 基类的设计与实现

所有 Agent 都继承自一个基类,基类负责处理通用的逻辑:消息收发、上下文加载、输出校验、错误处理。子类只需要实现具体的业务逻辑。

class BaseAgent: def __init__(self, config: AgentConfig, workspace: Workspace): self.name = config.name self.role_prompt = config.role_prompt self.input_spec = config.input_spec self.output_spec = config.output_spec self.tools = config.tools self.workspace = workspace async def execute(self, task: Task) -> AgentResult: context = await self.load_context(task) prompt = self.build_prompt(task, context) raw_output = await self.call_llm(prompt) validated = self.validate_output(raw_output) if not validated.success: return await self.retry_with_feedback(task, validated.error) artifacts = await self.persist_artifacts(validated.content) return AgentResult( task_id=task.id, artifacts=artifacts, context_snapshot=self.build_context_snapshot(task, validated) )

这个基类的关键设计点是validate_output和retry_with_feedback。输出校验不是简单的格式检查,而是基于output_spec做结构化校验。比如编码 Agent 的输出必须包含文件列表和每个文件的完整内容,缺一不可。

4.3 工作流配置与编排逻辑

工作流用 YAML 定义,编排层读取配置后构建任务图。

workflow: name: feature_development steps: - id: requirements agent: analyst inputs: [] outputs: [docs/requirements.md] - id: architecture agent: architect inputs: [docs/requirements.md] outputs: [docs/architecture.md] - id: implementation agent: coder inputs: [docs/requirements.md, docs/architecture.md] outputs: [src/] - id: review agent: reviewer inputs: [docs/requirements.md, docs/architecture.md, src/] outputs: [docs/review_report.md] on_fail: implementation - id: testing agent: tester inputs: [docs/requirements.md, src/] outputs: [tests/, docs/test_report.md] on_fail: implementation

编排层的核心逻辑是拓扑排序 + 条件跳转。正常情况下按顺序执行,遇到on_fail时跳回指定步骤重做。这里要注意防止无限循环,我设置了一个全局的最大重试次数(默认 5 次),超过后中断并输出当前状态。

4.4 一次完整的运行记录

我拿一个实际的小需求跑了一遍:给一个已有的用户管理系统增加“密码重置”功能。以下是运行记录的关键节点。

第一轮:需求分析

需求分析 Agent 输出了docs/requirements.md,包含功能描述、输入输出、异常场景。我检查后发现它遗漏了“重置链接过期”这个场景,手动补充后进入下一轮。

第二轮:架构设计

架构设计 Agent 输出了接口定义和数据模型。接口定义里有一个POST /api/password/reset-request和一个POST /api/password/reset-confirm。数据模型增加了一张password_reset_tokens表。这部分基本一次通过。

第三轮:编码实现

编码 Agent 生成了三个文件:src/password_reset.py、src/models.py(修改)、src/routes.py(修改)。运行后发现models.py的修改与原有代码有冲突,评审 Agent 标记为 FAIL。

第四轮:评审反馈与修复

评审报告指出两个问题:一是models.py中新增的字段没有加索引,二是routes.py中的错误处理不完整。编码 Agent 根据反馈修复后,第二轮评审通过。

第五轮:测试

测试 Agent 生成了 8 个测试用例,覆盖了正常流程和 5 个异常场景。执行后 7 个通过,1 个失败——失败的是“并发重置请求”场景,暴露了一个竞态条件。修复后全部通过。

整个流程跑下来,从需求到可运行代码,大约花了 40 分钟。如果人工做,保守估计也要半天。当然,这只是一个简单功能,复杂功能的收益比例会有所不同。

4.5 参数调优与性能考量

多智能体系统的性能瓶颈通常在 LLM 调用上。我做了几组对比实验,总结出几个调优方向:

调优项默认值建议值影响
单任务最大 token80004000-6000降低上下文压力,减少幻觉
评审重试次数32减少无效循环
并发 Agent 数12-3提升吞吐,但增加冲突概率
上下文快照保留全部最近 3 个减少 token 消耗

我实测下来,把单任务最大 token 从 8000 降到 5000,配合更细的任务拆解,整体成功率反而提升了。原因是 Agent 在上下文较短时,注意力更集中,输出质量更稳定。

5. 常见问题与排查技巧实录

5.1 Agent 输出格式不符合规范怎么办

这是最高频的问题。表现是 Agent 输出的内容无法被下游解析,比如要求输出 JSON 却输出了 Markdown,或者缺少必填字段。

排查思路分三步:第一,检查output_spec是否足够明确,有没有给出具体的格式示例;第二,检查提示词里有没有强调“必须严格按照格式输出”;第三,检查是不是上下文太长导致 Agent “忘记”了格式要求。

我的解决经验是:在提示词末尾重复一遍格式要求,并且给出一个完整的输出示例。这个简单的改动,让格式错误率下降了大约 70%。

5.2 Agent 之间互相“踢皮球”怎么破

表现是任务在几个 Agent 之间反复流转,始终无法收敛。根本原因通常是职责边界模糊,或者某个 Agent 的输出不满足下游要求但又无法自行修正。

解决办法是引入仲裁机制:当同一个任务被退回超过 2 次时,编排层介入,分析退回原因,要么调整任务拆解,要么指定一个 Agent 做最终决策。我在编排层加了一个简单的仲裁逻辑,效果立竿见影。

5.3 上下文超限的应急处理

当任务复杂到一定程度,上下文超限几乎不可避免。我的处理策略是分层压缩:

  • 第一层:丢弃中间过程的详细日志,只保留决策记录。
  • 第二层:将产出物内容替换为文件引用和摘要。
  • 第三层:如果还是超限,强制拆解任务,把当前任务一分为二。

注意:压缩上下文时一定要保留“决策记录”,这是后续排查问题的关键线索。我最初压缩时把决策记录也丢了,结果出问题后完全不知道 Agent 为什么做了某个选择。

5.4 常见问题速查表

问题现象可能原因排查方向解决措施
输出格式错误格式要求不明确检查 output_spec增加格式示例,末尾重复要求
任务反复退回职责边界模糊检查 Agent 定义引入仲裁机制,明确边界
上下文超限任务拆解过粗检查任务粒度细化拆解,分层压缩
工具调用失败权限不足或参数错误检查工具配置调整权限,增加参数校验
产出质量差提示词约束不足检查角色提示词改为约束式写法,增加检查清单
运行超时LLM 响应慢或死循环检查调用日志设置超时,限制最大迭代次数

5.5 几个我踩过的坑和对应的经验

第一个坑是过度依赖 Agent 的“智能”。我最初期望 Agent 能自己理解模糊需求,结果产出一塌糊涂。后来我明白,多智能体系统的前提是输入足够清晰。模糊的需求要先由人工澄清,再交给系统。

第二个坑是忽略人工介入点。完全自动化的流水线听起来很美,但实际上,关键决策点(如架构选型、接口定义)最好保留人工确认环节。我在架构设计之后加了一个人工确认步骤,整体返工率大幅下降。

第三个坑是没有版本控制。Agent 修改文件时如果不做版本管理,出问题后无法回滚。我后来把工作区接入了 Git,每次 Agent 产出后自动提交,出问题可以随时回退到任意版本。

第四个坑是测试用例覆盖不足。测试 Agent 生成的用例往往偏向正常流程,异常场景覆盖不够。我的做法是给测试 Agent 一个异常场景检查清单,强制它逐项覆盖。

6. 这套系统还能怎么扩展

跑通基础流程之后,我尝试了几个扩展方向,效果还不错。

第一个扩展是引入领域知识库。给每个 Agent 挂载一个向量数据库,存放项目相关的历史文档、代码规范、常见问题。Agent 在执行任务前先检索相关知识,产出质量有明显提升。尤其是编码 Agent,有了代码规范知识库后,生成的代码风格一致性好了很多。

第二个扩展是增加性能分析 Agent。在测试通过后,自动分析代码的复杂度、潜在性能瓶颈,并给出优化建议。这个 Agent 的产出不强制修改代码,而是作为参考报告输出。

第三个扩展是多项目并行。编排层支持同时管理多个项目的工作流,共享 Agent 池。这个扩展的难点在于资源隔离和优先级调度,我目前只做到了简单的队列管理,还没有做精细的优先级控制。

第四个扩展是人工反馈闭环。在关键节点增加人工评分入口,评分结果反馈给 Agent 作为后续任务的参考。这个机制还在试验阶段,初步效果是 Agent 会逐渐适应团队的偏好。

我个人在实际操作中的体会是,多智能体协作系统的价值不在于“替代人”,而在于“把人从重复性的协调工作中解放出来”。它最适合的场景是需求相对明确、流程相对标准化的开发任务。对于高度创新、需求模糊的场景,还是得靠人来主导。另外,这套系统的搭建和维护本身也需要投入,不是搭完就一劳永逸的,需要持续调优和迭代。如果你打算动手,建议从一个最小的闭环开始——比如只做“需求分析到代码生成”这一段,跑通之后再逐步扩展。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进