1. 为什么 Harness 自进化值得你亲手跑一遍
Terminal-Bench-2.0 上的 Self-Harness 结果最近在 Agent 圈子里传得挺开:底层模型不动、工具集不动、评测协议不动,只改模型外面那层 Harness,Qwen3.5-35B-A3B 拿到 104% 的 held-out 提升,MiniMax M2.5 和 GLM-5 分别提升 28% 和 24%。这个数字真正有意思的地方不是“涨了多少”,而是它证明了一件事——Agent 的表现瓶颈很多时候不在模型权重里,而在那套决定它怎么调工具、什么时候停、失败后怎么恢复的运行装置里。
Harness 是什么?你可以把它理解成包在模型外面的一层“驾驶舱”:系统提示词、工具调用规则、验证器、运行时控制策略、轻量 middleware 都算。多轮工具任务里,模型只负责“想”,Harness 负责“怎么执行、执行到哪一步算完、出错怎么办”。过去这套东西靠工程师读轨迹、找失败模式、手改提示词,再反复跑 benchmark。模型一多、任务一杂,人工调参就顶不住了。
Self-Harness 的思路是把这三步压成一个闭环:Weakness Mining 从失败轨迹里挖可复用的失败机制,Harness Proposal 让同一个模型切换成 proposer 提出有边界的 edit,Proposal Validation 用 held-in / held-out 回归测试决定采不采纳。接受规则很保守——至少一个 split 提升、另一个不退化,才进入下一代。
这篇要交付的不是论文复述,而是一套你能在自己机器上跑起来的接入骨架:用 TaoToken 统一 Key 打通 Harness 评测流程,给出可复制的config.toml和settings.json,再走一遍 benchmark 复跑与结果校验。适合已经在做 Agent 评测、想验证“换 Harness 不换模型”到底有没有用的同学。
2. TaoToken 前置:统一 Key 与 API 通道怎么接
Self-Harness 的评测流程里,模型会被反复调用:挖弱点时要跑一批任务、提 proposal 时要让模型生成 edit、验证时要重跑候选 Harness。如果每个模型后端都单独配一套 Key 和 endpoint,Harness 代码里就会散落一堆 provider 分支,回归测试一跑起来光切换配置就够乱的。
TaoToken 在这里的角色是统一入口:一个 Key、一套 OpenAI 兼容的 API 通道,把不同模型后端的调用收敛到同一个 base_url 上。这样 Harness 的 proposer、executor、validator 都走同一套请求逻辑,切换模型只改model字段,不用动调用代码。
先拿 Key。打开控制台创建 API Key:
https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite创建完在 API Keys 页面复制,注意它只完整显示一次:
https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite接入文档在这里,OpenAI 兼容的调用方式、参数说明、错误码都能查到:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewriteAPI 的 base_url 是:
https://taotoken.net/api注意这个地址不加 UTM 参数,直接作为base_url写进配置。Key 建议放环境变量,别硬编码进仓库:
export TAOTOKEN_API_KEY="sk-你的key"如果你只是想先确认模型通道通不通,可以先用模型对话页面发一条消息验证:
https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite长期跑编码类 Agent 或需要反复调 Harness 的场景,Coding Plan 会更省心,额度模型和调用方式在页面里有说明:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite3. 可复制配置:config.toml 与 settings.json 骨架
Self-Harness 的评测配置分两层:一层是 Harness 运行参数(config.toml),一层是模型与工具环境设置(settings.json)。下面这套骨架可以直接改字段用。
3.1 config.toml:Harness 运行与评测参数
# config.toml — Self-Harness 评测运行配置 [harness] name = "self-harness-terminal-bench" version = "0.1.0" # 可编辑表面:只允许改这些,防止 proposer 推倒整个控制架构 editable_surfaces = [ "system_prompt", "tool_retry_policy", "artifact_check", "shell_state_guard", "stop_condition", ] [harness.loop] max_turns = 40 tool_timeout_sec = 120 # 连续相同命令重试上限,超过则触发 artifact-focused 提醒 max_identical_retry = 2 # 长时间探索未产出时,强制转向实现 explore_budget_turns = 12 [harness.validation] # 回归测试门控:至少一个 split 提升,另一个不退化 require_held_in_improve = true require_held_out_no_regress = true min_improve_ratio = 0.02 [benchmark] name = "terminal-bench-2.0" split_held_in = "held_in" split_held_out = "held_out" task_timeout_sec = 600 container_image = "tb2-base:latest" result_dir = "./runs/self-harness" [model] provider = "taotoken" base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" # 固定模型后端,Self-Harness 不改这里 model = "qwen3.5-35b-a3b" temperature = 0.2 max_tokens = 4096 [proposer] # 同一个模型切换成 proposer 角色 model = "qwen3.5-35b-a3b" temperature = 0.7 max_edits_per_round = 3 require_risk_note = true几个字段值得单独说。editable_surfaces是 Self-Harness 的关键约束——proposal 只能落在预先声明的表面上,不能把整个 Agent 控制架构重写。max_identical_retry和explore_budget_turns对应论文里 Qwen3.5 暴露的“工具失败后陷入循环”和“探索太久不进入实现”两类弱点。require_held_out_no_regress是接受规则的核心,没有它,自动改 Harness 就退化成凭感觉拍板。
3.2 settings.json:模型与工具环境
{ "runtime": { "shell": "/bin/bash", "workdir": "/workspace", "env_persist": true, "precheck_dependencies": true }, "tools": { "enabled": ["shell", "file_read", "file_write", "file_edit"], "retry_policy": { "on_tool_error": "recover_artifact", "avoid_identical_command": true, "max_retries": 3 } }, "artifact": { "required_outputs": ["answer.json", "result.txt"], "create_initial_artifact": true, "verify_before_stop": true }, "shell_state": { "confirm_env_persist": true, "check_path_after_install": true }, "model_client": { "base_url": "https://taotoken.net/api", "api_key_env": "TAOTOKEN_API_KEY", "timeout_sec": 180, "max_retries": 2 } }artifact.required_outputs对应 MiniMax M2.5 那类“找到线索却不交付”的失败——Harness 会鼓励 Agent 更早创建初始产物。shell_state.confirm_env_persist对应 GLM-5 暴露的 shell 会话状态问题,改完环境变量或路径后要确认能跨命令持续可用。
3.3 环境变量与启动
export TAOTOKEN_API_KEY="sk-你的key" export HARNESS_CONFIG="./config.toml" export HARNESS_SETTINGS="./settings.json" python -m self_harness.run \ --config "$HARNESS_CONFIG" \ --settings "$HARNESS_SETTINGS" \ --benchmark terminal-bench-2.0 \ --rounds 5--rounds 5表示跑 5 轮自进化迭代,每轮包含挖弱点、提 proposal、回归验证三个阶段。
4. 验证请求:从单次调用到 benchmark 复跑
配置写完别急着跑全量 benchmark,先做三层验证,一层层往上加。
4.1 第一层:确认 API 通道通
用 curl 发一条最小请求,确认 Key 和 base_url 没问题:
curl -s https://taotoken.net/api/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen3.5-35b-a3b", "messages": [{"role": "user", "content": "reply with ok"}], "max_tokens": 16 }'返回里有choices[0].message.content就说明通道通了。如果返回 401,检查 Key 是否复制完整;返回 404,检查 base_url 是不是写成了带路径的形式。
4.2 第二层:单任务 Harness 跑通
先跑一个 Terminal-Bench-2.0 任务,确认 Harness 能驱动模型完成多轮工具调用:
python -m self_harness.run \ --config "$HARNESS_CONFIG" \ --settings "$HARNESS_SETTINGS" \ --task tb2-file-manage-001 \ --rounds 1 \ --dry-run-proposal--dry-run-proposal表示只跑执行和弱点挖掘,不实际应用 proposal。这一步看的是轨迹里有没有完整的工具调用记录、失败样本有没有被正确归类。
4.3 第三层:benchmark 复跑与结果校验
确认单任务没问题后,跑 held-in 和 held-out 两个 split:
python -m self_harness.run \ --config "$HARNESS_CONFIG" \ --settings "$HARNESS_SETTINGS" \ --benchmark terminal-bench-2.0 \ --split held_in \ --rounds 5 \ --output ./runs/held_in python -m self_harness.run \ --config "$HARNESS_CONFIG" \ --settings "$HARNESS_SETTINGS" \ --benchmark terminal-bench-2.0 \ --split held_out \ --rounds 5 \ --output ./runs/held_out跑完对比两轮结果,校验逻辑就是接受规则本身:
import json def load_metrics(path): with open(path) as f: return json.load(f) held_in = load_metrics("./runs/held_in/metrics.json") held_out = load_metrics("./runs/held_out/metrics.json") improve = held_out["score"] - held_out["baseline_score"] regress = held_in["score"] - held_in["baseline_score"] if improve >= 0.02 and regress >= 0: print(f"accept: held_out +{improve:.2%}, held_in {regress:+.2%}") else: print(f"reject: held_out {improve:+.2%}, held_in {regress:+.2%}")成功的结果长这样:held_out 提升明显、held_in 不退化,每一代 Harness 的 edit 都有记录、可复现、可回退。如果 held_out 涨了但 held_in 掉了,说明 proposal 过拟合到 held-out 的失败模式,应该拒绝这一代。
5. 本篇常见错排查
5.1 401 / 403:Key 没生效
最常见的原因是环境变量没导出到当前 shell,或者 Key 复制时带了空格。先确认:
echo "${TAOTOKEN_API_KEY:0:8}"只打印前 8 位,确认非空且格式对。如果用的是.env文件,注意 Harness 进程有没有加载它。
5.2 模型调用超时:max_tokens 或 timeout 设太小
多轮工具任务里单次响应可能比较长,max_tokens设 512 很容易截断,导致 Harness 解析不到工具调用。把max_tokens提到 4096,timeout_sec提到 180。如果还是超时,看是不是任务本身在容器里卡住了,跟模型通道无关。
5.3 proposal 被全部拒绝:editable_surfaces 太窄或太宽
如果连续几轮 proposal 都被回归测试拒掉,先看editable_surfaces。太窄(比如只允许改system_prompt)会导致 proposal 修不到真正的失败机制;太宽(允许改整个控制架构)会导致改动太大、回归测试必然退化。建议从 3 到 5 个表面起步,对应论文里那几类弱点:产物检查、重试策略、shell 状态、停止条件。
5.4 held_out 涨、held_in 跌:过拟合信号
这是最需要警惕的情况。说明 proposer 在针对 held-out 的失败样本做局部修补,而不是挖可复用的失败机制。处理方式是收紧min_improve_ratio,或者在 Weakness Mining 阶段要求失败机制至少覆盖 N 个任务才允许进入 proposal。
5.5 容器内命令找不到:依赖预检查没开
Qwen3.5 那类“工具失败后陷入循环”很多时候根因是依赖没装。确认settings.json里precheck_dependencies为true,并且 Harness 在首次工具调用前会检查shell、file_read等工具是否可用。
5.6 结果目录里没有 metrics.json
检查result_dir和--output是否指向同一路径。有些运行模式下 metrics 写在runs/<split>/<round>/metrics.json,需要按轮次聚合。跑完先find ./runs -name "metrics.json"确认文件位置。
6. 把统一 Key 接进你的 Harness 评测流程
Self-Harness 给出的边界其实很清楚:改什么(预先声明的可编辑表面)、怎么改(基于失败机制的 proposal)、怎么验(held-in / held-out 回归门控)、什么时候拒绝(任一 split 退化就拒)。这套闭环要跑起来,模型调用必须稳定且可切换,否则光在 provider 配置上折腾就耗掉大半精力。
用 TaoToken 统一 Key 的价值就在这里:executor、proposer、validator 走同一个base_url,切换模型后端只改model字段,回归测试的复现性也更好保证。先把单任务跑通,再上 held-in / held-out 双 split,最后按接受规则校验——这套流程跑顺了,你就能自己验证“不换模型、只改 Harness”在你的任务集上到底能涨多少。
接入相关的 Key 和文档入口:
API Keys: https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 接入文档: https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite需要长期跑编码类 Agent 或反复迭代 Harness 的话,Coding Plan 的额度模型更适合这种高频调用场景:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite如果你更想先确认某个模型在 Terminal-Bench-2.0 风格任务上的表现,可以直接在模型对话里发一条多轮工具指令试试:
https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite我自己的做法是:先用--dry-run-proposal跑两轮,确认弱点挖掘能把失败样本聚成可复用的机制,再放开 proposal 和回归门控。这样即使某一轮 proposal 被拒,你也能从轨迹里看到它想改什么、为什么没通过,比直接看最终分数有用得多。