ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

多智能体协作架构与Loop Engineering实战:角色划分、循环控制与成本优化

多智能体协作架构与Loop Engineering实战:角色划分、循环控制与成本优化

1. 多智能体协作架构到底在解决什么问题

1.1 从单体智能到群体协作的必然演进

过去两年我一直在做智能体系统的落地,从最早的单个大模型调用工具,到后来多个智能体互相配合完成复杂任务,踩过的坑比写过的代码还多。Loop Engineering 这个词最近被频繁提起,本质上它讲的不是某个具体框架,而是一套让多个智能体在循环反馈中持续协作、自我修正的工程方法论。你可以把它理解成:以前我们写一个脚本让模型跑一次就结束,现在我们要设计一个闭环,让多个各有所长的智能体在里面反复迭代,直到输出达到可接受的质量标准。

为什么单体智能不够用?我举个实际例子。假设你要做一个竞品分析报告,单个智能体需要同时完成信息检索、数据清洗、趋势判断、文案撰写、事实核查这五件事。实际跑下来你会发现,它在检索时可能漏掉关键来源,在撰写时又容易把未经核实的数据写进去,而且一旦中间某步出错,整个链条就崩了,你根本不知道是哪一环出了问题。多智能体协作架构的核心价值就在于职责分离与交叉验证——让检索智能体专注找资料,分析智能体专注提炼观点,审核智能体专门挑毛病,每个角色只做自己最擅长的事,通过循环反馈机制把错误率压下来。

Loop Engineering 里的“Loop”指的就是这个循环:执行、评估、反馈、修正、再执行。它不是简单的重试,而是有结构的迭代。我见过太多团队把多智能体做成了“多个模型轮流说一遍话”,那不叫协作,那叫轮流发言。真正的协作架构需要明确每个智能体的输入输出边界、失败处理策略、以及循环终止条件。

1.2 哪些场景真的需要多智能体协作

不是所有任务都值得上多智能体。我个人的判断标准是:任务是否具有可分解性、是否需要多视角验证、是否对错误容忍度低。三个条件满足两个以上,才考虑多智能体方案。

适合的场景包括:复杂研究报告生成、代码审查与重构、多源数据交叉验证、长流程任务编排(比如从需求分析到测试用例生成)、以及需要模拟多方立场的决策推演。不适合的场景也很明确:简单的问答、单步工具调用、对延迟极度敏感的场景。我试过用多智能体做一个简单的天气查询,结果三个智能体互相确认了五轮才给出答案,延迟从200毫秒涨到了8秒,完全得不偿失。

注意:多智能体协作的通信开销和协调成本是单体方案的数倍,如果任务本身不需要多视角验证,强行上多智能体只会让系统更脆弱。

1.3 Loop Engineering 与传统工作流引擎的区别

传统工作流引擎(比如 Airflow、Prefect)是确定性编排,你定义好 DAG,任务按固定路径执行。Loop Engineering 面对的是不确定性环境——智能体的输出质量波动大,需要动态决定下一步走哪条分支、是否需要回退、是否要增加额外的验证轮次。这就引出了几个核心设计问题:循环由谁触发、反馈信号怎么定义、终止条件怎么设置、以及如何避免无限循环。

我自己的经验是,循环控制权应该交给一个独立的协调者智能体,而不是让执行智能体自己决定要不要继续。原因很简单:执行者往往对自己的输出过于自信,而协调者可以从全局视角判断当前状态是否满足退出条件。这个协调者不需要很强的生成能力,但需要清晰的评估逻辑和稳定的判断标准。

2. 核心架构拆解:角色、通信与循环控制

2.1 角色定义与职责边界划分

多智能体系统最容易犯的错误就是角色重叠。我见过一个团队定义了“分析智能体”和“洞察智能体”,结果两个智能体干的事几乎一样,只是提示词略有不同,白白浪费了一倍的 token 成本。角色划分应该遵循单一职责原则,每个智能体只负责一个明确的职能,且职能之间尽量正交。

一个典型的研究报告生成系统,我会这样划分角色:

角色名称核心职责输入输出失败处理
检索智能体从指定来源收集原始资料查询关键词列表结构化资料条目扩大检索范围重试
分析智能体从资料中提炼观点和证据资料条目观点-证据映射表标记低置信度条目
撰写智能体生成报告初稿观点-证据映射表报告草稿分段重写
审核智能体核查事实与逻辑一致性报告草稿+原始资料问题清单逐条标注
协调智能体控制循环流程与终止判断各阶段状态下一步指令触发人工介入

这个划分的关键在于:审核智能体的输入必须包含原始资料,否则它只能检查语言流畅度,无法验证事实准确性。很多团队做审核只让审核者看草稿,那审核就变成了语法检查,失去了交叉验证的意义。

2.2 通信协议与消息格式设计

智能体之间怎么传递信息,直接决定了系统的稳定性和可调试性。我强烈建议所有智能体间通信都使用结构化数据格式,比如 JSON Schema 定义的固定字段,而不是自由文本。自由文本传递看起来灵活,实际上会让下游智能体难以解析,而且一旦上游输出格式漂移,整个链条就断了。

我常用的消息格式包含这几个字段:task_id(任务标识)、sender(发送方角色)、receiver(接收方角色)、payload(结构化内容)、confidence(置信度 0-1)、timestamp(时间戳)、retry_count(重试次数)。其中confidence字段特别有用,协调智能体可以根据置信度决定是否需要额外验证轮次。比如审核智能体返回置信度低于 0.7 时,协调者可以自动触发一轮补充检索。

提示:消息格式一旦确定,所有智能体必须严格遵守。我通常会在系统入口加一个格式校验层,不符合 schema 的消息直接打回,避免脏数据在系统里传播。

2.3 循环控制机制与终止条件

循环控制是多智能体系统最核心也最容易出问题的地方。我见过太多系统因为终止条件设置不当,要么提前退出导致质量不达标,要么陷入死循环烧掉大量 token。我的做法是设置多重终止条件,满足任意一个就退出:

  • 质量达标:审核智能体返回的问题清单为空,且整体置信度高于阈值(我通常设 0.85)
  • 最大轮次:硬性限制循环次数,一般设 3-5 轮,超过就强制退出并标记为“需人工复核”
  • 边际收益递减:连续两轮审核发现的问题数量没有明显减少,说明系统已经收敛,继续循环意义不大
  • 成本超限:累计 token 消耗超过预算上限,立即终止

这里有个经验值:大多数任务在 2-3 轮循环后就能达到质量峰值,第 4 轮之后基本是在做无用功。所以最大轮次设 5 轮是合理的,既给了足够的修正机会,又不会浪费太多资源。

2.4 状态管理与上下文传递

多智能体系统里,每个智能体都需要知道“之前发生了什么”。但把所有历史消息都塞给每个智能体,会导致上下文爆炸,而且引入大量无关信息干扰判断。我的做法是维护一个共享状态存储,只传递与当前智能体职责相关的状态切片。

具体来说,检索智能体只需要知道“当前还需要补充哪些方面的资料”,不需要知道撰写智能体写了什么。审核智能体需要知道“原始资料是什么”和“当前草稿是什么”,但不需要知道检索过程中的中间查询。这种按需传递的方式,既控制了上下文长度,又让每个智能体聚焦在自己的任务上。

状态存储我一般用简单的键值对结构,键是状态名称,值是结构化数据。比如research_findings存检索结果,draft_report存当前草稿,review_issues存审核问题清单。协调智能体负责读写这些状态,其他智能体只读自己需要的部分。

3. 实操落地:从零搭建一个多智能体协作系统

3.1 环境准备与技术选型

搭建多智能体系统,技术选型不需要太复杂。我的建议是先用最轻量的方案跑通流程,再考虑优化。初期完全可以用 Python 脚本加几个 API 调用搞定,不需要一上来就上 LangGraph、AutoGen 这些框架。框架虽然提供了便利,但也引入了额外的抽象层,出问题时排查起来更麻烦。

我常用的基础依赖就几个:openai或同类模型调用库、pydantic做数据校验、tenacity做重试控制、loguru做日志记录。整个系统跑在一个 Python 进程里,智能体之间通过函数调用传递消息,状态存在内存字典里。等流程稳定了,再考虑把状态持久化到 Redis 或数据库,把智能体拆成独立服务。

# 基础消息结构定义 from pydantic import BaseModel from typing import Any, Optional from datetime import datetime class AgentMessage(BaseModel): task_id: str sender: str receiver: str payload: Any confidence: float = 1.0 timestamp: str = datetime.now().isoformat() retry_count: int = 0

这个结构看起来简单,但包含了调试所需的所有关键信息。task_id让你能追踪一个任务在所有智能体之间的流转路径,confidence让协调者能做动态决策,retry_count防止无限重试。

3.2 协调智能体的实现逻辑

协调智能体是整个系统的大脑,它不生成内容,只做决策。我把它设计成一个状态机:根据当前状态决定下一步调用哪个智能体、传递什么参数、以及是否终止循环。

class Coordinator: def __init__(self, max_rounds=5, confidence_threshold=0.85): self.max_rounds = max_rounds self.confidence_threshold = confidence_threshold self.state = {} self.round = 0 def should_continue(self, review_result): # 质量达标 if not review_result['issues'] and review_result['confidence'] >= self.confidence_threshold: return False, "quality_met" # 最大轮次 if self.round >= self.max_rounds: return False, "max_rounds_reached" # 边际收益递减 if self._is_converging(review_result): return False, "converged" return True, "continue" def _is_converging(self, review_result): # 比较最近两轮的问题数量 current_issues = len(review_result['issues']) previous_issues = self.state.get('last_issue_count', float('inf')) self.state['last_issue_count'] = current_issues return current_issues >= previous_issues and self.round > 1

这段代码的核心逻辑是:先判断质量是否达标,再判断是否超限,最后判断是否收敛。顺序很重要,因为质量达标是最理想的退出方式,应该优先检查。_is_converging方法通过比较连续两轮的问题数量来判断系统是否已经收敛,如果问题数量没有减少,说明继续循环也不会带来改善。

3.3 审核智能体的提示词设计

审核智能体是多智能体系统里最容易被低估的角色。很多团队随便写个提示词让它“检查一下”,结果审核出来的都是无关痛痒的格式问题。我的经验是,审核提示词必须包含明确的检查清单和判定标准,让审核者有章可循。

我常用的审核提示词结构是这样的:先给审核者提供原始资料和当前草稿,然后列出具体的检查维度(事实准确性、逻辑一致性、数据完整性、来源可追溯性),每个维度给出明确的通过标准。最后要求审核者以结构化格式输出问题清单,每个问题包含位置、类型、严重程度、修改建议。

注意:审核智能体的温度参数建议设低一些(0.1-0.3),因为审核需要的是稳定和一致,而不是创造性。执行智能体的温度可以适当高一些(0.7-0.9),鼓励多样性输出。

3.4 完整循环流程的代码实现

把各个角色串起来,形成一个完整的循环流程。下面是我常用的主循环框架:

def run_multi_agent_loop(task_description, max_rounds=5): coordinator = Coordinator(max_rounds=max_rounds) state = {'task': task_description, 'round': 0} # 第一轮:检索 -> 分析 -> 撰写 research = research_agent(task_description) analysis = analysis_agent(research) draft = writing_agent(analysis) state['draft'] = draft # 进入审核循环 while True: state['round'] += 1 review = review_agent(draft, research) should_continue, reason = coordinator.should_continue(review) if not should_continue: state['exit_reason'] = reason break # 根据审核问题修正草稿 draft = writing_agent(analysis, previous_draft=draft, issues=review['issues']) state['draft'] = draft return state

这个流程的关键在于:检索和分析只做一次,撰写和审核循环多轮。因为检索和分析的结果是相对稳定的,反复做没有意义,而撰写和审核是需要迭代优化的环节。当然,如果审核发现原始资料不足,可以触发补充检索,但那属于异常分支,不是主流程。

3.5 参数调优与成本控制

多智能体系统的成本主要来自 token 消耗。我做过统计,一个中等复杂度的报告生成任务,单智能体方案大约消耗 8000 token,多智能体方案(3 轮循环)大约消耗 35000 token,是前者的 4 倍多。所以成本控制非常重要。

我的做法是:给每个智能体设置独立的 token 预算,检索智能体预算最高(因为需要处理大量原始资料),审核智能体预算最低(只需要输出问题清单)。协调智能体实时监控累计消耗,接近预算上限时提前终止循环。另外,审核智能体可以只审核草稿的变更部分,而不是每次都全文审核,这样能省下不少 token。

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

4.1 循环不收敛的典型原因

循环不收敛是我遇到最多的问题。表现是审核智能体每轮都能挑出新问题,但问题数量不减少,系统一直跑到最大轮次才退出。排查下来,原因通常有三个:

第一个是审核标准过于模糊。如果审核提示词只说“检查质量”,审核者每轮都会从不同角度挑毛病,永远挑不完。解决办法是给审核者明确的检查清单和通过标准,让它只检查清单上的项目。

第二个是修正不彻底。撰写智能体收到问题清单后,可能只改了表面文字,没有真正解决问题。解决办法是在修正提示词里要求撰写者逐条回应每个问题,并说明修改方式。

第三个是角色职责重叠。如果审核者和撰写者对“好报告”的定义不一致,就会陷入反复拉扯。解决办法是让审核者和撰写者共享同一套质量标准文档。

4.2 智能体输出格式漂移的处理

格式漂移是指智能体输出的 JSON 结构不符合预期,导致下游解析失败。这个问题在系统刚上线时特别常见。我的处理策略是三层防护:

第一层是在提示词里明确给出输出格式示例,并要求“只输出 JSON,不要有任何其他文字”。第二层是在代码里加解析容错,比如用正则提取 JSON 块,或者用json_repair库尝试修复。第三层是解析失败时自动重试,并在重试提示词里强调格式要求。

如果某个智能体频繁出现格式问题,我会考虑换一个指令遵循能力更强的模型,或者把输出格式简化。有时候格式太复杂(比如嵌套多层),模型确实容易出错,简化格式比反复重试更有效。

4.3 上下文超限的应对方案

多轮循环后,上下文会越来越长,最终超出模型的最大上下文窗口。我的应对方案是分层摘要:每轮循环结束后,把该轮的关键信息压缩成摘要,只保留摘要进入下一轮,而不是保留完整历史。

具体来说,检索结果只保留结构化条目,不保留原始网页内容;草稿只保留当前版本,不保留历史版本;审核问题只保留未解决的,已解决的直接丢弃。这样能把上下文控制在合理范围内。如果任务特别复杂,还可以引入外部记忆存储,需要时再检索相关片段。

4.4 常见问题速查表

问题现象可能原因排查方法解决方案
循环不收敛审核标准模糊/修正不彻底检查审核问题清单是否重复明确检查清单,要求逐条回应
格式解析失败提示词格式说明不清查看原始输出内容加格式示例,加解析容错
上下文超限历史消息累积过多统计每轮 token 消耗分层摘要,只保留关键信息
成本超预算循环轮次过多统计各智能体 token 占比设预算上限,提前终止
输出质量波动大温度参数过高对比不同温度下的输出审核者降温,执行者适度降温
智能体互相推诿职责边界不清检查各智能体输入输出重新划分职责,消除重叠

4.5 我踩过的三个坑

第一个坑是让执行智能体自己决定是否继续循环。结果它总是觉得自己做得很好,第一轮就宣布完成,质量惨不忍睹。后来我把循环控制权收归协调者,问题才解决。

第二个坑是所有智能体共用同一个系统提示词。我以为这样能保持风格一致,实际上导致角色混淆,检索智能体开始写分析,分析智能体开始写报告。后来给每个智能体独立的系统提示词,明确各自职责,才恢复正常。

第三个坑是没有设置成本上限。有一次一个任务因为审核标准太严,循环了 12 轮,烧掉了将近 10 万 token。从那以后我强制设置最大轮次和 token 预算,双保险。

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

如果系统跑得太慢,可以试试这几个优化:并行化无依赖的智能体调用,比如检索和分析可以同时进行;缓存重复的检索结果,同一批资料不要反复检索;用小模型做初步筛选,大模型做精细处理,比如检索用便宜模型,撰写用强模型;审核只检查变更部分,不要每轮全文审核。

另外,日志记录非常重要。我会记录每个智能体的输入输出、耗时、token 消耗、置信度,这些数据是后续优化的基础。没有日志,你根本不知道瓶颈在哪里。

5. 多智能体协作的边界与未来演进

5.1 什么情况下应该放弃多智能体方案

多智能体不是银弹。如果任务本身很简单,或者对延迟极度敏感,或者预算非常有限,单体方案加精心设计的提示词往往更划算。我自己的判断标准是:当单体方案的质量瓶颈无法通过提示词优化突破时,才考虑多智能体。如果单体方案已经能达到 80 分,多智能体能到 90 分但成本翻四倍,那就要看这 10 分是否值得。

还有一个容易被忽视的点:多智能体系统的维护成本远高于单体系统。每个智能体的提示词、参数、依赖都需要单独维护,系统复杂度呈指数增长。如果团队没有足够的工程能力,强行上多智能体只会带来无尽的调试噩梦。

5.2 从固定角色到动态角色分配

目前大多数多智能体系统都是固定角色,任务开始前就定义好有哪些智能体。但更灵活的做法是动态角色分配:根据任务特点,由协调者决定需要哪些角色、每个角色用什么模型、分配多少预算。比如简单任务只启用检索和撰写两个角色,复杂任务才启用完整的五角色配置。

这种动态分配能显著降低成本,但实现难度也更高。协调者需要具备任务分析能力,能判断任务的复杂度和所需角色。我目前的做法是预设几套角色配置模板,协调者根据任务描述选择最接近的模板,再微调参数。完全动态生成角色定义还不太稳定,容易产生职责重叠。

5.3 评估体系的建立

多智能体系统如果没有评估体系,优化就是盲人摸象。我建议至少建立三个维度的评估:质量维度(事实准确性、逻辑一致性、完整性)、效率维度(耗时、token 消耗、循环轮次)、稳定性维度(格式合规率、异常退出率、重试率)。

评估数据要持续收集,形成趋势图。当某个指标恶化时,能快速定位是哪个智能体、哪个环节出了问题。我通常每周做一次评估复盘,看看有没有需要调整的参数或提示词。这个习惯帮我提前发现了好几次潜在问题,避免了线上事故。

5.4 我个人在实际操作中的体会

做了这么多多智能体项目,我最大的体会是:架构设计比模型选择重要,流程控制比提示词技巧重要。很多人把精力花在调提示词上,却忽略了角色划分、循环控制、状态管理这些架构层面的问题。结果就是提示词写得再漂亮,系统整体还是不稳定。

另一个体会是:从简单开始,逐步增加复杂度。不要一上来就设计五个智能体、三层循环、动态角色分配。先用两个智能体跑通基本流程,确认协作机制有效,再逐步增加角色和循环。每增加一个复杂度,都要有明确的收益,否则就是过度设计。

最后分享一个小技巧:给每个智能体起个名字。听起来很幼稚,但实际很有用。当你在日志里看到“检索者-01 返回了 15 条结果,置信度 0.72”时,比看到“agent_3 返回了 15 条结果”要直观得多。名字让角色更具体,也让调试更轻松。这个习惯是我从一位前辈那里学来的,一直用到现在。

RELATED READING

延伸阅读

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