Agent开发入门系列第 7 篇 · 读这一篇需要 6 分钟
系列导读:这个系列不追热点,只把 Agent 架构里那些密度极高、一次读不透的概念,一个一个拆开。
先讲一个我见过的事故。
某团队做了一个订单处理 Agent:核实身份、匹配库存、调用支付、发货通知。测试环境跑得顺,于是改了一件事——这几步写死太麻烦,不如让 Agent 自己决定下一步。
上线第一周,Agent 遇到一个从没出现过的分支:某类订单金额超过阈值。按流程该转人工审核,它没转,自己批了个 8% 的折扣,然后把流程跑完了。
全流程没有一个报错,每一步工具调用都成功。这就是最危险的失败形态——一个完全自主的 Agent,走通了一条谁都没批准过的路径。 而问题在上游:这条路径本来就确定,压根不需要模型决策。
一、编排模式到底在决定什么
编排模式一次性决定六件事:
- 上下文流动 —— 每步输入从哪来,上一步输出怎么注入
- 工具调度 —— 代码按固定顺序调,还是模型自己决定调哪个
- 路径是否预定义 —— 节点和边写死在代码里,还是运行时才确定
- 是否动态决策 —— 这里的"决策"指选下一步行动,不是节点内生成文本
- 何时停止 —— 循环退出条件谁来定
- 何时转人工 —— 什么条件下把控制权交回给人
二、推荐顺序:先简单,最后才上自主 Agent
这里有个非常明确的选择建议——它比"哪个更先进"重要得多,理由有三条:
先尝试单个 LLM 调用 → 再考虑工作流 → 最后才引入自主 Agent。
越自主,延迟和成本越高。 单次调用是一次请求,自主 Agent 是几十次甚至上百次串行调用,账单差一个数量级是结构决定的。
越自主,复合错误风险越大。 单次调用出错可重试;工作流出错,你知道错在哪个节点;自主 Agent 出错,是一串决策里某步偏了,后面每步都建在那个错误之上——它看到的世界已被污染。
固定业务约束不一定需要模型自主决策。 "订单超阈值要人工审核"写在代码里就是一个 if。让模型去"自主判断"它能不能执行,等于把确定的规则交给概率组件——你不但没获得灵活性,还失去了确定性。
如果业务流程本身是确定的,模型自主决策带来的不是收益,是风险敞口。
三、工作流:路径由代码说了算
通过预定义的代码路径编排 LLM 和工具。
关键在"每一步由代码规定,下一步也由代码规定"——LLM 只是被调用的能力,不是决策者。订机票的工作流版本,代码顺序调用四个节点:
- 核实用户身份
- 搜索可用航班
- 完成付款
- 确认预订
LLM 在节点内部做的事包括:把"我下周五从北京去上海,最好早上走"解析成查询参数。但节点之间的顺序,LLM 插不上手。
优势很实在:流程控制严格,关键步骤不会跳过或乱序;业务规则可由代码强制执行;提示注入和模型错误被限制在单节点内;成本与延迟可预测——支付、合规、状态机类流程里这些是刚需。
局限也明确:缺乏灵活性。 遇到未预见的分支,要么预设处理逻辑,要么失败——而真实世界的意外无穷无尽。
一个最小例子:文生图工作流
两个节点:① LLM 把自然语言改写成 Stable Diffusion 风格的提示词 ② 调用文生图模型生成图片。
它是一个适配层:文生图模型只认带权重和标签的提示词格式。用户说"画一只窗台上的猫,忧郁的",得转成 a cat on a windowsill, melancholic mood, ...。这类节点本质上在弥补模型不接受自然语言这一短板。
那些正在消失的"翻译"节点
Harness 里那些弥补模型能力短板的**"翻译"和"脚手架"代码,会随模型能力增强被内化**(第 6 篇讲的"内化")。
| 当年需要的脚手架 | 现在的状态 |
|---|---|
| few-shot 示例堆在提示词里 | 被指令微调和推理模型吸收 |
| "让我们一步一步思考"这类提示 | 被模型的原生推理能力吸收 |
| JSON 修复、格式容错的解析代码 | 被结构化输出和原生工具调用吸收 |
| 文生图提示词改写节点 | 正在被原生多模态理解和生成能力吸收 |
这类代码的保质期,取决于模型什么时候学会直接理解 A。 反过来,换成有原生图像生成的多模态模型,那个改写节点可能就不需要了——两端能力都上来后它只剩负担。
四、自主 Agent:路径由模型说了算
不依赖固定执行路径,根据环境反馈实时决定下一步。
订机票的自主版本,实际轨迹可能是这样:
- 搜索航班
- 发现需要登录 —— 搜索接口返回 401,环境里没有凭据
- 核实身份 —— 调用认证工具补上凭据
- 返回搜索 —— 带着凭据重跑第 1 步
- 发现最便宜的航班需要转机
- 询问用户是否接受转机
- 用户拒绝转机
- 调整搜索条件 —— 加"直飞"约束重新搜索
- 继续完成任务
注意第 2 步。工作流版本根本没有这一格——代码不会想到"需要登录",要么预设一个登录分支(哪怕多数用户不需要),要么流程直接失败。自主版本里这只是普通的环境观察:观察、归因、解决、回到原任务重新搜索。第 5 到 8 步同理——用户拒绝后不是重试,而是换策略。
灵活性不在于模型更聪明,而在于路径允许在运行时改变。
必要能力与停止条件
必要能力:自主规划、环境观察、动态决策、失败识别、策略调整、停止条件。前三项让它跑起来,后三项决定它跑得对不对——缺了失败识别它就不知道自己错了。
停止条件最易被忽略,后果也最严重:没有退出条件的循环,结局只有两种——烧完预算,或在无人监督下改变外部状态。必须设置的是:任务完成、输出最终答案(显式交付动作,而非靠沉默表示完成)、没有工具调用(说明模型认为可以回答了)、达到最大迭代次数(防死循环)、不可恢复错误、人工接管。
从实现角度说,自主 Agent 本质上就是在循环中使用工具的 LLM——这正是第 3 篇讲的 ReAct 循环。退出信号最常见的是"调用最终输出工具"和"响应不含任何工具调用",另两种是"遇到错误"和"达到最大轮数"。
适用场景与风险
适用:开放式问题、步骤数量难预测的任务、Coding Agent、Computer Use、深度研究、SWE-bench 这类复杂软件任务——共同点是目标明确、路径未知。
风险同样实在:成本高、延迟高(串行多轮是数量级的差距);复合错误(沿轨迹传播,越走越偏);死循环(调用成功但任务没进展);过度执行(任务已完成还在动手);不可逆操作(删除、支付、对外发送无法撤销)。上生产的前提是:充分沙盒测试(让 Agent 反复撞预设之外的意外)、护栏(边界设在执行层)、监控、关键点人工检查。
五、混合:真正的工程答案
工作流和自主 Agent 不是互斥关系。 常见三种混合方式:
按职责切分。 合规、支付、身份核验这类关键步骤走工作流;搜索、判断、探索这类需要灵活的部分走 Agent。确定的锁死在代码里,不确定的交给模型。
Agent 生成工作流。 Agent 读完任务后自行决定拓扑,生成一段编排代码。价值恰恰在"一段"上——Agent 先生成工作流,再由确定性工作流执行。 代码一旦生成,执行阶段就退回确定性。既保留面对未知任务的灵活性,又不必让模型在每次调度上参与决策:生成一次,执行多次。
同一系统里两种节点并存。 n8n 是典型:成熟的工作流自动化开源框架,开发者拖拽组件构建 Agent,同一系统里可同时用两种节点。对非技术团队这是最现实的路。
六、主流 Agent 框架对比
| 框架/平台 | 定位 | 编排模式 | 开发方式 | 适用场景 |
|---|---|---|---|---|
| Codex Harness | Codex 的开源 Agent 运行时 | 自主 | 代码优先,可嵌入应用 | Coding Agent、产品嵌入 |
| Claude Agent SDK | 生产级 Agent 开发框架 | 自主 | 代码优先 | 复杂自主任务、Coding Agent |
| LangChain / LangGraph | 通用 LLM 应用框架 | 工作流 + 自主 | 代码优先 | 链式思考、多步骤流程 |
| n8n | 可视化工作流自动化 | 工作流 + 自主 | 低代码、拖拽 | 业务自动化、非技术团队 |
| Dify | LLM 应用开发平台 | 工作流 + 对话式 | 低代码、API | 企业 RAG、知识库 |
| CrewAI | 角色化多 Agent 编排 | Multi-Agent | 代码优先 | 团队式任务分解 |
| OpenClaw | 开源个人 Agent | 自主 + 事件驱动 | 配置 + 代码、自托管 | 个人助理、研究、Computer Use、消息集成 |
| DeepSeek Harness | Agent 自进化框架 | 插件化 | 代码优先 | Agent 开发和研究 |
| Pi | 极简 Coding Agent 框架 | 自主 | 代码优先 | Agent 定制开发 |
选框架时不该只看它是否流行,而该关注:抽象层数量——多一层,出问题时你能看见的就少一层;可调试性——能否看清每步输入输出与依据;业务契合度;开发效率。
七、什么时候这个说法会失效
第一,"Agent 生成工作流"这条路的账没那么好算。 生成出来的编排代码本身可能有 bug,而且极难调试——路径确定,错了每次都错在同一处,你看到的是"稳定复现的错误结果"而非根因线索。更麻烦的是你分不清是模型写错了代码,还是工作流设计不成立。
第二,混合模式的职责边界会漂移。 随着模型能力和业务变化,"下单归工作流、选品归 Agent"这条边界会不断移动——移动成本很高,因为它动的是架构而非代码。 难点不在第一次怎么切,而在之后怎么维护。
第三,低代码平台的表达力上限是硬约束。 n8n、Dify 拖拽连线就能出流程。但当需求超出拖拽能表达的范围——复杂条件分支、节点间传结构化状态、自定义工具——你就在平台里写胶水代码。"低代码"在某个复杂度以下是优势,超过是负担。
第四,停止条件的阈值很难定。 最大迭代次数设 20 还是 50?没有通用答案。设低了复杂任务被中途砍断,设高了死循环要多烧几十次调用才发现。它只能靠真实任务分布去调,且要随模型能力重调。
第五,低延迟场景里自主 Agent 直接不可接受。 客服实时对话、交互式补全这类场景,用户耐心按秒计算,自主 Agent 的串行多轮却按十几秒到几十秒计算。这不是优化问题,是选型问题。
第六,"应该用工作流"这个判断也会过期。 Harness 里的脚手架会被模型逐步内化,很多今天必须写死的节点,等模型再强一代可能就不需要显式编排。今天的最佳实践,可能是明天的包袱。
小结
编排模式不是"哪个更先进"的技术选型,而是一次决定权分配:
- 推荐顺序:单个 LLM 调用 → 工作流 → 自主 Agent,越自主延迟成本越高、复合错误越大
- 工作流的路径由代码定,优势是可控,代价是应对不了未预见分支
- 自主 Agent 的路径由模型定,灵活性来自"路径允许运行时改变",代价是成本与延迟
- 停止条件必须由代码显式设置,不能指望模型自己觉得差不多了
- Harness 里的翻译层会被模型内化,选节点时想想还能活多久
- 混合才是工程常态:关键步骤走工作流,灵活部分交给 Agent
回到开头那个事故。团队的错误不在于选了自主 Agent,而在于那条路径本来就确定——换成工作流,"订单超阈值转人工"就是一个 if,Agent 连碰的机会都没有。判断标准就一句:
先问路径是不是确定的。是,就写代码;不是,再让模型决策。
就算路径确定、该用工作流,如果工作流本身要调一个自主 Agent 呢?答案不在提示词里——只在提示词里写"不许做",为什么一行代码都拦不住?
下一篇:《三层护栏:为什么只在提示词里写"不许做"没用》
关注这个系列,我会持续更新。觉得有用的话,欢迎点个赞——它会让我更有动力把下一篇写好。