OpenCode Go 请求失败?NewAPI 中转配置 x-opencode-session 请求头教程
OpenCode Go 请求失败?NewAPI 中转配置 x-opencode-session 请求头教程
周末收到了 OpenCode 的邮件,提醒我,部分请求缺失 x-opencode-session 请求头,在 09/06 之后,如果缺失这个请求头,请求可能会失败。

发生了什么:OpenCode Go 的风控要求
简而言之就是 OpenCode 的风控要求,使用 Go 订阅的请求至少需要有:
X-Opencode-Session 与 user-agent 这两个请求头
user-agent:用来识别你用的是什么 agent 工具,根据他们飞书群内客服的说法:目前允许用户将 Go 订阅用于 opencode 之外的其他 agent 工具,也不阻止你用中转,但仅限常见的 agent 工具,禁止直接使用脚本调用,Zen 则没有这个限制(毕竟浪费的算力和 token 是你掏钱,OpenCode 反正不会亏)。-
X-Opencode-Session:OpenCode 靠这个标头做 GPU 上下文缓存。同一个对话的所有多轮请求,都带上同一个固定的 Session ID;而不同的对话之间,使用不同的 Session ID,这样可以将同一个对话的请求调度到同一个 GPU,直接复用上一轮已经生成的显存缓存,而不用做跨 GPU 复制 KV 缓存。(为了节省算力,省钱)是一个符合UUID(v4)格式,形如550e8400-e29b-41d4-a716-446655440000的32(36)位字符串。
怎么办:用 NewAPI 中转时构造符合要求的请求头
NewAPI 本身提供修改请求头的功能,我们的思路就是:
- 先抓包看看 agent 工具发过去的请求头是什么样的,找到 agent 工具等效于
X-Opencode-Session的请求头。(比如Session-Id、Session_id、X-Conversation-Id、X-Claude-Code-Session-Id) - 看看 OpenCode 那边要求什么请求头。
- 用请求头覆盖或者请求体修改等功能,将请求头改成要求的样子。
- 隐藏工具发出的可能存在风险的请求头,比如暴露真实 IP 的,用于用户追踪的。
第一步:用 webhook.site 抓包看你的请求头
可以用 webhook.site 抓包。访问网页后,复制网页上为你生成的唯一链接(比如 https://webhook.site/3a2b1d-a1b2-c3d4-d5e6-123456789),把 agent 工具对应模型的 Base URL 改成这个链接(记得换个假 KEY,不然真实 Key 会被抓包到),模型名随便填一个能发出去请求的就行,去工具里随便发一次请求,看看你的工具,正常的请求头会是什么样的。

以 Workbuddy 为例,可以看到工具本身就会发送 user-agent,所以这个好解决,但是 Workbuddy 是不可能发送 X-Opencode-Session 的,毕竟这是个 OpenCode 客户端专有的请求头。
不过仔细测试后发现,Workbuddy 会为每个对话发送 x-conversation-id 和 acp-connection-id 请求头,其中的 x-conversation-id 完美符合 x-opencode-session 的要求和格式:不同对话间不同,同一个对话中固定,断开网络或重启也不变,使用UUID V4格式(acp-connection-id 则属于标记连接的,网络环境变化或重启后会变化)。
方案一:使用「请求头覆盖」功能修改请求头
找到「渠道 – 编辑 – 请求头覆盖」填入如下 JSON
- 简单粗暴版(透传所有请求头 + 转换
x-conversation-id为X-Opencode-Session)
{
"*": true,
"X-Opencode-Session": "{client_header:x-conversation-id}"
}
- 只透传
User-Agent和X-Opencode-Session,屏蔽其他请求头
{
"User-Agent": "{client_header:user-agent}",
"X-Opencode-Session": "{client_header:x-conversation-id}"
}
- 更精细一点(尽可能透传没问题的请求头,隐藏可能有问题的)
正常的 agent 工具,请求头可能有十几个二十几个,如果只发关键的,其实也在暴露”你有个中间层在改请求头”这个事实。
所以先抓包看看你的 agent 工具到底发了什么请求,然后把 x-real-ip(真实 IP)、remote-host(主机名)、x-user-id(设备追踪标识)这种会暴露你实际位置和用户身份的参数给干掉。其他的都给透传了,这样更像真实的工具请求。具体怎么写你可以问你的 AI。
方案二:使用「参数覆盖」功能修改请求头
找到「渠道 – 编辑 – 参数覆盖」填入如下 JSON
{
"operations": [
{
"mode": "copy_header",
"keep_origin": true,
"from": "X-Opencode-Session",
"to": "X-Opencode-Session"
},
{
"mode": "copy_header",
"keep_origin": true,
"from": "Session-Id",
"to": "X-Opencode-Session"
},
{
"mode": "copy_header",
"keep_origin": true,
"from": "Session_id",
"to": "X-Opencode-Session"
},
{
"mode": "copy_header",
"keep_origin": true,
"from": "X-Conversation-Id",
"to": "X-Opencode-Session"
},
{
"mode": "copy_header",
"keep_origin": true,
"from": "X-Claude-Code-Session-Id",
"to": "X-Opencode-Session"
}
]
}
注意:参数覆盖无法修改 stream 参数,另外它本身只处理请求体/请求头的映射操作,和请求头覆盖不一样,按需选用。
总结
- 总而言之就是 OpenCode 要什么,我们就给他什么,没有就自己造一个,请求头能传的都传过去,不能传的坚决屏蔽掉。
- 不要直接写死
X-Opencode-Session的值,不然一旦有并行任务,在上游看来就是同一个人在交替请求完全不一样的任务,看起来像是多人共用,妥妥属于高风险特征。 - 配好之后如果还遇到 OpenCode Go 请求失败,先检查 NewAPI 实际转发出去的请求头,用
webhook.site再抓一次包对着看,缺什么补什么。 - 询问了 OpenCode 的客服,目前要求比较宽松,这两个请求头只执行了非空校验,但未来会严格要求格式。(就是目前只要有就行,值可以瞎写,但未来需要符合格式)
- 没事别在NewAPI里测速玩,测试会使用默认的 Go HTTP client 请求头。


Liudon
2026-09-08 15:21
我用的Hermes也收到这个通知了,我直接更新了下镜像
去年夏天
2026-09-08 15:49
是的,Hermes v0.21.0之后的版本已经解决这个问题了,如果中转了,直接透传所有请求头就解决了
obaby
2026-09-08 10:08
降本,一切都是为了降本
去年夏天
2026-09-08 15:47
降本增笑啊