先把仓库改造成 Agent 能干活的地方:Harness 的作用
先把仓库改造成 Agent 能干活的地方:Harness 的作用
本文是「AI 编程铁三角」系列的第一篇。
铁三角由三层构成,各管一件事:Harness 管工程环境——让 Agent 在一个可理解、可验证、可约束的仓库里工作;OpenSpec 管需求规格——把模糊需求变成 Agent 无法误读的可执行规格;Superpowers 管执行流程——把编码过程拆成小步,每步留证据。三者不是三个工具选一个用,而是「规范—执行—验证」的闭环。
本篇只讲第一件事:为什么不能先装 AI 工具再摸索,以及怎么把仓库变成 Agent 真正能干活的地方。
一、先问一个问题:你的仓库,Agent 看得懂吗
很多团队上 AI Coding 的顺序是反的:先装工具,再让开发者自行摸索。结果是每个人用法不同,Agent 反复猜测构建方式和目录边界,最终形成大量不可复用的对话。
对 Agent 而言,看不到的工程事实等于不存在。仓库里必须有一套稳定、可执行的"最短路径":
- 如何初始化
- 如何编译
- 如何运行单元测试
- 如何执行静态分析
- 如何在目标板部署
- 哪些目录属于生成物
- 哪些文件严禁修改
这些不是文档里的散文,而是 Agent 一条命令就能跑出来、并能据此判断"我现在能不能开始干活"的事实。没有这套基线,Agent 就会在错误分支、脏工作区或过期构建结果上继续工作,并把工程风险放大。
二、Harness 的五层上下文
Harness 不是一份 AGENTS.md,而是分层的上下文体系。从稳定到易变,大致分五层:
- 组织级:安全红线、编码规范、合规要求。稳定,适合版本化管理。
- 仓库级:仓库用途、构建入口、禁止修改目录。稳定。
- 模块级:模块所有权规则、热路径约束、并发模型。半稳定。
- 任务级:本次变更的规格、允许修改范围、审批点。随变更更新。
- 动态上下文:当前分支、未提交修改、基线测试、工具链版本、目标板状态。每次任务前由脚本自动生成。
组织级和仓库级内容稳定,适合版本化管理;任务级和动态上下文随变更更新,应由脚本自动生成,避免人工抄写过期信息。
三、指令文件:一份源,多入口
不同 Agent 对项目指令文件的名称和加载规则不同:Codex 用 AGENTS.md,Claude Code 用 CLAUDE.md 和目录级 rules。企业落地时不应维护两套互相矛盾的内容。
推荐做法:以一份平台无关的 ENGINEERING_GUIDE.md 为源,再通过软链接、生成脚本或精简映射同步到各工具入口。判断是否落地成功,只看三类职责是否完整,不看工具名字是否一致。
仓库级 AGENTS.md 的骨架大致长这样(以一个含控制面/数据面分层的系统级项目为例,字段可按实际仓库替换):
# AGENTS.md(仓库级示例)
## Repository purpose
本仓库用于系统级软件开发,包含 controlplane、dataplane、platform 和 tests。
## Mandatory workflow
1. 修改前读取本文件、目标模块的 AGENTS.override.md 和对应 OpenSpec 变更。
2. 先运行 scripts/context.sh,确认分支、基线测试和工具链。
3. 新增或修复行为必须先提交失败测试;不能主机测试的内容必须说明原因并提供替代证据。
4. 不得修改 third_party、generated、sdk/vendor;确需修改必须等待人工审批。
5. 每次完成任务必须执行 scripts/verify_changed.sh,并在报告中列出命令与返回码。
## Critical constraints
- 数据面热路径禁止动态内存分配、阻塞 I/O 和无采样日志。
- 所有网络长度字段在加减乘前完成上界与溢出检查。
- 跨线程对象必须声明所有权和同步方式。
- 不得改变持久化配置格式、HA 协议和对外 API,除非 design.md 已明确。
有效指令的关键是短、具体、可验证。"代码要高质量"几乎没有约束力;"所有网络长度字段在计算前检查,新增解析器必须通过 fuzz_parser 语料 10 分钟且 ASan/UBSan 无报告"才是可以执行的规则。
四、权限:默认拒绝,最小授权
Coding Agent 通常具备读文件、写文件、执行 Shell、访问网络和调用外部工具的能力。源代码、漏洞信息、私有 SDK、签名密钥和客户数据都可能属于敏感资产。
权限设计的原则是默认拒绝、按任务最小授权:
- 敏感目录由文件权限和 Agent ignore 共同保护
- 外发流量经过 API 网关和 DLP
- 执行环境使用容器或受限用户
- 危险命令由 PreToolUse/Hook 阻断
- 审计日志关联用户、角色、阶段和场景
仅靠员工承诺不能构成保护。安全策略必须落到技术控制上。
五、Hooks:把"建议"变成"无法绕过的门禁"
Harness 的价值在于把"建议"变成"无法绕过的门禁"。三类 Hook 职责不同:
- Agent Hook(PreToolUse/PostToolUse):防止即时危险动作,例如阻止写入
third_party/。 - Git Hook:提交前检查格式、敏感信息、禁止修改路径,提前反馈。
- CI:合并前完成独立验证,提供可信的最终结果。
门禁可以分阶段执行:开发早期跑增量和主机侧检查,合并前再跑多配置构建、目标板、性能和回归。
一个可复用的增量验证脚本长这样:
#!/usr/bin/env bash
# scripts/verify_changed.sh
set -euo pipefail
BASE=${BASE_REF:-origin/main}
CHANGED=$(git diff --name-only "$BASE"...HEAD)
echo "[1/5] formatting"
clang-format --dry-run --Werror $(echo "$CHANGED" | grep -E '\.(c|h|cc|cpp|hpp)$' || true)
echo "[2/5] host build"
cmake --preset host-debug
cmake --build --preset host-debug -j
echo "[3/5] unit tests"
ctest --preset host-unit --output-on-failure
echo "[4/5] static analysis"
scripts/run_clang_tidy_changed.sh "$BASE"
echo "[5/5] policy checks"
scripts/check_forbidden_changes.sh "$BASE"
这个脚本的意义不是"跑一遍",而是让 Agent 在每次任务结束时必须列出命令与返回码,把验证变成可复查的证据。
六、动态上下文:让 Agent 看见"当前事实"
静态指令描述长期规则,动态上下文描述"当前事实"。Agent 开始任务前应自动生成 CONTEXT.md 或 JSON,内容包括:
- 当前分支、HEAD
- 未提交修改
- 基线测试是否通过
- 编译器和 SDK 版本
- 目标板状态
- 最近失败
- 本次允许修改的文件
一个最小可用的生成脚本:
#!/usr/bin/env bash
# scripts/context.sh
set -e
{
echo "# Dynamic Context"
echo "generated_at: $(date -Iseconds)"
echo "branch: $(git branch --show-current)"
echo "head: $(git rev-parse --short HEAD)"
echo "dirty_files:"
git status --short | sed 's/^/ - /'
echo "compiler: $(clang --version | head -1)"
echo "toolchain: ${TARGET_TOOLCHAIN:-unknown}"
echo "baseline_unit_test:"
ctest --preset host-unit --output-on-failure && echo " status: pass" || echo " status: fail"
} > .ai/CONTEXT.md
这一步看似简单,却能挡掉一类高频错误:Agent 在错误分支、脏工作区或基线已坏的情况下继续"努力工作"。
七、熵管理:Harness 也会退化
Harness 不是一次建好就永远有效。长期使用后会出现退化:
- 指令越来越长
- 同一规则重复出现
- 测试变慢
- 忽略项累积
- Agent 频繁犯同类错误
建议的维护节奏:
- 每个迭代:对 Harness 做一次小维护,去重、补漏、收紧。
- 每季度:做一次系统审计,评估指令有效性、门禁覆盖率和 Agent 错误模式。
熵管理不是"打扫卫生",而是保证 Harness 持续约束 Agent 行为的能力。
八、小结:Harness 先行的真正含义
Harness 先行,不是"先写文档再写代码",而是先把仓库变成 Agent 可理解、可验证、可约束的工程,再开始批量使用。
判断 Harness 是否到位,可以问三个问题:
- Agent 一条命令能否拿到当前分支、基线测试和工具链版本?
- Agent 试图修改
third_party/或改变对外 API 时,会不会被自动阻断? - 每次任务结束时,Agent 能不能列出验证命令和返回码,而不是用"代码看起来正确"交差?
三个都能答"是",Harness 才算到位。这时再进入下一篇的 OpenSpec,规格才有意义——因为 Agent 已经在一个可约束的环境里读规格、写测试、跑验证。
下一篇,我们讲怎么把模糊需求变成 Agent 无法误读的可执行规格。系列最后一篇,会把三层合起来看它们如何共同构成 AI 编程的完整闭环。
更多推荐



所有评论(0)