第30章 Human-in-the-loop 与长任务¶
第22章把 waiting_human 定义为 Run 六态之一。它表示 Runtime 有意暂停,正在等待 Console 或人工回调。这个状态在生产系统里非常常见:报告草稿已经生成,但还不能对外发送;折扣方案已经算出,但超过阈值需要经理确认;合同风险点已经抽取,但法务需要先看证据。如果没有 HITL,Agent 容易把“看起来合理”的结果直接变成系统动作。未经审核的竞品描述可能被发到区域经理群,错误折扣可能写入主数据,含个人信息的报告可能被外发。Amershi 等人关于交互式机器学习的研究强调,人应是有控制权的协作者,而非被动标注机 (Amershi et al. 2014; Mosqueira-Rey et al. 2023)。企业 Agent 中的人工介入,正是这个原则的工程化表达。
以区域经营分析报告为例。DataAgent 可以生成销售下滑原因、库存建议和对外沟通口径。SQL 查询和图表生成可以自动完成,但“是否把这份报告发给区域经理”是另一个动作。前者是分析过程,后者是组织承诺。HITL 要拦截的是后者:审批人看到报告正文、数据版本、关键 SQL 摘要和模型建议后,决定发布、驳回或要求重写。长任务还有另一个问题。季度分析、批处理 SQL、外部 A2A Task 和多轮报告修改可能持续数小时。系统不能让一个 HTTP SSE 连接一直占着 Worker,也不能在用户关闭页面后丢失任务。Runtime 必须用异步队列和检查点,把“等机器”和“等人”纳入同一个 run_id 生命周期。
HITL 在企业里经常被误解成“模型不够可靠,所以加个人看一下”。这种理解会把人工介入放到错误位置。人工应按用来承接组织责任:谁批准导出客户名单,谁确认折扣写入主数据,谁决定报告可以对外发送,谁承担某个高风险建议进入流程的后果理解,不能停留在用来替模型补所有判断。模型可以给出建议和证据,Runtime 要负责把决策暂停在合适位置,让有权限的人基于证据作出选择。
长任务同样不是“把超时调大”。一个报告生成任务如果跑 40 分钟,中间可能经历多次 SQL、Python、图表、文档写入和人工反馈。用户关闭页面后任务还要继续,系统重启后任务还要恢复,审批人拒绝后任务要能结束或重写。所有这些都要求 Runtime 保存足够状态,而非依赖一条还活着的连接。检查点的价值在这里才显出来:它让机器等待、人工等待和失败恢复都落在同一个 Run 里。
HITL 与长任务放在同一章,是因为它们都在处理“任务不能立即完成”的情况。一个在等数据,一个在等模型,一个在等外部 Agent,一个在等人。平台如果把这些等待分散到业务代码、前端状态和临时队列里,后续很难审计和恢复。把等待统一成 Runtime 状态,才能让用户看到进度,让审批人看到证据,让 SRE 知道任务是否卡住,让审计知道谁在什么时候做了决定。
30.1 HITL 的设计目标¶
30.1.1 人工介入的治理目标¶
HITL 和聊天里的追问不是一回事。澄清问题用于补全任务输入,人工审批用于授权 Agent 执行动作。前者常发生在规划前,后者发生在 Runtime 准备执行高风险动作或发布 artifact 之前。企业引入 HITL 通常为了四类目标。
表30-1:HITL 的目标与无人工介入时的风险。来源:本书整理。
| 目标 | HITL 负责什么 | 缺失后的风险 |
|---|---|---|
| 授权 | 金额、折扣、发布、写操作由具备权限的人确认 | 越权自动化 |
| 质量 | 报告、代码、客服话术在关键节点被复核 | 事实错误或品牌风险 |
| 合规 | 隐私、广告法、反垄断、行业监管要求可追踪 | 处罚和审计失败 |
| 学习 | 人工拒绝和修改进入评测与样本闭环 | 同类错误反复出现 |
金融、医疗、政务、零售营销等场景都可能要求人类监督 (EU AI Act 2024; NIST 2023)。但就算没有外部监管,企业也需要把风险动作放进组织授权体系。Agent 只是发起者之一,不应绕过已有审批链。
30.1.2 waiting_human 的 Runtime 状态语义¶
审批必须进入 Run 六态的 waiting_human,而非写在某个 Agent 应用的 if/else 里。原因很直接:只有 Runtime 状态知道当前 Run 是否暂停、是否能恢复、是否应该继续推送 SSE、检查点是否完整、审批超时后该怎么处理。进入 waiting_human 时,Runtime 不能只改一个状态字段。它要写引擎检查点,保存 Run 状态、Memory、Tool 结果和等待中的审批信息;也要写业务检查点,让 Console 能展示“报告草稿已生成,待审批”;同时推送 approval_request 事件,让前端或工单系统生成待办。如果审批只是业务代码里的一个字段,进程重启后 Runtime 可能不知道该从哪里恢复;如果审批通过后重新 POST /run,发布工具可能被执行两次;如果拒绝审批后静默结束,用户和审计系统都无法知道任务为何失败。
30.1.3 全自动与人工介入的边界¶
只读查询、内部预览和低风险草稿可以全自动。写工单、改主数据、对外邮件、合同发布和高金额折扣应默认触发 Policy,进入 waiting_human 或更严格的审批链。自动化测试环境可以关闭 HITL,但这个开关应由环境和租户策略控制,不能由模型决定。HITL 的基本规则可以概括为三条:写操作默认可拦截;审批在同一个 run_id 上恢复;审批超时必须有策略。无限挂起的审批不是安全设计,只是把风险推迟到没人处理。在架构评审里,可以要求每个高风险工具都回答四个问题:谁有权批准,批准前能看到什么证据,批准后允许执行哪些动作,拒绝后任务怎样结束。回答不了这四个问题,说明工具还不适合接入自动化链路。HITL 不负责兜底所有错误;它把组织授权变成 Runtime 可执行、可审计的状态迁移。
这个评审比“是否加确认弹窗”更重要。确认弹窗只能证明用户点过一次按钮,不能证明用户有权限、看过证据、理解影响范围,也不能证明后台执行的是同一个动作。生产级 HITL 要把审批对象、证据包、审批人身份、审批结果和后续工具调用绑定起来。审批体验也会影响系统是否被使用。若每个小动作都要求经理确认,业务团队会把 Agent 当成低效工具;若高风险动作只弹一个模糊确认框,审批人又无法承担责任。平台应按动作风险分层:低风险只读分析自动执行,中风险发布或导出要求用户确认,高风险写操作进入正式审批链,特别高风险动作转人工流程或禁止自动化。这样人工介入才出现在真正需要判断的位置。
长任务中的人工介入还要处理时间差。报告生成后等待审批,审批期间数据可能刷新、指标版本可能更新、用户可能要求修改。如果审批人批准的是旧 artifact,系统就不能把批准结果套到新内容上。审批记录要绑定 artifact hash、数据快照和策略版本;内容发生变化时,旧审批应失效或要求重新确认。这一点看似繁琐,却能避免“批准 A,执行 B”的事故。审批拒绝也不是简单失败。拒绝可能意味着内容质量不足、证据不充分、风险太高、收件人不对,或者业务已经不需要该任务。系统应要求审批人选择或填写拒绝原因,并把原因回写到评测和模板优化。这样 HITL 不只阻止风险,也为后续自动化提供训练和规则改进材料。
对于长任务,取消和超时同样需要语义。用户取消报告生成,已经执行的只读查询可以保留证据,尚未发送的外部通知要停止,已写入的临时 artifact 要标记失效;审批超时后,系统可以提醒、升级、自动关闭或转人工队列,但策略要提前写清。没有这些语义,任务会停在“处理中”,用户不敢重试,工程师也不知道是否存在副作用。HITL 的证据包应同时服务审批和审计。审批人需要看到影响范围、关键参数、数据来源、模型建议、可替代动作和拒绝后的结果;审计人员需要看到审批人身份、时间、策略版本、artifact hash 和后续工具调用。两类视图可以共用底层数据,但展示重点不同。审批界面若只显示“同意/拒绝”,人很难做出负责的判断。
长任务还要处理并发修改。一个报告在等待审批时,用户可能要求重写摘要,另一个协作者可能修改附件,系统也可能收到数据新鲜度更新。Runtime 需要把这些变化变成新的 artifact 版本,而非覆盖原内容。审批永远绑定具体版本;新版本需要新审批或明确的增量复核。这样协作不会破坏责任链。对平台来说,HITL 不是降低自动化率的负担。它让高风险动作可以进入 Agent 流程,因为组织知道关键节点有人接管责任。没有 HITL,很多写操作、导出和对外发布只能被禁止;有了清晰的审批状态、证据和恢复机制,平台反而能安全地开放更多能力。
30.2 审批模式与事件契约¶
30.2.1 前置审批、后置审批与分级审批¶
审批模式取决于风险动作发生在哪一步。前置审批是在工具执行前暂停,适合大额转账、删库、改主数据等动作。后置审批是在草稿 artifact 生成后、发布类副作用发生前暂停,适合报告发送、邮件群发、公告发布。分级审批用于经理、总监、法务等多角色会签。
表30-2:常见审批模式。来源:本书整理。
| 模式 | 行为 | 适用场景 |
|---|---|---|
| 前置审批 | 展示拟执行工具和参数,批准后才执行 | 高风险写操作、删除、转账 |
| 后置审批 | 先生成草稿,批准后才发布或外发 | 报告、邮件、公告、营销内容 |
| 分级审批 | 多个 waiting_human 节点串联 |
合同、采购、对外声明 |
| Reviewer Agent + 人 | Agent 先筛,低风险自动通过,高风险升级 | 大批量内容审核 |
经营报告适合后置审批:Report Agent 先调用 render_report 生成草稿并写入 Memory,Runtime 进入 waiting_human,Console 展示报告预览;审批通过后,Workflow Agent 才调用 publish_report。草稿已经生成,发布类副作用尚未发生。
30.2.2 SSE 与审批回调¶
Console 需要通过 SSE 感知审批状态。approval_request 应带上待办标题、artifact 引用、允许动作和过期时间;approval_result 应带上审批人、结论和备注。
event: state
data: {"run_id":"run-8f3a","state":"waiting_human","step_index":4}
event: approval_request
data: {"approval_id":"ap-001","run_id":"run-8f3a","title":"Q1 华东毛利报告发布","artifact_ref":"mem://run-8f3a/report_md","requested_actions":["publish_report"]}
event: approval_result
data: {"run_id":"run-8f3a","decision":"approved","approver_id":"u-director-001","comment":"口径已确认"}
审批回调可以表达为:
POST /runs/{run_id}/approvals/{approval_id}
Content-Type: application/json
{
"decision": "approved",
"comment": "口径已与财务确认",
"approver_id": "u-director-001"
}
Runtime 收到回调后要校验三件事:Run 当前确实处于 waiting_human;approval_id 与检查点匹配;审批人角色满足 Policy。通过后触发 approved 迁移,从引擎检查点恢复 Planner 上下文继续执行。同一 approval_id 重复 approved 必须幂等,不能重复调用发布工具。
30.2.3 Policy 触发条件¶
Policy 决定哪些动作需要人工介入。常见触发条件包括工具标签 requires_approval、参数阈值、数据域、租户策略、Reviewer Agent 的风险分数等。例如 discount_rate > 0.15、文档含 pii:true、工具名是 send_email 或 publish_report,都可以触发 need_approval。审批 SLA 也属于策略。到期后可以自动拒绝、提醒审批人或升级到上级审批人。无论采用哪种策略,状态变化都要写入检查点和审批记录,不能只在 Console 前端更新待办状态。
审批记录还要保存“当时看到的证据”。同一个报告草稿在审批前后可能被重新生成,指标版本也可能更新。如果审批记录只保存 approved=true,后续无法证明审批人批准的是哪一份内容。生产系统至少应保存 artifact hash、指标版本、关键数据新鲜度、Policy 触发原因和审批页快照引用。Policy 还要避免把所有风险都丢给审批人。低风险、重复性强、证据明确的动作可以自动通过;高风险但证据不足的动作应先要求 Planner 补证据,不要直接发给人。否则审批台会变成新的瓶颈,重要审批反而被大量低价值待办淹没。因此,HITL 不是越多越好。一个成熟系统应该减少无意义审批,提高高风险审批的证据质量。审批人不应只看到“是否同意发布”的按钮,还应看到模型为何建议发布、用了哪些数据、哪些 Policy 被触发、拒绝后会发生什么。这样人工介入才是决策节点,不是形式上的按钮。
30.3 暂停、恢复与取消¶
30.3.1 同一 Run 内恢复¶
审批通过不是新 Run。Runtime 应在同一 run_id 上从检查点恢复,继续执行批准后的动作。这样才能保留原始输入、工具结果、草稿 artifact、审批记录和最终发布结果之间的因果链。审批拒绝通常进入 failed,并记录结构化原因。用户可以修改输入后发起新 Run,也可以在产品设计允许时创建带 revision 的 replanning。不要在原 Run 里静默修改 artifact 并继续执行,否则审计时很难说清“人批准的到底是哪一版”。
30.3.2 Cancel 与 Hold¶
Cancel 是主动放弃任务。用户或运维触发取消后,Runtime 应停止未开始的工具,尽力取消进行中的工具,关闭审批待办,写入 failed + reason_code=user_cancel。已完成的副作用不会自动回滚,需要补偿事务或人工处理。Hold 是审批中的暂存或等待补充材料。Run 可以保持 waiting_human,业务检查点记录 revision_draft 或补充意见。Hold 不是新的 Runtime 状态,更像 waiting_human 的业务子状态。
表30-3:审批通过、拒绝、取消和暂存的状态语义。来源:本书整理。
| 动作 | 触发者 | Runtime 结果 | 说明 |
|---|---|---|---|
approved |
审批人 | waiting_human → executing |
同一 Run 恢复 |
rejected |
审批人 | waiting_human → failed |
记录拒绝原因 |
cancel |
用户或运维 | 非终态 → failed |
主动放弃任务 |
hold |
审批人或用户 | 保持 waiting_human |
记录业务子状态 |
30.3.3 进程恢复¶
Pod 重启时,Runtime 根据 run_id 加载引擎检查点。如果状态是 waiting_human,它只能幂等同步审批待办到 Console,不能自动批准。审批人回调后,Runtime 再触发 approved 或 rejected。这个流程能避免两类事故:一类是重启后自动越过审批,另一类是重启后重复创建审批工单。审批工单要以 approval_id 幂等注册;发布工具要以 tool_call_id 或业务幂等键去重。恢复时还要保留“人批准的是哪一版”。如果报告草稿在审批期间被重新生成,原审批就不应继续用于新 artifact。一个简单做法是让 approval_request 记录 artifact hash,审批回调时再次校验 hash;如果内容已变更,旧审批作废并生成新的待办。
30.4 两类检查点与长任务队列¶
30.4.1 引擎检查点与业务检查点¶
HITL 和长任务需要两类检查点。引擎检查点服务 Runtime 恢复,业务检查点服务 Console 展示和合规回放。二者引用同一个 run_id,但字段和读取方不同。
图30-1:双检查点关系。来源:本书自绘。Alt text:图中并列展示引擎检查点和业务检查点;前者保存 Runtime 状态、工具结果和 Memory 引用,后者保存报告草稿、审批里程碑和展示状态,二者通过同一个 run_id 对齐。
表30-4:引擎检查点与业务检查点的区别。来源:本书整理。
| 类型 | 读取方 | 保存内容 | 作用 |
|---|---|---|---|
| 引擎检查点 | Runtime | state, step_index, memory_refs, tool_calls, handoff_stack |
崩溃恢复、继续执行 |
| 业务检查点 | Console、合规、业务用户 | label, artifact_ref, created_at, approval_status, metadata |
展示进度、SLA、回放 |
混淆这两类检查点会造成很隐蔽的问题。Console 可能显示“报告草稿已审批”,但 Runtime 恢复时没有 Memory 和工具结果,只能重新生成报告;或者 Runtime 能继续执行,但业务用户看不到任务卡在哪个里程碑。
30.4.2 异步队列长任务¶
超过分钟级的任务不应阻塞同步 Worker。Runtime 可以提交异步 Tool Call 到队列,Worker 执行后把结果写回,RunLoop 再根据结果触发下一步。Worker 不持有 Run 状态机,只处理 tool_call_id 对应的工作;RunLoop 才负责状态迁移、审批和检查点。长任务里,“等机器”和“等人”可以并存。异步 SQL 仍属于 executing,Tool Call 状态为 running;报告生成后触发审批,Run 才进入 waiting_human。不要为了等待外部任务新增 waiting_external 之类的 Run 状态,否则对外生命周期会越来越复杂。
保持 Run 状态克制很重要。等待外部系统、等待队列 Worker、等待用户审批,都是不同原因的等待,但不一定都要变成新的 Runtime 状态。Runtime 对外只需要表达任务是否还在执行、是否等人、是否成功或失败;更细的等待原因可以放在 Tool Call 状态、业务 milestone 或 Trace span 中。经营分析的时间线通常是:用户发起 Run,异步 SQL 入队,数据就绪,报告草稿生成,进入审批,审批通过,发布完成。T4 到 T48h 期间 SSE 可以断开;恢复靠检查点和事件日志,不靠重新从 T0 跑一遍。
30.4.3 超时和 SLA¶
长任务至少有三类时间约束:工具执行超时、Run 总超时、审批 SLA。队列的 visibility timeout 应短于 Run 超时;审批 SLA 应单独配置。审批超时后是自动拒绝、提醒还是升级,要由 Policy 决定。如果所有等待都算进同一个超时,系统会误判。一个 SQL 工具跑了 40 分钟可能是性能问题;一个审批等了 40 分钟可能完全正常;一个外部 A2A Task 等了 40 分钟则需要看对方 SLA。Runtime 要把这些等待类型区分开。异步队列也不能替代检查点。队列知道某个 tool_call_id 是否还在执行,但不知道 Planner 看过哪些结果,也不知道 Console 展示到哪个业务里程碑。长任务要同时维护队列消息、引擎检查点和业务检查点,三者缺一项都会让恢复或回放变得不完整。
30.5 业务回放与审计¶
30.5.1 回放包¶
合规和客诉场景常要求在限定时间内证明:谁批准了内容,依据什么数据,发布了哪个版本,模型是否自动越过人工监督。第38章的 Trace 解决技术回放,本节的业务回放包解决组织责任。回放包可以由 API 导出:
审批回调返回的内容不能只给一个“通过”或“拒绝”。业务里程碑、审批记录、工具调用摘要、artifact hash、数据血缘和 Policy 决策都应该一起带回,后续复盘才有证据可查。
{
"run_id": "run-8f3a",
"milestones": [],
"approvals": [],
"tool_calls": [],
"artifacts": [{"ref": "mem://run-8f3a/report_md", "sha256": "..."}],
"data_lineage": [{"semantic_layer_version": "2026Q1"}],
"policy_decisions": []
}
回放包不一定保存完整模型推理草稿,尤其当策略禁止存储 CoT 时。但它必须保存工具参数、审批意见、artifact hash 和数据版本。否则,团队只能说明“系统大概做过什么”,不能证明“这一版内容由谁基于什么数据批准”。
30.5.2 不可篡改与学习闭环¶
审批记录和 artifact 应采用追加写和内容寻址。关键报告、邮件、公告可以按 hash 存储;审批记录包含 approver_id、SSO 会话、时间戳和 comment。合规导出只对审计角色开放,并记录访问日志。人工拒绝和修改也应进入评测样本。一次 rejected 说明同类输入下次可能要更早触发 HITL,或让 Planner 生成更好的草稿。人类反馈进入评测和训练时,要保留版本、来源和适用范围,避免把一次临时判断固化成全局规则。回放包的粒度也要克制。合规人员通常关心的是版本、证据、审批和发布结果,不需要阅读完整模型过程。把所有中间草稿都无差别归档,会增加隐私和存储压力;只归档最终发布物,又无法解释审批为何发生。更合理的做法是保存关键 artifact、工具参数摘要、数据版本和人工 comment。
30.6 HITL 与 Runtime 状态恢复¶
30.6.1 从 Runtime 状态到审批恢复¶
projects/multi-agent-workflow/ 已经演示了这条链路:报告草稿生成后进入 waiting_human,SSE 推送 approval_request,另一终端执行 approve 之后,Runtime 再在同一 run_id 上恢复并发布。这个例子需要验证的是运行记录是否完整:暂停、审批、恢复和发布都挂在同一条 Run 上,前端事件只是这条链路的外部表现。若前端能显示审批按钮,但后端把批准后的动作当成一次新请求执行,审计时仍然无法还原因果关系。
mini-platform/
├── core/runtime/
│ ├── run_loop.py
│ └── approval.py
└── projects/multi-agent-workflow/
└── run.py
运行方式:
cd mini-platform
python3 projects/multi-agent-workflow/run.py start
python3 projects/multi-agent-workflow/run.py approve
自动化验证:
30.6.2 HITL 示例范围与后续演进¶
本章示例覆盖 waiting_human 状态迁移、approval_request、approval_result、手动 approve/resume 和检查点。生产版本还需要 HTTP 审批回调、Console 待办、审批 SLA、业务 milestone API、Export Bundle、异步队列、幂等工单同步和审计权限。
表30-5:HITL 示例实现与后续补齐项。来源:本书整理。
| 能力 | 示例实现 | 后续补齐 |
|---|---|---|
waiting_human |
已覆盖 | 与 Policy、Console、检查点联动 |
| 审批事件 | 已覆盖核心 SSE | 增加 SLA、角色、工单状态 |
| 检查点 | 已覆盖引擎检查点 | 增加业务 milestone 和审计归档 |
| 长任务 | 基础流程演示 | 接入队列、Worker 幂等、嵌套超时 |
| 审计导出 | 未覆盖 | Export Bundle、hash、访问控制 |
早期验收可以聚焦三个场景:报告草稿审批通过后同一 Run 发布;审批拒绝后 Run 进入失败且记录原因;进程在 waiting_human 重启后不自动批准,也不重复创建审批工单。审批链路还要验证“审批内容未变化”。报告、邮件、折扣方案这类 artifact 在等待期间可能被重新生成,也可能被人工编辑。审批请求应绑定 artifact hash、关键指标版本和允许动作;审批回调时 Runtime 再次校验这些字段。若 hash 已变化,旧审批应失效并生成新待办。这样做会多一次用户操作,但可以避免审批人批准 A 版本、系统发布 B 版本。长任务的早期也不必一次接入完整工作流引擎。只要 Run 有独立状态、Tool Call 有幂等键、审批有可恢复检查点、前端能按 run_id 查进度,就已经能覆盖大部分报告生成和人工确认场景。后续再接入队列优先级、SLA 升级、工单同步和审计导出。把这些能力分阶段落地,比先设计一个庞大的审批平台更容易稳定。
30.6.3 人工介入的责任链路¶
HITL 要把模型建议之后的责任转移到可识别的人、流程和审批记录上。用户点击批准时,平台要记录批准人、角色、审批对象、证据摘要、风险等级和批准后的执行动作。若只在前端弹出确认框,后端仍按普通工具调用执行,这个确认既不能审计,也不能在事故后说明责任归属。审批材料要足够具体。高风险动作不能只展示“是否继续执行”,而应展示影响范围、关键参数、数据来源、模型建议、可替代动作和拒绝后结果。比如 DataAgent 准备导出客户明细时,审批卡片应说明字段范围、行数上限、脱敏状态、导出目的和保存期限。审批人看到的是业务后果,而非模型生成的一段解释。
超时策略也要提前定义。审批长时间无人处理时,Run 是继续等待、自动取消、降级为只读报告,还是转派给上级审批,都应写入状态机。不同风险等级可以有不同超时策略:低风险报告发布可以提醒后继续等待,高风险写操作应超时取消并保留恢复入口。这样用户刷新页面或服务重启后,系统仍能解释任务停在哪里。HITL 还应反哺评测。人工拒绝、修改审批意见、要求补证据,都是很有价值的评估信号。平台可以把这些信号写入第39章的业务金标准集,用于改进 Planner、工具参数和报告模板。但反馈进入训练或提示词前必须脱敏,并保留来源和适用范围,避免把一次个案意见扩散成全局规则。
30.7 审批责任与假按钮风险¶
HITL 的价值不在于界面上出现一个“同意”按钮,而在于人工决策真正进入运行链路。很多系统把审批做成前端确认框,用户点击后后端继续执行,但审批原因、审批人身份、审批上下文和审批后的状态变化没有进入 Runtime。这样的按钮只能降低用户心理压力,不能承担审计责任。企业场景里的 HITL 必须把人作为状态机参与者,而非界面装饰。审批责任需要明确到动作级别。人工确认的是执行某个工具、发布某份报告、读取某类数据,还是接受某个风险判断,含义完全不同。审批事件应当记录审批对象、风险说明、候选动作、可见证据、审批人、审批时间和有效范围。审批通过也不代表后续所有动作都获得授权,如果 Runtime 在审批后生成了新的工具调用或扩大了数据范围,应当重新触发审批或降级执行。
假按钮风险还来自超时处理。用户长时间不审批时,系统不能默认继续执行;审批页面断线时,也不能让后台任务停在不明状态。比较稳妥的策略是把审批超时视为独立状态,允许取消、重新通知、转交或降级为只读输出。所有处理都要进入 Trace,后续复盘才能判断任务是被人工拒绝、系统超时还是业务规则阻断。
30.8 长任务恢复中的人工上下文¶
长任务恢复不能只恢复机器状态,还要恢复人工上下文。审批人看到的页面、证据、风险说明和候选动作,构成了审批决策的上下文。系统重启或页面刷新后,如果这些内容重新生成,可能和当时不一致。Runtime 应当保存审批快照,恢复时展示同一份证据,而非基于最新数据重建一份看似相同的页面。人工上下文也影响补偿动作。一个任务在审批后失败,平台需要判断是否可以自动重试,还是必须再次请求人工确认。比如发送合同、更新客户状态、触发付款审批这类动作,重试前必须确认上一次是否已经部分成功。HITL 与 Runtime 的接口应覆盖幂等、补偿和审计:审批回调要能去重,失败后要能判断是否需要人工重新确认,审计记录要能说明批准发生在什么版本和什么动作之前。在早期实现中,可以先把 HITL 限制在少数高风险节点:外部写操作、敏感数据访问、报告发布和跨系统任务委派。范围小一些没问题,但每个节点都要做完整。一个可靠的审批节点,比到处都有但无法审计的确认按钮更有价值。
30.9 HITL 的产品体验边界¶
HITL 既是后端状态,也是前端体验。用户需要知道系统为什么暂停、需要谁处理、处理后会发生什么、等待期间能否取消或补充信息。若前端只显示一个加载状态,用户会误以为系统卡住;若前端只显示审批按钮,审批人又无法理解风险。产品体验必须把 Runtime 状态翻译成可操作信息。体验设计还要避免把责任推给用户。高风险操作需要人工确认,但确认页面应展示足够证据,例如原始请求、计划动作、工具参数、影响范围和失败后果。审批人不能只看到一句“是否继续”。如果证据不足,正确动作应是要求系统补充材料,而非让审批人凭经验判断。HITL 的用户体验边界最终要回到工程状态。前端展示的每个按钮,都应对应后端可审计事件;前端展示的每条风险说明,都应能回到策略或工具证据。只有这样,人工介入才不会停留在交互层,而能真正进入平台治理。
人工介入还需要运营指标。平台应观察审批等待时间、超时率、拒绝率、改派率、审批后失败率和重复审批比例。等待时间过长,说明流程设计或责任人配置有问题;拒绝率过高,说明模型或策略过早触发高风险动作;审批后失败率高,说明审批前证据不足。这些指标直接影响自动化边界:长期通过且风险较低的审批,可以考虑降低打断频率;长期被拒绝的动作,应在 Planner 或 Policy 阶段提前拦截。HITL 上线后,也要观察审批负担。审批量过高,说明策略过紧或任务拆分不合理;审批通过率过高,说明某些动作可能可以降为用户确认或自动放行;审批驳回原因集中在证据不足,说明上游报告或工具结果需要改进。人工介入应是一套随运营数据校准的流程,不应只是租户配置里的静态开关。
长任务运营同样需要看队列和恢复数据。哪些任务经常超时,哪些审批经常无人处理,哪些外部 A2A Task 经常无法取消,哪些用户反复重跑同类任务。这些信号会告诉平台下一步应优化队列、通知、检查点、模板,还是业务流程本身。HITL 的权限模型也要细。批准报告发布的人,不一定有权修改底层数据;能批准导出聚合报表的人,不一定能导出客户明细;能驳回营销文案的人,不一定能修改模型策略。审批动作应绑定具体权限,而非把“审批人”当成一个万能角色。在用户体验上,长任务要给出稳定入口。用户离开页面后回来,应能看到任务状态、待办、已生成产物和下一步动作;审批人从消息系统点进来,也应进入同一个 Run,而非新建一个孤立页面。这样用户感受到的是一个持续任务,不是一组松散通知。
工程实现上,HITL 和长任务还需要幂等设计。审批回调可能重复发送,用户可能多次点击批准,外部系统可能重复推送状态。Runtime 要用 approval_id、artifact hash 和工具调用幂等键识别重复事件。没有幂等,人工介入反而会成为重复执行副作用的来源。人工介入的运营指标也应进入平台看板。待审批数量、平均审批时长、超时率、驳回原因、重复审批和审批后失败,都能反映流程是否健康。没有这些指标,团队只能凭感觉判断 HITL 是保护了业务,还是拖慢了业务。HITL 还要考虑代理审批和交接。审批人休假、组织调整或权限变化时,待办不能长期悬挂。平台需要支持转派、升级和权限重新校验。这些细节决定 HITL 能否长期运行。审批是一段可恢复、可转派、可复核的组织流程;运行数据会反过来帮助团队调整审批分级,把人工放在最有价值的位置,也让后续审计有据可查。
30.10 HITL 运行台账与审批复盘¶
HITL 上线后需要一份运行台账,记录每一次人工介入的对象和后果。台账字段不必复杂,但必须覆盖 run_id、approval_id、审批对象、artifact hash、风险等级、审批人、等待时长、审批结果、拒绝原因、后续动作和审批后失败情况。没有这份记录,团队只能知道“有人点过批准”,无法判断批准的是哪份内容、当时看到什么证据、批准后系统执行了哪个动作。对于报告、导出、外部写操作和跨系统委派,这个差别会直接影响审计结论。
审批复盘要把等待、拒绝和失败分开分析。等待时间长,可能是责任人配置错误、通知渠道失效,也可能是风险说明太含糊,审批人不敢处理;拒绝率高,可能是 Planner 过早提出高风险动作,也可能是审批材料缺少证据;审批后失败率高,通常说明审批前没有充分验证工具参数、artifact 版本或外部系统状态。三类问题的修复路径不同,不能用“审批效率低”一个标签概括。
运行台账还应支持自动化边界校准。长期稳定通过、风险低、证据充分的审批节点,可以降低打断频率,改成批量审批、用户确认或策略自动放行;长期被拒绝的节点,应前移到 Planner 或 Policy 阶段拦截;经常超时的节点,需要调整审批人、SLA 或转派规则。HITL 应减少无意义等待,把人工判断放在风险和证据真正需要的位置。这个边界只能通过运行数据持续校准。
复盘时还要检查假按钮风险。若审批事件没有绑定 artifact hash,或者审批通过后 Runtime 重新生成了内容,审批记录就不能证明发布物经过人工确认。若前端按钮没有对应后端事件,审计包中也看不到审批对象和允许动作。每次复盘都应抽查若干已通过任务,确认审批页面、后台事件、Trace、artifact 和最终发布物一致。发现不一致时,应暂停该类自动发布,直到审批链路能证明版本和动作一致。
早期可以把 HITL 运营纳入每周平台例会。平台团队查看等待和超时,业务负责人查看拒绝原因,合规负责人抽查高风险审批包,产品负责人决定哪些节点降级、保留或提高自动化程度。这样人工介入不再只是一个开发完成的功能,而是一套可度量、可调整、可审计的运行流程。
30.11 人工审批的责任记录与超时恢复¶
HITL 的生产价值不在于页面上出现一个“确认”按钮,而在于人工判断能改变 Run 状态并留下责任记录。审批记录至少要说明谁在什么权限下确认了什么动作,看到的证据是什么,是否修改了模型建议,是否设置了附加条件,审批结果影响了哪些工具调用。若审批只存在前端事件里,Runtime 和审计系统无法证明高风险动作经过了人。
超时恢复要和责任记录一起设计。审批人长时间未响应时,系统可以提醒、转派、降级、取消或保留等待状态,但不能让任务静默继续。不同场景的超时动作不同:数据导出可以取消,合同发送可以转主管审批,低风险报告可以保留草稿,外部系统写入应暂停并释放相关锁。超时动作也要进入 Trace,说明任务为何没有继续执行。
人工节点还要避免“假确认”。如果前端按钮只是让模型继续生成,后端没有审批状态、权限校验和工具执行约束,这个按钮不能承担责任。真正的 HITL 应由 Runtime 创建等待节点,Policy Engine 判断是否需要人工,前端展示证据和可选动作,审批结果回写状态机。这样人工参与才能成为生产链路的一部分,而不是界面上的装饰。
30.12 人工反馈的样本回流¶
人工审批和人工复核会产生高质量反馈。审批人修改结论、退回报告、补充证据、拒绝导出、要求重新查询,都说明 Agent 在某个环节没有达到业务要求。这些反馈如果只停留在审批记录里,就无法改进 Planner、工具、语义层和报告模板。平台应把人工反馈转成结构化样本。
样本至少要记录原始任务、Agent 建议、人工修改、修改原因、相关证据、影响工具和最终处理。若审批人经常补充同一类证据,说明默认证据展示不足;若人工总是改写同一类结论,说明报告模板或指标解释有问题;若大量导出被拒绝,说明风险提示和策略边界需要调整。
反馈回流也要注意责任边界。人工修改不一定意味着模型错误,可能是业务策略变化、数据口径争议或权限限制。样本分类要保留这些原因,避免把所有反馈都当成模型训练材料。HITL 的长期价值,来自把人的判断变成平台证据,而不是只让人在关键时刻点按钮。
30.13 人工节点的体验与责任一致性¶
HITL 的体验设计必须和责任设计一致。用户看到的按钮、提示和倒计时,应该对应后端真实状态。若前端显示“已审批”,后端仍在等待写操作;若用户看到“可取消”,Runtime 实际已经提交外部系统;若审批人只看到了摘要,没有看到证据和风险,责任记录就不完整。人工节点的可靠性,取决于界面、状态机和审计记录是否表达同一件事。
审批页面要呈现足够证据。高风险写操作需要参数、影响对象、数据来源、策略命中、过期时间和回滚方式;报告发布需要 EvidenceRef、人工修改、数据时间和导出范围;权限申请需要申请原因、数据分类和审批范围。审批人不应只看到一段模型生成的说明,否则批准动作会变成形式。
早期可以把人工节点分成确认、审批、复核和接管四类。确认用于低风险澄清,审批用于有副作用动作,复核用于证据或合规判断,接管用于系统无法继续执行。每类节点有自己的状态、超时、责任记录和用户提示。这样 HITL 不会被简化成一个万能按钮,而会成为运行链路中可解释的责任机制。
30.14 人工节点的跨系统通知与回执¶
HITL进入生产后,审批通常不会只发生在 Agent 页面里。审批人可能从企业微信、飞书、Slack、邮件、工单系统或审批系统进入任务。跨系统通知必须和 Runtime 状态保持一致。通知里展示的 artifact 版本、风险等级、到期时间和可选动作,应与审批页面和后端事件一致;审批人从外部系统点击批准后,回执也要回到同一个 run_id 和 approval_id。否则,通知看起来完成了工作,Runtime 却无法证明是谁批准了哪一次动作。
通知链路还要处理失败。消息发送失败、审批人无权限、链接过期、审批系统回调超时、重复回调和审批人组织关系变化,都会让任务卡住。平台应把通知状态纳入人工节点:待发送、已发送、已读、已回执、发送失败、回执失败、已转派。每个状态都要能被 Trace 看到,支持平台判断是用户没有处理,还是通知系统没有送达。
早期可以先支持少量关键回执字段:通知渠道、接收人、发送时间、回执时间、审批动作、artifact hash、权限校验结果和失败原因。这样 HITL 不再依赖单一页面,也不会因为跨系统通知而丢掉责任链。人工审批是一段组织流程,通知和回执就是这段流程的运行证据。
30.15 人工节点争议的证据包¶
HITL 争议通常发生在责任交接处。审批人认为自己只是确认信息,系统却把确认解释成执行授权;业务 owner 认为人工节点已经处理,Runtime 却因为回执缺失继续等待;用户认为已经取消任务,后台工具却完成了写操作。人工节点一旦进入生产,就不能只依赖按钮文案和聊天记录解释责任。平台要为高风险人工节点生成证据包。
证据包应包含任务目标、触发人工节点的原因、审批人身份、审批权限、展示给审批人的上下文、用户可见文案、审批动作、动作时间、后续工具调用和最终状态。若审批涉及外部系统,还要记录外部系统回执和幂等键。这样复盘时可以判断审批人批准的是“继续分析”“生成草稿”“提交写操作”还是“发布结果”。不同授权范围的后果完全不同,不能在事故后再解释。
证据包也能帮助产品设计。若很多审批人只看标题就点通过,说明上下文过长或风险提示不清;若审批频繁超时,说明责任人、通知渠道或候补机制有问题;若用户取消后审批仍继续,说明 Runtime 事件和通知系统没有同步。把这些材料回流到第39章 Eval 和第42章 SLO 后,HITL 就能被持续改进,而不是只作为合规装饰。
早期可以先对三类人工节点生成证据包:高风险写操作、对外发布、权限或数据出域。低风险人工反馈可以保留轻量记录,高风险节点必须能导出完整时间线。HITL 的价值来自清晰责任和可恢复状态,而不是界面上多一个“人工确认”按钮。
30.16 人工节点的轮值与替补机制¶
HITL进入生产后,人工节点不能只绑定一个人。审批人请假、岗位调整、组织变更、通知失败或高峰期积压,都会让长任务卡在等待状态。用户看到的是 Agent 一直没有完成,平台看到的是 Run 挂起,业务 owner 看到的是流程无人负责。人工节点需要轮值和替补机制,把等待从个人行为变成可运营流程。
轮值机制应明确主审批人、替补审批人、升级路径和超时动作。低风险任务可以在超时后转给替补,高风险任务可以要求二次确认或转人工队列;对外发布和写操作则需要保留原审批责任,不应自动绕过。Runtime 要记录每一次通知、确认、转派和超时,前端也要告诉用户当前任务正在等待谁、何时会升级、是否可以取消或补充材料。
替补机制还要处理权限。替补人能否看到同样的上下文,能否批准同样的动作,能否修改已经生成的 artifact,都要由 Policy 决定。若替补人权限不足,系统应提前发现,而不是等任务超时后才失败。对于跨部门审批,平台还要避免把敏感上下文发给不具备权限的替补人。
早期可以先为高频人工节点配置轮值表。轮值表包含角色、主责人、替补人、通知渠道、超时时间、升级规则和审计字段。这样 HITL 不会因为某个审批人离线而阻塞整条 Agent 链路,也能让第42章 SLO 对长任务等待给出可执行承诺。
30.17 审批积压与替补责任人¶
HITL进入生产后,审批积压会直接影响用户体验和业务时效。高风险动作进入人工确认是必要边界,但如果审批人休假、组织调整、消息未读或任务过多,Run 会长期挂起。平台不能只把状态显示为等待人工,而要定义超时、提醒、替补责任人和升级路径。否则用户会反复催促或重新提交,后台形成重复任务。
替补机制要保持责任清楚。主审批人超时后,可以转给备份审批人、业务 owner 或值班角色;但转交必须记录原因、时间和可见材料。备份审批人看到的证据应与主审批人一致,包括用户请求、工具参数、风险标签、历史上下文和可选动作。若材料不完整,备份审批只是形式动作,无法真正承担责任。
早期可以为每类 HITL 任务设置 SLA:首次提醒时间、超时转交时间、最终失败时间和用户提示。挂起状态进入 Trace 和运营看板,团队定期复盘哪些审批经常积压。若某类任务长期依赖人工,平台要判断是需要补自动校验,还是需要重新设计业务流程。HITL 的目标是让高风险动作有责任人,而不是制造新的等待黑洞。
30.18 人工审批的责任证据¶
HITL进入生产后,平台需要把审批人、可见材料、可选动作、审批时间、例外范围、到期时间和后续复测放进统一证据口径。证据口径会减少事后解释成本,让业务、平台、数据、安全和运营团队能够围绕同一组事实讨论问题。没有这些材料,故障发生后只能凭经验判断;有了这些材料,团队可以知道哪些输入有效、哪些动作已经执行、哪些产物可以继续使用、哪些结果需要撤回。
这类证据应和第25章 Planner、第28章多 Agent 协作和第52章合规连起来。上游章节提供能力基础,下游章节使用运行结果,本章则负责说明中间环节如何被验证。若某个能力只在本章看起来完整,却无法进入 Trace、Eval、发布记录或合规证据包,生产系统仍然会出现断点。读者在实现时应把章节之间的接口看成工程契约,而不是阅读顺序上的相邻关系。
常见风险包括按钮存在但 reviewer 看不到关键证据、审批发生在风险动作之后、例外长期有效。这些问题通常不会在一次成功演示中暴露,因为演示样本往往干净、短小、路径明确。真实业务会带来旧数据、异常输入、权限变化、用户撤回、预算限制和长时间运行状态。平台如果没有把这些情况纳入样本和台账,后续扩展场景时就会重复遇到同类问题。
人工审批应证明 reviewer 具备信息和权限,审批记录也要进入后续复测。执行记录至少要说明 owner、版本、样本、影响范围、处置动作和复查时间。记录不需要写成流程报告,但要足够让后来者理解当时的判断。对于高风险能力,还应说明哪些条件满足后才能扩大使用,哪些条件失败时必须降级或撤回。
落地时可以先选择少量代表场景建立这种习惯。实践上,应先把高频、高风险、外部可见的路径做扎实,再把样本、台账和复盘方式复制到其他能力中。这样做能让能力说明落到接入、验证、运营和退出,而不是停留在概念描述。
本章小结¶
HITL 是高风险 Agent 的治理能力,不是模型效果不足时的临时补丁。审批应进入 Runtime 的 waiting_human 状态,并在同一 run_id 上恢复。前置审批、后置审批和分级审批对应不同风险;报告类场景通常先生成草稿,再审批发布动作。引擎检查点负责恢复执行,业务检查点负责展示进度和合规回放,二者不能混用。长任务应通过异步队列、检查点和事件日志承载,避免长期占用同步连接。业务回放包至少要回答谁批准、依据什么数据、发布了什么版本,以及模型是否越过人工监督。
参考文献¶
Amershi, S., et al. (2014). Power to the people: The role of humans in interactive machine learning. AI Magazine, 35(4), 105-120. https://doi.org/10.1609/aimag.v35i4.2513
Mosqueira-Rey, E., et al. (2023). Human-in-the-loop machine learning: A state of the art. Artificial Intelligence Review, 56, 3005-3054. https://doi.org/10.1007/s10462-022-10397-w
EU AI Act. (2024). Regulation (EU) 2024/1689. https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689
NIST. (2023). Artificial Intelligence Risk Management Framework (AI RMF 1.0). https://www.nist.gov/itl/ai-risk-management-framework
Shneiderman, B. (2022). Human-centered AI. Oxford University Press.
LangChain. (n.d.). Human-in-the-loop. LangGraph. https://docs.langchain.com/oss/python/langgraph/interrupts
Temporal. (n.d.). Workflow persistence. https://docs.temporal.io/workflows
