多智能体协作框架agency-agents:架构设计与工程实践

发布时间:2026/10/24 7:27:58
多智能体协作框架agency-agents:架构设计与工程实践

1. 从"agency-agents"这个标题说起:一个多智能体协作框架的完整拆解

第一次看到"agency-agents"这个命名的时候,我的直觉是:这大概率是一个围绕"代理"和"代理机构"概念构建的多智能体协作系统。拆开来看,"agency"在软件语境里通常指代"代理机构"或"能动性",而"agents"则是"智能体"的复数形式。把这两个词拼在一起,指向的应该是一套让多个智能体像一家代理公司那样分工协作、各司其职的架构方案。

我之所以对这个方向特别感兴趣,是因为过去一年多我在实际项目里反复踩过一个坑:单个智能体再强,面对复杂任务时也会顾此失彼。你让它同时做需求分析、代码生成、测试验证、文档撰写,它往往在某个环节掉链子。而"agency-agents"这个思路,本质上是把一个大任务拆成多个角色,让每个智能体专注自己擅长的那一块,再通过一套协调机制把它们串起来。这就像一家广告公司里,客户经理、文案、设计师、媒介采购各管一摊,最后交付一个完整方案。

这篇文章适合谁看?如果你正在做多智能体系统的架构设计,或者你手头有一个复杂任务想用智能体来拆解,又或者你只是好奇"多个AI怎么协作"这件事到底怎么落地,那接下来的内容应该能给你一些可以直接抄作业的思路。我会从整体设计、核心角色拆解、协作机制实现、常见坑排查这几个维度,把"agency-agents"这类系统的骨架和血肉都讲清楚。

2. 整体架构设计:为什么是"代理机构"而不是"单打独斗"

2.1 核心设计思路与选型考量

"agency-agents"这类系统的核心设计哲学,用一句话概括就是:用组织架构的思维来组织智能体。传统单智能体方案是"一个全能选手干所有活",而代理机构模式是"一群专才各干各的,通过流程串联"。

我选择这种架构的理由很直接。第一,上下文窗口是有限资源。单个智能体如果既要记住需求文档,又要记住代码规范,还要记住测试用例,上下文很快就会被塞满,导致它在关键决策上"失忆"。拆成多个智能体后,每个智能体只需要关注自己那一块的上下文,信息密度更高,决策质量更稳。

第二,专业化提示词的效果远好于通用提示词。你给一个智能体写"你是一个资深全栈工程师"这种泛泛的角色设定,它的输出往往也是泛泛的。但如果你写"你是一个专门负责代码审查的智能体,只关注边界条件、异常处理和命名规范",它的输出会精准得多。代理机构模式天然支持这种专业化分工。

第三,可观测性和可调试性。单智能体出错时,你很难定位是哪一步推理出了问题。多智能体系统里,每个智能体的输入输出都是独立的,你可以清楚地看到"需求分析智能体给出的结论是A,但架构设计智能体理解成了B",问题定位效率提升一个量级。

在方案选型上,我倾向于采用**"协调者+执行者"的两层结构**。协调者负责接收原始任务、拆解子任务、分配角色、汇总结果;执行者负责各自领域的实际工作。这种结构比"扁平化对等协作"更容易控制,也比"纯流水线"更灵活。

2.2 角色划分的底层逻辑

角色划分不是拍脑袋决定的,它遵循一个原则:按任务阶段划分,而不是按技术栈划分。什么意思?不要设"前端智能体""后端智能体""数据库智能体",而要设"需求澄清智能体""方案设计智能体""实现智能体""验证智能体"。

原因在于,按技术栈划分会导致智能体之间的依赖关系变得极其复杂,前端要等后端接口,后端要等数据库设计,协调成本极高。而按阶段划分,每个阶段的输出是下一个阶段的输入,依赖关系是线性的,协调逻辑简单清晰。

一个典型的代理机构角色配置如下表:

角色名称核心职责输入输出
协调者任务拆解与调度原始需求子任务列表与分配方案
分析者需求澄清与边界定义子任务描述结构化需求文档
设计者方案设计与技术选型需求文档架构方案与接口定义
实现者代码/内容生成设计方案可运行产物
验证者质量检查与反馈产物+需求问题清单与修正建议
汇总者结果整合与交付各阶段产物最终交付物

这张表看起来简单,但实际落地时,每个角色的提示词设计、上下文管理、输出格式约束,都有大量细节要抠。

2.3 与单智能体方案的对比实测

我做过一个对比实验,用同一个任务(生成一个带增删改查的完整模块)分别跑单智能体和代理机构模式。单智能体模式下,首次生成能跑通的概率大概在四成左右,主要问题集中在边界条件遗漏和异常处理缺失。代理机构模式下,首次生成能跑通的概率提升到七成以上,而且代码的可读性和结构合理性明显更好。

代价是什么?Token消耗大约是单智能体的三到四倍,耗时大约是两到三倍。所以这不是一个"无脑选"的方案,而是一个"用成本换质量"的权衡。如果你的任务足够复杂,质量比速度重要,那代理机构模式值得上;如果只是简单任务,单智能体反而更划算。

注意:不要为了用多智能体而用多智能体。我见过不少项目,明明一个智能体就能搞定的事,硬拆成五个角色,结果协调开销比实际工作还大,得不偿失。

3. 核心角色拆解与提示词设计要点

3.1 协调者智能体:任务拆解的艺术

协调者是整个系统的入口,它的核心能力是把模糊需求拆成可执行的子任务。这里最大的坑是拆得太粗或太细。拆得太粗,执行者拿到任务后还是不知道从哪下手;拆得太细,子任务数量爆炸,协调开销剧增。

我的经验是,每个子任务的粒度控制在"一个执行者能在一次交互内完成"。具体来说,如果一个子任务的预期输出超过两千字或者超过两百行代码,就应该继续拆;如果少于两百字或者二十行代码,就应该合并。

协调者的提示词里必须包含几个关键约束。第一,明确输出格式,要求它输出结构化的子任务列表,每个子任务包含任务描述、预期输出、依赖关系。第二,明确拆解原则,比如"按阶段拆解而非按技术栈拆解""每个子任务必须有明确的验收标准"。第三,明确边界,告诉它哪些事情不在本次任务范围内,避免它过度发散。

一个实际可用的协调者提示词骨架大概是这样:

你是一个任务协调者。你的职责是将用户需求拆解为可独立执行的子任务。 拆解原则: 1. 按任务阶段拆解,不按技术栈拆解 2. 每个子任务必须能在一次交互内完成 3. 每个子任务必须有明确的输入和输出定义 4. 子任务之间的依赖关系必须显式声明 输出格式: - 子任务编号 - 任务描述(不超过100字) - 预期输出(具体产物形式) - 依赖的子任务编号(无依赖则写"无") - 验收标准(可验证的条件)

3.2 分析者与设计者:把"想要"翻译成"要做"

分析者和设计者是两个最容易混淆的角色。分析者负责搞清楚"用户到底要什么",设计者负责决定"我们怎么做"。这两个角色如果合并,很容易出现"还没搞清楚需求就开始设计"的问题。

分析者的核心任务是消除歧义。用户说"做一个用户管理功能",这句话里有大量歧义:用户有哪些字段?需不需要角色权限?要不要支持批量操作?分析者要做的就是把这些问题列出来,并给出合理的默认假设。注意,分析者不需要真的去问用户,而是基于常见实践给出假设,并明确标注"这是假设,如有不同请指出"。

设计者的核心任务是把需求翻译成技术方案。它需要决定用什么数据结构、什么接口形式、什么存储方案。这里的关键是设计者不能引入需求之外的东西。我见过设计者自作主张加了缓存层、加了消息队列,结果实现者一脸懵。所以设计者的提示词里要明确约束:"只设计需求文档中明确要求的功能,不添加额外特性。"

3.3 实现者与验证者:生成与检查的分离

实现者和验证者必须分离,这是代理机构模式里最重要的一条原则。让同一个智能体既生成又检查,它几乎永远检查不出自己的问题,因为它会倾向于认为自己的输出是对的。

实现者的提示词要强调"严格按设计方案实现,不自行发挥"。验证者的提示词则要强调"以需求文档为唯一标准,逐条核对,不放过任何偏差"。验证者的输出应该是一个问题清单,每个问题包含位置、问题描述、严重程度、修正建议。

这里有个实操技巧:验证者的提示词里要加入"对抗性思维"的引导。比如告诉它"你的任务是找出实现者可能犯的错误,假设实现者一定会遗漏边界条件"。这种引导能显著提升验证者的检出率。

3.4 汇总者:最后的把关人

汇总者负责把各阶段的产物整合成最终交付物。它的工作看似简单,实则不然。它需要处理各阶段产物之间的不一致,比如设计文档里说用A方案,但实现产物里用了B方案,汇总者要能发现并标记这种冲突。

汇总者的提示词要强调"一致性检查"。它需要逐项核对:需求文档里的每个需求点,在设计方案里有没有对应?设计方案里的每个设计点,在实现产物里有没有落地?实现产物里的每个功能,在验证报告里有没有被覆盖?

4. 协作机制实现:让智能体真正"对话"起来

4.1 消息传递与上下文管理

多智能体协作的底层是消息传递。每个智能体的输出作为下一个智能体的输入,形成一条消息链。这里最大的技术挑战是上下文膨胀。如果每个智能体都把前面所有智能体的完整输出作为输入,到第四个智能体时上下文就已经爆炸了。

我的解决方案是分层上下文。每个智能体只接收三类信息:自己的角色提示词、直接上游的输出、全局共享的"任务摘要"。任务摘要由协调者维护,只保留关键决策和约束,长度控制在五百字以内。

具体实现上,可以用一个共享的状态对象来管理:

class AgencyState: def __init__(self, original_task): self.original_task = original_task self.task_summary = "" # 协调者维护的全局摘要 self.subtasks = [] # 子任务列表 self.artifacts = {} # 各阶段产物,key为子任务编号 self.issues = [] # 验证者发现的问题 def get_context_for(self, agent_role, subtask_id): # 只返回该智能体需要的上下文 context = { "role": agent_role, "task_summary": self.task_summary, "upstream_output": self._get_upstream(subtask_id), "shared_constraints": self._get_constraints() } return context

这种设计的好处是,每个智能体看到的上下文都是精简且相关的,不会被无关信息干扰。

4.2 依赖调度与执行顺序

子任务之间有依赖关系,不能随便乱序执行。我用的是拓扑排序+并行执行的策略。先把子任务按依赖关系排成一个有向无环图,然后逐层执行:没有依赖的子任务并行跑,有依赖的等上游完成后再跑。

这里有个细节要注意:并行执行时,多个智能体可能同时修改共享状态。比如两个实现者同时往artifacts里写东西,可能冲突。解决办法是给每个子任务分配独立的命名空间,汇总时再合并。

调度逻辑的核心代码大概是这样:

def execute_agency(state): while state.has_pending_subtasks(): ready = state.get_ready_subtasks() # 依赖已满足的子任务 if not ready: raise Exception("检测到循环依赖") # 并行执行就绪的子任务 results = parallel_execute(ready, state) # 更新状态 for subtask_id, result in results.items(): state.artifacts[subtask_id] = result state.mark_completed(subtask_id) # 协调者更新任务摘要 state.task_summary = coordinator_update_summary(state)

4.3 反馈循环与迭代修正

代理机构模式不是一次性的流水线,而是带反馈循环的。验证者发现问题后,要把问题反馈给实现者,让实现者修正,然后再验证。这个循环要设置最大迭代次数,避免无限循环。

我的经验是,最大迭代次数设为三轮。第一轮通常能解决大部分明显问题,第二轮解决边界问题,第三轮如果还有问题,大概率是需求本身有歧义,应该退回给分析者而不是继续让实现者改。

反馈循环的提示词设计有个关键点:给实现者的反馈必须具体到可操作。不要说"代码质量不高",要说"第23行的异常处理没有覆盖空输入的情况,请补充"。验证者的输出格式要强制包含"位置+问题+建议"三要素。

4.4 状态持久化与断点续跑

多智能体系统跑起来耗时较长,中途可能因为各种原因中断。状态持久化是必须的。每完成一个子任务,就把状态序列化到磁盘。下次启动时,先检查有没有未完成的状态,有的话从断点继续。

持久化的粒度要权衡。太粗,中断后要重跑很多;太细,频繁写磁盘影响性能。我的做法是每个子任务完成后持久化一次,这个粒度刚好。

import json def save_state(state, path): with open(path, 'w') as f: json.dump({ "original_task": state.original_task, "task_summary": state.task_summary, "completed_subtasks": state.completed_subtasks, "artifacts": state.artifacts, "issues": state.issues }, f, ensure_ascii=False, indent=2) def load_state(path): with open(path, 'r') as f: data = json.load(f) state = AgencyState(data["original_task"]) state.task_summary = data["task_summary"] state.completed_subtasks = data["completed_subtasks"] state.artifacts = data["artifacts"] state.issues = data["issues"] return state

5. 实操过程与核心环节实现

5.1 环境准备与基础依赖

先把基础环境搭起来。我用的是Python 3.10以上版本,核心依赖包括一个支持结构化输出的模型调用库、一个用于状态管理的轻量级框架,以及一个用于并行执行的线程池工具。不需要太重的框架,代理机构模式的本质是"提示词编排+状态管理",用最朴素的工具反而更可控。

目录结构建议这样组织:

agency-agents/ ├── config/ │ ├── roles.yaml # 各角色的提示词配置 │ └── settings.yaml # 全局参数 ├── core/ │ ├── state.py # 状态管理 │ ├── scheduler.py # 调度逻辑 │ └── executor.py # 智能体执行器 ├── agents/ │ ├── coordinator.py # 协调者 │ ├── analyzer.py # 分析者 │ ├── designer.py # 设计者 │ ├── implementer.py # 实现者 │ └── verifier.py # 验证者 ├── runs/ # 运行状态持久化目录 └── main.py # 入口

把角色提示词放在配置文件里而不是硬编码在代码里,好处是调整提示词不需要改代码,方便快速迭代。

5.2 角色提示词的参数化配置

每个角色的提示词都应该是模板化的,支持注入动态参数。我用YAML来管理:

coordinator: system_prompt: | 你是一个任务协调者。你的职责是将用户需求拆解为可独立执行的子任务。 拆解原则: 1. 按任务阶段拆解,不按技术栈拆解 2. 每个子任务必须能在一次交互内完成 3. 每个子任务必须有明确的输入和输出定义 4. 子任务之间的依赖关系必须显式声明 当前任务摘要:{task_summary} 已完成子任务:{completed_subtasks} 请输出下一步的子任务拆解方案。 output_format: "json" max_retries: 3 verifier: system_prompt: | 你是一个质量验证者。你的任务是找出实现产物中与需求文档不符的地方。 验证原则: 1. 以需求文档为唯一标准 2. 逐条核对,不放过任何偏差 3. 假设实现者一定会遗漏边界条件 4. 每个问题必须包含位置、描述、严重程度、修正建议 需求文档:{requirements} 待验证产物:{artifact} 请输出问题清单。 output_format: "json" max_retries: 3

这种配置方式的好处是,你可以针对不同项目快速切换提示词模板,而不需要动核心代码。

5.3 完整执行流程的代码实现

把各个模块串起来的主流程大概是这样:

def run_agency(original_task, config_path): # 1. 加载配置 config = load_config(config_path) # 2. 初始化状态 state = AgencyState(original_task) # 3. 协调者拆解任务 subtasks = coordinator.decompose(original_task, config) state.subtasks = subtasks state.task_summary = coordinator.summarize(subtasks) # 4. 按依赖顺序执行 max_iterations = 3 iteration = 0 while state.has_pending_subtasks() and iteration < max_iterations: ready = state.get_ready_subtasks() for subtask in ready: # 根据子任务类型选择执行者 agent = select_agent(subtask.type, config) context = state.get_context_for(agent.role, subtask.id) result = agent.execute(context) # 如果是实现类任务,走验证流程 if subtask.type == "implementation": issues = verifier.check(result, state.artifacts["requirements"]) if issues: result = implementer.fix(result, issues) state.issues.extend(issues) state.artifacts[subtask.id] = result state.mark_completed(subtask.id) save_state(state, f"runs/{state.run_id}.json") iteration += 1 # 5. 汇总交付 final_output = summarizer.aggregate(state) return final_output

这段代码的核心逻辑是清晰的:拆解、调度、执行、验证、汇总。每个环节都有明确的输入输出,方便单独调试。

5.4 参数调优与性能实测

跑通之后就是调优。我实测下来,影响效果最大的三个参数是:子任务粒度、验证轮次、上下文摘要长度。

子任务粒度前面说过了,控制在"一次交互能完成"的量级。验证轮次我试过1轮、3轮、5轮,3轮是性价比最高的,5轮之后边际收益几乎为零。上下文摘要长度我试过200字、500字、1000字,500字左右效果最好,太短会丢失关键约束,太长会干扰智能体注意力。

性能方面,一个中等复杂度的任务(比如生成一个包含五个接口的模块),代理机构模式大约需要8到12次模型调用,总耗时3到5分钟,Token消耗在2万到4万之间。这个成本对于质量敏感的场景是可以接受的。

提示:如果你的模型调用有速率限制,记得在并行执行时加一个信号量控制并发数,否则容易触发限流导致任务失败。

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

6.1 子任务拆解不合理怎么办

这是最常见的问题。表现是:执行者拿到子任务后输出质量很差,或者输出内容明显偏离预期。排查思路是先看子任务描述是否足够具体。如果子任务描述只有一句话,比如"实现用户模块",那执行者只能靠猜,输出质量自然不稳定。

解决办法是在协调者的提示词里加入强制约束:每个子任务的描述必须包含"做什么、输入是什么、输出是什么、验收标准是什么"四个要素。缺一个就重新拆解。

另一个常见表现是子任务之间依赖关系混乱,出现循环依赖。这时候要检查协调者输出的依赖声明是否合理。我的经验是,依赖关系超过三层的子任务链,大概率是拆解粒度太细了,应该合并一些子任务。

6.2 验证者漏检问题怎么破

验证者漏检是另一个高频问题。表现是实现产物明明有问题,但验证者说"通过"。原因通常是验证者的提示词太温和,没有对抗性。

我的解决办法是在验证者提示词里加入**"红队思维"引导**:明确告诉它"你的绩效取决于你能找出多少问题,找不出问题就是失职"。同时给它一个检查清单模板,强制它逐项核对:边界条件、异常处理、输入校验、输出格式、命名规范、注释完整性。

还有一个技巧是让验证者分两轮检查。第一轮做"需求符合性检查",逐条核对需求文档;第二轮做"质量检查",检查代码规范、可读性、健壮性。两轮分开,检出率明显提升。

6.3 上下文丢失导致前后不一致

多智能体系统里,后面的智能体不知道前面的决策,导致前后不一致,这是很典型的问题。比如设计者决定用JSON格式传输,但实现者用了XML。

根因是上下文传递不完整。解决办法是强化任务摘要的维护。协调者每完成一个阶段,就要更新任务摘要,把关键决策记录进去。任务摘要要包含:已确定的技术选型、已定义的接口格式、已确认的约束条件。

我还会在状态对象里维护一个**"决策日志"**,记录每个关键决策是谁在什么时候做的。当出现不一致时,可以快速定位是哪个环节出了问题。

6.4 常见问题速查表

问题现象可能原因排查方向解决措施
执行者输出质量差子任务描述太模糊检查子任务四要素是否完整补充子任务描述,重新拆解
循环依赖拆解粒度过细检查依赖链层数合并子任务,减少依赖层级
验证者漏检提示词缺乏对抗性检查验证者提示词加入红队思维引导和检查清单
前后不一致上下文传递不完整检查任务摘要内容强化决策日志,更新摘要
任务超时并行度过高触发限流检查并发数设置加信号量控制并发
状态丢失持久化粒度太粗检查持久化时机每个子任务完成后持久化
Token消耗过大上下文膨胀检查每个智能体的输入精简上下文,只传必要信息

6.5 几个我踩过的坑

第一个坑是过早优化。一开始我就想搞一套复杂的消息总线,结果发现根本用不上,简单的函数调用就够了。多智能体系统的复杂度应该来自任务本身,而不是来自框架。

第二个坑是忽视输出格式约束。早期我没强制智能体输出JSON,结果它一会儿输出Markdown,一会儿输出纯文本,解析起来极其痛苦。后来强制所有智能体输出JSON,并在提示词里给出schema示例,问题就解决了。

第三个坑是没有设置超时和重试。模型调用偶尔会失败或返回空结果,没有重试机制的话整个流程就卡住了。后来我给每个智能体调用都加了超时和重试,稳定性大幅提升。

第四个坑是验证者和实现者用了同一个模型实例。虽然角色提示词不同,但同一个实例的"思维惯性"还是会影响判断。后来我把验证者换成独立的实例,检出率明显提高。

7. 扩展方向与个人实践体会

这套代理机构模式跑通之后,我发现它的扩展空间比想象中大。一个方向是引入更多专业角色,比如专门做性能优化的角色、专门做安全审查的角色。另一个方向是让角色之间支持协商,比如实现者觉得设计方案不合理时,可以发起一个"设计复议"流程,让设计者重新考虑。

还有一个我觉得很有价值的方向是把代理机构模式应用到非代码领域。比如内容创作,可以设"选题分析者""大纲设计者""初稿撰写者""事实核查者""润色者",本质上和代码生成是同一套逻辑。我试过用这套框架做长文写作,效果比单智能体好不少,尤其是事实核查环节,能抓出不少单智能体容易忽略的细节。

我个人在实际操作中的体会是,代理机构模式的价值不在于"智能体数量多",而在于"职责边界清晰"。一个职责边界清晰的三角色系统,效果往往好过一个职责模糊的七角色系统。所以如果你刚开始尝试,建议从三个角色起步:一个协调者、一个执行者、一个验证者。跑顺了再逐步增加角色。

最后再分享一个小技巧:给每个智能体的输出加一个"置信度"字段。让智能体自己评估对这次输出的把握程度,低于某个阈值时自动触发人工复核或重新执行。这个机制在实际使用中帮我拦下了不少潜在问题,尤其是需求分析阶段,分析者如果对某个假设的置信度很低,就说明这里需要人工介入澄清了。