Plugin SDK
“Hooks Are the API”
A well-designed hook system makes the agent infinitely extensible.
@opencode-ai/plugin 包将钩子定义为 agent 核心与扩展之间的公共 API。钩子覆盖了每个生命周期阶段:配置加载、工具执行(前后)、消息处理、权限、认证、shell 环境设置和会话压缩。这种全面覆盖意味着大多数扩展需求无需修改核心代码即可满足。
架构流程图
问题:稳定的核心,不稳定的扩展
每个插件系统都面临同样的张力:核心必须足够稳定以保证可推理性,同时又必须足够灵活以适应未知的未来需求。OpenCode 的插件 SDK 通过将钩子定义为 TypeScript 接口来解决这个问题。这是核心与扩展之间的契约。核心声明:我将在这些时间点调用这些函数。插件声明:我将提供匹配这些签名的函数。只要双方遵守该接口,核心永远不需要了解具体插件,插件也永远不需要修补核心。
全面的钩子覆盖:每个钩子为什么存在
每个钩子的存在都源于实际需求。'config' 钩子允许插件在 agent 启动前修改配置。'tool.execute.before' 和 'tool.execute.after' 支持日志、指标收集和验证。'permission.ask' 允许插件实现自定义审批流程。'shell.env' 注入环境变量以确保可重现的构建。全面覆盖意味着对于'能否用插件 API 实现 X?'这类问题,答案几乎总是'是的,有对应的钩子。'
设计决策
Hooks 接口使用可选方法:插件只实现它需要的钩子。无需继承基类或实现抽象方法。这是结构化类型系统的实际应用。
某些钩子上的 'experimental.' 前缀表示其 API 可能发生变化。这为核心团队保留了演进自由,同时为插件作者提供早期访问权限。稳定后,该前缀会被移除。
对比 Claude Code
Plugin SDK 是 OpenCode 最独特的特性之一,Claude Code 没有对等功能。registerPlugin(plugin: Plugin) → hooks[] → lifecycle events 模式支持市场风格的生态系统,第三方插件可以添加新工具、权限策略和配置转换,而无需 fork 核心仓库。
深入设计决策
钩子即公共 API
@opencode-ai/plugin 包定义了插件实现的钩子。这是 agent 核心和扩展生态系统之间的契约——稳定、版本化、文档化。
覆盖 Agent 生命周期的每个阶段
钩子覆盖了配置加载、工具执行、消息处理、权限、shell 环境设置和会话压缩。每个可扩展点都被覆盖。