首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >让 new-api 智谱 Coding Plan 跑通 /v1/responses:一场由 model_access_denied 引发的连环踩坑

让 new-api 智谱 Coding Plan 跑通 /v1/responses:一场由 model_access_denied 引发的连环踩坑

原创
作者头像
高老师
发布2026-08-17 14:33:26
发布2026-08-17 14:33:26
70
举报

让 new-api 智谱 Coding Plan 跑通 /v1/responses:一场由 model_access_denied 引发的连环踩坑

环境:new-api v1.0.0-rc.24 / 智谱 GLM Coding Plan / 2026-08

背景

公司最近在推广 Codex。之前我用 new-api 搭了一套 token 中心给团队用,只开了 chat 和 Claude 两种协议——那是 Claude Code 专用的年代,大家拿着令牌走 /v1/messages,岁月静好。

现在要接 Codex,就得让网关支持 OpenAI Responses 协议(/v1/responses)。上游是智谱 GLM Coding Plan,官网上明晃晃写着它支持三种接入方式:

协议类型

Base URL

Anthropic Message 协议

/api/anthropic

OpenAI Chat Completion 协议

/api/coding/paas/v4

OpenAI Response 协议

/api/v1

看起来是个半小时的活儿。实际折腾了一圈,踩了三个坑,其中一个坑的成因可以说是相当搞笑。记录下来,方便后来人。

第一坑:ZhipuV4 渠道类型,压根不支持 Responses

按直觉,智谱的渠道应该选「ZhipuV4」类型吧?加渠道、填 Key、保存,然后让同事请求 /v1/responses——直接报错。

翻源码发现,ZhipuV4 渠道适配器的 Responses 转换函数是个摆设(relay/channel/zhipu_4v/adaptor.go:104):

代码语言:go
复制
func (a *Adaptor) ConvertOpenAIResponsesRequest(...) (any, error) {
    // TODO implement me
    return nil, errors.New("not implemented")
}

它只会把请求往 /api/paas/v4/chat/completions 上发。也就是说,渠道类型选 ZhipuV4,Responses 协议必挂,没有降级转换。

正确姿势:OpenAI 类型 + 不带 /v1 的 Base URL

改用 OpenAI 类型的渠道。它的 URL 拼接规则是「渠道 Base URL + 客户端原始请求路径」的纯字符串拼接(relay/common/relay_utils.go:27),请求体原生透传,流式/非流式响应都有专门的 handler。

所以 Base URL 这样填(注意不要带 /v1,它会自己拼):

代码语言:bash
复制
类型:    OpenAI
Base URL: https://open.bigmodel.cn/api
密钥:    你的 Coding Plan Key

拼出来的效果:

代码语言:bash
复制
https://open.bigmodel.cn/api  +  /v1/responses
= https://open.bigmodel.cn/api/v1/responses   ← 正好是 Coding Plan 的 Responses 端点

配置完,先点个「测试」按钮验证一下——好戏开场了。

第二坑:测试按钮给了我一个 403,而且是假阴性

点下测试按钮,返回:

代码语言:bash
复制
bad response status code 403, message: No permission to access model: glm-5.2,
body: {"error":{"code":"model_access_denied","message":"No permission to access model: glm-5.2","type":"model_access_denied"}}

model_access_denied?没权限?我拿着同一把 Key 直接 curl 官方端点:

代码语言:bash
复制
curl https://open.bigmodel.cn/api/v1/responses \
  -H "Authorization: Bearer <你的CodingPlanKey>" \
  -H "Content-Type: application/json" \
  -d '{"model":"glm-5.2","input":"hi","max_output_tokens":16}'

# HTTP 200,正常出字

同一把 Key、同一个模型、同一个端点,curl 是 200,网关测试是 403。 这时候人已经开始怀疑人生了。

鉴别过程

用这把 Key 把各种可能的端点全打了一遍:

端点

结果

/api/v1/responses + glm-5.2

✅ 200

/api/coding/paas/v4/chat/completions + glm-5.2

✅ 200

/api/paas/v4/chat/completions(按量端点)

429 余额不足(错误格式是数字 code)

/api/v1/chat/completions + glm-5.2

403 model_access_denied,一字不差

最后一行就是元凶。而智谱 Coding Plan 的 /api/v1 这个 Base,只开放 Responses 协议——chat completions 打过去就是这个 403。

真相:测试按钮看的是模型名,不是渠道名

那网关为什么去打 /api/v1/chat/completions?读 controller/channel-test.go,真相令人捧腹:

代码语言:go
复制
// controller/channel-test.go:116
requestPath := "/v1/chat/completions"   // 测试按钮默认按 chat 协议测

// controller/channel-test.go:145
// responses-only models
if strings.Contains(strings.ToLower(testModel), "codex") {
    requestPath = "/v1/responses"       // 模型名里含 "codex" 才改测 Responses
}

渠道测试按钮默认按 chat completions 协议测试;只有当"测试模型名"里包含 codex 字样时,才切换成 /v1/responses

我当时把渠道命名为「测试codex」——没用,它查的是模型的身份证,不看渠道的户口本。测试模型是 glm-5.2,于是老老实实走了 chat 协议,一头撞上"该端点不开放"的 403。

也就是说:渠道配置从头到尾都是对的,这个 403 是个假阴性——测试按钮用错了协议去测一个只支持另一种协议的端点。

顺带一提:渠道测试不写 relay 日志,所以数据库 logs 表里这个渠道一条记录都没有,这也一度干扰了排查方向。

第三坑:不点测试、让同事直接请求,流量根本不往我这走

明白了测试按钮的坑之后,把模型名改成带 codex 的,测试立刻通过。但这里必须澄清一个容易误解的点(我自己也一度搞混):

模型名带不带 codex,只影响"测试按钮"用哪个协议测;真实流量的协议由请求路径决定——客户端请求 /v1/responses,网关就按 Responses 协议处理,跟模型名没有任何关系。

真实流量的问题在别处:new-api 选渠道只看「分组 + 模型名 + 优先级」,与请求协议无关(model/channel_cache.go)。而我们这套 token 中心里已经有一堆 Claude 时代的 Anthropic 类型渠道,模型列表里都有 glm-5.x,优先级 100;新渠道优先级 0。于是:

代码语言:bash
复制
同事请求 /v1/responses (model: glm-5.2)
  → 在优先级 100 的池子里随机挑一个 Anthropic 渠道
  → Responses 请求被"好心"地转成 Claude 格式
  → 发到 /api/anthropic/v1/messages,用的是那个渠道里别人的 Key
  → 碰到没权限的 Key → 403 model_access_denied

同一个报错,两个完全不同的成因——这也是这次排查最迷惑的地方。日志表里 glm-5.2 的流量均匀分布在十几个渠道上,而新渠道是 0 条,坐实了"流量根本没来过我这"。

最终配置

一步到位的方案:给 Responses 专用渠道起独占的模型名,并且名字里带 codex。一举两得——路由独占,测试按钮也自动走 Responses 协议。

配置项

渠道类型

OpenAI

Base URL

https://open.bigmodel.cn/api

密钥

Coding Plan 的 API Key

模型

glm-5.2-codex,glm-5.3-codex(独占名,其他渠道都没有)

模型重定向

{"glm-5.2-codex": "glm-5.2", "glm-5.3-codex": "glm-5.3"}

状态

启用

再在「运营设置 → 模型固定价格/倍率」里给这两个新名字配上与 glm-5.2/glm-5.3 相同的价格——计费按客户端请求的模型名查价,不配会报价格未配置。

调用方这样用:

代码语言:bash
复制
curl https://你的网关地址/v1/responses \
  -H "Authorization: Bearer sk-你的newapi令牌" \
  -H "Content-Type: application/json" \
  -d '{"model":"glm-5.2-codex","input":"hi"}'

原有的 chat / Claude 协议渠道完全不受影响,Claude Code 的团队继续用 /v1/messages + glm-5.2,互不干扰。

如果不想改模型名,也可以用独立分组方案:新建一个分组(如 responses),把新渠道归进去,给 Codex 用户发该分组的令牌——令牌分组同样能实现确定性路由,只是测试按钮依旧是假阴性。

千万不要图省事把新渠道优先级调到全场最高:那会把所有 glm-5.2 流量(包括团队的 Claude 流量)都抢过来,转成 OpenAI 格式打到一个不开放的端点上,而且全部消耗你这一个 Key 的配额。

总结:三个反直觉的事实

  1. ZhipuV4 渠道类型不支持 /v1/responses, Responses 协议要用 OpenAI 类型渠道 + Base URL https://open.bigmodel.cn/api 实现。
  2. 渠道测试按钮默认测 chat completions 协议,测试模型名含 codex 才测 Responses——在只开放 Responses 的端点上,测试报 403 model_access_denied 恰恰说明渠道配对了,别被假阴性骗了。
  3. 渠道路由与请求协议无关,只看分组 + 模型名 + 优先级。同一个模型名出现在多个渠道时,Responses 请求会被转成别的协议、用别的 Key 发出去。想确定性路由,要么独占模型名,要么独立分组。

以及一条隐性经验:报错是上游给的,不代表流量走的是你以为的那条路。先查日志里这条请求到底用了哪个渠道,再谈别的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 让 new-api 智谱 Coding Plan 跑通 /v1/responses:一场由 model_access_denied 引发的连环踩坑
    • 背景
    • 第一坑:ZhipuV4 渠道类型,压根不支持 Responses
      • 正确姿势:OpenAI 类型 + 不带 /v1 的 Base URL
    • 第二坑:测试按钮给了我一个 403,而且是假阴性
      • 鉴别过程
      • 真相:测试按钮看的是模型名,不是渠道名
    • 第三坑:不点测试、让同事直接请求,流量根本不往我这走
    • 最终配置
    • 总结:三个反直觉的事实
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档