模型列表拉不出来怎么排查:自动拉取型与手写型工具的两条不同路径
接好自定义 API 之后选不到模型,第一步不该是换密钥,而是先判断你手上这个工具的模型列表到底是它自己去服务端拉的,还是要你一行行写进配置文件的。 这两类工具的排查动作从第一步就分叉:前者是网络与端点的问题,后者根本不是”出错”,而是你还没写。判断错了方向,密钥换三遍也没用。
本文只谈”模型选不到”这一段。相关但不同的问题各有专文:路由到了某个上游却调用失败,看 OpenRouter 路由失败排查;模型能选到、请求也发出去了,但返回的 JSON 结构对不上导致解析炸掉,看 API 返回结构变了怎么办;模型正常但工具读不懂你的代码库,那是索引层的事,看 Cursor 索引失败排查。这篇的边界很窄:卡在”还没能选中一个模型”之前。
一、先分清两类:列表是拉来的,还是你写上去的
先把一个容易混的概念说清楚。OpenAI 兼容端点指的是:服务商把自家的接口做成和 OpenAI 那套 HTTP 协议一样的形状,路径、请求体、返回体都对齐,于是任何按 OpenAI 协议写的客户端都能直接接上去。绝大多数编程工具的”自定义模型”功能,走的就是这条路。
但”协议一样”不等于”取模型列表的方式一样”。截至 2026-08-07 各家官方文档,可以看出两种明显不同的设计取向:
第一类,客户端主动去拉。 Kilo Code 官方文档写明:凭据有效时,它会从 /v1/models 端点自动拉取模型列表;自动检测失败可以手动填模型 ID。按这段文档描述的机制去推,这类工具的”没有可选模型”就有一条可追的因果链 —— 有一次取列表的网络请求应该发出去过,结果不合预期。链条可追,排查才有顺序可言。
第二类,你写多少它就有多少。 Zed 的 settings.json 里,模型写在 available_models 数组中,每一项自己带 name、display_name、max_tokens。Continue 的 config.yaml 里,模型写在 models 块下,每一项必填 name、provider、model 三项。这两家的文档记录都是手写形态。对这类工具来说,你没写,就没有 —— 这不是故障,是设计。
判断方法很直接:看这个工具的官方文档里,配置模型时给的是”一个表单/一条命令”,还是”一段 YAML/JSON 数组”。给数组的,八成属于第二类。
顺带说一句界面:本文不描述任何一家的界面长什么样,配置项在哪一屏、有没有提示文字,以你实际看到的界面为准。这里只谈配置层,因为配置层是你能在文件里、在终端里自己复核的部分。
二、自动拉取型:排查顺序跟着那次请求走
如果你的工具属于第一类,排查就沿着”客户端 → 端点 → 凭据 → 返回”这条链走,而不是漫无目的地换东西。
第一步核 Base URL 的形态。 这一项各家写法不统一,也最容易照着别家的示例填错。Kilo Code 官方文档明确说它接受两种形态:标准形态 https://api.provider.com/v1,以及完整端点 https://api.provider.com/v1/chat/completions;文档说明第二种是为”端点结构非标准”的服务商与自建网关准备的。注意这是 Kilo Code 这一家文档的写法,别把它套到别家 —— 各家这一项连字段名都不一样,详见下一节的表。
至于”少写或多写一段路径会怎样”,这属于 HTTP 路由的一般机制:客户端会把配置的前缀和它自己要访问的路径拼起来发出去,拼出来的地址在服务端不存在,就拿不到列表。这是协议层的推理,不是哪家文档写的结论。要自己验一次很简单:打开终端,用 curl 带上你的密钥去请求你填进配置的那个地址后面接 /models(例如前缀写的是 .../v1,就请求 .../v1/models),命令形如 curl -H "Authorization: Bearer 你的密钥" 地址。算通过的标准:HTTP 状态码 200,返回体里能看到一个模型对象的数组。若返回 404,说明地址拼错或该服务端不提供这个接口;返回 401/403,问题在密钥不在地址;连接直接失败或超时,问题在网络层,往下看第五节的边界说明。
第二步核凭据。 密钥无效时拉不到列表,这在逻辑上是显然的 —— Kilo Code 文档的措辞就是”凭据有效时”才会自动拉取。所以别急着怀疑端点,先确认这把密钥在别处能用。具体动作:拿上一步那条 curl 命令,把地址换成服务商文档首页给的示例地址,密钥不变再跑一次。算通过的标准:换了地址就能拿到 200,说明密钥没问题,锅在你填的那个前缀;两个地址都是 401/403,说明密钥本身失效或复制时带了空格与换行 —— 后者极常见,重新复制一遍再试。
第三步看是不是这条链根本不适用。 Kilo Code 文档里有一条很具体的提醒:接 Azure 上的 GPT-5 时,不要用通用的 OpenAI 兼容 provider,要用 Kilo 原生的 azure provider,因为 Azure 会拒绝 max_tokens 参数。这条提醒的价值在于提醒你一个更普遍的判断 —— 你以为的”兼容端点”,可能在某个参数上并不兼容。这时候换密钥、改 URL 都是徒劳。
第四步再回到手填。 Kilo Code 文档说得很清楚,自动检测失败可以手动填模型 ID。所以自动拉取型工具最终也能退化成手写型来用。这一步不丢人:并非所有 OpenAI 兼容端点都实现了列模型的那个接口,上一步的 curl 若稳定返回 404,基本就该走手填这条路了。手填时模型 ID 从哪儿抄?从服务商文档里调用示例的请求体上抄,别自己拼。
三、手写型:列表是空的,因为你还没写完那段配置
第二类工具的排查,本质上是”对照文档补字段”。
Continue 的模型配置在 config.yaml 的 models 块下,必填三项:name(唯一标识)、provider(如 openai、ollama、mistral)、model(具体模型名)。可选项里有 apiBase,用于覆盖默认 API 端点。官方文档给的示例可以原样抄:
models:
- name: GPT-4o
provider: openai
model: gpt-4o
roles:
- chat
- edit
defaultCompletionOptions:
temperature: 0.7
maxTokens: 1500
这里有个很容易忽略的机制:Continue 的 roles 取值有 chat、autocomplete、embed、rerank、edit、apply、summarize,默认值是 [chat, edit, apply, summarize]。embed 指把文本转成向量用于检索,rerank 指对检索回来的结果重新排序 —— 这两件事和聊天是不同的角色。文档记录到”取值有哪些、默认是哪几个”为止,客户端拿这份取值具体怎么分派功能,文档没有逐条说明;按字段语义推,默认值里不含 embed/rerank,要用到它们大概率得显式写出来,实际行为以官方文档为准。这不是”列表空”,但和”某个功能选不到模型”是同一类误会。
Zed 这边,官方文档给的 settings.json 结构如下:
{
"language_models": {
"openai_compatible": {
"my-provider": {
"api_url": "https://example.com/v1",
"available_models": [
{
"name": "my-model",
"display_name": "My Model",
"max_tokens": 128000
}
]
}
}
}
}
api_url 是自定义 base URL;available_models 是模型数组,每项含 name(模型标识)、display_name(界面显示名)、max_tokens(上下文窗口上限)。上下文窗口指模型一次请求能容纳的 token 总量,超出就装不下 —— 这一项在 Zed 这里要你自己填。另外 Zed 还有 capabilities 对象控制能力开关,含 tools、images、parallel_tool_calls 等。
密钥这一项 Zed 的文档态度很明确,原话是 “Do not put API keys in settings.json.”,另一页写的是 “Provider keys saved through Zed are stored in the system keychain, not in settings.json.”(keychain 是操作系统提供的凭据保管服务,密码由系统加密保存,不落在明文文件里)。凭据的两条路是:provider 设置界面,或环境变量,命名规则为 <PROVIDER_NAME>_API_KEY —— provider 名为 my-provider 时对应 MY_PROVIDER_API_KEY。以上是官方文档的说法,不是本文的建议。
顺带对照一下:Gemini CLI 的 settings.json 支持环境变量插值,写成 $VAR_NAME 或 ${VAR_NAME},加载时自动解析。所谓插值就是配置文件里只写变量名,实际值运行时从环境里取 —— 这样配置文件能进版本库,密钥不进。三家在”密钥怎么和配置文件共处”上给的答案不同,但都是可复核的文档事实。
四、字段对照表:同一件事,五个名字
下表的字段名逐字来自各家官方文档,核对日期 2026-08-07。
| 配置项(逐字) | 属于哪家 | 它是什么 | 这一项不对时的后果(按协议与字段语义推断,非厂商说法) | 出处 |
|---|---|---|---|---|
Base URL | Kilo Code | 服务端 API 的地址前缀,文档说接受 /v1 与 /v1/chat/completions 两种形态 | 拼出的地址在服务端不存在,请求拿不到有效返回 | kilo.ai 文档 |
Models | Kilo Code | 模型来源,可手动添加或自动检测 | 自动检测走不通时需退回手填模型 ID | 同上 |
Headers | Kilo Code | 可选,自定义 HTTP 头,键值对形式 | 网关要求的鉴权头缺失时,请求会被上游拒绝 | 同上 |
apiBase | Continue | 覆盖默认 API 端点 | 不写则走该 provider 的默认端点,自建服务不会被访问到 | docs.continue.dev |
roles | Continue | 模型承担的角色,默认 [chat, edit, apply, summarize] | 需要 embed/rerank 却没写,对应功能选不到这个模型 | 同上 |
api_url | Zed | 自定义 base URL | 同 Base URL 的路由后果 | zed.dev 文档 |
available_models | Zed | 手写的模型数组,每项含 name/display_name/max_tokens | 数组为空则没有可选项,这是配置结果不是故障 | 同上 |
<PROVIDER_NAME>_API_KEY | Zed | 环境变量形式的密钥命名规则 | 变量名拼错等同于没配密钥 | 同上 |
再补一条跨家对照,同样来自各家文档:Cline、Roo Code、Kilo Code 在配置里叫 Base URL;Continue 叫 apiBase;Zed 叫 api_url;goose 用 OPENAI_HOST(另有 OPENAI_BASE_PATH,是拆成两段的设计);Crush 用命令行参数 --base-url。这五个不是同一个东西,照搬别家的填法就是自己给自己造 bug。
还有一条硬门槛值得单列。Roo Code 官方文档原话是:
“Roo Code uses native tool calling exclusively. This is the only supported tool protocol — there is no XML-based fallback.”
原生工具调用(function calling)指模型按结构化协议返回”要调用哪个工具、传什么参数”,而不是把意图写在自然语言里让客户端猜。按 Roo Code 文档的说法,它只认这一种协议、没有 XML 回退,文档建议先查服务商文档确认该模型是否支持工具调用。这意味着在 Roo Code 上,“模型能选到”和”模型能干活”是两道关。Continue 有 capabilities.tool_use,Zed 的 capabilities 含 tools 与 parallel_tool_calls,说明这件事在几家都被当成需要显式声明的能力。
五、边界与代价:这条排查路径不管什么
先说这套方法放弃了什么。
它只覆盖配置层,不覆盖网络层。 公司代理、证书拦截、DNS 解析异常,都会让”端点填对了也拉不到”,而这套排查完全看不见这类原因。遇到怎么改配置都不通的情况,请把排查交给网络侧,别在配置文件里继续试。
它不判断模型好不好用。 能选中一个模型,和这个模型能不能撑住你的活,是两件事。工具调用支持与否、上下文窗口够不够,属于模型能力范畴,本文只讲到”配置项在哪一栏”为止。接入方式的整体对比可以看 编辑器接入自定义 API 的做法,兼容端点本身的协议差异看 OpenAI 兼容端点是什么。
它不给你任何数字。 价格、免费额度、限速、各家支持的完整模型清单,本文一律不写,这类内容变化太快,写下来就是给你埋雷。
它不能替代官方文档的完整性。 本文依据的是各家官方文档在 2026-08-07 那一天的记录。某个字段没在本文出现,只说明本文依据的那一页记录里没有它,不等于该产品没有这项能力。要下结论请翻文末列出的原始 URL。
还有一件明确不管的事:本文不排各家座次。几家在设计取向上确实不同 —— 有的把模型列表交给服务端接口,有的要你写死在配置里 —— 但这是取向差异,不是优劣。自动拉取省事,代价是多一层依赖;手写麻烦,代价换来的是配置完全可预期。
六、避坑清单:为什么会踩,怎么避
坑一:把别家的字段名搬过来用。
为什么会踩:这些工具在你眼里都是”填个地址和密钥”,字段名的差异在脑子里被抹平了。怎么避:配置前先打开你正在用的那一家的文档页,字段名逐字对照,尤其是 apiBase、api_url、Base URL、OPENAI_HOST、--base-url 这五个 —— 长得像,位置也像,但不通用。
坑二:在手写型工具上等着列表自己出现。
为什么会踩:用惯了自动拉取型工具,会默认”配完就该有”。怎么避:先确认工具类型。看到文档给的是 available_models 数组或 models 块,就说明模型得你写;写完之前不存在”列表为空”这个故障。
坑三:/v1 加不加全靠猜。
为什么会踩:各家示例形态不一致,Kilo Code 文档接受两种写法,别家未必。怎么避:以你正在配的这一家的文档示例为准,别用另一家的示例反推。真拿不准就用命令行直接请求一次那个地址,看服务端怎么回。
坑四:把密钥写进会进版本库的文件。
为什么会踩:JSON/YAML 配置文件里正好有个像密钥的位置,顺手就填了。怎么避:Zed 文档直接写了 “Do not put API keys in settings.json.”,凭据走设置界面或 <PROVIDER_NAME>_API_KEY 环境变量;Gemini CLI 那种支持 $VAR_NAME 插值的,也可以让配置进库、密钥留在环境里。
坑五:只顾着接上,忘了工具调用这道关。 为什么会踩:模型能出现在可选项里,看起来就”成了”。怎么避:如果你用的工具对工具调用有硬要求(Roo Code 文档写明只认原生 tool calling、无 XML 回退),配之前先去服务商文档确认这个模型支持不支持 —— 这是 Roo Code 文档自己给的建议。
坑六:把”兼容”当成全参数兼容。 为什么会踩:兼容端点这个词太让人放心了。怎么避:记住 Kilo Code 文档那条 Azure 提醒的形状 —— 某个上游可能拒绝某个具体参数,这时候通用兼容通道就是走不通的,得换专用接入方式。遇到怎么调都不对的情况,早点怀疑参数层。
坑七:把 roles 的默认值当成”全都有”。
为什么会踩:写完 models 三项必填就以为配完了。怎么避:打开文档的 roles 一节,逐字对一遍默认值 —— Continue 文档记的默认是 [chat, edit, apply, summarize],embed、rerank 不在其中。要用嵌入或重排,先试着把这两个值显式写进 roles 再看功能里能不能选到这个模型;这一步是按字段语义推的做法,文档没有逐条说明其效果,以官方文档为准。
最后提醒时效:上面提到的所有字段与行为,都是截至 2026-08-07 各家官方文档的情况,请以官方文档最新版为准。
数据来源与核对日期
本文全部产品事实来自以下官方文档页面,核对日期均为 2026-08-07:
- Kilo Code(Base URL 两种形态、
/v1/models自动拉取、Provider ID / Display name / Provider API / Base URL / API key / Models / Headers 字段、Azuremax_tokens提醒):https://kilo.ai/docs/providers/openai-compatible - Continue(
config.yaml的models块、name/provider/model必填、apiBase、roles取值与默认值、capabilities、YAML 示例):https://docs.continue.dev/reference - Zed(
settings.json结构、api_url、available_models与name/display_name/max_tokens、capabilities、密钥两句原话与<PROVIDER_NAME>_API_KEY命名规则):https://zed.dev/docs/ai/use-api-access、https://zed.dev/docs/ai/configuration - Roo Code(native tool calling 原话与”先查服务商文档确认工具调用支持”的建议):https://roocodeinc.github.io/Roo-Code/providers/openai-compatible
- Cline(配置里的 Base URL 一项,用于跨家字段名对照):https://docs.cline.bot/provider-config/openai-compatible
- goose(
OPENAI_HOST与OPENAI_BASE_PATH的两段式设计):https://goose-docs.ai/docs/getting-started/providers/ - Crush(
--base-url命令行参数):https://raw.githubusercontent.com/charmbracelet/crush/main/README.md - Gemini CLI(
settings.json的$VAR_NAME/${VAR_NAME}环境变量插值):https://google-gemini.github.io/gemini-cli/docs/get-started/configuration.html
本文明确没有写的内容:任何产品的价格、免费额度、订阅档位、限速数字、版本号,以及各家支持的完整模型清单。这些要么会随时变动,要么本次未做核实,写进来只会误导你;请一律以各产品官方文档为准。同样没有写的还有各家的界面长相与菜单层级 —— 本文依据的是配置层记录,界面以你实际看到的为准。表格中”后果”一列,以及正文里关于 roles 取值如何影响功能可选性的说法,都是按 HTTP 协议通用行为与字段名语义推出的判断,不是任何一家官方文档的原文表述;同样地,正文给出的 curl 验证步骤是通用协议层做法,不是哪一家文档记载的官方排查流程。
延伸阅读:同一组里的 编辑器里报 401 但 curl 正常、聊天能用补全不工作;接完之后照 接完自定义模型别急着干活 逐项过一遍,才算真接通。