
OpenClaw Discord Skill用 message 工具完成 Discord 消息工作流的设计与实现【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw本文以 OpenClaw 仓库中 Discord 插件内置的 discord skill 为主体完整还原该 skill 定义的工作流规则ID 选取、线程与 forum 约束、破坏性操作确认、交互式组件Components V2的 JSON 用法及其硬性限制并结合 discord 插件源码 逐条印证channels.discord.actions.*配置门控如何动态生成message工具的动作清单与参数 schema以及 send 类动作为何在本地执行、其余动作交由 gateway 处理。读完后你可以理解为什么模型不能假设不存在的 action以及一个 Discord 消息请求从工具 schema 发现到实际执行的完整链路。Skill 的定位与 frontmatter该 skill 位于 Discord 插件内部extensions/discord/skills/discord/SKILL.md其 frontmatter 声明了 skill 的基本契约--- name: discord description: Discord messaging workflows through OpenClaws message tool. metadata: { openclaw: { emoji: , requires: { config: [channels.discord] } } } allowed-tools: [message] ---三个关键点requires.config: [channels.discord]表示只有配置中启用了 Discord 通道存在channels.discord配置时该 skill 才会对 Agent 生效。这与源码中describeDiscordMessageTool的发现逻辑一致当没有任何已启用且已配置的 Discord 账号时直接返回actions: []、capabilities: []、schema: null即工具不暴露任何 Discord 动作见 channel-actions.ts。allowed-tools: [message]表明该 skill 的全部能力收敛在单一的message工具上调用时固定携带channel: discord。原文档开宗明义工具 schema 会列出当前账号channels.discord.actions.*门控允许的动作不要假设不存在的动作。这不是空话而是由源码保证的——下文展开。动作清单由配置门控动态生成Skill 的核心原则是以工具 schema 为准而非静态动作目录。在 channel-actions.ts 的describeDiscordMessageTool中可以看到完整的门控→动作映射actions.*配置键默认值解锁的 message 动作无门控—send始终可用只要有可发现的账号polls开pollreactions开react、reactions、emoji-listmessages开upload-file、read、edit、deletepins开pin、unpin、list-pinspermissions开permissionsthreads开thread-create、thread-list、thread-replysearch开searchstickers开stickermemberInfo开member-inforoleInfo开role-infoemojiUploads开emoji-uploadstickerUploads开sticker-uploadroles关role-add、role-removechannelInfo开channel-info、channel-listchannels开channel-create、channel-edit、channel-delete、channel-move、category-create、category-edit、category-deletevoiceStatus开voice-statusevents开event-list、event-createmoderation关timeout、kick、banpresence关set-presence这些配置键与 config-schema.ts 中actions的严格 schema 一一对应reactions、stickers、emojiUploads、stickerUploads、polls、permissions、messages、threads、pins、search、memberInfo、roleInfo、roles、channelInfo、voiceStatus、events、moderation、channels、presence均为可选布尔值。注意三个默认关闭的门控roles、moderation、presence——涉及角色增删、禁言/踢出/封禁、状态设置这类高敏感操作需要显式开启这与 skill 文档不要假设不可用动作的告诫相互印证。门控的取值来源有双层结构见 accounts.ts 的createDiscordActionGate基础层cfg.channels.discord.actions通道级默认账号层cfg.channels.discord.accounts.accountId.actions单账号覆盖。当未指定accountId时channel-actions.ts 的resolveDiscordActionDiscovery会对所有已启用且已配置的账号做并集createUnionActionGate任一账号开启某门控该动作就会出现在工具 schema 中指定了accountId后则只看该账号自己的门控。这就是 skill 中当多个 Discord 账号可能适用时请传accountId的底层依据——传与不传决定的是动作清单的并集还是单集。Skill 工作流规则及其源码依据Skill 文档给出的四条工作流规则每一条都能落到具体实现约束上1. 优先使用稳定的guildId、channelId、messageId、userId多账号时传accountId。Discord 的 Snowflake ID 是全局稳定标识。配置层面config-schema.ts 的DiscordIdSchema明确允许数字或字符串形式的 ID并对数字做了安全整数校验非安全整数会被要求在配置文件中加引号说明整个体系以 Snowflake 字符串为一等公民。2. 用户指代含糊时先解析出精确消息再执行编辑、删除、置顶、 moderation 或 reaction。这一条对应动作侧的实现编辑/删除/置顶等动作都归入messages/pins/moderation门控见上表执行入口统一走 handle-action.ts 与 runtime.moderation.ts后者带有独立的鉴权测试 runtime.moderation.authz.test.ts。源码结构表明 moderation 类动作在执行前会做请求者身份核验因此先确认精确目标既是行为要求也是安全边界。3. 线程回复留在原线程内forum 父频道不能接收 components应发到已创建的 forum 线程中。这是 Discord 平台侧的真实限制forum 类型的父频道是只读的消息容器只有其下自动创建的帖子线程才可承载交互组件。工具层对线程语义有专门的适配——channel-actions.ts 中的resolveDiscordThreadReplyTarget/resolveDiscordThreadReplyDeliveryAlias会把threadId归一化为channel:threadId目标thread-reply动作通过messageActionTargetAliases声明threadId别名第 278-286 行并在matchesCurrentConversation命中时直接投递到当前会话线程保证线程回复留在原线程。4. 破坏性或 moderation 动作必须确认除非用户已明确指定目标与动作。配合默认关闭的moderation、roles门控以及requiresTrustedRequesterSenderguild-admin 类动作需要受信任请求者见 channel-actions.tsskill 文档把确认写成了 Agent 的硬性行为约束。交互式组件Components V2 的用法与硬性限制Skill 文档给出的组件示例原文完整保留{ action: send, channel: discord, to: channel:123, message: Choose an option, components: { blocks: [ { type: actions, buttons: [ { label: Approve, style: success, callbackData: approve }, { label: Decline, style: danger, callbackData: decline } ] } ] } }两条硬性约束来自原文且都能在源码中找到执行点约束一components必须是结构化对象或原生组件数组绝不能是占位字符串。在 channel-actions.ts 的prepareSendPayload中ctx.params.components先经coerceDiscordComponentParam强制转换定义于 components.parse.ts若转换结果是函数非法输入形态直接返回null拒绝发送。合法对象再经readDiscordComponentSpec解析为组件 spec原生数组则作为nativeComponents直通最终写入channelData.discord.components。schema 侧同样如此describeDiscordMessageTool为send动作声明的components属性是blocksV2 块数组text、buttons、selects、media、containers、separators加可选modal的对象结构第 229-262 行与 components.ts 导出的类型体系DiscordComponentBlock、DiscordComponentButtonSpec、DiscordModalSpec等及构建器buildDiscordComponentMessage、createDiscordFormModal保持一致。约束二Components V2 不得与 legacyembeds混用。这一点在prepareSendPayload中被写成显式守卫if ((componentSpec || nativeComponents) embeds?.length) { return null; // 组件与 embeds 同时出现 → 拒绝 }即两者同时存在时整个 payload 被拒绝而不是静默降级这正是 skill 文档要求 Agent不要组合的原因。组件点击后的回传链路同样有源码支撑custom id 的编解码集中在 component-custom-id.tsbuildDiscordComponentCustomId/parseDiscordComponentCustomId交互分发在 interactive-dispatch.ts按钮/选择器事件最终被格式化为Clicked Approve.这类文本回灌给模型formatDiscordComponentEventText。执行位置本地动作与 gateway 动作的分流从源码结构看Discord 动作并非全部在同一位置执行。channel-actions.ts 定义了localExecutionActions白名单const localExecutionActions new SetChannelMessageActionName([ send, poll, upload-file, thread-reply, sticker, emoji-upload, sticker-upload, event-create, ]);白名单内的动作以local模式执行源码注释解释了原因Credential-only Discord actions run in the gateway when one is available. Send/file-style actions stay local because core owns their thread, media, component, and client-local payload semantics.——发送、上传、线程回复这类动作涉及核心拥有的线程路由、媒体文件与本地组件语义必须留在客户端本地处理而编辑、删除、置顶、moderation 等只需凭证的动作在可用时交给 gateway 执行。此外supportsAction明确排除pollDiscord 投票走独立本地路径。理解这个分流有助于在排查某个动作为什么没执行/在哪里执行时定位正确的日志与进程边界。提示注入与不要维护重复目录Skill 文档最后一句值得单独强调Discord mention 语法、组件可用性和表单提示会自动注入。请遵循当前的提示与工具 schema而不是复制的动作目录。结合源码可以推断其设计动机动作清单、schema 描述例如react动作的emoji参数说明会根据emoji-list是否可用动态变化见 channel-actions.ts在每次工具发现时实时计算。若 skill 文档里硬编码一份动作目录配置变更后必然失真因此文档只固化工作流规则与组件约束这类不变量把能力清单完全交给运行时 schema。这也是编写其他 OpenClaw channel skill 时可参考的模式frontmatter 声明依赖配置与允许工具正文写行为规则能力细节交给门控与 schema 动态生成。相关源码索引主题路径Skill 定义本文主体extensions/discord/skills/discord/SKILL.md工具发现与动作门控映射extensions/discord/src/channel-actions.ts账号配置合并与 action gateextensions/discord/src/accounts.tschannels.discord配置 schema含actions.*extensions/discord/src/config-schema.ts组件解析/构建/模态框extensions/discord/src/components.ts动作执行入口extensions/discord/src/actions/handle-action.tsmoderation 执行与鉴权测试extensions/discord/src/actions/runtime.moderation.ts、runtime.moderation.authz.test.ts门控行为的契约测试extensions/discord/src/channel-actions.contract.test.ts、channel-actions.test.ts适用前提以上所有结论均基于当前仓库中 Discord 插件的源码与 skill 文档需配置channels.discord含有效 bot token账号可通过token配置项或DISCORD_BOT_TOKEN环境变量提供见 accounts.ts方可生效动作的最终可见集合由通道级与账号级actions.*门控共同决定。【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考