id: ADR-003 title: WASM 插件使用 Extism 作为初始执行桥梁 date: 2026-03-15 status: superseded-by-ADR-009 relates-to:
- ADR-009
- crates/zeroclaw-plugins
- crates/zeroclaw-api
ADR-003:WASM 插件使用 Extism 作为初始执行桥接
这是一个恢复的追溯记录。原始 ADR 添加在 docs/architecture/decisions/adr-003-wasm-extism-plugin-model.md 下,并在 mdBook 迁移期间被移除。它记录了于 2026-03-15 被接受的基于 Extism 的历史插件桥接。当前的 WIT 和直接 wasmtime 模型已由 ADR-009 取代。
上下文
ZeroClaw 将许多工具和通道编译进一个单一二进制文件。每个用户都为他们可能永远不会使用的能力付出了编译时间和二进制体积的代价。第三方开发者无法在不 fork 该仓库并针对内部 API 编写 Rust 代码的情况下扩展 ZeroClaw。
Intentional Architecture RFC 定义了一个 microkernel 目标,其中非核心工具和通道变为可加载的插件。这就需要一种沙箱化的执行模型,它:
- 在不危及宿主进程的情况下运行不受信任的代码。
- 适用于 Linux、macOS、Windows、ARM 和 x86_64 目标。
- 支持基于能力的权限,例如 HTTP 访问、读取环境变量和文件 I/O。
- 允许使用任何可编译为 WASM 的语言编写插件。
- 当未使用该功能时,只会增加最小的二进制大小。
最初的评估考虑了三种 WASM 运行时选项:
| 运行时 | 优点 | 缺点 |
|---|---|---|
| Extism | 高级 SDK、内置宿主函数系统、面向多种来宾语言的 PDK、持续维护 | 在功能标志后添加二进制大小 |
| Raw wasmtime | 最大控制,成熟的运行时 | 需要直接构建 ABI、内存协议和主机函数系统 |
| Wasmer | LLVM 和 Cranelift 后端 | 更小的生态系统和较差的 Rust 原生 host 函数易用性 |
决策
ZeroClaw 将在 plugins-wasm 特性标志后使用 Extism 1.x 作为初始 WASM 插件运行时。
插件是导出两个 JSON 函数的 WASM 模块:
tool_metadata(String) -> String,返回包含name、description和parameters_schema字段的 JSON。execute(String) -> String,接收工具参数为 JSON,并返回一个包含success、output和可选error字段的 JSON 结果。
运行时提供了两个受权限控制的主机函数:
zc_http_request(String) -> String,受PluginPermission::HttpClient约束。zc_env_read(String) -> String,受PluginPermission::EnvRead约束。
之所以刻意不使用 Extism 内置的 HTTP 支持,是因为它会绕过 ZeroClaw 的权限强制执行。
每个插件都随其 .wasm 文件一起提供了一个 manifest.toml。该清单声明了名称、版本、功能(如 tool、channel、memory 和 observer),以及所需权限(如 http_client、env_read、file_read、file_write、memory_read 和 memory_write)。
插件清单支持可选的 Ed25519 签名,并提供三种强制模式:disabled、permissive 和 strict。
插件作者依赖于 extism-pdk 并编译为 wasm32-wasip1。该协议使用了文档化的 JSON 契约,而不是 ZeroClaw 特定的 guest SDK crate。
后果
正数:
- WASM 线性内存隔离阻止了插件访问宿主内存。
- 带权限门控的主机函数为最初的桥接提供了清晰的能力模型。
- WASM 模块可以在底层运行时支持的任何平台上运行。
- 具有
wasm32-wasip1目标的语言可以生成插件。 - 禁用
plugins-wasm的用户无需承担二进制大小或编译时间成本。
负值:
- Extism 在功能标志后面添加了二进制大小。
- 插件作者依赖于
extism-pdk,一个外部 SDK。 - 最初的桥接使工具插件在通道插件之前就能正常工作。
- Extism 调用是同步的,而 ZeroClaw 的
Tooltrait 是异步的,因此调用使用了阻塞任务桥接。
已知缺口:
zc_http_request可以转发插件提供的 URL,而不受原生 HTTP 工具所使用的相同私有 IP、回环地址和链路本地地址限制。env_read授予了按名称访问任意变量的权限,而不是按插件的允许列表。- CPU 执行没有燃料限制或 epoch 中断。
这些缺口意味着,权限模型最初只是一个有文档说明的契约,而还不是对来自不受信任作者的插件的硬边界。
参考文献
- ADR-009: WIT 组件和直接 wasmtime 插件执行
- Historical source path:
docs/architecture/decisions/adr-003-wasm-extism-plugin-model.md - 历史实现路径:
crates/zeroclaw-plugins/src/runtime.rs、crates/zeroclaw-plugins/src/wasm_tool.rs、crates/zeroclaw-plugins/src/host.rs和crates/zeroclaw-plugins/src/signature.rs - 跟踪原始 ADR 中的问题:#5918 和 #5919