这是《OpenCode v2 实战:从零搭建企业级 AI 编程助手》专题第 4 篇。前三篇完成了能力全景、Windows 安装路线以及 v1 到 v2 的迁移。本篇开始真正连接模型:不仅告诉你"密钥填在哪里",还把 Provider、模型、凭据、配置优先级、本地模型和企业网关之间的关系一次讲清楚。
很多人第一次配置 AI 编程工具,会把"接入模型"理解为把 API Key 粘贴进去。结果常见问题几乎都来自这个误区:Provider 已连接但模型不可用、模型 ID 猜错、项目之间凭据不继承、代理地址改了却仍请求官方端点,或者为了省事把真实密钥提交进 Git。
OpenCode v2 的正确心智模型可以概括为:
text
凭据(Credential)
↓
Provider(服务商、云平台、本地运行时或兼容网关)
↓
Model(具体模型及能力、上下文和变体)
↓
Session / Agent / Command(本次任务如何使用)
只有四层同时成立,模型才会真正出现在当前项目的可用列表中。
一、先分清 Provider、Model 与 Credential
OpenCode 使用 provider/model 标识模型,例如:
text
anthropic/claude-sonnet-4-5
openai/gpt-5.2
ollama/gemma3:4b
openrouter/anthropic/claude-sonnet-4.5
第一个 / 之前是 Provider ID,之后都是 Model ID;模型 ID 本身可以继续包含 /。模型变体放在最后的 # 后:
text
openai/gpt-5.2#high
三类对象的职责不同:
| 对象 | 负责什么 | 常见错误 |
|---|---|---|
| Provider | 请求发到哪里、用什么协议和凭据 | 只改模型名,忘了连接账号或配置端点 |
| Model | 实际调用哪个模型、能力和限制是什么 | 使用展示名代替模型 ID,或猜一个不存在的 ID |
| Credential | 证明你有权调用 Provider | 把真实 Key 写进项目配置并提交 Git |
官方目录来自 models.dev、内置 Provider 集成和项目配置。/models 只显示当前项目中已启用、且 Provider 可用的模型。因此"目录里存在"不等于"当前项目能用"。
二、最快接入:先 /connect,再 /models
对于 OpenCode 已内置的 Provider,优先走交互式连接,不必一开始就手写复杂 JSON。
text
/connect
选择 Provider 后,按界面要求完成登录或输入凭据。连接完成再执行:
text
/models
从列表里选择模型,而不是凭记忆猜 Provider ID 和 Model ID。这样能避开大小写、版本后缀以及模型下线带来的问题。
选择后只影响当前会话,不会自动改写 opencode.jsonc。这很适合临时比较模型:先用便宜快速的模型理解项目,再切到推理能力更强的模型完成关键修改。
如何判断连接真的成功
不要只看到"已保存凭据"就结束,至少验证三件事:
/models中能看到目标 Provider 下的模型;- 选中模型后能完成一次普通问答;
- 再完成一次需要工具调用的只读任务,例如列出项目文件。
有些兼容接口能聊天,却不支持 OpenCode 所需的工具调用。只测"你好"会得到假阳性。
三、设置默认模型与单次覆盖
希望新会话默认使用固定模型,可以在 opencode.jsonc 中配置:
jsonc
{
"$schema": "https://opencode.ai/config.json",
"model": "anthropic/claude-sonnet-4-5"
}
如果只想让一次命令使用特定模型,可以用:
powershell
opencode run --model anthropic/claude-sonnet-4-5 "检查当前改动是否缺少测试"
模型选择的优先关系可以理解为:
text
当前会话已选择模型
↓ 优先于
配置文件中的默认模型
↓ 不可用时
OpenCode 选择当前可用的较新支持模型
切换会话模型不会重写配置文件。配置中的默认模型只有在它已启用、且对应 Provider 在当前项目可用时才能生效。
模型变体不要写错位置
变体常用于推理强度或预算:
powershell
opencode run --model openai/gpt-5.2#high "评审这份数据库迁移方案"
low、high、max 并不是所有模型都支持。应以当前模型目录提供的变体为准。官方还特别说明,根级默认模型目前不会保留 #variant,所以需要固定变体时,应放在会话、单次 run、Agent 或 Command 中。
四、API Key 的三种配置方式
密钥配置的原则很简单:能交给连接流程就交给连接流程;需要声明式配置时,优先环境变量或独立文件;不要把真实值写入 Git 管理的 JSON。
方式一:使用 /connect
这是个人开发环境最省心的做法:
text
/connect
优点是配置少、能利用 Provider 的官方认证方式。缺点是自动化构建、服务器部署和团队统一配置时不够声明式。
方式二:引用环境变量
OpenCode v2 支持在 JSON 字符串中使用 {env:VARIABLE_NAME}:
jsonc
{
"$schema": "https://opencode.ai/config.json",
"providers": {
"anthropic": {
"settings": {
"apiKey": "{env:ANTHROPIC_API_KEY}"
}
}
}
}
PowerShell 当前会话可临时设置:
powershell
$env:ANTHROPIC_API_KEY = "请在本机输入真实密钥"
opencode
关闭终端后临时变量失效,适合测试。长期保存时应使用操作系统凭据方案、CI Secret 或企业密钥管理工具,不要把命令和真实值写进公开脚本。
若环境变量不存在,OpenCode 会将替换结果视为空字符串。遇到认证失败时,应先检查启动 OpenCode 的那个进程是否真的继承了变量,而不是反复更换模型。
方式三:引用独立文件
也可以用 {file:...} 读取文件内容:
jsonc
{
"$schema": "https://opencode.ai/config.json",
"providers": {
"openai": {
"settings": {
"apiKey": "{file:~/.secrets/openai-key}"
}
}
}
}
文件路径可相对配置文件、使用绝对路径,或以 ~/ 开头。这个方式适合由权限系统挂载 Secret 文件的服务器或容器。
| 方式 | 适用场景 | 主要注意点 |
|---|---|---|
/connect |
个人桌面、交互式使用 | 验证当前项目是否能看到 Provider |
{env:...} |
CI、服务器、团队统一启动脚本 | 确认变量传给了实际运行的服务进程 |
{file:...} |
容器挂载 Secret、受控本地密钥文件 | 收紧文件权限,不把文件纳入仓库 |
五、配置自定义 OpenAI 兼容 Provider
如果模型服务不在内置目录中,但提供 OpenAI 兼容接口,可以同时声明 Provider、端点、凭据来源和模型:
jsonc
{
"$schema": "https://opencode.ai/config.json",
"model": "acme/qwen3-coder",
"providers": {
"acme": {
"name": "Acme AI Gateway",
"env": ["ACME_API_KEY"],
"package": "@opencode/ai/providers/openai-compatible",
"settings": {
"baseURL": "https://llm.example.com/v1"
},
"models": {
"qwen3-coder": {
"name": "Qwen 3 Coder"
}
}
}
}
}
这里有四个容易混淆的字段:
acme是 OpenCode 内部使用的 Provider ID;env是可提供凭据的环境变量名列表;package决定运行时采用哪种协议实现;models的键是 OpenCode 中可选择的 Model ID。
最终引用是:
text
acme/qwen3-coder
如果上游真实模型名与希望展示的 ID 不同,用 modelID 做别名映射:
jsonc
{
"model": "acme/coding-default",
"providers": {
"acme": {
"package": "@opencode/ai/providers/openai-compatible",
"settings": {
"baseURL": "https://llm.example.com/v1",
"apiKey": "{env:ACME_API_KEY}"
},
"models": {
"coding-default": {
"modelID": "qwen3-coder-production",
"name": "团队编码模型"
}
}
}
}
}
acme/coding-default 是用户选择的名称,发送给上游的是 qwen3-coder-production。
六、通过代理或企业网关转发内置 Provider
如果企业要求所有请求经过统一网关,可以覆盖内置 Provider 的 baseURL:
jsonc
{
"$schema": "https://opencode.ai/config.json",
"providers": {
"anthropic": {
"settings": {
"baseURL": "https://llm-proxy.example.com/anthropic"
}
}
}
}
这样可以继续复用内置 Provider 的包、目录模型和连接信息,同时将请求发往代理。
但"OpenAI 兼容"不是完全等价。企业网关至少要验证:
- 流式输出是否正常;
- 工具调用格式是否完整;
- 多轮工具消息能否原样回传;
- 推理字段是否需要兼容映射;
- 上下文和最大输出限制是否准确;
- 429、401、超时和上游错误是否透明返回。
代理只实现 /chat/completions 的基础对话,并不意味着可以稳定驱动编码 Agent。
七、接入 Ollama、LM Studio 与 vLLM
OpenCode v2 会从默认地址自动发现 Ollama、LM Studio 和 vLLM 的模型。
Ollama
Ollama 默认监听 http://127.0.0.1:11434,发现后可直接选择:
jsonc
{
"$schema": "https://opencode.ai/config.json",
"model": "ollama/gemma3:4b"
}
非默认端口可配置 OpenAI 兼容 URL:
jsonc
{
"providers": {
"ollama": {
"settings": {
"baseURL": "http://127.0.0.1:5678/v1"
}
}
}
}
无认证时可以省略 apiKey;若服务器要求认证,则引用环境变量。
LM Studio
LM Studio 默认地址是 http://127.0.0.1:1234,模型引用形如:
text
lmstudio/google/gemma-4-26b-a4b
自定义地址示例:
jsonc
{
"providers": {
"lmstudio": {
"settings": {
"baseURL": "http://127.0.0.1:5678/v1",
"apiKey": "{env:LMSTUDIO_API_KEY}"
}
}
}
}
如果本地服务没有开启认证,删除 apiKey 字段即可。
vLLM
vLLM 默认监听 http://127.0.0.1:8000,引用示例:
text
vllm/Qwen/Qwen3-Coder-30B-A3B-Instruct
OpenCode 会检查 /health,并在后台刷新 /v1/models。自定义端点可写成:
jsonc
{
"providers": {
"vllm": {
"settings": {
"baseURL": "http://127.0.0.1:9000/v1",
"apiKey": "{env:VLLM_API_KEY}"
}
}
}
}
需要注意,vLLM 的模型发现不会自动证明工具调用能力。服务端通常还需要正确启用 tool choice 和对应解析器,再做真实工具调用验收。
八、模型能力与限制必须如实声明
对于不在目录中的自定义模型,OpenCode 会给出一组回退假设,但这不是能力探测结果。生产环境应按服务端真实规格声明:
jsonc
{
"$schema": "https://opencode.ai/config.json",
"model": "local/coder",
"providers": {
"local": {
"name": "Local server",
"package": "@opencode/ai/providers/openai-compatible",
"settings": {
"baseURL": "http://127.0.0.1:1234/v1"
},
"models": {
"coder": {
"modelID": "model-name-on-server",
"capabilities": {
"tools": true,
"input": ["text"],
"output": ["text"]
},
"limit": {
"context": 32768,
"output": 8192
}
}
}
}
}
}
上下文写大了,上游可能在长任务中突然拒绝请求;写小了,OpenCode 会过早压缩上下文。tools: true 也不应凭空填写,必须用真实的文件读取或 Shell 工具调用验证。
九、如何按任务选择模型
模型选择不应该只有"最强"和"最便宜"两个档位。编码 Agent 的实际效果还取决于工具调用稳定性、长上下文、延迟、输出上限和错误恢复。
| 任务 | 优先关注 | 适合策略 |
|---|---|---|
| 仓库浏览、简单问答 | 延迟和成本 | 快速模型作为默认 |
| 小范围代码修改 | 工具调用、指令遵循 | 中档编码模型 |
| 架构设计、复杂排障 | 推理、长上下文 | 高能力模型或高推理变体 |
| 批量机械改动 | 稳定性、吞吐、价格 | 先缩小范围,再用经济模型 |
| 敏感代码、本地数据 | 数据边界、部署方式 | 企业网关或本地模型 |
一个实用的分层配置是:默认模型处理大多数任务,专用 Agent 绑定更强模型做评审,命令级模型完成固定流程。
jsonc
{
"$schema": "https://opencode.ai/config.json",
"model": "openai/gpt-5.2",
"agents": {
"architecture-reviewer": {
"description": "审查架构、风险和遗漏的测试",
"mode": "subagent",
"model": "openai/gpt-5.2#high"
}
}
}
这样不用让每个普通任务都承担最高推理成本。
十、团队与企业环境的安全基线
个人能跑通不等于团队可管理。进入企业环境后,建议建立以下基线:
- 项目仓库只保存 Provider ID、模型 ID、端点占位和变量引用;
- Key 由环境变量、Secret 文件、CI Secret 或密钥系统注入;
- 不在聊天记录、日志、截图和故障单中粘贴完整 Key;
- 为开发、测试、生产使用不同凭据并设置额度;
- 企业代理记录请求元数据时,应明确代码和提示词的留存策略;
- 定期轮换凭据,人员离职或设备丢失时立即吊销;
- 通过系统级策略限制未经批准的 Provider。
系统级配置可以定义允许使用的 Provider:
jsonc
{
"policies": [
{
"action": "provider.use",
"resource": "*",
"effect": "deny"
},
{
"action": "provider.use",
"resource": "anthropic",
"effect": "allow"
}
]
}
策略是否满足组织要求,应结合配置优先级和实际部署验证。仅在项目文件写一条约定,无法阻止用户在更高权限环境中添加其他 Provider。
十一、常见报错的排查顺序
1. /models 看不到目标模型
按以下顺序检查:
text
Provider 是否已连接
→ 当前项目是否加载了正确配置
→ 模型是否被禁用
→ Provider 是否被策略禁止
→ 模型 ID 是否来自当前目录
凭据和配置具有项目或位置范围,一个项目能用,不代表另一个目录自动可用。
2. 401 或认证失败
重点不是更换模型,而是确认凭据链:
powershell
# 只检查变量是否存在,不输出真实内容
if ($env:ACME_API_KEY) { "ACME_API_KEY is set" } else { "ACME_API_KEY is missing" }
若 OpenCode 通过后台服务运行,变量必须设置在服务进程环境中。当前 PowerShell 有值,不代表已经启动的后台进程也有值。
3. 404 或 Model Not Found
分别核对:
baseURL是否已经包含正确的/v1前缀;- OpenCode 中的模型键与上游
modelID是否区分清楚; - Provider ID、Model ID 大小写是否一致;
- 网关是否对该账号开放目标模型。
4. 能对话但不会调用工具
这通常是兼容层问题。检查模型本身、服务端启动参数、流式工具调用格式和多轮消息回传。不要通过把 capabilities.tools 强行设为 true 掩盖问题。
5. 配置改了但没有生效
OpenCode 通常会自动重新加载配置,但进行中的模型请求会继续使用启动时的设置。还要检查配置层级:系统、全局、项目根目录和 .opencode/ 中可能存在覆盖关系。
十二、一套可复制的验收清单
完成 Provider 配置后,不要只做一次聊天。建议按下面的清单验收:
text
[ ] /models 能看到目标模型
[ ] 新会话默认模型符合配置
[ ] --model 能完成单次覆盖
[ ] 普通文本问答正常
[ ] 文件读取工具正常
[ ] Shell 只读命令正常
[ ] 多轮工具调用没有丢失上下文
[ ] 401、429、超时能返回可诊断错误
[ ] 配置文件不包含真实 API Key
[ ] Git 历史中不存在已泄露密钥
[ ] 团队成员在各自凭据下可以复现
如果真实 Key 曾经提交到 Git,仅从最新版本删除是不够的。应立即吊销并轮换,再按组织流程处理历史记录。
十三、完整示例:个人开发与企业网关分离
项目仓库保存不敏感配置:
jsonc
{
"$schema": "https://opencode.ai/config.json",
"model": "team/coder",
"providers": {
"team": {
"name": "Team AI Gateway",
"package": "@opencode/ai/providers/openai-compatible",
"settings": {
"baseURL": "{env:TEAM_LLM_BASE_URL}",
"apiKey": "{env:TEAM_LLM_API_KEY}"
},
"models": {
"coder": {
"modelID": "coding-model-production",
"capabilities": {
"tools": true,
"input": ["text", "image"],
"output": ["text"]
},
"limit": {
"context": 131072,
"output": 16384
}
}
}
}
}
}
每位开发者或 CI 环境分别注入:
powershell
$env:TEAM_LLM_BASE_URL = "https://llm-gateway.example.com/v1"
$env:TEAM_LLM_API_KEY = "由密钥系统注入的值"
opencode
仓库统一模型别名和能力声明,凭据留在个人或部署环境,既方便复现,也避免共享密钥。
十四、总结
给 OpenCode v2 接入模型,最稳妥的顺序不是"先找一个 Key 粘进去",而是:
text
确定数据与合规边界
→ 选择 Provider
→ 用 /connect 或安全变量提供凭据
→ 用 /models 选择真实可用模型
→ 配置默认模型或任务级变体
→ 验证聊天、工具调用和错误恢复
→ 再固化为团队配置与策略
记住三个关键结论:
- Provider 决定连接方式,Model 决定实际能力,Credential 决定是否有权调用;
- 配置中只保存变量引用或 Secret 文件引用,不保存真实 API Key;
- "能聊天"不是编码 Agent 的验收标准,工具调用和多轮稳定性同样重要。
下一篇将继续专题第 5 篇:对比 OpenCode v2 的 CLI、Desktop 与 Web 三种形态,说明它们各自适合什么工作流,以及团队应该如何组合使用。