Skip to content
源码分析手册

Fast Mode:请求层的速度标记位与动态冷却机制

先搞清楚这是什么

Fast Mode(快速模式)在 Claude Code 中并非指代某种轻量级小模型,它实际上是附着在 Opus 等主力模型请求上的一个运行时速度标记位(Speed Tag)

其本质在于:用户通过 /fast 表达一个“尽可能快”的愿望,而系统则根据当前的组织策略、账户额度、模型能力以及实时的负载状态(Cooldown),动态决定这一轮请求是否真正以 fast 速度发出。这是一种典型的“尽力而为(Best-effort)”服务模式,而非绝对的开关。如果将它误解为“切换模型”,就会忽略它在同一模型线路上通过 API Header 和参数进行调度的复杂逻辑。

代码里的真实逻辑

这套机制的运作逻辑分层清晰:从用户偏好设置,到会话状态计算,再到最终的请求参数注入。

三层状态的解耦

系统内部维护了三层独立的状态:

  1. 持久化设置(User Settings):存储在 settings.json 中,决定了用户是否“希望”默认开启快速模式。
  2. 会话状态(AppState):在 claude-code-opensource/src/main.tsx 初始化。即便是设置中开启了 Fast Mode,如果当前模型不支持(例如切到了 Haiku),会话状态也会被暂时重置。
  3. 运行时冷却(Runtime Cooldown):定义在 claude-code-opensource/src/utils/fastMode.ts 中。如果 API 返回 429 或 529 错误且重试等待时间较长,系统会自动切入 Cooldown 状态。此时用户偏好依然是“开启”,但实际发出的请求会被降级为标准速度(Normal Speed)。

请求层的精准标记

当请求发往 Anthropic API 时,claude-code-opensource/src/services/api/claude.ts 会进行多重校验。只有当功能未被禁用、环境可用、且不在冷却期时,请求才会带上 speed: 'fast' 参数以及特殊的 FAST_MODE_BETA_HEADER

为了保护提示词缓存(Prompt Cache),系统还实现了一个 Sticky Latch 机制:一旦在会话中首次使用了 Fast Mode 的 Beta Header,后续请求将持续携带该 Header,避免因 Header 变化导致服务端缓存键(Cache Key)失效,从而降低响应速度和增加成本。

自动降级与持久化清除

claude-code-opensource/src/services/api/withRetry.ts 承担了智能回退的职责。当检测到快速模式超限时,它不会简单报错,而是将请求转为标准速度进行重试,并向用户发出通知。

更严厉的逻辑在于权限拒绝处理:如果 API 明确返回“组织不允许使用 Fast Mode”或“额度已彻底枯竭”,handleFastModeRejectedByAPI() 会直接清除本地的 userSettings.fastMode 偏好。这意味着某些类型的失败不是暂时冷却,而是“永久撤销”,以防止用户在不具备条件的场景下持续发起无效的快速请求。

每会话重新加入(Per-session Opt-in)

对于受管环境,管理员可以配置 fastModePerSessionOptIn: true。在 main.tsx 的初始化阶段,getInitialFastModeSetting() 会识别该项:即便用户全局开启了 Fast Mode,每个新会话启动时也会被强制设为关闭状态。这迫使开发者在每个独立任务中显式权衡是否需要消耗更高成本或额度的快速通道。

使用时的关键约束

第一,模型没有变,变的是速度参数。开启 Fast Mode 可能会把你推向 Opus 4.6,但它与 Standard Opus 4.6 之间唯一的物理区别在于请求体中的 speed 字段。

第二,关闭不代表“回滚”。关闭 Fast Mode 仅仅是去掉了速度标记,系统并不会自动帮你切回到你上一个使用的非 Opus 模型。

第三,冷却(Cooldown)是静默的。当你看到提示说进入冷却时,你的 /fast 开关可能还是亮的,但此时的推理速度已经降级,直到冷却计时器结束。

第四,环境依赖性极高。在第三方 Provider(如 Bedrock 或 Vertex)或非交互式认证路径下,Fast Mode 会被 getFastModeUnavailableReason() 判定为直接不可用,此时 /fast 命令将失效或隐藏。

第五,缓存破坏检测。中途切换 Fast Mode 会被系统标记为一次 Cache Break。如果你极其在意 Prompt Cache 带来的性能提升,应在会话开始前就决定好是否使用 Fast Mode,中途反复横跳会浪费大量缓存。

接下来看什么

如果你关注快速模式对 Prompt Cache 命中的影响,建议阅读 Prompt Cache Break Detection 相关的源码。

如果你想了解管理员如何配置每会话强制 Opt-in,可以回到 Server-managed Settings 章节。

如果你正在开发一个高频调用 API 的插件,应重点研究 withRetry.ts 中关于 429 降级的处理策略。

源码锚点

  • claude-code-opensource/src/utils/fastMode.ts: Fast Mode 能力判定、冷却状态管理及 API 拒绝后的清除逻辑。
📄 src/utils/fastMode.ts — Fast Mode 能力判定、冷却状态管理及 API 拒绝后的清除逻辑。L38-40 of 533
typescript
export function isFastModeEnabled(): boolean {
  return !isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_FAST_MODE)
}
  • claude-code-opensource/src/services/api/claude.ts: 请求参数 speed: 'fast' 与 Beta Header 的注入点。
📄 src/services/api/claude.ts — 请求参数 `speed: 'fast'` 与 Beta Header 的注入点。L2-20 of 3420
typescript
  BetaContentBlock,
  BetaContentBlockParam,
  BetaImageBlockParam,
  BetaJSONOutputFormat,
  BetaMessage,
  BetaMessageDeltaUsage,
  BetaMessageStreamParams,
  BetaOutputConfig,
  BetaRawMessageStreamEvent,
  BetaRequestDocumentBlock,
  BetaStopReason,
  BetaToolChoiceAuto,
  BetaToolChoiceTool,
  BetaToolResultBlockParam,
  BetaToolUnion,
  BetaUsage,
  BetaMessageParam as MessageParam,
} from '@anthropic-ai/sdk/resources/beta/messages/messages.mjs'
import type { TextBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'
  • claude-code-opensource/src/services/api/withRetry.ts: 429/529 触发的自动重试降级与冷却触发机制。
📄 src/services/api/withRetry.ts — 429/529 触发的自动重试降级与冷却触发机制。L27-34 of 823
typescript
  type CooldownReason,
  handleFastModeOverageRejection,
  handleFastModeRejectedByAPI,
  isFastModeCooldown,
  isFastModeEnabled,
  triggerFastModeCooldown,
} from '../../utils/fastMode.js'
import { isNonCustomOpusModel } from '../../utils/model/model.js'
  • claude-code-opensource/src/commands/fast/fast.tsx: /fast 命令的实现,包括对 AppState 和 User Settings 的修改。
📄 src/commands/fast/fast.tsx — `/fast` 命令的实现,包括对 AppState 和 User Settings 的修改。L16-40 of 269
tsx
function applyFastMode(enable: boolean, setAppState: (f: (prev: AppState) => AppState) => void): void {
  clearFastModeCooldown();
  updateSettingsForSource('userSettings', {
    fastMode: enable ? true : undefined
  });
  if (enable) {
    setAppState(prev => {
      // Only switch model if current model doesn't support fast mode
      const needsModelSwitch = !isFastModeSupportedByModel(prev.mainLoopModel);
      return {
        ...prev,
        ...(needsModelSwitch ? {
          mainLoopModel: getFastModeModel(),
          mainLoopModelForSession: null
        } : {}),
        fastMode: true
      };
    });
  } else {
    setAppState(prev => ({
      ...prev,
      fastMode: false
    }));
  }
}
  • claude-code-opensource/src/main.tsx: 启动时基于 fastModePerSessionOptIn 的状态初始化逻辑。
📄 src/main.tsx — 启动时基于 `fastModePerSessionOptIn` 的状态初始化逻辑。L70-82 of 4684
tsx
const getTeammateUtils = () => require('./utils/teammate.js') as typeof import('./utils/teammate.js');
const getTeammatePromptAddendum = () => require('./utils/swarm/teammatePromptAddendum.js') as typeof import('./utils/swarm/teammatePromptAddendum.js');
const getTeammateModeSnapshot = () => require('./utils/swarm/backends/teammateModeSnapshot.js') as typeof import('./utils/swarm/backends/teammateModeSnapshot.js');
/* eslint-enable @typescript-eslint/no-require-imports */
// Dead code elimination: conditional import for COORDINATOR_MODE
/* eslint-disable @typescript-eslint/no-require-imports */
const coordinatorModeModule = feature('COORDINATOR_MODE') ? require('./coordinator/coordinatorMode.js') as typeof import('./coordinator/coordinatorMode.js') : null;
/* eslint-enable @typescript-eslint/no-require-imports */
// Dead code elimination: conditional import for KAIROS (assistant mode)
/* eslint-disable @typescript-eslint/no-require-imports */
const assistantModule = feature('KAIROS') ? require('./assistant/index.js') as typeof import('./assistant/index.js') : null;
const kairosGate = feature('KAIROS') ? require('./assistant/gate.js') as typeof import('./assistant/gate.js') : null;
import { relative, resolve } from 'path';
  • claude-code-opensource/src/hooks/notifs/useFastModeNotification.tsx: 将运行时状态转换为前台通知的 Hook。
📄 src/hooks/notifs/useFastModeNotification.tsx — 将运行时状态转换为前台通知的 Hook。L8-37 of 162
tsx
const COOLDOWN_STARTED_KEY = 'fast-mode-cooldown-started';
const COOLDOWN_EXPIRED_KEY = 'fast-mode-cooldown-expired';
const ORG_CHANGED_KEY = 'fast-mode-org-changed';
const OVERAGE_REJECTED_KEY = 'fast-mode-overage-rejected';
export function useFastModeNotification() {
  const $ = _c(13);
  const {
    addNotification
  } = useNotifications();
  const isFastMode = useAppState(_temp);
  const setAppState = useSetAppState();
  let t0;
  let t1;
  if ($[0] !== addNotification || $[1] !== isFastMode || $[2] !== setAppState) {
    t0 = () => {
      if (getIsRemoteMode()) {
        return;
      }
      if (!isFastModeEnabled()) {
        return;
      }
      return onOrgFastModeChanged(orgEnabled => {
        if (orgEnabled) {
          addNotification({
            key: ORG_CHANGED_KEY,
            color: "fastMode",
            priority: "immediate",
            text: "Fast mode is now available \xB7 /fast to turn on"
          });
        } else {

基于 Claude Code v2.1.88 开源快照的深度分析