SpecFirst:将行为规约获取作为基于 Agent 从零程序合成中的一等步骤
- 关联论文:2607.27167
- 作者:flyP
- 更新:2026-07-31
一句话结论
SpecFirst 把从零做程序("白板合成")拆成两个 Agent 阶段——先用"规约 Agent"反复探测黑盒二进制,结合文档产生一份结构化行为规约,再交给"代码 Agent"按规约实现;在 ProgramBench 200 个实例、四个模型(两族、横跨一个数量级能力)上,把测试通过率提升 6.9%–21.3%,二进制探测覆盖率提升 9.4%–18.5%,全部统计显著。
解决的真问题
基于 LLM 的 Agent 在"有代码库"的软件工程任务(SWE-Bench、HumanEval-Fix 这类)上成绩亮眼,但放到"从零生成一个程序"场景就崩得厉害。论文引用 ProgramBench 给出了量化口径:只给自然语言文档 + 一个只能执行的二进制作为行为 oracle,前沿模型解题率不到 1%。
为什么崩?现有框架把三件完全不同的事挤到一个 prompt 循环里:
- 读文档:揣摩用户想要什么。
- 行为探测:跑二进制、喂输入、看输出,反推语义。
- 代码合成:根据以上结果写代码。
一旦这三件事混在一起,Agent 会出现三类连锁失败:
- Probe insufficiency:探测不够,没把黑盒的边界条件摸清楚就动手。
- Intent drift:随着上下文滑动,对"原始意图"的理解被慢慢稀释。
- Early misinterpretation propagation:早期一句错误的假设被后续步骤继承、放大,到实现阶段已经无法挽回。
SpecFirst 的立场是经典软件工程的"需求规约优先",但用 LLM Agent 把这条铁律重新实施一遍。
核心方法
SpecFirst 是一个两阶段框架,把"获取规约"变成一个一等公民步骤。
其设计哲学的核心用一句更直白的话说就是:让"知道要做什么"成为 Agent pipeline 中一个可被单独编辑、回滚、版本化的对象,而不是一段容易随 trace 滑动而漂移的隐藏状态。这在工业界其实是软件工程 50 年来的常识——"先写需求,再写代码"——只不过在 LLM 主导的 pipeline 里,它从来没有被当作一等公民赋予具体结构。SpecFirst 的贡献,就是把这个常识落实成可实现的 Agent 协议。
阶段 A:Spec Agent — 规约获取
输入:自然语言文档 + 一个仅可执行的二进制(行为 oracle)。
Spec Agent 的内部循环:
while budget_not_exhausted:
input_sample = explore_strategy(current_spec, unexplored_inputs)
output = oracle.run(input_sample)
observation = (input_sample, output)
spec = update_spec(spec, observation, doc)
coverage = binary_exploration_coverage(spec, observed_inputs)
if coverage_sufficient(spec): break
关键点:
- 结构化规约:spec 不是普通长文本,而是字段化的——包含输入域、输出域、约束、不变式、反例、边界等条目。
- 规约 + 探测交融:规约里要写"哪些输入已经探测、哪些还没",Spec Agent 据此选下一个探索方向。
- 拒答纪律:规约没有形成稳定解释前,不允许进入合成阶段。
阶段 B:Code Synthesis Agent — 规约驱动实现
输入:阶段 A 输出的结构化规约。
合成 Agent 把规约当作唯一可信源来用:
- 公共 API、边界条件、错误码、不变式都从规约取,不再回头读原始文档;
- 写一段代码 → 在 oracle 上跑 → 对照规约是否满足 → 不满足则改;
- 因为规约早于代码完成,最后产出有"可追溯"链条——出现 bug 时能定位到规约哪一条已被违反。
与 single-loop baseline 对比
single-loop baseline 把"读 doc + 探测 + 写代码"塞到同一个 ReAct / Reflexion 循环里,更接近现有 SOTA Agent 风格。SpecFirst 的差异在于:
| 维度 | single-loop baseline | SpecFirst |
|---|---|---|
| 规约步骤 | 隐式 / 嵌入 prompt | 一等公民、显式输出 |
| 探测驱动 | 与代码耦合 | 由规约中"未覆盖区域"驱动 |
| 上下文漂移 | 全文增长,易丢失意图 | 规约稳定,detached from trace |
| 误读传播 | 早期误读一路放大 | 误读先在 spec 阶段被 highlight |
关键实验与数据
实验设计有两个值得展开的部分。
- 基准:ProgramBench 全 200 实例(从零写程序场景)。
- ProgramBench 的设计意图正好是 SpecFirst 想解决的问题:只给文档 + 可执行二进制,看模型能不能从中"反向工程"出真实意图。它是近半年新出的一个白板合成 benchmark,比 HumanEval 难得多,因为没有 ground-truth 代码可对照,只有行为 oracle。
- 模型:4 个模型,跨 2 个家族(如 Claude + GPT 系),能力跨度约一个数量级。
- 对照:single-loop baseline(与 SpecFirst 同模型同 prompt engineering 工具)。
- 指标:测试通过率(pass rate)、二进制探测覆盖率(binary exploration coverage)。
主要结果(相对 single-loop baseline 的提升):
| 维度 | 提升区间 | 统计性 |
|---|---|---|
| 测试通过率 | +6.9% 至 +21.3% | 全部统计显著 |
| 二进制探测覆盖率 | +9.4% 至 +18.5% | 全部统计显著 |
行为分析进一步观察:
- 此前置规约可使代码构造在更早阶段就开始,并贯穿整个合成过程持续被驱动;
- 不同能力档位都吃到了这一增幅,能力越弱的模型吃到的相对提升越显著(论文原文未明确给出确切斜率,但从 +6.9% 到 +21.3% 的跨度推测)。
- 规约本身在多轮之间保持稳定,"intent drift"被显著削弱。
为什么"两阶段 + 中间对象"会赢
值得给非论文读者留一段体会:SpecFirst 的解法之所以效果稳定,根本原因是它解决的是LLM Agent 已知的最弱一环——长程 planning。
LLM 在短 planning 上没问题,例如"先读 doc、再探测、再合成"5 步以内不会崩。但放到 30 步、50 步的循环里,意图漂移几乎一定出现,靠 reflection 去压制也不稳定。最经济的对策就是承认自己会漂,在 prompt 内部强制设置一个"锚点"——也就是结构化规约。两个 Agent 之间通过这份规约相互引用,不再依赖滚动上下文。结构化规约相当于一个外部长期记忆,把人类程序员在 IDE 里写下来"TODO / 假设 / 已确认"这种习惯,正式搬进 Agent pipeline。
另一个隐含好处:规约文档让 debug 容易十倍。任何模型合成失败,你都可以先读规约,看是哪一条规约被打脸,比在 30 步 trace 里找根因强太多。
亮点与局限
亮点:
- 把经典"需求优先"重新做成 Agent 形态,比"塞一段系统提示要求它先想清楚"靠谱得多——它把规约当作一个对象来操作,而不是一段话。
- 适用场景广:从零写 CLI / 算法题 / 黑盒游戏 / 工具脚本都自然适配,因为只要有"可执行的 oracle"就能跑。
- 弱模型相对吃到的提升更大,给出"小模型也能做难任务"的可行方案。
- 探测覆盖率与测试通过率双重提升,说明它不是靠"猜对",而是真的在探。
- 二阶段结构天然产出可审计、可解释的中间产物(结构化规约),落地成本极低。
局限:
- 只在 ProgramBench 上验证,未覆盖有图形界面、长程多文件、需要外部状态(如数据库、网络)等的更复杂合成任务。
- "可执行 oracle"是必备前提——若目标系统没有可直接执行的"行为金标",SpecFirst 退化回无 oracle 的代码生成。
- 阶段 A 的规约质量上限受限于 Spec Agent 的探测预算;预算给得少时,提升会缩水(原文未明确给出预算 vs 提升的曲线)。
- 阶段 B 的代码 Agent 仍可能出现"规约正确、实现错",论文对错误的归因分析粒度,原文 abstract 未明确给出。
- 跨域迁移性(不同 families 的模型差异)在 +6.9% 到 +21.3% 之间仍明显——说明规约质量与底模型能力耦合。
对工程落地的启发
- 任何"基于黑盒 oracle 的代码生成"任务都该考虑拆规约/合成两步——这条经验不只适用程序合成。
- 结构化中间产物是高 ROI 的设计:让 Agent 显式吐出一份可校验的 schema,比让它"保持一致地"长思考稳定得多。
- 弱模型 + 强结构 > 强模型 + 弱结构:SpecFirst 在弱模型上的相对提升更大,提示在算力受限团队里,与其追更强的模型,不如把 pipeline 做规整。
- 探测覆盖率指标应进入你的 Agent 评测库:只看最后通过率,会忽略"模型只是在猜"和"模型真的探到位"这两种本质不同的情况。
- 白板合成场景值得单独做产品:SWE-Agent / Devin 这类对"已有仓库"投入很多,"从零写一个完全黑盒的需求"反而没专门工具;SpecFirst 是一条可直接产品化的路径。
一个被低估的副产品:可审计的"中间文档"
SpecFirst 的实施副产品是 structure specification——它本质上是一份写得非常好的"我要做什么"。把它喂给下一个 Agent、下一个工程师、下一轮产品评审,可读性比"从长 reasoning 里挖意图"高一个量级。这件事在多 Agent 协同里非常值钱:让每一步都有一个明确可读的交接包,是工程团队减少踩坑的最朴素做法。SpecFirst 在论文里没说要做这件事,但它已经具备这种属性——你不需要"先做一个产品再考虑可审计",你只需要承认 Agent 之间的传递物也是产品的一部分。
与同方向工作的关系
- SWE-Agent、AutoCodeRover、Devin:聚焦"在已有代码库中修 bug / 加 feature",SpecFirst 走的是互补赛道。
- ProgramBench(基准本身):SpecFirst 是首个明确报告在该基准上做"两阶段"框架改进的工作(原文表述如此)。
- Reflexion / Self-Refine / CRITIC:反思类方法在"代码出来后做反思",SpecFirst 把反思前置到"代码出来前"——是对反思范式在时序上的重新分配。
- Classic requirements engineering(Zave & Jackson, 1997; Jackson, 1995):形式化方法里"先有规约再有实现"的传统,SpecFirst 把这条原则搬到 LLM Agent 时代并加上探测 oracle 的耦合。
- Program-of-Thought / Tool-Integrated Reasoning:与 CoT 这类"在解释中推理"不同,SpecFirst 把推理产物固化成结构化文档以便后阶段复用。
适合谁读
- 做 Agent 编程工具(Devin / SWE-Agent / Claude Code 类)的团队:评估是否要把"规约获取"纳入主流程。
- 内部工具 / 自动化产线负责人:在很多企业里"用户给一段自然语言 + 一段可执行代码",这种场景天然适配 SpecFirst。
- 形式化方法 / 需求工程背景的研究者:这是少见的把 RE 原则搬到 LLM Agent 里并量化的论文。
- Agent benchmark 设计者:把"规约质量"作为一个独立指标,可能是未来评测的新维度。
- 单模型选型工程师:如果你的内部 benchmark 显示"模型换了好几版通过率还是差不多",可能是 pipeline 上限而非模型上限——SpecFirst 提供了一种 pipeline 改进方案。
不确定处标记:原文 abstract 中"提升幅度随能力档位如何变化""规约阶段的 token / 探测 budget 与提升的曲线""阶段 B 中误读归因粒度"等未明确给出;具体数字以论文 v1 PDF 为准。
工程落地与核查(Jay)
事实核查
- ✅ ProgramBench 200 实例:ProgramBench 是 2026 年新出的白板合成 benchmark,与 SWE-Bench 并列但针对"从零合成"场景,GitHub 仓库(program-bench/program-bench)存在,数字可信。
- ✅ 测试通过率 +6.9%–21.3% / 覆盖率 +9.4%–18.5%:原文 abstract 明确提及,统计显著性有说明,可信。
- ✅ single-loop baseline 作为对照:方法论上合理——spec-first 确实是相对于"单循环混合"的差异化设计,对照成立。
- ✅ 弱模型提升更大的规律:从 +6.9% 到 +21.3% 的跨模型差异方向可信,但跨模型提升斜率未在 abstract 中明确。
- ⚠️ 代码未明确注明是否公开:解读未注明。落地前需确认 GitHub 仓库是否已公开,若代码未发布,两阶段 Agent 的实现细节(如规约 schema、coverage 判定逻辑)难以完整复现。
- ⚠️ "两族、横跨一个数量级能力"的四个模型:原文未明确是哪四个模型。工程引用时需确认具体模型名称,以评估该结论的可推广性。
工程落地三坑
坑 1:规约阶段探测预算决定上限
Spec Agent 的循环有 budget_not_exhausted 退出条件——探测预算直接决定规约覆盖率,进而决定代码合成的成功率。原文未给出预算与提升的曲线(原文 abstract 也承认这点)。生产部署必须把探测预算作为可配置参数,并根据任务复杂度分级设置,避免预算过低导致半成品规约流入合成阶段。
坑 2:规约 schema 的工程化成本被低估 结构化规约包含"输入域、输出域、约束、不变式、反例、边界"——这意味着 Spec Agent 必须输出 JSON/YAML 结构化数据,而不是纯文本。"不变式"和"约束"的提取尤其难——对 LLM 的结构化输出有强要求。建议先选一个具体规约 schema(如 OpenAPI 风格或 JSON Schema)作为标准模板,不要让 LLM 自由发挥格式。
坑 3:可执行 oracle 是强依赖,不是所有场景都有 SpecFirst 的核心假设是"有一个行为 oracle 可以反复跑"——这对 CLI 工具、算法题、游戏逻辑成立,但对 Web 界面、数据库交互、外部 API 调用等场景,oracle 可能不存在或成本极高。接入 SpecFirst 前必须先评估 oracle 的可用性;无 oracle 时,SpecFirst 退化为"先思考再写代码"的单阶段。
快速可跑命令
# 依赖(假设官方代码已发布)
git clone https://github.com/program-bench/specfirst.git
cd specfirst
# 查看规约 schema 定义
cat spec/spec_schema.json | python -m json.tool
# 阶段 A:运行 Spec Agent 生成规约
python -m specfirst.spec_agent \
--problem-dir ./problems/001 \
--oracle ./problems/001/oracle \
--doc ./problems/001/description.md \
--output ./specs/001.json \
--max-probes 50
# 阶段 B:规约驱动合成代码
python -m specfirst.code_agent \
--spec ./specs/001.json \
--oracle ./problems/001/oracle \
--output ./solutions/001/solution.py
# 端到端评测(ProgramBench 格式)
python -m specfirst.eval \
--problem-dir ./program-bench/ \
--method specfirst \
--model gpt-4o
适用场景判断
| 场景 | 推荐程度 | 原因 |
|---|---|---|
| 算法题 / CLI 工具自动生成 | ⭐⭐⭐⭐⭐ | oracle 可完美构造,规约质量高 |
| 企业内部自动化脚本(Python/Shell) | ⭐⭐⭐⭐ | 有二进制或测试脚本做 oracle,天然适配 |
| Web/前端合成(浏览器自动化) | ⭐⭐ | oracle 构造困难(浏览器状态复杂),难以闭环验证 |
| 数据库 schema 生成 / SQL 合成 | ⭐⭐⭐ | 有 SQL 执行引擎可做 oracle,但 DDL 语义复杂 |
| 已有大型代码库中的 feature 开发 | ⭐ | 完全不适用,这是白板合成赛道 |
| 开放域对话 / 非结构化任务 | ⭐ | 没有 oracle,SpecFirst 无法运行 |