一个 Agent 项目开始变复杂时,团队最容易做的动作,是再加一个 Agent。

需求来了,给它配一个 Planner。Planner 的结果不稳定,再上一个 Reviewer。工具调用太杂,拆一个 Router。最后你会得到一张看起来很像生产级架构的图,方框很多,箭头很漂亮,日志也终于开始滚动。只是用户问了一句「为什么这次没改对」,没人能在十分钟内回答。

Anthropic Applied AI 团队最近给出了一份反直觉的建议,很多 Router、Planner 和领域子智能体,并不该天然留在 orchestrator 下面。有 skills 的单 Agent 循环,常常比一提示全包和多 Agent 编排质量更高,成本与延迟也更低。有客户把多层结构收回单循环后,运行时间大约快了两倍。

我觉得这条建议比某个框架又支持了多少节点重要得多。它戳到 Agent 工程里一个常被忽略的问题,复杂度不是免费买来的可靠性。你加进来的每一个角色,都在把上下文、状态、责任和验收往更多地方推。

这篇不打算劝你把所有多 Agent 系统拆掉。复杂任务确实有边界,有些边界不拆会更危险。但如果你正在用 LangGraph、Spring AI 或自建工作流编排一个 Agent,我想认真聊聊,什么时候拆分是在解决问题,什么时候只是把问题画成了流程图。

那个看着很专业的 Agent 团队,为什么常常跑得别扭

故事通常是这样的。

一个客服 Agent 要查订单、解释规则、发起退款。第一版只有一个模型和几个工具,能跑,但偶尔会先退款再查资格。于是团队增加 Planner,让它先生成计划。后来发现 Planner 会漏掉风控约束,又增加 Policy Agent。再后来不同业务线要接入,于是 Router 根据意图分发到订单、物流、售后三个专业 Agent。每个 Agent 都留了一段自己的 memory,每次都把结论交给下一个人。

架构图更完整了,真实体验却未必更好。

因为每一次交接都要发生四件事。上游要把它认为重要的信息压缩成文字,下游要猜这段文字有没有漏东西,下游要决定能不能相信它,出错后还要有人把责任倒着追回去。模型不会因为名字从 Agent A 变成 Agent B,就自动获得组织协作能力。它只是又读了一次不完整的上下文。

这不是说角色拆分不行,而是说很多拆分把「提示词太乱」误诊成了「人手不够」。

你想想看,一个资深工程师处理线上告警时,并不会先把自己硬拆成监控工程师、SQL 工程师、修复工程师,再靠三份摘要接力。他会在同一个任务上下文里看指标、读日志、检查最近发布、形成判断,然后根据权限执行。中间可能调用不同工具,甚至找人确认,但任务认知并没有被无端切断。

单循环 Agent 追求的就是这种连续性。一个主 Agent 持有目标、工作状态和工具权限,在循环中观察、行动、核对,再决定下一步。skills 不承担第二个大脑,它们更像经过整理的操作手册和受约束的工具入口。

这两者差别很大。

把能力装进 skills,不是把人塞进队伍

很多团队把 skills 当成一堆 Markdown 文档,这个理解太轻了。一个好的 skill 至少要把某类工作的可重复部分固定下来。

它应该写清触发条件。比如用户说要排查支付回调重复,不是泛泛地丢给一个「后端专家」。它还应该列出要读的系统边界、需要查询的指标、允许调用的工具、输出必须包含的证据,以及失败时应当停止还是转人工。

拿 Java 和 Spring 场景举个很实际的例子。假如主 Agent 收到「订单偶发重复扣款」这个任务,正确的 skill 不是一句「分析代码并修复」。它可以要求 Agent 按顺序检查幂等键的生成和存储、消息消费的 ack 时机、事务边界、支付渠道回调的重试语义,再把具体订单号、日志时间窗和数据库证据放进结论。主 Agent 仍然在同一个循环里工作,skill 则把人类已经验证过的排障顺序带给它。

这样做有两个好处。

第一,技能是可审计的。你可以 review 一个 skill 的权限和步骤,就像 review runbook。第二,技能不会天然丢失当前任务的关键细节。主 Agent 刚看到的异常堆栈、刚查到的 traceId、用户限定的时间窗,都还在眼前。

反过来,若把这项排查交给 Database Agent、Code Agent 和 Summary Agent,后面那两个角色能否拿到同样的现场信息,全看前面的摘要写得好不好。摘要一旦把「只在异步回调重试时发生」压缩成「存在重复扣款」,排查方向可能从第一步就歪了。

我自己一直觉得,Agent 的第一性能力不是分工,而是保持任务事实不走样。

真正该拆开的,不是角色名,而是边界

单 Agent 循环并不等于一个 prompt 包打天下。那样同样会失控。关键在于把边界拆对。

有三类边界,拆开通常是划算的。

权限边界

只读检索和执行生产变更,应该是两条不同的路径。能看到客户数据的 Agent,不该顺手拥有删库或打款权限。这里的分离不是为了模拟一个团队,而是为了缩小爆炸半径。

比较稳妥的方式,是主 Agent 负责调查和拟定变更,执行工具把参数、审批人和回滚条件卡住。高风险动作还要通过确定性的 policy check。不要指望另一个「安全 Agent」凭感觉替你兜底,它自己也会误读上下文。

上下文边界

任务很长、材料很大,或者来源之间存在隔离要求时,硬把所有内容塞进一个 context window 并不聪明。此时可以让子任务做有界检索、抽取或计算,再返回结构化产物。

重点在「有界」。输入是什么、输出 schema 是什么、允许看哪些数据,都应该写出来。让 Research Agent 漫游互联网找答案,和让一个受限 worker 从指定文档里提取五个字段,工程风险完全不是一个量级。

验证边界

生成与验证不该由同一段自由发挥的文本完成。代码 Agent 可以提出 patch,但测试、静态检查、权限检查、金额校验这些环节,应该尽量由确定性工具完成。模型负责判断「下一步该跑哪个验证」,不负责宣布「我已经验证过了」。

这块尤其适合接进 CI/CD。让 Agent 生成一个修复分支,触发单测、集成测试和 lint,把失败输出送回主循环。通过标准由流水线说了算,不由 Agent 的自我评价说了算。

所以不是单 Agent 对多 Agent 的二选一。更准确的说法是,认知可以集中,权限、数据和验收必须隔离。

多 Agent 真正付出的账,远比 token 多

谈多 Agent 时,大家先想到的往往是 token 成本。这个账当然要算,但它甚至不是最贵的那一项。

更贵的是协调税。

每个子 Agent 都要有任务描述、上下文包、输出格式和失败处理。一个 Planner 多写一轮,后续所有 worker 都要读它的计划。一个 Router 路由错了,后面做得再专业也没有用。一个 Reviewer 给出模糊意见,主流程还得决定是否返工。调用次数、延迟和上下文重复只是看得见的部分。

还有一笔隐形账,调试税。

线上失败后,你究竟要看哪条链路。是 Router 理解错了,Planner 的前提错了,还是 worker 在摘要里漏了一个约束。每个节点都有自己的 prompt、模型版本、工具权限与 memory,复盘会从「复现一次调用」变成「复现一次分布式叙事」。这话听着有点刺耳,但不少多 Agent 系统的可观测性,仍停在把一堆自然语言中间件串到 trace 里。

有 trace 不等于有解释。

对 Channing 这类做平台工程的人来说,这里可以套用熟悉的分布式系统直觉。服务拆分不是为了让架构图更现代,而是为了独立扩缩、独立演进、隔离故障。若两个服务总是同步调用、共享同一个事务事实、任何一个出错都会让另一个无法完成任务,拆开只会增加网络和一致性成本。

Agent 也是一样。没有独立目标、独立状态、独立权限和独立验收的所谓子 Agent,大概率只是一次昂贵的函数调用。

先把主循环做厚,再考虑横向编排

如果现在让我给一个团队改 Agent 架构,我不会从画新的 DAG 开始。我会先追问一个问题,主循环是否真的具备完成任务的基本条件。

它要能拿到清晰目标,知道当前已经做了什么,知道哪些工具可用,也知道用什么事实判断成功。没有这些,叠多少角色都只是放大不确定性。

一个可落地的主循环,通常可以长成下面这样。

在落地时,我建议别急着把这个循环塞进一个万能节点。可以把它当成一个任务状态机来设计。任务刚进来时先写入不可变的原始诉求和约束,随后每一轮只追加观察、行动和验证记录。这样用户临时补充了「不要碰生产」或者「只处理华东区域订单」,系统能明确看到这是哪一轮加入的限制,而不是让新 prompt 覆盖旧记忆。

状态里的证据字段也别做成一段大文本。日志查询最好保留查询语句和时间范围,代码结论保留仓库提交或文件定位,外部资料保留 URL 与抓取时间。模型可以据此归纳,工程师也可以不经过模型直接复查。真正出了事故时,这些枯燥字段比一篇漂亮的执行总结有用得多。

还有一个容易被忽略的点,循环需要有停止条件。很多 Agent 失败不是能力不够,而是不知道何时该承认信息不足。连续两次工具返回同类错误、关键前提无法验证、动作将跨越权限等级时,都应该把任务转成带证据的人工待办。让 Agent 停下不是示弱,它是在保护系统和用户。

1
2
3
4
5
6
7
接收目标与约束
-> 读取当前任务状态
-> 选择 skill 和工具
-> 执行一次有证据的行动
-> 运行确定性验证
-> 记录结果、失败原因与下一步
-> 未满足完成条件则继续

这里的状态不要只留在对话历史。把任务 ID、已调用工具、关键证据、待验证假设、重试次数和审批状态持久化。LangGraph 之类的状态图工具能帮上忙,但它不是答案。真正重要的是状态字段要服务于复盘,而不是为了凑一份 schema。

再往前一步,可以给每个 skill 明确四个契约。

  • 输入契约,哪些事实必须已知,哪些字段不能猜
  • 行动契约,允许调用什么工具,最大重试次数是多少
  • 输出契约,返回什么结构化结果和证据链接
  • 失败契约,何时中断,何时要求人工确认

这套东西看上去没有「Agent 群体协作」酷,却能让系统逐渐可测。你能做离线回放,能统计哪个 skill 反复失败,也能知道成本到底花在检索、推理还是无效重试上。

复杂度该晚一点来。

别凭感觉决定合并,给架构做一次小实验

这件事不必靠信仰站队。挑一个近期真实任务,准备同一组脱敏输入和同一份成功标准,让现有多 Agent 流程与收回后的主循环各跑二三十次。记录完成率、人工介入次数、端到端耗时、工具调用数、失败后定位耗时。别只看一次跑通的演示,随机性会把一次好运伪装成架构优势。

我会特别看两项数据。第一是首次有效行动前的时间,系统究竟花了多久才开始查真实日志、读代码或运行测试。第二是证据覆盖率,最终结论中的每个关键断言,能否回指到工具输出或可复查产物。前一项衡量协调税,后一项衡量系统有没有在用流畅文字掩盖空白。

如果收回单循环后,成功率没有下降,耗时和定位成本却明显减少,答案就已经很清楚。此时保留那些角色名称,只是在维护一种心理上的安全感。反过来,若拆出的 worker 在并行任务上稳定提高吞吐,且失败能够被独立重放,它才配拥有自己的生命周期和监控面板。

哪些信号告诉你,子智能体真的该回来合并

如果你的系统出现下面几种情况,我会优先尝试合并,而不是继续加节点。

一是子 Agent 的输入总要重复粘贴主任务背景。它没有独立上下文,只是被迫重新阅读。

二是多个 Agent 操作同一份任务状态,却靠自然语言同步。比如一个更新了工单状态,另一个还在按旧状态制定计划。这是状态所有权没定义清楚。

三是失败分析总落在「模型没理解」上。很多时候不是模型不理解,而是约束散落在不同 prompt 里,谁也看不到全貌。

四是你为了让 Router 做对,写了越来越长的路由 prompt。要是分类结果仍需要主 Agent 二次判断,Router 就不该当成独立智能体。把它降成主循环里的一个受测分类步骤,或许更诚实。

五是团队很难说清每个 Agent 的独立 SLA。没有独立成功标准的节点,通常也没有必要独立存在。

当然,反方向也成立。若一个 worker 可以在严格输入输出下异步运行,比如批量解析文档、跑大量测试、针对多份独立材料做检索,它完全可以拆出去。它返回的不是「我想了想」,而是一份可验证的产物。这种并行才会真的提高吞吐。

别把组织结构的焦虑交给模型

多 Agent 之所以迷人,有一部分原因是它很像组织。我们习惯把复杂工作分配给不同角色,也自然会觉得模型有了 Planner、Coder、Reviewer,就像组建了一支小团队。

但软件里的角色名,不会制造责任感。

人类团队能协作,是因为成员有长期记忆、共同语境、责任制度,也会在交接不清时追问。Agent 没有这些默认能力。你若没有把共享状态、工具权限、交接格式和验收规则工程化,所谓协作只是在一条调用链里生成更多文字。

Anthropic 那份建议给出的不是一个反多 Agent 的口号,它是在提醒我们先把系统做简单,直到简单真的不够用。先让一个主 Agent 用好 skills、状态和验证工具。只有当任务存在可证明的独立边界,再让 worker 离开主循环。

一开始那张有很多箭头的图,未必是成熟的标志。有时它只是告诉你,系统还没有决定谁该对结果负责。

来源