构建渠道插件
本指南将带你完成一个渠道插件的构建,该插件用于将 OpenClaw 连接到某个消息平台。完成后,你将拥有一个可正常工作的渠道,具备私信安全、配对、回复线程和出站消息能力。如果你之前还没有构建过任何 OpenClaw 插件,请先阅读
入门指南 以了解基础包结构和清单设置。
渠道插件如何工作
渠道插件不需要自己的发送/编辑/反应工具。OpenClaw 在核心中保留了一个共享的message 工具。你的插件负责:
- 配置 — 账号解析和设置向导
- 安全 — 私信策略和允许列表
- 配对 — 私信批准流程
- 会话语法 — 提供商特定的会话 id 如何映射到基础聊天、线程 id 和父级回退
- 出站 — 向平台发送文本、媒体和投票
- 线程 — 回复如何在线程中组织
:thread: 记录,以及分发。
如果你的平台会在会话 id 中存储额外的作用域,请将该解析逻辑保留在插件中,使用 messaging.resolveSessionConversation(...)。这是将 rawId 映射到基础会话 id、可选线程 id、显式 baseConversationId 和任何 parentConversationCandidates 的规范钩子。
当你返回 parentConversationCandidates 时,请保持它们按从最窄父级到最宽/基础会话的顺序排列。
需要在渠道注册表启动前执行相同解析的内置插件,也可以公开一个顶层 session-key-api.ts 文件,并导出匹配的 resolveSessionConversation(...)。只有当运行时插件注册表尚不可用时,核心才会使用这个可安全引导的表面。
当插件只需要在通用/原始 id 之上提供父级回退时,messaging.resolveParentConversationCandidates(...) 仍可作为旧版兼容回退使用。如果两个钩子都存在,核心会先使用
resolveSessionConversation(...).parentConversationCandidates,只有当规范钩子省略它们时,才会回退到 resolveParentConversationCandidates(...)。
批准和渠道能力
大多数渠道插件不需要编写与批准特定相关的代码。- 核心负责同聊天内的
/approve、共享批准按钮负载,以及通用回退投递。 - 当渠道需要与批准相关的特定行为时,优先在渠道插件上使用一个
approvalCapability对象。 ChannelPlugin.approvals已移除。将批准投递/原生/渲染/授权相关信息放到approvalCapability上。plugin.auth仅用于登录/登出;核心不再从该对象读取批准授权钩子。approvalCapability.authorizeActorAction和approvalCapability.getActionAvailabilityState是规范的批准授权扩展点。- 对于同聊天批准授权可用性,使用
approvalCapability.getActionAvailabilityState。 - 如果你的渠道公开原生 exec 批准,请在其与同聊天批准授权不同时,使用
approvalCapability.getExecInitiatingSurfaceState表示发起表面/原生客户端状态。核心会使用这个 exec 专用钩子来区分enabled与disabled,判断发起渠道是否支持原生 exec 批准,并在原生客户端回退指引中包含该渠道。createApproverRestrictedNativeApprovalCapability(...)为常见场景填充了这一点。 - 对于渠道特定的负载生命周期行为,例如隐藏重复的本地批准提示或在投递前发送输入中指示,请使用
outbound.shouldSuppressLocalPayloadPrompt或outbound.beforeDeliverPayload。 - 仅将
approvalCapability.delivery用于原生批准路由或回退抑制。 - 将
approvalCapability.nativeRuntime用于渠道自有的原生批准信息。对于高频渠道入口点,请通过createLazyChannelApprovalNativeRuntimeAdapter(...)保持其惰性加载,这样它可以按需导入你的运行时模块,同时仍让核心组装批准生命周期。 - 仅在渠道确实需要自定义批准负载而不是共享渲染器时,才使用
approvalCapability.render。 - 当渠道希望禁用路径回复解释启用原生 exec 批准所需的确切配置项时,使用
approvalCapability.describeExecApprovalSetup。该钩子接收{ channel, channelLabel, accountId };命名账号渠道应渲染账号作用域路径,例如channels.<channel>.accounts.<id>.execApprovals.*,而不是顶层默认值。 - 如果某个渠道可以从现有配置中推断出稳定的类似所有者的私信身份,请使用
openclaw/plugin-sdk/approval-runtime中的createResolvedApproverActionAuthAdapter来限制同聊天/approve,而无需添加批准特定的核心逻辑。 - 如果某个渠道需要原生批准投递,请让渠道代码专注于目标规范化以及传输/展示事实。使用
openclaw/plugin-sdk/approval-runtime中的createChannelExecApprovalProfile、createChannelNativeOriginTargetResolver、createChannelApproverDmTargetResolver和createApproverRestrictedNativeApprovalCapability。将渠道特定信息放在approvalCapability.nativeRuntime后面,理想情况下通过createChannelApprovalNativeRuntimeAdapter(...)或createLazyChannelApprovalNativeRuntimeAdapter(...),这样核心就可以组装处理器并负责请求过滤、路由、去重、过期、Gateway 网关订阅以及“已路由到其他地方”的通知。nativeRuntime被拆分为几个更小的扩展点: availability— 账号是否已配置,以及请求是否应被处理presentation— 将共享批准视图模型映射为待处理/已解决/已过期的原生负载或最终动作transport— 准备目标并发送/更新/删除原生批准消息interactions— 原生按钮或反应的可选绑定/解绑/清除动作钩子observe— 可选的投递诊断钩子- 如果渠道需要运行时自有对象,例如客户端、令牌、Bolt 应用或 webhook 接收器,请通过
openclaw/plugin-sdk/channel-runtime-context注册它们。通用 runtime-context 注册表让核心能够从渠道启动状态引导由能力驱动的处理器,而无需添加批准特定的包装胶水代码。 - 只有当能力驱动的扩展点仍不够表达需求时,才使用更底层的
createChannelApprovalHandler或createChannelNativeApprovalRuntime。 - 原生批准渠道必须通过这些辅助工具同时传递
accountId和approvalKind。accountId可使多账号批准策略限定在正确的机器人账号范围内,而approvalKind可让渠道在无需核心中硬编码分支的情况下区分 exec 与插件批准行为。 - 核心现在也负责批准改道路由通知。渠道插件不应再从
createChannelNativeApprovalRuntime发送它们自己的“批准已发送到私信/另一个渠道”后续消息;请改为通过共享批准能力辅助工具公开准确的源头 + approver 私信路由,让核心在向发起聊天发送任何通知前聚合实际投递结果。 - 在端到端流程中保留已投递批准 id 的种类。原生客户端不应根据渠道本地状态去猜测或重写 exec 与插件批准路由。
- 不同批准种类可以有意公开不同的原生表面。
当前的内置示例:
- Slack 对 exec 和插件 id 都保留原生批准路由能力。
- Matrix 对 exec 和插件批准保留相同的原生私信/渠道路由和反应 UX,同时仍允许授权随批准种类而不同。
createApproverRestrictedNativeApprovalAdapter仍然作为兼容性包装器存在,但新代码应优先使用能力构建器,并在插件上公开approvalCapability。
openclaw/plugin-sdk/approval-auth-runtimeopenclaw/plugin-sdk/approval-client-runtimeopenclaw/plugin-sdk/approval-delivery-runtimeopenclaw/plugin-sdk/approval-gateway-runtimeopenclaw/plugin-sdk/approval-handler-adapter-runtimeopenclaw/plugin-sdk/approval-handler-runtimeopenclaw/plugin-sdk/approval-native-runtimeopenclaw/plugin-sdk/approval-reply-runtimeopenclaw/plugin-sdk/channel-runtime-context
openclaw/plugin-sdk/setup-runtime、
openclaw/plugin-sdk/setup-adapter-runtime、
openclaw/plugin-sdk/reply-runtime、
openclaw/plugin-sdk/reply-dispatch-runtime、
openclaw/plugin-sdk/reply-reference 和
openclaw/plugin-sdk/reply-chunking。
对于设置,具体如下:
openclaw/plugin-sdk/setup-runtime包含运行时安全的设置辅助工具: 可安全导入的设置补丁适配器(createPatchedAccountSetupAdapter、createEnvPatchedAccountSetupAdapter、createSetupInputPresenceValidator)、查找说明输出、promptResolvedAllowFrom、splitSetupEntries以及委托式 setup-proxy 构建器openclaw/plugin-sdk/setup-adapter-runtime是用于createEnvPatchedAccountSetupAdapter的窄型环境感知适配器扩展点openclaw/plugin-sdk/channel-setup涵盖可选安装设置构建器以及少量设置安全原语:createOptionalChannelSetupSurface、createOptionalChannelSetupAdapter、
channelEnvVars 声明它们。将渠道运行时 envVars 或本地常量仅用于面向操作员的文案。
createOptionalChannelSetupWizard、DEFAULT_ACCOUNT_ID、
createTopLevelChannelDmPolicy、setSetupChannelEnabled 和
splitSetupEntries
- 仅当你还需要更重的共享设置/配置辅助工具时,才使用更宽泛的
openclaw/plugin-sdk/setup扩展点,例如moveSingleAccountChannelSectionToDefaultAccount(...)
createOptionalChannelSetupSurface(...)。生成的适配器/向导会在配置写入和最终化时采用默认拒绝行为,并在验证、完成和文档链接文案中复用相同的“需要安装”消息。
对于其他高频渠道路径,请优先使用窄型辅助工具,而不是更宽泛的旧版表面:
openclaw/plugin-sdk/account-core、openclaw/plugin-sdk/account-id、openclaw/plugin-sdk/account-resolution和openclaw/plugin-sdk/account-helpers用于多账号配置和默认账号回退openclaw/plugin-sdk/inbound-envelope和openclaw/plugin-sdk/inbound-reply-dispatch用于入站路由/封装以及记录与分发接线openclaw/plugin-sdk/messaging-targets用于目标解析/匹配openclaw/plugin-sdk/outbound-media和openclaw/plugin-sdk/outbound-runtime用于媒体加载以及出站身份/发送委托openclaw/plugin-sdk/thread-bindings-runtime用于线程绑定生命周期和适配器注册- 仅当仍需要旧版智能体/媒体负载字段布局时,才使用
openclaw/plugin-sdk/agent-media-payload openclaw/plugin-sdk/telegram-command-config用于 Telegram 自定义命令规范化、重复/冲突校验,以及一个可稳定回退的命令配置契约
入站提及策略
请将入站提及处理拆分为两层:- 插件自有的证据收集
- 共享策略评估
openclaw/plugin-sdk/channel-inbound。
适合放在插件本地逻辑中的内容:
- 回复机器人检测
- 引用机器人检测
- 线程参与检查
- 服务/系统消息排除
- 证明机器人参与所需的平台原生缓存
requireMention- 显式提及结果
- 隐式提及允许列表
- 命令绕过
- 最终跳过决策
- 计算本地提及事实。
- 将这些事实传给
resolveInboundMentionDecision({ facts, policy })。 - 在你的入站门控中使用
decision.effectiveWasMentioned、decision.shouldBypassMention和decision.shouldSkip。
api.runtime.channel.mentions 公开了相同的共享提及辅助工具:
buildMentionRegexesmatchesMentionPatternsmatchesMentionWithExplicitimplicitMentionKindWhenresolveInboundMentionDecision
resolveMentionGating* 辅助工具仍保留在
openclaw/plugin-sdk/channel-inbound 中,但仅作为兼容性导出。新代码应使用
resolveInboundMentionDecision({ facts, policy })。
演练
包和清单
创建标准插件文件。
package.json 中的 channel 字段
使其成为一个渠道插件。有关完整的包元数据表面,
请参见 插件设置和配置:构建渠道插件对象
ChannelPlugin 接口有许多可选适配器表面。先从最小集合开始——id 和 setup——然后按需添加适配器。创建 src/channel.ts:src/channel.ts
`createChatChannelPlugin` 为你做了什么
`createChatChannelPlugin` 为你做了什么
你无需手动实现底层适配器接口,而是传入声明式选项,由构建器负责组合:
如果你需要完全控制,也可以传入原始适配器对象,而不是这些声明式选项。
| 选项 | 接线内容 |
|---|---|
security.dm | 基于配置字段的作用域私信安全解析器 |
pairing.text | 基于文本和验证码交换的私信配对流程 |
threading | 回复模式解析器(固定、账号作用域或自定义) |
outbound.attachedResults | 返回结果元数据(消息 id)的发送函数 |
接线入口点
创建 将渠道自有的 CLI 描述符放在
index.ts:index.ts
registerCliMetadata(...) 中,这样 OpenClaw 就能在不激活完整渠道运行时的情况下,在根帮助中显示它们;而普通完整加载仍会拾取相同的描述符以进行真实命令注册。将 registerFull(...) 保留给仅运行时工作。
如果 registerFull(...) 注册 Gateway 网关 RPC 方法,请使用插件特定前缀。核心管理命名空间(config.*、
exec.approvals.*、wizard.*、update.*)保持保留,并始终解析到 operator.admin。
defineChannelPluginEntry 会自动处理注册模式拆分。有关全部选项,请参见
入口点。添加设置入口
创建 当渠道被禁用或尚未配置时,OpenClaw 会加载它,而不是完整入口。
这样可以避免在设置流程中拉入沉重的运行时代码。
详情请参见 设置和配置。
setup-entry.ts,用于在新手引导期间轻量加载:setup-entry.ts
处理入站消息
你的插件需要从平台接收消息并将其转发给 OpenClaw。典型模式是一个 webhook:验证请求后,通过你渠道的入站处理器进行分发。
入站消息处理是渠道特定的。每个渠道插件都拥有自己的入站处理管线。请查看内置渠道插件
(例如 Microsoft Teams 或 Google Chat 插件包)以了解真实模式。
测试
文件结构
高级主题
线程选项
固定、账号作用域或自定义回复模式
消息工具集成
describeMessageTool 和动作发现
目标解析
inferTargetChatType、looksLikeId、resolveTarget
运行时辅助工具
通过 api.runtime 使用 TTS、STT、媒体、子智能体
某些内置辅助扩展点仍保留,用于内置插件维护和兼容性。它们并不是新渠道插件的推荐模式;
除非你正在直接维护该内置插件家族,否则应优先使用公共 SDK 表面中的通用渠道/设置/回复/运行时子路径。