让 Claude Code 走自建 LLM 网关:connect 与 rollout 的两阶段

2026-08-18

一、你多半是被这几件事推到网关上的

真正把人推到自建 LLM 网关上的通常是这几种处境:安全那边不允许开发机上散落着直连模型厂商的密钥;财务想按人头看用量而不是看一张合并账单;合规要求每次模型请求都留审计日志;或者网络策略只放行一个出口地址。

Claude Code 官方文档在 code.claude.com/docs/en/llm-gateway 这一页把网关能集中管的事列成了五类:凭据(provider 的密钥留在服务端,开发者手里拿的是网关凭据)、用量归属、成本控制、审计日志、切换 provider。最后一类有个前提——文档写明,「不动开发者机器就换 provider」还依赖网关无论上游是谁都对外暴露同一套 Anthropic 格式端点;网关直接暴露某个 provider 自己的格式,客户端配置就被绑死了。

另外两句得先摆在前面,省得后面白忙:文档明写 Anthropic 不背书、不维护、也不审计第三方网关产品,并且不支持通过任何网关把 Claude Code 路由到非 Claude 模型。还有一句代价:网关一旦上了,它就变成你们自己要运维的基础设施——Claude Code 每次发版都会加能力,网关不转发新东西,对应功能就坏掉。

二、前置条件:分清你是哪一侧的人

文档把这件事拆成了两页,对应两种角色,别串着看。

开发者侧(对应 llm-gateway-connect 页)需要向网关团队要两样东西:网关的 base URL,以及一份凭据——可能是一串 key 或 token,也可能是一条能取出凭据的命令。文档特意提醒:如果对方没说清是哪种凭据,先按 ANTHROPIC_AUTH_TOKEN 试。

管理员侧(对应 llm-gateway-rollout 页)的前置条件更硬:网关必须以 HTTPS 服务在你要分发给开发者的那个准确地址上,而不是一个会跳转过去的地址;要有 provider 凭据(走 Anthropic API 就是 Console 里的 API key,走云厂商就是对应云凭据);还要有一条把 settings 文件推到开发机的通道,比如 MDM 或配置管理。

有几个版本门槛是文档点名的,配之前先对一下:apiKeyHelper 在 v2.1.227 及以后,脚本里除了凭据多打一行 banner 或日志就会导致 helper 失败;Microsoft Foundry 那组变量里的 ANTHROPIC_FOUNDRY_AUTH_TOKEN 要求 v2.1.203 或更新;managed settings 里的 forceLoginMethod / forceLoginOrgUUID 在 v2.1.146 及以后与网关凭据互斥。

三、开发者侧:connect 其实只有两个变量

先做一件不花钱的事:跑 claude。如果它直接进了会话而不是登录页,说明管理员可能已经把配置发下来了,具体怎么核对见本文最后一节。凭据没发下来就得自己设,核心只有两个变量,而凭据该放哪个变量取决于网关读哪个 header:

凭据放在什么时候用实际走的 header
ANTHROPIC_AUTH_TOKEN网关团队说的是 bearer token / Authorization headerAuthorization: Bearer
ANTHROPIC_API_KEY网关团队说的是 API key / x-api-keyx-api-key
apiKeyHelper凭据会过期,或来自 vault两个 header 都发

这张表值得记的是最后一列:凭据放错变量,它会以网关不读的 header 送过去,结果就是 401。文档给的判定很直白——验证请求返回 401,就换另一个变量重试。

Bash 或 Zsh:

export ANTHROPIC_BASE_URL=https://llm-gateway.example.com
export ANTHROPIC_AUTH_TOKEN=sk-gateway-key

PowerShell:

$env:ANTHROPIC_BASE_URL = "https://llm-gateway.example.com"
$env:ANTHROPIC_AUTH_TOKEN = "sk-gateway-key"

shell 里 export 只对当前终端及其子进程有效,从 Start 菜单或 Dock 起来的编辑器看不到。要持久化,文档给了两条路:写进 shell profile(~/.zshrc~/.bashrc,Windows 上是 PowerShell 的 $PROFILE),或者写进 settings 文件的 env 块。后者更彻底——文档写明,只在 shell 里 export,由 supervisor 托管的后台 agent 不一定能拿到;后台会话也必须走网关的场景就用 settings 文件。

settings 文件分作用域:~/.claude/settings.json 管你所有项目,Windows 上路径是 %USERPROFILE%\.claude\settings.json.claude/settings.local.json 只管一个项目。env 块两边写法一样:

{
  "env": {
    "ANTHROPIC_BASE_URL": "https://llm-gateway.example.com",
    "ANTHROPIC_AUTH_TOKEN": "sk-gateway-key"
  }
}

文档在这里有一条 Warning,值得单独拎出来:别把凭据放进项目的 .claude/settings.json,那个文件是要提交并共享给所有 clone 仓库的人的。settings.local.json 由 Claude Code 保存设置时自动加进全局 gitignore,但如果你是手写或让 Claude 写的,得自己先把它加进 gitignore。

优先级也明确:shell export 和 settings 文件 env 块设了同一个变量时,settings 文件的值生效

另外三个变量按需加:网关要租户标识或路由键这类额外 header 时用 ANTHROPIC_CUSTOM_HEADERS,shell 里一行一个 Name: Value,写进 JSON 时因为字符串不能跨行、多个之间用 \n 分隔;网关自带的模型名不在 Claude Code 内置列表里时,设 CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1,启动时会去查网关并把结果加进 /model 选择器、标为 From gateway,确认它跑没跑用 claude --debug 然后在 ~/.claude/debug/<session-id>.txt 里找 [gatewayDiscovery] 开头的行。

网络只放行网关出口的话,还有个 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1,关掉版本检查、遥测、错误上报这类走网关之外的背景流量。它不是个纯净开关,副作用文档列了:自动更新会被关掉(得另外安排升级路径)、fast mode 可用性检查被抑制、连上面那个模型发现也会一起关掉(已发现的还在本地缓存里,但不再刷新);而 WebFetch 的域名安全检查不受它影响,仍会调 api.anthropic.com,要关得单独设 skipWebFetchPreflight: true

四、管理员侧:rollout 的五步,每步带一个检查点

llm-gateway-rollout 页把放量拆成五步,并且每一步都配了一个「检查点」,用来判断失败在哪一环:

  1. 确认网关能路由你的模型名——用 <gateway-key> 发一个最小请求,200 且带 content 字段说明网关把这个模型名转到了 provider;404 说明这个名字在网关上没配路由;provider 返回 401 说明网关手里的 provider 凭据不对。文档要求每个模型名都测一遍,没配路由的名字会对任何选它的开发者返回 404

  2. 给每个开发者发独立凭据——同一个请求把 <gateway-key> 换成新发的 <developer-key> 复测。上一步通过而这一步 401,说明开发者 key 不对或还没在网关生效。文档写明,一人一 key 而不是共用一把,正是按人归属用量与离职时单独吊销得以成立的前提。

  3. 自己先用这份配置跑一遍 Claude Code——在终端里直接 export(文档强调别写进 .env 或 settings 文件,关掉终端机器就回到原状),然后发一条一次性提示:

    claude -p "Reply with one word: connected"
    

    检查点是:拿到回复,并且网关日志里出现一条对 /v1/messages 路径的 POST、状态 200。这里有个容易踩的细节——Claude Code 会在后面追加类似 ?beta=true 的查询串,所以日志匹配要匹路径,不要匹完整 URL

  4. 分发 base URL 与凭据——走 managed settings 的 env 块,由 MDM、注册表策略或配置管理推下去。文档明说 managed 的 ANTHROPIC_BASE_URL 是强制的,开发者的 shell export 覆盖不掉。

  5. 在开发者机器上验收——注意是在开发机而不是网关主机上做,这样才覆盖开发者实际走的网络路径。

第五步文档给的验收动作是发一个流式请求(curl 加 -N),一次把端点、流式透传、模型路由三件事都验了:应该看到 data: 行陆续到达;停顿一下然后整坨一起到,说明网关在做缓冲。收尾再去网关日志里找刚才那条消息,凭据能标出是哪个开发者,x-claude-code-session-id 这个请求头能把同一次会话的请求归到一起。

本文各处 curl 与请求体示例里出现的 claude-sonnet-4-6(包括后面第六节那两条),都只是官方文档当时用来举例的模型名——平台上有哪些模型名随时在变,请一律按你们网关路由表里实际配置的名字替换,别把它当成一份可用模型清单。以上命令为按官方文档中的参数语义组合的示例,未经实测,以官方文档与 --help 的实际输出为准。

网关产品本身的硬要求文档列了六条:接受受支持的 API 格式(rollout 步骤按 POST /v1/messages 的 Anthropic Messages API 写);流式响应边到边透传、含 keep-alive ping,不能整体缓冲;能把 Claude 模型名映射到上游;anthropic-betaanthropic-version 和请求体双向原样转发;上游错误原样返回——Claude Code 的自动恢复是按错误措辞匹配的,套一层网关自己的 envelope 就失效;以及把该路径从 WAF 的请求体检查里豁免出来。最后这条的表现很有迷惑性:Claude Code 的提示词里带源码和 XML 风格标签,会命中跨站脚本的请求体规则,于是短测试请求能过、真实会话返回 403GET /v1/models 是可选的,配了才支持前面那个模型发现。

还有一条独立的 Note:别把网关放在重定向后面——文档给的理由是重定向可能丢掉请求体或剥掉凭据头,而模型发现会把任何重定向直接当失败处理,以免凭据泄漏到重定向目标。

五、边界:这些地方文档明说不成立

  • 订阅在网关下不生效。只要网关凭据变量或 apiKeyHelper 是激活的,开发者的 claude.ai 订阅就不被使用,那部分流量按 token 记在网关转发的那份凭据的所有者头上。反过来,只设 ANTHROPIC_BASE_URL 而不设凭据不会替换订阅——请求照样过网关,但生效的仍是已保存的 claude.ai 登录。
  • Slack 与 web 上的 Claude Code 不属于网关部署,它们始终用 Anthropic 的 API,在云会话环境配置里设网关变量也不会被应用。文档给的处置很直接:流量必须留在网关上,就别给这些用户开这两个面。
  • Remote Control 与语音听写在网关凭据下不可用,它们依赖 claude.ai 身份;Remote Control 还会在 ANTHROPIC_BASE_URL 指向非 Anthropic 主机时被禁用,光用 claude.ai 登录也不够。
  • 桌面端不读 ANTHROPIC_BASE_URLsettings.json,它走自己的第三方推理配置,要管理员另行随 MDM 下发。
  • forceLoginMethod / forceLoginOrgUUID 与网关凭据不能共存(v2.1.146 及以后),只能取其一;server-managed settings 的下发需要直连 api.anthropic.com,不会到达走网关的会话,网关部署要用基于文件的 managed settings。托管 Windows 机器上的 WSL,只有 wslInheritsWindowsSettingstrue 时才读 Windows 的 managed settings。

至于「网关挂了会怎么退化」「多网关容灾怎么配」,官方文档没有说明这一点,别按直觉替它补。

六、怎么确认真的配对了

按文档的顺序,验证是从外往里收的,别一上来就开会话。

第一层是绕开 Claude Code 直接打网关:用 shell 里已经 export 的变量发一个最小请求。

curl -X POST "$ANTHROPIC_BASE_URL/v1/messages" \
  -H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'

Windows 上的对应写法:

Invoke-RestMethod -Method Post -Uri "$env:ANTHROPIC_BASE_URL/v1/messages" `
  -Headers @{ "Authorization" = "Bearer $env:ANTHROPIC_AUTH_TOKEN"; "anthropic-version" = "2023-06-01" } `
  -ContentType "application/json" `
  -Body '{"model": "claude-sonnet-4-6", "max_tokens": 1, "messages": [{"role": "user", "content": "."}]}'

网关读 x-api-key 的话,把 Bash 里的 Authorization 头换成 x-api-key: $ANTHROPIC_API_KEY,PowerShell 里把哈希表那一项换成 "x-api-key" = "$env:ANTHROPIC_API_KEY"

判定标准有个反直觉的地方值得记:返回以 {"id":"msg_ 开头、带 "content":[...] 的 JSON 当然是通过;但一个「模型名未知」的错误同样算通过——因为网关是先认证再拒绝模型名的,这说明 URL 和凭据都是对的,你不需要为这一步专门去找一个网关真的服务的模型名。返回 401 才是凭据被拒,回上一节换变量。

第二层是从同一个 shell 起 claude(这样才继承得到 export),发一条消息,再跑 /status 看 Status 标签页三行:Anthropic base URL 显示你的网关地址,说明请求确实往那儿走,这一行只有设了网关地址才会出现;Auth tokenAPI key 行点名你设的那个变量,说明生效的是网关凭据,若显示的是 Login method 指向某个 claude.ai 账号则凭据没生效;管理员分发的场景再看 Setting sources,里面应该包含 managed settings——登录页出现或 base URL 那行缺失,就是配置没到这台机器。

最后是几个「curl 过了但会话不行」的典型错位,文档的排查表里各有各的因:403 而网关自己日志里根本没收到请求,是前面的 WAF 或反代把请求体拦了;HTTP 200 却报响应为空或格式错误,是网关或中间代理返回了非 API 内容(常见是 HTML 错误页或登录页);curl 正常而 Claude Code 报证书或 TLS 错误,是它的运行时没信任 curl 用的那个 CA,用 NODE_EXTRA_CA_CERTS 指向 CA bundle。


本文依据 Claude Code 官方文档(code.claude.com/docs)于 2026-08-17 的公开内容整理。 该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。 该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。 本文不涉及价格、额度与限流的具体数值,相关信息请以官方定价与用量说明页为准。

安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。