关于 autoresearch
autoresearch 是面向编码 Agent 的技能,将代码优化组织为有记录的实验,并进行重复测量和正确性检查。它强调明确假设、可比较的测试及本地报告,避免依赖单次基准结果。
主要功能
- 01开始前确认目标与约束
- 02每次实验限定一个假设
- 03执行预热和重复测量
- 04记录失败情况与实验结论
- 05生成本地 CSV 和 HTML 报告
适用场景
- 01将候选代码改动与基线比较
- 02调查有噪声的性能测量结果
- 03跟踪优化尝试及失败方案
- 04将实验产物与版本控制隔离
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ckorhonen/ claude-skills --skill autoresearch安装后在 Claude Code 中输入/autoresearch确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
scripts/common.pyinit_experiment.pylog_experiment.pyrender_report.pyrun_experiment.py详细介绍
Autoresearch
只有像严谨研究而非基准测试赌博那样开展时,自主优化才有意义。
此技能会执行严格的实验循环:
- 在更改代码前明确目标
- 在测试前写下假设
- 通过重复试验进行测量,而非依赖一次性的胜出结果
- 记录每项实验,包括失败的实验
- 生成不会提交到版本库的本地报告和图表
核心原则
- 不得默默推断范围
如果请求含糊不清,请暂停并先进行简短的问答。不要默默臆造目标工作负载、正确性门槛或权衡取舍。
- 一次实验 = 一个假设
在进行更改前,说明拟议的更改及其预期效果。避免将无关调整打包在一起。
- 记录所有实验
每项实验都必须列入机器可读的台账,包括被舍弃的想法、崩溃和未通过的检查。
- 重复测量胜过嘈杂的轶闻
不要因一次快速运行就保留某项更改。应进行预热和重复测量,并明确决策规则。
- 产物保留在本地
报告、CSV、JSONL 台账和图表应放在本地 .autoresearch/ 目录中,不应提交到版本库。
可用脚本
scripts/init_experiment.py— 初始化.autoresearch/session.json,确保.autoresearch/保持未跟踪状态,并在需要时创建autoresearch.md框架。scripts/run_experiment.py— 运行预热和测量试验,解析METRIC行,运行可选检查,并生成 JSON 实验记录。scripts/log_experiment.py— 将实验追加到.autoresearch/results.jsonl,决定keep还是discard,并更新 CSV 和 HTML 产物。scripts/render_report.py— 根据 JSONL 台账重新生成.autoresearch/results.csv和.autoresearch/report.html。
所有脚本均为非交互式,提供 --help,在 stdout 输出结构化 JSON,并将诊断信息写入 stderr。
默认工作流
-
在前期问答后初始化会话:
python3 scripts/init_experiment.py \ --goal "Reduce latency in hot path" \ --metric-name latency_ms \ --unit ms \ --direction lower \ --command ./autoresearch.sh \ --checks-command ./autoresearch.checks.sh \ --scope src/hot_path.ts -
记录基线:
# Option A: save to file first, then log python3 scripts/run_experiment.py \ --id baseline \ --hypothesis "Control run" \ --change-summary "No code changes" \ --baseline \ --output .autoresearch/baseline.json python3 scripts/log_experiment.py --input .autoresearch/baseline.json # Option B: pipe directly python3 scripts/run_experiment.py \ --id baseline \ --hypothesis "Control run" \ --change-summary "No code changes" \ --baseline \ | python3 scripts/log_experiment.py -
记录每项候选实验:
python3 scripts/run_experiment.py \ --id exp-001 \ --hypothesis "Inlining removes allocation churn" \ --change-summary "Inline helper and pre-size buffer" \ --output .autoresearch/exp-001.json python3 scripts/log_experiment.py --input .autoresearch/exp-001.json -
按需重新渲染产物:
python3 scripts/render_report.py
前期问答
开始前,收集或确认以下所有信息。如有任何项目含糊不清或缺失,请先提出有针对性的问题。
- 目标 — 要优化什么?
- 主要指标 — 确切名称、单位,以及数值越低还是越高越好
- 最小有效改进幅度 — 如果用户未指定,默认为
1% - 工作负载命令 — 能代表实际情况的确切命令或脚本
- 正确性门槛 — 测试、类型检查、lint、评估集、准确率下限或其他不可妥协的要求
- 范围 — 允许修改哪些文件,哪些文件不得修改
- 预算 — 如果用户有要求,明确时间预算、计算资源预算或停止条件
如果用户说“直接开始吧”,请在首次实验前将假设明确写入 autoresearch.md,然后通过 python3 scripts/init_experiment.py ... 将其记录下来。
工作区设置
-
优先在新分支上使用专用工作树:
git worktree add ../autoresearch-<goal>-<date> -b autoresearch/<goal>-<date>如果不便使用工作树,则在干净的工作树中创建新分支。不要在包含无关用户更改的脏工作树中运行此技能。
-
创建:
autoresearch.md— 提交到版本库,作为持久的会话说明autoresearch.sh— 提交到版本库,作为基准测试运行器autoresearch.checks.sh— 仅在需要正确性门槛时提交到版本库.autoresearch/— 本地产物目录,不提交到版本库
-
确保本地产物保持未跟踪状态:
rg -qxF '.autoresearch/' .git/info/exclude || printf '\n.autoresearch/\n' >> .git/info/exclude -
如需了解确切接口,请运行
python3 scripts/init_experiment.py --help,然后初始化会话,使用python3 scripts/run_experiment.py ...收集基线,并在修改任何代码前使用python3 scripts/log_experiment.py ...将其记录下来。
必需文件
autoresearch.md
这是本次会话的持久契约。新的 Agent 应能依据它继续工作,无需猜测。
# Autoresearch: <goal>
## Objective
<What is being optimized and why it matters.>
## Up-Front Answers
- Primary metric:
- Unit:
- Direction:
- Minimum meaningful improvement:
- Workload command:
- Correctness gates:
- Budget / stop criteria:
## Scope
- In scope:
- Off limits:
## Decision Rule
<How many warmups, how many measured trials, how "keep" is decided.>
## Experiment Ledger
`.autoresearch/results.jsonl`
## Report Outputs
- `.autoresearch/report.html`
- `.autoresearch/results.csv`
- `.autoresearch/plots/`
## Current Best Result
<Best known baseline or kept variant.>
## What We've Learned
<Key wins, dead ends, confounders, and structural insights.>
每当假设发生变化、发现新的最佳结果或明确某种模式时,都要更新 autoresearch.md。
autoresearch.sh
使用 set -euo pipefail 的 Bash 脚本,该脚本:
- 只执行非常快速的预检查
- 运行实际基准测试工作负载
- 输出可解析的
METRIC name=value行 - 在各次实验中保持稳定,以确保运行结果可比较
尽可能保持脚本精简、确定。如果更改基准测试协议,请在 autoresearch.md 中记录,并建立新的基线。
autoresearch.checks.sh
如果本次会话设有正确性门槛,则创建此脚本。它必须:
- 在候选方案通过基准测试后验证其正确性
- 不影响主要指标的计时
- 输出简短,并聚焦于错误
- 候选方案不够安全、不可保留时,必须明确失败
如果检查失败,实验处置结果应为 checks_failed,而非 keep。默认脚本工作流会自动处理此情况。
本地构件契约
以下所有内容都位于 .autoresearch/ 中,且应保持未跟踪状态。
.autoresearch/results.jsonl
每次实验追加一个 JSON 对象。这是枚举所有实验的唯一事实来源。
必需字段:
{
"id": "exp-007",
"timestamp": "2026-03-14T13:00:00Z",
"hypothesis": "Inlining X removes allocation churn in hot path Y.",
"change_summary": "Inline helper and pre-size buffer.",
"files_touched": ["src/hot_path.ts"],
"baseline_commit": "abc1234",
"candidate_ref": "def5678",
"metric_name": "latency_ms",
"direction": "lower",
"warmup_trials": [12.8, 12.7],
"measured_trials": [11.9, 12.0, 11.8, 11.9, 12.1],
"summary": {
"median": 11.9,
"mean": 11.94,
"min": 11.8,
"max": 12.1
},
"secondary_metrics": {
"memory_mb": 84.1
},
"checks": "passed",
"disposition": "keep",
"reason": "Median improved by 5.2%, checks passed, complexity acceptable."
}
.autoresearch/results.csv
每次实验后或定期将 JSONL 展平为便于电子表格处理的摘要。
.autoresearch/report.html
生成一个可视化会话过程的 HTML 报告。至少包括:
- 列出每项实验及其处置结果的表格
- 主要指标随时间的变化
- 最佳结果趋势
- 各实验测量试验的分布
- 检查通过/失败/崩溃的次数
- 保留的改进与舍弃的想法摘要
.autoresearch/plots/
如果报告使用外部资源,则在此处存储生成的图表或导出的图片。
实验卡片
每次实验前,在 autoresearch.md 或临时笔记中编写一份简短的实验卡片:
idhypothesisplanned changewhy this should affect the metricfiles expected to changepredicted direction and rough magnituderollback plan
如果无法说明更改为何有帮助,就先不要运行实验。
测量协议
除非用户指定更严格的要求,否则使用以下默认协议:
-
先预热
- 至少运行
2次预热试验,这些试验不用于决策。
- 至少运行
-
重复测量
- 对基线和每个重要候选方案,至少运行
5次测量试验。 - 如果噪声较大或收益微乎其微,则增加样本量。不要接受模棱两可的结果。
- 对基线和每个重要候选方案,至少运行
-
稳健地汇总
- 使用中位数作为主要决策统计量。
- 同时记录平均值、最小值和最大值,以便观察方差。
-
应用预先声明的阈值
- 只有当更改至少达到最低有效改进阈值且通过所有正确性检查时,才予以保留。
-
必要时重置基线
- 如果工作负载、机器条件、数据集或基准测试框架发生实质性变化,则建立新的基线并说明原因。
决策规则
-
keep- 候选方案按已声明的指标方向优于当前最佳方案
- 改进达到最低有效改进阈值
- 正确性检查通过
- 必需的次要指标没有出现不可接受的退化
-
discard- 候选方案表现更差
- 候选方案实际上没有变化
- 结果噪声太大,无法建立足够信心
- 复杂度成本不值得这点收益
-
checks_failed- 基准测试结果可能有所改善,但必需的正确性门槛未通过
-
crash- 候选方案破坏了工作负载,或无法可靠测量
不要因为某个结果看起来有前景,就把模棱两可的结果判为 keep。
循环行为
自主运行,但不要在没有新发现的情况下无限运行。满足以下任一条件时停止:
- 时间或算力预算耗尽
- 尝试了几种不同的假设后,仍未发现有意义的改进
- 已穷尽所有有前景的思路
- 用户中断或调整了工作方向
循环期间:
- 一次只做一项有意义的更改
- 避免对同一个失败思路稍作表面修改后反复尝试
- 记录走不通的思路,以免后续 Agent 重蹈覆辙
- 在各次实验之间保持工作树干净
放弃某个候选方案时,在开始尝试下一个思路之前,先在隔离的工作树中恢复到上一个已提交的良好状态。
常见陷阱
Autoresearch 讲究实证,但在长期运行的优化循环中,仍会出现几种失败模式。了解这些模式有助于避免浪费实验资源和破坏工作流。
1. 优化陷入平台期后,实验循环仍未停止
症状:
- Agent 在最近一次改进之后,仍连续多轮开展新实验
- 没有明确的停止点;进行 10–15 次实验后,循环开始失去方向
- 消耗时间或算力预算,却没有发现新的见解
根本原因:
- 除预算耗尽外,缺少退出条件
- Agent 认为“实验越多 = 知识越多”,却没有检查学习曲线是否已趋于饱和
- 没有系统地检测重复的假设模式或收益递减
缓解措施:
- 在
autoresearch.md中设置平台期阈值:连续 N 次实验没有改进时停止,例如:“如果连续 3 次实验的增益低于 0.5%,则停止” - 跟踪假设多样性——如果新假设只是对旧思路换种说法,就停止并记录经验
- 实施移动窗口启发式方法:计算最近 5 次实验的改进速度;当每次实验的改进速度低于 0.1% 时停止
- 提前退出时,在
autoresearch.md中明确记录停止原因
2. 经过 5–10 次迭代后,假设生成变得重复
症状:
- 后续实验只是早期思路的小幅变化(例如,“缓冲区大小为 16、32 还是 24”)
- 假设缺少明确的因果理论,只是在调整常量
- 结果的差异逐渐缩小,但仍未出现明确的赢家
根本原因:
- Agent 默认采用局部梯度下降,却没有停下来反思根本原因
- 缺少明确的假设清单,也没有进行新颖性检查
- 深入研究微优化之前,没有充分探索假设空间
缓解措施:
- 每次实验前,将假设写成能够回答“为什么这能改善指标?”的形式。如果答案是“因为我在调参数”,就先暂停并构思一个新方向
- 记录走不通的思路——放弃实验时,明确说明失败原因,以免后续假设再次走上这条路
- 每隔 3–4 次实验轮换假设类型:
- 算法改动(例如,用跳表替换哈希表)
- 数据结构改动(例如,预分配、布局)
- 控制流改动(例如,分支预测、循环展开)
- 外部因素(例如,编译器标志、采样率)
- 检查点与反思:完成 5 次实验后,重新阅读
autoresearch.md,并明确撰写“我们的发现”部分,列出 2–3 条关键见解。如果该部分为空,说明你只是在原地打转
3. 长时间运行时日志文件无限增长
症状:
- 进行 50 多次实验后,
.autoresearch/目录膨胀到数十甚至数百 MB - 随着时间推移,运行
python3 scripts/render_report.py的速度明显变慢 - 在资源受限的机器上,磁盘用量成为运维问题
根本原因:
- 每次实验都会生成一条完整的 JSON 记录,而且记录从未清理
- 如果测量结果包含冗长的调试输出或跟踪信息,这些内容会不断累积在 JSONL 文件中
- HTML 报告可能会内嵌所有原始数据,导致 HTML 文件达到数 MB
缓解措施:
- 定期归档:每进行 20 次实验,就将旧结果归档到
.autoresearch/archive/YYYYMMDD-run-N.jsonl,并重新创建一个空的results.jsonl - 限制测量输出:确保
autoresearch.sh不输出冗长日志;只捕获METRIC行 - 存储摘要,而非原始跟踪数据:如果空间紧张,在
results.jsonl中记录{"summary": {...}, "median": X},而不是所有原始试验值 - 在
autoresearch.md中记录归档情况:注明账本的归档时间,以及如何访问之前的运行记录 - 监控产物大小:在循环中添加检查:
du -sh .autoresearch/ | grep -qE '[0-9]+M' && echo "WARNING: artifact directory >100MB"
4. 实验次数超过 100 时 HTML 报告无法正常呈现
症状:
- 多次实验后打开
.autoresearch/report.html,浏览器变得卡顿或无响应 - 图表无法呈现,或只显示部分数据
- 页面大小膨胀到 50 多 MB,导致分享或纳入版本控制变得不切实际
根本原因:
render_report.py会生成一个内嵌所有数据的单体 HTML 文件- 如果没有分页或延迟加载,JavaScript 图表库无法处理 100 个以上的数据点
- 对于大型结果集,没有截断或摘要模式
缓解措施:
- 对结果分页:将实验账本拆分为每 50 条一组,并生成单独的报告页面(
report-01.html、report-02.html等),同时添加导航链接 - 大型运行使用摘要模式:如果
len(results) > 100,则生成精简报告,其中包含:- 仅保留实验的表格(过滤掉 discard、crash、checks_failed)
- 迄今为止的最佳结果趋势线(而非所有单独的数据点)
- 按阶段统计的摘要,而非按实验展示分布
- 将大型数据移至 JSON:将完整结果集嵌入
.autoresearch/data.json,并在 HTML 中引用,由客户端渲染,使 HTML 文件本身保持在 1 MB 以下 - 自动检测并发出警告:在
render_report.py中,如果结果数量 > 100,则记录:"WARNING: report contains >100 experiments; consider archiving old runs or using --summary-mode"
报告生成
定期生成或刷新 .autoresearch/report.html,并始终在会话结束时生成或刷新:
python3 scripts/render_report.py
报告应回答以下问题:
- 尝试了哪些实验
- 哪些实验成功、失败或崩溃
- 最佳指标如何随时间变化
- 次要指标出现了哪些权衡
- 最终建议的更改是什么,以及原因
如果制作丰富的图表过于繁琐,可以生成一个简单的静态 HTML 文件,使用内嵌 SVG 图表或轻量级本地资源。报告比美化更重要。
恢复运行行为
恢复运行时:
- 阅读
autoresearch.md - 检查
.autoresearch/results.jsonl - 如果
.autoresearch/report.html存在,则检查该文件 - 查看 git 历史中的保留提交
- 从已知的最佳状态继续,而不是基于过时的假设继续
实验期间的用户消息
如果用户在实验运行期间发送消息,且当前测量周期较短并且安全,则先完成该周期,再进行回复。如果运行时间较长或存在风险,则在最近的安全检查点停止并回复。