Harness Engineering 可运行架构

cover
Harness Engineering 可运行架构
核心定位
在保证 agent 自发性和涌现能力的同时,不偏离外部目标、不崩溃。
三个基本约束:
- 目标一定是外部注入的——需求来自人/商业,agent 花的是你的钱
- 控制论的迁移方式:不是完全他控(操纵),也不是完全自治——而是约束环境下的有限自主
- 架构必须在三个维度上可扩展:交互(环境设计)、空间(几百个 agent 并行)、时间(单 agent 连续运行十几小时)
一、反馈回路:分层控制体系
PID 不是一个控制器,而是四层控制手段的组合。从底到顶,延迟递增、成本递增、干预力度递增。

PID 四层控制体系:从 L0 约束层到元层,延迟与干预力度递增
第 0 层:物理约束(零延迟)
来源:Watt 飞球调速器——把被控系统的输出直接耦合到输入上,不经过任何计算。
原则:能用约束解决的不要用监控。约束是无限增益的 P 控制器——让误差根本不可能发生。
具体手段:
- 沙箱隔离:每个 agent 运行在独立的文件系统和网络命名空间中,只能访问被显式授权的资源
- 权限白名单:agent 可用的工具必须显式列出,未列出的工具不可调用
- 硬性超时:每个执行步骤有时间上限,超时即杀进程
- 注意力权重矩阵:通过可见性控制(而非规则禁令)限制 agent 的行动空间——权重为零的模块对 agent 不可见
Scalability 特性:
- 交互:约束嵌入环境本身,不需要额外的监控基础设施
- 空间:每个 agent 的沙箱天然独立,不需要全局协调
- 时间:约束不疲劳、不漂移、不饱和——第 1 小时和第 13 小时行为完全一致
第 1 层:P 即时纠错(秒级)
来源:Armstrong 的 Let it crash 哲学——不要修复失败,重启到已知好状态。
原则:不需要精确度量"偏差是多少",只需要判断"是否偏差了"——这是一个二值判断。
具体手段:
- 异常检测:测试失败、类型错误、构建失败、超时——任何一个都算异常
- kill + restart from checkpoint:检测到异常后杀掉当前执行,从最近的 checkpoint 恢复
- checkpoint 自适应间距:进展顺利时拉大间距(减少存档开销),反复失败时缩小间距(减少回滚损失)
Scalability 特性:
- 交互:环境必须支持快速 checkpoint 和快速 restart(目标:2 秒内恢复)
- 空间:每个 agent 独立 kill/restart,不影响其他 agent——监督树的叶子节点行为
- 时间:checkpoint 是时间维度上的"存档点",跑多久都能回到最近的好状态
第 2 层:I 策略调整(分钟-小时级)
来源:Kálmán 的积分控制——消除系统性偏差,不是修 bug 而是修策略。
原则:单次失败是噪声,反复失败是信号。I 层响应的是模式,不是事件。
具体手段:
- 漏桶计数器:每次异常 +1,每步正常 -0.1。超过阈值 M 时触发策略变更
- 策略变更工具箱:修改 prompt 模板、切换工具链、调整权限范围、拆分任务粒度
- 滑动窗口防饱和(anti-windup):I 分量只计算最近 K 步的累积,不从头算起——防止 agent 因早期错误而后期过度保守
- K 值随阶段缩小:后期对偏差更敏感
Scalability 特性:
- 交互:策略变更通过配置文件下发,agent 在下次重启时自动加载——利用 P 层的 restart 传播配置
- 空间:P 层本地化(每 agent 独立),I 层跨 agent 聚合——一个 agent 偶尔犯的错是噪声,50 个 agent 都犯同一类错说明问题在 prompt 模板或工具链层面
- 时间:滑动窗口大小 K 随阶段调整——早期探索取大值(容忍波动),后期收敛取小值(快速捕捉偏差)
第 3 层:D 预警(趋势驱动)
来源:Boyd 的 OODA Loop——不等误差超标,在误差加速时就提前介入。
原则:agent 不会突然崩溃——它会先慢下来。趋势比阈值更早预警。
具体手段:
- CUSUM 变点检测:对传感器时间序列做在线变点检测,统计特性(均值或方差)发生跳变时触发
- 紧急通道使用频率追踪:如果 P 层和 I 层的触发频率在加速,这本身就是系统退化的高阶信号
- 提前升级:通知人类或触发结构重组,不等到 I 层计数器溢出
Scalability 特性:
- 交互:CUSUM 算法轻量(几行代码),嵌入传感器运行时,零额外成本
- 空间:全局趋势面板——聚合所有 agent 的 D 信号,用一张表纵览系统健康度
- 时间:变点检测天然适合长时间运行——它专门寻找"什么时候 agent 的状态发生了质变"
元层:约束监控
来源:Leveson 的 STAMP 理论——事故发生不是因为组件失败,而是因为控制结构的假设过时了。
原则:监控 harness 本身,而非 agent。最危险的盲区是 harness 的假设过时了而你不知道。
具体手段:
- 约束-任务匹配度检查:当前约束是否仍然适用于当前任务状态?agent 是否在合法地"撞墙"——请求它确实需要但没有权限的资源?
- 传感器自检(Chaos Monkey):定期向系统注入已知异常,检查传感器是否能检测到
- 误报率追踪:过去 N 次警报中多少被忽略或覆写——高误报率 = 传感器标定有问题
- 可控性分析(定期):在任务进度 25%/50%/75% 时,检查是否有重要目标维度在当前架构下不可控
Scalability 特性:
- 交互:元层运行频率低(定期检查点),不常驻,不占用 agent 的执行资源
- 空间:看门狗模式守护全局聚合器的存活性
- 时间:最危险的时刻是第 4-6 小时——初始约束可能已不合适但还没到全局审查时间,元层在此区间提高警觉
二、传感器体系:风险匹配的动态配置
核心原则:传感器精度应匹配失败后果。便宜的传感器永远开着,贵的传感器条件激活。
传感器分类

传感器配置矩阵:按可逆性与作用域匹配传感器精度与响应策略
一级传感器(始终开启,成本极低)
| 传感器 | 测量对象 | 信号类型 | 来源 |
|---|---|---|---|
| 测试通过/失败 | 代码功能正确性 | 二值 | 环境反射弧 |
| 编译/类型检查 | 代码结构合法性 | 二值 | 环境反射弧 |
| Lint/静态分析 | 已知反模式 | 计数 | 环境反射弧 |
| 重启次数计数器 | agent 的挣扎程度 | 计数 | P 层副产物 |
| 需求覆盖率 | spec 条目被实现了几条 | 百分比 | 任务管理器 |
二级传感器(高风险时激活,成本中等)
| 传感器 | 测量对象 | 激活条件 |
|---|---|---|
| 步速(token/步、时间/步) | agent 的行为节奏变化 | 一级传感器出现异常 |
| 回退频率 | agent 的不确定性程度 | 步速骤变时 |
| 工具调用模式 | 循环思维检测 | 同一工具重复调用时 |
| diff 结构分析 | 变更范围和性质 | 涉及跨模块修改时 |
| 跨沙箱契约验证 | 接口一致性 | 多 agent 修改同一边界时 |
元级传感器(定期 + 关键节点)
| 传感器 | 测量对象 | 运行频率 |
|---|---|---|
| 约束-任务匹配度 | harness 的假设是否过时 | 任务进度 25%/50%/75% |
| 传感器自检 | 传感器是否仍在工作 | 定期(Chaos Monkey) |
| 误报率 | 传感器标定是否偏移 | 持续追踪 |
传感器配置矩阵
按失败后果动态选择传感器精度:
可逆 不可逆
┌──────────────┬──────────────┐
本地 │ 一级(二值) │ 二级(节奏) │
│ kill/restart │ 降速+审查 │
├──────────────┼──────────────┤
跨域 │ 二级(契约) │ 元级+人类 │
│ 契约验证 │ 审查 │
└──────────────┴──────────────┘传感器的工程实现原则
- 环境反射弧优先:测试/lint/type check 的结果不是"报告给监控系统",而是直接注入 agent 的下一步输入——传感器和执行器是一体的,没有中间分析层
- 传感器是运行时内建属性:心跳、退出信号、资源计量——这些是进程运行时的自然产物,不是外挂组件
- 日志不是传感器:日志是原始数据流,必须经过特征提取才能变成传感器信号
- 从控制动作倒推传感器需求:harness 只有 5 个控制动作(继续/kill+restart/修改策略/拆分任务/升级人类),不需要度量超出这 5 个动作所需信息的维度
动作审查门(前置传感器)
在每个副作用动作执行前拦截审查:
- 读取型 → 放行
- 写入型 → 检查约束 + 查全局写锁注册表
- 不可逆型 → 严审(可能请求人类批准)
审查严格度随任务阶段调节:早期宽松(鼓励探索),后期收紧(保护交付物)。
三、跨层通信:三种机制组合
核心原则:不是所有跨层通信都需要同一种机制。匹配场景选择最简方案。
机制 A:结构耦合(相邻层常规通信)
适用场景:P→I、I→约束层、D→人类
实现方式:
- P→I:共享计数器。P 层每次 kill+restart 时计数器 +1。I 层定期读计数器,超过阈值即行动。不需要消息、队列、TTL。
- I→约束层:配置文件。I 层修改策略时写入配置文件。Agent 下次重启(被 P 层 kill 后一定会重启)自动加载新配置。配置变更通过重启传播。
- D→人类:报告文件 + 系统通知。不需要实时通道。
特点:零延迟、零基础设施、天然持久化。
机制 B:事件总线(跨 agent 协调)
适用场景:全局态势感知、跨 agent 协调、I/D 信号的全局聚合
实现方式:
- 分区消息队列(按 agent ID 分区,防全局争用)
- 消息 TTL 分级:P 层 anomaly = 1 小时,I 层 threshold_breach = 6 小时,元层 meta_alert = 任务全程
- 监督树结构映射为消息订阅拓扑——消息先到直接父节点,必要时向上传递
技术选型:轻量即可——Redis Stream、内存队列、甚至 Unix 管道。关键是所有跨 agent 通信必须经过这条总线,禁止旁路。
机制 C:安全门控通道(能力变更的下行通信)
适用场景:任何扩大 agent 能力边界的下行变更
核心规则:收缩方向和扩张方向走不同通道。
- 收缩方向(杀进程、收紧权限、缩小约束范围)→ 快通道,最小验证。收缩不扩大 agent 能力,本质上安全。
- 扩张方向(增加权限、放宽约束、增加工具)→ 慢通道,完整验证:影响分析 → 一致性检查(含全局写锁注册表)→ 配置快照 → 执行/阻断
配置版本链:每次下行变更前快照当前配置,形成可回滚的版本链——就像 git 对代码做的事。
触发条件(何时跨层通信)
触发检查内嵌于传感器本身,不是独立组件:
- 阈值突破:传感器读数超过自适应阈值(μ + nσ,基于滑动窗口计算)→ 触发 P 层
- 持续偏离:漏桶计数器超过阈值 M → 触发 I 层
- 趋势突变:CUSUM 检测到统计特性跳变 → 触发 D 层
四、结构重组:三个层次、四种策略
不可变核心(架构不变量)
以下是 harness 的"宪法"——运行时的任何自动化过程都不可修改它们:
- 安全验证门的逻辑
- 跨层通信的消息协议格式
- "每个 agent 必须被某个监督者监督"这一关系
- 人类升级通道的存在性
- kill + restart 的能力
- 传感器的类型和安装位置
修改不变量 = 宪法修正案 = 需要人类审查 + 版本发布。
三个重组层次
| 层次 | 内容 | 频率 | 成本 | 机制 |
|---|---|---|---|---|
| 参数滑动 | 超时值、阈值、OODA 速度 | 每步 | 零 | PID 回路的正常工作 |
| 配置切换 | prompt 模板、工具链、权限集、传感器级别 | 每阶段(2-4 次/任务) | 低 | 加载预定义 profile |
| 拓扑重组 | 监督树结构、agent 分配、任务分解 | 极少(0-2 次/任务) | 高 | 蓝绿部署 / 竞速 / 权重矩阵 |
配置模板(阶段 profile)
profiles:
explore: # 探索阶段:理解需求、阅读代码
checkpoint_interval: 30m
sensor_level: basic # 一级传感器
ooda_speed: slow
constraint_strictness: loose
attention_weights: focused # 主模块权重高,其他低
implement: # 实现阶段:写代码、改配置
checkpoint_interval: 10m
sensor_level: standard # 一级 + 按需二级
ooda_speed: fast
constraint_strictness: medium
attention_weights: expanding # 逐渐展开跨模块可见性
integrate: # 集成阶段:跨模块组装、端到端测试
checkpoint_interval: 3m
sensor_level: full # 全传感器
ooda_speed: fastest
constraint_strictness: strict
attention_weights: cross_module # 跨模块权重升高
converge: # 收敛阶段:最终测试、文档、清理
checkpoint_interval: 5m
sensor_level: full
ooda_speed: slow
constraint_strictness: strictest
attention_weights: global # 全局均匀拓扑重组的四种策略
按确定性和风险选择:
策略 1:权重矩阵调整(最常用)
把离散的"一个 agent 负责一个模块"转变为连续的注意力权重矩阵。"重组"变成"权重调节",走 PID 回路。
模块A 模块B 模块C 模块D
Agent 1: 0.9 0.1 0.0 0.0
Agent 2: 0.1 0.8 0.1 0.0
Agent 3: 0.0 0.1 0.7 0.2
Agent 4: 0.0 0.0 0.2 0.8权重随任务演化平滑调整:前期聚焦(主对角线高),后期扩散(全局趋于均匀)。
策略 2:渐进式迁移(常规拓扑调整)
新旧监督树并行运行,agent 在到达 checkpoint 时逐个迁移到新树,验证通过后关闭旧树。不停机、可回滚。分批金丝雀:先迁移 10% 验证,再迁移其余。
策略 3:竞速探索(不确定最佳方案时)
同时启动多条执行路径(fork from checkpoint),各用不同策略,谁先达标就采纳谁。用资源换速度和确定性。竞速必须有严格时间预算——预算耗尽仍无结果则升级给人类。
策略 4:冻结迁移(不可逆的关键变更)
暂停 → 快照 → 规划 → 验证 → 迁移 → 恢复。最安全但成本最高。仅在涉及不可逆变更时使用。
重组决策流
目标维度持续不达标
│
▼
可控性分析(架构 agent)
│
├─ 手段存在且可用 → 调参数(L1/L2)
├─ 手段存在但不可用 → 拓扑重组(L3)
│ ├─ 知道新拓扑 → 权重调整 或 渐进迁移
│ ├─ 不知道新拓扑 → 竞速探索
│ └─ 涉及不可逆 → 冻结迁移
├─ 手段不存在 → 升级给人类(增加能力)
└─ 目标本身有问题 → L4 目标修正(人类决策)重组冷却期:两次 L3 重组之间至少间隔任务总时间的 10%。频繁触发 L3 自动升级为 L4——因为频繁需要拓扑重组说明问题在目标定义上。
五、三维 Scalability 完整方案

三维 Scalability:交互(环境设计) x 空间(多Agent并行) x 时间(长时间运行)
交互 Scalability:环境设计
环境 = 约束工厂 + 误差信号工厂 + 进程运行时
环境必备的 7 个组件:
| # | 组件 | 功能 | 优先级 |
|---|---|---|---|
| 1 | 沙箱运行时 | 文件隔离 + 网络限制 + 权限控制 | 最高 |
| 2 | 环境反射弧 | 自动测试/lint/type check,结果直接注入 agent | 最高 |
| 3 | Checkpoint 存储 | 快速保存/恢复 agent 状态(目标 2 秒) | 最高 |
| 4 | 动作审查门 | 统一 action gateway,所有工具调用必经 | 高 |
| 5 | 事件总线 | 轻量消息队列,跨 agent 通信 | 高 |
| 6 | 写锁注册表 | 共享资源的并发控制 | 高 |
| 7 | 人类审批接口 | L4 目标修正的入口 | 中 |
设计原则排序:约束 > 快反馈 > 精确反馈
空间 Scalability:几百个 agent 并行
组织结构:监督树
全局监督者
╱ │ ╲
子树A 子树B 子树C ...
╱ ╲ ╱ ╲ ╱ ╲
a1 a2 a3 a4 a5 a6 ...- 叶子节点 = 执行 agent
- 父节点 = 监督 agent(执行 P 层 kill/restart、聚合 I/D 信号)
- 子树可独立做 L3 重组,不影响其他子树
并行策略:
- P 层本地化:每 agent 独立 kill/restart
- I/D 层按子树聚合:子树监督者做本层决策
- 传感器分级配置:95% Watt 级 / 4% Kálmán 级 / 1% Leveson 级(按风险长尾分布)
- 写锁注册表防跨 agent 资源冲突
- 注意力权重矩阵控制可见性,连续可调
分工方式:
- 初始按模块/功能分(权重矩阵主对角线高)
- 困难点竞速探索(fork 多路,选优合并)
- 权重随集成阶段展开,后期趋于均匀
收敛方式:
- 跨沙箱契约验证器保全局接口一致性
- 集成阶段由专门的集成 agent 子树完成
- 全局收敛检查:所有子树的需求覆盖率之和 ≥ spec 要求
时间 Scalability:十几小时连续运行
阶段模型与参数联动:
时间 ──────────────────────────────────────────────────►
0% 25% 50% 75% 100%
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
探索 实现 集成 收敛 交付
OODA 速度: 慢 快 极快 慢
传感器级别: 基础 标准 全开 全开
审查严格度: 松(多读少写) 中 紧 极紧
权重分布: 聚焦主模块 渐展开 跨模块 全局均匀
Checkpoint: 间距大 间距中 间距小 每步存档
I 窗口 K: 大(容忍波动) 中 小(敏感) 最小防退化的 6 个机制:
- I 分量滑动窗口:只看最近 K 步,K 随阶段缩小
- 二级传感器自适应基线:μ + nσ 基于滑动窗口动态计算,不被早期噪声污染
- 约束定期刷新:在 25%/50%/75% 进度时做可控性分析
- 配置版本链:每次变更前快照,支持任意时间点回滚
- 紧急通道使用频率追踪:频率上升 = 系统在退化
- Checkpoint 自适应间距:顺利拉大,失败缩小
六、完整架构图
╔══════════════════════════════════════════════════════════════════════╗
║ HARNESS ENGINEERING 架构 ║
║ ║
║ 外部输入:需求 spec / 验收标准 / 优先级(人类注入) ║
║ │ ║
║ ▼ ║
║ ┌──────────────────────────────────────────────────────────────┐ ║
║ │ 不可变核心 │ ║
║ │ 安全验证门 │ 消息协议 │ 监督关系 │ 人类通道 │ kill 能力 │ ║
║ └──────────────────────────────────────────────────────────────┘ ║
║ │ ║
║ ┌───────────────────────┼──────────────────────────────────────┐ ║
║ │ 元层 │ │ ║
║ │ 架构 agent · 可控性分析(定期) · 元传感器 · L4→人类审批 │ ║
║ │ 配置版本链 · 拓扑重组决策 │ ║
║ └───────────┬───────────┼───────────▲──────────────────────────┘ ║
║ 下行:约束重塑 │ 上行:元信号(趋势/分布偏移) ║
║ (安全验证门) │ (漏桶计数器/CUSUM) ║
║ ┌───────────▼───────────┼───────────┴──────────────────────────┐ ║
║ │ D 层 CUSUM变点检测 │ 紧急通道频率追踪 │ 提前升级/人类 │ ║
║ └───────────┬───────────┼───────────▲──────────────────────────┘ ║
║ 下行:策略变更 │ 上行:趋势加速度 ║
║ (收缩=快/扩张=慢) │ ║
║ ┌───────────▼───────────┼───────────▲──────────────────────────┐ ║
║ │ I 层 漏桶计数器 │ 跨agent聚合 │ 修改prompt/工具/权限 │ ║
║ │ 滑动窗口防饱和│ │ ║
║ └───────────┬───────────┼───────────▲──────────────────────────┘ ║
║ 下行:配置文件 │ 上行:重启计数(结构耦合) ║
║ (重启时生效) │ ║
║ ┌───────────▼───────────┼───────────▲──────────────────────────┐ ║
║ │ P 层 异常检测(二值)│ kill+restart from checkpoint │ ║
║ │ checkpoint自适应间距 │ ║
║ └───────────┬───────────┼───────────▲──────────────────────────┘ ║
║ │ │ │ ║
║ ┌───────────▼───────────┼───────────┴──────────────────────────┐ ║
║ │ 约束层 沙箱 │ 权限白名单 │ 硬超时 │ 动作审查门 │ ║
║ │ 注意力权重矩阵(可见性控制) │ ║
║ └───────────────────────┼──────────────────────────────────────┘ ║
║ │ ║
║ ┌───────────────────────▼──────────────────────────────────────┐ ║
║ │ Agent 运行时 │ ║
║ │ · 环境反射弧(测试/lint/typecheck → 直接注入agent输入) │ ║
║ │ · 内建传感器(心跳/退出信号/资源计量) │ ║
║ │ · 行为模式传感器(步速/回退频率/工具调用模式) │ ║
║ │ · 每个副作用动作经动作审查门 │ ║
║ └──────────────────────────────────────────────────────────────┘ ║
║ ║
║ 跨 Agent 基础设施 ║
║ ┌──────────────────────────────────────────────────────────────┐ ║
║ │ 事件总线(分区消息队列) · 全局写锁注册表 · 监督树 │ ║
║ │ 权重矩阵管理器 · 阶段profile管理器 · 配置版本链存储 │ ║
║ └──────────────────────────────────────────────────────────────┘ ║
╚══════════════════════════════════════════════════════════════════════╝七、从概念到代号的映射表
给工程实现者的快速参考——把控制论术语映射到你已经熟悉的工程概念:
| 控制论概念 | Harness 工程对应 | 你可能已经知道的类比 |
|---|---|---|
| 负反馈回路 | 测试失败 → 修代码 → 重测 | CI/CD 红绿灯 |
| 设定值 | 需求 spec + 验收标准 | User Story 的 AC |
| 误差信号 | 测试失败数 + lint 错误数 | PR Check 的红色项 |
| P 控制 | 即时修复或 kill+restart | git revert + 重跑 |
| I 控制 | 趋势分析 → 修改 prompt/工具 | Sprint 回顾 → 改流程 |
| D 控制 | 变点检测 → 提前预警 | 监控告警的 anomaly detection |
| 物理约束 | 沙箱 + 权限 + 超时 | Docker 容器 + RBAC |
| 必要多样性 | 控制手段的丰富度 ≥ 故障模式的多样性 | Runbook 覆盖率 |
| 信道容量 | harness 的信息处理预算 | 团队的 On-call 带宽 |
| 超稳定系统 | 快回路失败 → 慢回路重构快回路 | "如果重试不行就换方案" |
| 可观测性 | 传感器能否重构 agent 的真实状态 | OpenTelemetry 的 trace |
| 飞球调速器 | 环境反射弧——输出直接耦合到输入 | 编辑器的实时红色波浪线 |
| Let it crash | 崩溃没关系,重启要快 | Kubernetes Pod 重启策略 |
| 监督树 | 父进程管理子进程的层级结构 | K8s Deployment → ReplicaSet → Pod |
| 蓝绿部署 | 新旧拓扑并行运行,验证后切换 | 蓝绿部署本身 |
| OODA Loop | 观察-判断-决策-行动的循环速度 | 热部署的 feedback loop |
| STAMP/STPA | 安全约束分析——哪些控制动作在哪些上下文下是不安全的 | Threat Modeling |
| 注意力权重矩阵 | agent 对各模块的可见性权重 | 文件系统挂载点 |
八、开放问题
权重矩阵的自动调节:权重怎么自动调?启发式规则(失败多就降权、协作多就升权)可能足够启动;后期可演化为在线学习。
架构 agent 的设计:这个 agent 不执行任务,只观察拓扑健康度。它的传感器是失配度 R 和可控性分析。它本身也需要被监督——但它的监督者是人类。
人类介入频率:最低频率 = 任务进度 25%/50%/75% 的三次检查点。额外介入 = D 层升级或 L4 目标修正提案时。目标:人类每天介入不超过 5 次。
Checkpoint 的内容:最小可行 checkpoint = 已完成工作的文件快照 + 当前任务分解状态 + 最近 K 步的传感器摘要。不需要保存 agent 的完整上下文窗口——从 checkpoint 恢复时重新构建上下文。
契约的自动生成与验证:当 agent 修改一个模块的接口时,自动从代码中提取接口签名作为契约。其他依赖该接口的 agent 在执行前自动检查契约是否兼容。技术上可以用类型系统实现。