OpenCode Policies 策略系统完全指南:精细化控制 LLM 提供商访问权限

OpenCode Policies 策略系统完全指南:精细化控制 LLM 提供商访问权限

引言

在使用 AI 编程助手时,控制"用哪个模型、不许用哪个模型"是一个高频需求。也许你想限制团队只使用公司采购的 Anthropic 账号,避免有人误用会产生额外费用的 OpenAI;也许你在个人项目中不想看到某个特定提供商的选项。OpenCode 的 Policies 策略系统正是为此而生——它提供了一套声明式规则引擎,让你能够精细化地控制 LLM 提供商的访问权限。

本文将深入讲解 Policies 系统的配置方式、规则语法、匹配机制和最佳实践,帮助你在多项目开发中建立清晰的模型使用边界。

Policies 与 Permissions:两个完全不同的系统

在开始之前,有必要澄清一个概念上的区分。OpenCode 有两个独立的安全控制体系:

| 系统 | 控制对象 | 典型场景 |
|------|---------|---------|
| Permissions(权限) | 工具调用行为 | 是否允许执行 Bash、读写文件、网络请求等 |
| Policies(策略) | 资源访问资格 | 是否允许使用某个 LLM 提供商(如 openaianthropic) |

打个比方:Permissions 控制的是"AI 能做什么动作"(能不能改代码、能不能上网),而 Policies 控制的是"AI 能用谁的大脑"(能接哪些模型提供商)。两者各司其职,互不干扰。

Policies 系统目前处于实验阶段,配置在 opencode.jsonexperimental.policies 字段中:

{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "openai"
      }
    ]
  }
}

一旦某个提供商被 deny,它将直接从模型选择列表中消失——即使你配置了正确的 API Key,也无法使用它。

策略规则的三要素

每条策略规则由三个字段构成:

1. effect:允许还是拒绝

取值为 "allow""deny",表示这条规则的效果是放行还是拦截。

2. action:控制什么操作

目前唯一支持的动作为 "provider.use",即控制 LLM 提供商的使用权。未来可能会扩展更多动作类型,用于控制其他资源类操作。

3. resource:作用的目标

目标资源的标识符,比如 "openai""anthropic""google" 等。这个字段支持 通配符匹配,让你可以用简洁的规则覆盖一批提供商。

通配符匹配:灵活覆盖多提供商

Policies 的 resource 字段支持两种通配符:

  • * —— 匹配零个或多个字符
  • ? —— 匹配恰好一个字符

这个设计让你能灵活地批量控制提供商。假设你的公司内部搭建了多套自托管模型,提供商 ID 分别是 company-uscompany-eucompany-apac,你想只开放这些内部提供商:

{
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "*"
      },
      {
        "effect": "allow",
        "action": "provider.use",
        "resource": "company-*"
      }
    ]
  }
}

第一条规则 "*" 拒绝了所有提供商,第二条规则 "company-*" 放行了所有以 company- 开头的内部提供商。这种"先全部拒绝,再逐个放行"的模式是实现白名单最常用的方式。

如果你的环境中有 model-v1model-v2model-v3 等多个版本标识的提供商,可以用单字符通配符精确匹配:

{
  "effect": "deny",
  "action": "provider.use",
  "resource": "model-v?"
}

这条规则会精确拒绝 model-v1model-v9,但不会影响 model-v10v10 是两个字符)。

规则优先级:最后匹配者胜出

Policies 系统采用"最后匹配者胜出"(last-match-wins)的规则排序策略。规则按照数组中的顺序从上到下评估,当多条规则匹配到同一个资源时,以最后一条匹配的规则为准。

理解这个机制至关重要,因为它决定了你应该如何组织规则顺序。来看一个实际案例——只允许使用 Anthropic,禁止其他所有提供商:

{
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "*"
      },
      {
        "effect": "allow",
        "action": "provider.use",
        "resource": "anthropic"
      }
    ]
  }
}

评估过程如下:

引擎按顺序读第一条规则 deny *,匹配 anthropic——暂记为拒绝。

读到第二条规则 allow anthropic,也匹配 anthropic——因为是最后一条匹配的,所以覆盖前面的结果,最终结果为允许。

如果把顺序反过来,先 allow anthropicdeny *anthropic 会被拒绝。核心原则:把大范围的通用规则放前面,小范围的例外规则放后面。

同样,如果某个提供商没有匹配到任何规则,则默认允许使用。Policies 是一个"默认开放,按需收紧"的系统。

全局策略与项目策略的层级关系

你可以在两个层级配置 Policies:

全局配置(用户级 opencode.json)——作用于所有项目

项目配置(项目根目录的 opencode.json)——仅作用于当前项目

当两个层级的策略同时匹配到同一个提供商时,全局策略的优先级高于项目策略。这是一个重要的安全设计:它防止某个项目仓库通过自己的配置文件绕过你在全局层面设定的限制。

举个例子,你在全局配置中禁止了 openai

// 全局 ~/.config/opencode/opencode.json
{
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "openai"
      }
    ]
  }
}

即使某个项目的 opencode.json 里写了 allow openai,全局的 deny 规则也会覆盖它。这个设计确保了安全策略的自上而下不可绕行。

替代旧版配置项

如果你之前一直使用旧版的 disabled_providersenabled_providers 来控制提供商,Policies 系统提供了对应的迁移路径。

替代 disabled_providers——直接对每个需要禁用的提供商写一条 deny 规则:

{
  "experimental": {
    "policies": [
      { "effect": "deny", "action": "provider.use", "resource": "openai" },
      { "effect": "deny", "action": "provider.use", "resource": "google" }
    ]
  }
}

替代 enabled_providers——先拒绝所有,再放行指定提供商:

{
  "experimental": {
    "policies": [
      { "effect": "deny", "action": "provider.use", "resource": "*" },
      { "effect": "allow", "action": "provider.use", "resource": "anthropic" },
      { "effect": "allow", "action": "provider.use", "resource": "openai" }
    ]
  }
}

建议新项目直接使用 Policies 系统,旧版配置项可能会在后续版本中逐步废弃。

实战场景

场景一:个人开发环境,限制成本

你想在日常开发中只用 Claude(Anthropic),偶尔在大型重构任务时手动切换 GPT-5(OpenAI),但不想让 AI 自己决定切换到其他模型,产生意外费用。可以这样配置:

{
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "*"
      },
      {
        "effect": "allow",
        "action": "provider.use",
        "resource": "anthropic"
      },
      {
        "effect": "allow",
        "action": "provider.use",
        "resource": "openai"
      }
    ]
  }
}

你自己手动切换时可以使用任何允许的提供商,但 AI 在选择工具时只能从这两个中挑选。

场景二:团队统一管理,只放行企业采购的提供商

公司统一采购了 Azure OpenAI 服务,部署为名为 azure-enterprise 的提供商。在团队共享的项目配置中:

{
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "*"
      },
      {
        "effect": "allow",
        "action": "provider.use",
        "resource": "azure-enterprise"
      }
    ]
  }
}

所有开发者 clone 项目后自动受此策略约束,确保不会有人无意中使用个人付费账号。

场景三:分环境管理

开发环境(dev)中允许使用任何提供商,生产 CI/CD 环境(通过 --config 指定配置)只允许使用专门的 CI 模型提供商:

// opencode.ci.json
{
  "experimental": {
    "policies": [
      {
        "effect": "deny",
        "action": "provider.use",
        "resource": "*"
      },
      {
        "effect": "allow",
        "action": "provider.use",
        "resource": "ci-model-prod"
      }
    ]
  }
}

通过 opencode --config opencode.ci.json 加载 CI 专用配置,实现环境隔离。

总结

OpenCode 的 Policies 策略系统虽然目前还是实验性功能,但其设计思路已经相当成熟。它用简洁的声明式规则语法,让你能够以直观、可预测、不可绕行的方式控制 LLM 提供商的使用资格。

回顾几个关键要点:

  • Policies ≠ Permissions:前者控制模型提供商的"准入",后者控制工具的"行为范围"。
  • 最后匹配者胜出:利用这个机制先写通用规则再写例外规则。
  • 全局策略优先于项目策略:这保证了安全基线的不可绕行。
  • 通配符让规则编写更简洁*? 覆盖大部分匹配场景。

相比旧版的 disabled_providersenabled_providers,Policies 系统更加灵活且具有扩展性。未来随着更多 action 类型的加入,这套规则引擎的适用场景会更加广泛。现在就把它配置起来,让你的 AI 编程环境更加可控。