1. 一条消息的完整旅程:从Slack到AI技能调用
在OpenClaw架构中,一条用户消息从发送到获得AI回复的全过程堪称精妙的交响乐演奏。让我们以"帮我清空收件箱里今天的GitHub通知,顺便给我一个总结"这条Slack消息为例,深入解析每个环节的技术实现。
1.1 消息接收与适配器转换
当用户在Slack输入消息并按下发送键时,OpenClaw系统会通过两种方式之一接收这个消息:
- Socket Mode:开发环境默认使用WebSocket长连接
- Events API:生产环境推荐使用HTTP Webhook
typescript复制// 使用@slack/bolt框架初始化连接
const app = new App({
token: config.botToken,
appToken: config.appToken,
socketMode: true // 开发模式使用WebSocket
});
app.message(async ({ message, event }) => {
const inbound = adaptSlackMessage(event); // 关键转换
emitInbound(inbound); // 进入系统管道
});
消息适配的核心是将平台特定的数据结构转换为OpenClaw通用格式:
typescript复制interface InboundMessage {
id: string; // 唯一消息ID
channel: string; // 来源渠道
peerId: string; // 发送者标识
chatId: string; // 会话标识
text: string; // 消息内容
timestamp: Date; // 时间戳
raw: any; // 原始数据
}
关键设计:每个通信渠道(Slack/Discord等)都有独立的适配器目录,保持代码隔离和可扩展性。适配器必须实现统一的ChannelAdapter接口。
1.2 安全验证与会话管理
消息进入系统后首先面临安全关卡:
typescript复制// 安全检查逻辑伪代码
async function checkInboundSecurity(msg) {
if (isGroupChat(msg.chatId)) return { allowed: true }; // 群组直接放行
const isApproved = await whitelist.isApproved(msg.peerId);
if (!isApproved) {
if (policy === "pairing") {
const code = generatePairingCode(); // 生成6位配对码
await sendPairingInstructions(code); // 发送配对指引
return { allowed: false, reason: "needs_pai
