前面几篇我们一直在拆循环内部:模型怎么输出一次工具调用,观察结果怎么喂回去,什么时候该停,工具报错之后怎么办。但真正动手写那行 while 之前,还有一个更靠前的问题:这件事到底需不需要这个循环?

很多团队一上来就把智能体套上去,结果钱多花了、调试变难了、正确率反而降了。Anthropic 在总结与几十个团队的实践后给出一条反直觉的结论:表现最好的系统,用的往往是简单、可组合的模式,而不是复杂框架——第一步要考虑的,可能是「根本别做智能体系统」1。这一篇就讲清:同一件事,什么时候预先编排好的固定流程就够了,什么时候才真需要让模型自己决定下一步。

先分清两件事:控制流归谁

先把术语摆正:这里的「工作流」和「智能体」不是两个产品,而是同一套积木的两种摆法1。

  • 工作流(workflow):大模型和工具的调用路径被一段预先写好的代码串起来。你先决定第一步调谁、拿到结果后走哪个分支、哪一步去调哪个工具。
  • 智能体(agent):模型在运行时自己决定下一步做什么、调哪个工具、什么时候收尾。

差别只有一句话:那张「谁调用谁、下一步往哪走」的图,归代码还是归模型。 注意这不等于「有没有用到工具」——工作流里照样能调工具,区别是调哪个、什么时候调由代码写死,不是模型临场挑。

固定流程长什么样

「固定流程」不是一条直线,它有几种常见形状:

  • 提示链(prompt chaining):把任务拆成固定顺序的几步,每一步吃上一步的输出。中间还能插一段普通代码做检查——比如上一步要求返回 JSON,就先校验它能不能解析,不能就提前终止,别把垃圾往下传。
  • 路由(routing):先给输入分类,再送去对应的专用处理路径,而不是用一个提示凑合所有情况。
  • 并行(parallelization):一批互不依赖的子任务同时跑,最后汇总结果。

这三种的共同点是控制流全在代码里:每次运行发几次请求、花多少 token、最慢多久,你都能提前算出来。

判断标准一:分支能不能提前写下来

最实用的一句是:在模型跑起来之前,你能不能把这件事的流程图画出来? 能画出来,就用工作流;画不出来——因为下一步取决于上一步真正返回了什么——才需要让模型自己决定2。

这个测试测的不是「任务复不复杂」。一个二十步的流水线照样是工作流;反过来,三步而每一步都要看着结果临场判断的任务,也照样得让模型自己走。真正让流程图画不出来的情形通常有两种:候选步骤本身就不固定(要改几个文件、要查几轮日志,事先不知道),或者 下一步依赖上一步的语义内容(看到那条报错,才知道该去查哪个服务)。

还有一条更严的补充:如果你能把输入空间明确写出来——可能的输入就那么几类——那你要的其实是解析器加一个 switch,不是智能体。真正让智能体挣得回成本的是 开放的输入空间,比如「一封客户来信」这种没法穷举的输入3。

绘制中

判断标准二:错了以后能不能被发现

这条比第一条更容易被漏掉。就算第一条说「可以放手」,还要追问:这个任务判对判错容易吗?判错的代价大吗?

  • 如果成功标准能用代码校验——输出能过 schema、测试能跑通、记录确实写进了数据库——那你大可以放心让模型自己决定路径,因为它每次试探都有个确定的验证器兜底,不合格就重来。
  • 如果错一次代价很高(医疗结论、财务报告、安全分级),而又没有代码验证器,那答案是:不要纯智能体。要么加人工审核,要么退回固定流程。

这里有个细节值得记住:验证器要验得住。 一次成功的写库操作能证明格式合法、字段齐全,但证明不了抽出来的那个发票号是 对的那个。格式正确、数值错误,照样能顺利写进去3。这种情况需要的是语义层面的交叉核对(拿同一份文件上另一个字段对一遍,或向开票系统要一个校验码),而不是格式校验。

取舍:多花的到底是什么

工作流的代价是「写死了就不灵活」:输入分布一变,硬编码的分支就失效。智能体换来的是适应变化的能力,代价是三样东西:

固定流程自主循环
控制流代码模型
每次调用的模型次数固定,可预算模型自己定
延迟可预估波动大
出错路径可复现、可打点要记下每次输入输出才能复现
适用场景输入稳定、分支可枚举输入开放、下一步依赖上一步

其中最容易被低估的是 可靠性按步数打折。假设每一步正确率 99%,十步串起来只剩 0.9910≈90%0.99^{10}\approx 90\%;步数再多,掉得更快2。工作流之所以稳,不只是因为它简单,而是因为它把「会错几步」变成了一个你能提前写死的常数。

最常见的一版:混合

真实系统基本都落在中间:用固定流程当骨架,把自主权塞进一个受约束的环节里。 两种常见摆法:

  • 让确定性的主管在顶层负责路由,只把真正需要判断的那一步交给模型自由发挥;
  • 反过来,让模型出计划,具体执行交给确定性代码——模型决定「做什么」,代码负责「怎么做」。

这样最坏的情况被框在一个小格子里:错了也就是某个节点的输出不合格,重试或者兜底都简单。LangChain 给同类场景的建议也是这个顺序:先加工具,再考虑加智能体4。

落地的顺序

先写最简单、跑得通的东西:一次普通模型调用,配上合适的检索和几个例子,往往就够了。不够,再加工具;还不够,再加一步链式调用、加个分支判断;只有当评估数据明确显示「必须把控制权交给模型」时,才去做真正的智能体。

要避开两个念头:因为 demo 效果惊艳就上智能体,以及 还没建好评估就扩大自主权。循环是一件很贵的工具,贵在它把控制流让给了模型。

所以这一篇的判断标准就两条:分支能不能提前写下来,错了能不能被及时发现。 两条都过关,才值得把那行本该属于你的 while,交给模型来决定怎么转。