跳到主要内容
注册

用一个 .qwen/.env 文件或一条 modelProviders 条目把 Qwen Code 接到 Router One

Qwen Code 是 Qwen 团队开源的终端编程 agent:读写文件、执行 shell 命令、循环调用工具;它最初基于 Gemini CLI,从 v0.1 起独立开发。它的 openai auth type 默认通过官方 OpenAI Node.js SDK 发送 Chat Completions 请求,指向 Router One 后就能用一把 Key 调用目录里在 /v1/chat/completions 上提供服务的所有聊天模型——GPT、Claude、Gemini、Grok 和 DeepSeek 系列——每一轮模型调用在控制台 → 日志都有成本和延迟 Trace,而 agent 循环、工具执行、审批和会话仍留在 Qwen Code 本地。网关在中国大陆可直连,无需 VPN。本指南讲三变量的 .qwen/.env 配置、把多个目录模型放进 /model 选择器的 modelProviders 条目、两者同时存在时哪个值生效,以及怎样给一次会话定预算。

安装 Qwen Code 并单独建一把 Key

用 npm 安装需要 Node.js 22 或更新版本;README 还提供 Linux/macOS/Windows 的独立安装脚本和 Homebrew 包。安装后在项目目录里启动 qwen:首次运行会打开 /auth 菜单,其中 Custom Provider 选项面向 OpenAI 兼容端点,但本指南的两个文件不经过菜单也能完成同样的配置;随时可以用 /doctor 查看认证和环境检查。动手之前,先为 Qwen Code 单独创建一把设了 maxSpend 的 Router One Key:agent 会话每一轮模型调用、每次工具结果回传都是一次请求,这个上限就是硬性止损。Key 只写进下面的 .qwen/.env,不写进 settings.json。

terminal
npm install -g @qwen-code/qwen-code@latest
cd /path/to/your-project
qwen

把 Qwen Code 配置到 Router One base URL

在项目根目录创建 .qwen/.env,写入下面三个变量;这是 Qwen Code 文档推荐存放项目级密钥的文件,要排除在 git 之外。OPENAI_API_KEY 填 Router One Key——按身份验证文档的说法,只用环境变量时,正是导出 OPENAI_API_KEY 这一步选中了 OpenAI 兼容认证,provider 专属的变量名不会。OPENAI_BASE_URL 填带 /v1 的 https://api.router.one/v1:openai auth type 用这个值构造官方 OpenAI Node.js SDK 客户端,SDK 在它后面拼 /chat/completions,所以每一轮模型调用就是一个 POST /v1/chat/completions。OPENAI_MODEL(别名 QWEN_MODEL)填精确的目录模型 ID,它就是每次请求 model 字段的值;--model <id> 可以在单次会话里覆盖它。Qwen Code 只加载找到的第一个 .env 文件——从当前目录向上依次找 .qwen/.env 和 .env,找不到再回退到 ~/.qwen/.env 和 ~/.env——而且不会覆盖 shell 里已经导出的变量,所以 ~/.zshrc 里一个过期的 OPENAI_BASE_URL 会压过这个文件。这种形式创建的是文档所说的 Runtime Model:只有一个模型,选择器里没有条目;如果 qwen 仍然弹出 /auth 菜单,按下一节加上 security.auth.selectedType。启动 qwen,运行 /doctor,发一条简短提示,再到日志里核对它的 Trace。文件内容如下,替换掉 Key 和模型 ID:

.qwen/.env
# <project>/.qwen/.env — the first .env file Qwen Code finds; keep it out of git
OPENAI_API_KEY=sk-your-router-one-key
OPENAI_BASE_URL=https://api.router.one/v1
OPENAI_MODEL=<exact-model-id-from-/models>

把 Router One 登记进 modelProviders,进入 /model 选择器

想在会话里切换多个目录模型,就把它们声明在 ~/.qwen/settings.json——这是文档推荐的用户级作用域,因为项目级设置会整体替换 modelProviders 对象而不是合并。键名 openai 就是 auth type;每个模型可选的 wireApi 决定走哪种 API——默认 Chat Completions,设为 "responses" 则走 /v1/responses;既不是内置 auth type、也没有在 providerProtocol 里映射的键名(例如写错的 openai-custom)会被跳过并给出警告,它下面的模型不会出现在 /model 里。每个条目必须有 id,即作为 model 字段发送的精确目录 ID;name 只是选择器里的显示名;envKey 填保存 Key 的环境变量名——运行时读取 process.env[envKey],从不保存凭据本身——所以把 ROUTER_ONE_API_KEY=sk-your-router-one-key 写进 .qwen/.env 或 ~/.qwen/.env,或者直接 export;baseUrl 填同一个带 /v1 的地址,条目按 API、id 与 baseUrl 三者一起识别,三者完全相同的重复条目会被跳过并给出警告。generationConfig 可选且封闭:选中 provider 模型时它的值整体生效,顶层 model.generationConfig 被忽略;源码里 timeout 默认 120000 毫秒、maxRetries 默认 3。security.auth.selectedType 设为 openai 后,qwen 启动不再弹 /auth 菜单,model.name 必须等于其中一个 id。运行中的会话会自动读取 modelProviders 的改动(重新打开 /model 即可);/model 和 /auth 会把 model.name 和 selectedType 写回定义了 modelProviders 的那个作用域。选中 provider 条目后,它的 baseUrl 和 envKey 优先于 --openai-base-url、OPENAI_BASE_URL 和 OPENAI_API_KEY。

~/.qwen/settings.json
{
  "modelProviders": {
    "openai": [
      {
        "id": "<exact-model-id-from-/models>",
        "name": "<在 /model 里显示的名字>",
        "envKey": "ROUTER_ONE_API_KEY",
        "baseUrl": "https://api.router.one/v1",
        "generationConfig": { "timeout": 120000, "maxRetries": 3 }
      },
      {
        "id": "<another-model-id-from-/models>",
        "envKey": "ROUTER_ONE_API_KEY",
        "baseUrl": "https://api.router.one/v1"
      }
    ]
  },
  "security": { "auth": { "selectedType": "openai" } },
  "model": { "name": "<exact-model-id-from-/models>" }
}

每个值填在哪里,怎么验证

Router One 需要的只有三个变量或一条 provider 条目;下表给出每个值,以及证明它已生效的检查方法。看实际请求最快的办法是 Qwen Code 自己的日志:打开 model.enableOpenAILogging(或加 --openai-logging 参数),每次请求和响应都会以 JSON 写到工作目录的 logs/openai 下。

每个值填在哪里,怎么验证
Qwen Code 字段填什么怎么验证
.qwen/.env → OPENAI_BASE_URL,或 modelProviders.openai[].baseUrlhttps://api.router.one/v1404 not_found 且消息要求 base URL 以 /v1 结尾,说明少了 /v1;打开日志后,logs/openai 下的 JSON 会显示实际 URL
.qwen/.env → OPENAI_API_KEY,或 envKey 指定的那个变量为 Qwen Code 单独创建、设了 maxSpend 的 Router One Key第一次请求出现在日志里这把 Key 名下;401 说明别的值生效了——shell export 压过 .env,而且只加载找到的第一个 .env 文件
.qwen/.env → OPENAI_MODEL(别名 QWEN_MODEL)、--model,或 modelProviders.openai[].id 与 model.name精确的目录模型 ID日志里每条 Trace 的模型与 /models 逐字一致;model.name 必须等于其中一个 id
modelProviders 的键名openai条目在 /model 里归在 openai 下;未知键名会被跳过并给出警告,它下面的模型不会出现
security.auth.selectedTypeopenaiqwen 启动不再弹 /auth 菜单;/doctor 显示认证检查;/model 和 /auth 会把这个字段写回
modelProviders.openai[].wireApi(可选)只在模型详情页列出 POST /v1/responses 的 ID 上设为 "responses";其他 ID 不写(走 Chat Completions);走这条线时 Qwen Code 会去掉 baseUrl 末尾的 /v1 再自行拼上 /v1/responses模型详情页列出 POST /v1/responses;Claude 系列 ID 会在调用任何模型之前收到 400 must be called via,Gemini 的 ID 在这里同样不提供
model.enableOpenAILogging,或 --openai-logging排查期间设为 truelogs/openai 下的 JSON 文件显示每次请求的实际 URL、模型和请求体,可与控制台 → 日志里的 Trace 对照

给一次 Qwen Code 会话定预算,并与日志对账

在 Qwen Code 里一条提示很少只对应一次请求。每一轮模型调用是一次请求,agent 每回传一次工具结果又是一轮;model.maxToolCallsPerTurn 默认把一轮限制在 100 次工具调用,按自适应方式执行,硬性上限 1000;用 /model --fast、--compaction、--vision 指定的辅助模型也各自发请求。openai 传输还会把 timeout(默认 120000 毫秒)和 maxRetries(默认 3)传给 OpenAI SDK,客户端每一次经网关发往模型的尝试都是独立请求,有各自的 request_id。给 Qwen Code 单独一把设了 maxSpend 的 Key:会话触到上限会收到 HTTP 402 并停下,花费不会超过这个上限,你的其他 Key 也照常可用。客户端一侧,model.maxSessionTurns 和 model.sessionTokenLimit 限制对话长度;客户端在输出开始后取消的流会记为 HTTP 499 client_cancelled,只按已上报的用量计费(在输出任何内容之前就取消的流可能没有记录)。对账用 /stats model:它显示 Qwen Code 自己统计的分模型 token 用量和它自己的费用估算;控制台 → 日志才是逐请求的实际费用,带模型、tokens、成本、延迟、状态和 request_id;/stats export 可以把客户端这一侧导出为 CSV 或 JSON。Router One 只记录模型调用元数据;工具、审批、会话和子 agent 都在 Qwen Code 里运行。

Qwen Code 该填哪个模型 ID?

从 /models 页复制精确的模型 ID,保留大小写、连字符和版本后缀,不要用展示名称代替。打开该模型的详情页,核对支持的 API 端点、上下文窗口和工具调用等能力,再与 Qwen Code 当前选择的 provider 和功能对应。模型出现在目录里,不等于当前客户端能调用它的所有功能。建议为每个客户端或应用单独建 API Key,并设置 maxSpend 消费上限。

Qwen Code 用的是哪种 API 协议?

OpenAI 兼容描述的是接口格式,不能据此推断 Chat Completions(/v1/chat/completions)、Responses(/v1/responses)和 Anthropic Messages(/v1/messages)可以互换。先核对工具当前版本、provider 配置和实际请求路径,再查模型详情与 API 兼容性事实页。一次普通对话成功,也不能证明服务端工具、历史状态或文件编辑功能都受支持。

在请求日志里核对 Qwen Code 的调用

先在 Qwen Code 发出一次简单文本请求,再到控制台 → 日志按时间、模型和 request_id 找到这条记录,核对 Token、花费、总耗时和状态码。成功后再分别验证流式输出、工具调用和多轮历史。失败时保留实际请求路径、完整错误消息及 request_id;没有对应日志时,要么请求没到达网关(客户端配置或网络问题),要么网关在调用模型之前就拒绝了它——Key 问题的 401、余额不足或 Key 达到 maxSpend 上限的 402、Key 或账户自身限额触发的 429,或模型 ID、端点不对的 400 / 404;在输出任何内容之前就失败的流式请求也可能没有日志。看客户端收到的状态码和错误消息就能区分是哪一种;先确认这一点,再判断是不是网关或上游故障。

常见问题

Qwen Code 能启动,但第一次请求报 404 或 401,实际用的是哪个 base URL 和哪把 Key?

生效的值按字段逐个决定,层级从高到低:/auth 里输入的值;选中的 modelProviders 条目(它的 baseUrl 和 env[envKey]);命令行参数 --openai-base-url 和 --openai-api-key;环境变量 OPENAI_BASE_URL 和 OPENAI_API_KEY——其中 shell export 压过 .env,而且只加载找到的第一个 .env 文件;最后才是已弃用的 security.auth.baseUrl 和 security.auth.apiKey。报 404 时先看 Qwen Code 打印的错误消息和它自己 logs/openai JSON 里的请求 URL(路径或模型 ID 导致的 404 在调用任何模型之前就被拒绝,控制台 → 日志里没有这条记录):openai auth type 在 base URL 后面拼 /chat/completions,所以 base URL 不带 /v1 就会得到 404 not_found,消息里要求 base URL 以 /v1 结尾;路径正确仍报 404,则指向模型 ID 或资源不存在,按 /models 核对 ID。报 401 说明到达网关的 Key 不是有效的 Router One Key:查 envKey 写的是哪个变量名——它填的是变量名而不是 Key 本身——再查是不是 shell export 或更早找到的 .env 文件提供了另一个值。打开 model.enableOpenAILogging 就能看到每次请求的实际 URL 和模型,报障时保留响应里的 request_id(只有到达模型的请求才能在控制台 → 日志里找到)。

Router One 的模型条目要不要把 wireApi 设为 responses?

只有模型详情页列出 POST /v1/responses 的 ID 才需要。从 Qwen Code 0.24.1 起,Responses API 改为在 openai provider 里按模型选择:wireApi 为 "chat-completions"(不写时的默认值)时,通过 OpenAI Node.js SDK 发送 Chat Completions,而 /v1/chat/completions 服务目录里的所有聊天模型,所以不写 wireApi 的条目适用于任意当前 ID。设为 "responses" 后,该模型改为不经 SDK、直接用 HTTP/SSE 调用 /v1/responses,目的是通过 reasoning.encrypted_content 在多轮之间回放推理,用 reasoning.effort 而不是 extra_body.enable_thinking 控制推理强度;它的管线会去掉 baseUrl 末尾的 /v1 再自行拼上 /v1/responses,所以 https://api.router.one/v1 和 https://api.router.one 会解析成同一个地址。网关只对目前列出的 GPT 系列、DeepSeek ID 与 Grok 对话模型原生提供 /v1/responses;Claude 系列 ID 发到这里会在调用任何模型之前收到 HTTP 400 invalid_request_error,消息为 model '<id>' must be called via /v1/messages or /v1/chat/completions;Gemini 的 ID 在这里同样不提供。同一个 ID 可以两种条目各配一条。0.23.3 引入的 modelProviders.openai-responses 旧写法仍能读取,但新配置应写成 openai 加 wireApi(按 Qwen Code 0.25.0 的模型提供商文档与源码,2026-10-09 核对)。

Qwen Code 能通过网关用哪些模型?

选用当前目录中同时支持 Qwen Code 所用端点和所需功能的模型。精确 ID、当前单价与能力以 /models 及模型详情为准;不要仅按 GPT、Claude 等系列名判断兼容性。客户端能列出模型,只说明它从自身配置或 GET /v1/models 读到了这个 ID,仍需验证实际调用。

能列出模型,但调用报 400 或 404,怎么办?

先记录实际请求路径和错误消息,再核对精确模型 ID。400 可能是参数、工具类型或模型与端点不匹配;404 可能是请求路径或资源不存在,不能直接判定模型下线。若错误提示 must be called via,按它指明的端点调整客户端 provider,或换用支持当前端点的模型。不要在所有工具里统一增删 /v1 或 /chat/completions。

中国大陆能直连吗?

能。网关在大陆可直连、无需 VPN,配置与全球环境完全一致。

报 401/402/403/429 怎么排查?

先看客户端收到的响应:状态码、错误消息和 X-Request-ID 响应头。401(Key 缺失、不存在、已吊销或已过期)、402(钱包余额不足,或这把 Key 达到 maxSpend 上限)以及 Key 或账户自身限额触发的 429,都在调用任何模型之前被拒绝,不会出现在控制台 → 日志里;模型 ID 或端点写错导致的 400 / 404 也一样。401 查 Key 是否完整传入、在控制台 → API 密钥里是否仍有效;402 充值或调高这把 Key 的 maxSpend;403 请保留完整错误消息。429 请退避后重试;日志里能查到的 429 是网关重试之后上游仍返回的。保留 request_id,再按错误码速查页逐项排查。