本阶段的核心命题 Agent 不是"更会聊天的模型",是模型在环境中的循环决策系统。 聊天的驱动力是用户下一次输入;Agent 的驱动力是停止条件尚未满足。这一个字的差别,带来了全部的工程复杂度。
| 组件 | 是什么 | 缺了会怎样 |
|---|---|---|
| Model | 决策者 | 没有决策者 |
| Instructions | 目标、规则、边界 | 无目标漂移 |
| Tools | 与环境交互的能力 | 只能空想,改变不了世界 |
| State | 已做过什么、当前在哪 | 重复劳动、自相矛盾 |
| Environment | 工具作用的对象与其反馈 | 没有反馈就没有闭环 |
| Loop + Stop | 循环与停止条件 | 要么不动,要么停不下来 |
本课程采用的工作定义 本课程为了区分工程复杂度,把“由模型动态控制多步循环”作为 Agent 的工作定义。因此 Tool Calling 只是一步;是否要继续、改走哪条路、何时停止,才构成 Agent Loop。这不是行业唯一术语标准,但它直接决定了是否需要轨迹评测、步数预算和审批点。

四个关口,每个都是产品可以介入的位置:
| 关口 | 产品可以定义什么 |
|---|---|
| 组装上下文 | 放什么、放多少、放在哪个位置(阶段 3) |
| 权限检查 | 哪些工具需要确认、哪些直接禁止(阶段 11) |
| 结果回填 | 回填多少、要不要摘要、要不要标注来源 |
| 停止原因判定 | 步数上限、token 预算、超时、人工介入点 |
不同 harness 的层级切法不同,但共同点是:一次用户输入可能对应很多次模型请求。
Codex 的三级循环(Task / Turn / Step)是这套划分最完整的一个实现;Claude Code 的主循环则展示了另一种生产做法:物理上可以仍是一个循环,但每次继续都要有明确的状态与转移原因。
| 模式 | 结构 | 适用 | 代价 |
|---|---|---|---|
| ReAct | 思考 → 行动 → 观察,交替进行(arXiv:2210.03629) | 通用默认 | 步数不可控 |
| Plan-and-Execute | 先出完整计划、再逐条执行 | 步骤多、可预先分解 | 计划错了全盘皆错 |
| Reflection / Reflexion | 执行后自我批评再重试(arXiv:2303.11366) | 有明确评判信号时 | 无信号时只是多花钱 |
| 确定性 Workflow | 代码写死路径,模型只在节点内工作 | 路径可枚举 | 覆盖不到的情况会失败 |
选型的首要判据 路径是否可枚举是最有用的起点:可枚举时优先 Workflow;不可枚举时才考虑 Agent;中间地带用 Workflow 骨架 + 局部 Agent 节点。但它不是唯一因素,还要同时看环境稳定性、错误可验证性、动作风险、维护成本、时延和模型调用成本。
Anthropic 在 Building Effective AI Agents 里给出的建议是同一个意思:先找最简单的方案,只在确有必要时才增加复杂度。
生产级 Loop 不应只记录“这一轮有没有工具调用”,而应把每次继续和终止的原因建模成一等状态:
| 字段 | 示例 | 用途 |
|---|---|---|
| transition_reason | normal_next_step / compact_resume / hook_blocked / budget_continue | 解释为什么进入下一圈 |
| withheld_error | 可恢复错误暂不向下游暴露 | 避免 SDK 或 UI 看到任意 error 就提前终止 |
| terminal_reason | completed / max_steps / permission_denied / unrecoverable_error | 统一结束语义与统计口径 |
Claude Code 的循环案例还揭示了两个值得迁移的工程原则:
这些机制不一定都要出现在最小 Agent 中,但轨迹 Schema 应先为它们留位置。详见 Claude Code:Agent Loop。
反思要有效,需要一个外部的、可信的评判信号——测试通过与否、校验器报错、业务规则校验结果。如果只是让模型"再检查一遍自己的答案",它会用产生错误的同一套机制去检查错误,结果通常是把错误说得更有说服力。
产品结论:要上反思,先建校验器。 没有校验器的反思是花钱买自信。
一个生产级的 Agent Loop 至少要有五种停止条件:
| 停止条件 | 阈值来源 | 停下来之后 |
|---|---|---|
| 任务完成 | 模型判定 + 校验 | 正常返回 |
| 最大步数 | 产品设定 | 返回部分结果 + 说明 |
| Token / 成本预算 | 产品设定 | 同上 |
| 超时 | 产品设定 | 同上 |
| 需人工确认 | 权限规则 | 挂起,等待输入 |
| 不可恢复错误 | 错误分类 | 停止,保留现场 |
"返回部分结果"是产品设计,不是异常处理 Agent 达到步数上限时最糟糕的表现是:什么都不给,只说"失败了"。正确做法是把已完成的部分交出来,并明确说明"做到哪一步、还差什么、下一步建议怎么做"。这一条在阶段 12(失败表达)会展开,但它的实现位置在这里——Loop 必须支持"带着中间产物退出"。
不要说"我们的 Agent 是 L3 自主"。要说:
| 动作 | 自主等级 |
|---|---|
| 查航班、查运价 | 全自主 |
| 生成报价方案 | 全自主,但结果标注来源 |
| 占座 | 需确认(可批量预授权) |
| 出票/扣款 | 每次确认,且展示影响 |
| 退票 | 每次确认 + 二次输入校验 |
云安全联盟(CSA)2026 的自主等级框架把它分成从全监督到全自主的六级,用它做动作级分类比做产品级标签有用得多。
| 症状 | 常见机制原因 | 对应修法 |
|---|---|---|
| 死循环 | 工具反复返回同样的失败,模型反复重试同一动作 | 相同工具+相同参数的重复检测;错误信息里给出可执行的下一步建议 |
| 偏航 | 长循环中原始目标被稀释;中间结果污染上下文 | 每步重申目标(放在窗口末尾);定期压缩时保留"任务目标"不丢 |
| 过早结束 | 模型认为已完成,但没有校验 | 完成判据外置:让校验器说了算,不让模型自己说了算 |
| 反复道歉不干活 | 错误信息措辞诱导;上下文里堆满失败 | 工具错误信息写成指令性的("参数 X 应为 ISO 日期"),而不是原始堆栈 |
| 越权 | 工具面没有权限层 | 权限在 Harness 层拦,不靠提示词(阶段 11) |
这是本阶段最有产品价值的一节。当有人说"Agent 不好用",要能追问到具体哪一类:
| 类别 | 判别信号 | 修的人 | 修法 |
|---|---|---|---|
| 模型失败 | 上下文里信息齐全、工具正常,但推理错 | 算法/选型 | 换模型、加推理、加示例 |
| 上下文失败 | 需要的信息根本不在窗口里,或被埋在中间 | 产品 + 研发 | 检索、组装、位置策略(阶段 3) |
| 工具失败 | 工具报错、返回歧义、描述不清导致选错 | 产品 + 研发 | 工具契约(阶段 5) |
| Harness 失败 | 会话丢了、权限没拦住、压缩把关键信息压没了、没有轨迹可查 | 平台 | 阶段 6~11 |
这张表是产品经理最重要的工作语言 没有它,所有 Agent 问题都会被归结为"模型不行,等下一代模型"。有了它,每个问题都能落到具体负责人和具体动作上。把这张表贴在评审会上。
从便宜到贵:
设计要点:每一层都要有次数上限,且升级路径必须是单向的。反复在 1、2 层之间打转是烧钱最快的失败模式。
| 误区 | 纠正 |
|---|---|
| "Agent 就是能调工具的 LLM" | 定义在循环控制权,不在工具 |
| "ReAct 是 Agent 的标准架构" | 它是一种提示模式,不是架构;生产系统常常是 Workflow + 局部 Agent |
| "加上反思就更准了" | 没有外部校验信号的反思等于花钱买自信 |
| "步数上限调大就能解决做不完的问题" | 通常是上下文或工具问题,加步数只是加钱 |
| "让模型自己判断做完没" | 完成判据要外置,否则过早结束和无限循环都会出现 |
| "自主等级是产品的属性" | 是动作的属性,必须逐个动作定义 |
| "失败就报错" | 带着中间产物退出是产品设计,不是可选项 |
| 资料 | 出处 | 读它拿什么 |
|---|---|---|
| Building Effective AI Agents | Anthropic,2024-12-19 | Workflow / Agent 的判别与五种基础模式 |
| A Practical Guide to Building Agents | OpenAI | instructions / guardrails / tools 三件套,以及何时该上 Agent |
| ReAct(arXiv:2210.03629) | 论文 | 读摘要与图示即可,理解"交替"这一结构 |
| Reflexion(arXiv:2303.11366) | 论文 | 理解反思生效的前提条件 |
| Building agents 学习路径 | OpenAI Developers | 一条从最小 loop 到编排的完整实践路径 |
本仓已有资料:
四份 Harness 的 Loop 按这个顺序读 Pi(看清骨架)→ Codex(看清层级与协议)→ Claude Code(看清状态转移、恢复与缓存约束)→ dsh(看清哪些部分可以被替换)。读完要能回答:我们自己要做一个 Agent,Loop 应该自己写、用 SDK,还是直接继承现成 Harness?