Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

插件的工作原理

本页从运维者的角度解释插件系统:如何发现插件、插件被允许执行什么操作,以及宿主如何将不受信任的插件限制在可控范围内。关于插件作者实现的磁盘协议约定(清单字段、bridge 导出、宿主函数),请参见 Plugin protocol

系统的形态

插件是一个沙盒化的 WebAssembly 模块加上一个清单。宿主会加载它,读取它声明的能力和权限,并且只有在操作员打开插件系统时,才将其工具暴露给代理。插件中的任何内容都不是隐式的:插件获得的能力仅限于其清单所声明且操作员策略允许的那些,除此之外没有别的。要自己构建一个,请从 plugin guides 开始。

每一层都满足三个属性:

  • 默认禁用。 插件系统不会加载任何内容,除非 [plugins] enabled = true。没有插件配置的默认构建不会运行任何插件代码。
  • 默认拒绝。 插件只有在其清单中声明了匹配的权限,才能访问宿主能力(HTTP 出站、配置、内存)。未声明的能力不可达,而不仅仅是未使用。
  • 已由策略验证。 未签名或不受信任的插件是否允许加载完全由操作员决定,在配置中一次性设置,并在发现时统一强制执行。

插件加载的生命周期

当运行时构建其工具集时,插件加载器会按顺序经历以下阶段。未通过前一阶段的插件不会进入后一阶段。

  1. 门控。 如果 [plugins] enabled 为 false,加载器不会执行任何操作。这是第一道也是最便宜的检查。
  2. 发现。 加载器会扫描已解析的插件目录([plugins] plugins_dir,默认 ~/.zeroclaw/plugins/)中的包含 manifest.toml 的子目录。
  3. 验证形状。 每个 manifest 必须声明至少一个 capability,且非 skill 插件必须指定一个存在的 wasm_path。格式错误的 manifest 会被跳过并发出警告,绝不会被加载。
  4. 强制执行签名策略。 每个插件都会根据已配置的 [plugins.security] signature_modetrusted_publisher_keys 进行检查。未通过该策略的插件会从已加载集合中移除,不会作为工具展示。
  5. 注册工具。 保留下来的工具插件会封装为代理工具,并追加到内置工具之后。工具分派按名称进行首次匹配,因此与内置名称冲突的插件工具永远不会被选中;请为插件工具提供唯一名称。工具和技能插件会被_自动发现_,因此仅当 [plugins] auto_discover = true 时才会执行此枚举(默认为 false,故障关闭):当 enabled = trueauto_discover = false 时,不会加载任何插件工具或技能,不过你在 [channels.plugin.<alias>] 下声明的通道仍会激活。技能加载器应用相同的 auto_discover 门控。

签名阶段是最容易配置错误的阶段,因此值得单独理解。

签名策略

每个插件清单都可以携带一个 Ed25519 签名,以及签署它的发布者的十六进制编码公钥。运维人员通过 [plugins.security] signature_mode 决定对该签名的强制执行有多严格:

模式什么加载用于
disabled每个格式正确的插件,无论是否已签名针对你自己构建的插件进行本地开发
permissive每个格式正确的插件;未签名、不受信任,以及无效签名的插件都会在加载时发出警告向签名迁移,同时不破坏现有安装
strict只有来自受信任发布者且签名有效的插件会加载任何共享或生产主机

strict 模式下,清单中的 publisher_key 必须出现在 [plugins.security] trusted_publisher_keys 中,并且签名必须针对规范化后的清单字节进行验证。未签名、由不受信任的密钥签名,或签名验证不通过的插件,会在发现阶段被丢弃,且永远不会成为工具。默认值是 disabled,因此新的本地检出无需密钥管理也能正常工作,但任何会从你不控制的来源加载插件的主机都应运行 strict

此策略统一强制执行:主机在你列出插件时应用的检查,与代理运行时在构建工具集时应用的检查是同一个,因此你在 strict 模式下看不到的插件,代理也无法调用。

功能与权限

清单声明两件独立的事情,而这种区别很重要。

  • Capabilities 是插件属于哪种扩展类型:toolchannelmemoryobserverskilltool 插件会提供 LLM 可以调用的工具。
  • 权限是插件代码在运行时可访问的宿主服务:HTTP 外联、配置、内存。清单未声明的权限,就是插件无法访问的宿主功能。

主机以严格范围授予权限:清单未声明的权限对应的主机函数,插件无法调用。配置根据主机签发的实例身份解析,因此插件无法选择其他包或绑定,也绝不会读取原始进程环境。http_client 控制出站 wasi:http 接口;共享的 SSRF 防护出站策略仍属于配套的插件强化工作。本页介绍签名策略边界。

配置参考

所有设置都位于 plugins.* 配置路径下,并可通过任何配置界面(zerocode、网关或 CLI)进行设置:

# 主开关。在这为 false 时不会加载任何内容。
zeroclaw config set plugins.enabled true

# 在运行时加载自动发现的工具和技能插件(默认值:false)。
# Without this, `enabled = true` activates only explicitly-declared channels.
zeroclaw config set plugins.auto_discover true

# 插件的发现位置(默认:~/.zeroclaw/plugins)。
zeroclaw config set plugins.plugins_dir ~/.zeroclaw/plugins

# 已禁用 | 宽松 | 严格
zeroclaw config set plugins.security.signature_mode strict

# 允许在严格模式下发布插件的十六进制编码 Ed25519 公钥。
zeroclaw config set plugins.security.trusted_publisher_keys '["a1b2c3d4e5f6..."]'

旨在加载第三方插件的宿主应设置 enabled = truesignature_mode = "strict",并仅列出你信任的发布者密钥。若还要加载自动发现的工具和技能插件,还应设置 auto_discover = true;它默认为 false,因此仅设置 enabled = true 只会启用你在 [channels.plugin.<alias>] 下声明的通道,不会启用任何插件工具或技能。仅运行你自行构建的插件的宿主,在开发期间可以让 signature_mode 保持其 disabled 默认值,并在共享宿主之前收紧设置。

插件仍然无法做到什么

即使授予了所有权限,沙箱仍会约束插件:

  • 它作为一个 WebAssembly 模块运行,无法对宿主进程或其根工作区之外的文件系统进行环境访问。网络外出流量受 HTTP 权限控制;由 SSRF 防护的外出边界本身由配套的插件加固工作提供。
  • 可信工具或通道插件可在已授权的服务调用期间,通过其作用域限定的 secrets.get 导入读取架构指定机密的明文。工具会在 execute 期间获得访问权限。通道会在 configure 和运行调用期间获得 config.getsecrets.get;同一次调用中的读取使用同一个规范修订版本,因此同一绑定的公开配置/机密轮换会在下一次操作时可用。实例化和静态元数据发现不能使用任一导入。主机可防止公开配置注入和跨实例选择,但返回明文的导入无法阻止恶意来宾保留其读取的内容。符合要求的通道插件必须在每个使用点解析配置和凭据。
  • 它不能取代内置工具:内置工具会先注册,而工具分发会按名称进行首次匹配解析,因此发生冲突的插件工具根本不会被选中。

沙箱和命名空间边界不受插件代码尝试执行的任何操作影响。相反,不保留规则属于受信任的通道插件契约的一部分,这也是发布者审核和签名策略仍然重要的原因。