最近在研究 harness ,AI 不是在抢我的工作:Harness 正在重构软件工程|让 Agent 完成任何复杂任务。
刷到这么一个项目:wow-harness,它是一个基于 Claude Code 的治理层框架,用于管理 AI 模型的行为。
我好奇它的具体实现,因为想用在自己的开发项目中:怎么把6周一次版本更新提升到1天8次部署?从用 AI 到 AI 优先
wow-harness 是为 Claude Code 打造的治理层(Governance Layer)框架。
核心主张:指令改变不了 AI 行为(遵从率 ~20%),但机械约束可以(执行率 100%)。
AI 坏毛病 | 表现 | 危害 |
|---|---|---|
假装完成 | "测试全过了"(实际没跑) | 上线出生产事故 |
跳过审查 | "这个改动很简单" | 引入未审查代码 |
任务漂移 | 修一个 bug,顺手重构三个文件 | 变更不可控 |
自我评价偏差 | 永远回答"做得好" | 无法发现自身错误 |
并行污染 | 多 session 互相影响 | 代码冲突 |
1. 16 个生命周期 Hook(实时拦截) 横跨 7 个阶段,AI 每次调用工具前都会被拦截,条件不满足则工具调用直接失败:
SessionStart → 加载上下文、重置风险状态
PreToolUse → 拦截危险部署、门控审查 agent
PostToolUse → 编辑时路由上下文、检测循环
Stop → 验证完成候选品(transcript × git diff)
SessionEnd → 反思、持久化进度2. 8 门状态机(8-Gate State Machine)
G0 问题 → G1 设计 → G2 审查★
→ G3 方案 → G4 审查+锁定★
→ G5 任务 → G6 审查★
→ G7 执行 → G8 终审★
★ = 独立审查者(独立上下文、只读工具)偶数关启动新 agent 审查,审查 agent 的工具清单物理上没有 Edit/Write,所以不能改。
3. 15 个自动验证器 — 文件变更时运行,捕获 API 类型不一致、文档过期、安全模式等
4. 16 个专业化 Skill — 架构设计(arch)、失败模式提取(crystal-learn)、Bug 分诊(bug-triage) 等
git clone https://github.com/NatureBlueee/wow-harness.git
cd wow-harness
python3 scripts/install/phase2_auto.py /path/to/your/project --tier drop-in三个安装层级:
层级 | 适合场景 | 说明 |
|---|---|---|
drop-in | 想先试试 | 原样安装 hook + skill |
adapt | 正式项目 | 读项目 README/文档,适配 skill |
mine | 团队协作 | 读工作 transcript,深度适配 |
安装后目录结构:
your-project/
├── .claude/
│ ├── settings.json # Hook 注册(追加模式,不覆盖已有)
│ ├── skills/ # 16 个 agent 行为定义
│ └── rules/ # 路径作用域上下文规则
├── scripts/
│ ├── hooks/ # 16 个生命周期 hook
│ └── checks/ # 15 个自动化验证器
└── CLAUDE.md # 治理指南(自动生成,可编辑)每个技能都以 SKILL.md 文件形式存在,开头是 YAML frontmatter:
---
name: lead # 技能名称
description: 开发流程统领... # 描述(用于触发匹配)
status: active # 状态
tier: entry # 层级
owner: nature # 维护者
last_audited: 2026-04-09 # 最后审计日期
triggers: # 触发条件
- 新功能
- 方向讨论
outputs: # 输出契约
- Gate 包
- 决策缺口
truth_policy: # 真相策略
- 不复制实时仓库事实
---关键字段解析:
entry(入口)、execution(执行)、meta(元层)meta 层(自省与进化)
crystal-learn → 提取失败模式,形成不变量
skill-discovery → 发现重复模式,提议新技能
entry 层(入口与编排)
lead → 9 Gate 状态机,流程阻塞者
arch → 架构设计,本质判断
harness-dev-handoff → 新 session 接手入口
execution 层(执行与实现)
harness-dev → 全栈开发,代码实现
guardian-fixer → Guardian issue 自动修复管道
task-arch → WP 拆分
plan-lock → 计划冻结
这是针对 LLM agent 的一个结构性偏见设计的:
LLM 在压力下会主动跳门("这个简单,不用审查也能过")
如果把判断和执行放在同一个 skill 里,agent 会倾向于"边做边判断",最终变成"做了再找理由"。
分层后:
lead 只判断 Gate 转移,不写代码harness-dev 只执行已冻结的计划,不做架构决策# crystal-learn 的定位
"""
我是 harness 的适应性免疫系统。
我不修具体 bug,也不写产品代码。
我提取"这类错误为什么总会回来",把它们压成不变量。
"""meta 层不参与日常开发,但在系统运行一段时间后,它会:
这种设计让系统能够从错误中学习,避免每次犯同样的错误。
harness-dev-handoff 的核心设计:
## Truth Policy
我不是新的权威副本。我只负责把新 agent 引到当前仍然活着的真相源上。entry 层不维护知识副本,只维护导航规则。
这避免了"skill 里的描述和代码实际状态不一致"的问题。

1. Towow(通爻)代理协作协议 — 6 个月生产实践
这是 wow-harness 的创作团队实际项目案例。
他们在开发 Agent 协作协议项目 Towow 时,逐步迭代出当前的 hook/gate/隔离体系,命名为 wow-harness。
核心经验:每一条规则都是"先被烧伤,再建防护"。
AI agent 找到了创造性的方式不遵守上一条规则,才有了下一条规则。
wow-harness 不是 Skill,它是基于 Claude Code 的 hooks 系统的原生消费者,在工具调用的前后拦截点注入。
它能生效,是因为 Claude Code 在每次工具调用的前后、session 的开始和结束、以及 compaction 之前,都会调用注册在 .claude/settings.json 里的脚本。
这些脚本的输出直接注入 AI 的上下文,exit code 直接决定工具调用是否被放行。
它的注入时机是机械的、不可绕过的。
Claude Code 有 7 个生命周期阶段,每个阶段可以注册 hook 脚本:
SessionStart → session 开始时
PreToolUse → 每次工具调用之前
PostToolUse → 每次工具调用之后
PreCompact → 上下文压缩之前
Stop → agent 尝试停止时
SessionEnd → session 结束时
PostToolUseFailure → 工具调用失败后Hook 协议的核心规则:
hook 输出 | 效果 |
|---|---|
exit 0 | 放行,不注入任何内容 |
exit 0 + stdout 有内容 | 放行,stdout 内容注入 AI 上下文(作为 additionalContext) |
exit 2 + stderr 有内容 | 阻止当前操作,stderr 内容注入 AI 上下文作为反馈 |
exit 1 | 硬阻断(deploy-guard 用) |
根据项目文档 ADR-038 的记录,Claude Code 源码中有 28 种 hook 事件:
Claude Code 原生 Hook 事件
会话生命周期
SessionStart ← 会话开始时触发
SessionEnd ← 会话结束时触发
Stop ← AI 回复完成后触发
PreCompact ← 上下文压缩前触发
工具调用
PreToolUse ← 工具调用前触发
PostToolUse ← 工具调用后触发
PostToolUseFailure ← 工具调用失败时触发
用户交互
UserPromptSubmit ← 用户提交 prompt 时触发
PermissionRequest ← 权限请求时触发
文件/环境
FileChanged ← 文件变更时触发
WorktreeCreate/Remove ← Worktree 生命周期在 .claude/settings.json 中配置:
{
"hooks": {
"SessionStart": [
{
"matcher": "*",
"hooks": [
{ "type": "command", "command": "python3 scripts/hooks/session-start-reset-risk.py" }
]
}
],
"PreToolUse": [...],
"PostToolUse": [...]
}
}
用户打开新对话
↓
Claude Code 初始化会话
↓
读取 .claude/settings.json
↓
执行 SessionStart hooks
↓
hook 脚本的 stdout 被注入到会话的初始上下文
↓
会话正式开始,AI 可以看到 hook 输出的内容
这就是 wow-harness 所有魔法的根基——它不是"建议 AI 做什么",而是在 AI 调用工具的瞬间,物理上允许或拒绝,同时在上下文中注入信息。假设任务:给 API 路由层添加一个新端点
你打开 Claude Code,输入任务描述。
Hook 触发顺序:
① session-start-reset-risk.py
→ 删除上次 session 的 risk-snapshot.json
→ exit 0(静默,不注入)
→ 作用:每个 session 从 R0 风险起步
② session-start-magic-docs.py
→ 检查自动生成的文档是否与源码同步
→ 如果有漂移:stdout 输出漂移告警 → 注入 AI 上下文
→ 如果无漂移:exit 0(静默)
→ 作用:防止 AI 基于过期文档工作
③ session-start-toolkit-reminder.py
→ 输出可用 skills 和工具清单
→ stdout 注入 → AI 知道自己有什么技能
→ 作用:防止 AI 忘记自己能做什么此时 AI 的上下文可能长这样:
[SessionStart 注入]
=== ADR-038 D5 Magic Doc Drift Alert ===
DRIFT: docs/magic/api-routes.md (source: backend/product/routes/ changed)
[toolkit-reminder 注入]
可用 Skills: lead, arch, plan-lock, bug-triage, crystal-learn ...AI 决定先看看现有路由代码,调用 Read backend/product/routes/protocol.py
PreToolUse 触发:
④ tool-call-counter.py
→ 计数器 +1(第 1 次调用)
→ 每 50 次调用才注入 Objective Recitation
→ 第 1 次:exit 0(静默)
⑤ sanitize-on-read.py
→ 读取目标文件,扫描敏感内容
→ 无 SECRET/TRADE_SECRET:exit 0
→ 有 PII/NETWORK:warn 但放行
→ 作用:防止密钥/密码进入 AI 上下文PostToolUse 触发:
(Read 操作不触发 guard-feedback.py,因为它只监听 Edit/Write)AI 看到了路由代码,开始规划。
AI 调用 Edit backend/product/routes/protocol.py 添加新端点。
PreToolUse 触发:
⑥ tool-call-counter.py
→ 计数器 +1,仍不是 50 的倍数 → 静默
⑦ review-agent-gatekeeper.py
→ 检查是否在 spawn 审查 subagent
→ 当前是 Edit 不是 Task → exit 0(放行)PostToolUse 触发(关键!三个 hook 同时运行):
⑧ guard-feedback.py
→ 机制 A:上下文路由
路由表查 "backend/product/routes/" → 匹配 "contract-consumers" 片段
加载 context-fragments/contract-consumers.md
→ 注入 AI 上下文:"改这个文件会影响以下消费方..."
→ 机制 B:guard 检查
路由表查 "backend/product/routes/" → 匹配 "check_doc_freshness"
运行 check_doc_freshness.run() → 如果文档过期,报告 finding
→ 注入 AI 上下文:"文档可能需要同步更新"
→ Fragment 去重:同一 session 内同一片段只注入一次
→ exit 2(有输出,注入上下文)
⑨ loop-detection.py
→ 检查 backend/product/routes/protocol.py 被编辑次数
→ 第 1 次编辑:不触发告警 → exit 0
→ 如果同一文件编辑 ≥5 次:
注入 "[LoopDetection] 你已经编辑 X 5 次了。考虑换方法。"
⑩ risk-tracker.py
→ 分析被编辑文件的路径
"backend/product/routes/" → 匹配 RISK_ELEVATORS → R2
→ 写入 .towow/state/risk-snapshot.json:
{"risk_level": "R2", "files_touched": [...]}
→ exit 0(不注入,纯记录)
→ 作用:风险只升不降(棘轮机制)此时 AI 的上下文多了:
[guard-feedback 注入]
## Context
--- 此文件是 API 契约定义点,以下模块消费此契约:
- backend/product/bridge/bridge_client.py
- mcp-server/towow_mcp/client.py
- website/app/api/ 代理层
修改此文件时必须同步更新所有消费方。
## Guard Findings
- P2 doc_integrity: routes/protocol.py 变更后文档可能需要同步更新AI 改了路由文件后,又去改了 mcp-server/ 的客户端代码,然后顺手改了 CLAUDE.md 想加点注释。
每次 Edit 都触发 guard-feedback + loop-detection + risk-tracker:
mcp-server/:路由表匹配 → 注入 mcp-parity 片段(提醒 MCP 双端一致性)CLAUDE.md:路由表匹配 → 注入 truth-source-hierarchy 片段这些注入直接出现在 AI 的工具调用返回中,和工具调用结果混在一起,AI 必须处理。
AI 觉得改完了,想直接 scp 文件到生产服务器。
PreToolUse Bash 触发:
⑪ deploy-guard.py
→ 解析 Bash 命令,发现包含受保护 IP "47.118.31.230"
→ 检测到 scp 上传操作
→ exit 1 + stderr: "BLOCKED: 禁止手动 scp 上传到受保护服务器"
→ Claude Code **物理阻止**这个 Bash 调用
→ AI 看到错误信息,被迫使用 deploy.shAI 改了 protocol.py 5 次,还在反复修改。
PostToolUse Edit 触发:
⑨ loop-detection.py
→ 计数器显示 protocol.py 已编辑 5 次
→ 注入:"你已经编辑 protocol.py 5 次了。考虑换方法。"
→ AI 被迫停下来重新思考方案AI 说"我完成了",尝试停止。
Stop 触发(最核心的拦截点):
⑫ stop-evaluator.py → 整体流程:
Step -1: 检查 stop_hook_active(CC 防循环字段)
→ 如果上一次 stop 已经注入过反馈 → 放行,避免无限循环
Step 0: D8 机械化第一关(零 LLM 成本)
→ 调用 initializer-agent.py stop-check
→ 读取 .towow/progress/current.json
→ 检查所有 feature 的 status 是否 == "passing"
→ 检查所有 passing feature 是否有 evidence
如果有 feature 不是 passing:
→ exit 2 + stderr: "D8 机械化第一关失败,以下 features 未 passing..."
→ **AI 被迫继续工作,不能 Stop**
如果所有 feature 都 passing 且有 evidence:
→ 进入 Step 1
Step 1: Completion Candidate 判定
→ 读取 session transcript(CC 提供的 .jsonl 文件)
→ 提取本 session 用 Edit/Write 写过的文件集合 A
→ 运行 git diff --name-only 获取未提交变更集合 B
→ A ∩ B 非空 → 是 completion candidate → 进入 Step 2
→ A ∩ B 为空 → 不是 completion candidate → 放行(纯聊天/研究场景)
Step 2: 注入 stop-evaluator.md 检查清单
→ exit 2 + stderr: 完整的 completion review 流程stop-evaluator.md 注入的内容要求 AI:
review-readonly subagent)AI 被 Stop hook 拒绝后,按照注入的指令 spawn 一个审查 agent。
PreToolUse Task 触发:
⑬ review-agent-gatekeeper.py
→ 检测到 spawn 的是 review subagent
→ 检查 prompt 中是否包含只读指令
→ 如果没有:exit 2,**阻止 spawn**
→ 如果有:记录 active-review-agent 标记 → exit 0
→ 作用:物理确保审查 agent 的 prompt 包含只读约束审查 agent 在独立上下文中运行,工具清单里没有 Edit/Write/Bash。
它只能 Read + Grep + ListFiles,然后给出 PASS/FAIL 评分。
对话很长时,Claude Code 会压缩上下文。
PreCompact 触发:
⑭ precompact.sh
→ 输出必须保留的信息:
- 当前 PLAN/TASK 状态
- Sprint Contract 验收标准
- 不可降级规则(guard > memory, 一个事实一个定义...)
- Objective Recitation:从 progress.json 读取原始目标
→ 作用:压缩后 AI 不会丢失关键约束
→ 防止 "改着改着忘了原始目标" 的问题SessionEnd 触发:
⑮ session-reflection.py
→ 收集 guard 命中统计 + loop 统计
→ 写入 metrics JSONL
→ 如果有频繁编辑的文件:输出改进建议
⑯ trace-analyzer.py
→ 聚合 trace 数据用于 harness 优化
⑰ deploy-progress-on-session-end.py
→ 持久化部署进度8-Gate 状态机是由skill 驱动的流程框架,不依赖 hook 自动触发。
Hook 是守门员,Gate 是流程。
Gate | 时机 | 谁触发 | Hook 保障 |
|---|---|---|---|
G0 问题定义 | 任务开始时 | lead skill 或人工 | — |
G1 设计方案 | G0 完成后 | 执行 agent | — |
G2 独立审查 | G1 完成后 | lead skill spawn 审查 agent | review-agent-gatekeeper 确保只读 |
G3 实现方案 | G2 PASS 后 | 执行 agent | — |
G4 审查+锁定 | G3 完成后 | lead skill spawn 审查 agent | review-agent-gatekeeper + plan-lock skill |
G5 任务拆分 | G4 PASS 后 | lead skill | initializer-agent 生成 progress.json |
G6 独立审查 | G5 完成后 | lead skill spawn 审查 agent | review-agent-gatekeeper |
G7 执行+日志 | G6 PASS 后 | 执行 agent | guard-feedback + risk-tracker 实时监控 |
G8 终审 | G7 完成后 | lead skill spawn 审查 agent | stop-evaluator + review-agent-gatekeeper |
流程有效 的关键:不是同一个 agent 审查自己。
审查 agent 是新创建的,有独立上下文,工具清单里没有写入工具。
指令方式(CLAUDE.md 写 "修改后必须跑测试"):
AI 读取 → 理解 → 决定是否遵守 → ~20% 概率遵守
↑ 失败原因:AI 可能忘记、误解、或"创造性"忽略
Hook 方式(stop-evaluator.py 检查 progress.json):
AI 尝试 Stop → hook 运行 → 检查结果 → 100% 执行
↑ 无法绕过:hook 在 AI 的工具调用路径上,物理拦截CLAUDE.md 是门上的告示牌"请敲门",Hook 是门锁——没钥匙就是进不来。
组件 | 解决什么问题 | 机制 |
|---|---|---|
stop-evaluator | 假装完成 | 机械化检查 transcript ∩ git_dirty + 独立 reviewer |
review-agent-gatekeeper | 审查者越权 | Schema 级工具隔离,审查者没有 Edit/Write |
initializer-agent (D8) | 自我评价偏差 | progress.json objective SHA256 不可篡改 + 机械化第一关 |
loop-detection | 循环修改 | 文件编辑计数 ≥5 次注入提醒 |
risk-tracker | 风险积累不可见 | 路径计算风险等级,棘轮只升不降 |
guard-feedback | 上下文缺失 | 编辑文件时自动注入相关约束和消费方信息 |
context_router | 注意力漂移 | 文件路径 → 上下文片段路由 |
deploy-guard | 危险部署 | 物理阻止 scp/ssh 写操作到生产服务器 |
sanitize-on-read | 敏感信息泄露 | Read 前扫描,SECRET 硬阻断 |
tool-call-counter | 目标遗忘 | 每 50 次调用注入 Objective Recitation |
precompact.sh | 压缩丢失关键信息 | 压缩前注入不可降级规则 + 原始目标 |
session-reflection | 经验无法积累 | SessionEnd 记录 guard 统计和失败模式 |
Claude Code 启动一个 subagent 时,有两种方式限制它的行为:
你是审查 agent。请只读代码,不要修改任何文件。AI 读了这句话 → 理解了 → 可能遵守,也可能不遵守。
实测遵从率 ~70%。
它会"好心"地顺手修个 typo、改个 import,因为它觉得"这明显是错的,我顺手修了更好"。
Claude Code 的 agent 系统支持在 agent 定义文件(如 .claude/agents/review-readonly.md)的 frontmatter 中声明 tools: 白名单:
---
name: review-readonly
tools:
- Read
- Search
- Grep
- ListFiles
# 注意:没有 Edit、Write、Bash、NotebookEdit
---这个 tools: 字段就是 Schema——它定义了这个 agent 能调用的工具的 JSON Schema。
当 Edit 不在 schema 里时,agent "根本不知道 Edit 的存在"。
就像你给一个人一把只有读权限的钥匙。
从源码 review-agent-gatekeeper.py 中可以清晰看到这两层的对比:
# 来源: ADR-038 D11
# 审查 agent must use schema-level tool isolation (frontmatter `tools:` whitelist),
# not prompt-level constraint. OpenDev arXiv 2603.05344 showed:
# prompt约束 ~70% adherence vs schema-level 100%.
# 对于本地 agent(frontmatter 可修改)→ 直接在 tools 白名单里排除
# 对于插件 agent(frontmatter 不可修改)→ 在 spawn 边界用 hook 强制检查这里的 Schema 是 工具调用的 JSON Schema:
即定义"这个 agent 能调用哪些工具、每个工具接受什么参数"的规范。
层级 | 类比 | 效果 |
|---|---|---|
Prompt 级 | 墙上贴"禁止入内" | 看到的人可能遵守,可能不遵守 |
Schema 级 | 门上根本没有门把手 | 物理上无法进入,非意愿问题 |
Prompt 级:你的手机上有微信,但老板说"上班别刷微信"
→ 你可能忍住,也可能偷偷刷
Schema 级:你的手机上根本没装微信
→ 想刷也刷不了看源码 review-agent-gatekeeper.py 的设计,它处理了两种 agent:
1. 本地 agent(.claude/agents/review-readonly.md)→ frontmatter 里已经写了 tools: 白名单,物理隔离,不需要 hook 干预。hook 直接放行:
LOCAL_REVIEW_EXEMPT = ("review-readonly",)
# 本地 agent 的 frontmatter 已经强制了 → 免检放行2. 插件 agent(如 pr-review-toolkit:code-reviewer)→ 这些 agent 来自 .claude/plugins/,作者无法修改它们的 frontmatter。
所以 wow-harness 在 spawn 边界加了一道 hook 拦截:
# 当 AI 尝试 spawn 一个审查 subagent 时
# hook 检查 prompt 中是否包含只读指令
REQUIRED_DIRECTIVES = (
"MUST NOT call Edit",
"MUST NOT use Edit",
"read-only reviewer",
"read-only mode",
"schema-level read-only",
"ADR-038 D11",
)
# 如果 prompt 里没有这些指令 → 阻止 spawn(exit 2)
# 如果 prompt 里有 → 放行,但记录一个标记让下游 hook 知道这里用 prompt 级约束是退而求其次:
因为插件 agent 的 frontmatter 无法修改,只能在 spawn 时强制 AI 在 prompt 里写上只读指令。
虽然不如 Schema 级完美,但在 spawn 边界拦截比运行时拦截强得多。
"Schema 级隔离":在工具定义的 schema 层面把写入工具从白名单中删除,使 agent 物理上无法调用这些工具。
对比维度 | Prompt 级 | Schema 级 |
|---|---|---|
约束方式 | 自然语言"请不要" | 工具白名单里没有 |
遵从率 | ~70% | 100% |
能否绕过 | 能("我觉得改了更好") | 不能(工具不存在) |
类比 | 门上贴"请勿入内" | 门上没把手 |
Claude Code 的主 agent 有一个内置工具叫 ,它的作用就是 spawn 一个子 agent 去执行特定任务。
调用方式长这样(从 stop-evaluator.md 和 review-agent-gatekeeper.py 源码中可以看到完整结构):
{
"tool_name": "Task",
"tool_input": {
"subagent_type": "review-readonly",
"description": "Completion review",
"prompt": "你是独立的 Completion Reviewer(ADR-044 L4)。你的任务是验证..."
}
}三个关键字段:
字段 | 含义 |
|---|---|
subagent_type | 用哪种 agent 定义来 spawn |
description | 任务简述 |
prompt | 给子 agent 的具体指令 |
每种 subagent_type 对应一个 agent 定义文件,存放在:
.claude/
├── agents/ # 本地自定义 agent
│ ├── review-readonly.md # 只读审查 agent
│ └── ...
└── plugins/ # 插件提供的 agent
└── pr-review-toolkit/
├── code-reviewer.md
├── silent-failure-hunter.md
└── ...每个定义文件有 YAML frontmatter:
---
name: review-readonly
model: claude-opus-4-6 # 指定用哪个模型
tools: # ← 这就是 Schema 级隔离的关键
- Read
- Search
- Grep
- ListFiles
# 没有 Edit / Write / Bash / NotebookEdit
---
你是一个独立的审查 agent...主 agent 判断"这个任务需要子 agent"
↓
调用 Task 工具(subagent_type + prompt)
↓
PreToolUse Task hook 触发
review-agent-gatekeeper.py
检查:是不是审查类 agent?
是 → prompt 里有没有只读指令?
没有 → exit 2 阻止 spawn
有 → exit 0 放行
↓
Claude Code 按照定义文件 spawn 子 agent
- 加载 agent 定义文件的 frontmatter(tools 白名单、model 等)
- 创建独立上下文(不是主 agent 的对话历史)
- 子 agent 只能用 tools 白名单里的工具
↓
子 agent 执行任务,返回结果给主 agent1. 独立上下文:子 agent 不继承主 agent 的完整对话历史。
它只拿到 prompt 里写的内容。这是"独立审查"能生效的前提——审查者看不到执行者的"借口"。
2. 工具白名单在 spawn(生成) 时就固定:
子 agent 一旦被 spawn 出来,它的工具集就锁死了。
Edit 这个工具对它来说不存在:调用时会直接报"tool not available"。
这和 WorkBuddy 的 Task 工具(就是我在用的 task 工具来启动 code-explorer subagent),本质上是同一个模式:
wow-harness 做的就是:
在这个 spawn 的必经之路上加了 hook 检查站,确保审查类子 agent 拿不到写入工具,在spawn 时工具清单里就没有。
依赖项 | 具体机制 | wow-harness 怎么用的 |
|---|---|---|
7 阶段 Hook 协议 | SessionStart/PreToolUse/PostToolUse/PreCompact/Stop/SessionEnd/PostToolUseFailure | 全部 16 个 hook 的存在基础 |
Hook 注入协议 | exit 0 + stdout → 注入上下文;exit 2 + stderr → 阻止 + 注入 | stop-evaluator 阻止 Stop,guard-feedback 注入上下文 |
Task 工具 | spawn 子 agent + 独立上下文 | 独立审查 agent |
Agent 定义文件 | .claude/agents/*.md frontmatter tools: 白名单 | Schema 级隔离 |
Transcript | 每次 session 自动生成 .jsonl | stop-evaluator 提取"本次 session 写过哪些文件" |
stdin JSON payload | hook 脚本从 stdin 读取结构化事件数据 | 所有 hook 的输入来源 |
settings.json | hook 注册表 | hook 的安装入口 |
7 层依赖,每一层都是 wow-harness 运行的必要条件。
是"运行在某个操作系统上"级别的依赖。
能力 | Claude Code | Codex (OpenAI) | Cursor | Trae | CodeBuddy |
|---|---|---|---|---|---|
生命周期 Hook | ✅ 7 阶段完整 | ❌ 无 hook 系统 | ❌ 无 hook | ❌ 无 hook | ❌ 无 hook |
Hook 注入协议 | ✅ exit code + stdin/stdout | ❌ | ❌ | ❌ | ❌ |
Task 子 agent | ✅ 原生工具 | ✅ 有 sub-agent | ✅ 有 agent | ❓ 不确定 | ✅ 有 Task 工具 |
Agent 工具白名单 | ✅ frontmatter tools: | ❓ 沙箱模式 | ❌ | ❌ | ❌ |
Session Transcript | ✅ 自动 .jsonl | ❌ | ❌ | ❌ | ❌ |
可编程阻止操作 | ✅ exit 2 | ❌ | ❌ | ❌ | ❌ |
结论:目前只有 Claude Code 具备 wow-harness 所需的全部能力。
Codex 有自己的 harness 机制(sandbox + 指令),但架构完全不同:
wow-harness 的核心价值——在工具调用瞬间拦截——在 Codex 上没有对应接口。
tools: 白名单机制来限制 subagent 能力把 wow-harness 的理念迁移可以,但机制几乎不可迁移:
wow-harness 理念 | 能否迁移 | 怎么迁移 |
|---|---|---|
Hook 优于指令 | ⚠️ 降级 | 降级为"指令 + 人工检查",遵从率从 100% 回到 ~20% |
Schema 级隔离 | ❌ 大部分工具不支持 | 只有 Claude Code 有 tools: 白名单;其他工具只能靠 prompt |
机械化完成验证 | ⚠️ 部分可以 | 可以写外部脚本手动检查 git diff + progress.json,但不能自动拦截 Stop |
独立审查 agent | ⚠️ 部分可以 | 可以 spawn 子 agent 审查,但无法限制它的工具集 |
上下文路由 | ⚠️ 可以迁移 | 可以通过 CLAUDE.md / system prompt 实现,但不是自动的 |
风险追踪 | ⚠️ 可以迁移 | 纯文件操作,不依赖 hook |
循环检测 | ❌ 依赖 PostToolUse hook | 无法在编辑后自动检测 |
部署保护 | ❌ 依赖 PreToolUse hook | 无法在 Bash 执行前拦截 |
目前,Claude Code 是唯一提供完整 hook 协议 + agent 工具白名单 + transcript 访问的编程 agent。
其他工具要达到同等效果,需要先在平台层面补齐这些能力。
wow-harness 的本质是:把"你应该如何做"从自然语言指令,转化为工具调用路径上的机械拦截点。
它的这套设计原则也值得我学习运用:
这些原则可以迁移,但实现方式完全取决于目标工具提供了什么接口。
你觉得能否提升 AI Code 的效率?评论区留言。
-END-