OpenCode 接入自定义 OpenAI 兼容 API:Provider 配置、模型限制与网关回退

OpenCode 自定义 Provider 配置教程:区分 Chat Completions 与 Responses API,设置 baseURL、模型上下文、网关路由、凭据和故障排查。

OpenCode 同时出现在 “AI coding”“vibe coding”“open source AI” 与 “coding agent” 的上升查询中。

最常见的接入错误不是 API key,而是协议、provider ID 和模型名没有对齐。

先确认上游使用哪种协议

/v1/chat/completions 通常使用 @ai-sdk/openai-compatible

/v1/responses 使用 @ai-sdk/openai

“OpenAI 兼容”不代表两个端点都实现。

先用上游文档和最小 curl 请求确认。

1
2
curl -sS https://gateway.example.com/v1/models \
  -H "Authorization: Bearer $API_KEY"

不要把 key 直接写进 shell history。

凭据与配置分开

在 OpenCode 运行 /connect,选择 Other

输入唯一 provider ID,例如 corp-gateway

这个 ID 必须与 opencode.json 完全一致。

只执行 /connect 只会存凭据,不会自动生成完整 provider 配置。

一个最小配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "corp-gateway": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Corporate Gateway",
      "options": {
        "baseURL": "https://gateway.example.com/v1"
      },
      "models": {
        "coding-model": {
          "name": "Coding Model"
        }
      }
    }
  }
}

模型键必须是网关实际接受的 model ID。

显示名称可以自定义,但不能代替真实 ID。

给未知模型补上下文限制

1
2
3
4
"limit": {
  "context": 200000,
  "output": 32768
}

OpenCode 用这些值估算剩余上下文。

不要把供应商宣传的总 token 直接同时填到 input 和 output。

输出上限过大可能导致请求被上游拒绝。

自定义 Header 的边界

租户或网关路由可能要求额外 Header。

静态非敏感值可以放配置。

密钥应引用环境变量。

不要把用户身份 Header 交给 Agent 自由修改。

网关应从可信认证信息派生租户,而不是相信客户端自报。

Vercel AI Gateway 路由

官方示例支持 orderonlyzeroDataRetention 等选项。

order 表示供应商尝试顺序。

only 限制可用供应商。

zeroDataRetention 用于筛选符合数据保留要求的路由。

回退不能只看 HTTP 状态码。

认证失败、余额不足和内容策略拒绝通常不应盲目换供应商重试。

用三个请求验收

先发送纯文本问答。

再发送需要工具调用的任务。

最后发送接近上下文上限的长输入。

记录模型名、请求 ID、首 token 延迟和总 token。

如果网关重写模型名,日志中要同时保留请求值与实际路由值。

常见错误

401:凭据未保存、环境变量没进入当前进程或 Header 名不对。

404:baseURL 多写或少写 /v1,也可能选错协议。

400 unknown model:配置键与上游 model ID 不一致。

工具不工作:上游只兼容文本格式,没有完整实现 tool calls。

上下文提前溢出:limit.context 与真实模型不符。

排查命令

1
opencode auth list

确认凭据条目存在,但不要打印实际 key。

然后用 /models 检查模型是否出现。

同一请求直接调用网关与通过 OpenCode 各执行一次。

直接请求成功、OpenCode 失败,重点检查配置与 SDK 协议。

两边都失败,优先检查网关和账号。

多环境配置

开发、测试和生产网关使用不同 provider ID。

例如 corp-devcorp-prod

生产 ID 默认不出现在个人开发配置里。

CI 使用短期凭据,不复用开发者本地 token。

切换环境后先运行只读任务,确认没有误连生产。

安全与成本控制

在网关侧设置每个 key 的预算和速率。

按 provider、模型、仓库和用户记录费用。

日志脱敏 Authorization 与提示中的凭据。

限制 Agent 能访问的文件和命令。

API 路由成功不代表本地工具执行安全。

验收清单

  • 确认 Chat Completions 或 Responses 协议。

  • /connect ID 与配置完全一致。

  • baseURL 只包含一次 /v1

  • 模型 ID 与网关一致。

  • context/output 限制来自真实文档。

  • 回退策略区分可重试和不可重试错误。

  • 凭据不在 JSON 与 Git 中。

  • 三类请求均保存请求 ID 和真实路由。

Provider 配置文档

先用独立脚本验证网关协议

在接入 OpenCode 前,用最小请求确认网关的认证、模型名和响应格式。下面是 Chat Completions 端点示意:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$headers = @{
  Authorization = "Bearer $env:AI_GATEWAY_KEY"
  "Content-Type" = "application/json"
}
$body = @{
  model = "coding-model"
  messages = @(
    @{ role = "user"; content = "Reply with OK" }
  )
  max_tokens = 16
} | ConvertTo-Json -Depth 5
Invoke-RestMethod `
  -Uri "https://gateway.example.com/v1/chat/completions" `
  -Method Post `
  -Headers $headers `
  -Body $body

如果这个请求失败,先解决网关问题。它成功而 OpenCode 失败,才检查 provider 配置和 AI SDK 包。

Responses API 不能只替换 URL

Responses API 的输入、工具定义和流式事件与 Chat Completions 不完全相同。上游只提供 /v1/responses 时,把 provider 的 npm 包换成 @ai-sdk/openai,同时核对网关是否透传该协议。

不要在反向代理中把两个请求体直接转发到同一处理器。看似简单的文本请求可能成功,工具调用和多模态请求却会在运行中损坏。

用环境变量引用 API key

项目配置提交到 Git 前,搜索是否包含真实凭据:

1
git grep -n -E "sk-[A-Za-z0-9]|Bearer [A-Za-z0-9]"

本地环境变量名称要体现用途,例如 CORP_GATEWAY_KEY,不要复用含义模糊的 API_KEY。CI、个人电脑和 VPS 分别使用不同 key。

校验流式输出

普通响应成功后,再测试较长回答和工具调用。检查首个事件、增量文本、结束原因和最终 usage 是否齐全。

代理服务器需要关闭不必要的响应缓冲,并把读取超时设置得比模型任务时限长。否则 OpenCode 会在模型仍运行时显示连接中断。

上下文上限写错会出现什么

配置值高于真实上限时,OpenCode 以为还有空间,上游却返回上下文过长。配置值过低时,客户端过早压缩或丢弃有用内容。

用固定 token 样本逐级增加输入,记录网关实际拒绝点。还要扣除系统提示、工具定义和预留输出,而不是只计算用户文件。

模型别名需要版本治理

网关常把 coding-model 指向不断更新的后端。这样方便切换,却会让同一个配置产生不同结果。

生产工作流使用带版本的别名,例如 coding-model-2026-07。升级时建立新别名,在测试仓库跑完回归后再切默认路由。

回退时保持能力兼容

主模型支持工具调用和长上下文,回退模型也必须满足任务最低能力。如果回退模型只支持文本,就应该明确失败,不能把工具 JSON 当普通文字返回给 Agent。

为每条路由记录 supports_toolssupports_vision、context、output 和数据保留策略。选择回退时按能力过滤,再按顺序尝试。

代理日志的脱敏规则

保留请求 ID、租户、模型、状态码、token 和耗时。删除 Authorization,提示正文默认不入集中日志。

调试时若必须采样正文,使用专门测试账号、短保留期和受限存储。结束排错后关闭采样,并删除临时数据。

关闭连接与重试策略

连接超时可以有限重试;认证失败、参数错误和内容策略拒绝不重试。429 根据 Retry-After 与预算决定是否等待。

写工具已经执行而模型响应中断时,不重新运行整个任务。先恢复 interaction 或检查工作树,避免重复修改。

配置变更后的五分钟冒烟测试

依次运行 /models、短文本问答、只读文件任务和一个需要工具调用的小任务。确认界面显示的模型与网关日志中的实际模型一致。

随后故意输入一个不存在的模型名。系统应返回明确的配置错误,而不是悄悄路由到昂贵的默认模型。

最后打开新的终端重新测试,排除当前会话临时环境变量造成的假成功。测试结果与配置 diff 一起保存,便于回滚。

如果冒烟测试失败,恢复上一份 opencode.json 和锁定的模型别名,不在故障状态下继续叠加配置修改。