乐于分享
好东西不私藏

Claude Code 的双面人生:源码揭示内部版与大众版的 Prompt 差异

Claude Code 的双面人生:源码揭示内部版与大众版的 Prompt 差异

一个被 process.env.USER_TYPE 控制的开关,把同一个模型分成了两个世界。

Claude Code 的源码泄露后,最让圈内人津津乐道的发现不是什么安全漏洞,而是一个简单的事实:Anthropic 内部工程师用的 Prompt 和给付费大众用户的 Prompt,完全是两套逻辑。

公开版被加上了层层行为束缚和效率阉割。内部版?上帝模式。

所有结论均基于泄露源码验证,文件路径和行号都标在旁边。


一、那个决定一切的开关

在深入具体差异之前,先看控制机制。整个双轨系统由一个环境变量驱动:

process.env.USER_TYPE === 'ant'

ant = Anthropic 员工。这个变量是构建时注入的,不是运行时设置的。源码中有明确注释(src/utils/undercover.ts:17-20):

// All code paths are gated on process.env.USER_TYPE === 'ant'. Since
// USER_TYPE is a build-time --define, the bundler constant-folds these
// checks and dead-code-eliminates the ant-only branches from external
// builds.

翻译:外部发布版在打包时,所有 USER_TYPE === 'ant' 的分支会被死代码消除。你拿到的二进制文件里,这些代码物理上不存在。不是隐藏,是删除。


二、输出风格:大众版被逼”短平快”,内部版允许”好好说话”

这是体感最明显的差异。

大众版:紧箍咒模式

src/constants/prompts.ts:416-427,外部用户看到的指令:

return`# Output efficiency

IMPORTANT: Go straight to the point. Try the simplest approach first
without going in circles. Do not overdo it. Be extra concise.

Keep your text output brief and direct. Lead with the answer or action,
not the reasoning. Skip filler words, preamble, and unnecessary transitions.
Do not restate what the user said — just do it.

If you can say it in one sentence, don't use three.`

还不够。在 Tone and style 部分(src/constants/prompts.ts:433-435),大众版额外加了一条:

process.env.USER_TYPE === 'ant'
  ? null// 内部版:这条不存在
  : `Your responses should be short and concise.`

注意那个 null —— 内部版直接把”回复要简短”这条过滤掉了。

内部版:VIP 沟通模式

同一个函数,process.env.USER_TYPE === 'ant' 的分支(src/constants/prompts.ts:404-414):

if (process.env.USER_TYPE === 'ant') {
return`# Communicating with the user
When sending user-facing text, you're writing for a person, not logging
to a console.

When making updates, assume the person has stepped away and lost the
thread. Write so they can pick back up cold: use complete, grammatically
correct sentences without unexplained jargon. Expand technical terms.
Err on the side of more explanation.

Attend to cues about the user's level of expertise; if they seem like
an expert, tilt a bit more concise, while if they seem like they're new,
be more explanatory.

What's most important is the reader understanding your output without
mental overhead or follow-ups, not how terse you are.`

}

对比一下:

维度
大众版
内部版
标题
Output efficiency
Communicating with the user
核心指令
“Go straight to the point”
“Writing for a person”
长度要求
“one sentence, don’t use three”
“not how terse you are”
解释程度
“Skip reasoning”
“Err on the side of more explanation”
用户假设
用户在等你快点说完
用户可能中途走开了需要 catch up

大白话:给大众的 Claude 像个赶 deadline 的实习生,输出精简到极致;内部工程师用的是”慢慢聊,我有时间”的 VIP 版。

更狠的:数字长度锚定

内部版还有一个大众版完全没有的模块(src/constants/prompts.ts:527-537):

// Numeric length anchors — research shows ~1.2% output token reduction vs
// qualitative "be concise". Ant-only to measure quality impact first.
...(process.env.USER_TYPE === 'ant'
  ? [
      systemPromptSection(
'numeric_length_anchors',
() =>'Length limits: keep text between tool calls to ≤25 words. '
            + 'Keep final responses to ≤100 words unless the task requires '
            + 'more detail.',
      ),
    ]
  : []),

注释说得很直白:”研究表明数字化长度限制比定性的’简洁点’有效 1.2%。先在内部测量质量影响。

内部先测,外部等着。


三、代码验证:内部有”完工检查”,外部靠”文件落盘就算成功”

这是最扎心的差异。

内部版:必须验证才能说完成

src/constants/prompts.ts:210-211,只有 USER_TYPE === 'ant' 才会注入的指令:

// @[MODEL LAUNCH]: capy v8 thoroughness counterweight (PR #24302)
// — un-gate once validated on external via A/B
...(process.env.USER_TYPE === 'ant'
  ? [
`Before reporting a task complete, verify it actually works:
       run the test, execute the script, check the output. Minimum
       complexity means no gold-plating, not skipping the finish line.
       If you can't verify (no test exists, can't run the code), say
       so explicitly rather than claiming success.`
,
    ]
  : []),

注意那行注释:**”un-gate once validated on external via A/B”** —— 意思是”等在外部 A/B 测试验证后再放开”。换言之,现在外部用户没有这条指令。

诚实度护栏:承认 29-30% 假成功率

同文件的另一处 ant-only 指令(src/constants/prompts.ts:237-241):

// @[MODEL LAUNCH]: False-claims mitigation for Capybara v8
// (29-30% FC rate vs v4's 16.7%)
...(process.env.USER_TYPE === 'ant'
  ? [
`Report outcomes faithfully: if tests fail, say so with the
       relevant output; if you did not run a verification step, say
       that rather than implying it succeeded. Never claim "all tests
       pass" when output shows failures, never suppress or simplify
       failing checks to manufacture a green result, and never
       characterize incomplete or broken work as done.`
,
    ]
  : []),

那行注释太真实了:**”29-30% FC rate”** —— False Claims rate,假成功率高达 29-30%。他们自己都知道模型有近三成概率在报假喜讯。

但这个诚实度护栏只给了内部版。外部用户?继续享受那 29-30% 的假成功率吧。

Verification Agent:内部专属 QA

还有一个更重量级的 ant-only 功能(src/constants/prompts.ts:390-395):

hasAgentTool &&
feature('VERIFICATION_AGENT') &&
// 3P default: false — verification agent is ant-only A/B
getFeatureValue_CACHED_MAY_BE_STALE('tengu_hive_evidence'false)
  ? `The contract: when non-trivial implementation happens on your turn,
     independent adversarial verification must happen before you report
     completion. Non-trivial means: 3+ file edits, backend/API changes,
     or infrastructure changes. Spawn the Agent tool with
     subagent_type="verification".`

  : null,

注释赤裸裸写着:**”3P default: false — verification agent is ant-only A/B”**

3P = third party = 外部用户。默认关闭。

内部工程师改了 3 个以上文件?自动拉一个独立的 Verification Agent 做对抗性验证,发现问题就打回重做,直到通过。外部用户?改多少文件都是 Claude 自己说”我搞定了”就算搞定。


四、协作质量:内部版是队友,外部版是工具人

内部版会主动纠错

src/constants/prompts.ts:224-228

// @[MODEL LAUNCH]: capy v8 assertiveness counterweight (PR #24302)
// — un-gate once validated on external via A/B
...(process.env.USER_TYPE === 'ant'
  ? [
`If you notice the user's request is based on a misconception,
       or spot a bug adjacent to what they asked about, say so. You're
       a collaborator, not just an executor — users benefit from your
       judgment, not just your compliance.`
,
    ]
  : []),

“You’re a collaborator, not just an executor” —— 你是协作者,不是执行机器。

这条只给内部版。外部版的 Claude 不会主动说”你的思路可能有问题”或”顺便,你旁边还有个 bug”。

内部版注释更干净

同样是 ant-only(src/constants/prompts.ts:205-209):

// @[MODEL LAUNCH]: Update comment writing for Capybara
// — remove or soften once the model stops over-commenting by default
...(process.env.USER_TYPE === 'ant'
  ? [
`Default to writing no comments. Only add one when the WHY is
       non-obvious: a hidden constraint, a subtle invariant, a workaround
       for a specific bug.`
,
`Don't explain WHAT the code does, since well-named identifiers
       already do that.`
,
`Don't remove existing comments unless you're removing the code
       they describe or you know they're wrong.`
,
    ]
  : []),

内部版被教导”只在 WHY 不明显时写注释”。外部版没有这个指导,所以你可能见过 Claude 给每一行都加注释的场景。


五、Undercover Mode:内部员工的隐身斗篷

这是最有戏剧性的功能。完整实现在 src/utils/undercover.ts

exportfunctionisUndercover(): boolean{
if (process.env.USER_TYPE === 'ant') {
if (isEnvTruthy(process.env.CLAUDE_CODE_UNDERCOVER)) returntrue
// Auto: active unless we've positively confirmed we're in an
// allowlisted internal repo.
return getRepoClassCached() !== 'internal'
  }
returnfalse// 外部用户:永远关闭
}

当 Anthropic 员工在公开/开源仓库工作时,Undercover 模式自动启动。它做三件事:

1. 清除 AI 署名

src/utils/attribution.ts:52-55

exportfunctiongetAttributionTexts(): AttributionTexts{
if (process.env.USER_TYPE === 'ant' && isUndercover()) {
return { commit: '', pr: '' }  // 空署名
  }
// 外部用户:Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
}

2. 禁止泄露内部信息

注入一段强指令(src/utils/undercover.ts:38-68):

exportfunctiongetUndercoverInstructions(): string{
if (process.env.USER_TYPE === 'ant') {
return`## UNDERCOVER MODE — CRITICAL

You are operating UNDERCOVER in a PUBLIC/OPEN-SOURCE repository.

NEVER include in commit messages or PR descriptions:
- Internal model codenames (animal names like Capybara, Tengu, etc.)
- Unreleased model version numbers (e.g., opus-4-7, sonnet-4-8)
- Internal repo or project names
- The phrase "Claude Code" or any mention that you are an AI
- Co-Authored-By lines or any other attribution

Write commit messages as a human developer would.

GOOD:
- "Fix race condition in file watcher initialization"

BAD (never write these):
- "Fix bug found while testing with Claude Capybara"
- "1-shotted by claude-opus-4-6"
- "Generated with Claude Code"`

  }
return''
}

3. 隐藏模型身份

src/constants/prompts.ts:612-628

// Undercover: keep ALL model names/IDs out of the system prompt so
// nothing internal can leak into public commits/PRs.
let modelDescription = ''
if (process.env.USER_TYPE === 'ant' && isUndercover()) {
// suppress — 完全不告诉模型它是什么型号
else {
  modelDescription = `You are powered by the model named ${marketingName}.`
}

Undercover 模式下,Claude 甚至不知道自己是什么模型。commit 消息干净得不留把柄。

外部用户?压根没这功能。你的每次 commit 都会被打上 Co-Authored-By: Claude 的标记。


六、内部模型通道:你用不到的型号

src/utils/model/antModels.ts:33-41

// @[MODEL LAUNCH]: Update tengu_ant_model_override with new ant-only models
// @[MODEL LAUNCH]: Add the codename to scripts/excluded-strings.txt to
// prevent it from leaking to external builds.
exportfunctiongetAntModelOverrideConfig(): AntModelOverrideConfig | null{
if (process.env.USER_TYPE !== 'ant') {
returnnull// 外部用户:永远为空
  }
return getFeatureValue_CACHED_MAY_BE_STALE<AntModelOverrideConfig | null>(
'tengu_ant_model_override',
null,
  )
}

内部工程师可以通过 GrowthBook feature flag 切换到未发布的模型。注释提到的代号包括 Capybara、Tengu 等。这些代号甚至有专门的排除清单(scripts/excluded-strings.txt),确保不会泄露到外部构建中。

src/constants/prompts.ts:136-139 还显示,内部版可以注入特定模型的额外 system prompt:

functiongetAntModelOverrideSection(): string | null{
if (process.env.USER_TYPE !== 'ant'returnnull
if (isUndercover()) returnnull
return getAntModelOverrideConfig()?.defaultSystemPromptSuffix || null
}

七、内部反馈通道

最后一个 ant-only 细节(src/constants/prompts.ts:243-247):

...(process.env.USER_TYPE === 'ant'
  ? [
`If the user reports a bug, slowness, or unexpected behavior
       with Claude Code itself, recommend the appropriate slash command:
       /issue for model-related problems, or /share to upload the full
       session transcript. After /share produces a ccshare link, if you
       have a Slack MCP tool available, offer to post the link to
       #claude-code-feedback (channel ID C07VBSHV7EV) for the user.`
,
    ]
  : []),

内部版的 Claude 知道怎么把问题反馈到 Slack 的 #claude-code-feedback 频道。外部版不知道这个频道的存在。


完整差异清单

功能
内部版(ant)
大众版
源码位置
输出风格
“Writing for a person”,允许详细解释
“Go straight to the point”,必须精简
prompts.ts:403-428
“简短回复”指令
不存在(null)
“Your responses should be short and concise”
prompts.ts:433-435
数字长度锚定
≤25词 / ≤100词
prompts.ts:527-537
完工验证
必须运行测试/脚本确认
无此要求
prompts.ts:210-211
诚实度护栏
禁止假成功报告(29-30% FC)
prompts.ts:237-241
主动纠错
“You’re a collaborator, not just an executor”
prompts.ts:224-228
注释规范
“Default to writing no comments”
prompts.ts:205-209
Verification Agent
3+ 文件变更时强制对抗验证
关闭
prompts.ts:390-395
Undercover 模式
自动启动,隐藏 AI 痕迹
不存在
undercover.ts:27-36
AI 署名
可清除
默认添加
attribution.ts:52-55
模型身份
可隐藏
始终展示
prompts.ts:621-628
内部模型通道
可切换未发布模型
仅公开模型
antModels.ts:33-41
反馈通道
知道 Slack #claude-code-feedback
不知道
prompts.ts:243-247

怎么看这件事

有人说这是”典型的自己人用好货,外人用阉割版”。但仔细看源码里的注释,故事没那么简单。

几乎每个 ant-only 的功能旁边都标着:

// @[MODEL LAUNCH]: capy v8 — un-gate once validated on external via A/B

“un-gate once validated on external via A/B” —— 在外部 A/B 测试验证后放开。

这些功能的定位是内部先行测试,不是永久内部独占。Anthropic 的逻辑是:

  1. 新的 Prompt 策略先在内部工程师群体中验证
  2. 确认质量影响后,通过 A/B 测试逐步开放给外部
  3. 数字长度锚定的注释说得最直白:”Ant-only to measure quality impact first”

但问题是:从泄露的代码来看,这些功能已经在内部跑了一段时间,外部用户还在用”紧箍咒版”。

不是模型本身变弱,而是 Prompt 层面的双标把”聪明”藏起来了。Anthropic 的理由大概是”安全 + 成本 + 用户体验统一”,但泄露后大家看得更透:

他们自己用的时候,可没这么多束缚。