从写代码到设计代码生产系统:从 Ryan Lopopolo 的 Harness Engineering 提炼出十二个心智模型
「编辑器之外才是真正的工程。」
这是我读完 Ryan Lopopolo 那篇《Harness engineering》之后,在 flomo 里给自己留的第一句话。
最近反复在读两份材料:一份是 Ryan Lopopolo 在 OpenAI 官方博客上发表的《Harness engineering: leveraging Codex in an agent-first world》(2026 年 2 月 11 日),另一份是 Latent Space 在 4 月 7 日对他做的长访谈。
它们讲的是同一件事:OpenAI 一个小团队用大约五个月,从空仓库开始构建了一个接近百万行规模、约 1500 个 PR 的内部产品——人类没有手写代码,全部由 Codex 完成;他自己估计大约是手写代码所需时间的十分之一。
我对这种“震撼数字”其实兴趣不大。每隔半年都会有人拿出新的数字震撼一次,听多了就麻木。让我反复回看的,是 Ryan 在数字背后展示的那套工作哲学——他几乎是在重新回答一个老问题:在一个机器可以代我执行的时代,作为一个工程师,我到底在做什么?
这篇笔记,是我把他散落在文章和访谈里的观点,提炼成十二个我打算长期使用的心智模型。每一节我都会先抄一段他原话或我的转述,再写下我自己的解读,以及打算怎么用在自己日常的工作和写作里。
模型 1:从 implementation layer 上移到 systems layer
「Humans steer. Agents execute.」
但这句话最容易被误读成“人类不用管了,模型自己写就行”。
读到这句话时,我第一反应不是激动,而是警觉。
因为它太朗朗上口,太容易被滑过去。
Ryan 自己在文章里其实给了限定:团队的主要工作变成了设计环境(designing environments)、表达意图(specifying intent)、构建反馈回路(building feedback loops)。换句话说——
人没有从循环里消失,人只是从打字员的位置,挪到了系统设计者的位置。
我把这件事写成一个心智模型:
工程师的工作层级有两层:implementation layer 和 systems layer。
在 implementation layer 上,你用键盘产出 diff。
在 systems layer 上,你产出的是约束、反馈回路、文档、工具和验收标准。
当 AI 的边际成本下降到接近零,layer 1 的产出价值会被快速稀释;layer 2 的产出价值反而会被放大。
这并不是“人不写代码”那么简单。它在悄悄改变我对自己每天时间的分配方式。
写代码两小时,等于交付一段一次性可执行的逻辑。
写一条让 agent 以后都不会再犯同类错误的规则,等于交付一段可以无限次复用的判断力。
我以前会本能觉得,前者是“在做事”,后者是“在偷懒”。读完 Ryan 之后,我开始怀疑这个判断,是不是已经过时了。
模型 2:把“模型缺陷”重命名为“环境缺陷”
「Don’t say the model can’t do it. Say the environment isn’t yet specified for it.」
(这是我对 Ryan 一段话的浓缩。)
Ryan 提到,他在最初的实验里给自己设了一个看起来挺极端的约束:完全不写任何代码。
为什么要这么做?
他给自己留了一个唯一出口:如果我不能写代码,那唯一能完成工作的办法,就是让 agent 完成工作。
这个约束的真正威力在于——
它封死了“我下次自己来”的退路。
每当 agent 失败,他不能说“算了我自己改”,只能问:
- 是缺什么工具?
- 是缺什么文档?
- 是缺什么测试?
- 是缺什么 trace?
- 是缺什么 sandbox?
- 是缺什么验收标准?
这种问法的不同,会带来完全不同的产出。
“模型不行” → 等下一代模型。
“环境不行” → 你今天就有事可做。
我把它沉淀成一个心智模型:
不要把 AI 的失败归因为模型缺陷。
把它归因为:你还没有把正确的能力暴露给它。
这个 reframing 看起来很微小,但它把“AI 是否能做这件事”,从一个模型能力问题,转化为一个工程师可设计问题。
副作用:你会发现自己开始有耐心了。
当你相信“再等一代模型就好”,你会拖延。当你相信“是我没把环境配好”,你会动手。
模型 3:注意力是稀缺资源,token 不是
「Models are trivially parallelizable.
Team attention isn’t.」
Ryan 的这句话,应该被每一个 AI 时代的团队 leader 抄在墙上。
他在访谈里反复提到,真正稀缺的,不再是写代码或 review 代码的时间,而是团队白天能同步投入的注意力。
这件事的含义远比表面深。
过去的工程流程,几乎全部默认了一个前提:人是瓶颈。所以每个 PR 都要认真看,每个 gate 都要严格。这套流程在人是瓶颈时是合理的;但当 agent 把代码产能拉到人类 review 容量的十倍,这套流程会在一夜之间反过来变成最大的瓶颈。
OpenAI 那篇文章里有一句让我反复琢磨的话:
这种 merge philosophy(短寿命 PR、阻塞 gate 较少、flaky test 后置处理)放在低吞吐环境里会不负责任,但在高吞吐环境里常常是正确取舍。
注意,他不是说“取消 review”。他是说:当人类 review 变成瓶颈,质量控制必须前移、机械化、agent 化。
我把这件事提炼成一个我打算用很久的判断标准:
如果你每天大量时间花在重复说同一件事——“别这么写”、“那个目录不要碰”、“这个字段叫 xxx 不是 yyy”——那不是你勤奋,那是你的 system 不够好。
真正高级的工程师,不是把这一类问题处理快的人;是把这一类问题变成“以后再也不会发生”的人。
把判断只表达一次、然后让它在未来无限次自动生效——
这就是 AI 时代的复利。
模型 4:AGENTS.md 不是手册,而是目录
一份巨型 AGENTS.md = 没有规则。
一份 100 行的 AGENTS.md + 结构化 docs/ + 机械验证 = 一个会自我更新的知识系统。
Ryan 团队最早试过那种“什么都往里塞”的巨型 AGENTS.md,结果如他所说——
上下文被挤占;所有规则都“重要”等于没有规则;文件迅速腐烂;机械验证不可能。
后来他们把 AGENTS.md 砍到 ~100 行,定位降级为目录——一个稳定入口,指向 repo 内更深层的 source of truth。真正的知识被搬到结构化的 docs/ 目录里:design docs、execution plans、product specs、references、quality score、reliability、security……
这事让我想起一句被引用太多的话:“Don’t have a single source of truth, have a single source of navigation.” 我以前不太理解这句话;读完 Ryan,我突然懂了。
他把背后的原则讲得很狠:从 agent 视角看,运行时拿不到的知识就等于不存在。
我把它扩成一个心智模型:
**三层知识可见性:
- 只在你脑子里 → 对世界不存在。
- 写在 Slack / Google Doc / Notion → 对未来 agent 不存在。
- 写在 repo 内可被工具访问、可被 lint 验证、可被 CI 守护 → 对 agent 真实存在。**
这条模型对我个人写作也有触动:
我所有的 flomo 卡片,如果不能被自己未来的搜索找到、不能被自己未来的写作引用,它们只是数字版的“曾经想过”,不是真正的资产。
顺手补一笔:Ryan 团队甚至有个 doc-gardening agent 定期扫“文档说的”和“代码做的”是否一致,发现偏差直接开 PR 修。
这才叫让知识自己保鲜。
模型 5:Agent legibility——代码不只写给同事看,也写给模型看
「The first reader of our code is no longer a new hire. It’s Codex.」
(我对 Ryan 文章里一段意思的浓缩。)
我们这一代工程师从读《Clean Code》开始,被反复教育“代码首先是给人读的”。
现在 Ryan 提了一个新概念:agent legibility——对 agent 的可读性。
不是说代码不再要给人读,而是说——
当一个仓库的多数代码已经由 agent 生成、未来的修改也将由 agent 来做,那么“对 agent 可读”就成了首要约束之一。
Ryan 的态度其实很微妙:代码不一定要符合所有人类的审美偏好,但只要它正确、可维护、对未来 agent runs 可读,就达标。
把这一点想通之后,human taste 没有消失,而是被重新定义了:
从「我喜欢这个实现长什么样」 →
变成 「这个实现是否可验证、可维护、可被 agent 稳定理解和复用」。
我把它沉淀成一条心智模型:
代码品味不再是个人审美问题,而是系统形状问题。
你的“好品味”应该可以被表达成一个 lint,一个 structural test,一份 AGENTS.md 规则;
而不是一句“我们这里不这样写”。
这一条直接改变了我评价“资深工程师”的方式。
以前我会被那种“一眼看出代码不对劲”的人折服。
现在我更佩服那种能把“为什么不对劲”提炼成 agent 也能机械检查的规则的人。
后者才是 agent 时代的核心能力。
模型 6:依赖的内部化,与“边界对 agent 是否透明”
「Sometimes it’s cheaper to let an agent rewrite a small dependency than to live with an opaque upstream library.」
Ryan 这个观点初看很激进——
他说,一个几千行的小依赖,agent 可能可以用一个下午重写一遍,只保留你真正需要的部分;以后做安全审查、修 bug、做适配时,Codex 能直接深入修改,不必等 upstream patch、发布、升级。
我第一反应是:“这不是反 DRY 吗?”
但读到下面这句话时停住了——
他没有否认重写有成本。他承认:内部化依赖意味着你回到零,需要重新建立信心和测试。
也就是说,这不是“造轮子有理”的浪漫宣言,而是一个成本结构变化后的冷静推算。
代码生成成本下降,但验证、可观测、边界、安全的成本仍然很贵。
我把这一切提炼成一条决策心智模型:
当你在评估是否引入一个依赖,问题不再只是“它能不能省我时间”。
还要问:
- 这个依赖对 agent 是不是透明?
- 我的 harness 能不能约束、测试、审查、修复它?
- 如果它出 bug,我的 agent 能不能直接进入它内部修?
如果三个问题里有任何一个是“否”,这个依赖在 agent 时代就不再“免费”。
这条原则也悄悄改变了我对“无聊技术”的看法。
以前我对那些组合性强、API 稳定、训练集中出现得多的“无聊技术”略带不耐。
现在我意识到——正是这种“无聊”,让 agent 更容易建模、更容易预测行为、更不容易出意外。
启示之一:写新项目时,主动选无聊技术,是一个对 agent 友好的决定。
模型 7:Agent 必须能看见应用本身
「If your agent can write code but can’t run the app, see the UI, query the logs, or read the traces — it still needs you to babysit.」
Ryan 团队后来吞代码量上去之后,撞到的下一个瓶颈是 人类 QA 跟不上。
他们的解法不是雇更多 QA,而是让 agent 自己能 QA:
- 应用支持按 git worktree 启动,每个 change 都能对应一个隔离实例。
- 把 Chrome DevTools Protocol 接入 agent runtime,给 Codex 写处理 DOM snapshot、screenshot、navigation 的 skill。
- 每个 worktree 配一个隔离的 observability stack,Codex 自己会用 LogQL、PromQL 查 logs、metrics、traces。
这一切搭起来之后,“确保服务启动低于 800ms”这种 prompt 才真正变得可执行。
让我印象很深的一个细节:他们让 Codex 直接 author Grafana dashboard 的 JSON,并且让 Codex 响应 page——告警发生时它能知道是哪条日志触发的;甚至当某个 outage 没有触发 page,它还可以根据已有 dashboard / metrics / logs 找到观测缺口并修复。
我把它写成一条简单但常被忽略的心智模型:
可观测性的真正受众,正在变化。
过去是给人类 on-call 看图用的;
现在它要被设计成给 agent 闭环修复用的。
这是一个挺颠覆的视角。
过去做 dashboard,目标是“让人一眼看懂”。
未来做 dashboard,目标可能是“让 agent 能稳定地从中读出下一步该做什么”。
这两件事并不总是同一个最优解。
顺手补一笔:Ryan 提到他们工程师有人花了一个下午做了一个漂亮的 trace visualization 工具——
后来发现,直接把 trace tarball 丢给 Codex 让它分析,更符合 agent-first 的路线。
这件事我反复回味。人类 UI 不一定是 AI 时代最高 ROI 的产出形态。
模型 8:约束 invariant,但不要 micromanage implementation
「Encode the invariants. Don’t dictate the implementation.」
这是我读 Ryan 文章时画了三道线的地方。
OpenAI 那篇文章里讲了他们怎么做:把业务 domain 切成固定层级,用 custom lint 和 structural test 强制依赖方向(大致是 Types → Config → Repo → Service → Runtime → UI),横切关注点通过 Provider 这种显式接口进入,其他边一律禁止。
但他们不指定 Codex 必须用某个具体库,只要求它在边界上解析数据形状。
这就是 invariant 与 implementation 的分界:
- invariant——架构边界、依赖方向、数据边界、不变量;这些是机械化的、不可妥协的。
- implementation——具体用什么库、什么结构、什么风格;这些应该尽量留给 agent 自由。
我把它提炼成一条很容易上手的心智模型:
当你要约束 agent 时,先问自己:这条约束是 invariant 还是 taste?
Invariant 写成 lint 或 structural test。
Taste 写成 docs 或 review prompt。
不要把 taste 假装成 invariant,否则你会让 agent 过度受限;也不要把 invariant 留在 docs 里漂着,否则它会被忽略。
Ryan 在访谈里还有一个我特别认同的比喻:他说自己心态像在 group tech lead 一个 500 人的组织——对一个 500 人组织的技术负责人来说,逐行点评每个 PR 是不合适的;更重要的是通过样本观察团队哪里卡住、哪里需要帮助、哪里已经跑得快,然后把注意力转到更高杠杆的位置。
他们的仓库有大约 500 个 NPM packages。一个七人团队搞这种结构,初看像“过度架构”。但 Ryan 反问得很好:如果每个工程师驱动 10 到 50 个 agent,那它已经不是七人团队了。
这条模型可以反过来 self-test 自己的组织:
你团队的人数 × 平均 agent 数 = 你真正需要的协作设计规模。
别再用“我们就几个人”为低组织化辩护——
你已经是大团队了,只是 head count 没涨。
模型 9:Review 的未来——从逐行审查到“可信任的证据包”
「Don’t shoulder-surf the agent. Make it produce a compressed packet of evidence you can trust.」
Ryan 在 review 这件事上的观点是很容易被攻击的——
他在 OpenAI 文章里说:人类可以 review PR,但不总是必须;随时间推移,他们把几乎所有 review 努力推向 agent-to-agent。访谈里他说得更直接:大部分 human review 已经是 post-merge。
但他立刻补了限定:他们做的是 native application,不是连续部署的高可靠基础设施;发布分支与分发前的 smoke test,仍然有人类批准。
所以他真正想说的不是“取消 review”,而是审查对象与信任机制要变。
让我印象最深的是他在访谈里那个具体设想——
他希望 coding agent 在 PR 上附一个视频,展示功能在真实产品里能跑起来。
这相当于把 agent 完整的工作轨迹压缩成一个 reviewer 可读的“信任包”。
我把它沉淀成一条 review 的心智模型:
人类同事提 PR 时,我们不会要求他屏幕录制整个写代码过程;我们只要他给出足够证据,让我们相信代码可以 merge。
Agent 也应当这样被对待。
你不需要 shoulder-surf 它的每一个动作,你需要的是 reviewer 的“证据包”——测试、trace、video walkthrough、log 摘要、review agent 结论、CI 状态、structural check、quality score、tech debt 更新。
这条模型直接改变了我评价“我做了多少 review”的方式。
不是逐行看了几个 PR,而是这周我把多少风险面变得可被自动验证。
前者是消耗品,后者是资产。
模型 10:错误不是“修补”,而是进入垃圾回收系统
「Tech debt is high-interest debt. Garbage collect it continuously, or it explodes.」
Ryan 没有回避一个问题:完全 agent autonomy 会带来新麻烦。
Codex 会复制 repo 里已有的模式,包括不均匀或次优模式,时间一长会 drift。他们最早每周五花 20% 时间清理“AI slop”,但很快发现这种打地鼠不可扩展。
他们后来做了两件事:
第一,把 golden principles 编码进仓库——有观点的机械规则,目标是维持代码对未来 agent runs 的可读性和一致性。
第二,建立 recurring cleanup process——后台 Codex 任务定期扫偏差、更新 quality score、开 targeted refactoring PR;很多可以一分钟内 review 并 automerge。
Ryan 把这事叫 garbage collection。
我特别喜欢这个比喻。因为它把“AI slop”从一个道德议题变成了一个工程对象。
他不否认 slop 存在。
他只是说——如果 agent 会复制坏模式,那就要设计持续回收坏模式的系统。
所谓 human taste,不是每次人类出来骂一句“这个写得丑”,而是把 taste 捕捉成原则、lint、review prompt、quality score 和后台清理任务。
我提炼出的心智模型:
任何长期运行的系统都会产生熵。
你不能靠“人类发现 → 人类修补”来对抗熵,因为这条路径的成本会随系统规模线性增长。
你必须有一个持续运行的 garbage collector——
在代码里、在文档里、在依赖关系里、在 review queue 里。
这个模型也适用于个人知识系统。
flomo 卡片越多,搜索的信噪比越差。
没有 garbage collection 的笔记系统,最后变成一个“装着自己曾经想过的东西的坟墓”,而不是一个能产出新洞察的工具。
模型 11:从“管理 session”到“让 issue tracker 成为 agent 的 control plane”
Symphony 不是工具,是一种 reframing:
不要监督 agent,让 agent 从任务系统里拉活。
Symphony 是 Ryan 后续工作里我最想单独拿出来讲的一项。
OpenAI 在 2026 年 4 月 27 日发了 Symphony 文章,团队在“无人手写代码”的工作流里继续撞墙——下一个瓶颈是 context switching:每个工程师每天能稳定推 5 到 10 个 PR,但代价是不断在 tmux pane 之间切换;同时管理 3 到 5 个 Codex session 就开始痛苦。
Symphony 的核心设计简单又狠:让 Linear 这类项目管理看板成为 coding agent 的 control plane——每个 open task 对应一个 agent workspace,agents 持续运行,人类 review 结果。
这一步的关键意义在于——
它把工作单位从 Codex session / PR,提升到了 ticket / deliverable。
OpenAI 文章给了一个数字:有些团队上 Symphony 三周后 landed PRs 增加了 500%。
但更深层的变化是——每个 change 的感知成本下降了。人不再亲自驱动实现,所以 speculative task 变得便宜:试一个想法、探索一个 refactor、测试一个假设,不行就丢掉。
我把它提炼成一条心智模型:
当执行成本接近零,你最该投资的,是降低“想要尝试”的心理摩擦。
试错越便宜,洞察越多。
这是一切创造性工作的底层规律。
Ryan 在访谈里特别提了一个 Symphony 的 rework state 设计,我觉得非常符合 agent-first 思维:
- 如果 PR 不可 merge,就把 worktree 和 PR 整个丢掉,从头再来。
- 然后追问“它为什么是垃圾”——先修 prompt、skill 或 guardrail,再把 ticket 重新推入 progress。
这背后是一个非常不一样的成本观:
当代码便宜时,保留错误路径不一定值得。有时丢弃 + 补护栏 + 重跑,比 patch 更干净。
个人启示:
我以前对自己写过的烂草稿会舍不得删——觉得“反正花了时间”。
现在我开始接受:“写得不行,那就丢掉,并且去问‘为什么我能写出这种东西’。”
修流程比修产物更值钱。
模型 12:把 agent 放进一个有目标、有上下文、有工具的“世界”里
「Don’t put agents in a box. Give them context and tools.」
这是 Ryan 在访谈里和主持人对完话之后追加的一句关键限定。
这条模型综合了前面所有模型,是我打算放在桌面上的那条。
Ryan 自己经历了一个明显的演进:早期他们倾向于把 agent 放在预定义 scaffold 或状态机里;但 reasoning model 一旦变强,过度僵硬的 scaffold 反而会限制它。
他们后来“反转”了系统——
不是先搭一个环境再把 coding agent spawn 进去;而是让 Codex 本身成为入口,再通过 skill 和 script 给 Codex 启动 stack、设置环境变量、查询 observability 数据的能力。
但这不意味着没有边界。
边界在哪里?
边界变成了整个 harness:权限、工具、repo 结构、workflow policy、observability、CI、lint、skill、sandbox、human escalation——共同构成一个可操作的环境。
我把它写成最后一条心智模型:
**失败的 agent workflow 通常掉在两个极端:
一种是把 agent 关进过窄的工具箱,期待它 magically 完成复杂任务;
另一种是给它完全开放的环境,但没有日志、测试、边界和 policy。Ryan 的中间道路是清楚的:
不要 micromanage 每一步,但要严肃设计 agent 可见的世界。
给目标,也给观测;给自由,也给 invariant;给工具,也给反馈;给上下文,也给可机械执行的验收标准。**
我从这十二个模型里看见的一条主线
把这十二个模型放在一起看,能看见一条隐藏的主线。
它本质上是关于“判断力的可复用性”的。
工程师的判断一直存在。一个好的工程师,他的脑子里装着大量隐性知识:哪些写法看起来对但其实不行;什么场景下要小心;某个边界什么时候必须显式;某种命名约定背后的取舍;某个性能假设在生产中如何破灭。
过去这些判断都困在脑子里。
它们靠什么传承?
靠 review、靠口口相传、靠“被骂的疼痛感”、靠新人在事故里学到的教训。
这种传承是一次性的,而且高度依赖人际接触。
Ryan 这套 harness engineering 在做的事,就是把这种判断从“一次性”变成“可复用”。
- 把“我喜欢这种结构” → 变成 lint。
- 把“我们不要再写这种代码” → 变成 structural test。
- 把“这种依赖太重” → 变成 quality score 规则。
- 把“上线前一定要看这条 trace” → 变成 verification skill。
- 把“改这块前要先了解上下文” → 变成 docs 索引和 AGENTS.md 入口。
- 把“这种 PR 必须配视频” → 变成 review packet 模板。
每一条规则都是把一个工程师的判断提炼成系统的一段刻度。
判断被提炼之后,agent 就能在所有未来的相似场景中复用它。
复利就在这里发生。
这件事最深的含义是——
“工程师”这个身份的核心价值,从“执行判断”,转向了“沉淀判断”。
执行一次的判断只服务这一次。
被沉淀进系统的判断,会服务所有未来 agent runs。
这两种工作的长期杠杆率差异是指数级的。
不是 2 倍、5 倍。
是 10 倍、100 倍。
写在最后:哪些是我打算这周就开始做的
每次读完这种“震撼级”的工程材料,我都会逼自己问一个问题——
接下来一周,我具体能做点什么?
不能落到一周内行动的“启发”,对我来说和没读过没差。
我列了一个最小行动清单,给自己用,也分享给同样在用 Cursor / Codex / Claude Code 的你:
- 本周内把现有的 AGENTS.md 砍到 100 行以内,剩下的拆到 docs/ 下结构化文件。
- 每次我跟 AI 重复说同一件事超过两次——立刻停下,把它写成一条规则。
- 本周提交的所有 PR——尝试附上一段证据(测试报告 / 截图 / 日志摘要),不要让自己或同事靠“看代码 + 信任”来 merge。
- 挑一个我目前手动 babysit 的任务(每天都要跑一遍那种)——花两小时把它写成 skill / script / cron job,让 agent 自己拉活。
- 每周末花 30 分钟做一次“知识 garbage collection”——把我和 agent 这一周的来回,重新提炼成 1 条新规则、1 篇 doc 修订、或 1 个 skill 改进。
- 用一句话提醒自己:
“我作为工程师的核心产出,是判断的可复用性,不是代码的行数。”
一个尾巴:关于“工具背后的人”
我喜欢 Ryan 这套观点的最后一个原因,是它没有走向“人类不重要”的悲观叙事。
他承认 hard and new 的问题仍然要人类驱动;他承认完全 agent-generated 系统的长期一致性还是未解;他承认这套打法依赖于他们仓库的具体结构和资源条件,不应该被假设能直接泛化到所有团队。
他真正在做的,是一件挺谦逊的事——
他在重新设计“工程师”这个职业,以便让人类的判断、品味、经验、风险感知,能够在 AI 极大放大执行力的时代,继续发挥作用,甚至发挥得更好。
这一点其实很重要。
我们这一代知识工作者,最大的恐慌不是工具变强,而是不知道工具变强之后,“我”还能站在哪里。
Ryan 给出了一个我愿意相信的回答——
你站在系统设计者的位置上。
你站在判断的沉淀者的位置上。
你站在让 agent 不需要 babysit 的那个人的位置上。
这听起来抽象。
但我把它翻成具体的、给自己的一条提醒:
少敲键盘,多沉淀;
少救火,多设计护栏;
少在脑子里存隐性经验,多把它们写进 repo;
少要求自己跟上模型的速度,多让 agent 跟得上自己的标准。
如果让我用一句话总结这十二个心智模型——
AI 时代的工程师,不再是写最多代码的人,而是把自己的判断变成系统的人。
这句话我打算抄在 flomo 顶部,每天早上看一遍。