Skip to content

第 22 章 高级 Agent 编排与协同 ​

从单个 Agent 到多 Agent 协同

22.0 那个听话但不会办事的机器人 ​

上一章的结尾,给模型接上了调用外部工具的能力。它能查股价、能订机票、能分析财报,看起来一个无所不能的助手就在眼前。

演示搭起来了,拿给老板或者同事看。让它查一下“北京今天下午三点会不会下雨”,它精准地调用了天气 API,给出了正确的回答。让它“找一篇关于AIGC技术最新进展的论文并总结”,它也做得无可挑剔。

但一个更真实、更复杂的问题,很快就会把这种兴奋打回去。

老板在对成果表示赞赏之后,可能会靠在椅背上,看似随意地提出一个新要求:“很棒!那……你让它帮我们策划一下下一季度的市场推广活动吧。”

问题就出在这里。

把这个指令输入 Agent,然后,那个刚才还显得无所不能的 Agent,突然就不知道该做什么了。它可能会停在原地,完全不知道指令在说什么;或者,它会抓住“市场推广”这个关键词,然后条件反射式地调用一个它觉得可能相关的工具,比如 web_search,搜一下“如何做市场推广”,然后把搜索结果的第一段话复述出来。

这种落差,每个试图构建复杂应用的工程师都遇到过。一个真正的“市场推广方案”,是一个庞大而复杂的“项目”。它需要先理解产品的核心卖点,然后去分析目标用户画像,接着调研竞争对手的动态,再然后是创意构思、渠道选择、预算分配、KPI 设定……这是一个需要统筹规划、多步执行,甚至可能需要跨部门协作的系统工程。

而手头的这个 Agent,接到“去把这份文件复印三十份”这样的指令,能完成得又快又好。但如果指令换成“这次年会就交给你来总负责了”,它大概率接不住。

上一章所构建的,就是一个出色的“单任务执行者”。它很擅长在清晰的、边界明确的指令下,完成一个定义好的动作。但现在需要的,不是一个单步骤的执行者,而是一个能拆解复杂任务、安排执行顺序、检查中间结果的协调者。

这一章,就要完成这个跨越,从“如何实现一个听话的执行者”,到“如何组织一个能胜任复杂任务的多 Agent 系统”。要学习的,是如何编排、调度、协同多个 Agent,让它们像一个经验丰富的专业团队一样,去完成那些真正有价值的、复杂的、开放式的现实世界任务。

这一章的内容不只是技术组件的堆砌,更涉及系统设计的思路。要探讨的,是高级 Agent 的核心能力,也就是如何让它们具备规划、反思、协作与适应变化的能力。

现在,从一个最根本的问题开始。到底要怎样,才能让 Agent 在行动之前,先把它的推理过程亮出来?

22.1 ReAct 让模型想清楚再动手 ​

黑盒问题:调试 Agent 为什么难 ​

调试上一章那个财务分析 Agent 时,很多人都有过这样的经历。当它顺利完成任务时,一切看起来都没问题。但只要它中间任何一个环节出了岔子,比如它调用了一个完全不相干的工具,或者基于正确的数据得出了一个匪夷所思的结论,排查起来就非常痛苦。

随之而来的,是漫长而痛苦的调试过程。整个 Agent 的决策过程,就是一个黑盒。外面的人只能看到最终那个错误输出,但完全不知道,在它那庞大的神经网络内部,究竟经过了哪些中间步骤。它为什么会选择调用 A 工具而不是 B 工具?它从 A 工具返回的结果里,到底得出了什么错误的信息,才导致它下一步做出了那个离谱的决策?

调试这种黑盒 Agent,是许多工程师都经历过的、最折磨人的开发体验之一。手头只有输入和最终输出,看不到中间过程,只能根据外部的表现去猜内部哪一步出了问题。每一次猜测,都是一次成本高昂、毫无头绪的试错。在分秒必争的工程世界里,这样的调试代价很难接受。

这种“结果不可追溯,过程不可解释”的特性,是阻碍 Agent 从一个“看起来很酷的演示”,走向一个“生产环境里靠得住的工具”最大的、也是最根本的障碍。需要一种方法,能把模型的中间推理过程完整暴露出来,让人能逐步看清它每一步的判断依据。

ReAct 的核心思想:把思考写在行动前面 ​

就在这个问题困扰大家的时候,一个简单却非常有效的范式出现了。它的名字叫 ReAct(Yao et al., ICLR 2023 Oral,arXiv:2210.03629,普林斯顿大学 + Google Research Brain Team),这个名字来自 Reasoning(推理) 和 Acting(行动) 这两个词的组合。

ReAct 的核心思想,用一句从小听到大的大白话就能讲清,强迫模型在决定“做什么”(Act)之前,必须先用文字把它的推理(Reason)过程,也就是“为什么这么想,以及打算怎么做”,给原原本本地写下来。

这个要求,中学的数学老师提过无数遍:“解题步骤!解题步骤!一定要写解题步骤!”一道复杂的解析几何题,光在草稿纸上算半天,最后只写下一个答案,没人能看出中间哪一步出了问题。

老师之所以如此执着于解题步骤,是因为写下来的步骤就是可检查的推理记录。就算最后答案算错了,顺着步骤也能一眼看出,到底是在哪一步出了错。是初始公式代错了?是某个正负号搞反了?还是在最终的化简过程中出现了计算失误?逻辑的轨迹清晰了,才能精准地定位错误,学生也才能真正地明白自己错在哪里,从而获得进步。

ReAct,就是给语言模型引入了这么一套强制性的“写解题步骤”的规范。它把 Agent 的每一次决策都完整写出来,所有的思考过程都可以查看和检查。

三段式汇报:Thought、Action、Observation ​

那么,在实际操作中,这是怎么实现的呢?不再允许模型像以前那样,直接返回一个不带说明的工具调用 JSON。恰恰相反,它的每一次输出,都必须严格地、一丝不苟地遵循一种特定的文本格式。这个格式是一个三段式的“标准汇报模板”,通常包含三个核心部分。

Thought(思考)。这部分是模型公开写出来的推理过程。在这里,模型必须用流畅的自然语言,详细地阐述它对当前局面的分析、它所理解的用户的最终目标是什么、为了达成这个目标它打算采取什么样的总体策略,以及在当前这一步,它为什么选择这个行动而不是其他的可能性。这里写下的每一个字,都是可供检查的推理依据。

Action(行动)。只有在完成了上面那段详尽的“思考”之后,模型才能在这里,把它经过深思熟虑后,决定要执行的具体动作给声明出来。这通常就是上一章已经非常熟悉的那个工具调用的 JSON 结构,清清楚楚地写明了要调用哪个工具,以及传递什么参数。

Observation(观察)。这一部分,不是模型生成的,而是代码侧的“工作日志”。程序接收到模型的 Action,并忠实地执行了相应的工具之后,会把工具返回的结果,无论是成功获取到的数据,还是一个表示失败的错误信息,都记录在这一部分。然后,再把这个 Observation,连同之前的全部历史记录,一起作为新的、更丰富的上下文,再次喂给模型,作为它进行下一轮 Thought 的坚实依据。

一个完整的 ReAct 循环,就是这样一个闭环的 Thought -> Action -> Observation 的三步流程。模型就在这个循环里,不断地“思考、行动、观察、再思考”,根据每一轮的新信息,一步步地修正自己的判断,最终完成任务。

实战:用 ReAct 重做财务分析 Agent ​

把上一章那个财务分析例子,用 ReAct 框架重新做一遍。这样就能真切地看到,把思考过程写出来,会给开发者带来怎样的掌控感。

这次,用户的初始问题带了点主观色彩,“我想对比一下苹果(AAPL)和微软(MSFT)的市盈率(P/E ratio),看看从估值的角度,哪个可能更值得投资一些?”

先看第一轮,Agent 的初次思考与行动规划。程序会将这个问题嵌入到一个精心设计的、引导 ReAct 行为的 Prompt 模板里,然后发送给模型。模型返回的,将不再是一个突兀的工具调用,而是这样一段逻辑清晰、娓娓道来的文本:

Thought: 好的,我理解了。用户的最终目标是比较苹果和微软的市盈率,并基于此给出一个初步的投资建议。这是一个两步走的问题:首先是客观的数据计算,然后是基于数据的主观分析。

要计算市盈率(P/E Ratio),我需要两个核心数据:公司的当前股价(Price)和它的每股收益(EPS)。我的内部知识库是静态的,无法获取实时金融数据,所以我必须使用外部工具。

我的总体作战计划是:

  1. 先专注处理苹果公司(AAPL)的数据。
  2. 使用 get_stock_price 工具获取AAPL的实时股价。
  3. 使用 get_financial_statement 工具获取AAPL的最新财报,并从中找到每股收益(EPS)。
  4. 然后,对微软公司(MSFT)重复上述2、3步。
  5. 当所有数据都收集完毕后,进行计算和比较,并给出我的分析。

计划清晰,现在开始执行第一步:获取苹果的股价。

Action:

json
{
"tool_name": "get_stock_price",
"parameters": {
"ticker": "AAPL"
}
}

看到这段输出,心里是不是一下就有底了?模型把它的行动方案完整写了出来,接下来每一步要做什么、为什么这么做,都摆在面前可查。

再看代码侧的执行与观察记录。后端代码会精准地解析出 Action 部分的 JSON,然后去调用 get_stock_price("AAPL") 这个函数。假设函数成功执行,从某个金融数据源获取到了结果。然后,程序会把这个结果,一丝不苟地格式化成 Observation。

Observation: Tool get_stock_price returned: {"ticker": "AAPL", "price": 170.00}

到了第二轮,Agent 要基于新的线索,进行再次思考。现在,最关键的一步来了。程序会把整个历史记录(用户的原始问题 + 第一轮的 Thought/Action + 刚刚生成的 Observation)全部拼接起来,作为新的、更长的上下文,再次发送给模型。模型看到了新的信息,会基于此开始进行第二轮的思考:

Thought: 非常好,我已经成功获取到了苹果的当前股价是170.00美元。这完成了我总体计划中的第一小步。根据计划,下一步是获取苹果的每股收益(EPS)。EPS这个关键财务指标,通常可以在公司的利润表(Income Statement)中找到。因此,我应该使用 get_financial_statement 这个工具,并且明确地告诉它,我需要的是利润表。

Action:

json
{
"tool_name": "get_financial_statement",
"parameters": {
"ticker": "AAPL",
"statement_type": "income_statement"
}
}

这个 Thought -> Action -> Observation 的循环,会一环扣一环地持续进行下去。模型会一步一步、有条不紊地获取完所有它需要的信息。它的每一步行动,都有清晰的、可供审查的“Thought”作为依据。

到了最终轮,任务完成,该给出结论了。当所有的数据都收集完毕后,它的最后一次 Thought,就是对全部结果的汇总说明:

Thought: 好的,现在所有的拼图都已集齐。我手头的数据有:苹果股价170.00美元,每股收益6.15美元;微软股价300.00美元,每股收益11.50美元。现在,我可以进行最终的计算和分析了。

首先,计算市盈率:

  • 苹果 P/E = 170.00 / 6.15 ≈ 27.64。
  • 微软 P/E = 300.00 / 11.50 ≈ 26.09。

其次,进行分析: 从计算结果来看,微软的市盈率略低于苹果,这在传统意义上可能意味着它的估值相对更“便宜”一些。但是,市盈率只是一个静态指标,并不能完全反映公司的价值。一个高市盈率的公司,可能市场对它的未来增长有更高的预期。

我已经完成了用户的请求,既提供了数据计算,也给出了分析。我不需要再调用任何工具了。现在,我应该使用 finish 这个特殊的Action,来输出一个综合性的、对用户友好的最终答案。

Action:

json
{
"tool_name": "finish",
"parameters": {
"answer": "根据我查询到的最新实时数据,苹果公司(AAPL)的市盈率约为27.64倍,而微软公司(MSFT)的市盈率约为26.09倍。从市盈率这个单一指标来看,微软的估值水平略低于苹果,可能显得更有吸引力一些。不过,我必须提醒您,这绝不构成直接的投资建议。一个公司的价值,还需要综合考量其未来的增长潜力、行业领导地位、技术护城河以及宏观经济环境等多种复杂因素。市盈率只是众多参考指标中的一个。"
}
}

当程序解析到这个特殊的 finish Action 时,就知道整个任务流程已经结束,可以放心地把 answer 中的内容呈现给用户了。

它换来什么:可调试、成功率与复杂任务 ​

回头再看看整个过程。有了 ReAct,Agent 的决策过程,就从一个不透明的黑盒,变成了可以逐步查看的执行记录。它的每一次行动、每一次转折,都有对应的“思考”作为注解。

这对工程师来说,好处是实质性的,它解决了几个最深的痛点。

最直接的好处,是无与伦比的可调试性。如果 Agent 在中间某个环节出错了,再也不需要毫无头绪地去猜。只要打开它的“Thought”日志,就能清晰地回溯它的整个推理过程,精准地定位到是哪一个环节的“推理”出了问题。是它误解了工具的说明书?是它对上一步的观察结果做出了错误的解读?还是一开始的宏观规划就存在致命的逻辑缺陷?一切都变得有迹可循,调试的效率和体验,提升了不止一个数量级。

再往深一层,是任务成功率的显著提升。可能会觉得,强迫模型“多想一步”,多写一些文字,会增加 Token 消耗和延迟。没错,这是它的成本。但这个成本,换来的是成功率的巨大提升。这个“把思考写下来”的过程,本身就是一种强大的自我审视和内在检验机制。它会在思考阶段,就预判到一些可能存在的陷阱或歧义,从而选择一条更稳妥、更可靠的行动路径。这就像程序员在写一段复杂的代码之前,愿意花点时间先写伪代码或者画流程图一样,前期的这点“麻烦”,能让最终的实现质量和鲁棒性,得到不成比例的回报。

而最核心的,是它赋予了 Agent 驾驭复杂任务的根本能力。对于那些需要长链条、多步骤,甚至需要反复试错和回溯才能完成的复杂任务,ReAct 几乎是唯一的选择。这个 Thought -> Action -> Observation 的循环,为模型提供了一个宝贵的“工作记忆”。它能通过回看自己之前写下的思考日志,来时刻提醒自己,长远的目标是什么、已经完成了哪些里程碑、下一步的关键路径在哪里。这使得它能够将一个庞大的任务,持续地、有逻辑地分解成一个个当下可执行的小步骤,而不会在漫长的流程中迷失方向。

和思维链是一回事吗 ​

这里很自然地会冒出一个问题。这和之前在第 9 章聊过的思维链(Chain of Thought, CoT)听起来很像,两者到底有什么区别?这个问题确实容易混淆。可以把 ReAct 看作是 CoT 的“实战交互升级版”。

CoT 是纯粹的单轮推演。它让模型在生成的文本里,进行一段不与外界发生任何交互的逻辑推演。它适用于所有必要信息都已经包含在 Prompt 里,只需要纯粹的逻辑和知识就能解决的问题,比如人人中学时代都做过的数学应用题。

而 ReAct,则是把这种“一步步推演”和“与现实世界互动”这两件至关重要的事情,完美地结合在了一起。它的每一步“推理”(Reasoning),都紧跟着一个会真实地改变环境,或者从环境中获取新信息的“行动”(Acting)。而这个行动的结果,也就是“观察”(Observation),又会成为下一步“思考”的输入。它不再是一次封闭的推演,而是一个与真实环境持续交互的“思考-行动”循环。

所以,这里有一条非常明确的建议。当准备构建任何一个需要与外部工具、API、数据库、文件系统等进行交互,并且需要执行超过一步操作的 Agent 时,请毫不犹豫地把 ReAct 作为默认基础架构。它前期可能会多花一点时间,去精心设计那个引导 ReAct 行为的 Prompt,以及编写解析其输出的逻辑。但这份前期的投入,会在后续漫长的开发、调试、迭代和维护阶段,节省下十倍,甚至百倍的时间和精力。

22.2 把 SOP 映射成状态机 ​

ReAct 的局限:高风险场景要的是确定执行 ​

ReAct 框架,赋予了 Agent 强大的自主规划和解决未知问题的能力。它不依赖固定的流程,每一步都由模型根据当前情况现场决定策略。在很多需要探索性、创造性的场景下,这种灵活性很有价值。

但是,换个场景来想一想。如果面对的是一家大型商业银行的贷款申请自动化审批系统,或者一家国际航空公司的全球航班起降智能调度中心,在这样严肃、高风险、对流程合规性要求到极致的场景里,还敢用这种每一步都现场决定的自主模式吗?

敢让它自行决定是否批准一笔数百万的贷款吗?敢让它临时调整一架载有三百名乘客的波音 747 的降落跑道吗?绝大多数工程负责人都不敢。

在绝大多数的企业级应用场景中,工程师所追求的,往往不是天马行空的灵活性,而是坚固的稳定性、可预测性和合规性。需要的是严格遵守既定流程的确定性执行,而不是全凭模型现场判断的自主决策。

回到客服这个熟悉的领域。假设要用 Agent 来自动化处理公司的客户服务工单。客服团队通常已经沉淀出一套标准作业流程(Standard Operating Procedure, SOP)。这套流程的每个步骤都来自实际经验的积累,不能轻易跳过。

这个流程,可能远比想象中复杂。它可能规定,当一个新工单进来时,必须先检查信息是否完整。如果信息完整,就要根据问题描述的关键词,将其初步判断为“技术故障”、“账单疑问”还是“功能咨询”。但如果初始信息不完整,比如用户只说了一句“你们的软件坏了”,那么系统必须自动向用户追问,直到获取到所有必要的信息(比如操作系统版本、软件版本、错误截图)为止。

在信息补全之后,系统再根据分类结果,将工单自动分配给最合适的处理团队。在团队处理期间,系统还要负责定时检查工单状态,如果超过 24 小时未响应,就要自动发送提醒邮件给团队负责人。当处理团队最终标记工单为“已解决”后,系统还要自动向用户发送满意度调查,并在用户确认或 72 小时无回应后,才允许正式关闭工单。

这个流程,每一步都是环环相扣,有明确的执行顺序和严格的条件分支。Agent 在这里进行任何形式的自主发挥,都是不能接受的。它在信息不全的情况下,就凭自己的“猜测”去做问题分类,可能会把一个紧急的技术故障,错误地分给财务部;它跳过“分配”步骤,自己尝试去“解决”一个它根本没有能力处理的复杂技术问题,也只会把事情搞得更糟。

在这样的需求面前,ReAct 那种开放式的思考模式,就显得约束不足了。需要一种新的、更具约束力的方法,把现实世界中这套严谨的业务流程(SOP),转写成 Agent 能够理解、并且必须严格执行的硬性规则。这就是所说的“SOP 映射”。

有限状态机:给业务流程建模 ​

从技术的本质上讲,要做的事情,其实就是用 Prompt,将一个复杂的、多状态的业务流程,精确地、无歧义地建模成一个有限状态机(Finite State Machine, FSM)。

“有限状态机”这个词听起来有点学术,但它的核心思想其实非常简单,日常生活里每天都在和它打交道。比如家里的洗衣机,它就是一个典型的状态机。它有“待机”、“进水”、“洗涤”、“漂洗”、“脱水”、“完成”这几个有限的、明确的状态。按下启动键(一个事件),它就从“待机”状态,跳转到“进水”状态,并执行“打开进水阀”这个动作。当水位传感器检测到水位已满(另一个事件),它又会从“进水”状态,跳转到“洗涤”状态,并执行“启动马达”这个动作。它绝不会在“进水”还没完成的时候,就开始“脱水”。

要做的,就是在 Agent 的 System Prompt 里,用严格的规定,为它清晰地定义出这套客服流程对应的状态机。这份 Prompt,将不再是启发式的、引导性的对话,而是一份接近“技术规格书”的强制性规定。

实战:把客服工单流程写成状态机 Prompt ​

下面就来设计一个处理上述客服工单流程的 Agent 的 System Prompt,看看怎么用自然语言,把程序化的、确定性的逻辑写出来。

这里不直接把一大段代码一样的 Prompt 端出来,而是描述构思它的过程。

先和业务专家坐在一起,为 Agent 定下它的核心身份和使命,写成这样:

“你是客服工单处理系统的执行 Agent。你的全部行为必须遵循公司定义的标准作业流程(SOP),该流程以状态机形式定义。任何情况下,你只能依据当前工单状态和状态机的转移规则决定下一步动作,不得跳过、合并或变更任何步骤。你的唯一目标:驱动工单按照状态机逐状态流转,直至工单关闭。”

接下来,就是最核心的部分,定义状态机本身。把业务流程图一个节点一个节点地翻译成 Agent 能执行的规则。

比如,对于第一个“新工单”的状态,可以这样描述:

状态定义:NEW(新工单)
- 进入条件:工单被创建时,处于 NEW 状态。
- 本状态职责:校验工单信息是否完整。
- 校验规则:`user_id` 字段格式有效;`description` 字段长度不少于 20 个字符。
- 转移规则 1(校验通过):调用 `classify_issue` 工具完成问题分类,工单状态更新为 `CLASSIFIED`。
- 转移规则 2(校验不通过):调用 `request_more_info` 工具,向用户说明缺失的信息,工单状态更新为 `WAITING_USER_INPUT`。

对于下一个“等待用户输入”的状态,可以这样规定:

状态定义:WAITING_USER_INPUT(等待用户补充信息)
- 进入条件:NEW 状态校验未通过。
- 本状态职责:等待用户提交补充信息,期间不执行任何其他操作。
- 转移规则(收到用户补充信息):不调用工具,将工单状态重置为 `NEW`,重新执行信息校验。

用这种逐条定规则的方式,把 CLASSIFIED、ASSIGNED、RESOLVED、CLOSED 等所有可能的状态,以及它们之间的跳转条件和需要执行的动作,都一一地、无歧义地定义清楚。

最后,再次强调它的工作流程:“执行约束:你的每一次回复都必须遵循 ReAct 框架。Thought 部分不得自由发挥,必须汇报三项内容:当前工单状态、做出判断所依据的状态机规则、即将执行的动作(Action)与目标状态(Next State)。”

代价与适用边界 ​

通过这样一份精心设计的、充满确定性逻辑的 Prompt,Agent 的行为模式就发生了根本性的改变。它从一个充满不确定性的、依赖直觉的概率性系统,变成了一个精确定义的、行为可预测的、确定性的流程执行引擎。它的每一次行动,都有据可查。

当然,这种 SOP 映射的方法,是以牺牲 Agent 的灵活性和创造性为代价的。它再也无法处理那些 SOP 之外的意外情况。但这个代价,在许多严肃的、对风险零容忍的企业级应用场景中,是值得付出的。它特别适合那些业务流程已经非常成熟和固化的领域,比如反复提到的财务审批、订单处理、IT 运维自动化,以及各种合规性检查。

实现这种系统的真正挑战,其实已经从“提示工程”本身,转移到了“业务分析”和“流程建模”。工程师需要和业务专家坐在一起,反复地推敲业务流程中的每一个状态、每一次跳转的每一个细节。这个过程,虽然辛苦,但其副产品,往往是对现有业务流程的一次深刻的梳理、简化和优化。这本身,就已经创造了巨大的价值。

22.3 把复杂任务拆给多个专才 Agent ​

到目前为止,所讨论的 Agent 有一个共同点,那就是不管每一步都是现场判断、边探索边调整的 ReAct,还是每一步都预先定死、照章执行的 SOP,从头到尾,都只有一个 Agent 在执行任务。

这在处理很多定义明确的任务时,是完全足够的。但有一类任务不是这个形态。目标只有一个大致方向,中间包含检索、分析、撰写等多个环节,每个环节需要的知识和工具都不一样。对这类任务,让一个 Agent 从头做到尾,往往做不好。

这就是多 Agent 协作(Multi-Agent Collaboration)要解决的问题。它不再要求一个 Agent 包揽全部工作,而是构建多个专才 Agent,每个 Agent 只负责一类自己擅长的子任务,再由一套协作机制把各部分工作衔接起来,共同完成一个复杂目标。

万能 Agent 为什么走不通 ​

构建高级 Agent 系统,面对的也是同一类问题。开篇提到的“策划下一季度的市场推广活动”,还有“撰写一份行业深度市场调研报告”这类任务,都是这种跨领域的复杂任务。一种直觉的做法是设计一个”万能 Agent”。给它配上几十个不同领域的工具,再写一份长达数千行、包含各种 IF/ELSE 逻辑的”万能 Prompt”,指望它独立完成所有环节。这条路通常走不通。

问题主要出在这份”万能 Prompt”上。任务种类一多,它就会变得臃肿,不同领域的指令互相干扰,改动一处往往牵连多处,最终无法维护。能力上也一样,什么都会一点的万能 Agent,搜集资料不如专门优化过搜索指令的 Agent 做得又快又全,分析数据不如专门配置了数据处理工具的 Agent 来得深入和专业。出错时的代价也更高。面对几千行的思考链,很难定位问题出在哪一步。

此时会出现一个疑问。Claude Code 这类通用 Agent 产品,既能写代码,又能做写作和分析,不就是一个运行得很成功的”万能 Agent”吗?

这里要区分两种东西。Claude Code 的”通用”指的是模型能力和工作台的通用。它面对的是人,由人来给方向、做拆解、验收结果,每个任务都在交互中完成。它并没有把一家公司的贷款审批流程或工单处理规则,全部塞进一份数千行的 Prompt 里,让它无人监督地端到端执行。事实上,Claude Code 处理复杂任务的做法恰恰是拆分。官方提供了子代理(subagent)机制,把搜索、代码审查这类专门任务交给拥有独立上下文的专职 Agent,避免把所有内容堆进一个对话。这是本章要讲的编排思路的工程实现,而不是它的反例。

所以,”万能 Agent 走不通”针对的是一种具体做法。它要求用单个 Agent、单份巨型 Prompt 承载一整套固定业务流程的全部规则,并期望它无人监督地端到端执行。通用助手和多 Agent 编排并不冲突,前者解决“什么任务都能搭把手”,后者解决“复杂任务怎么可靠地做完”。子代理是 Claude Code 这类通用助手产品的内置能力;对自建多 Agent 系统而言,仍需自己设计 manager-worker 协议与上下文隔离策略(参见 24.2 节 Harness)。

思维方式的转变也在这里。重心从优化单个 Agent 的提示词,转到设计整个协作系统。

经理-员工模式:分解、委派、整合 ​

在众多的协作模式中,最经典的是“经理-员工(Manager-Worker)”模式,也常称作“分层(Hierarchical)”或“编排(Orchestration)”模式。名称借自人类组织里的管理分工,指的则是同一种结构。一个 Agent 负责规划和调度,其余 Agent 负责执行子任务,信息在两类角色之间流动。

在这个模式里,至少需要两种角色定位截然不同的 Agent。

一种是经理 Agent(Manager Agent),负责全局的规划与调度。它不直接执行业务操作,搜索资料、写代码、做计算这些工作全部交给员工 Agent。这样设计是有原因的。经理 Agent 的上下文要用来保存任务规划和中间结果,一旦亲自执行子任务,具体领域的执行细节很快会占满它的上下文。它的核心职责可以概括为三件事,分解(Decomposition)、委派(Delegation)、整合(Synthesis)。

接收到用户的最终目标后,它按照定义在 System Prompt 里的规划与分解指令,把一个往往只有方向、没有细节的大任务,分解成一系列边界明确、可独立执行的子任务。

分解完任务,它接着做委派。每个员工 Agent 的定义里都写明了自己拥有的工具和能力,经理 Agent 对照这份清单,把每个子任务交给最适合执行它的那个员工 Agent。

执行期间,它还要持续跟踪每个子任务的进展,收集各员工 Agent 返回的中间结果(可能是原始数据、分析摘要、代码片段、文字草稿等),最后把这些材料整合成一份符合用户最初要求的完整交付物。

另一种是员工 Agent(Worker Agent),负责执行具体的子任务。每个员工 Agent 的职责都应该设计得单一、聚焦,只覆盖一个领域,只配备这个领域需要的工具。职责越单一,System Prompt 就越能写得精确,执行效果也越稳定。

搭建这样的系统时,模型的选择也有了新的自由度。经理 Agent 和员工 Agent,不必绑定在同一个模型上。大批量、可并行的员工任务,比如上百次检索和数据分析,交给 DeepSeek、通义千问 Qwen 这类开源系、价格友好的模型来跑,能把成本压下来;而负责规划调度的经理 Agent,以及最后负责成稿的角色,则可以交给能力更强的模型。这种按角色混搭模型的自由,是多 Agent 架构独有的优势。

三种专才 Agent 的分工 ​

以市场调研项目为例,可以按下面的分工配置一组 Agent。

信息检索专家(Research Specialist Agent),负责检索信息和甄别来源。它的 System Prompt 里写入了高级搜索技巧和信息甄别策略,能把一个模糊的业务问题,转化成一组高效的、能挖出深层信息的网络搜索查询。它的工具包括 web_search、read_pdf_from_url、academic_paper_search,以及一个可以访问付费行业数据库的 proprietary_database_query 工具。

数据分析专家(Data Analyst Agent),负责计算、统计分析和数据可视化。它本质上是一套运行在安全沙箱里的 Python 代码执行环境,核心工具是 run_python_code。它的 Prompt 里预置了 Pandas、NumPy、Matplotlib 等常用数据分析库的用法和最佳实践,让它能够写出高质量、高效率的分析代码。

文案创意专家(Creative Writer Agent),负责撰写最终报告。它比较特殊:不配备任何外部工具,全部能力来自经过调优的 System Prompt。这个 Prompt 把它的角色设定为一名曾在顶级咨询公司工作的资深商业分析师,并对它的语言风格、逻辑组织能力,以及将复杂数据转化为有说服力的商业洞察的能力做了针对性强化。它的工作,就是把一堆零散的信息点,组织成一篇结构严谨、观点鲜明的专业文章。

实战走查:市场调研的完整协作 ​

现在,把这一组 Agent 放进一个具体的市场调研任务,完整走一遍协作流程。

这一次,用户的初始需求依然是一条模糊的指令,“我需要一份关于全球智能咖啡机市场的深度分析报告,重点关注市场趋势、主要玩家和未来机会。”

第一步是分解与委派。经理 Agent 接到指令后,不会直接去调用搜索工具,而是按照定义在 System Prompt 里的规划与分解指令,用熟悉的 ReAct 框架,把思考过程完整写出来:

Thought: 用户的最终目标是一份深度市场分析报告。这是一个典型的、需要多阶段、多角色参与的复杂信息处理任务。根据我内置的“波特五力分析”和“SWOT分析”等商业分析框架知识,一份高质量的市场分析报告,必须包含以下几个不可或缺的核心模块:

首先,是市场概览,我们需要知道这个市场的盘子有多大,增长速度如何,未来的潜力在哪里。 其次,是竞争格局,我们需要知道牌桌上有哪些主要的玩家,他们各自的打法和实力如何。 再次,是消费者洞察,我们需要知道用户到底为什么会买(或者不买)这类产品,他们的痛点和爽点分别是什么。 最后,是技术趋势与未来机会,我们需要抬头看路,预测未来的风口在哪里。

好的,战略蓝图已经清晰。现在,我需要将这个蓝图,分解成一个个可以被具体执行的“工程包”,并委派给我的专家团队。

  • 市场概览和竞争格局的分析,本质上是信息搜集和整理工作,这正是“信息检索专家”的强项。
  • 消费者洞察,需要处理大量的、非结构化的用户评论和社交媒体数据,进行情感分析和关键词提取。这个任务需要两步走:先让“信息检索专家”把原始数据抓回来,然后交给“数据分析专家”去深度挖掘。
  • 技术趋势与未来机会的研判,需要结合前三者的所有信息,进行综合性的推理和预测。这部分工作,需要较高的战略眼光,可以由我自己(经理Agent)来初步完成,或者,如果我有一个更高级的“战略分析Agent”,我会交给它。
  • 当所有这些“原材料”都备齐后,最后的“烹饪”和“摆盘”工作,也就是报告的最终撰写,必须交给我们的“文案创意专家”来完成,以确保最终的出品质量。

计划制定完毕,现在开始执行第一步:委派第一个任务给“信息检索专家”。

Action:

json
{
"tool_name": "delegate_task",
"parameters": {
"to_agent": "InformationSearchAgent",
"task_description": "请搜集并总结近三年全球智能咖啡机市场的规模数据、权威机构预测的未来五年年复合增长率(CAGR),以及至少三篇行业报告中提到的主要市场驱动因素。"
}
}

第二步,员工 Agent 各自执行。系统接收到这个 delegate_task Action 后,会创建一个信息检索专家的实例,并把任务描述作为它的初始输入。信息检索专家接到任务后开始工作。它可能进行多次 web_search 调用,找到几篇来自 Gartner 或 IDC 的权威行业报告,再调用 read_pdf_from_url 工具,逐篇深度阅读这些数十页的 PDF 文档。

收集完毕,它会对搜集到的关键信息进行交叉验证和提炼,形成一个结构化的 JSON 对象,作为结果返回给经理 Agent。

第三步,经理 Agent 持续调度。收到第一份结果,它会把这个信息存入自己的上下文,把第一个子任务标记为”已完成”,然后根据总体计划派发下一个任务。它可能让信息检索专家继续去深挖竞争对手的财报和产品发布会纪要,或者在拿到足够多的原始用户评论数据后,再启动数据分析专家,让它去跑一个情感分析和主题建模的脚本。

整个过程里,经理 Agent 做的就是持续调度。它不断检查每个成员 Agent 的进度,协调它们之间的依赖关系,处理它们遇到的失败和异常,并根据最新的中间结果调整后续任务的安排。它也可以做并行调度。在信息检索专家还在检索竞争对手的负面新闻时,先让数据分析专家处理已经拿到的市场规模数据,提前把所有数据图表制作出来。

最后一步,成果汇总,最终交付。当所有的子任务都完成时,经理 Agent 的上下文里,已经汇集了各环节的产出汇总。有市场规模的精炼摘要,有主要竞争对手的详细 SWOT 分析,有消费者痛点的关键词云图,还有已经生成好、可以直接使用的数据图表代码。

经理 Agent 把这些素材整理好,交给文案创意专家,让它撰写最终报告。

Thought: 很好,所有的情报搜集和数据分析工作,都已按照最高标准完成。我现在手里,拥有了构建一份顶级报告所需要的所有“原材料”。现在,是时候将这些冰冷的、零散的素材,升华为一份有温度、有洞察力、有说服力的专业报告了。这个从“信息”到“智慧”的飞跃,非我们的“文案创意专家”莫属。我需要把所有材料,以一种高度结构化的方式提供给它,并对最终的成品,提出明确的、高标准的要求。

Action:

json
{
"tool_name": "delegate_task",
"parameters": {
"to_agent": "CopywritingAgent",
"task_description": "请根据我提供的以下所有材料,撰写一份标题为《全球智能咖啡机市场深度分析与未来机遇展望》的商业报告。报告的目标读者是公司的高层决策者,所以语言风格要求专业、精炼、有洞察力。报告必须结构清晰,严格分为四个章节(市场概览、竞争格局、消费者洞察、未来机会),并且在适当的位置,插入我提供的数据图表。最终成品请以Markdown格式输出。所有必需的材料如下:[这里是所有员工成果的、经过精心组织的结构化汇总]..."
}
}

最终,文案创意专家依据这些材料,输出一份结构完整、论证清晰的研究报告。经理 Agent 再将这份报告呈现给用户。多个专才 Agent 就这样分工协作,完成了这个单靠一个 Agent 很难做好的开放式任务。

收益与真正的难点 ​

这种“经理-员工”的多 Agent 架构,带来的好处已经超出了“提示工程”的范畴,进入了“系统工程”的层面。

它实现了高度的模块化与关注点分离。每个 Agent 的职责单一、内聚,System Prompt 可以写得精炼、聚焦,从而获得更好的性能和更低的出错率。再也不用去维护那份长达数千行、改动任何一处都可能牵连其他功能的“万能 Prompt”了。

它带来了强大的可扩展性与可维护性。如果将来,系统需要增加一项全新的能力,比如说,“根据这份市场报告,自动生成一份面向投资人的PPT演示文稿”,不需要去修改任何现有的 Agent。只需要开发一个新的、专门的“PPT 制作专家 Agent”,把它的工具与职责定义登记进经理 Agent 读取的配置里。此后经理 Agent 在分解任务时,就能把相关子任务委派给它,整个系统就此完成能力的扩展。

它还带来了更高的执行效率。一个优秀的经理 Agent,可以分析任务之间的依赖关系图(DAG),找出那些可以并行处理的节点,然后将它们同时派发出去,从而充分利用计算资源,大大缩短任务的总执行时间。

当然,也要认识到,构建这样复杂的系统,核心的挑战已经从“如何写好一个具体的 Prompt”,转移到了“如何设计好一个可靠的经理 Agent”。它的任务分解能力、员工选择策略、任务并行化的调度算法,以及处理员工 Agent 之间协同冲突的机制,是整个系统成败的关键和难点,需要投入比写单个 Prompt 多得多的设计精力。

22.4 人类在环,关键节点人来拍板 ​

Agent 系统,在引入了 ReAct 的自省能力、SOP 的流程规范,以及多 Agent 的协同机制之后,自动化程度越来越高,正在逼近一个可以 7×24 小时不间断运行的、高度自主的系统。但一个现实的问题也随之而来,这样的系统,能完全放手不管吗?

一个具体的风险场景。某天凌晨三点,负责这个系统的工程师正在熟睡。而他部署在服务器上的那个多 Agent 系统,正在自动处理一笔来自大客户的、价值数百万元的复杂采购订单。这个流程,需要调用库存系统、物流系统、财务系统,并最终生成一份具有法律效力的合同。真的能百分之百地放心,把这一切,完全、彻底地交给一个无法百分之百预测其行为的概率性系统去处理,中间不设置任何人工的检查点和干预机制吗?

万一,那个负责整体调度的经理 Agent,在第一步进行任务分解时,就对客户订单里的某个复杂条款,产生了根本性的误解呢?比如说,它把“分三期交付”理解成了“一次性交付”。那么,后续所有员工 Agent,无论工作得多么出色、多么高效,都会沿着一个完全错误的方向推进,最终产出一份会让公司蒙受巨大损失的错误合同。

又或者,在流程的中间环节,某个负责查询库存的员工 Agent,因为底层数据库的临时抖动,返回了一个错误的库存数据(比如把 100 件看成了 10000 件)。而经理 Agent 如果不做校验,就可能会基于这个严重失真的错误数据,继续派发后续的生产和物流任务。这种“错误的累积和放大”,在长链条的自动化任务中,是极其致命的,初始的一个小错误,一路传下去可能变成无法挽回的大问题。

这种一路走到底、无法中途纠正的风险,在任何严肃的、对准确性和安全性有要求的业务场景中,都是绝对不可接受的。完全封闭、无人监管的“全自动运行”不值得追求,那不是智能,那是失控。

所以,一个真正成熟、可靠、负责任的 Agent 系统设计,必须将人类在环(Human-in-the-Loop, HITL),作为一个核心的、不可或缺的、贯穿系统的设计原则。这个词在中文文献里还有“人机回圈”“人在回路”等译法,这本书统一叫人类在环。在整个自动化工作流的某些关键的、高风险的决策节点,主动地让流程“暂停”下来,将当前的进展、分析的结果,以及下一步的行动计划,用最清晰、最直观的方式,展示给一个拥有最终决定权的人类用户,请求他的确认、修改、或最终批准。

这个思想,其实一点也不新鲜。它源于现实世界中最普遍、也最有效的管理实践。一个经验丰富的项目经理,在带领他的团队,投入公司宝贵的研发资源,花费数周甚至数月的时间去开发一个新功能之前,他必须先写一份详尽的需求文档(PRD)和技术设计方案。然后,他必须拿着这份方案,去跟他的上级、产品总监、法务部门,甚至最终的客户,开一个气氛可能很紧张的“评审会”。只有当所有关键的干系人,都在这份方案上确认,甚至书面签字,这个项目才能正式启动。这个“评审会”,就是一个至关重要的、必不可少的人工检查点。它确保了大家在投入沉没成本之前,在同一个方向上达成了共识。

在 Agent 系统中,加入这样可控的“审批节点”,其价值是很大的。

再次回到那个市场调研的例子。经理 Agent,在完成任务分解和规划之后,它的下一个动作,不应该是立刻去 delegate_task。它的第一个动作,应该是把它的整个执行计划提交给人类用户来审批。

经理 Agent 的输出,将会是这样的:

Thought: 我已经根据用户的初始请求,制定了一个包含四个主要阶段、预计需要调用三个不同专家Agent的详细执行计划。这是一个复杂的、耗时可能较长的长任务。根据我内置的“审慎原则”,在正式启动并消耗计算资源之前,我必须获得用户的明确批准,以确保我的规划方向与用户的真实期望完全一致。因此,我将调用 request_human_approval 这个特殊的工具,来主动暂停流程,并等待用户的最终指令。

Action:

json
{
"tool_name": "request_human_approval",
"parameters": {
"title": "市场调研计划确认",
"plan_summary": "尊敬的用户,我已经为您制定了如下的市场调研计划,请您审阅并决定下一步操作:",
"plan_steps": [
{"step": 1, "description": "搜集市场规模与增长趋势的宏观数据。", "assigned_to": "信息检索专家"},
{"step": 2, "description": "深度分析市场上排名前五的竞争对手的产品线、定价策略与用户口碑。", "assigned_to": "信息检索专家"},
{"step": 3, "description": "通过分析社交媒体和电商评论,洞察消费者的核心讨论热点与未被满足的痛点。", "assigned_to": "数据分析专家"},
{"step": 4, "description": "综合以上所有信息,由文案专家撰写最终的深度分析报告。", "assigned_to": "文案创意专家"}
],
"user_options": ["批准计划并立即开始执行", "我需要修改计划"]
}
}

应用程序后端,在接收到这个 request_human_approval Action 后,就能识别出,这并不是一个需要去调用外部 API 的指令。它会识别出,这是一个需要与前端 UI 进行深度交互的特殊指令。于是,它会驱动前端界面,弹出一个经过精心设计的、非常友好的交互式对话框,将 plan_steps 等信息,用最清晰直观的方式,呈现给正在屏幕前等待的用户。

用户看到这个计划,他可能会觉得非常完美,完全符合他的预期,于是他会毫不犹豫地点击“批准计划并立即开始执行”。这时,前端会发送一个“批准”的信号给后端,后端再将这个“人类的观察结果”(Observation: User approved the plan without any changes.)喂给 Agent。Agent 收到这个批准之后,就会开始执行后续的庞大任务。

也可能,用户是一位深耕行业多年的专家,他觉得“TOP 5”这个范围太窄了,可能会遗漏掉一些正在快速崛起的新品牌。于是,他点击“我需要修改计划”,直接在界面上,将第二步的描述,手动修改成了“分析市场上所有主流(市场份额超过1%)以及三家新兴的、值得关注的竞争对手”。这个经过人类智慧修正的计划,会作为新的、更精确的指令,更新 Agent 的规划,让它接下来的所有工作,都集中在关键处。

这个看似简单的、增加了一个人工确认的步骤,为整个系统的健康和成功,带来了多重、巨大的价值。

它从源头上确保了方向的正确性。这是最核心、最根本的价值。它相当于在开工之前,对方案做的最后一次、也是最关键的一次确认。它能从根本上,避免 Agent 因为对初始需求的理解偏差,从第一步就走上错误方向,从而节省下海量的、本可以完全避免的计算资源、时间和机会成本。

它极大地增强了用户的控制感与信任感。当用户不再是一个被动的、只能焦虑地等待最终结果的旁观者,而是成为整个自动化流程中,拥有最终决定权的审批者时,他的心理体验会发生质的改变。他清楚地知道系统正在做什么,为什么这么做,并且在任何他认为必要的时刻可以叫停或修改。这种掌控感,是建立用户对复杂、不透明的 AI 系统信任的基础。

它还提供了一种处理模糊与歧义的有效机制。Agent 最头疼的,就是人类语言中无处不在的模糊性。当它遇到一个自己无法做出确定性判断的指令时,比如用户说“帮我找一些‘性价比高’的酒店”,它对“性价比高”的定义,可能和用户的真实想法,相去甚远。这时,一个设计精良的 Agent,就可以主动地、智能地触发一个人类在环节点,向用户发起一次澄清式的提问:“请问您定义的‘性价比高’,主要是指价格在500元以下,并且用户评分在4.5以上吗?还是说,您对地理位置有特殊的要求?”这种主动的澄清,远比它自己基于训练数据做一个自以为是的、大概率会出错的猜测,效果要好得多。

人类在环的设计,可以有非常多样的形式和粒度。它可以是任务开始前的“计划审批(Gating)”,也可以是流程进行中,当 Agent 遇到一个它自己也拿不准的低置信度决策时的“疑难求助(Clarification)”。它还可以是某个员工 Agent 提交了一份复杂的工作成果后,系统自动将其路由给一位人类领域专家,进行“质量审核与修正(Correction)”。甚至,当团队中的两个 Agent,对某个问题,基于不同的工具和数据,提出了相互矛盾的看法时,可以让人类来进行“最终仲裁(Tie-breaking)”。

设计一个优秀的人类在环工作流,其真正的挑战,在于找到正确的“干预时机”和“干预粒度”。不能让 Agent 每执行一个微小的步骤,都来请示汇报,那会把用户烦死,自动化也就失去了其核心价值,变成了一种光会添乱的摆设。但也不能从头到尾,对一个长达数小时的复杂任务,完全不闻不问,那又会把风险累积到不可控的程度。

这需要像一位经验丰富的产品架构师那样,去仔细地、深入地分析整个业务流程,识别出那些决策影响最重大、信息不确定性最高,或者失败成本最昂贵的节点,然后,就在这些最关键的节点,精准地设置人工检查点。

有一条核心的设计原则,值得始终记住。构建 Agent 的目标,从来都不是为了完全地、冷冰冰地取代人类。而是人机协同(Human-AI Collaboration)。让机器做它最擅长的、规模化的、高速的、不知疲倦的信息处理和重复性执行工作;让人类做自己最擅长的、需要深层领域知识、复杂价值判断、创造性思维和最终责任担当的战略性决策。这才是构建真正高级、可用、可信的智能系统的正确方向。

22.5 Pipeline 的串行、并行与路由 ​

当讨论深入到 SOP 状态机、多 Agent 的协同委派,以及人类在环的审批节点时,关注点其实已经在不知不觉中,从语言交互本身,转移到了系统流程和结构组织,工程师在这里扮演的,是“流程架构师”的角色。

现在所设计的,已经不再是一个单一的、线性的“请求-响应”过程了。正在构建的,是一个复杂的工作流管道(Pipeline),它由多个不同功能的处理单元有机地、动态地组合而成,其中有各有所长的专才 Agent、五花八门的工具、庞大的数据库,也有关键的人工审批节点。

如何科学、高效地组织这个管道的内部结构,直接决定了整个系统的执行效率、健壮性,以及未来的扩展能力。同样的组件,组织方式不同,系统的稳定性、效率和可维护性会差得很远。组织得好,各个处理单元各司其职、衔接顺畅;组织得差,流程混乱、问题不断。

在工作流设计这个领域,任何复杂的 Pipeline,归根结底,都可以看作是由三种最基本的连接模式组合、嵌套而成的。

第一种,也是最简单、最符合线性思维直觉的,是串行(Serial)模式。 一个处理单元的输出,直接成为下一个处理单元的输入。任务 A 必须百分之百地、无可争议地完成后,任务 B 才能开始。它们之间,存在着一种严格的、不可逾越的“因果”或“依赖”关系。

举个具体的例子,假设要构建一个“多语言新闻实时分析”的 Pipeline。它的核心流程,必然是高度串行的。

第一步,先从目标新闻网站,把那篇外文新闻的原文给抓取下来(fetch_article);第二步,把这篇抓取下来的原文,完整地翻译成能读懂的中文(translate_text);第三步,对这篇翻译后的、可能依然很冗长的中文文本,进行一次精准的摘要,提炼出核心观点(summarize_text);第四步,再从这个摘要中,进一步地提取出人名、地名、公司名等关键的实体信息(extract_entities)。这个流程中的每一步,都严重依赖于上一步的输出。翻译完成之前,做不了摘要;连原文都还没抓取到的时候,更是无从翻译。

这种模式的优点,在于它的逻辑非常清晰,因果关系明确,因此非常容易实现、理解和调试。当整个流程出了问题时,可以一个环节一个环节地去排查,很容易就能定位到问题出在哪一步。但它的缺点,也同样明显,执行效率是最低的。整个 Pipeline 的总耗时,约等于所有步骤耗时的简单总和。如果其中任何一个环节,是一个耗时很长的性能瓶颈(比如那个翻译模型需要很长时间来处理长文章),那么它就会把整个流程拖慢。

第二种,是并行(Parallel)模式,这是提升系统吞吐量的关键手段。 当需要处理一大批互相之间没有依赖关系的、同质化的任务时,串行模式那种一个挨一个排队处理的方式,就显得太低效了。并行模式的核心思想,就是把这批任务,同时分发给多个独立工作的处理单元,让它们同时开工,最后再把各自的结果汇总到一起。

再举个例子,假设产品刚刚上线了一个新功能,想快速地分析社交媒体上用户对这个新功能的第一波反馈。短短一个小时内,可能就收集到了成千上万条相关的用户评论。每一条评论的情感分析(是压倒性的好评,还是毁誉参半,抑或是大面积的差评),都是一个完全独立的事件。分析第一条评论的结果,并不会以任何方式,影响第二条评论的分析。

如果这时还用串行方式,让一个 Agent 一条条地读和分析,等分析完,热度早就过去了。正确的做法是启动并行模式。比如说,根据服务器算力同时启动 100 个情感分析 Agent 的实例,把这一万条评论切分成 100 个“任务包”,每个包 100 条,再同时分发给这 100 个 Agent。这 100 个实例会同时开始工作。原来需要数小时的串行任务,现在几分钟内就能全部完成。

当然,同时跑 100 个 Agent 实例,成本就是实实在在的账单。这类大批量、可并行的任务,正适合沿用前面多 Agent 协作一节的那套搭配,交给开源系、价格友好的模型去跑,把成本压下来;把需要统筹、审核和最终成稿的角色,留给能力更强的模型。

这种模式的优点,是能够极大地提升系统的吞吐量,实现真正意义上的规模化数据处理。这是所有高性能计算和大数据系统的基础。但它也引入了新的工程复杂性。需要一个高效的“分发器(Dispatcher)”来分配任务,还需要一个可靠的“收集器(Aggregator)”来安全地合并最终的结果。此外,还要仔细地考虑资源管理的问题,比如如何动态地控制并发的数量,以防止瞬间的巨大流量,把下游系统(比如调用的 API)给压垮。

第三种,是路由(Routing)模式,它让工作流具备了按条件做决策的能力。 在很多时候,一个工作流的后续走向,并不是一成不变的,而是需要根据当前正在处理的数据的某些关键特征,来动态地决定下一步到底该走哪条路。这就需要在 Pipeline 的关键分叉点,设置一个在工作流引擎里称为“条件网关(Conditional Gateway)”的组件。它会检查每一条流经的数据,然后根据预设的规则,决定这条数据该走哪条分支。

SOP 映射那一节深入讨论过的客服工单系统,就是一个最典型的路由模式应用。当一个新工单进来后,一个专门负责分类的 Agent(它扮演的就是“路由器”的角色),会先对工单的内容进行深度分析。

然后,它会根据分析的结果,做出一个关键的路由决策:IF 这个工单的类型,判定为“紧急的技术故障”,THEN 将工单立刻路由到那条由资深工程师组成的、拥有最高优先级的“红色紧急处理 Pipeline”;IF 工单的类型,判定为“普通的账单疑问”,THEN 将其平稳地路由到那条财务部门同事处理的、遵循标准工作时间的“蓝色常规处理 Pipeline”;ELSE (对于所有其他无法明确分类的疑难杂症),则将其路由到那条由一线客服专家组成的、负责兜底的“灰色疑难问题 Pipeline”。

每一条 Pipeline 后续的处理流程、SLA 要求,以及参与的人员,都可能完全不同。

这种模式的优点,在于它能够构建出非常灵活的、能够智能地适应不同情况的、具有复杂业务逻辑的动态工作流。但它的缺点,也恰恰在于,路由规则的设计本身,可能会变得异常复杂。如果业务逻辑中,存在着大量的、层层嵌套的条件分支,那么整个工作流的结构可能会变得错综复杂,给日后的理解、调试和维护带来巨大的挑战。

一个真正强大的、企业级的、能够处理真实世界复杂问题的 Agent 系统,在其内部,往往都不是单一的模式,而是一个由这三种基本模式,经过精心编排、层层嵌套而成的复杂混合体。

之前讨论的那个负责整体调度的“经理 Agent”,从某种意义上说,它的核心职责之一,就是根据用户的原始需求,动态地去生成和指挥这样一个混合了串行、并行和路由逻辑的、高效而又可靠的执行计划(Pipeline)。

它可能会生成一个像下面这样经过多方权衡的、高度复杂的计划。

首先,在阶段一,它会采用并行启动的策略,来最大化信息搜集的效率。它会同时启动两个并行的子流程。任务 1.1,是一个串行的子流程,它让信息检索专家 A,先去网上搜索最新的市场报告,然后读取 PDF,最后提炼出关于市场规模的宏观数据。任务 1.2,是另一个串行的子流程,它让信息检索专家 B,同时去爬取主要竞争对手的官方网站,然后从混乱的 HTML 中,提取出结构化的产品列表。

然后,在阶段二,它会设置一个人工审批节点,这个节点本身,就是一个关键的路由器。它会等待阶段一的所有并行任务全部完成,然后将专家 A 的摘要和专家 B 的列表,汇总成一份清晰的简报,提交给人类用户进行审批。IF 用户批准了这份计划,THEN 整个工作流,就进入阶段三。ELSE (如果用户认为竞品列表不准确,并手动修改了它),THEN 经理 Agent 就需要根据用户修改后的列表,动态地、智能地重新规划后续的所有步骤。

在阶段三,它会采用“扇出并行(Fan-out Parallelism)”这个高级模式。它会根据用户在阶段二最终确认的那个竞品列表(比如说,用户最终圈定了 3 个最关心的竞争对手),并行地为每一个竞争对手,启动一个独立的、耗时可能会很长的“深度分析”子流程。这三个子流程会同时推进,各自完成对一个竞品的深入分析。

在阶段四,它会执行一个“收集与串行收尾”的操作。它会等待阶段三的所有并行分析全部完成。然后,它会将所有分析结果,分门别类地收集起来,整理成一个逻辑清晰、内容完整的上下文,最后,再串行地、一次性地传递给“文案创意专家”,让它基于这些最完整、最全面的信息,去完成最终的分析报告。

经过这种精巧的、多层次的 Pipeline 设计,一个复杂 Agent 系统能够同时兼顾三件事,用并行计算榨干系统性能、提升效率,用串行和路由保证核心业务逻辑的严谨性,再穿插人工节点,确保方向的正确性和最终结果的可靠性。

到了这个阶段,所思考和解决的问题,已经远远超出了“如何写好一句话,让模型能够听懂”的范畴,正式进入了真正的“系统工程(Systems Engineering)”的领域。现在设计的,是一个个自动化的、智能的“数据处理与决策的流水线”。这要求工程师,必须具备跨领域的、复合型的知识结构。既要懂 LLM 的能力和局限,又要懂软件架构的原则和权衡,更要能深入地理解所要服务的那个业务流程的内在逻辑和痛点。


本章总结 从提示工程师到智能系统架构师 ​

这一章的视角,经历了一次重要的扩展。从在微观尺度上打磨单个组件(比如一个具体的 Prompt,或者一个单一功能的 Agent),上升到在宏观尺度上组织一个复杂而有序的系统,也就是一个由多个 Agent、大量工具、严谨规则和人类智慧共同组成的复杂协同系统。

从那个最根本、最棘手的痛点,也就是 Agent 行为的不可解释性出发,这一章学习了 ReAct 这个强大而又简洁的范式。它让 Agent 在每一次行动之前,都必须先写出推理过程,并留下可检查的记录。这个“思考-行动-观察”的循环,不仅让调试黑盒里的中间过程变得可以逐步查看,也给了 Agent 处理复杂、长链条任务所需的规划、反思与记忆能力。它是后续构建一切高级 Agent 的基础。

在 22.2 一节,处理的是对确定性和合规性要求严格的企业级场景。SOP 映射的方法,能把现实世界中那些严谨的、不容出错的业务流程,精确地、无歧义地建模成 Agent 必须严格遵守的“状态机”。哪些环节交给 Agent 的自主判断,哪些环节交给固定流程,这个边界要想清楚。想清楚之后,就能构建出在严肃的商业环境中 7×24 小时稳定运行的可靠系统。

在 22.3 一节,讨论了多 Agent 协作。既然“万能 Agent”走不通,就换一条路,沿用“经理-员工模式”,构建多个各司其职的专才 Agent,由经理 Agent 负责分解、委派、整合,由员工 Agent 各自执行子任务。面对复杂任务,这种分而治之、专业分工的做法,比把全部工作压给一个 Agent 更可靠,也更容易维护。

在 22.4 一节,视角转回到最终服务的对象“人”。人类在环正是为此设置的干预机制。在那些关键的、高风险的、模棱两可的决策节点,让人类的智慧、经验和价值观介入进来,做最终决定,这不是对自动化的妥协,而是对系统可靠性和用户信任的保障。值得追求的,是人与 AI 各展所长的协作。

在 22.5 一节,用Pipeline 设计的视角,重新审视和组织所构建的一切。串行、并行、路由这三种最基本的连接件,可以编排和组织整个复杂的工作流,让每一股数据流都高效、安全、准确地流向它应该去的地方。

走完这一章,可以看到工程师角色定位的变化。“提示工程师(Prompt Engineer)”,一个每天大部分时间都在琢磨如何调整措辞、变换句式、优化示例的角色,只是这个方向的起点。

从这一章开始,要像设计一个系统那样,为每一个 Agent 角色定义职责和工作方式,让它们在明确的编排下协同完成复杂任务。

也要像一个系统集成者,分析任务的结构和约束,安排不同的专才 Agent 在不同的阶段协同工作,去完成一个又一个单个 Agent 完成不了的目标。

再往上,就是“智能系统架构师(AI Systems Architect)”的角色。所设计的,将从具体的代码行扩展到智能体之间的交互协议,从数据的存储格式扩展到数据与决策的流动路径,从用户界面的像素扩展到自动化与人类智慧的融合接口。

这,才是“Prompt Engineering”这个词汇中,那个人们常常忽略的后缀“Engineering(工程)”的真正含义。它要构建的不是只能演示一阵的聊天应用,而是把《数据密集型应用系统设计》里讲的那套可靠性与可维护性标准用到智能应用上,做出能长期稳定支撑真实工作的系统。

参考资料 ​

  1. Yao, S. et al. (2023). ReAct: Synergizing Reasoning and Acting in Language Models. ICLR 2023(Oral), arXiv:2210.03629. https://arxiv.org/abs/2210.03629
  2. ICLR 2023 虚拟会场 Oral 6 Track 6 议程页(ReAct 为该 Oral session 的报告论文之一). https://iclr.cc/virtual/2023/session/14954
  3. Google Research. ReAct: Synergizing Reasoning and Acting in Language Models(作者团队含普林斯顿大学与 Google Research Brain Team). https://research.google/blog/react-synergizing-reasoning-and-acting-in-language-models/
  4. Kleppmann, M.(马丁·克莱普曼). 《数据密集型应用系统设计》(Designing Data-Intensive Applications 中译本). 中国电力出版社, 2018.
  5. Anthropic. Claude Code Subagents(官方文档:子代理为处理特定类型任务的专门助手,拥有独立上下文,避免辅助任务充斥主对话). https://code.claude.com/docs/en/sub-agents