1. 从单兵作战到团队协作:为什么我们需要重新思考智能体架构
做过智能体应用开发的人都有一个共同感受:单个智能体再强,遇到复杂任务时也容易“翻车”。你让它写一份行业分析报告,它可能前两段写得有模有样,到第三段就开始胡编数据;你让它处理一个多步骤的客户服务流程,它可能在第二步就忘了第一步的约束条件。这不是模型能力不够,而是架构设计的问题——你让一个“全能选手”同时扮演研究员、分析师、写手和审核员,它不精神分裂才怪。
Agency Agents 这套多智能体协作系统,核心要解决的就是这个问题。它的基本思路非常朴素:既然一个智能体搞不定复杂任务,那就拆成多个各有所长的智能体,让它们像一家公司里的不同岗位一样分工协作。有的负责理解需求,有的负责搜集信息,有的负责撰写内容,有的负责质量把关,最后还有一个“管理者”角色来协调全局。这套思路听起来简单,但真正落地时会遇到大量工程细节问题:智能体之间怎么通信?任务怎么分配?出现冲突怎么仲裁?上下文怎么传递才不丢失关键信息?
这篇文章适合两类人看。一类是已经在做智能体应用开发、但感觉单智能体方案碰到天花板的开发者;另一类是对多智能体协作感兴趣、想了解这套架构到底怎么落地、有哪些坑要避的技术负责人。我会从架构设计思路讲起,然后拆解核心模块的实现要点,接着给出一套可参考的实操方案,最后分享我在实际项目中踩过的坑和排查技巧。整篇内容基于常见的工程实践展开,不涉及任何特定平台或框架的绑定,你可以根据自己的技术栈灵活调整。
2. 架构设计拆解:Agency Agents 的底层逻辑与选型考量
2.1 为什么是“代理团队”而不是“超级代理”
在决定用多智能体架构之前,我和团队试过另一条路:把单个智能体的提示词写得极其详尽,把各种角色要求、输出格式、约束条件全部塞进去。结果发现两个致命问题。第一,提示词长度爆炸后,模型对关键指令的注意力被稀释,经常顾此失彼。第二,调试极其困难——当输出不符合预期时,你根本不知道是哪个环节的指令出了问题,只能从头到尾逐句排查。
多智能体架构的本质是“关注点分离”。每个智能体只负责一个明确的子任务,它的提示词可以写得很聚焦,行为可预测性大幅提升。更重要的是,当某个环节出问题时,你可以单独调试那个智能体,而不用动整个系统。这就像软件开发中的微服务架构——每个服务只做一件事,做好一件事,服务之间通过明确定义的接口通信。
Agency Agents 的设计哲学还包含一个关键判断:智能体之间的协作成本必须低于单个智能体处理全部任务的成本。如果拆成五个智能体后,它们之间的通信开销、协调开销、上下文同步开销加起来超过了收益,那这个拆分就是失败的。所以在实际设计中,我们通常把智能体数量控制在三到七个之间,每个智能体的职责边界要非常清晰,避免出现“两个智能体都能做这件事”的模糊地带。
2.2 核心角色划分与职责边界
一套典型的 Agency Agents 系统包含以下几类角色。协调者是整个团队的入口和出口,它负责接收用户需求、拆解任务、分配给合适的执行者、收集结果并整合输出。研究者负责信息搜集和事实核查,它的输出是结构化的参考资料。分析者负责对研究结果进行深度加工,提取关键洞察和逻辑关系。撰写者负责将分析结果转化为可读性强的最终内容。审核者负责质量把关,检查事实准确性、逻辑一致性和格式合规性。
这里有一个容易踩的坑:角色划分过细会导致通信成本飙升。我见过一个项目把撰写者又拆成“开头撰写者”“正文撰写者”“结尾撰写者”,结果三个智能体之间的衔接极其生硬,读起来像三个人各写了一段拼在一起。角色划分的粒度应该以“输出物是否具有独立完整性”为标准。如果两个角色的输出必须深度融合才能使用,那它们大概率应该合并成一个角色。
另一个关键设计决策是:协调者是否应该具备执行能力?我的建议是不要。协调者如果既能分配任务又能自己干活,它就会倾向于“自己顺手做了”,导致任务分配逻辑混乱。协调者的唯一职责是调度和整合,它不应该直接产出内容。这个边界一旦模糊,整个系统的可观测性就会急剧下降。
2.3 通信机制选型:消息队列 vs 共享上下文
智能体之间怎么传递信息,这是架构设计中最核心的技术决策之一。常见方案有两种:消息队列模式和共享上下文模式。
消息队列模式中,每个智能体完成自己的任务后,把结果作为消息发送给下一个智能体。这种模式的好处是解耦彻底,每个智能体只需要知道“我从谁那里收消息、发给谁”,不需要了解全局状态。缺点是上下文容易丢失——当任务链较长时,后面的智能体可能看不到前面的关键约束条件。
共享上下文模式中,所有智能体读写同一个上下文存储。每个智能体完成任务后,把自己的输出写入上下文,下一个智能体从上下文中读取所需信息。这种模式的好处是信息完整,任何智能体都能访问全局状态。缺点是上下文会迅速膨胀,如果不做有效的摘要和裁剪,很快就会超出模型的上下文窗口限制。
Agency Agents 实际采用的是混合模式:维护一个全局上下文存储,但每个智能体只被授权访问其中与自己职责相关的部分。协调者负责在任务流转时,从全局上下文中提取并传递必要的上下文片段给下一个智能体。这样既保证了信息的完整性,又控制了每个智能体实际接收到的信息量。
实操心得:全局上下文存储建议用结构化格式(如 JSON),每个字段有明确的语义标签。不要用纯文本堆砌,否则后续做上下文提取时你会非常痛苦。
2.4 任务分配策略:静态路由与动态调度的取舍
任务分配有两种基本策略。静态路由是预先定义好“什么类型的任务交给哪个智能体”,实现简单、行为可预测。动态调度是协调者根据当前任务的具体特征和各个智能体的当前负载,实时决定分配给谁,灵活性高但实现复杂。
我的建议是:初期用静态路由,等系统稳定后再逐步引入动态调度。静态路由虽然笨,但它的行为完全可预测,调试起来非常直观。你可以在日志里清楚地看到每个任务被分配给了谁、为什么分配给它。动态调度虽然理论上更优,但它的决策逻辑往往是个黑盒,出问题时很难定位原因。
Agency Agents 在静态路由的基础上做了一个改进:引入“能力标签”机制。每个智能体注册时声明自己具备哪些能力标签(如“信息检索”“数据分析”“文本生成”“事实核查”),协调者根据任务所需的标签来匹配智能体。这比硬编码的路由规则灵活,又比完全动态调度可控。
3. 核心模块实现细节:从任务拆解到结果整合的完整链路
3.1 任务拆解模块:如何把模糊需求变成可执行指令
任务拆解是整个系统的第一步,也是最容易出问题的一步。用户输入往往是一句模糊的话,比如“帮我分析一下这个市场的竞争格局”。协调者需要把这句话拆解成多个具体的、可执行的子任务:需要搜集哪些数据?需要从哪些维度分析?最终输出应该是什么格式?
拆解的质量直接决定了后续所有环节的质量。如果拆解得太粗,执行者不知道具体要做什么;如果拆解得太细,又会造成大量琐碎的通信开销。我的经验是:每个子任务应该能在一次智能体调用中完成,且输出物有明确的验收标准。
具体实现上,协调者首先对用户需求做意图识别,判断任务类型(信息搜集类、分析类、创作类、操作类等)。然后根据任务类型调用对应的拆解模板。拆解模板是一组预定义的子任务序列,每个子任务包含任务描述、所需能力标签、输入依赖、输出格式要求。最后协调者对拆解结果做一次自检:子任务之间是否有循环依赖?是否有子任务的输出无人使用?所有子任务的输出整合后是否能满足原始需求?
注意事项:拆解模板不要写得太死。我见过一个项目把模板写成了硬编码的步骤列表,结果遇到稍微变形的需求就完全无法处理。模板应该定义“子任务的类型和顺序约束”,而不是“具体的执行步骤”。
3.2 智能体调度与状态管理:让每个角色知道何时该上场
调度模块的核心职责是:根据当前的任务队列和各个智能体的状态,决定下一个执行哪个子任务、由哪个智能体执行。这里的关键挑战是处理依赖关系——某些子任务必须在其他子任务完成后才能开始,某些子任务可以并行执行。
Agency Agents 采用基于有向无环图的任务依赖管理。每个子任务是一个节点,依赖关系是边。调度器持续扫描图中“所有依赖都已满足”的节点,将它们加入就绪队列。然后根据智能体的可用性和能力匹配度,从就绪队列中选取任务进行分配。
状态管理方面,每个智能体维护三种状态:空闲、忙碌、异常。空闲状态可以接受新任务;忙碌状态表示正在执行任务,调度器不会给它分配新任务;异常状态表示上次执行失败,需要人工介入或自动重试。协调者定期检查所有智能体的状态,对于长时间处于忙碌状态的智能体,会触发超时检查。
这里有一个容易被忽视的细节:智能体的“忙碌”状态应该有超时机制。我遇到过智能体因为某个外部接口调用卡死,一直处于忙碌状态,导致整个任务链停滞。后来加了超时检测:如果某个智能体忙碌超过预设阈值,调度器会将其标记为异常并重新分配任务。
3.3 上下文传递与记忆管理:解决信息丢失与膨胀的平衡术
上下文传递是多智能体系统中最微妙的部分。传递太少,后续智能体缺少必要信息;传递太多,模型注意力被稀释,关键信息反而被淹没。
我们的做法是分层上下文管理。第一层是全局上下文,存储所有智能体的输出摘要和关键决策记录,体量控制在模型上下文窗口的百分之二十以内。第二层是任务上下文,只包含当前子任务直接依赖的前置输出,体量控制在百分之三十以内。第三层是智能体私有上下文,是智能体自己的历史执行记录,用于保持行为一致性,体量控制在百分之十以内。剩余百分之四十的窗口留给当前任务的输入和输出。
上下文摘要的生成策略也很关键。我们不让智能体直接输出完整的长文本,而是要求它输出“结构化摘要加关键原文片段”。结构化摘要包含任务结论、关键数据点、置信度评估;关键原文片段是支撑结论的原始证据。这样后续智能体既能快速理解前序工作的要点,又能在需要时查阅原始细节。
实操心得:上下文摘要的生成提示词里一定要加一句“如果某个信息你不确定是否重要,宁可保留也不要丢弃”。我吃过亏——摘要智能体把一些它认为“不重要”的约束条件删掉了,导致后续智能体完全不知道有这个约束,输出完全跑偏。
3.4 结果整合与质量校验:确保最终输出的一致性与可靠性
所有子任务完成后,协调者需要把各个智能体的输出整合成最终结果。这一步的难点在于:不同智能体的输出风格可能不一致,甚至可能存在事实性冲突。
整合流程分三步。第一步是冲突检测:协调者对比不同智能体输出中涉及同一事实的部分,如果存在矛盾,标记为待仲裁项。第二步是仲裁:对于待仲裁项,协调者调用审核者智能体,由审核者根据原始资料和逻辑推理做出判断。第三步是风格统一:协调者对整合后的内容做一次通读,调整表述风格,确保最终输出读起来像一个人写的,而不是多个人的拼凑。
质量校验环节,我们设置了三道关卡。事实校验由审核者智能体执行,逐条核对关键事实是否有可靠来源支撑。逻辑校验检查论证链条是否完整、是否存在跳跃。格式校验检查输出是否符合用户要求的格式规范。三道关卡全部通过后,协调者才将最终结果返回给用户。
4. 实操落地全流程:从零搭建一套可运行的多智能体协作系统
4.1 环境准备与技术栈选型
搭建 Agency Agents 系统不需要特别复杂的环境。核心依赖包括:一个支持函数调用的语言模型接口、一个轻量级的任务队列(可以用内存队列起步)、一个结构化存储(用于全局上下文,可以用 JSON 文件或轻量数据库)、一个日志系统(用于追踪每个智能体的输入输出)。
技术栈方面,Python 是最自然的选择,因为大多数模型接口的官方 SDK 都是 Python 优先。异步框架建议用 asyncio,因为智能体之间的通信天然适合异步模型。如果你需要更复杂的调度逻辑,可以引入 Celery 或类似的任务队列框架,但我建议初期先用 asyncio 的原生队列,减少依赖复杂度。
目录结构建议这样组织:agents/目录存放各个智能体的实现,每个智能体一个文件;orchestrator/目录存放协调者逻辑;context/目录存放上下文管理相关代码;tasks/目录存放任务拆解模板;logs/目录存放运行日志。这种组织方式让每个模块的职责非常清晰,后续扩展和调试都很方便。
4.2 定义智能体接口与注册机制
每个智能体需要实现统一的接口,包含三个核心方法:can_handle(task)判断自己是否能处理某个任务,execute(task, context)执行任务并返回结果,get_capabilities()返回自己的能力标签列表。
注册机制采用配置文件驱动。在agents/config.yaml中定义每个智能体的名称、能力标签、模型参数、超时设置。系统启动时读取配置,动态加载对应的智能体实现。这样增加或替换智能体时只需要改配置,不需要动核心调度代码。
# 智能体基类示例 class BaseAgent: def __init__(self, name, capabilities, model_config): self.name = name self.capabilities = capabilities self.model_config = model_config self.state = "idle" def can_handle(self, task): required = set(task.required_capabilities) return required.issubset(set(self.capabilities)) async def execute(self, task, context): self.state = "busy" try: result = await self._run(task, context) self.state = "idle" return result except Exception as e: self.state = "error" raise e async def _run(self, task, context): raise NotImplementedError4.3 协调者核心逻辑实现
协调者的主循环逻辑如下:从任务队列取出就绪任务,筛选出能处理该任务的空闲智能体,选择匹配度最高的一个,构造该智能体所需的上下文片段,调用智能体的执行方法,收集结果并更新全局上下文,标记任务完成,触发依赖该任务的新任务进入就绪队列。
匹配度计算考虑三个因素:能力标签匹配度(权重最高)、历史执行成功率、当前负载。能力标签完全匹配得满分,部分匹配按比例得分。历史成功率低于阈值的智能体降权。当前负载高的智能体降权,避免所有任务都堆到同一个智能体上。
async def orchestrate(self, user_request): tasks = self.decompose(user_request) self.build_dependency_graph(tasks) while not self.all_tasks_completed(tasks): ready_tasks = self.get_ready_tasks(tasks) for task in ready_tasks: candidates = [a for a in self.agents if a.can_handle(task) and a.state == "idle"] if not candidates: continue selected = self.select_best_agent(candidates, task) context = self.build_context(task, self.global_context) result = await selected.execute(task, context) self.update_global_context(task, result) self.mark_completed(task) return self.integrate_results(tasks)4.4 上下文存储与检索实现
全局上下文用 JSON 文件存储,结构如下:顶层按任务 ID 分组,每个任务下存储该任务的输出摘要、关键数据点、原始输出引用。检索时根据当前任务的依赖列表,提取相关任务的摘要和关键数据点,组装成上下文片段。
上下文裁剪策略:如果组装后的上下文超过预设的 token 上限,按优先级裁剪。优先级排序为:直接依赖任务的输出 > 间接依赖任务的摘要 > 全局决策记录 > 历史执行日志。裁剪时从低优先级开始移除,直到满足 token 限制。
注意事项:token 计数不要用估算,要用模型提供的精确计数接口。我见过因为估算偏差导致上下文超限、模型直接报错的案例。精确计数虽然多一次接口调用,但省去了大量调试时间。
4.5 日志与可观测性建设
多智能体系统的调试难度远高于单智能体,因为问题可能出在任何一个环节。完善的日志系统是必须的。我们记录以下信息:每个任务的拆解结果、每个智能体的调用输入和输出、每次上下文传递的内容和大小、每个决策点的选择理由、每个异常事件的完整堆栈。
日志格式采用结构化 JSON,每条日志包含时间戳、任务 ID、智能体名称、事件类型、事件详情。这样后续可以用脚本做自动化分析,比如统计每个智能体的平均执行时间、失败率、上下文膨胀速度等。
可观测性方面,建议做一个简单的 Web 面板,实时展示当前任务队列状态、各个智能体的状态、上下文大小变化趋势。这个面板不需要多精美,能看清关键指标就行。我在实际项目中用 Streamlit 花了一个下午搭了一个,后续调试效率提升非常明显。
5. 常见问题与排查技巧实录
5.1 智能体“各说各话”:输出风格不一致的根因与解法
这是多智能体系统最常见的问题。最终输出读起来像多人拼凑,风格跳跃,术语不统一。根因通常有三个:一是各个智能体的提示词风格差异太大;二是上下文传递时没有传递风格约束;三是整合环节没有做风格统一处理。
解法分三步。首先,在系统初始化时定义一个“风格指南”,包含术语表、语气要求、格式规范,作为全局上下文的一部分传递给所有智能体。其次,每个智能体的提示词里明确引用风格指南,要求输出必须符合指南。最后,整合环节增加一个“风格统一”步骤,由撰写者智能体对整合后的内容做一次通读和改写。
5.2 任务链断裂:依赖关系处理中的典型错误
任务链断裂表现为某个任务一直处于等待状态,因为它的依赖任务从未被标记为完成。常见原因包括:依赖关系配置错误导致循环依赖;某个任务执行失败后没有触发重试或降级处理;调度器在某个异常分支中跳过了状态更新。
排查方法:首先检查依赖图是否有环,用拓扑排序验证。然后检查失败任务的处理逻辑,确保失败后要么重试、要么标记为失败并触发降级路径。最后在调度器的每个分支都加上状态更新日志,确保没有遗漏。
实操心得:建议在系统启动时做一次依赖图的完整性校验,包括检查是否有环、是否有孤立节点、是否有节点没有入边或出边。这个校验花不了多少时间,但能避免大量运行时问题。
5.3 上下文爆炸:token 超限的预防与应急处理
上下文爆炸通常发生在任务链较长、每个智能体输出都很详细的情况下。预防措施包括:强制智能体输出结构化摘要而非全文;设置全局上下文的大小上限,超过时触发裁剪;定期对全局上下文做压缩,合并相似信息。
应急处理:当检测到上下文即将超限时,协调者可以触发“上下文压缩”流程,调用一个专门的压缩智能体,将当前上下文压缩到原来的百分之五十。压缩时保留关键决策和结论,丢弃中间过程细节。如果压缩后仍然超限,则触发“上下文重置”,只保留最近三个任务的输出,更早的信息转为长期存储,需要时再检索。
5.4 智能体“偷懒”:输出质量下降的检测与干预
智能体偷懒表现为输出越来越简短、越来越模板化、越来越不愿意做深度分析。这通常是因为模型在长上下文下注意力衰减,或者提示词中的质量要求被后续内容淹没。
检测方法:对每个智能体的输出做质量评分,评分维度包括长度、信息密度、与输入的相关性。如果连续多次评分低于阈值,标记该智能体为“低质量状态”。干预措施:对该智能体的下一次调用增加“质量提醒”,在提示词开头强调质量要求;如果仍然无效,降低该智能体的调度优先级,让其他智能体接管。
5.5 常见问题速查表
| 问题现象 | 可能原因 | 排查步骤 | 解决方案 |
|---|---|---|---|
| 最终输出风格跳跃 | 提示词风格不统一 | 对比各智能体提示词 | 增加全局风格指南 |
| 任务链停滞 | 依赖关系有环或失败未处理 | 检查依赖图和失败日志 | 修复依赖关系,增加重试机制 |
| 上下文超限报错 | 输出未做摘要或裁剪 | 检查上下文大小趋势 | 启用压缩和裁剪策略 |
| 输出质量持续下降 | 模型注意力衰减 | 检查输出长度和信息密度 | 增加质量提醒,调整调度优先级 |
| 智能体卡死 | 外部调用超时 | 检查智能体状态和超时日志 | 增加超时检测和任务重分配 |
| 事实性冲突 | 多源信息未仲裁 | 对比不同智能体的事实陈述 | 引入审核者仲裁机制 |
6. 性能调优与扩展思路
6.1 并行化改造:哪些环节可以并行,哪些必须串行
任务依赖图中,没有直接依赖关系的任务可以并行执行。典型的可并行环节包括:多个独立的信息搜集任务、多个维度的分析任务、多个格式的适配任务。必须串行的环节包括:任务拆解必须在所有执行之前完成;结果整合必须在所有执行之后进行;仲裁必须在冲突检测之后进行。
并行化改造的关键是识别出依赖图中的“宽层”——同一层级有多个节点且互不依赖。调度器可以同时将这些节点分配给不同的智能体并行执行。实测下来,一个典型的内容生成任务,并行化后总耗时可以降低百分之四十到六十。
6.2 缓存策略:减少重复计算,提升响应速度
多智能体系统中存在大量重复计算。比如同一个信息检索任务可能在多个任务链中被反复执行。引入缓存层可以显著降低响应时间和计算成本。
缓存策略分两级。结果缓存存储智能体的完整输出,键为任务描述加输入上下文的哈希。摘要缓存存储上下文摘要,键为原始输出的哈希。查询时先查结果缓存,命中则直接返回;未命中则查摘要缓存,命中则基于摘要做增量处理。
注意事项:缓存失效策略要谨慎设计。我建议设置较短的过期时间(如一小时),并在全局上下文发生重大变化时主动清除相关缓存。否则可能返回过时的结果。
6.3 智能体动态扩缩容:根据负载自动调整团队规模
当任务量波动较大时,固定数量的智能体要么在高峰期成为瓶颈,要么在低谷期浪费资源。动态扩缩容机制根据当前就绪队列的长度和各个智能体的负载,决定是否创建新的智能体实例或销毁空闲实例。
扩容触发条件:就绪队列长度超过阈值且所有现有智能体都处于忙碌状态。缩容触发条件:就绪队列为空且某个智能体空闲时间超过阈值。扩缩容的粒度建议以“同类智能体”为单位,即扩容时增加一个与现有某智能体能力标签相同的实例,而不是创建一个全新类型的智能体。
6.4 从单机到分布式:扩展时的架构调整要点
单机运行时,智能体之间的通信可以用内存队列,上下文存储可以用本地文件。当任务量增长到单机无法承载时,需要迁移到分布式架构。核心调整包括:通信层从内存队列换成消息中间件;上下文存储从本地文件换成分布式存储;调度器从单实例换成多实例加分布式锁;日志系统从本地文件换成集中式日志服务。
迁移过程中最大的坑是状态一致性。分布式环境下,多个调度器实例可能同时尝试分配同一个任务。解决方案是引入分布式锁,确保同一时刻只有一个调度器能修改任务状态。另一个坑是上下文同步延迟,分布式存储的读写延迟远高于本地文件,需要在上下文传递时增加重试和超时处理。
7. 我踩过的坑与最终沉淀下来的经验
7.1 不要过早追求“全自动”
刚开始做 Agency Agents 时,我试图让系统完全自动地处理一切——自动拆解、自动分配、自动仲裁、自动整合。结果发现,在任务拆解和结果仲裁这两个环节,人工介入的价值远超预期。拆解环节,人工确认一下拆解结果是否合理,能避免后续大量无效工作。仲裁环节,人工判断一下冲突双方谁更有道理,比让模型自己仲裁准确得多。
我的建议是:在拆解和仲裁两个环节保留人工确认点,其他环节可以全自动。这样系统的可靠性大幅提升,而人工成本增加有限。
7.2 提示词版本管理比想象中重要
多智能体系统中,每个智能体都有自己的提示词。当系统行为出现异常时,你很难判断是哪个智能体的提示词出了问题。更麻烦的是,当你调整了某个智能体的提示词后,可能会意外影响其他智能体的行为。
后来我们引入了提示词版本管理:每个提示词有版本号,每次修改都记录修改内容和修改原因。系统运行时记录每个智能体使用的提示词版本。当出现异常时,可以快速定位到是哪个版本、哪个修改引入的问题。这个实践看起来简单,但节省了大量排查时间。
7.3 从三智能体起步,逐步扩展
如果你刚开始搭建多智能体系统,我的建议是从三个智能体起步:一个协调者、一个执行者、一个审核者。这个最小可行系统能跑通完整的任务流程,同时复杂度可控。等这个基础架构稳定后,再逐步拆分执行者为多个专业智能体,增加研究者、分析者等角色。
我见过太多项目一开始就设计七八个智能体,结果通信逻辑复杂到无法调试,最后不得不推倒重来。从简单开始,逐步演进,这个原则在多智能体系统设计中尤其重要。
7.4 日志要记录“为什么”而不只是“是什么”
常规日志记录的是“发生了什么”——任务 A 分配给了智能体 B,智能体 B 输出了结果 C。但调试多智能体系统时,你更需要知道“为什么”——为什么任务 A 分配给了智能体 B 而不是智能体 D?为什么智能体 B 输出了结果 C 而不是其他结果?
我们在日志中增加了决策理由字段。每次调度决策都记录选择该智能体的理由(能力匹配度得分、当前负载、历史成功率)。每次智能体输出都记录关键决策点(为什么选择这个分析角度、为什么排除那个数据源)。这些“为什么”信息在排查问题时价值极高。
7.5 定期做“压力测试”和“混沌测试”
多智能体系统的故障模式比单智能体复杂得多。我们定期做两类测试。压力测试:模拟大量并发任务,观察系统在高峰负载下的表现,找出瓶颈环节。混沌测试:随机让某个智能体执行失败、随机让上下文存储不可用、随机让通信延迟增加,观察系统的容错能力和恢复速度。
混沌测试帮我们发现了多个隐藏问题,比如某个智能体失败后没有正确释放资源、上下文存储短暂不可用导致整个任务链崩溃等。这些问题在正常运行时不会暴露,但一旦出现就会造成严重后果。
7.6 关于成本控制的几点体会
多智能体系统的 token 消耗远高于单智能体,因为每个智能体都要接收上下文、生成输出,而且上下文在多个智能体之间反复传递。成本控制的核心是减少不必要的上下文传递和优化智能体调用次数。
具体措施包括:上下文摘要要精炼,只传递必要信息;能合并的智能体调用尽量合并;缓存高频使用的中间结果;对简单任务使用更小的模型。实测下来,这些措施能把成本降低百分之五十以上,而对输出质量的影响微乎其微。
这个方向后续还可以继续深挖,比如引入更智能的上下文压缩算法、探索智能体之间的直接通信机制、研究如何让智能体从历史执行中自动学习优化策略。但那是下一步的事了,当前这套架构已经能稳定支撑大部分复杂任务场景。