Claude Code 源码深度解析:是否对第三方模型投毒?
一、核心结论
Anthropic 没有进行主观“投毒”。 但 Claude Code 确实是一个与 Anthropic API 深度耦合的客户端,大量功能基于 Anthropic 独有的 API 特性(Beta Headers、Extended Thinking、Prompt Caching、Server-side Context Management 等)构建。第三方模型即使兼容 Anthropic Messages API 的基本格式,也无法支持这些专有特性,导致功能降级和体验下降。这是架构耦合的结果,而非主观恶意。
体验下降的根本原因:
本文以GLM-4.7模型为例子,分析Claude Code对第三方模型适配的影响:
| 降级维度 | 根因 | 影响程度 | 是否“投毒” |
|---|---|---|---|
| 思考能力缺失 | 发送 thinking: {type: "adaptive"} 但 API 不支持 |
🔴 严重 | 否,架构耦合 |
| Beta Headers 被忽略 | 15+ 个 Beta Headers 全部不被第三方 API 识别 | 🔴 严重 | 否,标准 API 特性 |
| Prompt Caching 失效 | cache_control 不被支持,每次全量计算 |
🟠 中等 | 否,API 层特性 |
| Effort Level 失效 | output_config.effort 不被支持 |
🟡 轻微 | 否 |
| 上下文管理失效 | context_management 不被支持,compact 更频繁 |
🟠 中等 | 否 |
| 工具 Schema 兼容性 | 扩展字段(defer_loading等)可能被拒绝 |
🟠 中等 | 否 |
| 流式事件不完整 | 缺少 thinking_delta 等事件类型 |
🔴 严重 | 否 |
| System Prompt 针对 Claude 优化 | Prompt 是为 Claude 行为模式定制的 | 🟠 中等 | 否,正常的产品优化 |
| Anti-distillation 注入 | fake_tools 被发送但不被第三方处理 |
🟡 轻微 | 否,安全特性 |
| 工具描述 Prompt 针对性 | 描述文本为 Claude 模型的指令跟随能力优化 | 🟠 中等 | 否 |
| 归因头注入 | x-anthropic-billing-header 作为系统提示词 |
🟡 轻微 | 否 |
| 模型名检测 Bug | 第三方模型被误判为支持某些 Claude 4+ 特性 | 🔴 严重 | 否,代码逻辑缺陷 |
二、请求机制分析
2.1 客户端创建流程
源文件: src/services/api/client.ts:88-316
客户端创建的核心逻辑:
// 最终走标准 Anthropic SDK 路径
const clientConfig = {
apiKey: isClaudeAISubscriber() ? null : apiKey || getAnthropicApiKey(),
authToken: isClaudeAISubscriber() ? getClaudeAIOAuthTokens()?.accessToken : undefined,
// ...ARGS 包含 timeout, headers, fetch 等
}
return new Anthropic(clientConfig)
关键发现:
-
ANTHROPIC_BASE_URL生效机制:当你设置ANTHROPIC_BASE_URL=https://open.bigmodel.cn/api/anthropic,Anthropic SDK 会将所有请求发往该地址。这个机制本身是 Anthropic SDK 原生支持的,Claude Code 没有做任何限制。 -
ANTHROPIC_AUTH_TOKEN:通过 Bearer Token 认证(src/services/api/client.ts:318-328),直接放入Authorization头,对第三方代理透明。 -
Provider 检测:
getAPIProvider()根据环境变量判断是firstParty | bedrock | vertex | foundry。设置ANTHROPIC_BASE_URL但不设置 Bedrock/Vertex/Foundry 标志时,Provider 仍被识别为firstParty。这是一个关键点——后续很多功能门控都依赖此判断。 -
isFirstPartyAnthropicBaseUrl()(src/utils/model/providers.ts:25-40):检查 URL 是否指向api.anthropic.com。你的第三方 URL 会返回false,导致部分 First-Party 专属功能被跳过。
对第三方模型的影响:
- 基本请求可以正常发送(Anthropic Messages API 格式兼容)
- 但大量附加功能(Beta Headers、特殊 Headers)可能被第三方代理拒绝
2.2 模型选择与覆盖机制
源文件: src/utils/model/model.ts
// 环境变量覆盖优先级
export function getDefaultSonnetModel(): ModelName {
if (process.env.ANTHROPIC_DEFAULT_SONNET_MODEL) {
return process.env.ANTHROPIC_DEFAULT_SONNET_MODEL // 你的 "glm-4.7"
}
// ...
}
关键发现:
当你设置 ANTHROPIC_DEFAULT_SONNET_MODEL=glm-4.7,Claude Code 会将 glm-4.7 作为模型名发送到 API。但后续的能力检测全部基于模型名的字符串匹配:
// src/utils/model/model.ts:217-270
export function firstPartyNameToCanonical(name: ModelName): ModelShortName {
name = name.toLowerCase()
if (name.includes('claude-opus-4-6')) return 'claude-opus-4-6'
if (name.includes('claude-sonnet-4-6')) return 'claude-sonnet-4-6'
// ...全部是 Claude 模型的匹配规则
// glm-4.7 不会匹配任何规则,返回原始名称
}
影响:glm-4.7 的 canonical name 就是 glm-4.7 本身,几乎所有基于 getCanonicalName() 的能力检测都会返回 false(因为不包含 claude- 前缀)。
2.3 3P 模型能力覆盖机制
源文件: src/utils/model/modelSupportOverrides.ts
Anthropic 专门提供了让第三方模型声明能力的环境变量:
const TIERS = [
{
modelEnvVar: 'ANTHROPIC_DEFAULT_OPUS_MODEL',
capabilitiesEnvVar: 'ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES',
},
{
modelEnvVar: 'ANTHROPIC_DEFAULT_SONNET_MODEL',
capabilitiesEnvVar: 'ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES',
},
// ...
]
这意味着:你需要在 settings.json 的 env 中额外设置:
{
"ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES": "thinking,adaptive_thinking,effort,interleaved_thinking"
}
但你的配置中缺少了这些关键的 capabilities 声明,这是体验下降的直接原因之一。
三、Beta Headers 机制分析(核心降级点)
3.1 Beta Headers 的作用
源文件: src/constants/betas.ts 和 src/utils/betas.ts
Claude Code 发送的每一个 API 请求都携带大量 Beta Headers,这些是启用高级特性的“开关”:
| Beta Header | 作用 | 第三方支持 |
|---|---|---|
claude-code-20250219 |
Claude Code 专用优化 | ❌ |
interleaved-thinking-2025-05-14 |
交错思考(思考+工具调用交替) | ❌ |
prompt-caching-scope-2026-01-05 |
全局缓存范围 | ❌ |
context-management-2025-06-27 |
API 侧上下文管理 | ❌ |
structured-outputs-2025-12-15 |
结构化输出 | ❌ |
effort-2025-11-24 |
思考力度控制 | ❌ |
redact-thinking-2026-02-12 |
思考摘要化(节省 token) | ❌ |
fast-mode-2026-02-01 |
快速模式 | ❌ |
advanced-tool-use-2025-11-20 |
高级工具使用(Tool Search) | ❌ |
advisor-tool-2026-03-01 |
服务端顾问工具 | ❌ |
token-efficient-tools-2026-03-28 |
Token 高效工具格式 | ❌ |
task-budgets-2026-03-13 |
服务端 Token 预算 | ❌ |
afk-mode-2026-01-31 |
AFK 自动模式 | ❌ |
cli-internal-2026-02-09 |
内部 CLI 功能(Ant-only) | ❌ |
summarize-connector-text-2026-03-13 |
文本摘要化(Ant-only) | ❌ |
3.2 Beta Header 的生成逻辑
源文件: src/utils/betas.ts:234-369
export const getAllModelBetas = memoize((model: string): string[] => {
const betaHeaders = []
const includeFirstPartyOnlyBetas = shouldIncludeFirstPartyOnlyBetas()
// 非 Haiku 模型都会加上 claude-code beta
if (!isHaiku) {
betaHeaders.push(CLAUDE_CODE_20250219_BETA_HEADER)
}
// 交错思考 — 需要模型支持
if (!isEnvTruthy(process.env.DISABLE_INTERLEAVED_THINKING) && modelSupportsISP(model)) {
betaHeaders.push(INTERLEAVED_THINKING_BETA_HEADER)
}
// 仅 First-Party: redact-thinking, context-management, structured-outputs 等
if (includeFirstPartyOnlyBetas && modelSupportsISP(model)) {
betaHeaders.push(REDACT_THINKING_BETA_HEADER)
}
// ... 更多
})
3.3 关键门控函数:shouldIncludeFirstPartyOnlyBetas()
// src/utils/betas.ts:215-220
export function shouldIncludeFirstPartyOnlyBetas(): boolean {
return (
(getAPIProvider() === 'firstParty' || getAPIProvider() === 'foundry') &&
!isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS)
)
}
你的情况:getAPIProvider() 返回 firstParty(因为没有设置 Bedrock/Vertex/Foundry 标志),但 isFirstPartyAnthropicBaseUrl() 返回 false(URL 不是 api.anthropic.com)。
这导致一个矛盾状态:
shouldIncludeFirstPartyOnlyBetas()→true(尝试发送所有 Beta Headers)- 但第三方 API 不认识这些 Headers,可能静默忽略或返回错误
这就是为什么需要设置 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1——但这个变量并不控制 Beta Headers 的发送。
3.4 实际发送到第三方 API 的请求内容
当 glm-4.7 被选为模型时:
{
"model": "glm-4.7",
"betas": [
"claude-code-20250219",
"interleaved-thinking-2025-05-14",
"prompt-caching-scope-2026-01-05",
"context-management-2025-06-27",
"redact-thinking-2026-02-12",
"advanced-tool-use-2025-11-20",
"advisor-tool-2026-03-01",
"effort-2025-11-24"
],
"thinking": { "type": "adaptive" },
"output_config": { "effort": "medium" },
"context_management": { "edits": [...] },
"metadata": { "user_id": "..." },
"anti_distillation": ["fake_tools"],
// ... 以及大量带有 cache_control、defer_loading 等字段的工具定义
}
第三方 API 的典型处理方式:
- 不认识的
betas:静默忽略 → 功能不启用 - 不认识的请求字段(
thinking、context_management、output_config、anti_distillation):可能忽略或报错 - 不认识的工具字段(
defer_loading、cache_control、eager_input_streaming):可能忽略或报 400
四、Thinking(思考)机制分析
4.1 思考能力检测
源文件: src/utils/thinking.ts:90-110
export function modelSupportsThinking(model: string): boolean {
const supported3P = get3PModelCapabilityOverride(model, 'thinking')
if (supported3P !== undefined) return supported3P // 环境变量覆盖
const canonical = getCanonicalName(model)
const provider = getAPIProvider()
// 1P 和 Foundry: 所有 Claude 4+ 模型
if (provider === 'foundry' || provider === 'firstParty') {
return !canonical.includes('claude-3-') // glm-4.7 不含 claude-3-,返回 true!
}
// ...
}
关键发现:由于 glm-4.7 的 canonical name 不包含 claude-3-,且 Provider 被识别为 firstParty,modelSupportsThinking() 返回 true!
这意味着 Claude Code 会发送:
{
"thinking": { "type": "adaptive" }
}
但第三方模型很可能不支持 adaptive 类型的思考,导致:
- API 忽略此参数 → 模型不进行深度思考 → 输出质量下降
- API 不认识此参数 → 报错 → 降级为非思考模式
4.2 自适应思考
// src/utils/thinking.ts:113-144
export function modelSupportsAdaptiveThinking(model: string): boolean {
const canonical = getCanonicalName(model)
if (canonical.includes('opus-4-6') || canonical.includes('sonnet-4-6')) return true
// glm-4.7 不匹配...
// 默认:1P 和 Foundry 返回 true
const provider = getAPIProvider()
return provider === 'firstParty' || provider === 'foundry' // true!
}
同样的问题:Provider 检测让 glm-4.7 被认为支持 adaptive thinking,但实际不支持。
五、Prompt Caching(缓存)机制分析
5.1 缓存断点注入
源文件: src/services/api/claude.ts:1699-1729
每次请求都会在消息中注入 cache_control 断点:
messages: addCacheBreakpoints(messagesForAPI, enablePromptCaching, ...)
system: [ // 系统提示词带 cache_control
{ text: "attribution header", cache_control: undefined },
{ text: "system prompt prefix", cache_control: { type: 'ephemeral' } },
{ text: "rest of system prompt", cache_control: { type: 'ephemeral', scope: 'global' } }
]
影响:
- 第三方 API 不支持
cache_control→ 每次请求都是完整计算,无缓存命中 - 全局缓存(
scope: 'global')是 Anthropic 独有功能 - 1h TTL 缓存需要特定的资格检查(
should1hCacheTTL())
5.2 缓存中断检测
源文件: src/services/api/promptCacheBreakDetection.ts
Claude Code 内置了完整的缓存命中监控,检测 cache_read_input_tokens 的变化。第三方 API 不返回这些字段 → 检测失效 → 无法优化缓存策略。
实际影响:每次请求都重新处理完整的系统提示词(约 20,000-50,000 tokens),增加延迟和成本。
六、工具调用机制分析
6.1 工具 Schema 构建
源文件: src/utils/api.ts:119-266
Claude Code 注册了大量工具(Bash、FileRead、FileEdit、FileWrite、Grep、Glob、Agent 等),每个工具的 Schema 都包含:
{
name: "Bash",
description: "...", // 非常长的工具描述(prompt)
input_schema: { ... }, // JSON Schema
cache_control: { // 缓存控制
type: 'ephemeral',
scope: 'global'
},
eager_input_streaming: true, // 细粒度工具流式传输(1P only)
defer_loading: true // 延迟加载(Tool Search)
}
6.2 工具描述中的 Prompt
每个工具的 description 字段实际上是精心编写的 Prompt,包含:
- 详细的使用说明
- 输入规范
- 行为约束
- 与 Claude Code 工作流集成的指令
这些 Prompt 是针对 Claude 模型的行为模式优化的。第三方模型(如 GLM-4):
- 可能不理解这些指令的格式
- 可能不遵循其中描述的行为约束
- 工具调用的 JSON 格式可能不完全兼容
6.3 Tool Search(动态工具加载)
// src/utils/betas.ts:197-208
export function getToolSearchBetaHeader(): string {
const provider = getAPIProvider()
if (provider === 'vertex' || provider === 'bedrock') {
return TOOL_SEARCH_BETA_HEADER_3P
}
return TOOL_SEARCH_BETA_HEADER_1P // 'advanced-tool-use-2025-11-20'
}
Tool Search 允许模型动态发现工具。这需要 API 侧支持 defer_loading 和 tool_reference blocks——这是 Anthropic 独有的特性。
6.4 Anti-Distillation(反蒸馏)
源文件: src/services/api/claude.ts:301-313
if (feature('ANTI_DISTILLATION_CC')
&& process.env.CLAUDE_CODE_ENTRYPOINT === 'cli'
&& shouldIncludeFirstPartyOnlyBetas()
&& getFeatureValue_CACHED_MAY_BE_STALE('tengu_anti_distill_fake_tool_injection', false)) {
result.anti_distillation = ['fake_tools']
}
Claude Code 会注入虚假工具(fake tools)来防止模型输出被用于蒸馏训练。这是 Anthropic 服务端功能,第三方 API 完全不支持。
七、上下文管理分析
7.1 服务端上下文管理
源文件: src/services/compact/apiMicrocompact.ts
Claude Code 使用 API 侧的上下文管理来动态清除旧的 tool results 和 thinking blocks:
{
context_management: {
edits: [
{ type: 'clear_tool_uses_20250919', trigger: {...}, keep: {...} },
{ type: 'clear_thinking_20251015', keep: 'all' }
]
}
}
影响:第三方 API 不支持 → 上下文窗口更快填满 → 触发更频繁的客户端侧 compact → 信息丢失。
7.2 上下文窗口检测
// src/utils/context.ts:51-98
export function getContextWindowForModel(model: string, betas?: string[]): number {
if (has1mContext(model)) return 1_000_000
// ...
return MODEL_CONTEXT_WINDOW_DEFAULT // 200,000
}
glm-4.7 不含 [1m] 后缀 → 默认 200K 上下文窗口。如果 GLM 的实际上下文窗口不同,compact 触发时机可能不准确。
八、Effort Level(思考力度)机制分析
源文件: src/utils/effort.ts:23-49
export function modelSupportsEffort(model: string): boolean {
const m = model.toLowerCase()
if (m.includes('opus-4-6') || m.includes('sonnet-4-6')) return true
if (m.includes('haiku') || m.includes('sonnet') || m.includes('opus')) return false
// glm-4.7 不匹配任何已知模型
// 默认:1P 返回 true
return getAPIProvider() === 'firstParty' // true!
}
你设置了 effortLevel: "medium",Claude Code 会发送:
{ "output_config": { "effort": "medium" } }
但第三方 API 不支持 effort 参数,该字段被忽略,模型以默认力度运行。
九、系统提示词(System Prompt)分析
9.1 前缀声明
源文件: src/constants/system.ts:10-46
const DEFAULT_PREFIX = `You are Claude Code, Anthropic's official CLI for Claude.`
每个请求的系统提示词都以这个声明开头。这意味着:
- 第三方模型(如 GLM-4)收到的指令是“你是 Claude Code,Anthropic 的官方 CLI”
- 整个 System Prompt 是为 Claude 模型的行为模式量身定制的
- Prompt 中包含大量针对 Claude 模型优化的指令格式、约束条件和工作流程
9.2 归因头(Attribution Header)
// src/constants/system.ts:73-94
const header = `x-anthropic-billing-header: cc_version=${version}; cc_entrypoint=${entrypoint};`
系统提示词的第一个 block 是一个计费/归因头,第三方 API 不需要但会被发送。
十、流式响应解析分析
10.1 流式事件类型
源文件: src/services/api/claude.ts:1940-2304
Claude Code 期望接收以下 SSE 事件类型:
message_start→ 包含 usage 信息content_block_start→ 支持thinking、text、tool_use、server_tool_use类型content_block_delta→ 支持thinking_delta、text_delta、input_json_delta、signature_delta、connector_text_deltacontent_block_stopmessage_delta→ 包含 stop_reason 和 usagemessage_stop
第三方 API 需要完全兼容这些事件类型,否则:
thinkingblocks 无法解析 → 思考内容丢失server_tool_use(Advisor)无法解析 → 顾问功能失效connector_textblocks 无法解析 → 文本摘要失效- usage 信息缺失 → token 计数和成本追踪不准
10.2 非流式降级
当流式请求失败时,Claude Code 会自动降级为非流式请求(src/services/api/claude.ts:2504-2569)。但这也要求非流式响应格式与 Anthropic API 完全一致。
十一、第三方 API 兼容代理(如 open.bigmodel.cn)的能力分析
11.1 Anthropic 兼容 API 的典型实现
第三方代理通常只实现了 Anthropic Messages API 的基础子集:
| 功能 | 典型支持情况 |
|---|---|
POST /v1/messages 基本请求 |
✅ 支持 |
model 字段透传 |
✅ 支持 |
messages 数组(user/assistant) |
✅ 支持 |
system 提示词 |
⚠️ 部分支持(可能忽略 cache_control) |
tools 定义 |
⚠️ 部分支持(可能忽略 defer_loading 等扩展字段) |
tool_choice |
⚠️ 可能不支持 |
betas header |
❌ 完全忽略 |
thinking 参数 |
❌ 不支持 |
output_config |
❌ 不支持 |
context_management |
❌ 不支持 |
speed(fast mode) |
❌ 不支持 |
stream: true(SSE) |
⚠️ 部分支持(事件类型可能不全) |
cache_control |
❌ 不支持 |
metadata |
❌ 忽略 |
anti_distillation |
❌ 不支持 |
11.2 你的配置中的问题
{
"env": {
"ANTHROPIC_AUTH_TOKEN": "...",
"ANTHROPIC_BASE_URL": "https://open.bigmodel.cn/api/anthropic",
"API_TIMEOUT_MS": "3000000",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": 1
}
}
缺失的关键配置:
-
缺少
ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES:- 没有告诉 Claude Code 你的模型支持哪些能力
- 所有能力检测基于 Claude 模型名的字符串匹配,GLM 模型名无法匹配
- 但由于 Provider 检测的 bug(
firstParty但非 Anthropic URL),部分功能被错误地启用
-
缺少
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1:- 这会发送所有实验性 Beta Headers
- 第三方 API 可能因无法识别而返回错误
- 设置此变量会剥离
defer_loading、eager_input_streaming等扩展字段
-
缺少
CLAUDE_CODE_DISABLE_THINKING=1(如果模型不支持思考):- 发送
thinking: { type: "adaptive" }可能导致错误
- 发送
十二、优化建议
12.1 必须配置的环境变量
{
"env": {
"ANTHROPIC_AUTH_TOKEN": "your-token",
"ANTHROPIC_BASE_URL": "https://open.bigmodel.cn/api/anthropic",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "glm-4.7",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-4.5-air",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-4.7",
"ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES": "thinking",
"ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES": "",
"ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES": "thinking",
"CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS": "1",
"DISABLE_PROMPT_CACHING": "1",
"DISABLE_INTERLEAVED_THINKING": "1",
"API_TIMEOUT_MS": "300000"
}
}
12.2 第三方 API 代理需要实现的最低兼容性
- 正确处理
betas字段(忽略不认识的值,不报错) - 正确处理
thinking字段(忽略或降级) - 正确处理
output_config字段(忽略) - 正确处理
context_management字段(忽略) - 完整的 SSE 流式响应(所有事件类型)
- 正确处理
tools中的扩展字段(忽略cache_control、defer_loading等) - 返回
usage字段(input_tokens、output_tokens)
十三、最终结论
Anthropic 是否“投毒”?
答案:否。
代码分析表明:
-
Claude Code 是一个为 Anthropic API 深度优化的客户端。所有高级功能(Thinking、Prompt Caching、Context Management、Effort Level、Tool Search、Advisor 等)都是基于 Anthropic 的专有 API 特性构建的。这不是“投毒”,而是正常的产品深度集成。
-
Anthropic 专门为第三方模型提供了能力覆盖机制(
ANTHROPIC_DEFAULT_*_MODEL_SUPPORTED_CAPABILITIES环境变量),说明他们有意识地考虑了第三方模型的兼容性。 -
代码中没有检测第三方 URL 然后降级行为的逻辑。所有降级都是自然发生的——第三方 API 不支持某些特性,请求要么被忽略要么报错。
-
Provider 检测存在一个设计缺陷:设置
ANTHROPIC_BASE_URL但不设置 Bedrock/Vertex/Foundry 标志时,Provider 被识别为firstParty,但 URL 检测返回false,导致部分 First-Party 功能被尝试发送但无法生效。这是一个架构设计上的疏忽,而非主观恶意。 -
体验下降的根本原因是:Claude Code 的 System Prompt、工具描述、Beta Headers、请求参数等全部针对 Claude 模型的能力进行了深度优化。第三方模型即使能解析 Anthropic Messages API 的基本格式,也无法利用这些优化,反而可能因不支持的参数导致错误。
类比
这就像用 PlayStation 5 的游戏光盘插到 PC 光驱里——光盘格式(API 格式)是兼容的,但游戏依赖 PS5 的专用硬件特性(GPU 指令集、专用芯片等),在 PC 上无法运行。这不是 Sony “投毒”了光盘,而是游戏本身就是为 PS5 深度优化的。
附录:OpenCode 的适配策略对比
更新说明:本节基于公开资料(包括 iFlow 插件、Canva LLMProxy、BytePlus 文档等)对 OpenCode 的模型适配机制进行补充,以澄清两种工具在设计哲学上的根本差异。原报告主体结论不受影响。
A.1 设计哲学差异
| 对比维度 | Claude Code | OpenCode |
|---|---|---|
| 适配方式 | 核心代码深度耦合 Anthropic API | 插件层适配 + 配置覆盖 |
| 对新模型的支持 | 需等待 Anthropic 官方更新 | 社区插件即可扩展 |
| 特殊特性处理 | 假设 API 支持(发送后忽略/报错) | 显式声明或由插件处理 |
| 模型能力声明 | 环境变量手动声明 | 插件自动配置或配置覆盖 |
A.2 OpenCode 的典型适配案例
1. GLM 模型的思考模式支持(iFlow 插件)
插件 @hung319/opencode-iflow-cli 为 GLM-4.6 实现了原生思考模式(thinking mode),通过配置显式指定思考预算:
{
"model": "glm-4.6",
"variant": "medium" // low: 1024 / medium: 8192 / max: 32768 tokens
}
这与 Claude Code 的“发送 thinking 参数然后希望 API 支持”不同——插件会主动适配模型的能力边界。
2. 模型上下文窗口修正(Canva LLMProxy)
Canva 的 LLMProxy 插件允许手动覆盖模型的上下文窗口限制,以纠正外部数据源(如 models.dev)的错误信息:
"models": {
"us.anthropic.claude-opus-4-6-v1": {
"limit": { "context": 200000, "output": 128000 }
}
}
3. 模型缺陷文档化
同一插件明确标记了 GLM 4.7 在 Bedrock 上的工具调用 Bug,使用户知情:
“GLM 4.7 models have a known tool-calling bug where the Converse API rejects tool result messages. They work for basic text generation but are not usable for agentic workflows.”
4. Deep Thinking 的模型级开关(BytePlus 方案)
BytePlus 官方文档展示了如何为特定模型单独启用 Deep Thinking:
{
"models": {
"<Model_Name>": {
"name": "<Model_Name>",
"options": {
"thinking": { "type": "enabled" }
}
}
}
}
5. 动态上下文剪枝(DCP 插件)的 per-model 配置
插件 @tarquinen/opencode-dcp 支持为不同模型配置不同的压缩触发阈值:
"compress": {
"modelMaxLimits": {
"openai/gpt-5.3-codex": 120000,
"anthropic/claude-sonnet-4.6": "80%"
}
}
A.3 关键差异总结
| 适配场景 | Claude Code 的处理 | OpenCode 的处理 |
|---|---|---|
| GLM 思考模式 | 发送 thinking 参数,希望 API 支持 | 插件显式配置 thinking budget |
| 模型上下文限制 | 基于模型名正则匹配(GLM 会误判) | 配置文件手动覆盖 |
| 模型 Bug(如 GLM 工具调用) | 无感知,请求照发 | 插件文档化,用户知情 |
| Deep Thinking 开关 | 通过 Beta Headers 隐式启用 | 配置文件显式声明 |
| 第三方平台接入 | 仅支持 Anthropic 兼容代理 | 支持 OpenAI / Anthropic / Google 多协议 |
A.4 为什么 OpenCode 在第三方模型上表现更好?
OpenCode 采用了 “自下而上” 的适配策略:假设 API 是未知的,通过插件体系为特定模型“赋予”能力。这种设计使得:
- 模型特殊性可以被精确描述(如 GLM 的思考格式、DeepSeek R1 的推理特性)
- 已知缺陷可以被文档化和规避(如 GLM 工具调用问题)
- 不同模型可以独立配置(上下文窗口、思考开关等)
相比之下,Claude Code 的 “自上而下” 策略(假设 API 是 Anthropic,然后通过环境变量“降级”)在遇到模型差异时,只能依赖环境变量覆盖或直接发送不兼容的请求,体验下降在所难免。
这也解释了为何同样的 第三方模型 在 OpenCode 上体验更好——OpenCode 的插件生态可以主动适配模型的特殊性,而 Claude Code 只能被动发送请求然后“希望” API 能正确处理。
报告基于 Claude Code 源码分析,分析日期:2026-04-01。附录基于公开资料整理。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)