Karpathy 用约 630 行代码搭了一个让 AI 自己跑实验的系统。我不是 ML 研究员,但从中拆出了三条原则,平移到了日常开发里------不绑定任何特定工具,Claude Code、Codex、opencode 都能用。这篇文章不讲模型训练,只讲方法论怎么落地。
声明 :本文讲的"Loop"是反馈闭环(执行→验证→不达标继续→达标停止),不是 Claude Code 的
/loop命令(定时重复执行,不检查结果)。两个不是一回事。
一、Karpathy 到底做对了什么
2026 年 3 月,Karpathy 开源了 AutoResearch。其中 Agent 主要编辑的 train.py 约 630 行,仓库还包含固定的评分脚本 prepare.py 和 Agent 指令 program.md。截至本文写作时约 9 万 star。
它的核心逻辑极其简单,三步:
Agent 改代码 → 自动打分 → 分数变好就保留,变差就回退 → 再来一轮
朴素到像废话。但真正厉害的不是这个流程本身,而是他在这套流程里嵌入了三个设计决策。这三个决策直接就能平移到我每天的开发工作里。
二、三条可迁移的核心原则
原则一:裁判和选手必须分离
AutoResearch 的核心设计是:Agent 可以改被优化对象的代码,但评分脚本保持固定,Agent 不应修改。
为什么?因为 LLM 被放进优化循环后,倾向于寻找最容易提高指标的路径:如果能改评分逻辑,它会选择"让分数看起来变好",而不是"让模型真的变好"。
平移到我日常开发里 :验证命令(npm test、npx tsc --noEmit)不由 Agent 定义、不由 Agent 修改。它只能跑,不能改。
具体做法:在项目的 DEV.md 里写死------
markdown
## 验证规则
- 每次改动后运行: npm test && npx tsc --noEmit
- 任一失败 → 先修,不要继续提新改动
提醒:DEV.md 是行为约束,不是安全边界。验证脚本本身应该放进项目脚本或 CI 中;如果要防止 Agent 篡改,需要通过权限、受保护分支或 CI 配置来实现。
Agent 可以改任何业务代码,但验证命令这道关它绕不过去。这道关就是我的 prepare.py。
原则二:先有尺子,才有 Loop
Karpathy 整个系统的前提不是 LLM 够聪明,而是 val loss 是一个能自动计算的数字。
对非 ML 开发者来说,val loss 可以理解为模型在"没见过的数据"上的错误分数,越低通常越好。类比到开发场景,它就相当于测试通过率、接口延迟、benchmark 分数------一个能自动跑、自动出分、不需要人拍脑袋判断的指标。
如果没有这个数字,Loop 就是在烧 token 做布朗运动------Agent 改来改去,每一轮都觉得自己改得不错,因为没有人在打分。
平移到我日常开发里:每次开一个任务前,我先问自己:
这个任务完成后,有没有一个命令能自动告诉我"做得好不好"?
| 模糊需求 | 翻译成可验证的目标 |
|---|---|
| "把这段代码改得优雅一点" | 消除重复逻辑 + npm test 全绿 + 单函数 ≤30 行 |
| "性能优化一下" | benchmark 跑分 ≥ 当前值的 1.2x |
| "重构这个模块" | 对外接口不变 + npm test 全绿 + tsc --noEmit 通过 |
没有可验证目标的 Loop = 自我认同生成器。
原则三:用 git 做状态文件
AutoResearch 的循环语义是:改代码、训练、评估,改进则保留,否则丢弃。日常开发可以借用 git 来记录每轮状态。
这意味着你不需要自己记"试过什么"------git log 就是实验日志。
平移到我日常开发里:在 DEV.md 里加一条------
markdown
## 迭代规则
- 完成一个独立小目标后 git commit
- commit 格式: type: <做了什么>
- 失败时先展示 diff,只回退本轮自己改过的文件
注意:日常开发和 AutoResearch 不完全一样。AutoResearch 是每轮实验自动化地 commit 或 reset;日常开发更适合在"小目标完成且验证通过"后手动 commit,不需要每轮都提交。另外,如果工作区有未提交的改动,不要直接 git checkout ,先 git stash 或用 diff 确认回退范围。
以上三条解决的是内层 Loop 如何稳定运行。下一步是:谁来观察这个 Loop 本身有没有走偏?
三、双层 Loop 的启发:你自己就是外层
AutoResearch 之后,Yaonan Qu 和 Meng Lu 在 2026 年 3 月 24 日提交了论文 Bilevel Autoresearch: Meta-Autoresearching Itself。论文在原版 Loop 上面又套了一层:
- 内层:Agent 改模型、训练、打分、保留或回退
- 外层:不碰模型,只观察内层的运行轨迹。发现内层在一个方向反复打转,就生成一条新规则注入,改变内层的搜索策略
在 Karpathy 的 GPT 预训练基准上,论文报告双层 Loop 相对单层的验证指标(val_bpb)改进约 5 倍(-0.045 vs -0.009)。注意这是该 benchmark 和论文实验设置下的结果。
这件事对我日常开发的启发是什么?我自己就是那个外层。
实际做法:
- AI 编程工具开着,Agent 在改代码(内层在跑)
- 我每隔 30 分钟回来看一眼最近的 commit log
- 如果我发现 Agent 在两个方案间反复横跳,就在 DEV.md 里加一条约束:"禁止改 X,先探索 Y"
- 这和论文里外层做的事思路相似------读了轨迹,发现卡点,生成新规则,注入。区别是论文外层由 LLM 自动完成,这里外层由人来做
当我做的事从"审每一行代码"变成"审 Agent 的行为模式",就完成了从 Prompt 使用者到 Loop 管理者的切换。
四、落地:把 Loop 规则放进项目规范,跨工具通用
前面三条原则不是哪一款工具的专属功能------它们是写在项目规范文件里的纯文本规则。只要入口文件或初始化提示明确要求读取 DEV.md,这套规则就可以跨工具复用。
4.1 规则放在哪里
我用的项目规范体系是 6 个文档(详见前一篇博客),核心设计是薄入口------CLAUDE.md 和 AGENTS.md 只做指针,真正的内容存在 DEV.md 里:
| 文件 | 角色 | Loop 相关规则放这里? |
|---|---|---|
| CLAUDE.md(Claude Code 入口) | 只引用 DEV.md,不承载内容 | 不放,保持薄入口 |
| AGENTS.md(Codex 入口) | 同上 | 不放,保持薄入口 |
| DEV.md(开发规范) | 工作流、约束、检查规则 | 放这里 |
| TODO.md(任务面板) | 当前任务、验证状态 | 任务级 Loop 目标放这里 |
为什么Loop 规则不放 CLAUDE.md?因为一旦项目换了 AI 工具(从 Claude Code 换到 Codex 或 opencode),CLAUDE.md 就不会被读取。在我的项目规范里,CLAUDE.md 和 AGENTS.md 只负责指向 DEV.md,这样不同工具通过各自入口进入后,读到的是同一套规则。
4.2 生成 Loop 规则:INIT.md 已经替你做了
上节的示例是用 TypeScript 项目举的(npm test、tsc --noEmit),但你的项目可能是 Go、Python、Rust,验证命令完全不同。手写一个通用模板不现实。
正确的做法是让 AI 读项目已有的 DEV.md,自动生成适合当前项目的 Loop 规则。这件事不需要你手动操作 ------如果你用 INIT.md 初始化项目(详见前一篇博客),INIT.md 的执行规则里已经包含了这一步:DEV.md 整理完成后,AI 会自动检查项目命令并在末尾追加 Loop 段落。
有真实命令的项目,AI 自动生成的效果(以 Go 为例):
markdown
## 自主迭代规则(Loop)
### 验证规则
- 每次改动后必须运行: go test ./... && go vet ./...
- 任一失败 → 先修,不继续提新改动
### 迭代规则
- 完成一个独立小目标 → git commit
- commit 格式: type: <描述>
- 失败时先展示 diff,只回退本轮自己改过的文件
### 完成标准(Stop Condition)
先看硬指标(必须全部满足):
- go test ./... 全绿
- go vet ./... 无报错
- golangci-lint run 无 warning
硬指标全过之后,再自评 1-10 分:
...
### 不要做的事
...
以 Python 项目为例,验证规则会变成 pytest && ruff check . && mypy src/;Rust 项目会变成 cargo test && cargo clippy。命令来自 DEV.md,AI 只是把它们组织成 Loop 结构。
你只需要这一句------拿到新项目,粘贴下面这段,回车。初始化完成后,DEV.md 末尾的 Loop 规则已经在项目里了:
text
请读取 http://nbtang.cn/dev/INIT.md,并严格按照其中规范初始化当前项目。
如果无法访问该 URL,必须立即停止并说明原因,不要凭空猜测、不要继续生成文档。
暂时不要修改任何业务代码、配置文件、依赖文件或构建产物。
只允许在当前项目根目录建立或完善以下文档:
INIT.md、DEV.md、README.md、TODO.md、AGENTS.md、CLAUDE.md。
除非我明确要求"提交代码""提交到 git""commit"等,否则不得主动执行 git commit。
可以执行 git status、git diff、git log 等只读检查;如认为需要提交,请先说明原因并等待我确认。
初始化完成后,请说明:
- 新增或修改了哪些文档
- 每个文档的主要内容
- 哪些信息仍需人工确认
4.3 不止写代码:一个基础设施项目的 Loop 实录
Loop 这套方法在非纯代码项目上同样有效。拿我自己部署的一个真实项目来说------
项目:Windows + WSL 开发环境自动化配置。涉及 netsh 端口转发、iptables 规则、systemd 定时器、Windows 计划任务------不是写业务代码,是配基础设施。
验证器:三个脚本,11 项自动化检查。
verify.ps1 → verify-windows.ps1(5 项:端口转发规则、服务连通性、进程状态、网络可达性、系统资源)
→ verify-wsl.sh (6 项:核心服务运行状态、网络接口配置、iptables 规则、定时器状态、进程存活、系统 uptime)
每次 Agent 改完配置,跑 verify.ps1,11 项全绿才算过关,否则修到绿为止。
实际效果 :项目从零到生产可用,DEV.md 里的 Loop 规则驱动了完整的迭代过程。最后还让 opencode 和 Codex 各自独立跑了一遍验证,双重确认了项目状态。(这是我自己的项目记录,不是 AutoResearch 仓库的结果。)整个过程中,我没有逐条配 iptables、没有手动调 systemd timer------我把验证标准写好,Loop 帮我搜到了正确配置。
这说明一件事:Loop 不挑技术栈。验证命令可以是 go test,也可以是一组检查服务状态和网络配置的脚本------只要是能自动返回成功/失败的检查,就能当尺子。
4.4 反模式:没有验证器的 Loop 是烧钱机
最常见的翻车场景:
你:"把这段代码改得更好一点"
Agent:改写 → 你觉得不对劲但挑不出错 → "再改"
Agent:又改 → 更不对劲 → 你放弃,手动重写
从头到尾没有一把尺子,每一轮都在空转。模糊需求先翻译成可验证目标,写入 TODO.md,再开 Loop。
4.5 一图总结
你(外层)
│ 每隔 30min 介入
│ 看 commit log → 发现卡点 → 更新 DEV.md 的约束规则
▼
AI 编程工具(内层 Loop)
│ 读 CLAUDE.md/AGENTS.md → 跳转 DEV.md
│ 读 TODO.md → 知道当前任务和验证标准
│ 改代码 → run 验证命令 → commit / 回退
│ 自评打分 → 全 ≥8 就停
│
└── 你回来验收最终结果
你不再是一行一行审代码,而是在审 Agent 的行为模式。这套 Loop 真正有启发的地方,不是"AI 替你干活",而是把你从每一步微操中移到了规则设计和结果验收的位置。
参考链接
如果您觉得有用,欢迎 点赞、转发、评论、关注。