Skip to content

第 36 章详细 Outline:Harness Design Patterns

写作契约

本章要完成的学习目标

读者完成本章后应能:

  1. 将“控制流模式”拆成触发条件、控制权所有者、工作契约、状态与证据、停止/升级和副作用责任,而不只按角色数量命名架构。
  2. 根据任务下一步的可预定义程度、子任务独立性、状态边界与外部触发条件,在受控单循环(Controlled Single Loop)、计划—执行(Plan–Execute)、监督者—工作者(Supervisor–Worker)、流水线(Pipeline)和事件驱动(Event-Driven)之间作出有限选择。
  3. 用本书的模式卡(Pattern Card)记录一种控制流为什么可用、何时不能用、何时应升级,以及它不证明哪些运行时性质。
  4. 识别把计划当执行许可、用并行掩盖共享状态冲突、让事件失去失败所有者和把模式组合当作成熟度的常见反模式。
  5. 为一个虚构文件修复请求定义从简单结构演进到更强控制结构所需的证据、停止条件和人工审批点。

读者、前置与明确边界

  • 读者: 已具备任务拆解、工作流、工具边界、审批和观察的基本概念,需要把这些概念组织成可比较控制流的工程读者。
  • 前置: 第 7 章的工作记忆与长期记忆、第 8 章的 Skill、第 9 章的 Planning、第 10 章的 Workflow 与状态管理、第 12 章的 Environment/Sandbox 与权限、第 14 至 15 章的人类在环与观察,以及第 26、28 至 35 章的协作、最小 Harness 和案例边界。
  • 本章负责: 提供控制流模式的选型语言、模式卡字段、组合限制、反模式和演进触发器;用虚构文件修复请求说明它们如何改变责任分配。
  • 本章不负责: 实现或运行 Agent、模型、队列、事件总线、调度器、工作流引擎、并发工作者、外部工具、Git、浏览器、CI、文件写入、网络、账户、凭证或真实 Bug 修复;也不比较模型能力、吞吐、延迟、价格、基准、可靠投递、恰好一次、安全或权限效果。

来源与本书模型的分层

使用位置可归因材料本章允许的有限陈述本书原创内容
第 1、3、4、7 节CH36-REF-01 / REF-029Anthropic 的工程文章在其语境中区分预定义代码路径的 workflow 与模型动态决定过程/工具使用的 agent,并列举若干组合结构和复杂度取舍。五张模式卡、选择顺序、结果所有者、演进触发器和反模式。
第 4、7 节CH36-REF-02 / REF-030OpenAI Agents SDK 的 Python 文档提供 manager、handoff、代码编排、串联、评估循环和独立任务并行的产品特定例子。监督者—工作者的委派契约、合并规则、共享状态限制与人工升级。
第 5、7 节CH36-REF-03 / REF-031AWS Step Functions 文档在该产品语境中描述事件驱动步骤的状态机,并列出 Choice、Wait、Map、Parallel 等流控制状态。流水线阶段门、状态记录、回退出口与本书模式卡字段。
第 6 节CH36-REF-04 / REF-114CloudEvents 规范将 event 描述为一次发生及其上下文的数据记录,并区分 producer、consumer 与 intermediary。事件契约、失败所有者、去重/顺序问题清单和保守停止。
第 6 节CH36-REF-05 / REF-115Node.js EventEmitter 在该运行时中使用命名事件与监听器,并按注册顺序同步调用监听器。“事件语义必须逐个运行时核验”的教学反例,不把具体顺序写成通用规则。

正文必须在对应位置使用“来源指出”“该 SDK/产品/规范在其语境中说明”“本书工程模型”或“虚构教学案例”标明层次。不得把来源材料写成通用模式标准、性能结论、默认架构、并发安全、投递保证、授权、真实运行或外部效果的证据。

章节叙事与逐节蓝图

1. 先选择控制责任,而不是先堆叠角色

  • 要回答的问题: 为什么“多 Agent”或“事件驱动”不能仅凭名称解决长任务、分派或可靠性问题?
  • 场景输入: 虚构文件修复请求仅提供只读诊断摘要、待核验症状、允许的分析范围和“任何写入必须人工批准”的限制;没有真实仓库、文件、错误、工具或运行环境。
  • 来源事实: REF-029 在其工程建议中区分预定义 workflow 与动态 agent,并指出复杂度需要结合结果改善判断;这不是本书的分类标准或选型算法。
  • 本书问题框架: 在增加角色、队列或循环前,先回答谁拥有最终结论、什么观察能改变下一步、状态写在哪里、何时停止、以及谁承担外部副作用责任。
  • 最小证据: 对照表区分 proposal_receivedpattern_selectedwork_observedexternal_effect_requestedexternal_effect_verified;任何前一项都不能自动证明后一项。
  • 失败分支: 输入没有结果所有者、停止条件或副作用边界时,不根据“任务复杂”猜测应使用多 Agent,返回 insufficient_contract 并要求补充模式卡。
  • 预期验证: 读者能说明角色数量不是选型依据;控制权、状态和证据的责任才是可检查输入。
  • 过渡: 下一节将上述问题固化为同一张模式卡,避免五种结构使用互不兼容的比较维度。

2. 模式卡:让选型理由成为可审查工件

  • 要回答的问题: 如何在不把自然语言架构说明当作可执行协议的前提下,比较不同控制流?
  • 本书模式卡: 每张卡至少填写 triggercontrolOwnerworkContractstateAndEvidencestopAndEscalationsideEffectBoundaryevolutionTrigger。字段是本书工程模型,不是 Agent SDK、工作流产品、CloudEvents 或 Node.js 的 schema。
  • 字段读法: trigger 只说明可进入比较的输入;controlOwner 指定决定下一步和承接最终结论的责任;workContract 划定子任务的输入、输出与禁止动作;stateAndEvidence 分开任务状态和可支持结论的材料;后两项保留停止、审批和升级出口。
  • 最小证据: 一张虚构“只读失败分析”卡显示没有写入能力、没有外部观察时,结论只能停在“可在隔离示例中实现”,不能称修复已完成。
  • 失败分支:controlOwner 留空、让多个角色写同一外部状态、把计划文本当作批准,或把工具返回文本当作业务效果时,卡应被拒绝或路由给人工复核。
  • 预期验证: 读者能用相同字段比较两种结构,并指出卡完整只证明计划边界完整,不证明真实实现可运行。
  • 过渡: 有了共同字段,第三节从风险最低的受控单循环开始,再说明何时必须把计划与执行拆开。

3. 受控单循环与计划—执行:先确认是否真的需要拆分

  • 要回答的问题: 什么任务可以由一个结果所有者按当前观察推进,什么任务需要把可预先审查的计划与执行状态分离?
  • 来源事实: REF-029 在其工程文章中提供 workflow、agent 与若干组合结构的受限背景;本章不把该文章的示例、成本或延迟判断写成适用于所有任务的规则。
  • 受控单循环(Controlled Single Loop): 本书把它定义为一名结果所有者读取受控观察、在尝试预算内决定下一步并保留停止原因的结构。它适用于下一步主要由当前观察决定、子任务尚不能稳定枚举、且没有未声明的并行或外部触发。
  • 计划—执行(Plan–Execute): 当子任务、依赖、验收门和不可触及范围能在执行前形成版本化计划时,本书将计划工件、执行状态和重新规划门拆开;计划本身不是执行许可。
  • 最小证据: 用同一虚构请求比较:单循环只产生“补哪一项诊断证据”的下一步;计划—执行先产生带依赖和验收门的只读分析计划。两者都不读取仓库、不运行测试或产生修复。
  • 失败分支: 单循环遇到固定子任务图却不断重述历史,或计划—执行遇到输入变化却继续沿用失效计划时,记录 evolution_triggered 并要求重新选择,而不是静默扩大范围。
  • 预期验证: 读者能说明“计划存在”与“计划可授权执行”不同,也能为不需要预定义子任务图的任务保留简单循环。
  • 过渡: 当一个结果所有者无法独立完成受限分析时,下一节讨论委派;委派不取消结果所有者的责任。

4. 监督者—工作者:委派要有归并与冲突出口

  • 要回答的问题: 在什么条件下可把不同分析工作交给多个受限角色,而不让多个输出竞争同一结论或副作用?
  • 来源事实: REF-030 仅在 OpenAI Agents SDK 的 Python 文档中展示 manager、handoff、代码编排和独立任务并行等例子;它不证明其他 SDK 接口相同,也不证明 handoff、并行或隔离安全。
  • 本书监督者—工作者(Supervisor–Worker): 监督者拥有最终结果、任务归并、冲突处理和升级责任;每个工作者只能接收具名输入、返回可定位材料并遵守禁止动作。它不是 SDK manager、产品 API 或自动授权角色。
  • 委派契约: 工作者必须说明专长、输入范围、输出形状、状态所有权、禁止副作用、超时/停止条件和冲突反馈。监督者不能仅凭“已分派”把候选输出改写为已验证结论。
  • 最小证据: 虚构工作者分别检查“复现契约是否完整”和“候选修复是否越界”;输出都回到监督者的教学记录,不能彼此写入,也不能访问真实文件或外部工具。
  • 失败分支: 两个工作者写同一状态、输出无法关联、监督者无合并规则、预算不可见或工作者请求外部执行时,停止分派并升级;不以增加一个“聚合器”掩盖责任缺口。
  • 预期验证: 读者能清楚指出谁拥有最终结论、哪些工作可独立、冲突由谁处理,以及什么情况下应退回单循环或计划—执行。
  • 过渡: 委派按专长拆分;下一节处理另一类约束:步骤顺序稳定且每一段都需要显式质量门。

5. 流水线:稳定顺序不等于自动完成

  • 要回答的问题: 当产物必须按固定顺序经过不同检查时,如何将阶段输入、输出和失败出口写清楚?
  • 来源事实: REF-031 在 AWS Step Functions 产品语境中说明事件驱动步骤、状态机和若干流控制状态;这些产品概念不构成本书字段、恢复保证或任意工作流的运行时语义。
  • 本书流水线(Pipeline): 阶段只消费已通过前一质量门的具名产物,并返回可审查状态、证据指针和下一阶段候选。阶段顺序稳定不意味着每一阶段已执行,更不意味着结论正确。
  • 教学链路: 虚构文件修复请求按“症状整理 → 复现契约检查 → 假设记录 → 候选修复审查 → 人工批准请求”排列。最后一步只形成请求,不能跨越批准门写入或宣称修复。
  • 最小证据: 阶段表记录输入、输出、质量门、失败分支、保留状态和不能据此主张的结论;例如“假设可检查”不等于“根因已证实”。
  • 失败分支: 阶段跳过输入验收、失败后丢失关联、回退目标不明、状态不可解释或某段试图产生外部效果时,流水线进入 conservative_stop,而不是重试所有阶段。
  • 预期验证: 读者能为一个稳定顺序的任务列出阶段门,并解释何时不应把高度动态的探索强行压成流水线。
  • 过渡: 流水线处理已知顺序;下一节处理由发生事实触发、且消费者责任必须单独定义的事件结构。

6. 事件驱动:发生事实、消费者与失败责任不能省略

  • 要回答的问题: 当任务因为某个状态变化而触发时,如何避免把“发出事件”误写成已经投递、处理、去重或安全完成?
  • 来源事实: REF-114 将 event、producer、consumer 与 intermediary 放在可互操作事件描述的规范背景中;REF-115 只描述 Node.js EventEmitter 的命名事件和按注册顺序同步监听器。两者均不支持通用投递、顺序、重试、去重、授权或消息队列结论。
  • 本书事件驱动(Event-Driven): 事件卡必须分开“何种发生事实可被记录”“谁产生候选事件”“谁可消费”“消费者如何关联状态”“失败由谁拥有”与“何时升级”。模式名称不暗示事件总线存在。
  • 事件契约: 只在可回答事件 ID、来源、时间窗、主题、消费者范围、去重依据、处理状态、失败记录和升级责任时讨论异步边界;无法定义任何一项时,保留同步路径或停止。
  • 最小证据: 虚构 analysis_ready 仅表示一个教学分析摘要可供后续审查;它不表示任务已由工作者领取、队列已投递、事件被消费或真实修复已开始。
  • 失败分支: 事件无消费者所有者、同一事件可能被重复处理而没有保守出口、顺序影响结论却未定义、观察无法关联或事件要求外部动作时,记录 requires_human_review,不补造运行时行为。
  • 预期验证: 读者能区分“事件描述格式”“某运行时的监听器语义”和“本书事件选择模型”,并能写出一个不把投递当完成的事件卡。
  • 过渡: 单个模式的边界清楚后,下一节讨论组合和演进;组合必须由可观察缺口驱动,而不是由架构名驱动。

7. 组合与演进:每增加一层都要新增可检查理由

  • 要回答的问题: 何时从简单结构升级到计划、委派、阶段门或事件,而不把“更复杂”误当作“更成熟”?
  • 来源事实: REF-029 提供从简单结构出发、审慎增加复杂度的受限工程建议;REF-030 和 REF-031 只分别提供特定 SDK 与产品中的编排/状态背景。它们不提供本章的升级阈值、并行安全或恢复保证。
  • 本书选择顺序: 先检查下一步能否由当前观察和一个结果所有者决定;再检查子任务能否预先枚举、是否真正独立;最后才检查外部触发、跨执行状态或副作用是否要求额外事件和运行时契约。
  • 演进触发器: 单循环反复丢失稳定子任务时才考虑计划;专长输出可独立、合并规则明确时才考虑工作者;阶段输入输出可固定且失败可定位时才考虑流水线;只有明确发生事实与消费者责任存在时才考虑事件驱动。
  • 组合限制: 计划—执行可以在监督者下工作,流水线中的一个阶段也可使用受控单循环;但每一层仍需独立声明控制权、状态所有权、预算、停止与副作用边界,不能把上层许可隐含传给下层。
  • 最小证据: 选型表对每一种新增结构都列出“观察到的缺口”“新增责任”“仍未解决的风险”和“回退条件”;表中不提供吞吐、成本或可靠性数值。
  • 失败分支: 只因任务看起来重要就预设多 Agent、使用并行覆盖共享状态、在事件前后省略人工批准、或无退出条件地叠加评估循环时,删除新增层或返回更简单的可观测结构。
  • 预期验证: 读者能为升级写出证据与回退条件,并解释为何没有该证据时应保留较简单模式。
  • 过渡: 下一节把模式卡的检查转化为纯内存教学示例;该示例只检查输入,不实现任何控制流。

8. 最小示例:纯内存模式提案评估器

  • 要回答的问题: 如何检查一份模式选择提案是否漏掉控制、停止或副作用边界,而不运行工作者、队列或事件?
  • 示例边界: 后续可实现 assessHarnessPatternSelection(proposal),只接收注入的模式卡与教学场景;不得启动 Agent、模型、并行任务、工作流、事件总线、文件、网络、Git、浏览器、CI、账户、凭证、工具或外部系统。
  • 计划输入: patterntriggercontrolOwnerworkContractstateAndEvidencestopAndEscalationsideEffectBoundaryevolutionTrigger 与可选的 composition
  • 计划返回: 字段完整且没有控制/副作用冲突时,只返回 ready 与“在隔离示例中实现”;缺控制权、缺停止、无法说明外部效果边界、事件无消费者所有者、并行缺合并规则或要求真实执行时,返回 stoppedrequires_approval
  • 计划测试: 受控单循环的完整卡、计划被误当执行许可、监督者没有最终结论、流水线缺质量门、事件没有失败所有者、并行缺状态隔离、组合没有退出条件和外部执行请求。
  • 预期验证: Example Implementation 阶段先记录模块缺失的红灯,再用实际 Node 测试和无副作用演示验证纯函数;本 Outline 不把函数、测试、命令或运行结果写成已存在或已执行。
  • 过渡: 示例检查一张提案;图示与完整案例则比较同一请求在不同模式下如何被限制。

9. 图示、完整教学案例与逐步增强

  • 要回答的问题: 如何让控制流比较图展示责任断点,而不把箭头、事件或状态框画成真实调度和已验证结果?
  • 图示内容: 后续图源 chapter-36-control-flow-pattern-selection.mmd 将同一虚构文件修复请求分别连接到五张模式卡;每张卡外侧标出控制权、状态/证据、停止/升级和副作用边界。图中必须保留“计划 ≠ 执行许可”“事件 ≠ 已处理”“观察 ≠ 外部效果”的断点。
  • 关键箭头解释: 请求先进入模式卡而不是直接进入工具;工作者、阶段或消费者的输出都回到具名结果所有者;人工批准门只能处理候选范围,不能回写成修复完成。
  • 完整教学案例: 同一个虚构请求从只读症状整理开始:受控单循环决定补充哪项观察;条件稳定后可形成计划—执行;两个独立审查问题才可由监督者委派;输出顺序稳定时才可列为流水线;若出现可定义的分析完成事实,才讨论事件卡。案例不提供真实文件、命令、队列、Git 记录、测试输出或修复结果。
  • 渐进表:
新需求必须新增的控制升级触发本章为何不实现
分派两个分析问题委派契约、最终结果所有者、合并规则、冲突与预算出口。两个子问题已独立且输出可合并。本章不启动工作者或并发任务。
固定交付阶段阶段输入输出、质量门、失败分支、回退状态。顺序稳定且每段能验收前一产物。本章不运行工作流引擎。
由状态变化触发后续工作事件契约、消费者责任、去重与失败升级。发生事实和消费者范围均可定义。本章不创建事件或事件总线。
提出真实修复环境准入、最小权限、人工批准、外部观察与回归验证。必须跨过只读分析边界。本章不读取、写入或修复任何真实文件。
  • 预期验证: Diagram Review 阶段才导出并目检 Mermaid;图不能从任意模式直接连到“修复完成”,也不能把 Node.js 或 CloudEvents 的受限事实画成通用运行时保证。
  • 过渡: 最后一节将选择问题转成读者可使用的检查清单,并指出第 37、38 章承接的不同模式层。

10. 反模式、选择清单与后续连接

  • 要回答的问题: 一项控制流设计在实施前,至少需要确认哪些问题,哪些问题应保留给权限、评估、记忆或具体运行时章节?
  • 本书选择清单:
    1. 谁拥有最终结果,谁可以改变下一步?
    2. 当前观察、计划、状态与证据分别是什么,缺哪一项时必须停止?
    3. 子任务是否真的独立,谁合并冲突、预算和失败?
    4. 阶段、事件或并行的具体运行时语义由哪项资料和测试核验?
    5. 哪些动作有副作用,谁批准,什么观察才能讨论外部效果?
    6. 新增模式层解决的可观察缺口是什么;若缺口消失,如何回退?
  • 常见误判:
误判表现根因修复方向
把多 Agent 当作默认架构角色重叠、最终结论无人拥有、失败只在角色间转述。没有先定义控制权和合并规则。先证明单循环或流水线不能满足可检查约束。
把计划当作执行许可计划写入了修复动作后,系统直接报告已完成。混淆计划、批准、执行和观察。分开计划版本、批准门、执行记录和外部效果验证。
把并行当作免费加速共享状态冲突、预算不可见、结果被强行合并。未证明子任务独立,也未定义状态所有权。只并行真正独立的任务,并保留冲突与停止出口。
把事件当作可靠处理事件产生后没有消费者所有者、去重、失败记录或升级。将描述格式或某运行时语义外推为系统保证。先写事件契约;无法定义时保留同步路径或停止。
无退出条件地组合模式计划、监督、评估与事件循环持续叠加。每层都没有停止与演进触发器。为每层补齐退出条件;不能补齐时删除新增层。
  • 章节总结: Harness Design Patterns 的价值不在于给任务贴上架构标签,而在于把控制权、状态、证据、停止和副作用责任变成可比较的输入。最小结构优先;只有观察到明确缺口且能写出新增边界时,才增加计划、委派、阶段或事件层。
  • 练习: 要求读者为一个虚构“测试失败摘要”写出两张模式卡:一张选择受控单循环,一张选择计划—执行;再说明哪项可观察变化会使其升级为监督者—工作者,以及为什么该变化仍不足以自动授权外部修复。
  • 后续连接: 第 37 章将把控制流之外的记忆与 Skill 接口整理为模式卡;第 38 章再组合反思、评估和审批。它们不得倒过来把本章的选型语言写成存储、授权、运行或业务效果的证明。

后续工件与验收边界

阶段计划交付物本阶段不得声称
First Draft原创正文、术语首现、虚构文件修复比较和受限来源陈述。Agent、SDK、状态机、事件、并行、工作流、真实文件修复或外部系统已运行。
Technical Review对 REF-029、REF-030、REF-031、REF-114、REF-115 的当日重读、来源/模型分层与术语检查。五项资料支持通用性能、投递、顺序、安全、授权或恢复结论。
Example Implementation纯内存 assessHarnessPatternSelection、最小测试和无副作用演示。提案评估器已经调度角色、执行计划、发送事件或验证真实架构。
Diagram Review可 diff 的 Mermaid 源、导出图、正文图块一致性和可读性检查。图表示真实队列、事件总线、工作流或修复路径已部署。
Fact Check 与 Language Editing逐项事实映射、主体、时态、术语、范围和交叉章节检查。未重读的动态资料、未运行的产品机制或未观察的外部效果已被核验。

本 Outline 只提供第 36 章的写作蓝图,不构成架构批准、产品配置、运行时设计、外部执行授权或任何真实系统的性能与可靠性结论。

从同一套 Markdown 书稿生成。