Harness Engineering 05Safety HITL Harness边界、接管与回滚activity-dev-harness 早期有一次事故Developer Agent 修复一个 UI 问题时判断根因在配置文件然后改了_generated/config.lua——这是构建产物目录每次构建会被覆盖。修改被覆盖后 Agent 检测到修复没生效于是再改一次再被覆盖再改……陷入死循环3 轮全部浪费。问题不是 Agent不够聪明。它的修复思路合理代码也写对了。问题是系统没有告诉它这个目录不能改。一个写权限没有边界的 Agent能力越强做出越界修改的概率就越高。同一时期配置表风险评估系统出了另一个问题Agent 判定某张高风险配表为低风险自动放行上线。原因是 RAG 召回了旧版规则新规则还没入索引。如果有人工接管机制——高风险配表必须人工确认——这张表就会被拦截。两个故事一个结论安全不能靠模型小心点接管不能靠人偶尔看看。两者都必须是系统内建的工程机制。三类安全问题不是说错了是做错了Agent 的安全问题和传统内容安全幻觉、有害输出不是一回事。一旦 Agent 有执行能力安全问题升级为三类系统风险风险类型 含义 举例 ────────── ──────────────── ────────────────────────────── 动作风险 执行了不该执行的动作 改了构建产物目录 删了不该删的文件 重复执行非幂等操作 权限风险 访问或操作了超出范围的资源 Reviewer 顺手修改了代码 读取了无权限的敏感配置 调用了超出角色定义的工具 传播风险 一个错误沿链路放大 错误修复 → 测试基于错误代码 → Reviewer 基于错误测试结果放行 → 错误代码进入下一轮关键区别内容风险的后果是回答不对系统风险的后果是动作不可逆。后者才是 Safety Harness 的核心关切。六类安全机制┌──────────────────────────────────────────────────────────────────────┐ │ Safety Harness 六层防线 │ ├──────────────────────────────────────────────────────────────────────┤ │ │ │ ① 最小权限 │ │ 每个角色只有完成任务所需的最小工具集和最小操作范围 │ │ │ │ ② 操作范围约束 │ │ 写操作限定目录/表/API禁区显式标记 │ │ │ │ ③ 动作分级 │ │ L1 自由执行 / L2 校验后执行 / L3 人工确认后执行 │ │ │ │ ④ 循环上限 │ │ 多轮任务有最大轮数限制防止死循环和成本爆炸 │ │ │ │ ⑤ 错误阻断 │ │ 关键检查失败时自动停止不允许带伤继续 │ │ │ │ ⑥ 回滚路径 │ │ 每次写操作前保存快照失败后可自动或手动回退 │ │ │ └──────────────────────────────────────────────────────────────────────┘错误示范 vs 正确示范activity-dev-harness 的安全设计❌ 早期版本无 Safety Harness Developer Agent 工具file_read, file_write, grep, pytest, dry_run, shell_exec 可编辑范围整个仓库没有限制 循环上限无跑到 token 耗尽为止 错误处理测试失败 → 自动重试 → 继续下一轮 Reviewer Agent 工具所有 SH 脚本 DC 脚本 file_write可以顺手修修 实际发生的问题 1. Developer 改了 _generated/ 目录 → 修改被覆盖 → 死循环 2. Developer 跑了 8 轮才停token 耗尽→ 成本 $2.40正常应 $0.55 3. Reviewer 发现问题后直接改了代码 → 审查独立性丧失 4. 错误修复传播到下一轮 → Reviewer 基于错误代码做审查 → 放行 ✅ 当前版本有 Safety Harness Developer Agent 工具file_read, file_write, grep, pytest, dry_run5 个砍掉 shell_exec 可编辑范围仅 combat/ 和 src/显式白名单 禁止区域_generated/, _archive/, cases/gold/显式黑名单 循环上限最多 3 轮 错误处理 pytest 失败 → 可重试幂等 file_write 到禁区 → 直接拒绝不重试 3 轮后仍 FAIL → Controller 终止标记为需人工处理 Reviewer Agent 工具SH-01~10, DC-01~07全部只读 可编辑范围无不能写任何文件 Controller 职责循环控制、终止决策、最终 closeout 安全规则 任一 gold case SH 检查全 FAIL → 自动阻断 3 轮循环未收敛 → 终止 人工升级 总 token 消耗超预算 200% → 强制终止改造前后的安全指标指标 无 Safety 有 Safety 变化 ────────────────── ────────── ────────── ────── 越界修改改禁区文件 22% 0% -22pp 死循环超过 5 轮 15% 0% -15pp 单 case 最大成本 $2.40 $0.82 -66% 审查独立性违规 18% 0% -18pp 错误传播到下一轮 31% 5% -26pp权限分级矩阵Developer Reviewer Controller 人类 ────────── ───────── ────────── ──── file_read ✓ ✓ ✓ ✓ grep ✓ ✓ ✓ ✓ file_write ✓(白名单) ✗ ✗ ✓ pytest ✓ ✗ ✗ ✓ dry_run ✓ ✗ ✗ ✓ SH 检查脚本 ✗ ✓ ✓(只读结果) ✓ DC 检查脚本 ✗ ✓ ✓(只读结果) ✓ 终止循环 ✗ ✗ ✓ ✓ 标记人工升级 ✗ ✗ ✓ ✓ 修改 gold case ✗ ✗ ✗ ✓ 修改评测规则 ✗ ✗ ✗ ✓ 关键原则 1. 能写代码的不能做审查防止 Reviewer 既当裁判又当选手 2. 能做审查的不能改代码保证审查独立性 3. 能终止流程的不能直接改结果Controller 只管流程不管内容 4. 能改规则的只有人类防止 Agent 修改自己的考试标准Human-in-the-loop不是不放心就让人看看HITL 最容易被理解成给系统加个审批按钮。但真正的 HITL 设计是一个关于决策权分配的工程问题哪些决策该自动化哪些必须让人接管 判断维度 风险低 风险高 ────── ────── 可逆 全自动 自动 事后审计 grep, read file_write 白名单内 不可逆 自动 确认 必须人工 pytest 执行 修改 gold case, 改评测规则, 高风险配表上线接管决策树Agent 即将执行一个动作 │ ▼ 动作在白名单内 ──── 否 ──→ 拒绝执行 │ 是 ▼ 动作风险等级 ├── L1只读──→ 直接执行 ├── L2有限写──→ 参数校验 → 执行 → 结果确认 └── L3高风险──→ 人工确认 → 执行 → 审计记录 │ ▼ 执行结果 ├── 成功 ──→ 继续流程 ├── 失败幂等操作──→ 可重试最多 2 次 └── 失败非幂等──→ 停止 回滚 通知人类 │ ▼ 累计循环次数 ├── 3 轮 ──→ 继续 └── ≥ 3 轮 ──→ Controller 终止 → 人工接管四类适合人工接管的节点节点类型 特征 真实案例 ────────── ──────────────────── ────────────────────────── 高风险决策 动作不可逆 影响范围大 配置表风险评估 高风险配表自动阻断 必须人工确认后才能上线 规则变更 改变系统行为标准 修改评测规则、更新 Prompt 模板、调整 Rerank 权重 异常升级 Agent 无法收敛 3 轮循环后仍 FAIL → Controller 终止 → 升级到人工排查 质量门控 结果需要领域专家判断 Crashsight 根因分析 AI 置信度不够高时 与人工分析一致性 80% 时标记为待确认配置表风险评估的分级接管设计配表变更 风险判定 │ │ ▼ ▼ ┌─────────────┐ ┌────────────────┐ │ RAG 检索 │ │ 规则匹配 │ │ 匹配规则 │────────→│ 判定风险等级 │ └─────────────┘ └───────┬────────┘ │ ┌─────────────────┼─────────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 低风险 │ │ 中风险 │ │ 高风险 │ │ │ │ │ │ │ │ 自动放行 │ │ 自动放行 │ │ 自动阻断 │ │ 记录 │ │ 抽检 │ │ 人工 │ │ │ │ (10%) │ │ 确认 │ └──────────┘ └──────────┘ └──────────┘ 实际数据月均 配表变更总数~400 张 低风险自动放行320 张80% 中风险自动放行抽检60 张15%→ 抽检发现 2 张误判 高风险人工确认20 张5%→ 确认后 3 张被驳回 如果没有分级接管 方案 A全部自动 → 3 张高风险配表上线每张可能造成线上事故 方案 B全部人审 → 每月 400 张人工审查ROI 极低 分级接管的价值用 5% 的人工成本拦截 100% 的高风险变更“交接质量”人工接管的工程标准把决策交给人的时候不是扔一句请人工确认就行。交接质量决定了人类能不能做出好的判断❌ 低交接质量 通知case-017 需要人工确认 附加信息无 人类需要自己读代码、跑测试、理解上下文 → 30 分钟 ✅ 高交接质量 通知case-017 需要人工确认 ┌──────────────────────────────────────────────┐ │ 任务修复 calculateDamage 暴击倍率 │ │ 状态3 轮循环未收敛 │ │ 原因SH-03 参数一致性检查持续 FAIL │ │ │ │ Developer 修改combat/damage.lua:42-48 │ │ diff: 3 -1 lines │ │ │ │ 已通过SH-01, SH-02, DC-01~05 │ │ 未通过SH-03暴击倍率参数 2.5 vs 期望 2.0 │ │ │ │ 建议检查 case JSON 中 critMultiplier 字段 │ │ 是否应为 2.5需求变更还是 2.0原设计 │ └──────────────────────────────────────────────┘ 人类需要读 5 行摘要 确认一个参数 → 2 分钟好的交接不是把问题甩给人而是把决策所需的最小必要信息打包好让人做最后一步判断。Safety HITL 在不同项目里的设计差异项目 Safety 重点 HITL 重点 ──────────── ────────────────── ────────────────────── activity-dev 写权限隔离 循环上限 3 轮未收敛 → 人工升级 harness 禁区标记 错误阻断 AIReview 规则不可篡改 低置信度审查 → 人工复核 审查结果只读输出 新规则上线 → 人工验证 配置表风险 RAG 时效性保障 高风险配表 → 人工确认 评估 批处理幂等性 规则变更 → 人工审批 Crashsight 历史数据质量保护 根因分析一致性 80% 错误根因不可污染新分析 → 标记待确认Safety 自查清单检查项 你的系统 ──────────────────────────────── ──────── 每个角色的权限是否显式定义最小权限 □ 写操作是否有范围约束白名单/黑名单 □ 是否有循环上限防止死循环和成本爆炸 □ 关键检查失败时是否自动阻断 □ 是否有回滚路径写操作前保存快照 □ 高风险决策是否需要人工确认 □ 人工接管时是否有高质量交接信息 □ Agent 是否有能力修改自己的评测标准 □ ← 必须是否 通过 6 项以上 → 系统有基本安全边界 通过 4-5 项 → 核心防线还缺关键环节 通过 3 项以下 → 系统在裸奔Safety HITL Harness 的核心判断安全不是让 Agent小心点而是让系统具备不可绕过的边界。HITL 不是不放心就让人看看而是把人放在高价值、高风险、低可逆的决策节点上。能力越强的 Agent越需要更严格的安全治理——因为能力越强越界的半径就越大。