Browse this library

Chinese source article

3.2.2 · 可执行策略与因果评测

把生成代码写成可验证策略,并用生命周期、监督和因果消融评测其长程作用。

View original Markdown ↗

1. 代码作为策略的形式语义

自然语言计划通常只描述意图,代码会把控制流、数据依赖和异常路径固定下来。设环境状态为 sts_t,生成程序为 pp,解释器语义为 ⟦p⟧\llbracket p\rrbracket,一次执行可以写成

(st+1,ot,et)=⟦p⟧(st),(1)(s_{t+1},o_t,e_t)=\llbracket p\rrbracket(s_t), \tag{1}

oto_t 是可观察输出,ete_t 是副作用记录。Harness 不只要判断程序能否运行,还要核对它是否在授权状态上实现目标、产生了哪些外部变化。 代码把部分推理从模型 token 转成解释器步骤。循环、条件和数据变换无需模型逐项生成,执行结果也能被测试。若要处理一万个文件,模型写一个遍历程序比发出一万次工具调用更紧凑;错误程序也会把同一错误复制一万次,因此静态约束和小样本试运行非常重要。

程序的语义不等于源代码文本。相同逻辑可有多种写法,文本相似度无法判断行为一致;一行命令也可能隐藏网络、文件和进程副作用。验证应落到输入输出、资源访问与环境差异,而非只让模型阅读代码后评价。 部分函数适合纯语义:相同输入得到相同输出,不读写外部环境。纯函数容易缓存、重放和单元测试。工具动作属于效果语义,需要记录文件、网络、时间、随机性和权限。Harness 若把两类混在一个无类型字符串中,就无法安全重试。

可将动作返回值写成带效果集合的类型

p:X→Y  !  E,(2)p:X\rightarrow Y\;!\;\mathcal E, \tag{2}

E\mathcal E 声明可能的读写、网络和外部事务。调度器据此安排沙箱和并发,Auditor 对实际效果与声明效果做差异检查。未声明副作用应视为合约违例。

从自然语言规格到程序的两次编译. Agent 先把用户目标编译成可执行规格,再把规格编译成代码。第一步决定「什么算正确」,第二步决定「怎样实现」。把两步直接合成一次生成,代码可能运行成功,却解决了错误问题。 规格至少包含前置条件 PP、后置条件 QQ 和允许副作用集合 EE。Hoare 三元组写成

{P} p {Q}E.(3)\{P\}\ p\ \{Q\}_{E}. \tag{3}

执行前验证 PP,沙箱限制效果不超出 EE,执行后验证 QQ。若前置条件不成立,程序没有义务产生正确结果;若后置条件不可观察,Harness 也无法证明完成。 例如「修复所有损坏图片」需要先定义损坏判据、扫描范围、允许重画或删除引用的条件和最终审计。直接写修复脚本会把模糊判断藏进代码。规格明确后,检测器、修复器和最终扫描可以分别测试。 规格本身也可能错。可以生成反例:构造文件头全零但尺寸正常、扩展名与 magic 不一致、Markdown 引用不存在等边界,检查 QQ 是否拒绝它们。若测试只覆盖正常图片,程序和验证器可能共享盲点。

第二次编译要保持规格追踪。代码模块、测试和日志引用对应 requirement ID;规格变化时定位受影响模块,而非全量重写。最终报告也能从 requirement 到测试证据反查。

程序搜索与执行反馈,代码型 Harness 常形成「生成—运行—观察—修复」循环。模型提出程序 pkp_k,环境返回测试和错误 fkf_k,下一轮生成 pk+1p_{k+1}. 这是一种带执行反馈的搜索,不应把每轮修改都当独立答案。 状态可表示为

zk=(pk,Tk,Fk,Dk),(4)z_k=(p_k,T_k,F_k,D_k), \tag{4}

TkT_k 是已通过测试,FkF_k 是失败证据,DkD_k 是环境 diff。下一轮应保持 TkT_k 对应的不变量,同时修复 FkF_k。只把收尾阶段一条报错塞回 prompt,容易修一个测试又破坏旧测试。 测试反馈的信息量不相同。编译错误定位语法,单元测试定位局部行为,端到端失败可能来自多模块。Manager 可以选择最能缩小候选空间的下一项检查,而非每次运行最昂贵全套测试。 设候选程序集合为 Pk\mathcal P_k,测试 tt 将其划分为通过与失败两部分。理想测试最大化预期信息增益

IG(t)=H(Pk)−Eyt[H(Pk∣yt)].(5)IG(t)=H(\mathcal P_k)- \mathbb E_{y_t}[H(\mathcal P_k\mid y_t)]. \tag{5}

真实系统不会枚举程序集合,但这个视角解释了为什么最小复现和针对性测试比反复跑大集更利于定位。 执行反馈还可能误导。flaky 测试、缓存产物和环境漂移会让同一程序得到不同结果。Harness 应保存输入版本和随机种子,对不稳定失败重复验证,再决定修改代码。否则模型会为环境噪声制造无关补丁。

验证器也必须在信任边界之外,Agent 若能读取并修改评分脚本,最容易的「修复」可能是让测试永远返回成功。验证器、隐藏测试和安全策略需要位于被测程序权限之外。代码作为 Harness 的可验证性依赖这个隔离。 可信计算基包括解释器、沙箱、权限检查、状态存储和最终验证器。它们越复杂,出现漏洞的机会越大;生成代码本身不应获得修改这些组件的权限。Harness 自我升级要走独立审查与版本发布,而非任务中的 Executor 随手改动。

验证器输出要绑定被测产物哈希。测试结束后代码若继续变化,旧 pass 失效。并行任务合并后,即使各分支单独通过,也要对组合版本重跑相关测试。 隐藏测试能防止直接迎合样例,却可能造成不可诊断失败。可以向 Agent 暴露失败类别或最小反例,同时保护完整答案。信息释放需要平衡搜索效率与防作弊。 机器验证也有覆盖边界。类型检查证明类型性质,单元测试证明样例,形式验证证明给定规格;规格与真实目标不一致时仍会通过。最终可信度来自多层证据,而非某个工具名字。

沙箱并不只有「开」和「关」. 沙箱由文件系统、网络、进程、系统调用、资源和凭证多条能力组成。一个程序可以只读仓库、写临时目录、禁止网络;也可以访问指定域名但不能读取用户目录。细粒度能力比全权限或全禁用更适合真实 Agent。 资源限制也是语义边界。无限循环、fork bomb、巨量磁盘写入和 GPU 占满都可能在逻辑正确前拖垮环境。CPU 时间、内存、进程数、输出大小和墙钟超时需要由外层强制。 网络访问会破坏可复现性。依赖下载内容随时间变化,API 返回受账户和速率限制影响。能预取并固定的资源应进入环境镜像;必须在线调用的动作记录请求版本和响应哈希,并避免把秘密写进生成代码。

沙箱逃逸测试不能只看正常任务。用专门探针尝试路径穿越、符号链接、子进程继承、环境变量泄漏和 localhost 服务访问,确认限制真实生效。配置声称隔离不等于隔离已经被观察。 Windows、Linux 与 macOS 的路径、权限和进程模型不同,同一策略不能机械复用。跨平台 Harness 应让能力抽象保持一致,再为每个平台验证实现。论文或仓库只在某一平台测试时,结论要限定。

1.1. 生成代码的生命周期

临时代码、任务脚本和长期 Harness 组件需要不同治理。一次性数据转换可以随任务归档;反复使用的工具应进入版本库、测试和依赖管理;改变控制逻辑的 Harness 代码属于基础设施,升级风险最高。 从临时脚本晋升为共享工具前,至少检查输入 schema、错误处理、幂等性、权限和测试。一个在当前目录偶然成功的脚本,不应直接成为所有 Agent 的默认能力。复用会放大收益,也会放大隐藏假设。

工具退役同样重要。环境 schema 已变化,旧工具仍被模型从文档中调用,会产生难以理解的失败。工具注册表保存版本、兼容范围和废弃状态;计划生成只暴露当前有效接口。 Harness 自我修改要形成受治理的变更:提出补丁,在隔离任务集回归,比较安全与效用,人工或独立策略批准,然后发布新版本。当前任务不能因为某次失败就直接改变全局安全规则。 回滚要求保存旧二进制、schema 迁移和状态兼容性。新版本生成的 checkpoint 可能无法由旧版本读取,因此发布前测试向前/向后迁移,或明确禁止回滚并提供导出路径。

代码怎样变成可执行记忆. 长程 Agent 的记忆不一定是一段摘要。已经验证的解析器、查询脚本、数据转换和测试本身就是可复用记忆:它们把过去解决问题的方法固化成可执行对象。下次遇到同类输入,系统运行程序即可,不必重新用自然语言推导。 可执行记忆至少包含代码 pp、适用前提 PP、版本 vv、测试集合 TT 和来源证据 EE:

m=(p,P,v,T,E).(6)m=(p,P,v,T,E). \tag{6}

缺少前提,工具容易在错误环境复用;缺少测试,无法判断升级后是否仍有效;缺少来源,使用者不知道结论为何可信。只把代码文件放进工具目录,不能算完整记忆。 程序记忆与事实记忆承担不同职责。「接口 v2 的字段名是 user_id」属于事实,可以结构化保存;「怎样把 v1 数据迁移到 v2」适合程序。事实变化会使程序前提失效,Harness 沿依赖关系触发重验或重新生成。 代码还能保存过程性知识。一个复杂网页操作被录成脚本后,步骤顺序、等待条件和错误分支都比文字描述精确。但 GUI DOM、坐标和权限随版本变化,程序记忆具有环境依赖。成功运行次数不能消除未来漂移,需要在每次使用前检查关键前提。

可执行记忆有组合优势。多个小工具可以由新程序调用,形成更高层能力;也有组合风险,两个工具分别安全,串联后可能扩大副作用。例如导出数据与发送邮件单独合法,组合就可能泄露信息。组合程序仍需整体权限审计。 工具使用反馈可以更新记忆,但不能让一次任务自动覆盖全局版本。候选修复先在当前任务分支验证,累积多次证据后再晋升共享工具。这样把在线适应和基础设施发布分开,避免偶然输入驱动全局自修改。

程序化计划与计划图. 自然语言计划通常是有序列表,代码计划可以显式表示条件、循环、并行和依赖。把任务编译成有向图 G=(V,E)G=(V,E),节点是有界动作或验证器,边表示数据与控制依赖。调度器只运行前置条件满足的节点。 节点 viv_i 可定义为

vi=(fi,Ii,Oi,Ri,Wi,Ci),(7)v_i=(f_i,I_i,O_i,R_i,W_i,C_i), \tag{7}

fif_i 是可执行函数,Ii/OiI_i/O_i 是输入输出 schema,Ri/WiR_i/W_i 是环境读写集合,CiC_i 是提交条件。结构化节点让并发、安全和恢复都能落到同一对象。 循环需要终止变量。Agent 说「不断修改直到测试通过」可能无限运行;程序计划应设置最大尝试、预算和单调进展指标。若失败集合在若干轮内不缩小,循环退出并请求重规划,而非换措辞继续。 条件分支也要由可观察谓词驱动。if deployment succeeded 太模糊,应写成健康端点、版本号和时间窗口的组合。谓词返回 unknown 时不能默认进入成功分支。三值逻辑比强行布尔化更适合外部环境。

计划图允许局部重算。接口节点输出 schema 变化,只使后继闭包失效;无关文档节点保持 verified。线性聊天没有显式依赖,常把变化之后的所有工作一起丢弃或全部保留。 动态计划会在执行中增删节点。变更本身形成版本化 patch,检查新节点是否覆盖原目标、是否引入循环依赖、是否扩大权限。模型可以提出图变更,调度器负责验证后应用。

多 Agent 共享程序工件. Scaling 层以带版本的代码、规格、测试和证据作为关键共享对象。Agent A 生成接口,Agent B 写实现,Agent C 做审查,每个角色通过工件 schema 协作。共享自然语言仍用于解释异常,不承担权威状态。 工件状态可分为 draft、tested、approved、released 和 deprecated。生成代码只进入 draft;测试通过进入 tested;安全或人工审查后 approved;被其他任务依赖前才 released。状态跳转带证据,不能由作者自己宣布。 多 Agent 审查并不自动独立。若审查者看到作者的长篇理由,可能被锚定;若共享相同测试,可能共同漏掉规格错误。审查输入应优先包含原始规格、diff 和环境证据,再把作者解释作为补充。

合并冲突有文本、语义和目标三层。文本冲突可由版本控制发现;没有文本冲突的接口变更仍可能造成语义冲突;两个分支分别满足局部目标,组合后也可能违反全局预算或安全条件。合并门必须运行组合验证。 代码所有权影响调度。某 Agent 对模块有局部上下文和历史经验,继续分配可能更高效;长期绑定又会形成单点和盲区。Harness 可以把所有权当软偏好,高风险审查仍交给独立角色。

共享缓存也需来源。编译产物、测试结果和分析索引绑定代码哈希、依赖版本与平台。缓存命中只省计算,不能跨版本证明正确。错误缓存若被多 Agent 复用,会比单体错误传播更快。

不完整反馈下的验证. 现实工具经常只返回部分信息。编译通过不代表运行正确,API 200 不代表业务成功,GUI 点击没有报错也不代表对象改变。代码 Harness 的确定性只能作用于已观察输入,无法自动补齐缺失反馈。 可以把验证结果表示为 {pass,fail,unknown}{pass,fail,unknown}。对要求 rir_i,多个观察 o1,ldots,oko_1,ldots,o_k 通过证据规则合成:任何可靠反例产生 fail;充分证据集合产生 pass;其余保持 unknown。unknown 不触发提交。 验证器覆盖率为

Cov⁡(V,R)=∣{ri:∃vj, vj 可判定 ri}∣∣R∣.(8)\operatorname{Cov}(V,R)= \frac{|\{r_i:\exists v_j,\ v_j\text{ 可判定 }r_i\}|}{|R|}. \tag{8}

覆盖率低时增加执行轮次没有用,应先改善可观察性。很多 Agent 失败表面像规划问题,实际是系统不知道动作是否生效。 反馈可能延迟。提交异步作业后,立即读取状态得到 pending;固定 sleep 会在快任务浪费,在慢任务误判。验证器应轮询有界条件、监听事件或查询作业 ID,并在超时后返回 unknown。 反馈也可能互相矛盾。健康端点显示新版本,页面仍是旧缓存;测试报告通过,日志包含异常。Harness 保存各观察的时间和来源,按一致性模型判断,而非让 LLM 选择更乐观的一项。

主动验证可以选择下一项观察,使不确定性下降最大。若文件哈希已证明写入,没必要重复读文件;若部署版本未知,查询版本端点比重跑本地测试更有价值。观察调度本身属于计划。

执行错误与规格错误要分开,测试失败可能因为程序没有实现规格,也可能因为规格本身错误或测试误解了目标。若 Harness 一律修代码,模型会不断迎合错误测试,最终得到稳定但无用的系统。 诊断可分三条假设:HpH_p 表示程序错,HsH_s 表示规格错,HtH_t 表示测试错。新证据应帮助区分三者。手算样例和外部规范更适合检查规格,独立实现和属性测试更适合检查程序,测试变异与覆盖分析更适合检查验证器。

例如实现排序函数,测试期望去重。程序保留重复项而失败,可能是实现不符测试,也可能用户只要求排序。回到原始目标能发现测试偷偷加入了去重语义。代码和测试共享同一生成上下文时,这类共同偏差尤其常见。 规格变更应产生新版本,旧测试按依赖关系失效;程序 bug 修复保持规格不变,只更新实现和对应证据。把两者都当普通 patch,会让审计历史难以解释。

模型提出修改测试时,权限应高于修改实现。至少要求说明原测试与原始要求的矛盾,并由独立角色审查。否则最短修复路径总可能是删掉失败断言。

代码 Harness 的成本模型. 把推理写成代码会减少重复模型调用,却增加生成、执行、验证和维护成本。总成本可以分解为

C=Cgen+Cexec+Cverify+Crepair+Cmaint+Ccoord.(9)C=C_{gen}+C_{exec}+C_{verify}+C_{repair} +C_{maint}+C_{coord}. \tag{9}

一次性小任务中,CgenC_{gen} 和沙箱启动可能高于直接工具调用;大规模重复任务中,程序复用会摊薄生成成本。多 Agent 扩展主要增加协调与组合验证。 程序执行成本也不等于模型 token。CPU/GPU 时间、网络、存储和外部 API 都应计入。一个只用少量 token 生成的暴力搜索可能消耗巨大计算;评测若只报告 token 会误判效率。 验证成本随风险变化。静态检查便宜,端到端环境昂贵,人工审批最慢。分层验证先运行便宜高召回检查,再对候选调用昂贵验证,可以降低平均成本,但最终高风险条件不能省略。

维护成本常被论文单次实验忽略。工具 schema 更新、依赖漏洞、平台迁移和测试失效都会消耗长期资源。代码成为 Harness 基础设施后,它进入软件生命周期,而非生成完就结束。 扩展收益应画吞吐—成功率—成本三维曲线。增加 Agent 数可能先提高并行度,随后因冲突、审查和环境瓶颈饱和。只展示最大并发点,无法找到实际经济区间。

扩展、权限与版本,多 Agent 系统里,生成任务的速度可能超过验证和合并速度。若没有背压,大量 draft 堆积,占用工作区和上下文,且都基于逐渐过期的状态。Scaling 不只是增加 worker,还要平衡各阶段服务率。 把规划、执行、验证、合并视为串联系统,阶段 ii 到达率为 λi\lambda_i,服务率为 μi\mu_i。稳定运行至少要求长期 λi<μi\lambda_i<\mu_i。Auditor 成为瓶颈时,继续增加 Executor 只会拉长队列。 优先级应考虑依赖关键路径、过期风险和资源。阻塞多个后继的接口审查优先于孤立低价值任务;即将因环境变化过期的结果优先验证;不可逆动作不因队列压力降低审计等级。

背压可以暂停新计划、缩小并发或合并相似验证。不能通过自动接受未审结果缓解队列,那会改变可信状态语义。低风险任务可使用便宜验证器,高风险任务保留强审计。 任务取消后,队列中的旧节点要撤销,运行中的 worker 收到版本更新,迟到结果在提交门被拒绝。只从前端隐藏任务不会停止后台副作用。

2. 一套可证伪的评测协议

评测应同时改变任务长度、程序复用度、反馈完整性、副作用风险和并发度。若只选适合脚本化的批处理任务,代码 Harness 天然占优;若只选一次性主观任务,又看不出可执行工件价值。 基线包括直接自然语言工具循环、带结构化计划但不生成程序、生成程序无持久化、完整 code harness,以及人工编写脚本上界。固定模型、工具权限和总预算,分别观察代码表示与 Harness 机制的贡献。 机制消融逐项关闭类型检查、沙箱、checkpoint、外部验证、版本门和共享工件。每项应有对应压力任务:错误 schema、越权程序、进程崩溃、虚假自报、环境漂移和多 Agent 接口冲突。若关闭机制不改变目标故障,设计解释需要重审。

指标包括终局成功、首次正确时间、重复动作、未声明副作用、错误提交、恢复成本、组合回归、峰值资源与人工介入。对程序复用任务还要记录第二次及后续任务的边际成本。 评测 Harness 自身时,验证器不能由被测 Agent 修改,环境镜像和隐藏测试要冻结。否则系统可能优化评分基础设施而非任务。预算耗尽记为停止,不应与明确错误混成同一失败原因。 任务级结果需要公开或保留完整 trace,才能判断提升来自哪些任务。少量端点平均分无法证明代码机制普遍有效,也无法发现某一安全边界被牺牲换取成功。

接口层的类型契约,Harness interface 把模型输出接到工具和环境。若接口只有函数名和一段自然语言描述,参数缺失、单位混淆、枚举越界和对象错配都会在运行时才暴露。类型 schema 将一部分错误提前到调用前。 工具 ff 的契约可写成

f:X×C→Y∪E,(10)f:X\times C\rightarrow Y\cup E, \tag{10}

XX 是参数类型,CC 是调用上下文与权限,YY 是成功结果,EE 是结构化错误。模型生成调用后先验证 XX 与 CC,只有通过才进入执行器;返回结果按 Y/EY/E 解析,不能用一段字符串同时表示成功和报错。 类型正确仍可能语义错误。路径字段是字符串,但 D:\data 与工作区内相对路径具有不同权限;数字参数类型为整数,单位可能是秒或毫秒。精化类型可以加入范围、单位、路径根和资源所有权。

TimeoutMs={n∈N:100≤n≤600000}.(11)\texttt{TimeoutMs}=\{n\in\mathbb N:100\le n\le600000\}. \tag{11}

这类约束由确定性验证器检查,模型无需每次重新理解,输出 schema 要支持部分成功。批量处理十个对象,八个成功、两个失败,不应只返回一个 success=true。逐项结果、重试安全性和副作用 ID 使计划器只修复失败部分。 schema 演化需要兼容策略。增加可选字段通常向后兼容,改变默认值或枚举语义可能破坏旧计划。每次工具调用记录 schema 版本,checkpoint 恢复时若版本不匹配,节点进入待迁移或重新规划。

接口文档和实现必须同源。根据 schema 自动生成模型可见说明、参数校验和测试样例,能减少三份定义漂移。自然语言补充用途与风险,机器字段负责硬边界。

2.1. 动作的事务语义

代码可能执行一串副作用。中途失败时,环境处于部分完成状态,简单重跑会重复前半段。Harness 需要为动作定义原子性、幂等性和补偿。 对动作序列 a1,ldots,ana_1,ldots,a_n,理想原子事务只暴露初始状态 s0s_0 或最终状态 sns_n。文件系统可以先写临时文件、验证后原子替换;数据库使用事务;跨外部服务往往无法原子提交,只能采用 saga。 幂等键 kk 使重复请求返回同一结果:

apply⁡(a,k,apply⁡(a,k,s))=apply⁡(a,k,s).(12)\operatorname{apply}(a,k,\operatorname{apply}(a,k,s)) =\operatorname{apply}(a,k,s). \tag{12}

这条等式描述可观察效果,不要求内部完全不执行。发送消息、创建订单等动作若服务支持幂等键,超时重试更安全;不支持时先查询外部状态。 补偿函数 cic_i 试图逆转 aia_i,但通常只能达到业务等价,而非抹去历史。删除已发布页面可以停止未来访问,不能保证所有缓存消失;恢复文件可以还原内容,无法收回已读取的数据。状态应保留事故和补偿证据。 事务边界应与验收边界一致。一个节点修改代码、运行测试并提交版本,可以在提交前回滚工作区;把发布也塞进同一节点,就跨越不可逆边界。拆成「准备」「验证」「发布」三阶段更容易控制。

故障注入要覆盖每个副作用之后崩溃。若只在动作开始前或全部完成后测试,无法发现中间状态。恢复程序读取动作日志和环境事实,判断继续、补偿还是人工处理。

程序化记忆何时失效,代码能把经验固化,却会把旧假设一起固化。判断记忆能否复用,需要检查输入分布、依赖版本、权限和目标语义。文件仍能运行,只说明语法兼容,不说明行为仍正确。 记忆条目 mm 的有效性可表示为

valid⁡(m,t)=Pm(st)∧Vm=Vt∧Am⊆At,(13)\operatorname{valid}(m,t)= P_m(s_t)\land V_m=V_t\land A_m\subseteq A_t, \tag{13}

PmP_m 是运行前提,VV 是依赖版本,AA 是权限。任一条件失败,工具从可调用集合移出,等待迁移或重验。 输入分布漂移不一定能由版本号发现。网页结构未声明升级,真实 DOM 已变化;数据字段仍存在,取值范围扩大。运行时监控错误率、边界值和输出不变量,能发现静默漂移。 程序记忆也可能被上游 bug 污染。一个自动生成报告的脚本长期使用错误公式,后续任务都继承结果。来源证据和回归样例帮助追踪受影响产物;修复工具后,依赖旧版本的报告应标记待重算。

删除记忆不只删代码。注册表、缓存、文档示例和模型提示里仍可能引用旧工具。退役流程更新所有发现入口,并让旧版本调用返回明确错误,避免静默转到不兼容替代品。

多模态环境怎样进入代码世界. GUI、图像和物理环境不能天然表示成 API。代码 Harness 需要把连续世界映射为对象、属性和动作,同时保留原始观察以供复核。映射错误会让后续程序在虚构对象上精确运行。 屏幕状态可由截图、可访问性树、DOM 和应用 API 共同描述。截图覆盖视觉内容但难精确定位语义,树和 DOM 结构清楚却可能漏掉画布。对象融合时记录每个字段来源和时间,不把冲突强行压成一个值。 动作同样有多种实现。点击坐标依赖布局,按可访问性 ID 更稳定,调用应用 API 最精确但可能绕过真实用户流程。评测 computer-use 能力时,允许哪种动作会改变任务含义,必须写清。

观察到按钮不代表按钮可点击,点击事件返回不代表业务状态完成。程序需要等待可观察后置条件。对动画和异步加载,轮询条件比固定 sleep 更可靠,并设置最大等待与失败证据。 多模态状态存在识别置信度。OCR 读到金额、视觉模型识别选中状态,都可能错。高风险动作在执行前使用第二观察或人工确认;低风险探索可以带置信继续。代码中的布尔变量若抹掉置信度,会制造虚假确定性。

环境对象还会失去身份。列表排序后第 3 行不再是原对象,坐标移动后旧引用过期。稳定 ID、内容特征和版本联合标识对象;操作前重新解析引用,避免对错对象执行。

Harness 代码的回归无损升级,综述把 regression-free harness improvement 列为开放问题。新增工具、缓存或并行策略可能提高平均成功率,同时破坏旧任务、安全边界或可恢复性。升级需要把行为不变量与能力增益分开验收。 基础回归集覆盖权限拒绝、幂等重试、checkpoint 恢复、schema 迁移、工具错误解析和取消传播。这些是 Harness 语义,不随具体 Agent 能力变化。模型升级或 prompt 调整也必须通过。 能力集覆盖代表任务,报告逐任务配对变化。新版本让十项成功、两项退化,不能只报平均上涨;退化是否落在高风险任务决定能否发布。对随机 Agent 运行多次,区分稳定退化与采样波动。

安全回归使用对抗输入:提示注入、路径穿越、秘密外泄、测试篡改和越权网络。效用提高不能抵消安全不变量失败。发布门对两类指标使用不同规则。 影子运行可以在不产生副作用的环境中重放真实 trace,比较新旧决策与验证结果。差异较大处人工检查,再逐步放量。直接替换所有活跃长任务,会让旧 checkpoint 和新语义混合。 版本发布要定义状态兼容矩阵。支持从哪些旧 schema 恢复、哪些任务必须固定旧版本、哪些节点需要重新验证,都在升级前确定。回滚也作为正式演练,不等事故发生才发现旧版本读不了新状态。

2.2. 人类监督在代码循环中的位置

人类不需要逐行批准所有代码,监督应集中在目标解释、权限升级、不可逆动作和机器验证覆盖不到的质量。其余可重复硬条件交给程序,提高监督信息密度。 审批界面应展示将执行的具体程序、目标对象、预期副作用和回滚方案,而非只问「是否继续」。大型生成脚本可提供 diff、dry-run 结果和资源上限,让人判断真实影响。 人类修改计划后,旧运行中的代码必须失效。批准绑定程序哈希和环境版本;代码在等待期间变化,重新审批。否则 Agent 可以先获得宽泛批准,再替换实现。

人工反馈也进入证据链。审稿人说「这一段事实不准确」,需要绑定文件版本和位置;后续修改后重新审查受影响范围。把反馈只留在聊天里,fresh context 会丢失。 监督成本应纳入评测。一个系统自动成功率高,却每步都要求人确认,未必比低一些但仅关键处接管的系统更实用。报告人工次数、响应时间和每次决策的信息量。

适用边界与端到端评测,可形式化、可执行、可观察的任务最适合代码承载:数据处理、软件修改、实验运行、资源调度和结构化业务流程。代码能复用控制流,测试能验证后置条件,checkpoint 能保存中间成果。 目标高度主观、环境不可观察或动作不可恢复时,代码只提供流程外壳。审美创作仍需人类判断,外部社会后果无法由单元测试覆盖,开放世界事实需要来源核查。把这些问题硬编码成分数,会把价值判断藏进验证器。

一次性极短任务也可能不值得生成程序。直接工具调用成本更低,失败范围小。Harness 应根据重复度、依赖深度、副作用和恢复价值选择代码化程度,而非所有动作都先写脚本。 代码还会制造新的攻击面和维护负担。执行权限、依赖供应链、生成漏洞和工具漂移都需要治理。代码的确定性只能保证同一程序按实现运行,不能保证实现符合用户意图。 因此「代码作为 Harness」最有价值的判断是:将适合机器约束的部分变成可执行、可测试、可版本化工件,同时保留对规格、观察和价值判断的不确定性。这样代码成为可靠承载层,而不是用确定语法掩盖开放世界问题。

形式验证能覆盖到哪里,代码提供形式化入口,但不意味着整个 Agent 系统都能被形式证明。对纯函数、协议状态机和资源边界,可以写不变量并使用类型系统、模型检查或证明器;对开放网页、自然语言目标和外部服务,只能验证局部抽象。 若程序 pp 的规格是前置条件 PP 与后置条件 QQ,证明

P(s)⇒Q(⟦p⟧(s))(14)P(s)\Rightarrow Q(\llbracket p\rrbracket(s)) \tag{14}

只在环境模型、工具语义和 P/QP/Q 正确时成立。真实 API 与模型不一致,或用户目标没有被 QQ 完整表达,证明仍可能与实际需求错位。 最适合验证的是 Harness 内核:状态只能合法迁移,未审计结果不能提交,权限不会扩大,重复事件保持幂等,checkpoint 重放得到同一状态。这些性质规模小、边界清晰,且一旦出错会污染所有任务。 生成程序本身可采用分层保证。类型检查排除结构错误,静态分析发现明显越权,属性测试覆盖广泛输入,形式证明用于少量高风险核心。要求每段临时代码都完成定理证明不现实,也会让验证成本超过任务价值。

证明工件同样需要版本绑定。代码、规格、依赖库或求解器变化后,旧证明证书可能失效。可检查证书由小型可信内核重新验证,比相信生成证明的模型自述更可靠。 无法形式化的部分保留经验与人工证据。界面是否易用、文章是否清楚、外部事实是否最新,都不应被伪装成定理。形式方法的价值是缩小不确定区域,而非宣称开放世界已经闭合。

3. 一条完整的代码 Harness 轨迹

考虑任务:扫描仓库中的损坏图片,能找到原件就修复,找不到则删除引用,最终所有审计计数为零。它包含检测、来源查找、文件修改、Markdown 更新和全局验证,适合展示三层如何连接。 接口层先定义 audit_image(path)、replace_image(path, bytes)、find_references(path) 和 remove_reference(file, target)。每个工具声明路径根、输入输出 schema 与副作用。检测结果区分 zero、bad magic、partial zero head 和 wrong extension,不能只返回一个坏/好布尔值。 机制层生成计划图。节点 A 全库只读扫描,输出带哈希的问题清单;节点 B 对每个问题寻找原件;节点 C 在隔离工作区修复;节点 D 对找不到原件的引用生成补丁;节点 E 重跑全量审计。B 可并行,C/D 按写集合调度,E 依赖所有修改合并。

假设 A 找到 12 个问题,B 找回 9 个原件,3 个没有来源。C 修复 9 张后,其中一张扩展名仍与 magic 不符,局部验证失败,只重开该节点;D 删除 3 个引用,但一个 Markdown 文件同时被另一任务修改,版本门拒绝旧补丁并重新生成。 最终 E 在合并版本上运行,四类计数均为零,同时链接检查通过。只有这份全局证据进入完成状态。若仅汇总局部节点的「9 张已修、3 个引用已删」,组合冲突和残留扩展名都可能漏掉。

扩展层负责并行搜索原件、限制下载网络、缓存哈希匹配并控制 worker 数。增加并发能缩短 B,却不会加速串行合并和最终审计;若磁盘成为瓶颈,更多 worker 反而提高尾延迟。 这条轨迹里的代码承担批量检测与确定修改,模型承担来源判断和缺失时的策略选择,验证器负责最终事实。任何一层都没有独占全部智能,边界清楚才让系统可恢复。

扩展性能的简单模型,设任务有 NN 个可并行节点,单节点平均执行时间 TeT_e,验证时间 TvT_v,串行协调与合并为 TcT_c,使用 ww 个 worker。理想墙钟下界为

T(w)≥N(Te+Tv)w+Tc.(15)T(w)\ge \frac{N(T_e+T_v)}{w}+T_c. \tag{15}

实际还要加冲突、队列和缓存失效成本 To(w)T_o(w):

T(w)=N(Te+Tv)w+Tc+To(w).(16)T(w)=\frac{N(T_e+T_v)}{w}+T_c+T_o(w). \tag{16}

ToT_o 往往随并发增长,达到某点后吞吐饱和。若验证器服务率低于执行到达率,队列持续增长;最优 worker 数由最慢阶段决定,不是硬件线程越多越好。 并行效率可写成

η(w)=T(1)wT(w).(17)\eta(w)=\frac{T(1)}{wT(w)}. \tag{17}

共享写热点、全局测试和模型 API 限流都会降低 η\eta。报告扩展结果时,应给 worker 数、任务图并行度、冲突率和各阶段利用率,不能只给总加速比。 成本还有 speculative waste。多个 Agent 同时探索替代方案,最终只采用一个,其余计算换来搜索多样性。若所有候选高度相关,浪费大;若环境反馈稀疏,适度并行探索可能降低找到可行方案的时间。调度器根据历史成功率和预算控制候选数。 代码工件复用会改变长期成本。第一次任务承担生成与测试,后续任务只参数化运行并复核前提。评测单次冷启动低估复用收益,只测成熟工具又忽略开发成本。两种阶段要分别报告。

可复现运行需要冻结什么,复现 Code as Agent Harness 不只保存 prompt。需要固定模型与采样、Harness commit、工具 schema、解释器和依赖版本、沙箱策略、环境镜像、任务初态、隐藏验证器以及资源预算。 生成程序可能依赖时间、网络和随机性。可以固定的输入进入镜像或数据快照,必须在线的依赖记录请求与响应。随机种子只能控制部分库,GPU kernel 和并发调度仍可能非确定,结果应多次运行。 每轮保存程序源码、执行命令、环境 diff、测试证据和状态转移。只保存最终代码无法知道失败路径,也无法比较 checkpoint、反馈与多 Agent 协作的贡献。大体积证据用内容寻址存储,trace 保存哈希。

预算停止与程序失败分开。Agent 在时间耗尽时仍有正确候选,属于 censored outcome;验证器明确反例才是错误。把两者都记零分会偏向更短但冒险的策略。 安全策略也要可观察验证。沙箱配置文件存在不代表限制生效,复现实验先运行越权探针并保存结果。验证器与隐藏答案必须位于 Agent 权限之外,隔离需要通过攻击测试证明。

3.1. 三层框架的因果消融

Interface、Mechanisms 和 Scaling 彼此依赖,仍可通过受控消融估计贡献。固定单 Agent,比较自由文本工具调用与类型接口,测参数错误和越权率;固定接口,逐项加入 checkpoint、验证与程序记忆,测恢复和重复工作;收尾阶段增加 worker,测吞吐与冲突。 如果一开始同时加入类型、测试、多 Agent 和更强模型,终局提升无法归因。三层逐级实验让每个机制有对应预测:类型层降低调用错误,验证层降低错误提交,checkpoint 降低恢复损失,扩展层降低可并行部分墙钟时间。

消融还需负向结果。类型检查可能增加调用修复轮次,严格验证可能提高假阴性,checkpoint 可能产生存储开销,多 Agent 可能因合并冲突变慢。只报告成功指标会把代价藏掉。 交互效应同样重要。类型接口让多 Agent 更容易共享工件,独立验证让程序记忆可安全复用,隔离工作区让并行修改可合并。单项收益小,不代表组合没有价值;但组合结果要通过因子实验,而非叙事推断。

最终应抓住的主线,代码在 Agent 系统中经历了角色变化:先是模型生成的目标产物,随后成为调用工具和表达计划的语言,再进一步成为保存状态、验证结果和协调多 Agent 的基础设施。三层框架正是在描述这条扩张路径。 Interface 层解决模型如何与可执行世界连接,Mechanisms 层解决执行怎样形成可信闭环,Scaling 层解决同一语义怎样在更多任务和 Agent 上保持。后一层不能弥补前一层的模糊:接口不安全,扩展会放大越权;验证不可靠,共享会传播错误。

代码带来的核心性质是可执行、可测试、可版本化和可复用。它没有自动提供正确规格、完整观察或价值判断。把这条边界留下,才能解释为什么最强的 code harness 仍需要环境证据、人工监督和故障恢复。 对长程任务而言,真正重要的是把一次次模型生成变成受约束状态转移:程序声明输入与效果,沙箱限制权限,环境返回证据,验证器决定提交,checkpoint 保存可信进度。模型可以更换,代码可以升级,这条状态语义必须稳定。

3.2. 行为漂移与验收边界

Agent 经常重构或重写程序,并声称「行为不变」。文本 diff 小不代表语义等价,文本完全不同也可能实现同一函数。Harness 需要根据任务选择等价标准。 对纯函数,可以要求观测等价:在输入域 XX 上

∀x∈X,p(x)=q(x).(18)\forall x\in X,\qquad p(x)=q(x). \tag{18}

无限输入域通常无法穷举,只能由证明、属性测试和代表样本近似。对有副作用程序,等价还要比较允许效果、顺序和失败状态;两个程序输出相同文件,一个额外上传数据,显然不等价。 重构验证可组合静态与动态方法。类型与控制流分析发现接口变化,差分测试在相同快照上运行新旧版本,环境 diff 比较副作用,性能基准检查资源回归。任何差异都映射回规格,判断是预期改进还是漂移。

随机和并发程序不能要求逐字输出一致。定义可接受分布、集合或不变量更合理,例如结果顺序可变但元素相同,延迟在阈值内且无重复提交。错误地使用精确快照测试,会制造大量假回归。 Agent 生成的「优化」尤其需要性能—正确性双门。减少验证、缓存旧结果或扩大批量都可能提速,同时改变错误边界。新版本在相同正确性与安全阈值下比较成本,才有资格称优化。

三个反例确定代码的边界,第一个反例是规格错误而程序完美。用户要求按当地法律计算税额,Harness 把错误税率写进规格,程序通过全部测试。代码的可执行性让错误更稳定,只有外部权威来源能纠正规格。 第二个反例是观察错误而控制正确。GUI 识别器把未选中复选框读成已选中,程序依据观察跳过操作并生成成功报告。控制流、类型和日志都正常,根因在感知。多模态 Harness 必须保留观察置信与原始证据。

第三个反例是局部程序正确、全局组合错误。一个 Agent 压缩图片,另一个更新引用,两者分别通过测试;合并后图片哈希变化使缓存清单过期,部署仍引用旧资源。局部验证无法代替组合审计。 还可以加入时间反例。程序昨日对 API 正确,今日服务改变分页默认值,代码继续无报错运行却漏掉数据。版本与运行时不变量检测比「过去成功过」更重要。 这些反例共同说明:code as harness 把行动变得可计算,却仍依赖正确规格、可靠观察、组合验证和持续环境核对。文章若只强调执行确定性,会把真正困难的边界移出视野。

一套代码型 Harness 的可用下限包括:接口参数在执行前验证,权限由外层强制,副作用具备日志和幂等语义,程序、规格与测试绑定版本,失败能从 checkpoint 恢复,验证器位于执行者权限之外,多 Agent 合并后重跑组合检查。反向测试分别传入错误类型、越权探针、重复动作、过期证据、崩溃重放和语义冲突分支,检查这些约束是否真正生效。

通过这些测试只证明 Harness 内核工作,仍需在目标领域验证模型能力与观察覆盖。基础设施验收和任务成功不能互相替代:前者防止系统性污染,后者证明具体工作真正完成。 最终交付应包含运行版本、状态摘要、产物哈希、验证证据、未解决项、已发生补偿和成本。只交一份生成代码,读者无法知道它是否在正确环境里运行过,也无法恢复后续任务。

3.3. 结论怎样被推翻

如果类型接口没有降低参数和对象错误,说明 schema 只增加格式负担;如果外部验证没有降低错误提交,说明验证覆盖不足或执行者仍能污染裁判;如果 checkpoint 没有减少故障后的重做,说明保存对象不完整;如果多 Agent 只增加 token 和冲突,没有缩短关键路径,Scaling 层没有产生有效并行。 同样,程序记忆若在第二次任务中没有降低成本,可能缺少可复用前提;代码生成若比直接工具调用更慢且更易出错,当前任务不适合代码化。这些负结果都应保留,避免「用了代码」本身成为成功叙事。

真正支持三层框架的证据,应在对应层出现:接口错误下降、执行与恢复更可靠、扩展后吞吐提高且可信状态不被破坏。终局成功率只是共同结果,机制指标才能说明改进来自哪里。 因此复现实验最好预先登记每个机制的预测和失败判据。实验结束后按原判据报告,不能看到结果再把没有改善的指标解释成无关。代码 Harness 的优势正是可执行与可检验,它自身也应接受同样严格的检验。


见微改进对照见 OasisMind 2026-08 Harness 波改进清单。