确认与人工接力
pnpm tutorial:dev v3-15 --locale zh源码examples/tutorials/v3-15-confirmation-and-human-handoff/agent 能描述一项页面能力,不等于它可以直接执行。归档工作区、删除记录、发布版本可能需要用户批准;验证码、U 盾、法律确认等步骤则根本不能交给 agent,必须由使用页面的人完成。
Pling 把这两类事件分开:
- 确认回答“允许 agent 做吗?”
- 人工接力回答“用户现在能完成这一步吗?”
它们都不是提示词要求,而是执行流水线中的真实环节:模型选定动作后、业务操作完成前,由框架停下来处理。
先声明风险,再做有意覆盖
动作的 kind 决定默认风险:
kind | 默认审批 |
|---|---|
read | 不确认 |
write | 不确认 |
danger | 每次都确认,不提供“始终允许” |
默认不合适时,用 confirm 覆盖:
const saveAction = {
id: 'save_workspace_name',
desc: '保存共享的工作区设置。这个写操作需要确认一次。',
kind: 'write',
confirm: true,
run: saveName,
};
const resetAction = {
id: 'reset_workspace',
desc: '清空工作区设置。这个危险操作每次都需要确认。',
kind: 'danger',
confirm: 'always',
run: resetWorkspace,
};解析后的策略是:
| 声明 | 审批 | 本段会话可“始终允许” |
|---|---|---|
read / write | none | 不适用 |
write + confirm: true | ask | 可以 |
danger(包括 confirm: true) | ask-always | 永不提供 |
任意 kind + confirm: "always" | ask-always | 永不提供 |
confirm: false 只用于确有独立安全机制的少数情况。它不会让动作变安全,只是移除了这道闸门。
确认发生在执行流水线里
模型提出动作后,执行器依次检查参数、作用域、可用性和审批。需要确认时,runtime 向用户询问。用户拒绝会产生 PERMISSION_DENIED,动作的 run 不会执行。
顺序很重要。只在界面上隐藏危险按钮不够,因为能力仍可能出现在快照中;只在提示词里写“不要删除”也不够,因为提示词不是策略边界。
agent runtime 通过界面提供待审批项。示例由 <AgentDock> 渲染审批面板。自定义宿主可以直接使用 runtime 的审批队列,但必须保留同一条规则:只有明确批准后才能执行。
不要先修改数据、再弹确认。审批是前置条件,不是事后通知。
人工接力意味着框架不会替用户点击
示例的发布动作声明了接力:
handoff: {
reason: '发布前需要本人确认验证码。',
steps: [
{ text: '在验证码输入框中填写 246810。', highlight: 'verification_code' },
{ text: '点击“发布变更”完成确认。', highlight: 'publish_changes' },
],
expect: {
desc: '工作区变更已经发布',
check: () => published.value,
},
}模型调用 publish_changes 时,执行器跳过动作的 run,发出包含原因与步骤的接力请求,高亮当前目标,然后等待三种结果之一:
| 结果 | 错误码 | 含义 |
|---|---|---|
| 用户完成 | 无 | expect 通过后才报告成功 |
| 用户取消 | HANDOFF_CANCELLED | 这一步没有发生 |
| 超时 | HANDOFF_TIMEOUT | 没有确认到完成 |
默认等待时间是五分钟;单个动作可以在自己的 handoff 声明中覆盖。超时不是“自动重试”的信号,模型应先询问用户接下来怎么办。
只要结果可以检查,就应写 expect。否则用户点“我已完成”只是一个说法。检查应读取真实业务状态,而不是短暂的 toast。
确认与人工接力不叠加
声明了 handoff 的动作不会再额外弹出确认审批,因为用户亲手完成这一步本身就已经是决定。先“批准”再“完成”既重复,也会让人分不清哪一次点击真正授权了操作。
两者适用的场景不同:
| 场景 | 机制 |
|---|---|
| agent 可以做,但应先获得用户同意 | confirm |
| 危险操作应每次都问 | kind: 'danger',必要时 confirm: 'always' |
| 必须由人输入信息或使用设备才能正确完成 | handoff |
| 需要指出给人操作的字段 | v-guide-target 配合接力步骤 |
如果 agent 决定“做什么”,但最后一步必须由人完成,用人工接力;如果 agent 可以完成全部操作,只需要人授权,用确认。
检查示例
启动:
pnpm tutorial:dev v3-15然后依次尝试:
- 让助手保存工作区设置。第一次会请求批准;允许一次后,同一段对话中的后续请求可以直接执行。
- 让助手重置工作区。每次都会询问,且没有“始终允许”。
- 让助手发布变更。助手不会替你点表单,而是说明接力步骤,并高亮验证码字段和发布按钮。
- 取消一次人工接力。助手会报告这一步没有完成。
- 输入
246810并发布,再让助手继续。只有页面状态变化后,才会得到经过验证的结果。
运行确定性检查:
pnpm tutorial:check v3-15测试覆盖三种审批策略、拒绝执行、取消接力、成功接力验证和中英文文案。
常见失败
把 danger 当成无需思考的安全判断。 风险等级不知道操作是否可逆、是否受监管、是否适合当前用户,业务含义必须由声明表达。
产生副作用后才请求确认。 如果接口已经调用,确认只是形式。闸门必须放在变更之前。
在后台模拟人工步骤。 不要偷偷 .click() 或填写验证码。声明为人工完成的步骤,要么等待用户,要么 fail-closed。
省略成功判据。 没有 expect 的 handoff 可能在用户只打开弹窗时就报告完成。应检查结果数据、路由或业务状态。
把拒绝当成临时错误。 PERMISSION_DENIED、HANDOFF_CANCELLED、HANDOFF_TIMEOUT 是用户决定或边界条件,不应静默循环重试。

