跳转至

提及策略

决定何时将一条入站消息计为提及,而无需重新实现共享策略。这是构建频道插件指南的一部分。

入站提及策略

保持入站提及处理分为两层:

  • 插件拥有的证据收集
  • 共享策略评估

用于提及策略决策时使用 openclaw/plugin-sdk/channel-mention-gating。 仅当需要更广泛的入站辅助 barrel 时使用 openclaw/plugin-sdk/channel-inbound。

适合插件本地逻辑的场景:

  • 回复机器人的检测
  • 引用机器人的检测
  • 线程参与检查
  • 机器人拥有的线程检测以及频道特定配置继承
  • 服务/系统消息排除
  • 证明机器人参与所需的平台原生缓存

适合共享辅助函数的场景:

  • requireMention
  • 显式提及结果
  • 隐式提及允许列表
  • 命令绕过
  • 最终跳过决策

对于符合条件的群线程条目,使用来自 openclaw/plugin-sdk/channel-inbound 的 resolveGroupThreadMentionFacts({ cfg, channel, peerId, text, sessionKey, acpBinding }) 一次性计算显式参与者提及事实,包括直接对话。传入已解析的会话键以及已配置的 ACP 绑定是否拥有该路由。对于独占 ACP 路由或没有符合条件的条目时,它返回 undefined;否则返回已解析的群组和 mentionedAgentIds。如果准备之后路由发生变化, 使用 isGroupThreadRouteExclusive({ sessionKey, acpBinding }) 丢弃 ACP 拥有目的地的 参与者事实,并仅使用最终路由的普通提及和命令事实重新评估准入。在普通门控之前, 将非空的参与者匹配与路由代理的本地提及事实合并,并将相同的选择事实带入分发。 对未路由参与者的提及不得被单代理门控丢弃。参与者选择需要 @ 样式匹配; 仅名称或表情符号不会选择代理。保持发送者授权和命令策略不变。

设置可选的 replyOptions.groupThreadReplyFormatter(text, participant), 以将适配器的参与者标签应用于源对话消息工具回复。参与者包含 agentId 和 name; 复用用于普通回复的相同传输格式化器,并带有参与者投递元数据。

对于插件拥有的发送,在投递入口从同一 SDK 读取 getGroupThreadDeliverySession()。 如果存在,使用其 agentId 和 sessionKey 用于媒体根、内部钩子和转录镜像, 包括未标记的单代理群组。保持传输账户所有权不变。共享持久投递在核心中选择 活动的参与者上下文和运行身份。

推荐流程:

  1. 计算本地提及事实。
  2. 将这些事实传入 resolveInboundMentionDecision({ facts, policy })。
  3. 在你的入站门控中使用 decision.effectiveWasMentioned、decision.shouldBypassMention 和 decision.shouldSkip。
import {
  implicitMentionKindWhen,
  matchesMentionWithExplicit,
  resolveInboundMentionDecision,
} from "openclaw/plugin-sdk/channel-inbound";
import { resolveChannelImplicitMentions } from "openclaw/plugin-sdk/channel-ingress-runtime";

const wasMentioned = matchesMentionWithExplicit({
  text,
  mentionRegexes,
  explicit: {
    hasAnyMention,
    isExplicitlyMentioned,
    canResolveExplicit,
  },
});

const facts = {
  canDetectMention: true,
  wasMentioned,
  hasAnyMention,
  implicitMentionKinds: [
    ...implicitMentionKindWhen("reply_to_bot", isReplyToBot),
    ...implicitMentionKindWhen("quoted_bot", isQuoteOfBot),
  ],
};

const implicitMentions = resolveChannelImplicitMentions({
  cfg,
  channel: channelId,
  accountId,
});

const decision = resolveInboundMentionDecision({
  facts,
  policy: {
    isGroup,
    requireMention,
    implicitMentions,
    allowTextCommands,
    hasControlCommand,
    commandAuthorized,
  },
});

if (decision.shouldSkip) return;

matchesMentionWithExplicit(...) 返回布尔值。hasAnyMention、 isExplicitlyMentioned 和 canResolveExplicit 来自频道自身的原生提及元数据 (消息实体、回复机器人标志等);当你的平台无法检测它们时,提供 false/undefined 值。

api.runtime.channel.mentions 为已经依赖运行时注入的捆绑频道插件公开相同的 共享提及辅助函数:buildMentionRegexes、matchesMentionPatterns、 matchesMentionWithExplicit、implicitMentionKindWhen、 resolveInboundMentionDecision。

如果你只需要 implicitMentionKindWhen 和 resolveInboundMentionDecision, 请从 openclaw/plugin-sdk/channel-mention-gating 导入,以避免加载无关的 入站运行时辅助函数。

机器人拥有的线程

具有原生线程所有权的频道可以公开 requireMentionInBotThreads。省略该值会保留 频道现有的提及行为。false 允许在由已配置机器人启动的线程中发送没有提及的消息。 true 要求在那里必须有提及,即使普通 requireMention 设置为 false; 回复或引用机器人以及先前的机器人参与都不满足该要求。显式提及、原生提及证据 和已授权命令绕过保留其普通行为。

插件负责证明当前机器人启动了线程,并在调用来自 openclaw/plugin-sdk/channel-mention-gating 的 resolveBotThreadMentionPolicy 之前解析最具体的配置值。仅有机器人参与并不构成所有权。对于未知所有权、外部线程 和普通频道消息,传入 isBotOwnedThread: false 以保留现有行为。

在收集提及证据之后、共享决策之前应用该辅助函数:

const threadPolicy = resolveBotThreadMentionPolicy({
  isBotOwnedThread,
  requireMentionInBotThreads,
  requireMention,
  implicitMentionKinds: facts.implicitMentionKinds,
});

const decision = resolveInboundMentionDecision({
  facts: { ...facts, implicitMentionKinds: threadPolicy.implicitMentionKinds },
  policy: { ...policy, requireMention: threadPolicy.requireMention },
});

此覆盖仅更改提及准入。请保留现有的发送者允许列表、频道访问策略和命令授权。对于没有可靠原生所有权证据的频道,不应根据缓存的参与记录推断所有权,也不应暴露其无法强制执行的覆盖。

在将回合交给共享分发之前,重新检查可变准入规则。准入之后,应保留该回合已捕获的策略用于其回复,而不是使用提及或发送者门控来取消投递。账户、运行和传输存活状态仍分别由其现有负责人负责。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw