多智能体协作框架agency-agents拆解:从设计到落地的完整指南

发布时间:2026/10/26 11:34:13
多智能体协作框架agency-agents拆解:从设计到落地的完整指南

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

第一次看到"agency-agents"这个标题的时候,我脑子里蹦出来的第一个念头是:这大概率是一个围绕"代理"和"智能体"做文章的项目,而且从命名习惯来看,它多半不是单指某一个agent,而是一整套"agency"级别的体系——也就是说,它关注的不是单个智能体怎么跑,而是一群智能体怎么组织、怎么分工、怎么协作。

这个判断不是拍脑袋来的。做过智能体相关项目的人都知道,单个agent能做的事情其实很有限:给它一个prompt,它调用几个工具,返回一个结果,流程就结束了。但真实业务场景里,几乎没有哪个需求是"一问一答"就能解决的。比如你要做一个自动化的市场调研,需要有人负责搜集信息、有人负责清洗数据、有人负责分析、有人负责写报告、还有人负责审核。这一整套流程,靠一个agent硬扛,要么prompt长到爆炸,要么中途就开始胡言乱语。所以"agency"这个词才是关键——它暗示的是一种组织化的智能体架构。

我打算把这篇文章写成一份完整的项目拆解笔记,从设计思路、核心机制、实操落地到踩坑排查,全部摊开来讲。适合谁看?如果你正在做多智能体编排、任务自动化、或者想把自己手头的一堆脚本升级成"能自己干活的小团队",那这篇内容应该能帮你省下不少试错时间。如果你只是刚听说"智能体"这个词,也没关系,我会尽量用生活化的类比把每个概念讲清楚。

2. 项目整体设计与思路拆解

2.1 为什么是"agency"而不是"agent"

先把这个最核心的命名逻辑讲透。单个agent的架构,本质上是一个"感知-决策-执行"的循环:接收输入,思考下一步,调用工具,拿到结果,再思考,直到任务完成。这个模式在简单任务上很好用,但一旦任务复杂度上来,就会遇到三个绕不过去的坎。

第一个坎是上下文窗口的物理限制。一个agent要处理完整流程,就得把所有中间结果都塞进上下文里。搜集的资料、清洗后的数据、分析结论、草稿、修改意见……这些东西叠加起来,很容易就超出模型能承受的长度。一旦超了,要么截断丢信息,要么压缩丢细节,两种结果都很难受。

第二个坎是角色冲突。让同一个agent既当"创作者"又当"审核者",它在审核自己的产出时,往往会倾向于认为"我写得挺好",这就是所谓的自我评估偏差。人也是这样,自己写的方案自己审,很难挑出毛病。

第三个坎是错误传播。单agent流程里,如果中间某一步推理错了,后面所有步骤都会基于这个错误继续往下走,而且很难定位到底哪一步出的问题。

"agency"的思路就是针对这三点来的:把一个大任务拆成若干子任务,每个子任务交给专门的agent,agent之间通过明确的接口传递信息。这样一来,每个agent的上下文只需要装自己那部分内容,窗口压力小了;创作者和审核者分开,评估更客观;某一步出错,也能快速定位到具体是哪个agent的问题。

打个比方,单agent像是一个什么都干的自由职业者,多agent agency就像是一家小公司,有销售、有设计、有开发、有质检。公司不一定比自由职业者聪明,但处理复杂项目时,组织化的分工明显更稳。

2.2 核心架构选型:编排层与执行层分离

在具体实现上,这类项目通常会采用"编排层+执行层"的两层结构。这个选择背后有很实际的考量。

编排层负责的是"谁在什么时候做什么"。它维护整个任务的状态,决定下一步该唤醒哪个agent,处理agent之间的依赖关系。执行层则是每个具体的agent,它们只关心"我拿到输入,该怎么产出输出",不需要知道整个流程长什么样。

为什么要这么分?因为如果让每个agent都感知全局,那每个agent的prompt里都得塞进整个流程说明,维护起来是灾难——改一个环节,所有agent的prompt都要跟着改。分离之后,编排逻辑集中在一处,agent只需要定义好自己的输入输出契约,两边可以独立演进。

我见过不少项目一开始图省事,把所有逻辑写在一个大prompt里,前期跑得挺欢,等到要加一个新角色或者调整流程顺序时,就发现牵一发动全身,最后只能推倒重来。所以这个分层不是过度设计,而是被现实教育出来的经验。

2.3 通信机制:消息传递还是共享状态

agent之间怎么交换信息,是另一个关键决策点。主流有两种做法:一种是消息传递,agent A把结果打包成消息发给agent B;另一种是共享状态,所有agent读写同一个全局状态对象。

消息传递的好处是解耦彻底,每个agent只需要知道自己上游是谁、下游是谁,不关心别人怎么存数据。缺点是当流程变复杂、出现分支和循环时,消息的路由逻辑会变得很绕。

共享状态的好处是简单直接,任何agent都能拿到自己需要的那部分数据,适合流程复杂、数据被多方引用的场景。缺点是容易产生隐式依赖——某个agent偷偷改了状态里的某个字段,另一个agent莫名其妙就出错了,排查起来很痛苦。

我的建议是:如果流程是线性的、角色数量在五个以内,用消息传递更清爽;如果流程有大量分支、循环、或者需要多个agent反复读写同一批数据,共享状态更实用。很多成熟项目其实是混着用的——主干流程走消息传递,共享的上下文(比如原始需求、全局约束)放在一个只读的状态区里。

3. 核心细节解析与实操要点

3.1 Agent的角色定义:别让prompt变成流水账

定义每个agent的时候,最容易犯的错误是把prompt写成一份冗长的说明书。我见过一个agent的prompt写了三千多字,从项目背景讲到注意事项,结果模型执行时反而抓不住重点,经常漏掉关键约束。

正确的做法是让每个agent的prompt聚焦在三件事上:我是谁、我拿到什么、我要产出什么。角色描述要短而准,输入输出格式要明确到字段级别。至于项目背景这类信息,应该放在编排层统一注入,而不是每个agent都重复一遍。

举个例子,一个"信息搜集agent"的prompt可以这样写:

你是信息搜集专员。你会收到一个调研主题和一组关键词。 你的任务是针对每个关键词,产出3-5条关键信息点。 输出格式为JSON数组,每条包含:关键词、信息点、来源类型、可信度评分(1-5)。 不要做分析,不要下结论,只负责搜集和整理。

注意最后那句"不要做分析,不要下结论"——这是角色边界的硬约束。如果不写,模型很容易越界,把分析和搜集混在一起,导致下游的分析agent拿到的是已经被加工过的信息,失去了独立判断的基础。

3.2 任务拆解的粒度控制

任务拆多细,是个需要反复调的手感活。拆得太粗,单个agent还是扛不住;拆得太细,agent之间通信开销剧增,而且每个agent拿到的上下文太少,反而做不出好判断。

我的经验法则是:一个agent的职责,应该能用一句话说清楚,且这句话里不出现"并且"。如果发现某个agent的职责是"搜集信息并且做初步分析",那就说明该拆了。反过来,如果两个agent的职责高度重叠,只是输入格式略有不同,那就可以合并。

还有一个实操技巧:先按最粗的粒度跑通全流程,观察哪个环节的输出质量最差或者耗时最长,再针对性地拆那个环节。不要一上来就设计一个十几个agent的完美架构,那样调试成本高到你会想放弃。

3.3 上下文传递的裁剪策略

agent之间传递上下文时,最忌讳的是"全量转发"。上游agent产出的所有内容,不加筛选地塞给下游,会让下游的上下文迅速膨胀,而且引入大量无关信息干扰判断。

合理的做法是给每个agent定义明确的"输入契约",只接收它真正需要的字段。比如分析agent只需要搜集agent产出的"信息点"和"可信度评分",不需要知道每条信息是从哪个来源类型来的。这种裁剪在编排层完成,agent本身不需要关心。

提示:裁剪策略要写进编排层的配置里,而不是散落在各个agent的代码中。否则当你需要调整传递内容时,又得满项目找。

3.4 失败重试与降级机制

多agent系统里,某个agent失败是常态,不是异常。模型可能返回格式错误、可能超时、可能产出明显不合理的内容。如果每次失败都让整个流程崩掉,那这套系统根本没法用。

必须设计重试和降级。重试的策略通常是:格式错误就重新调用一次,并在prompt里强调格式要求;超时就缩短输入或者换更快的模型;内容不合理就触发一次"自我修正"调用,把问题反馈给同一个agent让它重做。

降级则是当重试多次仍失败时的兜底方案。比如分析agent连续失败,可以让编排层跳过分析环节,直接把原始信息交给报告agent,并在报告里标注"分析环节缺失"。这样至少能产出一个不完整但可用的结果,而不是彻底失败。

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

4.1 环境准备与依赖梳理

动手之前,先把依赖理清楚。这类项目通常需要三样东西:一个大模型调用接口、一个流程编排的运行时、以及一个存放中间状态的地方。

大模型接口这块,建议抽象成一个统一的client,把重试、超时、日志这些通用逻辑封装进去。不要在每个agent里各写一套调用代码,否则后面换模型或者调参数时会非常痛苦。

编排运行时,如果项目规模不大,用简单的状态机就够了,不需要上重型的工作流引擎。状态机的好处是逻辑直观,每个状态对应一个agent,状态之间的转移条件写清楚就行。规模大了再考虑引入更复杂的编排框架。

中间状态的存放,小项目用内存字典就够,但要注意加锁,因为agent可能是并发执行的。如果流程需要持久化(比如中途要人工介入),那就得用数据库或者文件系统。

4.2 编排层的核心逻辑实现

编排层是整个系统的大脑,它的核心逻辑可以概括成一个循环:检查当前状态,决定下一个要执行的agent,调用它,处理它的输出,更新状态,然后进入下一轮。

用伪代码表示大概是这样:

def run_agency(task): state = init_state(task) while not state.is_finished: agent = select_next_agent(state) if agent is None: break try: result = agent.execute(state.get_input_for(agent)) state.update(agent.name, result) except AgentError as e: handle_failure(state, agent, e) return state.final_output

这里有几个细节值得展开。select_next_agent不是简单地按顺序取,而是要根据当前状态判断哪些agent的前置条件已经满足。比如报告agent必须等分析agent完成后才能启动,如果分析还没做,就不能选它。

state.get_input_for(agent)体现了前面说的裁剪策略,每个agent拿到的输入是经过筛选的,不是全量状态。

handle_failure里包含了重试计数、降级判断等逻辑。这里要注意,重试次数要有限制,否则一个持续失败的agent会让整个流程卡死。

4.3 单个Agent的执行封装

每个agent的执行逻辑,本质上是"构造prompt、调用模型、解析输出"三步。但每一步都有讲究。

构造prompt时,要把角色定义、输入数据、输出格式要求三部分拼装好。输入数据要做序列化,通常是JSON格式,方便模型理解结构。输出格式要求要写得非常明确,最好给出一个示例,模型照着示例产出的准确率会高很多。

调用模型时,要设置合理的超时和重试参数。超时太短会导致正常的长任务被误杀,太长会让失败任务拖慢整个流程。我的经验是,根据任务复杂度设置,简单任务30秒,复杂任务可以到2分钟。

解析输出时,不要假设模型一定返回合法JSON。要先做格式校验,失败了就走重试流程。解析成功后,还要做一次内容合理性检查,比如必填字段是否为空、数值是否在合理范围内。

4.4 一个完整的任务流转示例

假设我们要做一个"竞品调研报告"的任务,整个流转过程是这样的:

第一步,编排层接收任务,初始化状态,把"调研主题"和"关键词列表"写入状态。

第二步,唤醒搜集agent。它拿到关键词列表,逐个关键词去检索信息,产出结构化的信息点列表。编排层把结果存入状态。

第三步,唤醒分析agent。它从状态里取出信息点列表,做归类、对比、提炼,产出分析结论。这里要注意,分析agent拿到的输入是裁剪过的,只有信息点和可信度,没有原始来源信息。

第四步,唤醒报告agent。它拿到分析结论,按照预设的报告模板组织内容,产出最终报告。

第五步,唤醒审核agent。它检查报告的完整性、逻辑一致性、是否有明显错误,产出审核意见。如果审核不通过,编排层会把意见反馈给报告agent,让它修改,然后再次审核,最多循环三次。

第六步,编排层把最终报告写入输出,标记任务完成。

这个流程里,每个agent的职责都很清晰,输入输出都有明确契约,任何一步出问题都能快速定位。

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

5.1 常见问题速查表

问题现象可能原因排查方向解决思路
流程卡住不动某个agent的前置条件永远不满足检查状态转移条件修正条件判断逻辑
输出格式频繁错误prompt里的格式说明不够明确查看失败时的原始输出补充示例,强化格式约束
结果质量差上下文裁剪过度,关键信息丢失对比裁剪前后的输入调整裁剪策略,保留必要字段
流程耗时过长串行执行,或某个agent反复重试查看各agent耗时统计并行化无依赖的agent,优化重试策略
审核环节形同虚设审核agent的prompt太宽松检查审核标准是否具体给出明确的审核清单和判定标准
状态数据被意外覆盖多个agent并发写同一字段检查状态更新逻辑加锁或改为消息传递

5.2 几个我踩过的坑

坑一:把编排逻辑写进了agent的prompt里。早期我图省事,在搜集agent的prompt里写了"搜集完成后请把结果交给分析agent"。结果模型真的在输出里加了一句"接下来请分析",导致解析失败。编排是编排层的事,agent只管自己的输入输出,这个边界一定要守住。

坑二:忽略了模型输出的不确定性。同样的输入,模型两次调用可能产出格式略有不同的结果。一开始我按固定格式解析,遇到一点偏差就报错。后来改成宽松解析——先尝试严格解析,失败则用正则提取关键字段,再失败才走重试。这样鲁棒性好了很多。

坑三:审核agent和报告agent用了同一个模型同一个温度。结果审核agent总是倾向于通过报告,因为它的"审美"和报告agent一致。后来我把审核agent的温度调低,并且在prompt里明确要求"以挑刺的心态审核",通过率才回归正常。

坑四:没有做超时控制。有一次某个agent因为输入过长,模型调用一直不返回,整个流程挂了半小时。后来给每个agent都加了硬超时,超时就走降级,流程再也没卡死过。

5.3 性能优化的几个实用技巧

第一个技巧是并行化无依赖的agent。比如搜集agent和分析agent之间如果有多个独立的搜集任务,可以并发执行,最后汇总。这能显著缩短整体耗时。

第二个技巧是缓存中间结果。如果某个agent的输入没变,就没必要重新执行。这在调试阶段特别有用,改了下游逻辑时,上游结果可以直接复用。

第三个技巧是分级模型。不是所有agent都需要用最强的模型。搜集、格式化这类任务用轻量模型就够了,分析和审核再用强模型。这样能在保证质量的同时控制成本。

第四个技巧是日志要记全。每个agent的输入、输出、耗时、重试次数都要记录。出问题时,这些日志就是你的排查依据。我习惯把日志按任务ID分组,这样查一个任务的完整流转非常方便。

6. 关于这套架构的扩展思考

这套agency-agents的架构跑通之后,其实可以往几个方向继续演进。

一个方向是引入人工介入节点。有些关键决策,比如最终报告是否发布,可以让流程暂停,等人工确认后再继续。这需要在编排层支持"挂起"和"恢复"状态。

另一个方向是动态调整agent数量。根据任务复杂度,自动决定是启动三个agent还是八个agent。这需要一套任务复杂度的评估机制,目前还比较依赖人工配置。

还有一个方向是agent之间的协商机制。现在agent之间是单向传递,上游产出什么下游就接收什么。如果引入双向协商,下游可以向上游提出"我需要更多细节",整个系统的智能程度会更高,但复杂度也会大幅上升。

我个人在实际操作中的体会是,不要一开始就追求这些高级特性。先把最基础的三四个agent跑通,把编排、通信、重试这些基础设施做扎实,再考虑扩展。很多项目失败不是因为架构不够先进,而是因为基础没打牢,跑起来到处漏风。

最后分享一个小技巧:给每个agent起一个简短好记的名字,并且在日志和状态里统一使用这个名字。这看起来是小事,但当你有十几个agent、排查一个跨多个agent的问题时,好记的名字能帮你省下大量脑力。