Appearance
第17章 Human-in-the-Loop:人机协作设计
"The best AI systems are not fully autonomous — they are force multipliers for human intelligence."
本章要点
- 人机协作是一个频谱:从全手动到全自动,Agent 应在中间找到合适的位置
- 介入时机:高风险操作、模糊需求、主观判断、专业领域
- 渐进式信任:从高干预开始,随信任积累逐步放权
- 中断成本:每次人类介入都有延迟代价,最小化不必要的中断
17.1 自动化频谱
全手动 AI 辅助 AI 主导+人审批 全自动
人做一切 ←──────── 人做决策,AI执行 ────── AI做决策,人确认 ────→ AI做一切
代码补全 Claude Code 无人值守脚本
搜索建议 Cursor Agent 定时任务大多数 Agent 系统应该处于中间位置——AI 主导执行,人类在关键节点审批。完全自动化看起来很酷,但在生产环境中几乎不可行——一个错误的 git push --force 就足以让团队加班到凌晨。
17.2 何时需要人类介入
高风险操作
操作的不可逆性越高,越需要人类确认:
低风险(自动执行):
- 读文件
- 搜索代码
- 运行测试
- 创建新文件
中风险(默认询问):
- 修改已有文件
- 安装依赖
- 执行 Shell 命令
高风险(必须确认):
- git push
- 删除文件/分支
- 修改 CI/CD 配置
- 发送消息到外部系统(Slack、邮件)
- 操作生产环境Claude Code 的做法:评估每个操作的可逆性和影响范围,不可逆或影响共享状态的操作需要确认。
模糊需求
当用户需求不明确时,Agent 应该先澄清再行动:
❌ 用户: "优化一下性能"
Agent: [修改了 20 个文件] 完成!
用户: 我说的是数据库查询的性能,不是前端...
✅ 用户: "优化一下性能"
Agent: 请问是指哪方面的性能?
- 前端渲染速度?
- API 响应延迟?
- 数据库查询效率?
- 构建/打包速度?主观判断
代码风格、架构选择、命名规范——这些没有唯一正确答案,应该让用户决定。
17.3 审批工作流设计
内联审批
最常见的模式——Agent 在执行前暂停,展示计划,等待用户确认:
Agent: 我准备执行以下操作:
1. 修改 src/auth.ts(添加 JWT 验证)
2. 修改 src/middleware.ts(注入认证中间件)
3. 运行 npm test 验证
是否继续?[Y/n]Claude Code 就是这个模式——用户可以逐个批准或拒绝工具调用。
批量审批
当操作数量多时,逐个确认效率太低:
Agent: 需要修改以下 8 个文件来完成重命名:
src/auth.ts
src/auth.test.ts
src/middleware.ts
...
全部批准 / 逐个审核 / 取消?异步审批
对于长时间运行的任务,允许 Agent 先做完不需要审批的部分,把需要审批的积攒起来:
python
# LangGraph 的 interrupt 机制
def deployment_node(state):
# 准备工作(无需审批)
build_result = build_project()
run_tests()
# 部署需要人类审批
interrupt({
"action": "deploy_to_production",
"build": build_result,
"tests": "all passed",
"message": "准备部署到生产环境,是否继续?"
})
# 人类审批后继续
deploy(build_result)三种审批模式的交互对比
LangGraph 的 interrupt 机制
LangGraph 提供了原生的中断/恢复支持。当图执行到 interrupt() 节点时:
- 状态被自动 checkpoint — 保存到 checkpointer(SQLite/PostgreSQL)
- 执行暂停 — 返回控制权给调用方
- 用户审批后 — 调用
graph.invoke(Command(resume=value))从断点恢复 - 状态完整恢复 — 所有之前的计算结果都在
这使得"等待人类审批"不需要占用任何服务器资源——审批可以发生在几小时甚至几天之后。
17.4 渐进式信任
用户对 Agent 的信任需要时间积累。好的系统支持渐进放权:
初次使用:
- 每个文件修改都需要确认
- 每个 Shell 命令都需要确认
使用一周后:
- 文件修改自动批准
- 安全命令(npm test, git status)自动批准
- 危险命令仍需确认
使用一个月后:
- 大部分操作自动批准
- 只有影响共享状态的操作需要确认信任积累的决策矩阵
关键原则:不可逆操作永远需要确认,与信任级别无关。 渐进放权只适用于可逆操作。
Claude Code 通过权限模式实现:
Plan Mode → Default Mode → Auto-Edit Mode → Full Auto Mode
(限最大) (限最小)用户根据自己的信任程度选择模式。关键是选择权在用户手中。
17.5 反馈循环
人类的修正是 Agent 最宝贵的学习信号。
即时反馈
Agent: [修改了文件]
用户: "不要这样写,我们团队的规范是..."
Agent: [记录为 feedback 记忆,下次避免]Claude Code 会将用户的纠正存入长期记忆(feedback 类型),未来对话中自动加载。
隐式反馈
用户的行为本身就是反馈:
Agent 提出方案 A,用户说"好的" → 正向信号
Agent 提出方案 A,用户说"换一种方式" → 需要调整
Agent 修改了文件,用户立即 git checkout 恢复 → 强烈负向信号反馈闭环
观察用户行为 → 提取信号 → 存入记忆 → 下次调整行为 → 观察效果17.6 降低中断成本
每次人类介入都有成本:打断心流、等待输入、上下文切换。好的人机协作应该最小化不必要的中断。
批处理确认
不要一个个文件问,把相关操作打包:
❌ 修改 auth.ts? [Y/n]
修改 auth.test.ts? [Y/n]
修改 middleware.ts? [Y/n]
✅ 修改以下 3 个文件完成 JWT 集成? [Y/n]
- auth.ts (添加 JWT 验证函数)
- auth.test.ts (新增测试用例)
- middleware.ts (注入认证中间件)提供足够信息
用户需要足够信息才能做出决策——但不需要看到所有细节:
❌ "是否执行这个命令?" ← 什么命令?为什么?
✅ "准备运行 npm test 验证修改 (预计 30 秒)
这是为了确保 JWT 集成没有破坏现有测试。
[执行] [跳过] [查看详情]"记住用户偏好
typescript
// 用户批准了 "npm test",记住这个偏好
if (userApproved && action.type === 'bash') {
permissionCache.allow(action.command, { scope: 'session' })
// 本次会话内不再询问相同命令
}17.7 信任构建要素
用户信任 Agent 需要三个条件:
透明性
Agent 应该解释自己在做什么、为什么这样做:
我准备修改 auth.ts,因为:
1. 当前的 token 验证逻辑在 JWT 过期时不会刷新
2. 这导致了你报告的"用户突然被登出"的 bug
3. 修改方案: 在验证失败时检查是否可刷新,而非直接拒绝可预测性
相同的输入应该产生相似的行为。如果 Agent 今天谨慎、明天激进,用户无法建立信任。
可逆性
让用户有信心——即使 Agent 做错了,也可以撤销:
Agent: 修改已完成。如果效果不好:
- git checkout src/auth.ts (恢复单个文件)
- git stash (暂存所有修改)
- 我可以帮你 revert17.8 本章小结
人机协作的核心设计原则:
- 频谱定位——大多数 Agent 应处于"AI 主导 + 人审批"的位置
- 风险驱动——操作越不可逆,越需要人类确认
- 渐进信任——从严格到宽松,让用户选择
- 最小中断——批处理、记忆偏好、提供决策信息
- 反馈闭环——将人类修正转化为长期记忆
- 建立信任——透明、可预测、可逆
下一章我们进入生产化部分——如何评估和测试 Agent 的行为。