Agent.Space 博客

Claude Code v2.1.251 模型切换 Hooks 指南

了解 Claude Code v2.1.251 的 PreModelSwitch 与 PostModelSwitch,安全阻止、确认、记录并适配模型切换。

Claude Code v2.1.251 新增了两个模型切换生命周期事件:PreModelSwitch 在用户请求的切换发生前运行,可以允许、拒绝或要求确认;PostModelSwitch 在模型改变后运行,可以记录变化,或给下一次请求补充针对新模型的上下文。最关键的区别是:前者是一道策略门禁,后者是切换后的适配与审计点。

如果团队会分别用不同模型做规划、实现或审查,这个区别就很重要。模型切换可能改变成本、可用上下文和预期行为,但代码仓库本身不会因此变化。新 Hooks 可以让这次转换变得可见、可管理,不再依赖每位开发者都记得某条约定。

本文只讨论新的模型切换合同。如果你想先弄清 Claude Code 的访问方式如何计费,可以查看 Claude Code 价格指南

Claude Code 2.1.251 改了什么

Anthropic 的 v2.1.251 发布说明新增了 PreModelSwitchPostModelSwitch。同一版本还给恢复会话时的 SessionStart Hook 增加了会话陈旧程度和预计重新写入缓存成本字段,但这些字段不能取代两个新的模型切换事件。

在此之前,Hook 可以观察会话启动或拦截工具调用,却没有一个触发点能精确代表“会话正在切换模型”。新事件会暴露切换前模型、用户请求的目标、解析后的目标、切换来源,以及这次切换可能产生的提示词缓存重写成本估算。

两个模型切换事件都要求 Claude Code v2.1.251 或更高版本。如果共享项目配置依赖它们,就应该写清最低版本,并核对所有需要执行这项策略的环境是否满足要求。

PreModelSwitch 与 PostModelSwitch 有什么区别

两个名字看起来对称,但它们的权限和覆盖范围并不一样。

问题PreModelSwitchPostModelSwitch
何时运行?用户或客户端请求切换之后、真正切换之前会话模型已经改变之后
能阻止切换吗?可以不可以
能要求确认吗?可以,但受使用界面限制不可以
能观察自动 fallback 吗?不可以如果会话模型确实改变,就可以
能给新模型补充指导吗?不能通过 additionalContext 补充可以,在下一次请求中生效
典型任务策略门禁或成本提示审计、环境更新或模型专属指导

根据官方 PreModelSwitch 参考文档,这个事件会在 /model 命令和模型选择器、/config 的 Model 设置、部分 fast mode 变化,以及 Agent SDK 主机或 Remote Control 发起的模型请求中运行。Claude Code 自己触发的改变不会进入这个前置事件,例如自动 fallback 或恢复会话时还原模型。

PostModelSwitch既覆盖上述用户请求的切换,也会观察真正改变会话模型的自动 fallback、部分模式触发的变化,以及恢复会话时还原的模型。如果 fallback 链只是临时替代一个回合,而会话选中的模型没有改变,就不会触发它。

如果你的规则既要阻止不合规切换,又要保留完整的事后可见性,应同时使用两个事件。只用 PreModelSwitch,自动变化不会进入审计记录;只用 PostModelSwitch,虽然能看见结果,却无法撤销已经发生的切换。

在阻止、确认、提示和审计之间怎么选

先从 Hook 必须完成的任务出发。

阻止不允许的目标模型

当仓库或组织确实有模型白名单时,使用 PreModelSwitch。命令 Hook 可以用退出码 2,或返回结构化的 deny 决策来取消切换。它适合拦截项目不支持的模型、未经批准的 Provider 路径,或事故期间临时冻结的目标。

不要只依赖 matcher。Claude Code 通常会把 matcher 与目标模型的规范名称进行比较。如果某个自定义模型 ID 只有 LLM Gateway 能识别、Claude Code 无法将其规范化,它会运行所有相关 PreModelSwitch Hooks。因此,Hook 自己还必须检查 to_model,再决定允许还是拒绝。

在成本较高或会打断缓存时要求确认

PreModelSwitch 输入包含 context_tokensprompt_cache_warmcache_ttlestimated_cache_write_usd,以及该估算采用的价格来源。Hook 可以用这些字段解释:为什么在缓存仍然有效时切换模型,可能要重新发送上下文。

这个美元数字只能当作估算,不是账单。官方文档明确指出,服务端未必需要重新缓存全部上下文。

ask 决策还有一个重要限制:只有交互式会话里的 /model 能显示确认框。在非交互模式、/config 和 SDK 的 set_model 请求里,Claude Code 会把 ask 当作拒绝。如果自动化流程必须无人值守地继续,就应该设定明确的允许或拒绝规则,不能假设会有人看到弹窗。

给切换后的模型补充指导

如果新模型需要条件式上下文,例如一份模型专属的审查清单,或关于当前任务阶段的提示,可以使用 PostModelSwitch。命令 Hook 成功退出时输出的纯文本,或 JSON 里的 additionalContext,会在切换后的下一次请求中传给模型。

这类上下文应简短、客观。永远不变的项目规则仍然应该写在 CLAUDE.md;模型切换 Hook 更适合只随当前模型而变化的信息。

审计所有真正改变会话模型的事件

可以用 PostModelSwitch 把结构化事件发送到内部审计端点,或追加到经过批准的日志。至少记录时间、会话标识、from_modelto_modelsource。不要因为 Hook 能读到会话元数据,就顺手把完整对话或密钥复制进日志。

一个最小且相对安全的配置

Hooks 可以放在用户、项目、本地、组织托管、插件或组件配置中。项目级规则通常适合写在 .claude/settings.json,这样可以共享和审查;个人实验则更适合 .claude/settings.local.json 或用户设置。

下面这个最小模式使用宽泛 matcher,并在命令内部检查真实目标。使用前必须把 YOUR_APPROVED_MODEL_PATTERN 换成经过明确审查的正则表达式:

json
{  "hooks": {    "PreModelSwitch": [      {        "matcher": ".*",        "hooks": [          {            "type": "command",            "command": "jq -e '.to_model | test(\"YOUR_APPROVED_MODEL_PATTERN\")' >/dev/null || { echo 'Target model is not approved for this project.' >&2; exit 2; }"          }        ]      }    ],    "PostModelSwitch": [      {        "matcher": ".*",        "hooks": [          {            "type": "command",            "command": "jq -r '\"Session model changed to \\(.to_model). Apply the matching project review policy.\"'"          }        ]      }    ]  }}

这只是一个配置模式,不是通用白名单。它假设环境里已经安装 jq,并且团队能够用明确、安全的命名规则表达允许的模型。生产环境最好把逻辑放进一个可单独测试的脚本,而不是继续拉长内联 Shell 命令。

可以用 /hooks 检查 Claude Code 实际加载的配置,然后在一次可丢弃的会话里,从一个允许的模型切换到另一个允许的模型,再尝试一个应被拒绝的目标。还要测试恢复会话,以及团队真正使用的 SDK 控制切换路径。

上线前需要测试的运行边界

官方 Hooks 参考文档定义了几个必须纳入审查的边界:

  • PreModelSwitch 支持 command、HTTP 和 MCP tool 处理器,不支持 prompt 或 agent 处理器。
  • PreModelSwitch 命令超时会阻止切换;默认超时是 30 秒。策略 Hook 应保持快速、可靠。
  • 多个前置 Hook 给出不同结论时,优先级是 denyaskallow
  • PostModelSwitch 无法阻止切换。如果它在下一条提示词发出后的五秒内还没结束,其上下文可能延后到再下一次请求。
  • 项目 Hook 配置会执行代码。它应该像其他可执行仓库改动一样接受审查;不要在未检查时接受不可信 Workspace 的 Hooks。
  • Hooks 是对 Claude Code 权限系统的补充,不能取代操作系统隔离、密钥控制、Provider 策略或代码审查。

正因为有这些边界,一条短而明确的策略通常比试图推断所有情况的复杂脚本更安全。

Agent.Space 在这套流程里的位置

模型切换 Hooks 管理的是 Claude Code 内部行为。它们不会决定一条 API 请求由什么资金来源支付,也不会发现账户能使用哪些模型,更不会把一种 Provider 协议自动变成另一种。这些属于不同层。

Agent.Space Developer API 指南解释了另一层面向已验证服务端集成的 Agent.Space 访问合同:客户端先发现实时模型列表,再选择受支持的协议,而请求选择的模型会决定由 Share 还是 Flex 提供资源。Share 和 Flex 始终分开,请求不会在两者之间静默切换。该指南当前没有定义经过验证的 Claude Code 接入路径。

把两层分开后,组合流程会更容易理解:

  1. 用 Claude Code 的 PreModelSwitchPostModelSwitch 管理本机或组织的切换策略。
  2. 用当前访问 Provider 的实时模型发现和请求历史,核对当时真正可用、真正计费的对象。
  3. 始终区分 harness、模型、Workspace 和资金来源——这也是 Agent.Space 如何工作一文说明的核心边界。

不要把服务端 SDK 配置直接复制进 Claude Code,也不要仅凭 Anthropic Messages 协议就推断兼容性。Claude Code 只应连接访问 Provider 当前明确记录并验证的路径;Agent.Space Developer API 的资金选择仍是另一项服务端集成决策。

最实际的结论

PreModelSwitch 决定用户请求的模型转换能否发生;用 PostModelSwitch 观察最后真正生效的会话模型,并适配下一次请求。如果团队同时需要策略门禁和完整可见性,就同时部署两者,并在把它当作团队控制前测试自动化、恢复会话、自定义 Gateway ID 与超时行为。