博客
工程 2026年8月24日 6 分钟阅读 OpenAI

Harness Engineering(四):把工程规则变成可执行约束

Agent 不会因为读过一次规范,就在此后始终遵守。可靠的 Harness 会把关键架构边界、质量要求和工程原则变成系统能够自动检查并强制执行的规则。

J

Jonathan

创始人

文档可以告诉 Agent 应该怎样工作,却不能保证它每次都这样工作。

即使把“服务层不能依赖 UI 层”写进 AGENTS.md,Agent 也可能只在大多数时候遵守。面对一个急需修复的问题,它仍有可能选择局部看来最短的路径。代码审查可以发现这次越界;但如果经验只停留在一条审查意见里,下一个 Agent 仍可能犯同样的错误。

OpenAI 在 Harness Engineering 实验中采用了更严格的做法:不逐步规定 Agent 应该怎样实现,而是把真正重要的不变量写成自定义 lint 规则和结构测试。Agent 可以自行选择局部实现,却不能跨越系统明确禁止的架构边界。

这条原则可以概括为:

用文字解释意图,用代码守住边界。

反复出现的审查意见,说明系统缺少约束

团队常常把代码审查当作质量控制的最后一道关口。工程师指出命名不一致、日志缺少字段,或外部数据没有在边界完成解析;作者修正后合并代码。眼前的问题解决了,这条判断却没有成为可复用的能力。

当 Agent 大幅提高代码产出速度后,这种工作方式很快就难以维持。同一种意见可能出现在十个 Pull Request 中,资深工程师不得不反复解释同一条原则。

可以把审查意见分成三类:

  • 一次性判断:只与当前需求、用户体验或特殊取舍有关,保留在人类审查中。
  • 需要解释的原则:适用于一类问题,但难以完全自动判断,写入架构或产品文档。
  • 可以执行的不变量:只要违反就一定不接受,转化成类型、lint、测试或 CI 检查。

如果同一种审查意见反复出现,就不应再只修正当前代码,而要判断这条规则能否进入 Harness,由系统持续执行。

架构只有能够被检查,才真正构成边界

画一张架构图并不难,难的是在日常修改中始终守住依赖方向。

OpenAI 的案例把每个业务领域划分为固定层次,代码只能沿 Types → Config → Repo → Service → Runtime → UI 的方向依赖。认证、连接器、遥测和功能开关等跨领域能力,统一通过明确的 Provider 接口进入,其他依赖关系会被结构测试直接拒绝。这类约束在人类主导的团队中,往往要等到代码库足够庞大才会建立;面对高速产出代码的 Agent,它却从一开始就很重要。

团队还通过自定义 lint 检查结构化日志、schema 和类型的命名方式、文件大小,以及平台特定的可靠性要求。这些都不是对具体实现逐行发号施令,而是在所有改动进入代码库之前,统一守住少数不可破坏的原则。

一个项目可以从几个简单问题开始:

  • 哪些目录可以互相依赖,哪些绝对不允许?
  • 哪些外部输入必须先经过数据结构验证?
  • 哪些模块只能通过公开入口导入?
  • 哪些横切能力必须使用统一接口?
  • 哪些文件大小、命名、日志和可靠性规则属于硬性要求?

其中能够通过静态分析判断的部分,应尽量交给工具执行。如果架构边界只能靠阅读文档得知,代码生成得越快,违规依赖就越容易混入代码库。

错误信息也是 Agent 理解规则的接口

传统 lint 错误往往只报告规则名称,例如“禁止跨层依赖”。人类工程师可以查阅文档或询问同事,再决定如何修改。Agent 也可以搜索,但每一次额外搜索都会消耗时间和上下文空间。

面向 Agent 的检查应该尽量同时回答三个问题:

违反了什么规则
为什么这条规则存在
允许采用哪些修复路径

例如,不只返回:

service-must-not-import-ui

而是返回:

Service 层不能导入 UI 层。
请把共享类型移动到 types/,或通过 Provider 接口注入跨层能力。
参见 docs/architecture/dependency-rules.md。

这样的错误信息会把修复指导直接送入 Agent 当前的上下文,减少它猜测规则意图的空间。检查工具不再只是拦截错误,也能在本次运行中告诉 Agent 应该如何修正。

边界越明确,局部实现越可以自由

把规则写进系统,不等于规定所有实现细节。

如果团队要求 Agent 始终使用某个具体库、某种循环写法和固定的文件结构,很快就会得到一套僵化的脚手架。当模型能力或项目需求发生变化,这些约束反而会阻碍更好的方案。

更耐用的做法是约束结果和边界:

  • 要求外部数据在边界完成解析,但不强制指定验证库。
  • 要求日志结构化并包含 trace ID,但不规定函数内部怎样组织。
  • 要求领域之间只通过公开接口通信,但允许领域内部自由重构。
  • 要求关键行为有验证证据,但不要求每个任务使用完全相同的测试方法。

系统统一守住正确性、可重复性和架构方向;在边界以内,Agent 可以选择合适的实现。约束越清楚,留给 Agent 的自主空间反而越安全。

让工程判断成为系统可以复用的能力

并非所有工程判断都能立刻写成规则。团队可以循序推进:

  1. 人在代码审查中指出问题并解释理由。
  2. 同类问题再次出现时,把原则写进相关文档。
  3. 能够判断的部分转化成 lint、测试或评分器。
  4. 错误信息提供明确修复方向和文档入口。
  5. 定期检查规则是否仍然必要,删除已经过时的脚手架。

这套过程把一次性的专家判断变成可复用能力,同时避免过早把模糊偏好固化为僵硬规则。

Harness Engineering 的目标不是消除人的工程判断,而是让高价值的判断不必由人反复表达。下一篇会继续讨论:当这些检查让 Agent 能够更独立地完成工作后,Pull Request、代码审查和合并策略为什么也必须改变。

本文整理自 OpenAI 的文章 Harness engineering: leveraging Codex in an agent-first world,核心观点来自原文。

Harness Engineering 系列

相关阅读

harness-engineering coding-agents architecture guardrails