首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Claude Code 的工程约束:模型提议,harness 裁决

Claude Code 的工程约束:模型提议,harness 裁决

原创
作者头像
IT大佬 jzit-top
发布于 2026-11-06 16:56:52
发布于 2026-11-06 16:56:52
1480
举报

Claude Code 的代码库中,决策逻辑只占约 1.6%,剩下 98.4% 是运行时护栏——权限检查、上下文压缩、工具执行、安全约束。这个比例揭示了一个常被误解的事实:Claude Code 的核心竞争力不在模型,而在模型周围那一层 agentic harness。Anthropic 官方文档的原话是:“Claude Code 提供工具、上下文管理和执行环境,将语言模型转变为一个有能力的编程智能体”。模型负责推理,harness 负责决定推理的后果能触及什么。理解这条边界,是从“会用 Claude Code”到“能用 Claude Code 做工程”的分水岭。

架构的第一性原理是模型与裁决的分离。 官方文档将 Claude 的工作划分为三个阶段:收集上下文、采取行动、验证结果,循环往复直到任务收敛。工具调用前,harness 按 deny/ask/allow 的顺序评估规则,deny 永远优先;一个被攻破的模型无法通过“说服”绕过安全检查,因为 harness 不读取模型的论点。下面的 Python 片段复现了这条裁决链的核心逻辑:模型输出工具调用请求,harness 独立决定放行、询问还是拦截,模型没有权限修改裁决结果。

代码语言:javascript
复制
from dataclasses import dataclass

@dataclass
class ToolCall:
    name: str
    target: str          # 文件路径或 shell 命令
    intent_risk: float   # 模型自报风险,仅参考,不影响裁决

DENY = ["secrets/", "migrations/", ".env"]
ASK  = ["git push", "rm -rf"]

def harness_gate(call: ToolCall) -> str:
    if any(p in call.target for p in DENY):
        return "BLOCK"                    # deny 优先,模型自报再低也拦截
    if any(p in call.target for p in ASK):
        return "ASK"                      # 需要用户确认
    return "ALLOW"

intent_risk 字段的存在是一个刻意的讽刺:模型可以“觉得自己很安全”,但 harness 的裁决完全忽略它。规则匹配的是工具调用,不是模型的意图——这是 Claude Code 安全模型的底层假设。

第二层约束是上下文的预算治理。 CLAUDE.md 不是一个大文件,而是一棵按目录分层的规则树:启动时加载工作目录及所有祖先目录的文件,子目录文件按需加载。根文件放全仓库通用规则,保持在约 200 行以内;每个子目录的 CLAUDE.md 只放该区域的栈特定约定。这个设计解决的不是“怎么写 Prompt”,而是有限上下文窗口的分配问题:无关子系统的约定在启动时根本不进入上下文。

但 CLAUDE.md 有一个根本局限:它是建议,不是强制。官方最佳实践对此说得很直接:CLAUDE.md 用于准则,Claude 可以判定某条准则不适用;对于“几乎”还不够好的规则,必须从 CLAUDE.md 移入 harness 自行应用的配置中。真正的硬约束是 Hooks:在工具调用前后运行外部命令,按退出码决定放行或拦截。一个 PreToolUse hook 返回 deny 时,即使 bypassPermissions 模式处于激活状态,工具调用仍然被阻止。下面的配置在每次 Edit 或 Write 之后强制运行 Prettier,在每次 Bash 调用前检查目标路径:CLAUDE.md 管“建议什么”,Hooks 管“禁止什么”,规则一旦是零例外的,就必须离开 Prompt,进入代码。

代码语言:javascript
复制
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Bash",
      "hooks": [{"type": "command", "command": "python3 .claude/guard.py"}]
    }],
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{"type": "command",
        "command": "npx prettier --write --ignore-unknown \"$(jq -r '.tool_input.file_path')\""}]
    }]
  }
}

第三层约束是 Subagent 的隔离与权限收窄。 每个 Subagent 在独立的上下文窗口中运行,拥有自定义的系统提示和受限的工具集,完成后只把摘要返回主对话。这意味着一个被定义为“只读代码审查员”的 Subagent,物理上没有 Edit 和 Bash 权限——它的能力边界不是靠提示词约束的,而是靠 tools 字段的白名单在架构层面锁死的。主对话的上下文不会被审查过程中的文件读取和搜索结果污染,而 Subagent 的产出是一段可直接消费的结论,而不是一堆需要二次筛选的原始日志。

最后,当 Claude Code 需要进入流水线而非停留在终端时,SDK 把同一个 agent loop 暴露为可编程接口,用于 CI/CD 管道、生产自动化和自定义应用。在这个场景下,两个参数从“可选”变成“必须”:max_turns 限制循环轮数,max_budget_usd 限制累计花费;--bare 模式跳过 hooks 和 CLAUDE.md 的自动发现,保证同一脚本在不同机器上产生一致的行为。没有预算上限的开放提示(如“改进这个代码库”)可能让循环持续到不可接受的成本,SDK 的护栏不是便利功能,而是生产部署的前置条件。

Claude Code 的专业性,最终不体现在“模型有多聪明”,而体现在每一层约束的归属是否清晰:模型提议动作,harness 裁决后果;CLAUDE.md 管理建议性的上下文,Hooks 执行零例外的硬规则;Subagent 收窄权限以保护主上下文,SDK 用预算和轮数把自主性关进可计量的笼子。把这四条边界写进仓库的配置文件,而不是某个人脑袋里的提示词习惯,才是 Claude Code 从“个人助手”走向“团队基础设施”的标志。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档