Appearance
有经验的 Claude Code 用户常常认为"Skills、Commands、Subagents、Hooks 最终都变成 prompt,强 prompt 就能等价替代"。这个论断在单次原子任务上成立,在真实工程工作上会失败。本文梳理 10 种 harness 层独有能力,说明为什么 prompt 是 harness 的子集,而不是替代品。
Claude Code Harness 价值论:为什么强 Prompt 不能替代工具框架
那个"听起来有道理"的论断
一个在有经验的 Claude Code 用户中流传的观点:
"Skills、Commands、Subagents、Hooks——它们最终都变成发给模型的 tokens,所以足够强的 prompt 就能等价替代。"
在模型最终推理调用这一层面,这在技术上是正确的——模型确实只看到 tokens。
但在其他所有层面——真实软件工程发生的层面——这个论断崩塌了。Harness 不是"prompt 的交付系统",而是 prompt 构建系统 + 确定性执行系统 + 上下文架构系统,这些能力不能被更强的措辞替代。
这个论断适用的唯一场景
对于单次原子任务——"写一个递归 Fibonacci 函数"——harness 确实对输出质量没有贡献。把相同 tokens 交给相同模型,无论通过 skill、command 还是原始 prompt,得到的输出分布相同。
这是论断成立的场景,也正是真实工程工作不在的场景。
Harness 层的 10 种独有能力
| # | 能力 | 作用 | 为什么 prompt 无法复制 |
|---|---|---|---|
| 1 | 上下文隔离 | Subagents 在独立上下文窗口中运行 | Prompt 只填一个窗口;N 个并行 subagent 提供约 N 倍有效上下文 |
| 2 | 工具限制强制 | tools/disallowedTools 在模型能使用前就拦截工具 | Prompt 指令是建议性的,模型可以忽略;deny 规则不可被忽略 |
| 3 | 懒加载规则 | paths: frontmatter 和子目录 CLAUDE.md 只在 Claude 访问匹配路径时加载 | Prompt 是静态的,无法根据运行时正在读哪些文件来条件性加载 |
| 4 | Hooks 确定性执行 | Shell 命令在生命周期事件(PreToolUse/PostToolUse/Stop)运行,可以阻断工具调用 | Prompt 无法拦截自己的工具调用;Hooks 即使模型"不想要"也会执行 |
| 5 | 模型路由 | model: haiku 或 model: opus 将调用路由到不同的模型端点 | Prompt 中没有任何 token 能改变谁来回答 |
| 6 | 并行执行 | 多个 subagent 并发执行 | Prompt 是顺序的;harness 负责调度和收集并行进程的结果 |
| 7 | 跨 session 持久化 | Memory 系统和 settings 层级跨对话持久化 | Session 结束时 prompt 就消失了 |
| 8 | 模块化系统提示 | CLI 根据激活的功能,条件性地加载 110+ 个系统提示片段 | 用户无法手工编写或替换 CLI 的内部提示片段 |
| 9 | Skill 预加载 | skills: 字段在 subagent 启动时将 skill 完整内容注入其上下文 | 用户无法预先填充另一个 agent 的上下文,只有 harness 加载器能做到 |
| 10 | 权限分类 | auto 权限模式用后台分类器预审批或拦截工具调用 | Prompt 无法为自己添加预执行安全层 |
"Prompt"的两种含义混淆
这个论断依赖于一个词义混淆:
| 含义 | 谁控制 | 大小 |
|---|---|---|
| (a) 用户输入的文字 | 用户 | ~6–60 tokens |
| (b) 模型在推理时实际看到的内容 | Harness | ~5,000–50,000+ tokens |
在聊天机器人中,(a) 和 (b) 是同一件事。 在 Claude Code 中,它们截然不同。
Harness 的工作恰恰是让 (b) 比 (a) 丰富得多:
用户输入: "写一个递归 flatten 函数" ← (a) ~6 tokens
模型在推理时实际看到的内容: ← (b) ~15,000 tokens
├── CLAUDE.md(项目规范)
├── 匹配 paths: 的 .claude/rules/*.md(按路径懒加载)
├── 模块化系统提示片段
├── 工具定义
├── 环境上下文(cwd、git 状态、平台信息)
├── 历史轮次
├── 模型通过 Read/Grep 工具读取的文件
└── 用户的 6 token 请求输出质量是 (b) 的函数,而不是 (a)。 Harness 构建 (b),"强 prompt"无法复现 (b),因为其中大部分内容根本不是用户写的。
同一 prompt、三种结果
考虑同一条 prompt——"写一个递归 flatten 函数"——在三种环境中的结果:
| 环境 | 模型看到什么 | 典型结果 |
|---|---|---|
| 聊天机器人,无工具 | 这句话 | 教科书式递归,通用风格 |
| Claude Code,无读取 | 这句话 + CLAUDE.md | 符合项目声明的规范 |
| Claude Code,agentic 循环 | 这句话 + CLAUDE.md + 相关文件 + 运行测试 | 符合实际代码库模式,通过测试,处理已有代码处理的边界情况 |
相同模型,相同用户 prompt,三种不同输出质量。 差异来自 harness——来自它组装的有效上下文和它支持的迭代循环。
对于非平凡任务:
输出质量 = f(有效上下文, 模型能力, 迭代循环)用户控制有效上下文中的一小片(自己输入的 prompt)。Harness 控制其余部分,以及整个迭代循环。
给实践者的结论
- 原子问答中,prompt 质量≈一切。 Harness 无关紧要,用聊天机器人就够了。
- 真实代码库工作中,harness 在默默做大量工作。 推理时的有效 prompt 主要由 harness 构建,而非用户输入。
- 用功能做 prompt 根本无法完成的事:确定性(Hooks)、隔离(Subagents)、懒加载(
paths:规则)、持久化(Memory)、路由(model:)、并行执行。 - 强 prompt 是必要但不充分的。功能提供了 prompt 无法提供的确定性、隔离和组合能力,两者互补而非替代。
FAQ
Q: Hooks 是最无可替代的功能吗? A: Hooks 是最典型的"prompt 绝对无法替代"的功能。Prompt 是建议,模型可以忽略;Hook 是在模型的工具调用前后插入的确定性代码执行,模型无法绕过。特别是 PreToolUse Hook 可以阻断工具调用,这是 prompt 根本做不到的。
Q: 对于简单的一次性问答,用 Claude Code 有意义吗? A: 对单次原子任务,Claude Code 和聊天机器人的输出质量接近。Claude Code 的价值在于处理真实代码库——需要读文件、运行测试、迭代执行、遵守项目规范的工作。如果只是问一个独立问题,chatbot 就够了。
Q: 模块化系统提示是什么?用户能看到吗? A: Claude Code CLI 内部有 110+ 个系统提示片段,根据激活的功能(worktree/memory/tools 等)条件性拼装为最终系统提示。用户无法直接看到这些片段的完整内容,但可以通过 --verbose 模式和 --debug api 查看实际发送给模型的内容。