Harness Engineering 05|Safety & HITL Harness:边界、接管与回滚

Harness Engineering 05|Safety & 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_run(5 个,砍掉 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,越需要更严格的安全治理------因为能力越强,越界的半径就越大。

相关推荐
上海合宙LuatOS9 小时前
LuatOS扩展库API——【xmodem】文件传输协议
物联网·junit·luatos
胡利光2 天前
Harness Engineering 02|Repo Harness:让仓库对 Agent 可读
java·junit·单元测试
上海合宙LuatOS3 天前
LuatOS扩展库API——【libnet】TCP/UDP协议
物联网·tcp/ip·junit·udp·luatos
上海合宙LuatOS4 天前
LuatOS扩展库API——【libfota】远程升级
物联网·junit·lua·luatos
上海合宙LuatOS4 天前
LuatOS扩展库API——【libfota2】远程升级
网络·物联网·junit·luatos
上海合宙LuatOS7 天前
LuatOS扩展库API——【 lbsLoc2】免费版单基站定位
数据库·物联网·oracle·junit·lua·luatos
Java成神之路-10 天前
SpringBoot 整合 SSM 全流程详解(含 JUnit+MyBatis 实战)(Spring系列18)
spring boot·junit·mybatis
那个失眠的夜13 天前
Spring 的纯注解配置
xml·java·数据库·后端·spring·junit
liulilittle13 天前
Lua 浮点数比较
开发语言·junit·lua