Table of contents
Open Table of contents
问题
八月我写过,自我进化是个数据问题。现在数据有了:几个月的生产轨迹,来自一个整天待在 Gmail、浏览器和各种长尾 connector 里的 agent。更接近 Manus,不太像 coding agent。
计划看起来很明显。挖这些轨迹,让 agent 重写自己的 harness,谁分高就上谁。
然后我试着写清楚,对一个会发邮件的 agent 来说,什么叫「分更高」。没写出几行。
于是去找。先看 coding agent,那里的「更好」有退出码替你定义。再看 Harness²,这个月的一篇论文,讲没有标准答案时怎么改进 harness。
一开始我问的是,agent 该怎么改进自己。最后变成了另一个问题:怎么知道它真的变好了。
大家都在过拟合
先说不太舒服的部分。自动改进 harness 这件事,只要有效,几乎都是在过拟合。拟合领域,很多时候直接拟合任务。
一个能通用地改进自己的 harness,仍然是个开放问题。我猜那些实验室也还在养着几十个工程师,日夜打磨自己的 harness。一部分自动化,很多还是手工。
有效的设计都承认这一点。Harness² 在测试时针对每个任务单独优化 harness。跨领域共用一个 harness,就会引入负迁移。而且进化的对象也该随任务类型变:做研究和办日常杂事,碰到的根本不是同一组模块。
所以过拟合不是 bug,是需求。唯一要设计的是,你要拟合什么。
对个人 agent 来说,这句话把整个项目换了个角度。个性化,就是被允许的过拟合。拟合任务,拟合团队,拟合这个人。
有意地过拟合,凭证据接受。
后半句是这篇剩下的内容。
什么算一个任务
Benchmark 的单位很干净:一个任务,一个 session,一个环境。生产里没有这些边界。一个 session 从「我今天有什么日程」开始,三个小时后还没结束,已经钻进某个供应商的账单后台。边界是糊的,一件事的上下文会漏到下一件事里。
又回到了 On Routing 的那个问题:单位是什么?叫不出名字的东西,没法优化。
所以第零步是一个离线作业。定期读生产轨迹,聚类,再把每一类抽象成真正的任务。把日志变成练习题。剩下的一切都从这里开始。
好消息是,用户会重复自己。同一种任务模式做对一次,以后每次重跑都能受益。
一个任务要能用,先得有两样东西:
- 意图。 Prompt 很吵。「把上周那个事做一下」不是规格。提取用户真正想要什么,就有了输入;事情最后变成什么样,是输出。中间才有一段可以优化的 workflow。
- 类型。 浏览器操作、connector,偶尔写点代码。每种类型都要有自己的策略和检查。拿一个 loop 管所有类型,就又回到了共用 harness。
然后按难度筛。我找到最管用的一条规则是:留下当前 agent 做十次能成功三四次的任务。
10/10 已经可靠了,没什么可学
3/10 预算全花在这里
0/10 可能是最好的数据,但这个模型用不上
全过,学不到东西。全挂,可能是你手上质量最高的数据,在这里却还是没用。因为自我改进不会凭空增加能力。模型偶尔都做不到的事,它教不会。它做的是把「偶尔」变成「稳定」。
新能力需要新信息,通常意味着联网搜索。做 benchmark 时你会把它关掉:答案就放在网上。
评分标准就是目标函数
任何优化都需要目标函数。拿 LLM 当优化器,目标函数就是 rubric,也就是评分标准。没有 rubric,就没有方向,只有漂移。
写代码自带评分标准,其他领域大多还靠经验:
代码 测试脚本。exit 0,否则不算
数学 固定答案格式,提取,比对
写作 人写一份参考,模型对照着评
个人助理 ?
最后一行,我目前最好的答案是:不可验证的东西,甚至「用户是否满意」,也可以用几条可验证的标准去近似。你在过去五次对话里都提过麦当劳,然后让 agent 给你点个汉堡,随便什么汉堡。如果它选了麦当劳,你会注意到。这就是一条 rubric。叫一致性。
找出五六条这样的标准,交给优化器,让它进化。它们覆盖不了全部,只要方向大致对就够了。
我的第一版清单:
一致性 同样的请求,同样的选择,除非用户另有交代
记忆 几周前只说过一次的事,现在还会用
意图 做的是用户想做的,不只是字面写的
成本 做完用了多少步、多少分钟
纠正 人需要介入多少次
难的不是任务,是 rubric。Rubric 来自领域专家,所以实验室要花钱请医生评医学,请文学博士评文章。
个性化的领域专家就是用户,而用户永远不会给你写 rubric。他们会纠正你,再问一遍,或者默默不用了。如果你记下来了,那就是 rubric。
所以我会单独建一个 rubric generator:一个专门为任务写测试和评分标准的 agent,再用用户反馈去修。「单独」很重要。永远不要让模型给自己的活儿打分。
但那个老问题到处都成立:写检查比做任务更难。让模型写测试,你拿到的往往是「能跑就算过」,或者十种情况只测了一种。生成出来的 rubric 只是草稿,得有人签字。
补丁得有个位置
给 agent 看一次失败,它一定能提一个 harness 补丁。每次都能。这是最便宜的部分。里面很多根本不该进:诊断是编的,或者把没坏的东西重写了一遍。
整个 harness 一起进化,一步就会碰五六个模块。分数涨了,没人说得清为什么;分数掉了,没人说得清掉在哪。
所以把 agent 切成模块:agent loop、上下文管理、工具、观测处理、记忆。每一步只准碰一个。不是因为小补丁更聪明,是因为小补丁有位置可找。
模块以外的东西,选什么 sandbox、用什么 API、花多少钱,都固定住。那是基础设施和预算,agent 没有投票权。
如果先拿 coding agent 试,我会从 Terminus 2 开始,Terminal-Bench 的参考 agent。它是故意做简单的:没有别的工具,只有一个能往里敲按键的 tmux pane。成熟 agent 到处都是专家打磨过的模块,剩下的提升空间很难量。简单的 agent,每一点提升都看得见。
简单也让失败容易读懂。比如 agent 每次从 pane 读回来的内容最多一千个字符。所有长输出任务都可能变得无解:它要找的报错在截断线后面。
这不是模型能力不够。是一个看起来像笨的 harness 缺陷。
验收关卡
我会这样跑验收:
运行 第 N 批 · 8 个任务 · 成功/失败 · 执行轨迹
提案 agent 读失败轨迹,只改一个模块
验收 重跑第 N 批 不能退步
跑第 N+1 批 不能退步:能泛化
代码能解析
diff 没有越出模块边界
不是把上周的补丁反向改回来
接受 commit · 第 N+1 批的轨迹作为下一轮输入
拒绝 revert
每一行都很无聊。每一行都堵住了一种 loop 骗自己的方式。检查历史是为了防止来回横跳:周二改上去,周四改回来,两次都记成进步。把第 N+1 批直接用作下一轮输入,能省掉一次完整运行。这很重要,因为整件事又慢又贵。Sandbox 不是免费的。
Harness² 从另一边处理慢的问题:它针对单个任务的 loop,既能串行扩展,也能并行扩展。慢的 loop,至少可以铺得宽一点。
版本管理就是 git。每一步一个 commit,走错一步就 revert。再借用 Darwin Gödel Machine 的版本档案:不只留最新版,而是保留一个不断增长的版本库。每个模块的每个版本,都写清楚它是干什么的、为什么改、哪里变好了、哪里变差了。
Commit message 就是经验。
把这些经验写成 Markdown,让 agent 读、理解,不要只变成检索出来的几行记录。Meta-Harness 做的就是类似的事:负责提案的 agent,能从磁盘上读到所有历史候选的代码、分数和轨迹。和 Orbit 是同一个教训:状态住在文件里,不在 agent 脑子里。
不能回放
在数据那篇里我写过:「回放。让打过补丁的 agent 跑录下来的片段。别搞 staging 表演。」
对个人 agent,这句话是错的。
一个问题就能把它问死:发过一封邮件的任务,怎么再跑一次?每次运行都有副作用。消息发出去了,登录触发了,配额烧掉了。哪怕一个 GET,只要 connector 每天限制读取次数,也有副作用。你不能在用户的真实环境里跑 benchmark,也不能把同一件事跑两遍。
写代码也没法干净地回放。Agent 会改环境,而环境就是状态。重建中间状态很难。你可以给每个中间错误写一个测试,再把历史当文本喂回去,但切到这个粒度,自我改进学到的就只剩过测试。
Mock 也救不了。把每次工具返回都录下来,当 fixture 喂回去,回放确实能跑。前提是打过补丁的 agent 一直沿着旧 agent 的路走。补丁存在的意义恰恰是改这条路。只要它走出一步不同的,录制就没东西可答了。
录制只能回答旧 agent 问过的问题。
所以环境得搭出来,不能只录下来。从生产里挖任务,在线下重建,每个任务有自己的 sandbox 和检查。在那里进化,然后像普通部署一样上线。先自己用,再给一小部分用户。旧 harness 收一百个用户的反馈,新 harness 也收一百个。赢的成为新基线,否则回滚。
Harness² 是为在线改进设计的:测试时,一个任务一个任务地改。对一个每次动作都会落进别人收件箱的 agent,我会把实验留在线下。实时进化,是发现自己错了最贵的一种方式。
Agent 改进自己,仍然只是又一次部署。只是不能拿生产环境排练。
Prompt 和 hook
对我原来那套做法,最有力的反对意见是:用 prompt 写 workflow,不要把它写死在架构里。固定工具和结构,让模型在里面优化,你也就定死了它的天花板。描述好的 workflow 应该是什么样,让模型自己组织,也别指望它每一行都照做。
这也是静态 skill 让人失望的原因。粒度太粗,选哪个又容易出错:塞进去几百个,模型还是反复用那两个;选错一个,效果甚至不如不用。只加载当前任务需要的。
我更愿意押的方向是,每种任务模式配一个 harness:prompt、脚本、工具作为一个整体,一起做版本管理,一起进化。一个动态 workflow,不是抽屉里的一份 skill。听起来和「prompt 优先于架构」正好相反。也不完全是:workflow 的主体仍然是 prompt,进化的是 workflow,不是外面那个笼子。
但有些指令不是建议。发东西必须走这个工具,不能走另一个。任何东西离开系统之前,先检查。长上下文里,偏偏最容易丢的就是这几句。这些要交给 hook:在触发点注入提醒,就放在工具调用之前,不要指望八万 token 以前的那一行还能活下来。
这是 On Harness 里按影响范围设关卡的规则,再往下一层。能评分的,交给 prompt;收不回来的,交给 hook。
个人数据是稀疏的
个人数据最难:稀疏、罕见,却又是整件事的意义。几个月前只提过一次的偏好,恰恰是让 agent 像「你的」agent 的那个信号,也恰恰最容易被检索器排到噪声后面。
所以对个性化来说,记忆就是 harness 的大半。什么时候写,什么时候更新,重复怎么办,冲突听谁的,只提过一次的事实该有多大权重。
而值得记住的不是日志,是意图。从用户的轨迹里提取底层意图,放进全局记忆,让每一个决策都对照它。又是一致性,只是从另一边看。
意图会变,跟你最近在和谁说话、身处哪里都有关系。所以它不是一张静态画像,是一条时间序列。每天提取,隔几周看 diff。Agent 拿不准时,就学推荐系统冷启动的做法:问。Netflix 推荐之前能先让你选三部片,agent 能问一个问题。
Harness² 给跨任务的那一半起了个名字:持续改进的 harness,把每个任务教会它的东西提炼出来,交给下一个任务继承。对个人 agent 来说,任务教会它的是这个人。这里所有版本的自我改进里,这是我真想用的那一种。
但是
这里所有有效的东西,下面都垫着 benchmark。
Coding agent 有退出码。Harness² 的提升是在三个专业工作 benchmark 上测出来的。连拆 rubric 那一招,也需要某个地方有某个人,能说清哪个答案是对的。
我们只有一个收件箱。每跑一次都有副作用,没有答案,也没有一个愿意写 rubric 的领域专家。
所以,个性化的好 rubric 到底是什么?我还不知道。所以这篇写的是施工顺序,不是结果。
施工顺序
数据那篇停在了「先有数据」。接下来是这些:
挖任务 生产轨迹 → 任务 · 意图输入,结果输出
筛难度 留下十次能做对三次的
定标准 每种任务几条可验证的检查 · 人来签字
切模块 把 harness 切开,让补丁有位置可找
做验收 同一批、下一批,都不能退步 · diff 留在模块内
记版本 每一步一个 commit · 每个 commit 说清为什么
上线 离线,然后自用,然后一小部分用户 · 留下或回滚
进化 大家画图时都爱画的那个框
优化器在最后一行。也只有这一行会被放进幻灯片。
Agent 几秒钟就能写一个补丁。知道它是不是更好,才是要做的工作。