Skip to content

通道抽象层

通道抽象层是 OpenClaw 通道系统的核心设计——通过 ChannelPlugin 接口和 ChannelDock 元数据的分离,实现了"重逻辑运行时加载、轻元数据全局可用"的架构。

ChannelPlugin 接口

Source: src/channels/plugins/types.ts

ChannelPlugin 是每个通道实现必须提供的核心接口,由多个 Adapter 组合而成:

typescript
// src/channels/plugins/types.ts (simplified)
interface ChannelPlugin {
  // Capabilities declaration
  capabilities: ChannelCapabilities;

  // Adapters
  outbound: ChannelOutboundAdapter;     // Send messages out
  messaging: ChannelMessagingAdapter;   // Receive messages
  commands?: ChannelCommandAdapter;     // Handle commands
  groups?: ChannelGroupAdapter;         // Group-specific behavior
  threading?: ChannelThreadingAdapter;  // Reply/thread handling
  mentions?: ChannelMentionAdapter;     // @mention parsing
  agentPrompt?: ChannelAgentPromptAdapter; // Platform-specific prompts
}

能力声明

typescript
// src/channels/plugins/types.ts (simplified)
interface ChannelCapabilities {
  chatTypes: ("direct" | "group" | "channel" | "thread")[];
  nativeCommands: boolean;       // Supports / commands
  blockStreaming: boolean;        // Can stream responses
  polls: boolean;                 // Supports polls
  reactions: boolean;             // Supports reactions
  media: MediaCapabilities;       // Image/audio/video support
}

每个通道声明自己支持的能力,Agent 和路由层据此决定行为。

Adapter 详解

OutboundAdapter — 消息发送

typescript
interface ChannelOutboundAdapter {
  sendText(opts: SendTextOpts): Promise<SendResult>;
  sendMedia(opts: SendMediaOpts): Promise<SendResult>;
  sendPayload?(opts: SendPayloadOpts): Promise<SendResult>;
  sendReaction?(opts: SendReactionOpts): Promise<void>;
}

ThreadingAdapter — 线程与回复

typescript
interface ChannelThreadingAdapter {
  // "first": reply to first message only
  // "all": reply to every message
  resolveReplyToMode(): "first" | "all";

  // Build context for tool execution
  buildToolContext(): {
    currentChannelId: string;
    currentThreadTs?: string;
  };
}

Telegram 默认使用 "first" 模式(只回复第一条消息),而 Slack 可能使用线程模式。

MentionAdapter — @提及处理

typescript
interface ChannelMentionAdapter {
  parseMention(text: string): MentionResult | null;
  stripMention(text: string): string;
}

ChannelDock 元数据

Source: src/channels/dock.ts

ChannelDock 是轻量级的通道元数据对象,在核心代码中全局可用,不依赖插件运行时:

typescript
// src/channels/dock.ts (simplified)
interface ChannelDock {
  id: string;                    // Channel identifier
  capabilities: ChannelCapabilities;
  outbound?: ChannelOutboundAdapter;
  commands?: ChannelCommandAdapter;
  groups?: ChannelGroupAdapter;
  mentions?: ChannelMentionAdapter;
  threading?: ChannelThreadingAdapter;
  agentPrompt?: ChannelAgentPromptAdapter;

  // Lightweight metadata (no runtime loading needed)
  textChunkLimit: number;        // Max chars per message
  streamingDefaults: boolean;    // Streaming enabled by default
  allowFrom: AllowFromConfig;    // Access control
}

Plugin vs Dock 的分离

为什么要这样分离?

  • Dock 是配置读取器和格式化工具——读取 textChunkLimitallowFrom 不需要启动 Telegram bot
  • Plugin 是运行时操作——连接 bot、监听消息、发送回复等需要实际的网络 I/O
  • 这种分离让核心路由逻辑可以快速访问通道元数据,而不必等待插件加载

Mention Gating

Source: src/channels/mention-gating.ts

Mention gating 决定在群组中是否需要 @ 提及才触发 AI 回复:

typescript
// src/channels/mention-gating.ts (simplified)
function resolveMentionGating(
  channel: string,
  chatType: "direct" | "group",
  config: ChannelConfig
): boolean {
  // Direct messages: never require mention
  if (chatType === "direct") return false;

  // Group messages: check per-group settings
  // Falls back to channel-level default
  return config.requireMention ?? true;
}

门控流程

通道配置

Source: src/channels/channel-config.ts

每个通道都有自己的配置模块:

typescript
// src/channels/channel-config.ts (simplified)
interface ChannelConfig {
  enabled: boolean;
  allowFrom?: AllowFromConfig;   // Who can send messages
  textChunkLimit?: number;       // Override default chunk limit
  requireMention?: boolean;      // Override mention gating
  // Channel-specific settings...
}

小结

  • ChannelPlugin 接口定义了 7 种 Adapter:Outbound、Messaging、Command、Group、Threading、Mention、AgentPrompt
  • ChannelDock 提供轻量元数据,不依赖运行时加载
  • 双层分离 让核心路由快速访问元数据,而插件按需加载
  • Mention gating 控制群组中是否需要 @提及 才触发 AI
  • 每个通道声明自己的 Capabilities,Agent 据此调整行为

下一章:Telegram 实现

OpenClaw 源码学习教程