1. 为什么我要把 Harness Engineering 蒸馏成四个 Skill
OpenAI 在 2 月发了一篇 Harness Engineering 的文章,讲他们怎么用 Codex 搭一个让 Agent 持续工作的执行环境。核心数据很扎眼:3 个工程师、5 个月、100 万行代码、零手写、每人每天 3.5 个 PR。我第一遍读完的感受不是"好厉害",而是"这不就是我一直想做的那个东西吗"。
我让 Agent 跑长任务一直有几个固定痛点:Context 重置之后不知道上一轮干了什么;跑到一半觉得"差不多了"就自己停;遇到模糊的地方卡住等我确认。OpenAI 那篇文章把这些问题讲得很清楚,也给了他们的解法。但他们的工具链是 Codex 云端加自研基础设施,我是本地环境,直接照搬不现实。
所以真正的问题变成了:怎么把文章里的方法论蒸馏成我能用的东西。我读技术文章习惯把内容分三类——直接可用的机制、思路可借鉴但实现要改的、他们能做但我现在不考虑的。这篇文章就是这套蒸馏过程的完整复盘,包括四个 Skill 的职责划分、Codex auth.json 改到 TaoToken 统一通道的配置片段,以及一次 25 小时 Agent 长跑的日志验证动作。
如果你也在本地跑 Codex 或 Claude Code 这类编码 Agent,想让它们从"跑十分钟就停"变成"能连续跑一整天",这篇的配置和排障步骤可以直接跟做。适合有后端基础、已经在用 Agent 写代码、但被长任务稳定性卡住的人。
2. 蒸馏 Harness Engineering 的四个 Skill 与职责划分
蒸馏完之后我发现,要解决的问题自然分成了几层:让 Agent 能持续跑、跑断了能恢复,这是执行引擎问题;让业务流测试有证据、判定来自不变式而不是脚本退出码,这是验证问题;让架构规则机械化执行、不依赖 Agent 自觉,这是约束问题;让 Prompt 写完 Agent 就不会停,这是运行策略问题。对应下来就是四个 Skill。
2.1 四个 Skill 的职责划分表
| Skill 名称 | 解决的问题 | 核心机制 | 关键产物 |
|---|---|---|---|
| harness | 持久执行与状态恢复 | 进度文件即上下文 | harness-tasks.json、harness-progress.txt、git log |
| closed-loop-testing | 业务流验证有证据 | 判定来自业务不变式 | verdict.json、请求响应记录、数据库快照 |
| architecture-guardrails | 架构规则机械执行 | 结构测试 + ratchet 策略 | allowlist、CI 结构测试 |
| harness-marathon | 运行策略不中断 | 三定律 + Doom Loop 检测 | 依赖清单、编辑次数告警 |
harness 是执行引擎。OpenAI 把 execution plans 和 decision logs 存在仓库里,Context 重置后 Agent 读这些文件就能恢复状态。我照搬了这个思路,用 harness-tasks.json 存任务拆解、harness-progress.txt 存操作日志,再加一个 git log,三件事一起读,10 秒内恢复会话。AGENTS.md 当目录不当百科全书,控制在 100 行左右,真正的知识放 docs/ 里。他们试过"一个大 AGENTS.md"失败了,原因我都踩过:文件太大挤占有效 Context,规则写太多等于没规则,一旦过期 Agent 没法分辨哪些还是真的。
closed-loop-testing 是验证层。OpenAI 的可观测性方案是每个 git worktree 配独立的 Victoria Logs + Metrics + Traces,Agent 用 LogQL/PromQL/TraceQL 查。思路很好,但我的场景偏业务流测试不是性能调优,所以换成了"证据包"概念:每个业务流测试完必须产出 verdict.json、请求响应记录、数据库快照、过滤好的日志,判定来自业务不变式,不来自"脚本跑完了"。业务流测试分三阶段:V1 测内部可控路径,V2 加入外部回调,V3 产出完整证据包。
architecture-guardrails 是约束层。OpenAI 用自定义 linter 加结构测试强制执行分层约束,lint 错误信息本身包含修复指引。这个设计很聪明——Agent 违规时报错,报错信息直接告诉它怎么改,不需要再去找文档。我把它编码成结构测试在 CI 里跑,加上 ratchet 策略:遗留违规加到 allowlist,新代码必须通过,慢慢蚕食存量问题。
harness-marathon 是运行策略层,OpenAI 文章里没有对应东西,是我加的。它本质是一套分析框架:Agent 停下来只有三个原因——工作耗尽了、遇到不确定的地方卡住了、Context 退化了。把这三个原因逐个干掉,Agent 就能跑很久。三定律里 Law 2"Zero decision points"最容易被忽略,提前把所有外部依赖写进 Prompt,说起来简单,但每次 Agent 中途停了,回头查基本都是漏写了某个依赖。
3. 把 Codex auth.json 改到 TaoToken 统一通道
四个 Skill 要跑起来,Agent 得先能稳定调用模型。我这边 Codex 负责开发写 PR,Claude Code 负责 review,两边如果各用各的 Key,长跑时切换和额度管理都很乱。所以我把 Codex 的 auth.json 改到 TaoToken 统一通道,一个 Key 走所有模型调用。
TaoToken 在这里的角色是统一 API 通道,官网是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。它不替代编辑器,也不替代 Codex 本身,只是把模型调用的 Base URL 和 Key 收敛到一处,方便长跑时统一管理。
3.1 Codex auth.json 配置片段
Codex 的 auth.json 一般在用户目录下的 .codex 文件夹里。改之前先备份一份,然后按下面结构写。三件套是 Base URL、Key、Model ID,缺一不可。
{ "OPENAI_API_KEY": "sk-你的TaoToken密钥", "OPENAI_BASE_URL": "https://taotoken.net/api", "model": "gpt-5-codex", "provider": { "name": "taotoken", "baseURL": "https://taotoken.net/api", "apiKey": "sk-你的TaoToken密钥" } }如果你用的是 Codex CLI 的 config.toml,对应写法是这样:
[model_providers.taotoken] name = "taotoken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" [profiles.default] model = "gpt-5-codex" model_provider = "taotoken"Key 的获取在控制台的 API Keys 页面,地址是 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。生成后复制到上面配置里,注意不要提交到 git 仓库,用环境变量或本地文件隔离。
3.2 Claude Code 侧的 settings 片段
Claude Code 做 review,走的是 Anthropic 兼容通道。settings.json 里这样配:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的TaoToken密钥", "ANTHROPIC_MODEL": "claude-sonnet-4-5" } }这样 Codex 和 Claude Code 共用同一个 Key 和 Base URL,长跑时额度、日志、切换都在一处。如果你用 CC Switch 管理多套配置,把上面这段作为一个 profile 存进去,切换时不用手改文件。Cline MCP 的场景同理,Base URL 填 https://taotoken.net/api ,Key 填同一个,Model ID 按你实际用的填。
4. 验证请求与 25 小时长跑的日志动作
配置写完不能直接开跑,先做一次最小验证请求,确认通道通了再上长任务。
4.1 最小验证请求
用 curl 打一次模型对话接口,确认返回正常:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的TaoToken密钥" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-5-codex", "messages": [{"role": "user", "content": "reply with ok"}] }'返回里能看到 choices 数组和正常内容,说明 Base URL、Key、Model ID 三件套都对。如果这一步就报错,先别往下走,去第 5 节对照排查。想先在网页里确认模型可用,可以打开模型对话页面 https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 手动发一条消息,排除是本地配置问题还是通道问题。
4.2 25 小时长跑的日志验证动作
那次 25 小时的长跑是一个比较大的 Go 服务重构任务,任务拆了 40 多个。跑之前我在 harness-tasks.json 里把每个子任务和依赖写清楚,harness-progress.txt 初始化为空,然后启动。长跑期间我做了几个固定的日志验证动作。
第一个动作是每 2 小时检查一次 harness-progress.txt 的最后 20 行,确认 Agent 在推进而不是绕圈。如果发现同一个文件被反复编辑,就去看 Doom Loop 计数。我在 harness 里加了机制:同一个文件编辑超过 6 次报警,超过 12 次强提醒。实测触发频率比我预想的高,每次触发基本就是 Agent 在绕圈,当前思路走不通,需要人工介入换个方向。
第二个动作是检查 git log 的提交节奏。正常推进时提交是均匀的,如果连续两小时没有新提交,要么是卡在某个依赖上,要么是 Context 退化。这时候去看 harness-progress.txt 里最后一条记录,通常能定位到卡点。
第三个动作是验证 closed-loop-testing 的证据包。每个业务流测试完,检查 verdict.json 是否存在、判定字段是否来自业务不变式。V1 阶段成功率接近 100%,V2 如果外部服务挂了可以切 replay 模式,不影响整体进度。以前我直接跑 E2E,经常因为外部服务不稳定全挂得重来,分阶段之后稳定很多。
跑完 25 小时,任务一次通过率大概 80%。剩下 20% 里,一半是需要人介入的真实设计分歧,一半是 Prompt 写得不够清楚导致的理解偏差。前者本来就该人来处理,后者可以继续优化 Prompt。
5. 本篇常见错误排查
长跑接入过程中我踩过的坑基本集中在这几类报错,对照着查能省不少时间。
401 报错最常见。表现是请求返回 Unauthorized,原因通常是 Key 没填对、Key 过期、或者 auth.json 里 Key 和 Base URL 不匹配。先确认 Key 是从控制台 API Keys 页面复制的完整字符串,没有多余空格;再确认 OPENAI_BASE_URL 和 provider.baseURL 都指向 https://taotoken.net/api ,没有多写或少写路径。如果 Codex 和 Claude Code 共用 Key,检查两边是不是都改了,只改一边会出现一边通一边 401。
local proxy failed 报错。这个通常是本地网络或代理配置干扰了请求。检查环境变量里有没有残留的 HTTP_PROXY、HTTPS_PROXY 指向本地端口,有的话先清掉再试。另外确认 auth.json 里没有写死某个本地代理地址。这个报错和通道本身无关,是本地环境问题。
reading choices 报错。表现是请求发出去了但解析响应时读不到 choices 字段。原因一般是 Model ID 写错了,或者请求体格式不对。确认 model 字段填的是通道支持的模型名,请求体是标准的 messages 数组结构。如果用的是 config.toml,检查 model 和 model_provider 是否对应。
OAuth 相关报错。Codex 有些版本会走 OAuth 登录流程,如果你已经改成 Key 认证,残留的 OAuth 配置会冲突。检查 .codex 目录下有没有旧的凭据文件,清掉后重新用 auth.json 的 Key 方式启动。CC Switch 用户注意 profile 切换后要重启 Codex 进程,否则读的还是旧配置。
还有一个不报错但很坑的情况:配置全对,但 Agent 跑一会儿就停。这基本不是通道问题,是 harness-marathon 的 Law 2 没做到位,Prompt 里漏写了某个外部依赖。回头查 harness-progress.txt 最后一条记录,通常能看到 Agent 停在等某个路径或某个 Key 上。把依赖补进 Prompt 再跑。
6. 长期编码与 Agent 长跑的接入建议
如果你打算把这套东西长期跑起来,几个实际建议。Codex 负责开发写 PR、Claude Code 负责 review 的组合比我预期好,两个 Agent 训练方式不同,review 盲区不重叠,PR 质量明显上来。这跟 OpenAI 说的 agent-to-agent review 是同一个思路,只是用两个不同模型实现。
长期跑编码任务和 Agent 的话,Coding Plan 比按量调用更划算,地址是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,配置细节和模型列表都在里面。Claude Code 的接入说明单独有一页 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,走 Anthropic 兼容通道的话照着配就行。
蒸馏一篇技术文章提炼成可用工具,核心是问三个问题:这个做法解决的是什么问题,不是他们做了什么,而是为什么要这么做;我的场景里这个问题存在吗;有没有更简单的实现能解决同一个问题。不是所有机制都值得完整实现,OpenAI 的 doc-gardening Agent 是个后台定期扫描修复文档的 Agent,我现在的场景里结构测试加人工偶尔检查就够了,没必要搭那个 Agent,等不够用了再加。