Claude Code、Codex CLI 与 Gemini CLI 接入前的 6 项兼容性检查
把 Claude Code、Codex CLI 或 Gemini CLI 接到同一个 API 网关时,最容易忽略的不是模型名称,而是协议差异:模型列表里能看到名称,客户端却报 404;普通对话能返回文本,一开工具调用就失败;请求返回 200,日志里的模型、用量字段却对不上。
本文只讨论如何验证兼容性,不做服务商排行,也不比较套餐或价格。三种 CLI 不是简单替换同一个 Base URL,它们背后至少涉及 Anthropic Messages、OpenAI Responses 和 Gemini generateContent 三种请求结构。
文中的请求字段以各厂商公开接口结构为依据,示例统一使用占位地址和占位模型名,读者应替换成自己实际使用的配置。
先看清:三种 CLI 不是一个接口换三次名字
| 客户端方向 | 官方核心接口 | 最小请求重点 | 成功后至少回读 |
|---|---|---|---|
| Claude Code | POST /v1/messages | x-api-key、anthropic-version、messages、max_tokens | id、content、usage、停止原因 |
| Codex CLI | POST /v1/responses | Bearer 鉴权、model、input | id、status、output、usage |
| Gemini CLI | POST .../v1beta/models/{model}:generateContent | x-goog-api-key、contents.parts | responseId、modelVersion、candidates、usageMetadata |
表中的路径和字段来自三家模型厂商当前官方 API 文档。中转平台可能在域名前增加自己的前缀,也可能只兼容其中一部分。“兼容 OpenAI”不能自动推导出兼容 Anthropic Messages 或 Gemini 原生协议。
检查一:路径是否真的存在
最先确认的不是模型名称,而是客户端实际访问的路径。下面的脚本只检查端点是否被网关识别,不要求返回成功内容:
BASE_URL="https://example-gateway.test"
for path in \
"/v1/messages" \
"/v1/responses" \
"/v1beta/models/example-model:generateContent"
do
code=$(curl -sS -o /dev/null -w '%{http_code}' \
-X POST "${BASE_URL}${path}" \
-H 'Content-Type: application/json' \
-d '{}')
printf '%-58s %s\n' "$path" "$code"
done
这里不能把所有非 200 都判为“不支持”。401 或 403 往往说明路径存在但鉴权失败,400 可能说明路径存在但请求体不完整;稳定的 404 才更接近“路径或前缀不对”。仍需结合平台文档和完整错误体判断。
检查二:鉴权头不能照搬
三套协议的官方鉴权写法不同。OpenAI Responses 通常使用 Authorization: Bearer ...,Anthropic Messages 使用 x-api-key 并要求 anthropic-version,Gemini API 使用 x-goog-api-key。有些中转站会把它们统一成一种写法,但这必须由文档或真实请求证明。
排障时建议先打印“发送了哪些请求头名称”,不要打印请求头的值。公开截图中只保留密钥前四位和后四位也不安全,最稳妥的做法是完整遮挡。
检查三:用最小请求验证响应结构
下面给出 Messages 和 Responses 两个最小请求。模型名、地址和 Key 都用环境变量提供,避免把真实密钥写进脚本:
# Anthropic Messages 结构
curl "$BASE_URL/v1/messages" \
-H "x-api-key: $API_KEY" \
-H 'anthropic-version: 2023-06-01' \
-H 'content-type: application/json' \
-d '{
"model": "'$CLAUDE_MODEL'",
"max_tokens": 32,
"messages": [{"role":"user","content":"只回复 OK"}]
}'
# OpenAI Responses 结构
curl "$BASE_URL/v1/responses" \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "'$OPENAI_MODEL'",
"input": "只回复 OK",
"max_output_tokens": 32
}'
最小请求只验证认证、路径、模型名和基本响应结构。它不能证明流式事件、工具调用、长上下文和 CLI 的完整交互已经兼容。
检查四:流式与工具调用要单独测
CLI 工具常常依赖流式事件和工具调用。如果平台只是把最终文本转换成兼容格式,普通 curl 可能成功,CLI 仍会卡在“等待工具结果”。
至少要追加两类测试:一是要求模型分段输出,确认事件顺序、结束事件和异常中断能被客户端解析;二是提供一个无副作用工具,例如只读取固定字符串,确认工具名称、参数、调用标识和工具结果能完整往返。文本能返回,不等于 Agent 工作流可用。
检查五:模型名、分组和实际路由要对上
模型出现在价格页,只能证明目录展示。真实请求完成后,应核对四层信息:请求中的目标模型、响应中的模型字段、账号所属分组、平台调用日志中的实际模型或渠道。如果平台发生自动回退,还要明确记录回退前后的模型,不能因为最终有文本就把它算作目标模型成功。
一个安全的脱敏记录可以长这样:
测试时间:2026-09-05 17:21 CST
目标协议:OpenAI Responses
目标模型:gpt-6-astra
结果标记:返回预期短文本
平台日志:模型字段一致
用量回读:输入 514 Token,输出 22 Token
费用回读:$0.000562
未公开:API Key、请求 ID、账号、上游线路
这条脱敏记录来自笔者运营的 FishAI API 测试环境。客户端收到预期文本,后台日志能对应同一时间窗口、模型、输入输出 Token 和费用。它只证明这一次 Responses 请求形成了“请求—响应—用量—扣费”闭环;不能外推为三种 CLI 全部兼容,也不能外推为长期稳定性。
检查六:失败重试是否造成重复消耗
只记录成功请求,会漏掉失败重试造成的额外消耗。建议为每次验收记录:总请求数、成功数、可重试失败数、实际重试次数、输入 Token、缓存读取、缓存写入、输出 Token 和最终费用。
最简单的总成本口径是:
总成本 = 所有尝试的输入费用 + 缓存费用 + 输出费用 + 失败请求可能产生的费用
如果第一次请求已经发送了长上下文,自动重试又完整发送一次,同一段输入就可能被重复处理。重试必须有上限;同一错误连续出现时,应先判断路径、鉴权、限流还是服务端故障,而不是无限重放。
一张可直接使用的验收表
在决定把某个中转站接进日常开发前,可以用下表保存结果:
| 检查项 | 通过标准 | 当前结果 |
|---|---|---|
| 协议路径 | 对应端点有明确文档且请求可达 | 通过 / 失败 / 未确认 |
| 鉴权 | 不改源码即可安全传递 Key | 通过 / 失败 / 未确认 |
| 最小请求 | 返回结构与目标协议一致 | 通过 / 失败 / 未确认 |
| 流式与工具 | CLI 能完成一次真实工具往返 | 通过 / 失败 / 未确认 |
| 路由与日志 | 目标模型、实际模型、用量可核对 | 通过 / 失败 / 未确认 |
| 计费与重试 | 成功和失败尝试都能解释成本 | 通过 / 失败 / 未确认 |
“未确认”不是零,也不是默认通过。特别是流式、工具调用和计费,缺证据时宁可保留未确认。
结论:先完成协议验收
三种 CLI 分别依赖不同的请求结构。可复现的兼容性判断应包括路径、鉴权、最小响应、流式工具、实际路由和计费重试六项。
无论使用自建网关还是第三方兼容服务,都应先用脱敏小样跑完目标协议,再核对自己的调用日志。能说清“请求去了哪里、返回了什么、用了多少 Token、为什么产生这些用量”,再进入更复杂的流式和工具调用测试。
资料核对日期:2026-09-06。官方协议依据:OpenAI Responses API、Anthropic Messages API、Google Gemini generateContent API。模型、路径和平台兼容范围会变化,发布前应再次核对当前文档和账号实际返回。
更多推荐



所有评论(0)