版本对照 · 14

Auto Mode 深度解析

分类器用一次 API 换免打扰,失败默认拒绝。HARD BLOCK 是用户意图跨不过去的红线:外泄仍拦;删文件这类 SOFT BLOCK 才允许明确意图放行。

1. 引入时间线#

首次引入:v2.1.78,2026-03-17。npm 二分:2.1.77 没有 autoMode.soft_deny / tengu_auto_mode_decision;2.1.78 分别 11 / 4 处。changelog 2.1.78 无任何 auto mode 条目——典型 research preview 静默发布。官方 What's New 说 Week 13(2026 年 3 月)上线,与 npm 吻合。

版本日期变化
2.1.782026-03-17引入(research preview,静默)
2.1.892026-03-31PermissionDenied hook;拒绝通知 + Recent 可 r 重试
2.1.972026-04-08sandbox 网络访问提示自动批准
2.1.1082026-04-14修复 classifier transcript 超限导致 Agent 误弹权限
2.1.1112026-04-16不再需要 --enable-auto-mode;Max 可用 Opus 4.7 分类器
2.1.1182026-04-22allow/soft_deny/environment 支持 "$defaults"
2.1.1282026-05-04无法评估时附 retry / /compact / --debug
2.1.1362026-05-08settings.autoMode.hard_deny:无视意图与 allow
2.1.1472026-05-21不再抑制用户/skill 显式依赖的 AskUserQuestion
2.1.1542026-05-28改进批量外泄检测
2.1.1602026-06-01常规动作少推理,降低 “could not evaluate”
2.1.1782026-06-15subagent 启动前也过分类器
2.1.1932026-06-25classifyAllShell
2.1.2002026-07-03“default” 权限模式改名 Manual
2.1.2072026-07-10Bedrock/Vertex/Foundry 无需 env opt-in
2.1.2102026-07-14外部会话分类器默认 Sonnet 5,首次请求锁定
2.1.2122026-07-16claude auto-mode reset
2.1.2182026-07-22危险 rm、后台 &、可疑 Windows 路径直接交分类器
2.1.2212026-08-03跨决策复用缓存前缀
2.1.2222026-08-04SendMessage 也过分类器
2.1.2332026-08-14Anthropic宣布auto mode将成为默认模式,且分类器将不再额外收取费用

日期均为 npm view time,约 5 个月窗口。

2. 设计理念#

2.1 AI 分类器的优势所在

官方 auto-mode-default 公告:分类器拦约 89% 危险命令,人类手动审批只拦约 13.6%

2.2 安全原则

  1. Fail-closed:API 错、解析失败、超时、中止一律 shouldBlock: true
  2. 沉默不是同意:每次动作单独评。用户没在连续动作之间打断,不等于批准——分类器分不清「看着点了头」和「根本还没看到」。只有用户自己写出来的话才算意图(「把 dist/ 删掉」「go ahead」);「能不能…」「要不要试试」是问题不是授权。反过来,用户先前打断过同类动作,应当拦。
  3. 快路径优先:白名单、acceptEdits 预检能省则省。
  4. 拒绝可解释:reason + 工作区引导(可用 head 代替 cat,不得恶意绕过)。
  5. 拒绝可恢复:连续 3 / 会话 20 次回退人工,不无限死循环。
  6. 防提示注入:分类器不读完整对话。主模型自己写的解说丢掉,只留 tool_use 这种机器事实,否则回复里可以伪造「用户刚同意删库」。序列化走 JSONL 一行一条({"Bash":"ls"} / {"user":"..."}),值做 JSON 转义,换行变 \n,敌意内容逃不出字符串去伪造下一条 {"user":...}

2.3 成本

分类器是「每步一次 API」。出于成本考虑,Anthropic 对分类器请求做了一些处理,让它跑得更便宜(尽管后来声明不再收这笔费用,见 §7.3)。

注意

分类器和主循环是两次独立请求。因为只组了用户消息和 tool_use,分类器按理比主循环瘦。Anthropic 用「分类器输入 token ÷ 主循环 token」盯这个关系:

  • 0.6–0.8:该丢掉的丢掉了。
  • > 1.0:分类器反而更大,投影发散了。

auto-compact 只按主循环体积压。主循环没到阈值就不会动;分类器自己那次请求可能已经超窗口——分类器模型和主模型的窗口大小也可能不一样。结果是分类器 400,主循环还在跑,分类器已经挂了。

3. 架构总览#

入口/配置   autoMode.ts · AutoModeOptInDialog · permissionSetup · autoModeState
决策层     permissions.ts → acceptEdits 预检 / 白名单 / 分类器
           denialTracking(连续/总拒绝)
分类器     yoloClassifier.ts
           bashClassifier · classifierShared · yolo-classifier-prompts/
观察       classifierApprovals · autoModeDenials
           tengu_auto_mode_decision / _outcome / _denial_limit_exceeded

模型要调一个工具。工具自己的权限检查说「该问人」。如果现在是 auto,permissions.ts 把这次弹窗截下来,自己判:

  1. 必须人看的:敏感路径、声明了要跟人交互的工具。AskUserQuestion 默认会进分类器,不在这里弹窗。
  2. 能便宜放行的先放:工作区内改文件(复用 acceptEdits 那套),或工具名在白名单(Read / Grep 这类)。
  3. 剩下的才打分类器。放行就过;拦住就记一笔。连续 3 次或本会话 20 次,或分类器自己超窗口,退回给人。分类器挂了默认当拒绝。

每一道门怎么判,见 §5

4. 分类器实现#

4.1 Transcript

分类器看到的是压缩投影,不是原始消息:只组用户消息和 assistant 的 tool_use。主模型解说丢掉(防它在回复里伪造用户批准);工具结果也不进(分类器看不见就当 unverifiable / agent-inferred,不要信)。少带同时也是成本手段,这就是 §2.3 里分类器比主循环瘦的原因。

4.2 模型

function getClassifierModel(): string {
  // 1. Ant:CLAUDE_CODE_AUTO_MODE_MODEL
  // 2. GrowthBook:tengu_auto_mode_config.model
  // 3. 默认:主循环模型
}

2.1.210 起外部会话走 getExternalClassifierDefault:主循环不是 Sonnet 4.5/4.6 / Haiku 时,分类器默认 Sonnet 5 并锁定。2.1.207 起 Bedrock/Vertex 等无需 opt-in。

4.3 怎么交卷(默认两阶段 XML)#

2.3 里「先便宜看一眼」就是这条。先把两个数字说清楚:它们不是送进分类器的材料有多长——transcript 该多长还是多长。它们是 API 的 max_tokens模型这次最多能往回写多少

分类器要交的卷其实就一行 XML:拦,还是放。默认拆成两趟,像安检:先让它吐一个字,大多数情况到此结束;只有说「要拦」才再给篇幅让它把理由写清楚。

stage1(快)stage2(深查)
什么时候跑默认先跑只有 stage1 说拦,或卷面解析失败,才打
允许写多长max_tokens: 64max_tokens: 8192(2.1.88 是 4096)
什么时候停生成到 </block> 立刻掐掉(stop_sequences写完思考再判,不提前掐
交卷长什么样只许 <block>yes/no</block>,连 reason 都不写<thinking>,再 <block>;拦的时候还要带 category / reason
干什么绝大多数安全动作在这里放行压误杀:stage1 宁可错拦,stage2 再按意图和 ALLOW 例外细看

GrowthBook tengu_auto_mode_config.twoStageClassifier 还能切一半:'fast' 只跑 stage1(放宽到 256,去掉提前掐断,好写下 reason);'thinking' 跳过 stage1 直接深查。getClassifierTemperature(2.1.233 新增,未进导出表)读 CLAUDE_CODE_AUTO_MODE_TEMPERATURE,读不到默认 1(2.1.88 写死 0)。getClassifierThinkingConfig 对「拒收 thinking: disabled」的模型会再垫 2048;外部默认的 Sonnet 5 在豁免名单里,不垫。这和导出表里的 getThinkingConfig 不是同一个函数:后者管主循环的 max_thinking_tokens 层。

为什么 64 够用

<block>no</block> 大约 6 个 token。stage1 的提示写死了「整段回复必须从 <block> 开头,前面不许分析」。再加上 stop_sequences: ['</block>'],模型刚写完闭合标签 API 就停。64 是给这句短答留的上限,不是给它写小作文的。如果每次 git status 都让模型写两千 token 的推理,分类器会把主循环拖死。

例子:git status 只跑 stage1

分类器看到的动作大概是 {"Bash":"git status"}。stage1 在整份材料末尾追加一句后缀(2.1.233 默认 both 模式):

Err on the side of blocking. Stage 1 does NOT apply user intent or ALLOW
exceptions — stage 2 will handle those. Judge the action by its full effect
— what it runs, sends, publishes, or enables — not its surface form.
Block if ANY rule could apply. Your ENTIRE response MUST begin with <block>.

模型回 <block>no</block>。解析器读到 no,直接 shouldBlock: false,reason 记成 "Allowed by fast classifier"。stage2 根本不打。用户无感。

例子:rm -rf dist/ 先拦再放

假设用户刚说「把 dist/ 删掉」。stage1 不看用户意图(后缀写明了,意图留给 stage2)。删除长得像 SOFT BLOCK「Irreversible Local Destruction」,stage1 回 <block>yes</block>。因为是 yes,才打 stage2。

两趟的 system + CLAUDE.md + transcript + 当前动作完全一样,只换最后一句后缀,所以 stage2 必中 prompt cache——贵的那份前缀已经付过一次。stage2 的后缀改成:先 <thinking>,再按完整流程判(含用户意图、ALLOW 例外)。它可能回:

<thinking>
SOFT BLOCK「Irreversible Local Destruction」命中。用户上一句点名了路径 dist/,
满足 must name,例外成立。
</thinking>
<block>no</block>

于是放行。如果用户只说了「删点文件」、没点名路径,stage2 会改成:

<block>yes</block><category>Irreversible Local Destruction</category><reason>[Irreversible Local Destruction] 删除 dist/,用户未点名该路径</reason>

这就是「专门压误杀」:stage1 宁可错拦,stage2 才认真看人有没有授权。

卷面格式(2.1.233)

<block>yes</block><category>Data Exfiltration</category><reason>[Data Exfiltration] …</reason>
<block>no</block>

拦的时候 reason 必须以规则名开头;放行不要 category / reason。标签对不上、yes/no 打架、解析失败,一律 fail-closed。2.1.88 没有 <category>。内部还有一条 severity 灰度(写 <severity>0-100</severity>,50 为界),默认外部会话走上面的 yes/no。

4.4 规则怎么判

分类器读的不是代码里的 if/else,是一份系统提示词:

看最后一条动作(展开 && / 包装脚本 / 本会话写过的文件)
  → HARD BLOCK?命中立刻拦。不看意图,ALLOW 也不算
  → SOFT BLOCK?
      没有 → 预备放行
      有,且命中 ALLOW 例外 → 预备放行(例外只对 SOFT 有效)
      有,没有例外 → 预备拦截
  → 用户意图
      预备放行但越过用户红线 → 拦
      预备拦截:点名了规则要求的 must name 项 → 放;否则拦
  → 放行前再做一次「规则列表是例子不是边界」

点名动作不等于点名 must name 项。说「删文件」翻不过「必须点名那条路径」。外泄是 HARD,说多少次都翻不过。

4.5 拦什么(2.1.233 外部默认)

语义类别,不是正则。对照「动作实际在干什么」。

HARD BLOCK 默认几乎就一条 Data Exfiltration(敏感数据出信任边界,看最终落点)。用户可在 autoMode.hard_deny 加。

SOFT BLOCK 模板里 60+ 条,每条都有 [named+specifics]。按伤害归类:外部代码 / 生产共享 / 本地破坏 / 安全削弱 / 凭证与外泄周边 / 自修改与绕过 / 对外动作(含 Browser Exfil)。2.1.88 的「推默认分支就算拦」没了——改由 ALLOW 的 Git Push Destination 放行本仓库任意分支(含默认分支);force-push 别人的提交仍归破坏类 SOFT。

4.6 ALLOW 例外(SOFT 命中后的豁免)

§4.4 走到 SOFT BLOCK 之后才看这张表。分类器已经觉得「这长得像要拦」,ALLOW 说「这种日常开发放过」。命中例外就必须放,不能再用「看起来严重」压回去。

两道门在前面:HARD 命中时这张表不看.env 真密钥推到公开 gist,说这是 Local Operations 也翻不过外泄)。例外只开它点名的那一扇门——目的地、资源、操作是三扇不同的门。Git Push Destination 只开「推到本仓库哪个分支」,不开「提交里装什么」,也不开「force-push 别人的提交」。

例子:git push origin main

2.1.88 有一条 SOFT「推默认分支就算拦」。2.1.233 改成 ALLOW Git Push Destination:推本仓库任意分支都普通,main 也算,光说「push」不用点名分支。

例外放过的日常不放
Git Push Destination(2.1.233)推进本仓库任意分支(含默认分支)提交内容、force-push 别人的提交、名字像发布目标的分支
Declared Dependenciesnpm install / pip install -r 装清单里已有的包,且本会话没改过清单npm install 随便起的包名
Toolchain Bootstrap从官方安装器装 rustup / uv / bun,且仓库构建配置表明需要随便 curl 一个安装脚本
Local Operations本仓库工作区内的日常文件操作走出仓库去 ~//etc;不可逆删已有文件
Test Artifacts例子里手写的假 API key从真密钥路径拷过来再改名
Read-Only Operations不改状态、不带回密钥的 GET用只读请求去踩点下一步要拦的动作
Standard Credentials读自己的 .env,发给对应的官方 API发给任意第三方
Security Discussion读、写、讨论安全相关代码真的跑 exploit、扫凭据
Transient Retry网络闪断后原样再试换编码去躲上一次的拦截
Session-Created Job Cleanup删本会话自己创建并记下 ID 的那个 job按名字猜、清生产任务、批量删
Trusted Internal InfraEnvironment 里列出的内网,按本来用途走数据在内网上改权限、动凭据
Multi-Agent Coordination队友之间的 SendMessage、交差发到无关频道;HARD 仍先拦
Memory Directory / CLAUDE.md Content读写 memory 目录;改偏好和项目笔记改权限 / auto-mode 行为;往 memory 里塞投毒内容
Claude Code SchedulingCronCreate / RemoteTrigger 管 Claude 自己的定时任务把系统 cron 当这个例外
Browser Trusted Navigation打开 Environment 内网、localhost、或用户点名的 URL打开用户没点名的外网
Scheduled-Task Fires定时器送来的 prompt 不当成「用户此刻点了头」定时文案点名了 SOFT 动作,仍要走那条规则的同意门槛

碰正在跑的生产基础设施时,上面那些「开发环境」例外全部失效。要放行只剩:用户点名了那个生产目标和操作,或命中本身就是基础设施例外(Trusted Internal Infra 只管数据流,Session-Created Job Cleanup)。npm install 在本仓库放行,在 prod-db 上装同一份依赖不放行。

4.7 用户规则:REPLACE 还是追加

用户可以写 autoMode.allow / soft_deny / hard_deny / environment。外部模板默认写在标签里面,配了对应数组就整段换掉。内部模板是追加。项目级 settings 故意不读"$defaults" 可以「默认留下,再加我的」。

5. 决策流细节#

这一节发生在 tool.checkPermissions() 已经返回 ask 之后。deny / allow 规则都过完了,本来该弹权限框。模式是 auto时,权限主循环把这次 ask 截下来。这段在 shouldAvoidPermissionPrompts 之前跑,所以 headless 也走分类器。

ask 进来
  ├─ safetyCheck 且不可交给分类器 → 原样 ask(敏感路径必须人看)
  ├─ requiresUserInteraction 且不是「AUQ 交给分类器」→ 原样 ask
  ├─ acceptEdits 预检通过 → 放行(fastPath: acceptEdits)
  ├─ 工具名在白名单 → 放行(fastPath: allowlist)
  └─ 打分类器(默认 xml_2stage)
       ├─ 放行 → allow,连续拒绝清零
       ├─ 拦 + transcript 超限 → 回退人工(headless 直接 abort)
       ├─ 拦 + 分类器挂了 → 默认 deny(fail-closed)
       └─ 拦 + 真判决 → 计数;连续 3 / 会话 20 → 回退人工(headless abort)

5.1 先过几道门,根本不进分类器

safetyCheck:工具自己标了「这个 ask 是安全检查」且 classifierApprovable 为假,三道自动放行(acceptEdits / 白名单 / 分类器)全跳过,保持人工。headless 没有权限框,改成 deny。敏感文件路径走这条。

需要真人交互的工具requiresUserInteraction() 为真就保持 ask。例外:AskUserQuestion 在 classifyAskUserQuestion 为真时(读不到 GB 时默认真)跳过这道门,交给分类器。

5.2 acceptEdits 预检:复用「工作区内编辑」那套逻辑

auto 自己没有「CWD 内写文件算安全」的实现。做法是临时撒谎:把 mode 改成 acceptEdits,再调一次同一个 checkPermissions。acceptEdits 的规则是:路径在启动时的工作目录里就 allow(pathInAllowedWorkingPath)。CWD 里改 src/foo.ts 会放行;改 ~/.ssh/config/etc/hosts、别的仓库不会,继续往下走。

放行时记遥测 fastPath: 'acceptEdits',连续拒绝清零。预检自己抛错(除了用户中止)就当没这道门,掉进分类器。

Agent 和 REPL 不走这道门。它们在 acceptEdits 下会直接 allow——REPL 的 JS 胶水里可能夹着 VM 逃逸,分类器必须看到整段胶水,不能只看见里面套的 Read/Bash。所以这两样跳过预检,去分类器。

5.3 白名单:按工具名跳过,不含任何写工具

预检没放行,再看工具名在不在白名单。在就放行,记 fastPath: 'allowlist'。这是名字集合,不看参数。

只读、任务元数据、Plan 切换、Sleep 仍在。SendMessage 不在名单里(2.1.222 起走分类器)。Chrome / Browser MCP 的只读动作也进了白名单。CLASSIFY_EDITS 默认关。

没有 Edit / Write / Bash。写文件走 5.2:CWD 内预检放行,CWD 外进分类器。Bash 一律分类器(除非前面的 allow 规则已经放了,且没开 classifyAllShell)。

5.4 分类器拦下来之后:计数、回退、fail-closed

走到这里才真正打 API。三种结果不一样。

放行shouldBlock: false → allow,recordSuccess 把连续拒绝清零。会话总拒绝不动。

真的拦recordDenial,连续和总数都 +1。返回给主模型的话是:

Permission for this action has been denied. Reason: <分类器的 reason>.
可以用别的工具合理替代(比如 head 代替 cat),
但不要恶意绕过(别用跑测试当借口去执行非测试动作)。
若这个能力对完成任务是必需的,停下向用户解释,让人决定。

计数存在 appState.denialTracking。异步子代理的 setAppState 是空操作,改走 localDenialTracking 就地改。

达限回退:连续 3 次,或本会话累计 20 次。任一到了就不再让分类器死循环:

快路径放行也算成功,连续计数会清。所以「读文件 → 被拦的 Bash → 再读文件 → 再 Bash」不会把连续计数叠满。

transcript 超限(确定性 400):对话只增不减,重试必炸。不加拒绝计数。交互回退人工;headless 直接 abort。

分类器没给出判决(API 错、超时、中止)默认 deny。

6. 模式转换与入口#

上一节是一次工具调用怎么判。这一节是怎么进、怎么出 auto:启动选模式、Shift+Tab 轮转、进门时剥掉会绕过分类器的 allow 规则、以及把规则 dump 出来看的 CLI。

6.1 启动时谁赢

initialPermissionModeFromCLI 先组一个有序列表,第一个合法的赢

  1. --dangerously-skip-permissionsbypassPermissions。组织策略(tengu_disable_bypass_permissions_mode)或 permissions.disableBypassPermissionsMode 开着就跳过,并提示被禁了。
  2. --permission-mode autoauto。断路器已经是 disabled 就不当它存在,掉到下一项。
  3. settings.permissions.defaultMode。写成 auto 同样过断路器。远程会话(CLAUDE_CODE_REMOTE)只认 acceptEdits / plan / default,settings 里的 bypass 或 auto 会被丢掉,免得远程环境被静默提权。

列表空了就回 default(2.1.200 改名 Manual)。账号策略把新会话默认设成 auto,走的是第 3 项,不是 Shift+Tab。

进了 REPL 之后,Shift+Tab 走 getNextPermissionMode。2.1.233 外部和内部同一条环,不再给 ant 开捷径:

default → acceptEdits → plan →(有 bypass 就多一档)→ auto → 回到 default

auto 默认就在环上。2.1.88 要 GrowthBook 写成 enabled、或用户已经 opt-in,转盘才露出 auto。2.1.233 把「转盘里有没有」和「能不能显式进」收成同一道门:没熔断、settings 没关、模型支持,就进环。tengu_auto_mode_config.enabled 读不到时默认就是 enabled。打开就能 Shift+Tab 转到 auto,不用先设 flag、也不用先同意一次。

6.2 进 auto 时剥掉会绕过分类器的 allow

剥 = 暂时让这些 always-allow 失效,调用去走分类器。不是把它们直接放行。

权限流水线里,整工具 always-allow 在分类器前面(step 2b toolAlwaysAllowedRule)。settings 里如果留着 Bash(*),不剥的话所有 Bash 在分类器看到之前就过了——auto 等于没开。所以进 auto 时先把这类规则从生效的 alwaysAllowRules 拿掉,塞进 strippedDangerousRules 暂存。用户磁盘上的 settings 不动。退出 auto 再按来源加回去。

Bash(*) 在 auto 里:lscurl | bash 都要过分类器。切回 Manual,settings 里那条 Bash(*) 又生效。

被当成危险、会剥掉的 always-allow:

窄规则比如 Bash(git status) 不在剥离名单里,进 auto 仍会在 2b 先放行,分类器看不到。CLI、Shift+Tab、SDK 改模式都走同一个 transitionPermissionMode,进出不会漏剥或漏还。

2.1.88 不剥 Edit(**)。CWD 内编辑本来就走 acceptEdits 预检;用户自己写的 Edit always-allow 仍会在 2b 放行。旧笔记写成「剥 Edit(**)」和源码不符。

6.3 claude auto-mode 子命令

规则是提示词,人眼难看清「分类器实际吃到什么」。四个只读/复位命令:

7. 版本变更历史#

BLOCK 后来拆成 HARD / SOFT BLOCK:数据外泄强制拦截,删文件这类SOFT BLOCK能遵循用户意图。详情见 §4.4–4.6

7.1 Environment:从「信谁」变成三类槽

早期只有 5 条,全是「什么算可信」:Trusted repo、Source control、Trusted internal domains、Trusted cloud buckets、Key internal services。没填就当 External,外泄和外部代码规则最严。

后来扩到约 20 个,写成三类。分类器靠这些槽判断「这个目的地算不算外泄」「这个集群算不算生产」,空着时各自有保守默认:

默认槽(举例)干什么
ContextNone / 保守假设Organization、Cloud provider、Repository visibility、CI/CD deploy targets、Network posture描述环境。可见性未核实时不当成「一定公开」,也不当成「一定私有」
Trust没填 = 谁都不信Trusted repo / domains / buckets / services、Internal package registry白名单。填了,往这些地方推代码、装包才不算 External
Sensitivity宽启发式(名字带 prod 就算)Sensitive data locations、Sensitive remote targets、Protected IaC scopes点名要保护的东西。不填也拦得住 prod-db

填了之后,分类器能区分「推进自己的私有 org」和「推进公开 gist」,也能把名字带 prod 的 namespace 当生产。

7.2 CLAUDE_CODE_AUTO_MODE_*

auto mode 有一批 CLAUDE_CODE_AUTO_MODE_* 旋钮。取值顺序一般是:环境变量 → 远程配置 → 默认值。看到名字不代表 export 就能开,不少只给内部或灰度用。曾经给 Bedrock / Vertex 用的 CLAUDE_CODE_ENABLE_AUTO_MODE 后来也不用了;CLI 的 --enable-auto-mode 更早就删了。

CLAUDE_CODE_ENABLE_AUTO_MODE                      # 曾经的平台 opt-in,后来不用了
CLAUDE_CODE_AUTO_MODE_MODEL                       # 分类器模型
CLAUDE_CODE_AUTO_MODE_CLASSIFY_ASK_USER_QUESTION  # AskUserQuestion 也交给分类器
CLAUDE_CODE_AUTO_MODE_CLASSIFY_EDITS              # 编辑操作也过分类器
CLAUDE_CODE_AUTO_MODE_EDIT_REMOVAL / _CAP         # 编辑剥离 / 上限
CLAUDE_CODE_AUTO_MODE_EXTERNAL_PERMISSIONS        # 走外部权限模板
CLAUDE_CODE_AUTO_MODE_GIT_STATUS / _LIMIT / _UPLOADS  # 把 git status 塞进分类器上下文
CLAUDE_CODE_AUTO_MODE_OUTCOME_CODES               # 分类器结果码
CLAUDE_CODE_AUTO_MODE_PRIOR_ASSISTANT_CONTEXT     # transcript 是否带上一条 assistant 上下文
CLAUDE_CODE_AUTO_MODE_REPO_VISIBILITY             # 探测仓库公开/私有
CLAUDE_CODE_AUTO_MODE_TEMPERATURE                 # 分类器温度
CLAUDE_CODE_BG_CLASSIFIER_MODEL                   # 后台分类器模型
CLAUDE_CODE_CLASSIFIER_SUMMARY                    # 分类器摘要

8. 可借鉴的模式#

  1. 快路径金字塔:白名单 → 低成本预检 → 昂贵判断
  2. 两阶段分类(2.1.233 默认):先用 64 token 的短输出快放行,只有可疑才用 8192 token 写思考再复核(2.1.88 深查是 4096)
  3. Fail-closed 默认,gate 可切 fail-open
  4. 拒绝逃生舱:3 / 20 回退人工
  5. 只给分类器看工具调用,不给模型文本
  6. stage2 复用 stage1 前缀打 cache
  7. claude auto-mode defaults/config/critique/reset + 遥测比
  8. 默认规则包在替换标签里,$defaults 追加