在自己的代码里接中转站:Python 和 TypeScript SDK、OpenAI 兼容层、Agent SDK 各填哪里,怎么先验证
自己写程序调 Claude,接中转站只改地址和 key,但各个 SDK 填法不同:Anthropic 的 SDK 地址不带 /v1,OpenAI 的要带;代码里传了 key 还读不读环境变量,Python 和 TypeScript 也不一样。本站用本机假网关看清每种写法发出了什么,再经中转站把四种 SDK 各跑一遍。
本站已实测,测试日期:2026-10-21。
本页目录(10 节)
这篇解决一个问题:自己写程序调 Claude,要走中转站,代码里该改哪几处,改完怎么确认接对了。
改的只有两样,地址和 key,但填法每个 SDK 都不一样,填错了多半是一个看不出原因的 404 或 401。本站先在服务器上起了一个本机的假网关,看清每种写法实际发出的请求路径和请求头(这一步不用 key、不连外网);再经一家中转站,把 Python、TypeScript、OpenAI 兼容层和 Agent SDK 各真跑一遍。
几篇相关的先分清:
- 用 Claude Code 的,看《Claude Code 接入中转站》。
- 三种接口是什么、地址一般填到哪一级,不分语言的通用说法在《接入中转站的通用方法》。
- 接上之后哪些功能和官方不一样,看《通过中转站用 Claude API》。
实测环境
| 项目 | 内容 |
|---|---|
| 日期 | 2026-10-21 |
| 机器 | 本站的测试服务器,Ubuntu 24.04,专用的普通用户 |
| Python | 3.12.3,anthropic 1.13.0,openai 3.29.0 |
| Node.js | 22.23.2,@anthropic-ai/sdk 0.133.0 |
| Agent SDK | Python 版 claude-agent-sdk 0.2.168,它自带的 Claude Code 是 2.1.301 |
| 中转站 | 酷站AI(koozhan.com)。地址和 key 由一个包装脚本放进测试进程的环境变量,脚本不打印它们 |
| 模型 | claude-sonnet-5-5,每次只让它回两个字 |
| 花费 | 经中转站的请求二十来次,按官方标价估算不到 1 美分 |
一、先对上三样东西
| 要对上的 | 怎么填 | 酷站AI 的例子 |
|---|---|---|
| 地址 | Anthropic 的 SDK(Python、TypeScript、Agent SDK)填到域名为止,不带 /v1,SDK 自己拼 /v1/messages;OpenAI 的 SDK 要带 /v1 |
https://api.koozhan.com 和 https://api.koozhan.com/v1 |
| key 走哪个请求头 | x-api-key 或 Authorization: Bearer,看中转站认哪个。SDK 里分别对应 api_key 和 auth_token |
两种都认(文档里 Anthropic 接口的 curl 例子用 x-api-key,接 Claude Code 时用 Bearer) |
| 模型名 | 以中转站列出来的为准,不一定和官方的全一样 | 见第六节 |
地址这一条是最常见的错:酷站AI 的文档专门写了“Anthropic SDK / Claude Code 的 base_url 不要带 /v1”。本站在假网关上看到,多写了 /v1,SDK 发出去的路径是 /v1/v1/messages。
二、Python SDK
不改代码:只设环境变量
SDK 读三个环境变量:ANTHROPIC_BASE_URL 是地址;key 放进 ANTHROPIC_AUTH_TOKEN 走 Bearer,放进 ANTHROPIC_API_KEY 走 x-api-key。
export ANTHROPIC_BASE_URL="https://api.koozhan.com"
export ANTHROPIC_AUTH_TOKEN="你的 key"
代码和直连官方时一模一样:
import anthropic
client = anthropic.Anthropic()
r = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=20,
messages=[{"role": "user", "content": "只回答两个字:收到"}],
)
print(r.model, r.content[0].text)
经中转站实测,Bearer 和 x-api-key 两种都返回了 收到,model 字段是 claude-sonnet-5-5。
写在代码里:传参数
地址和 key 放在你自己的配置里时,直接传给构造函数。下面这段在服务器上经中转站跑过:
import os
import anthropic
# 地址和 key 从你自己的配置里读,这里用两个自定义的环境变量代替
RELAY_URL = os.environ["MY_RELAY_URL"]
RELAY_KEY = os.environ["MY_RELAY_KEY"]
client = anthropic.Anthropic(base_url=RELAY_URL, auth_token=RELAY_KEY)
中转站要 x-api-key 的,把 auth_token= 换成 api_key=。
几种设置同时出现时,到底发出了什么
这一节是在假网关上测的:用假的 key,只记下收到的路径和带了哪个请求头。TypeScript 的结果放在一起对照,下一节细说。
| 设置 | Python 1.13.0 发出的 | TypeScript 0.133.0 发出的 |
|---|---|---|
只设 ANTHROPIC_AUTH_TOKEN |
Authorization |
同左 |
只设 ANTHROPIC_API_KEY |
x-api-key |
同左 |
| 两个都设 | 两个头都发 | 同左 |
ANTHROPIC_API_KEY="",另设 ANTHROPIC_AUTH_TOKEN |
只发 Authorization,空字符串当作没设 |
同左 |
环境里有 ANTHROPIC_API_KEY,代码里传 auth_token / authToken |
只发代码里那个,环境里的 key 不读 | 两个头都发:代码里的走 Authorization,环境里的照样走 x-api-key |
地址末尾多写 /v1 |
路径变成 /v1/v1/messages,404 |
同左 |
地址末尾带一个 / |
正常,SDK 去掉了 | 同左 |
环境变量指向别处,代码里传 base_url / baseURL |
用代码里的 | 同左 |
设 ANTHROPIC_CUSTOM_HEADERS="X-Org-Route: test" |
多带了这个头 | 同左 |
几件要记住的事:
- 代码里传了任何一种凭据,Python SDK 就不再读环境变量里的 key。 官方文档的凭据先后也是这么写的:构造参数第一,其次才是
ANTHROPIC_API_KEY和ANTHROPIC_AUTH_TOKEN。 - 两个变量都设了,两个头都会发出去。 酷站AI 上,
x-api-key是个错的、Bearer 是对的,请求照样成功;别的中转站先看哪个头,本站没有测。最稳的是只留一个。 - 空字符串:文档和 SDK 的行为不一样。 官方文档说设成空字符串的变量“仍然占着它在先后顺序里的位置”,建议用
unset而不是设成""。本站测的两个版本都把空字符串当作没设。照文档的建议做,不受版本影响。 - 只设地址、不设 key 时要小心。 按文档的先后,环境变量里没有 key,SDK 会接着找
ANTHROPIC_PROFILE和磁盘上的配置(~/.config/anthropic/下的 profile,用官方命令行ant auth login登录过就有)。照这个顺序推,地址指向中转站时,那份官方登录的凭据可能被带过去。这是本站的推断,测试机上没有 profile,没有实测;接中转站时把 key 也设上,就不会走到这一步。 ANTHROPIC_CUSTOM_HEADERS是 Claude Code 网关文档里给“要额外带一个头”的网关准备的变量,两个 SDK 都认,多个头用换行分隔。SDK 的文档没写它,以上是这两个版本的实测。
三、TypeScript SDK
参数名换成驼峰:baseURL、apiKey、authToken,读的还是那三个环境变量。只设环境变量、代码不改,经中转站实测正常。
和 Python 最大的不同在上表第五行:代码里传了 authToken,环境里的 ANTHROPIC_API_KEY 仍然会作为 x-api-key 一起发出去。 如果你的机器上本来就有一个官方的 ANTHROPIC_API_KEY,它会跟着请求发给中转站。要只发代码里那个,把 apiKey 显式写成 null:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: process.env.MY_RELAY_URL,
authToken: process.env.MY_RELAY_KEY,
apiKey: null, // 不再读环境里的 ANTHROPIC_API_KEY
});
假网关上,加了 apiKey: null 之后只收到 Authorization。经中转站,加与不加都返回了 收到(酷站AI 用的是 Bearer 那个)。
四、OpenAI SDK
已有代码用的是 OpenAI 的 SDK,也可以直接调 Claude 的模型。地址要带 /v1,key 走 Authorization: Bearer:
from openai import OpenAI
client = OpenAI(base_url="https://api.koozhan.com/v1", api_key="你的 key")
r = client.chat.completions.create(
model="claude-sonnet-5-5",
max_tokens=20,
messages=[{"role": "user", "content": "只回答两个字:收到"}],
)
print(r.model, r.choices[0].message.content)
经中转站实测:带 /v1 正常,finish_reason 是 stop;不带 /v1 返回 404(假网关上看到的路径是 /chat/completions)。
官方文档说这个兼容层主要是拿来测试和对比模型的,不算长期、正式的方案,很多 Claude 自己的功能用不了,细节见《Claude 的 SDK 和命令行》的兼容层一节。酷站AI 的文档也写了,走 OpenAI 兼容接口时,Claude 模型会在网关里转换成 Anthropic 的接口。要用 Claude 特有的功能,换回 Anthropic 的 SDK。
五、Agent SDK
Agent SDK 不是自己发请求,而是起一个 Claude Code 子进程,由 Claude Code 去调接口。所以凭据要让那个子进程拿到,有三条路:
| 凭据从哪来 | 实测结果 |
|---|---|
进程的环境变量(ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN),配置目录是空的 |
正常 |
进程环境里没有,写在 ClaudeAgentOptions(env={...}) 里 |
正常 |
环境变量都没有,靠 ~/.claude/settings.json 里 env 那两行 |
正常 |
同上,但设了 setting_sources=[] |
报 Not logged in · Please run /login,设置文件不读了,凭据也就没了 |
| 配置目录是空的,也没有环境变量 | 同上,未登录 |
from claude_agent_sdk import query, ClaudeAgentOptions
# RELAY_URL、RELAY_KEY 同第二节,从你自己的配置里读
options = ClaudeAgentOptions(
env={"ANTHROPIC_BASE_URL": RELAY_URL, "ANTHROPIC_AUTH_TOKEN": RELAY_KEY},
model="claude-sonnet-5-5",
)
几点说明:
- Python 版的
env是合并,TypeScript 版是整个替换。 官方文档写明,TypeScript 里要先展开process.env再加自己的变量,否则PATH、HOME这些都没了。TypeScript 版本站这次没有测。 - 初始化消息里的
apiKeySource三种能用的情况都是none。 这个字段只报ANTHROPIC_API_KEY一类的来源,key 放在ANTHROPIC_AUTH_TOKEN时它显示none,不代表没有凭据。 - 放到服务器上跑时,凭据用环境变量给,不要依赖某个用户的设置文件,见《把 Agent SDK 的智能体放到服务器上》。
六、接上之后,先做三件事
1. 列一下模型。 能列出来,说明地址和 key 都对;顺便看你要用的模型在不在:
print([m.id for m in anthropic.Anthropic().models.list(limit=100)])
本站这把 key 列出 16 个,有 claude-sonnet-5-5、claude-opus-5-5、claude-fable-5-1,没有 claude-haiku-5-5。
2. 发一条最小的请求。 max_tokens 给 20,看返回的 model 字段和 usage 是不是你预期的。
3. 判断给的是不是真的 Claude。 能调通不等于模型是真的。办法见《thinking signature 是什么》和《中转站怎么掺假》,也可以用 Veridrop 测一次。
七、报错对照
都是经中转站实测到的:
| 现象 | 可能的原因 | 怎么分辨 |
|---|---|---|
| 404 | Anthropic 的 SDK 地址多写了 /v1 |
列模型也 404,就是地址的问题 |
| 404 | OpenAI 的 SDK 地址少写了 /v1 |
同上 |
| 404 | 地址末尾有两个斜杠(一个没事) | 同上 |
| 404 | 模型名写错(比如 claude-sonnet-5.5),或者这把 key 没开这个模型(比如 claude-haiku-5-5) |
列模型能成功,就是模型名的问题。Claude Code 的网关文档也说,报“模型不认识”本身就证明地址和 key 是通的 |
Agent SDK 报 Not logged in |
凭据没传进子进程,或者 setting_sources=[] 把设置文件关了 |
看环境变量和 env 参数 |
Claude Code 的网关文档说,key 放进了网关不读的那个头,会返回 401,提示 key 无效。酷站AI 两种头都认,本站在它上面测不出这个 401;碰到了,把 auth_token 和 api_key 换一下再试。
这次实测没有覆盖到的
- 只测了 Python 和 TypeScript 两种 SDK。 Go、Java、C#、PHP、Ruby 的 SDK 没有测,参数名以各自的文档为准。
- profile 和身份联合那两步没有测,测试机上没有
ant的登录配置。 - 只测了一家中转站。 两个头都发时用哪个、key 放错头时返回什么,各家可能不一样。
- Agent SDK 只测了 Python 版,TypeScript 版
env的替换行为照文档写。 - 流式输出这次没有单独测,经中转站的流式见《第一次直接调 Claude 的接口》。