在上一篇中,我关注的是如何让 Agent 根据真实反馈持续修复问题。接下来遇到的问题是:当任务变成多阶段、多条并行链路时,谁来可靠地决定下一步?

如果所有计划、中间结果和调度决策都回到同一个会话里,模型既要解决问题,又要充当任务调度器。任务越多,越容易遗漏检查、重复工作,或把“流程走过了”误当作“目标完成了”。

Loop 管反馈,Graph 管编排

我把 Loop 理解为“执行、验证、修复、继续”的反馈机制;把 Graph 理解为组织这些工作的一层控制流:哪些节点先执行,哪些可以并行,结果如何汇总,什么时候退出。

两者可以叠加。一个图中的节点可以包含自己的验证与修复循环;一个 Agent 内部也可以继续使用工具和反馈。复杂工作流并不是简单任务的必需品,而是当协调成本上升时的一种工程选择。

Claude Code 的 Dynamic Workflows 是这类设计的一个具体实现:让脚本持有编排逻辑,由运行时执行,而不是由主会话逐轮记住所有调度步骤。具体能力与接口应以官方文档为准。

哪些约束适合写进代码

问题 可以显式化的约束
必要检查被跳过 必经节点和依赖关系
重试没有尽头 重试次数、截止时间和预算
下游拿到不完整结果 结构化输出与字段校验
多个执行者修改同一资源 所有权、串行写入或隔离工作区
实现者宣布自己成功 读取外部证据的验证节点
中断后不知道从哪里继续 可持久化状态和恢复规则

代码能保证某个分支被执行,却不能保证分支里的模型判断正确。Schema 能保证结果有一个 passed 字段,却不能保证它真的通过了验收。稳定性仍然来自控制流、证据和验证器共同工作。

把验证与修复循环放进编排器

下面是一个概念示例。implement、verify 和 repair 代表你自己的工具适配层;验证结果必须来自约定的检查,而不是实现者的自述。

async function runScenario(scenario, tools, maxRepairs = 3) {
  await tools.implement(scenario);
  let result = await tools.verify(scenario);

  for (let attempt = 0; attempt < maxRepairs; attempt++) {
    if (result.status === "passed" || result.status === "blocked") {
      return result;
    }
    await tools.repair(scenario, result.evidence);
    result = await tools.verify(scenario);
  }

  return result.status === "passed" || result.status === "blocked"
    ? result
    : { ...result, status: "budget_exhausted" };
}

这里有几个容易遗漏的细节:实现后先验证;修复后必须再次验证;被阻塞的任务不被当作成功;耗尽预算时返回真实状态。生产实现还需要异常处理、超时、取消、持久化和运行级预算。

并发不是越多越好

如果下一阶段需要所有结果,例如去重和总体报告,可以使用屏障:等待所有前置任务完成,再推进。若每个条目可以独立走完整条链路,则可以采用流水线,让已完成的条目继续向前。

但独立性必须检查。两个场景即使来自不同页面,也可能修改同一个文件或共享一份测试数据。此时盲目并行会引入竞争。应限制并发数,隔离工作区或测试资源,并把冲突写入编排设计。

流水线可能缩短等待时间,但不会自动带来固定倍数的加速。实际收益取决于任务分布、资源限制、模型限流和节点之间的依赖。

恢复结果不等于恢复副作用

一个节点的返回值可以存进日志,但它执行过的动作未必能够重放。

例如,一个节点已修改文件或向外部系统提交请求;重跑时直接使用缓存,可能忽略环境已经变化,重新执行又可能制造重复操作。因此恢复点至少应关联输入、代码版本、验证证据和副作用状态。

纯计算节点可以优先复用结果。有副作用的节点需要幂等键、状态核对,或明确的人工处理出口。恢复的目标是继续正确的工作,而不只是让进度条接着增长。

模型分层需要先建立任务边界

设计控制流、处理证据冲突和最终综合判断,可以使用能力更强的模型。格式归一、字段提取和边界清楚的检查,才适合尝试成本更低的模型。

模型分层是否合算,要看固定样本上的质量和总成本;如果下游需要不断修补上游错误,局部节省可能变成全局浪费。每个节点应有明确输入、输出结构、验证方式和失败出口。

什么时候值得引入 Graph

单个目标、单条反馈链,通常先用简单 Loop 就够了。只有当任务包含大量独立条目、多个阶段、可复用的质量门禁,或需要可审查和可恢复的调度时,脚本编排才更有价值。

我的演进顺序是:先找到一条有效的反馈路径,记录常见失败,再把已经稳定的协调规则写成代码。开放性探索仍然可以留在节点内部,不必把所有判断提前固定。

Skill 保存领域知识与操作惯例,Agent 执行有边界的任务,Workflow 组织依赖和状态。把这几层区分开,才能知道一次失败该修提示词、工具、验证器,还是控制流。

Graph 的价值不是画出一张漂亮的图,而是让可以确定的部分变得可检查、可复现,同时给需要判断的部分保留探索空间。

延伸阅读