Harness Engineering 最佳实践:从概念到落地的完整操作手册
Harness Engineering 最佳实践从概念到落地的完整操作手册本文是 Harness Engineering 上篇 的续篇。上篇解读了 OpenAI 的方法论——什么是 Harness Engineering、核心理念、五大工程实践和哲学内核。本篇不再重复概念直接进入实操怎么在你自己的项目中落地 Harness Engineering用什么工具踩什么坑有哪些可以直接抄的模板。一、落地路线图三步走在动手之前先画清楚路线。Harness Engineering 的落地不是一把梭而是渐进式的Phase 1: 信息层1-2天 Phase 2: 约束层3-5天 Phase 3: 自动化层1-2周 ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐ │ AGENTS.md 地图模式 │ → │ 分层架构 Linter │ → │ Agent 自验证闭环 │ │ docs/ 结构化文档 │ │ CI 约束检查 │ │ 后台清理 Agent │ │ 编码规范文档化 │ │ 错误信息含修复指令 │ │ CDP/截图自动验证 │ └───────────────────┘ └───────────────────┘ └───────────────────┘ 适合所有项目 适合中期项目 适合长期维护项目 收益Agent 输出一致性 ↑ 收益代码质量可控 收益人工审查量 ↓↓↓不要一步到位。很多人失败就在于想一次性搭完所有基础设施。Phase 1 已经能带来显著提升Phase 2 是质变点Phase 3 是锦上添花。二、Phase 1信息层——让 Agent 看得懂你的项目2.1 AGENTS.md写地图不写百科全书上篇提到 OpenAI 用地图模式替代超长指令文件。这里给出可以直接拷贝使用的模板。反面教材别这么写# ❌ 错误示范把所有内容塞进一个文件 我们使用 React 18 TypeScript 5.3 Next.js 14... 组件命名使用 PascalCase函数用 camelCase... 数据库用 PostgreSQLORM 用 Prisma... 后面还有 500 行问题挤占上下文窗口、难以维护、Agent 很难定位需要的信息。正确做法直接用# AGENTS.md ## 项目简介 [一句话] 这是一个面向中小企业的在线项目管理平台基于 Next.js PostgreSQL。 ## 快速导航 | 你想做什么 | 去哪里看 | |-----------|---------| | 了解系统架构 | docs/architecture/overview.md | | 了解模块边界和依赖规则 | docs/architecture/boundaries.md | | 了解编码规范 | docs/conventions/README.md | | 了解当前迭代任务 | docs/plans/current-sprint.md | | 了解 API 规范 | docs/reference/api-spec.yaml | | 了解错误码 | docs/reference/error-codes.md | | 了解测试规范 | docs/conventions/testing.md | ## 硬性规则必须遵守CI 会验证 1. 依赖方向types/ → config/ → repo/ → service/ → runtime/ → ui/ 2. 横切关注点auth/log/telemetry只能通过 Provider 注入 3. 单文件不超过 300 行 4. 新增代码必须有对应测试 5. 使用结构化日志禁止 console.log ## 提交规范 - feat: 新功能 - fix: 修复 - refactor: 重构 - docs: 文档 - test: 测试关键设计原则AGENTS.md 控制在 50-100 行。超过就说明你在写百科全书了**“你想做什么 → 去哪里看”**比这是什么更有效——面向任务而非面向知识硬性规则单独列出这些是 CI 会强制验证的不是建议2.2 docs/ 目录结构化知识库docs/ ├── architecture/ # 稳定层很少变 │ ├── overview.md # 系统架构图 一段话描述 │ ├── boundaries.md # 模块边界和依赖规则 │ └──>--- last_updated: 2026-03-28 status: active # active | deprecated | draft owner: zhangsan ---这样 doc-gardening Agent 可以自动扫描过期文档。2.3 设计文档模板Agent 执行复杂功能前先写设计文档。以下是模板# Feature: [功能名称] ## Status: Draft | Approved | In Progress | ✅ Implemented ## 目标 一句话描述这个功能要解决什么问题。 ## 非目标 明确列出这次不做什么防止 Agent 扩大范围。 ## 技术方案 ### 涉及的模块 - types/: 新增 XXX 类型定义 - service/: 新增 XXX 业务逻辑 - ui/: 新增 XXX 页面 ### 数据模型变更 sql -- 如有数据库变更写在这里API 变更POST /api/xxxRequest:{...}Response:{...}验收标准标准1具体的、可验证的标准2具体的、可验证的测试覆盖率 ≥ 80%依赖依赖 feature-auth已实现 ✅**为什么要这么做**Agent 拿到一个功能需求后先填写这个模板或人工填写审批通过后再动手写代码。这就是明确意图的工程化实现。 --- ## 三、Phase 2约束层——让 Agent 不得不写好代码 ### 3.1 分层架构用 ESLint/Linter 锁死依赖方向 上篇讲了 Types → Config → Repo → Service → Runtime → UI 的六层架构。这里给出具体的 Linter 配置。 #### ESLint 配置TypeScript/JavaScript 项目 javascript // eslint.config.js export default [ { rules: { no-restricted-imports: [error, { patterns: [ { group: [../../repo/*, ../../repo], message: ❌ UI 层不能直接引用 Repo 层。\n✅ FIX: 通过 Runtime 层访问数据。\n See: docs/architecture/boundaries.md }, { group: [../../service/*, ../../service], message: ❌ UI 层不能直接引用 Service 层。\n✅ FIX: 通过 Runtime 层暴露的接口访问。\n See: docs/architecture/boundaries.md } ] }], no-console: [error, { allow: [warn, error] }], max-lines: [error, { max: 300, skipBlankLines: true, skipComments: true }], max-lines-per-function: [error, { max: 50, skipBlankLines: true, skipComments: true }] } } ];Go 项目用 go-architect 或自定义脚本#!/bin/bash# scripts/check-layer-deps.sh# 检查分层依赖方向ERRORS0# UI 层不能引用 Repo 层ifgrep-r.*\/repo./internal/ui/2/dev/null;thenecho❌ ERROR: ui/ 层直接引用了 repo/ 层echo✅ FIX: 通过 runtime/ 层的接口访问数据echo See: docs/architecture/boundaries.mdERRORS$((ERRORS1))fi# Repo 层不能引用 Service 层反向依赖ifgrep-r.*\/service./internal/repo/2/dev/null;thenecho❌ ERROR: repo/ 层反向引用了 service/ 层echo✅ FIX: 使用接口interface解耦依赖注入ERRORS$((ERRORS1))fiif[$ERRORS-gt0];thenecho发现$ERRORS个架构违规请修复后重试。exit1fiecho✅ 架构依赖检查通过Python 项目用 import-linter# .importlinter [importlinter] root_packages myapp [importlinter:contract:layers] name Layer Dependencies type layers layers myapp.ui myapp.runtime myapp.service myapp.repo myapp.config myapp.typespipinstallimport-linter lint-imports# CI 中运行3.2 自定义 Linter 规则错误信息即 Prompt这是 Harness Engineering 最有杠杆的实践之一。核心思路每条 Linter 报错都必须包含三要素——问题是什么、怎么修、去哪看文档。以 ESLint 自定义规则为例禁止直接使用fetch要求通过统一的 API Client// eslint-rules/no-raw-fetch.jsmodule.exports{meta:{type:problem,docs:{description:Disallow raw fetch(), use apiClient instead},messages:{noRawFetch:[❌ 禁止直接使用 fetch()。,✅ FIX: 使用统一的 API Client, import { apiClient } from /lib/api-client;, const data await apiClient.get(/endpoint);, See: docs/conventions/api-calls.md].join(\n)}},create(context){return{CallExpression(node){if(node.callee.namefetch){context.report({node,messageId:noRawFetch});}}};}};一个万能公式❌ [什么错了] ✅ FIX: [怎么改给出代码片段] See: [哪个文档有详细说明]Agent 看到这种报错不需要任何额外提示就能自动修复。你写的每一条 Linter 规则本质上都是一个自动触发的 Prompt。3.3 CI 管线配置完整的 Agent 护栏# .github/workflows/agent-guardrails.ymlname:Agent Guardrailson:[pull_request]jobs:quality-gates:runs-on:ubuntu-lateststeps:-uses:actions/checkoutv4-uses:actions/setup-nodev4with:node-version:20-name:Install dependenciesrun:npm ci# ── Gate 1: 类型检查 ──-name:TypeScript Checkrun:npx tsc--noEmit# ── Gate 2: Linter含自定义规则──-name:Lintrun:npm run lint# ── Gate 3: 单元测试 ──-name:Unit Testsrun:npm test----coverage# ── Gate 4: 覆盖率阈值 ──-name:Coverage Thresholdrun:|COVERAGE$(npx nyc report --reportertext-summary | grep Lines | awk {print $3} | tr -d %) if (( $(echo $COVERAGE 80 | bc -l) )); then echo ❌ 代码覆盖率 ${COVERAGE}% 80% echo ✅ FIX: 为新增代码添加测试 exit 1 fi# ── Gate 5: 架构约束 ──-name:Architecture Checkrun:bash scripts/check-layer-deps.sh# ── Gate 6: 文件大小检查 ──-name:File Size Checkrun:|find src/ -name *.ts -o -name *.tsx | while read f; do lines$(wc -l $f) if [ $lines -gt 300 ]; then echo ❌ $f 有 $lines 行上限 300 echo ✅ FIX: 拆分为更小的模块将辅助函数移至 utils/ exit 1 fi done# ── Gate 7: 文档新鲜度 ──-name:Doc Freshnessrun:|find docs/design/ -name *.md | while read f; do last_mod$(git log -1 --format%ct $f) now$(date %s) days_old$(( (now - last_mod) / 86400 )) if [ $days_old -gt 60 ]; then echo ⚠️ $f 已 ${days_old} 天未更新可能已过期 fi done3.4 把主观品味翻译成机械规则这是 Phase 2 中最需要花时间的部分——把团队的代码审美变成 CI 能检查的规则。团队口头约定机械化规则实现方式“函数要短”单函数 ≤ 50 行max-lines-per-function“文件要短”单文件 ≤ 300 行max-lines“别用 any”禁止 TypeScriptanytypescript-eslint/no-explicit-any“日志要规范”禁止console.logno-console“API 调用要统一”禁止裸fetch()自定义规则no-raw-fetch“错误要有上下文”Error 必须包含 code 字段自定义规则“组件要纯”UI 组件不能直接调数据库no-restricted-imports“测试要充分”覆盖率 ≥ 80%CI coverage check经验法则如果一条规则在 Code Review 中被提过 3 次以上就应该写成 Linter 规则。四、Phase 3自动化层——让 Agent 自我验证和自我修复4.1 后台清理 Agent定时任务模板以下是一个实用的代码卫生清理 Prompt可以配合任何 Agent 工具Claude Code、Cline、Aider定期执行# 任务代码库卫生清理 请执行以下检查对每个发现的问题生成独立的修复 PR ## 检查清单 1. **超长文件**找出 src/ 下超过 300 行的 .ts/.tsx 文件拆分为更小模块 2. **缺失测试**找出 src/ 下没有对应 .test.* 文件的模块补充基础测试 3. **未使用的 import**清理所有未使用的 import 语句 4. **TODO/FIXME**列出所有 TODO 和 FIXME如果超过 30 天未处理则生成清理 PR 5. **重复代码**找出高度相似的代码段10行提取为共享工具函数 6. **过时文档**检查 docs/design/ 中状态为 Draft 但已超过 30 天的文档 ## 约束 - 每个修复作为独立 PR不要混在一起 - 每个 PR 修改后必须确保所有测试通过 - PR 标题格式chore(cleanup): [具体描述] - 如果不确定某个修改是否安全跳过并在 PR 中标注原因4.2 Git Worktree 自动化脚本让 Agent 在隔离环境中验证自己的代码#!/bin/bash# scripts/agent-verify.sh# 为指定 PR 分支创建隔离验证环境BRANCH$1WORKTREE_DIR/tmp/agent-verify-$(date%s)echo 创建 worktree:$WORKTREE_DIRgitworktreeadd$WORKTREE_DIR$BRANCHcd$WORKTREE_DIRecho 安装依赖...npmci--silentecho 运行类型检查...npx tsc--noEmit||{echo❌ 类型检查失败;exit1;}echo 运行 Linter...npmrun lint||{echo❌ Lint 失败;exit1;}echo 运行测试...npmtest||{echo❌ 测试失败;exit1;}echo 启动应用验证...npmrun devDEV_PID$!sleep10# 基础健康检查ifcurl-shttp://localhost:3000/api/health|grep-qok;thenecho✅ 健康检查通过elseecho❌ 应用启动失败或健康检查未通过kill$DEV_PID2/dev/nullexit1fikill$DEV_PID2/dev/nullecho 清理 worktree...cd-gitworktree remove$WORKTREE_DIRecho✅ 所有验证通过4.3 可观测性接入让 Agent 能看日志在本地开发环境部署一个轻量级的可观测性堆栈让 Agent 在排错时有据可查# docker-compose.observability.ymlversion:3.8services:# 日志Loki Promtailloki:image:grafana/loki:2.9.0ports:[3100:3100]promtail:image:grafana/promtail:2.9.0volumes:-./logs:/var/log/app-./promtail-config.yml:/etc/promtail/config.yml# 指标Prometheusprometheus:image:prom/prometheus:latestports:[9090:9090]volumes:-./prometheus.yml:/etc/prometheus/prometheus.yml# 可视化Grafanagrafana:image:grafana/grafana:latestports:[3001:3000]depends_on:[loki,prometheus]Agent 排错时可以用这样的 Prompt应用在 /api/users 端点返回 500 错误。 请查看 Loki 日志http://localhost:3100中最近 5 分钟的错误日志 找出根因并修复。修复后重新运行对应的测试验证。五、开源工具推荐按落地阶段选择5.1 工具全景图┌─────────────────────────────────┐ │ 你的项目代码仓库 │ └─────────────┬───────────────────┘ │ ┌───────────────────────┼───────────────────────┐ │ │ │ ┌─────────▼─────────┐ ┌─────────▼─────────┐ ┌─────────▼─────────┐ │ Phase 1: 信息层 │ │ Phase 2: 约束层 │ │ Phase 3: 自动化层 │ │ │ │ │ │ │ │ • AGENTS.md │ │ • ESLint 自定义规则 │ │ • Git Worktree │ │ • docs/ 结构 │ │ • import-linter │ │ • CDP / Playwright │ │ • Aider Repo Map │ │ • CI 管线 │ │ • Loki/Prometheus │ └────────────────────┘ └────────────────────┘ └────────────────────┘ │ │ │ └───────────────────────┼───────────────────────┘ │ ┌─────────────▼───────────────────┐ │ Agent 工具选一个 │ │ │ │ Aider │ Cline │ Claude Code │ │ │ OpenHands │ Cursor │ Codex │ └───────────────────────────────────┘5.2 Agent 工具对比与选型工具Stars类型最适合的场景Harness 友好度Aider30kCLI 结对编程个人开发者终端党⭐⭐⭐⭐⭐Cline40kVS Code Agent小团队需要 Plan/Act 模式⭐⭐⭐⭐Claude Code-CLI Agent深度自主任务6h连续工作⭐⭐⭐⭐⭐OpenHands50k平台团队级部署需要沙箱隔离⭐⭐⭐⭐⭐SWE-agent15kCLI Agent自动修复 GitHub Issue⭐⭐⭐Superpowers127k技能框架强制 TDD 子 Agent 模式⭐⭐⭐⭐⭐怎么选个人项目想快速体验→ Aider。30 分钟上手Repo Map 天然实现渐进式披露自动 lint test 构成反馈回路。pipinstallaider-chatcdyour-projectaider--modelgpt-4o团队项目需要流程控制→ Cline Superpowers。Plan/Act 模式让你审批 Agent 的计划再执行Superpowers 强制 TDD。# VS Code 中安装 Cline 扩展# 然后在 Claude Code 中安装 Superpowersclaude /plugininstallsuperpowersclaude-plugins-official生产级需要完全隔离→ OpenHands。Docker 沙箱确保 Agent 操作不影响主环境模型无关。pipinstallopenhands-ai openhands--modelgpt-4o5.3 Superpowers 深度解析Superpowers 值得单独讲因为它是目前 Harness Engineering 思想最完整的开源实现。核心流程┌──────────────────────────────────────────────────────┐ │ 1. Brainstorming │ │ 苏格拉底式追问确保需求清晰 │ │ 你说的 X 功能是指...? 有没有考虑过 Y 方案? │ ├──────────────────────────────────────────────────────┤ │ 2. Git Worktree │ │ 自动创建隔离分支不污染主分支 │ ├──────────────────────────────────────────────────────┤ │ 3. Writing Plans │ │ 拆解为 2-5 分钟的微任务清单 │ │ 每个任务有明确的输入/输出/验收标准 │ ├──────────────────────────────────────────────────────┤ │ 4. Subagent-Driven Development │ │ 每个微任务分配独立子 Agent │ │ 天然避免上下文污染和任务干扰 │ ├──────────────────────────────────────────────────────┤ │ 5. Test-Driven Development强制 │ │ RED → GREEN → REFACTOR │ │ ⚠️ 如果 Agent 先写代码再写测试代码会被删除 │ ├──────────────────────────────────────────────────────┤ │ 6. Code Review │ │ 自动按规范检查代码质量 │ ├──────────────────────────────────────────────────────┤ │ 7. Finishing Branch │ │ 验证所有测试通过 → 合并 → 清理 worktree │ └──────────────────────────────────────────────────────┘杀手特性——强制 TDD大多数 Agent 工具的问题是 Agent 会先写实现再补测试甚至跳过测试。Superpowers 用一个极端手段解决这个问题如果检测到 Agent 在测试之前写了实现代码直接删除那段代码强制从测试开始。这听起来激进但效果显著测试先行确保了每一段代码都有验证这正是 Harness Engineering “Verify” 环节的核心。5.4 学习资源资源类型适合谁链接deusyu/harness-engineeringGitHub 学习指南从零入门GitHubharness-engineering.ai知识图谱883 实体快速了解生态全貌WebsiteOpenAI 原文博客理解原始思想OpenAI六、实战案例从零搭建一个 Harness 环境30 分钟以一个 Next.js 项目为例走完 Phase 1 Phase 2 的核心步骤。Step 1初始化项目结构5 分钟# 创建 docs 目录结构mkdir-pdocs/{architecture,conventions,design,plans,reference}# 创建 AGENTS.mdcatAGENTS.mdEOF # AGENTS.md ## 项目简介 这是一个任务管理 Web 应用基于 Next.js 14 PostgreSQL Prisma。 ## 快速导航 | 你想做什么 | 去哪里看 | |-----------|---------| | 了解系统架构 | docs/architecture/overview.md | | 了解编码规范 | docs/conventions/README.md | | 了解当前任务 | docs/plans/current-sprint.md | ## 硬性规则 1. 依赖方向types/ → lib/ → services/ → app/ 2. 禁止 console.log使用结构化日志 3. 单文件 ≤ 300 行 4. 新功能必须有测试 5. API 调用使用统一的 apiClient EOFStep 2写架构文档5 分钟catdocs/architecture/overview.mdEOF# 系统架构## 分层结构src/├── types/ # 纯类型定义不依赖任何层├── lib/ # 工具函数和基础设施只依赖 types/│ ├── api-client.ts│ ├── logger.ts│ └── providers.ts├── services/ # 业务逻辑依赖 types/ 和 lib/├── app/ # Next.js 路由和页面依赖所有层└── components/ # UI 组件只依赖 types/ 和 lib/providers## 依赖规则 - types/ → 不依赖任何层 - lib/ → 只依赖 types/ - services/ → 依赖 types/ 和 lib/ - components/ → 依赖 types/ 和 lib/providers - app/ → 可以依赖所有层 EOFStep 3配置 Linter 约束10 分钟# 在 eslint.config.js 中添加自定义规则cateslint.config.custom.jsEOF // 自定义 Harness 规则 module.exports { rules: { // 禁止 UI 组件直接引用 services no-restricted-imports: [error, { patterns: [{ group: [../../services/*, ../services/*, /services/*], importNames: undefined, message: ❌ 组件层不能直接引用 Service 层。\n✅ FIX: 在 app/ 路由中调用 service通过 props 传递数据给组件。\n See: docs/architecture/overview.md }] }], no-console: [error, { allow: [warn, error] }], max-lines: [error, { max: 300, skipBlankLines: true, skipComments: true }] } }; EOFStep 4配置 CI8 分钟mkdir-p.github/workflowscat.github/workflows/harness-checks.ymlEOF name: Harness Checks on: [pull_request] jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-nodev4 with: { node-version: 20 } - run: npm ci - run: npx tsc --noEmit - run: npm run lint - run: npm test -- --coverage --passWithNoTests - name: File size check run: | find src/ -name *.ts -o -name *.tsx | while read f; do lines$(wc -l $f) if [ $lines -gt 300 ]; then echo ❌ $f: $lines lines (max 300) echo ✅ FIX: Split into smaller modules exit 1 fi done EOFStep 5验证2 分钟让 Agent 执行一个简单任务验证 Harness 是否生效任务在 services/ 中添加一个 getUserById 函数。 要求有类型定义、错误处理、单元测试。 预期 ✅ Agent 在 types/ 中定义 User 类型 ✅ Agent 在 services/ 中实现函数 ✅ Agent 写了对应测试 ❌ 如果 Agent 在 components/ 中直接 import services/Linter 报错 ❌ 如果文件超 300 行Linter 报错七、踩坑指南我们犯过的错7.1 AGENTS.md 写太长症状Agent 的输出质量反而下降了经常忽略部分规则。原因上下文窗口被指令文件占满留给正事的空间不够。解法砍到 50-100 行。如果超过把内容移到 docs/ 并在 AGENTS.md 中只留链接。7.2 Linter 规则太多Agent 陷入死循环症状Agent 修了一个 Linter 错误引入了另一个反复循环。原因规则之间有冲突或者修复建议不够具体。解法逐条添加 Linter 规则每加一条都让 Agent 试跑一遍确保每条规则的 FIX 信息给出具体代码片段而不是模糊的建议互相冲突的规则只保留一条7.3 架构约束太严阻碍合理的跨层调用症状某些合理的代码模式被 CI 拦截团队开始绕过规则。解法设置豁免白名单机制在特定目录或文件中可以显式声明例外定期回顾约束规则根据实际开发需要调整// eslint-disable-next-line no-restricted-imports -- 此处需要直接访问 repo 层原因见 #PR-234import{dbClient}from/repo/client;7.4 Doc-gardening 没人管文档比不写还误导症状Agent 参考了过时文档写出的代码基于错误的假设。解法在 CI 中加文档新鲜度检查见上面 3.3 节的 CI 配置每两周跑一次 doc-gardening Agent设计文档加status字段过期的标记为deprecated7.5 过度依赖 Agent忘了审查环境症状Agent 产出质量下降团队没有及时发现。解法每周花 30 分钟做一次环境审查最近一周的 CI 失败率是否上升Linter 规则是否覆盖了新出现的 bad pattern有没有新的架构约束需要加AGENTS.md 和 docs/ 是否跟代码库一致八、总结Harness Engineering 落地清单□ Phase 1: 信息层 □ 创建 AGENTS.md50-100 行地图模式 □ 建立 docs/ 结构化目录 □ 编写架构文档 编码规范文档 □ 设计文档模板含 Status 标记 □ Phase 2: 约束层 □ 配置分层架构的 Linter 规则 □ 每条 Linter 错误包含 ❌问题 ✅修复 文档 □ CI 管线类型检查 Lint 测试 覆盖率 架构约束 □ 把团队口头约定翻译成机械规则 □ Phase 3: 自动化层可选长期项目推荐 □ Git Worktree 隔离验证脚本 □ 后台清理 Agent 定时任务 □ 可观测性堆栈日志 指标 □ 文档新鲜度自动检查 □ 持续维护 □ 每周 30 分钟环境审查 □ 每月回顾并更新 Linter 规则 □ 每两周运行 doc-gardening Agent记住Harness Engineering 的核心不是搭建复杂的基础设施而是一个简单的闭环——约束 → 告知 → 验证 → 纠正。从 AGENTS.md 和一条 Linter 规则开始比什么都不做强一百倍。参考资料上篇Harness Engineering当人类不再写代码软件工程反而更工程了OpenAIHarness engineering: leveraging Codex in an agent-first worldSuperpowers — Agent 技能框架127k ⭐OpenHands — AI 软件开发平台50k ⭐Aider — 终端 AI 结对编程30k ⭐Cline — VS Code Agent40k ⭐SWE-agent — 自主修复 Agent15k ⭐deusyu/harness-engineering — 学习指南310 ⭐harness-engineering.ai — 知识图谱883 实体