让 Agent 在每次工作会话前先完成初始化:独立初始化阶段的设计与落地(learn-harness-engineering 课程 06 深度解析)
【免费下载链接】learn-harness-engineeringHarness engineering beginner tutorial, from 0 to 1项目地址: https://gitcode.com/gh_mirrors/le/learn-harness-engineering
导读:本指南围绕 learn-harness-engineering 仓库中课程 06「为什么初始化必须拥有独立阶段」展开,核心论点是:Agent 初始化与功能实现是两种优化目标完全不同的工作,混在一起只会两败俱伤。你将学会什么是 Bootstrap Contract(启动就绪契约)、为什么要用「独立初始化阶段 + 模板化起步」替代「边干活边搭环境」,以及如何在仓库中以
init.sh、feature_list.json、session-handoff.md等产物落地一整套可验证的初始化流程。
一、问题的起点:20 分钟写代码,40 分钟在"搞懂项目怎么跑"
打开一个新会话,对 Agent 说"加一个搜索功能"。它立刻扑进代码里——热情可嘉。20 分钟后它发现测试框架根本没配好,花 10 分钟补上;又发现数据库迁移脚本格式不对,再调一阵子。功能最终加上了,但整场会话的效率惨不忍睹:大部分时间花在"搞清楚这个项目到底怎么运作"上,而不是写搜索功能本身。
更糟的是这种混乱会传染给后续会话:
本课程的核心结论:在让 Agent 开始干活之前,先用一个独立阶段把基础环境准备好、把验证命令跑通、把项目结构摸清。就像盖房子——你不会一边浇地基一边砌墙,地基没干就砌墙,整栋楼都得推倒重来。先浇地基、等它干透、再砌墙,干净又高效。
二、为什么要分开:两类工作的优化目标根本不同
初始化与实现是两种优化目标完全相反的工作:
- 实现阶段优化的是:最大化"已验证功能"的数量与质量;
- 初始化阶段优化的是:最大化"后续所有实现"的可靠性与效率。
把两者混在一起,Agent 面对的是一个多目标优化问题——同时要搭基础设施、又要写功能代码。在没有显式优先级的情况下,Agent 天然会倾向写代码(因为这是立即可见的产出),而牺牲基础设施(因为它的价值要到后续会话才显现)。就像要求施工队同时浇地基和砌墙,他们多半会抢先去砌墙——墙看得见、能展示。但地基差的房子,后面一定会出系统性大问题。
三、混在一起的四个代价
3.1 基础设施"没有干透"
最直接的问题:Agent 把 80% 的精力花在功能代码上,只用 20% 草草配置基础设施。测试框架配了但从未验证,lint 规则设了但过于宽松,没有任何进度文件。这些缺陷在第一会话不明显(因为 Agent 还记得自己干过什么),但在第二会话全部爆发——新 Agent 不知道如何启动、如何测试、进展到哪了。地基潦草,楼就不稳。
3.2 "未经验证的积累":返工的地雷
更隐蔽的代价是未验证的代码堆积。在测试框架配好之前写的功能代码,属于"没有验证"的代码。等你终于回头给这些代码补测试时,可能发现设计从一开始就是错的——如果早知如此,当初会采用完全不同的实现。就像在还没干的水泥上贴瓷砖,等发现地面不平,所有瓷砖都得撬掉重贴。
3.3 会话预算被白白烧掉
初始化工作(配置环境、搭测试、理解项目结构)会消耗大量上下文预算,留给真正功能实现的就少了。结果:第一会话只完成一半功能,第二会话还得从头理解项目。预算花在了地基上,但地基也没建好——两头落空。
3.4 隐性假设的地雷:没人记录的决策会互相打架
最容易被忽视的问题。Agent 在初始化期间做的决策——选哪个测试框架、目录怎么组织、依赖怎么管理——如果没有显式记录,后续会话就无法理解这些选择。更糟的是后续会话可能做出矛盾决策:第一会话选了 Vitest,第二会话的 Agent 不知道,引入了 Jest,两套测试框架共存,维护成本翻倍。
3.5 行业研究的佐证
- Anthropic关于长时运行 Agent 的研究明确建议将初始化与实现分离。其实验数据:使用独立初始化阶段的项目,在多会话场景下功能完成率比混合方式高 31%;且初始化阶段投入的时间在接下来的 3-4 个会话内被完全回收。
- OpenAI Codex的 harness engineering 指南强调"仓库即操作记录"(repository as operational record)原则:从第一次运行就建立清晰的操作结构,否则每个新会话都得重新推断项目约定。
四、核心概念速查表
| 概念 | 定义 | 关键点 |
|---|---|---|
| 初始化阶段(Initialization Phase) | Agent 生命周期的第一阶段 | 不做任何功能实现,只建立后续实现的全部前置条件;产出不是代码,而是基础设施 |
| 启动就绪契约(Bootstrap Contract) | 一个新 Agent 会话能够无歧义操作该项目的条件 | 四项全部必须满足:能启动、能测试、能看到进度、能接续下一步 |
| 冷启动 vs 热启动 | 冷启动从空目录开始,Agent 必须自行推断项目结构;热启动基于模板或已有项目,基础设施就位 | 热启动显著优于冷启动——相当于在有水电的工地上干活 vs 从荒地开始 |
| 随时可交接(Handoff Readiness) | 项目处于"任何时刻新 Agent 都能接手"的状态 | 不需要口头解释,只看仓库内容即可续工 |
| 首次验证时间(Time to First Verification) | 从项目开始到第一个功能点通过验证的时长 | 衡量初始化效率的核心指标 |
| 下游可用性(Downstream Usability) | 后续会话能在不依赖隐性知识的情况下成功执行任务的比例 | 衡量初始化质量的最佳指标 |
五、如何把初始化做对:五个产物 + 三项策略
5.1 把初始化当成一个独立阶段
第一会话只做初始化,不写任何业务功能代码。初始化产出五样东西:
产物 1:可运行的环境。项目能启动、依赖已安装、无环境问题。地基浇好,没有裂缝。
产物 2:可验证的测试框架。至少有一个示例测试通过——这证明测试框架本身配置正确,如同在地基上立起一根柱子,证明它能承重。
产物 3:启动就绪契约文档。用一份清晰文档告诉后续会话:
# Initialization Contract ## Start Commands - Install dependencies: `make setup` - Start dev server: `make dev` - Run tests: `make test` - Full verification: `make check` ## Current State - All dependencies installed and locked - Test framework configured (Vitest + React Testing Library) - Example test passing (1/1) - Lint rules configured (ESLint + Prettier) ## Project Structure - src/ — Source code - src/components/ — React components - src/api/ — API client - tests/ — Test files产物 4:任务拆解。把整个项目拆成有序任务列表,每个任务带清晰的验收标准:
# Task Breakdown ## Task 1: User Authentication Basics - Implement JWT auth middleware - Add login/register endpoints - Acceptance: pytest tests/test_auth.py all passing ## Task 2: User Profile Page - Implement user profile CRUD - Add profile edit form - Acceptance: pytest tests/test_profile.py all passing ## Task 3: Search Feature - ...产物 5:Git 提交作为检查点。初始化完成后提交一个干净的检查点(clean checkpoint),后续所有工作都从这个检查点出发。
5.2 热启动策略:别从空目录开始
不要从空目录起步。使用项目模板(create-react-app、fastapi-template 等)预置标准目录结构、依赖配置和测试框架,把通用初始化步骤"烘焙"进模板,只留下项目特有的初始化工作。相当于在有水电的工地上开工——比从荒地开始好上千倍。
5.3 初始化完成标准:不是代码量,而是四条契约
判定初始化是否完成,不看"写了多少代码",而看启动就绪契约的四个条件是否全部满足。用这份验收清单来验证:
## Initialization Acceptance Checklist - [ ] `make setup` succeeds from scratch - [ ] `make test` has at least one passing test - [ ] A new agent session can answer "how to run" and "how to test" from repo contents alone - [ ] Task breakdown file exists with at least 3 tasks - [ ] Everything committed to git六、仓库落地:本仓库里的初始化实践
以上方法论并非空谈——本仓库正是这套模式的活样本。
6.1 标准化的 init.sh:一次运行,全链路验证
skills/harness-creator/templates/init.sh展示了语言无关的通用初始化脚本。它按包管理器探测逻辑自动适配:检测pnpm-lock.yaml、yarn.lock、bun.lock等锁文件来选定包管理器(pnpm/yarn/bun/npm),随后依次执行check/typecheck/lint/test/build(存在对应 script 才执行)。对 Python 项目则运行pytest(并专门处理了 pytest 退出码 5——"未收集到测试"在全新项目中不算失败)与compileall语法检查;对 Go、Rust、Maven、Gradle、.NET 项目分别走go test ./...、cargo test、mvn test、./gradlew test、dotnet test。脚本结尾明确提示后续步骤:
Next steps: 1. Read feature_list.json to see current feature state 2. Pick ONE unfinished feature to work on 3. Implement only that feature 4. Re-run verification before claiming done而projects/project-03/solution/init.sh则是项目级初始化的实例:先npm install装依赖,再npm run check跑类型检查,最后npm run build构建,全部通过才输出=== Init complete. All checks passed. ===,并提示npm run dev启动应用。
6.2 初始化检查脚本:把"隐性失败"变成"显式报告"
docs/fr/lectures/lecture-06-why-initialization-needs-its-own-phase/code/init-check.ts是一个可以直接运行的示例(npx tsx <路径>/code/init-check.ts),它程序化地检查 8 项初始化前置条件:
| 检查项 | 类别 | 缺失时的后果 |
|---|---|---|
| Node.js 版本 >= 18 | Runtime | TypeScript 特性与内置 API 不可用 |
| package.json 存在 | Config | 无法安装依赖或运行脚本 |
| node_modules 已安装 | Dependencies | 所有 import 在运行时失败 |
TypeScript 可用(npx tsc --version) | Toolchain | 无法编译 TS 文件 |
| tsconfig.json 存在 | Config | 编译器走默认配置,可能不符项目需求 |
| 源码目录存在(src/lib/app) | Structure | Agent 找不到要修改的源文件 |
| 测试目录存在(test/tests/tests/spec) | Structure | Agent 找不到或无法运行现有测试 |
| Git 仓库已初始化 | Version Control | 无回滚能力、无变更历史 |
该脚本最精彩的部分是两场景模拟:simulateWithoutInit()跳过前置检查直接开工,逐个踩中缺失项,每踩一个按 200ms 计浪费时间,最终"工作尝试了但可能失败";simulateWithInit()则先跑完全部检查、把所有问题暴露在开工前。运行后会输出一份对比表,直观展示显式初始化阶段如何把问题消灭在浪费时间之前。
6.3 会话交接与进度追踪模板
skills/harness-creator/templates/session-handoff.md定义了会话交接文档的结构:当前目标(Goal/Status/Branch-commit)、本会话完成项、验证证据表(Check / Command / Result / Notes 四列)、变更文件、已做决策、阻塞项/风险,以及"下一会话启动"步骤——先读AGENTS.md,再读feature_list.json和progress.md,审阅交接文档,最后在编辑前运行./init.sh。
skills/harness-creator/templates/progress.md则提供进度日志模板:当前状态(最后更新时间、会话 ID、活动功能)、已完成/进行中/下一步、阻塞项、决策记录(含背景与备选方案)、本次修改的文件、完成证据(测试通过、类型检查干净、手动验证)、给下一会话的备注。
projects/project-03/solution/session-handoff.md是这些模板的真实应用——记录了元数据提取、文档分块、索引状态 UI、带引用的 grounded Q&A 等已完成工作,明确"每完成一个功能就验证并记录,再进入下一个",并列出决策(如"分块使用段落感知的按双换行符切分,避免截断句子")与所有修改过的文件。
6.4 初始化器输出清单
docs/fr/lectures/lecture-06-why-initialization-needs-its-own-phase/code/initializer-output-checklist.md给出了初始化器产出的自检清单:
- 是否存在规范的启动命令?
- 是否存在规范的验证命令?
- 是否存在第一个进度产物?
- 是否存在第一个稳定提交?
- 是否存在对后续会话可见的功能表面?
七、实例对比:混合式 vs 独立初始化
以 React 前端项目为例,对比两种初始化路径:
混合式(同时浇地基和砌墙):Agent 在会话 1 同时创建项目脚手架并实现第一个功能。会话结束时仓库里有可运行代码,但:没有 start/test 命令的显式文档、没有进度追踪文件、没有任务拆解。会话 2 花了约 20 分钟推断项目结构、测试框架和构建流程——就像新施工队进场,不知道地基进度、不知道管线走向,只能一个个挖洞去探。
独立初始化(先浇地基):会话 1 只做初始化——基于模板创建目录结构、配置测试框架(Vitest + React Testing Library)、编写并验证一个示例测试、创建启动就绪契约与任务拆解文件、提交初始检查点。会话 2 的重建时间不到 3 分钟,直接从任务清单开始干活——施工队到场,看一眼图纸,就知道该从哪接着干。
全项目周期对比:混合式在所有会话上的总重建时间比独立初始化方式高约 60%。初始化多花的 20 分钟,在后续会话中被多次回收。地基稳,墙才起得快——慢即是快。
八、关键要点
- 初始化与实现的优化目标不同——混在一起只会两败俱伤。先浇地基,再砌墙。
- 初始化的产出不是业务代码,而是基础设施:可运行环境、可验证测试、启动就绪契约、任务拆解。
- 用启动就绪契约的四条件验证初始化:能启动、能测试、能看到进度、能接续下一步。
- 热启动优于冷启动。用项目模板预置标准化基础设施。
- 初始化投入的时间在 3-4 个会话内完全回收。这不是额外成本,而是前置投资。
九、延伸阅读与动手练习
延伸阅读(均可在本仓库内继续深入):
- 课程 06 配套代码目录:初始化脚本、检查脚本与产出清单
- Lifecycle and Bootstrap Pattern:含分阶段 Bootstrap 序列与验证清单的模式文档
- Project 03. Multi-session continuity:本课程对应的实战项目
- Harness Creator 模板:init.sh、feature_list.json、progress.md、session-handoff.md
- Project 03 解决方案:含 init.sh 与 session-handoff.md 的完整落地实例
练习 1:启动就绪契约设计。为你正在开发的项目写一份完整的启动就绪契约。然后开启一个全新的 Agent 会话,只给它仓库内容(不给任何口头上下文),让它尝试启动项目、运行测试、理解当前进度。记录它遇到的每一个问题——每个问题都对应你契约中缺失的一条。
练习 2:对比实验。选一个中等复杂度的新项目。方案 A:让 Agent 同时进行初始化和第一次实现。方案 B:用一整个会话做独立初始化,第二会话开始实现。跑满 4 个会话后对比:首次验证时间、重建成本、功能完成率。
练习 3:初始化验收清单。为你的项目设计一份初始化验收清单。让一个新 Agent 会话逐项执行清单,记录哪些通过、哪些失败。失败项就是你的 harness 需要加固的地方。
【免费下载链接】learn-harness-engineeringHarness engineering beginner tutorial, from 0 to 1项目地址: https://gitcode.com/gh_mirrors/le/learn-harness-engineering
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考