前沿
Agent 的能力与不可控性成 正比
Claude Code 和 Codex CLI 已经能够在单个会话中出色的完成任务,从需求理解到代码实现、测试、部署的完整链路能力都早已具备。
这在提升个体开发效率方面的价值是正向的,这也是 OPC 盛行的原因之一。
但规模化引入团队后,情况开始分化。
比如这些很常见的现象:
- 小A 用 Claude Code 生成的代码风格与小B 完全不同;
- 有人习惯先写实现再补测试,有人确让 Agent 跳过测试直接提交;
- 同一个错误模式在不同模块里反复出现
很显然,这些情况不是因为 Agent 不够强,反而就是因为太强了,在没有约束的情况下,它会沿着各自的路径漫无边际的发散。

正文
一个案例
某后端小组全员引入 Claude Code 两个月后的审计结果:
风格碎片化
同一个模块中,开发者 A 的 Agent 使用 Guava Preconditions 做参数校验,B 的 Agent 使用 Spring Assert,C 的 Agent 使用 jakarta.validation 注解。
三种风格并存,没有对错之分,但维护者在三种心智模型间切换,同时也为后续的屎山堆积埋下伏笔。
测试覆盖率下降
Agent 写测试的速度远超人工,问题在于当开发者没有明确要求时,Agent 默认跳过测试。
阶段内新增 42 个接口,其中17 个完全没有任何单元测试。
而这些接口的 MR 全部通过了审查,因为审查者默认信任 Agent 写的代码。
密钥泄露
开发者在调试本地连接问题时,Agent 自行判断"需要一个有效密钥来完成验证",于是将一组测试环境密钥写入了 application-dev.yml。
文件随后被提交到仓库。
事后排查发现,没有人在 prompt 中要求 Agent 写入密钥,仅仅是 Agent 自主做了这个决定。
知识无法传递
开发者 D 花两个下午排查出 JPA 懒加载的跨线程问题(OpenSessionInView 在异步线程中失效),解决方案留在当次会话的上下文中。两周后开发者 E 遇到相同问题,再次从零排查------因为没有人知道这个问题已被解决。
这些问题可以归纳为四个维度:代码一致性、质量基线、过程可溯、知识沉淀。以下从理论和落地两个维度,给出每一层的具体方案。
五层治理体系总览
每一层解决一个具体维度的不可控问题,五层之间递进互补:
先理论,再落地,最后验证,我们统一采用这种方式来进行梳理和推进。
第一层:项目指令文件
理论
Agent 在每次会话启动时,拥有完整的代码能力但没有项目上下文。
开发者通过 prompt 提供上下文,但 prompt 的内容和质量完全取决于个人习惯------有人详细,有人简洁,还有人愤怒对喷 😂。
项目指令文件(一般指 CLAUDE.md / AGENTS.md)的核心价值在于:将项目的基础上下文从「每次 prompt 中临时提供」提升为「Agent 的持久配置」。
它不需要开发者记住、也不需要在每次会话中重复------因为 Agent 启动时会自动加载。
这解决的是代码风格与规范一致性的问题。
当所有 Agent 会话共享同一份规范文件时,"不同人写出不同风格的代码"就从概率问题变为了配置问题。
指令文件还有一个间接但重要的效应:它使代码规范变得可讨论、可审查。
口头约定的规范无法追溯------比方说"我们约定用 Jakarta Validation"------但当这份约定写成 CLAUDE.md 并纳入 Git 版本控制后,就形成了规范变更。
落地
在项目根目录创建 CLAUDE.md(Claude Code)或 AGENTS.md(Codex),Agent 每次启动时自动读取。以下是可直接复制的模板:
diff
# 项目开发规范
## 技术栈
- 语言:Java 17
- 框架:Spring Boot 3.x + Spring Data JPA
- 测试:JUnit 5 + AssertJ,覆盖率门槛 70%
- 数据库:PostgreSQL 15,迁移工具 Flyway
## 代码风格
- 所有公开 API 方法必须包含 Javadoc
- 参数校验统一使用 Jakarta Bean Validation 注解(@NotNull, @Valid)
- 禁止使用 Guava Preconditions 和 Spring Assert 做参数校验
- 数据库查询统一通过 Repository 接口,禁止在 Service 中拼接 JPQL 字符串
- 异常设计:Service 层抛出自定义业务异常,ControllerAdvice 统一转换为 HTTP 响应
## 提交前检查
- 每个新接口必须包含至少一个正常路径和一个异常路径的单元测试
- 修改已有接口必须更新对应测试
- 禁止在 application*.yml 中写入密钥、Token、连接串
- 新增依赖必须在 PR 描述中说明选用理由
## 禁止事项
- 不得修改 .github/workflows/ 下的 CI 配置
- 不得使用 @Transactional 注解在 Controller 层
- 不得在实体类中使用 Jackson 注解(序列化逻辑放在 DTO 层)
验证
objectivec
cp CLAUDE.md ./你的项目/CLAUDE.md
git add CLAUDE.md && git commit -m "添加 AI 编码规范文件"
新开一个 Claude Code 会话,问它"这个项目的参数校验规范是什么?"
如果回答正确,说明文件已被正确加载。
第二层:Skills 可复用单元
理论
指令文件解决"做什么、不做什么"的问题,但无法覆盖"怎么做"。
后者往往需要结构化的执行流程。
以代码审查为例:一个高质量审查的标准流程至少包含------阅读 diff、提取受影响模块、检查测试覆盖、验证安全性、确认没有遗漏的清理工作。
但在没有约束的情况下,Agent 的审查质量完全取决于 prompt 的质量。
开发者 A 可能只让它"检查一下代码"(得到一段笼统的评论),开发者 B 可能让它"逐行审查"(得到更好的结果,但消耗更多 token)。
Skills 的核心价值在于:将"怎么做"从个人 prompt 技巧转化为可安装、可分发的能力模块。每个 Skill 封装了一个完整的执行流程,Agent 按流程执行而不是按 prompt 执行。
这解决的是关键工作流因人而异的问题。
当所有团队成员使用同一套 Skills 进行方案设计(/think)、代码审查(/check)、Bug 排查(/hunt)时,这些关键节点的输出质量就从"个人经验"变为"流程设计"。
落地
最主流的 skills 毋庸置疑是 superpowers ,但私以为太重,不适合轻装上阵的团队。
和我有类似想法的,不妨尝试 tw93/Waza ,是个不错的选择。
csharp
# 全局安装(一行命令,对所有项目生效)
npx skills add tw93/Waza -a claude-code -g -y
安装后获得的核心能力:
| Skill | 触发时机 | 执行流程 |
|---|---|---|
/think |
任何新功能开发前 | 需求澄清 → 方案设计 → 决策输出 → 等待确认。Agent 必须先输出方案文档并获确认,禁止跳过直接编码 |
/check |
任务完成、PR 合并前 | 读取 diff → 检查测试覆盖 → 扫描安全隐患 → 提取项目特定约束 → 确认清理工作,全部通过后才标记完成 |
/hunt |
Bug 或异常出现时 | 收集错误信息 → 定位相关代码 → 形成根因假设 → 验证假设 → 根因确认后才允许修改代码 |
/health |
定期运行 | 审计 Agent 配置漂移 → 检查 hook 状态 → 评估指令遵守情况 |
验证
bash
ls ~/.claude/skills/ # 确认 skills 已安装
# 在新会话中输入 /check,Agent 应按 skill 定义的流程执行
第三层:Hooks 自动拦截
理论
指令文件和 Skills 有一个共同的假设:Agent 会遵守它们。
但在实际运行中,Agent 可能出于各种原因,会绕过约束。
它判断某条指令在当前场景下不适用,或者在 prompt 的引导下做出了与规范冲突的判断。
这里存在一个治理上的关键区别:规范性约束 与机械性约束。
指令文件属于前者------Agent 被要求遵守,但可以选择不遵守。
Hooks 属于后者------Agent 无法绕开,因为 Hook 在工具调用层面拦截,不是在 prompt 层面建议。
这解决的是危险操作和违规行为无法阻止的问题。
一条指令说"不要写入密钥"和一段脚本在每次 Write 操作后扫描文件内容,两者的可靠性不在同一量级。
前者依赖 Agent 的判断,后者是机械的、可重复的检查。
Hook 的设计有一个关键原则:拦截面要窄、判断要明确。
Hook 只应该拦截明确有害的行为------危险命令、密钥泄露、受保护文件的修改,而不应该过度限制 Agent 的灵活性。
并非 Hook 越多越好。
落地
项目中的 .claude/ 目录结构:
bash
项目根目录/
├── CLAUDE.md
└── .claude/
├── settings.json # Hook 配置
└── hooks/
├── block-dangerous.sh # 危险命令拦截
└── check-secrets.sh # 密钥泄露检测
Hook 1:拦截危险命令
.claude/hooks/block-dangerous.sh:
bash
#!/bin/bash
COMMAND="$1"
if echo "$COMMAND" | grep -qE 'rm\s+-rf\s+/|git\s+push\s+--force|git\s+reset\s+--hard|DROP\s+TABLE|TRUNCATE'; then
echo "BLOCKED: 危险命令被拦截 --- $COMMAND"
exit 1
fi
exit 0
Hook 2:检测密钥泄露
.claude/hooks/check-secrets.sh:
bash
#!/bin/bash
FILE_PATH="$1"
CONTENT="$2"
PATTERNS='(sk-[a-zA-Z0-9]{32,}|AKIA[A-Z0-9]{16}|ghp_[a-zA-Z0-9]{36}|-----BEGIN (RSA |EC )?PRIVATE KEY-----|eyJ[a-zA-Z0-9_-]{20,}.[a-zA-Z0-9_-]{20,}.[a-zA-Z0-9_-]{20,})'
if echo "$CONTENT" | grep -qE "$PATTERNS"; then
echo "SECURITY: 检测到写入内容包含疑似密钥/Token --- $FILE_PATH"
exit 1
fi
exit 0
.claude/settings.json(注册两个 Hook):
json
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "bash .claude/hooks/block-dangerous.sh" }]
}],
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{ "type": "command", "command": "bash .claude/hooks/check-secrets.sh" }]
}]
}
}
验证
bash
chmod +x .claude/hooks/*.sh
# 在新会话中让 Agent 执行 "rm -rf /tmp/test"
# Hook 应拦截并返回 BLOCKED
第四层:SDD 流程约束
理论
前三层------指令文件、Skills、Hooks------解决的是单次操作层面的合规性问题。
但 Agent 开发中最隐蔽的问题不在操作层面,而在流程层面。
Agent 可能在需求理解不充分的情况下直接开始编码。
这也是 Agent 发散的最主要来源。
Agent 接收到指令后,会在毫秒级的时间内从"需要什么"跳到"怎么写代码"。
中间缺失的环节是设计决策------用什么方案、为什么选这个方案、有哪些边界条件需要考虑。
人工开发中,这些思考隐含在开发者的头脑中;Agent 开发中,如果不强制这个思考环节,它就会被跳过。
Spec-Driven Development(SDD)的核心理念是:在任何代码被修改之前,先让 Agent 输出结构化的规格文档,经人工确认后再进入实现阶段。
这解决的是流程发散的问题。
当一个复杂需求被分解为"需求文档→设计文档→任务拆解→逐任务实现→合并验证"后,每一步的输出都成为下一步的输入,从而确保 Agent 不能再从需求直接跳进代码。
落地
三套可直接使用的 Markdown 模板,放入 docs/sdd/ 目录:
docs/sdd/TEMPLATE-requirements.md:
ini
# 需求文档:[功能名称]
## 背景与动机
- 当前系统存在什么问题?
- 为什么要做这个功能?
## 功能范围
- [ ] 功能点 1
- [ ] 功能点 2
## 非功能约束
- 响应时间:P95 < [X]ms
- 向下兼容性:[是 / 否]
## 验收条件
- [ ] Given [前置条件], When [操作], Then [预期结果]
## 不在范围内(明确排除)
- 不包含 XXX
docs/sdd/TEMPLATE-design.md:
bash
# 设计文档:[功能名称]
## 架构决策
| 决策 | 选项 | 选择 | 理由 |
|------|------|------|------|
| 缓存方案 | Redis vs Caffeine | Caffeine | 数据量小,单机即可 |
## 接口定义
### POST /api/xxx
- 请求体:{ "field1": "string" }
- 响应体:{ "id": "string" }
- 异常:400 参数错误
## 数据库变更
- 新增 Flyway 迁移:V1.2__add_xxx.sql
docs/sdd/TEMPLATE-tasks.md:
markdown
# 任务清单:[功能名称]
## Task 1: [任务标题]
- 描述:具体要做什么
- 涉及文件:src/main/java/.../XxxService.java
- 依赖:无
- Issue: #123
启用
bash
mkdir -p docs/sdd
# 将三个模板放入 docs/sdd/
# 在 CLAUDE.md 中追加:
cat >> CLAUDE.md << 'EOF'
## SDD 流程
- Medium 及以上复杂度的需求,必须先完成 requirements.md 和 design.md
- 设计确认后,拆解为 tasks 并创建对应 GitHub Issues
- 每个 task 在独立会话中实现,完成后运行 /check
EOF
第五层:团队统一分发
理论
前四层积累的治理资产------指令文件、Skills、Hooks、模板。
在单个开发者本地有效,但团队其他人如何获取同样的配置?
靠口口相传和文档链接?
治理资产的统一分发是我们整个治理体系闭环的最后一步。
没有这一层,前四层的效果也仅仅是局限于个人。
通俗的讲,就是团队中配置最全的人享受到最高的治理水平,而配置少的人仍然不受约束。
Plugin Marketplace 和 npx skills 工具解决的是同一个问题:让治理资产的安装从"手动复制多个文件"变为"一条命令",从"个人选择"变为"团队默认"。
当新成员入职只需要一条命令就能获得全套治理配置时,治理就从"建议"变成了真正的"基础设施"。
落地
团队治理仓库结构:
bash
org-ai-governance/
├── CLAUDE.md # 基础指令模板
├── skills/
│ └── team-code-style/
│ └── SKILL.md # 团队代码风格检查 Skill
├── hooks/
│ ├── block-dangerous.sh
│ ├── check-secrets.sh
│ └── install.sh # 一键安装
├── templates/
│ ├── sdd-requirements.md
│ ├── sdd-design.md
│ └── sdd-tasks.md
└── .github/workflows/
└── sync-config.yml # 自动同步到各项目
团队成员一键安装:
bash
npx skills add <org>/team-governance -a claude-code -g -y
bash ~/.claude/team-config/hooks/install.sh
写到最后
随着 Agent 工程能力的发展,一些变化悄然发生:
熟练使用 Claude Code、Codex CLI 的人,正在成为天才程序员。
需求理解更快,代码产出更快,排查问题更快,文档和测试也更完善。
过去可能需要一周完成的工作,现在一个熟练的开发者带着 Agent,可能半天就能推进到七七八八。
这当然令人兴奋。
但也迫使我反复思考另一个问题:
团队里那些还不熟练的人怎么办?
不会用 Agent、用不好 Agent 的同学,在产出指标上,可能很快就会变成低效率,进而演变成低绩效。
尤其是我们这种全员 Agent 化的团队。
如果 Agent 只停留在个人能力层面,那么它一定会放大个体差异。会用的人越来越强,不会用的人越来越焦虑,最后团队内部形成新的能力断层。
但我更希望看到的是另一种结果:
Agent 不是少数人的资本,而是整个团队的基石。
强者会因为 Agent 变得更强,这是必然的。
而团队治理的价值在于:不要让学习慢的人,被工具革命甩在身后。
让每个人都能在清晰的规则、可复用的流程和足够安全的边界内,把 Agent 用起来,用稳、用好。
这或许才是 Agent 工程化真正重要的地方。