OpenClaw 项目架构分析

[TOC]

项目地址: OpenClaw

项目概述

OpenClaw 是一个个人 AI 助手平台,用户可以在自己的设备上运行,支持多种通讯渠道的统一接入。该项目采用 TypeScript 开发,具有高度的模块化和可扩展性。

核心特性

  • 多渠道支持: WhatsApp、Telegram、Slack、Discord、Google Chat、Signal、iMessage、Microsoft Teams、LINE、Matrix 等
  • AI 集成: 支持 OpenAI、Anthropic、Google、MiniMax、Moonshot 等多个 AI 提供商
  • 跨平台: 提供 iOS、Android、macOS 原生应用
  • 插件化: 通过扩展系统支持自定义渠道和功能
  • 本地优先: 数据存储在用户设备,保护隐私

整体目录结构

openclaw/
├── src/                        # 核心源代码
│   ├── cli/                    # CLI 命令行界面
│   ├── channels/               # 通用渠道功能
│   ├── gateway/                # 网关和 API 服务器
│   ├── commands/               # 命令实现
│   ├── config/                 # 配置管理
│   ├── infra/                  # 基础设施
│   ├── media/                  # 媒体处理
│   ├── plugin-sdk/             # 插件开发 SDK
│   ├── routing/                # 消息路由
│   ├── auto-reply/             # 自动回复
│   └── [channel-id]/           # 各渠道具体实现
│       ├── telegram/
│       ├── discord/
│       ├── slack/
│       ├── signal/
│       ├── imessage/
│       ├── whatsapp/
│       ├── line/
│       └── web/
├── extensions/                 # 扩展插件
│   ├── matrix/
│   ├── msteams/
│   ├── zalo/
│   ├── bluebubbles/
│   └── voice-call/
├── apps/                       # 移动和桌面应用
│   ├── ios/
│   ├── android/
│   ├── macos/
│   └── shared/
├── skills/                     # 技能模块
├── docs/                       # 文档
├── scripts/                    # 构建脚本
├── test/                       # 测试文件
├── ui/                         # UI 组件
└── packages/                   # 工作空间包

核心架构设计

分层架构

┌─────────────────────────────────────────────────────────────┐
│                     客户端层 (Client Layer)                   │
│  iOS / Android / macOS / Web UI / CLI                       │
└─────────────────────────────────────────────────────────────┘
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    网关层 (Gateway Layer)                     │
│  WebSocket Server / HTTP API / 认证 / 会话管理                │
└─────────────────────────────────────────────────────────────┘
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                   路由层 (Routing Layer)                      │
│  消息路由 / 代理解析 / 会话绑定                              │
└─────────────────────────────────────────────────────────────┘
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  渠道层 (Channel Layer)                       │
│  Telegram / WhatsApp / Discord / Slack / Signal / ...       │
└─────────────────────────────────────────────────────────────┘
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  提供商层 (Provider Layer)                    │
│  OpenAI / Anthropic / Google / 本地模型                     │
└─────────────────────────────────────────────────────────────┘

核心模块职责

CLI 模块 (src/cli/)

  • 职责: 命令行界面入口和命令分发
  • 核心文件:
    • program/build-program.ts: CLI 程序构建
    • command-registry.ts: 命令注册中心
    • deps.ts: 依赖注入工厂

网关模块 (src/gateway/)

  • 职责: 核心 API 服务器和消息中枢
  • 核心功能:
    • server-browser.ts: WebSocket 服务器
    • server-http.ts: HTTP API 服务器
    • auth.ts: 认证授权
    • server-chat.ts: 聊天状态管理

路由模块 (src/routing/)

  • 职责: 消息路由和代理选择
  • 核心文件:
    • resolve-route.ts: 路由解析引擎
    • session-key.ts: 会话密钥生成

配置模块 (src/config/)

  • 职责: 配置文件加载和管理
  • 特性:
    • 支持 JSON5 格式
    • 环境变量替换
    • 配置文件包含 ($include)
    • 原子写入和备份

消息流与路由机制

消息流程图

┌──────────┐   消息接收    ┌──────────┐   路由解析    ┌──────────┐
│  渠道监听器  │ ────────▶ │  路由器   │ ────────▶ │  代理解析  │
│ (Channel) │             │ (Router) │             │ (Resolver)│
└──────────┘             └──────────┘             └──────────┘
                                                           ▼
┌──────────┐   回复发送    ┌──────────┐   AI 处理    ┌──────────┐
│  渠道发送器  │ ◀─────── │  会话管理  │ ◀─────── │  AI Provider│
│ (Sender)  │             │ (Session) │             │ (Provider)│
└──────────┘             └──────────┘             └──────────┘

路由解析优先级

路由解析器按照以下优先级匹配代理绑定:

  1. binding.peer - 特定用户/群组绑定
  2. binding.peer.parent - 父级群组继承(用于线程)
  3. binding.guild - Discord 服务器绑定
  4. binding.team - 团队绑定
  5. binding.account - 账户绑定
  6. binding.channel - 渠道绑定
  7. default - 默认代理

会话密钥结构

sessionKey = buildAgentSessionKey({
  agentId,           // 代理 ID
  channel,           // 渠道 ID
  accountId,         // 账户 ID
  peerKind,          // 对等方类型 (user/group)
  peerId,            // 对等方 ID
  dmScope,           // DM 范围 (main/per-peer/per-channel)
  identityLinks,     // 身份链接
})

插件系统架构

插件类型

OpenClaw 支持两种插件类型:

  1. 渠道插件: 扩展新的通讯渠道
  2. 技能插件: 扩展 AI 助手能力

插件结构

extensions/<plugin-name>/
├── package.json              # NPM 包配置
├── openclaw.plugin.json      # OpenClaw 插件元数据
├── index.ts                  # 插件入口
├── src/                      # 源代码
│   ├── channel.ts           # 渠道适配器
│   ├── auth.ts              # 认证实现
│   └── config.ts            # 配置 schema
└── README.md                 # 文档

插件加载流程

  1. 发现: 扫描 extensions/ 目录
  2. 验证: 检查 openclaw.plugin.json
  3. 加载: 动态导入插件模块
  4. 初始化: 调用插件初始化函数
  5. 注册: 注册到渠道注册表

核心技术栈

运行时环境

组件 版本要求 说明
Node.js ≥22 主要运行时
Bun 最新 可选的 TypeScript 执行
TypeScript 5.x 开发语言

核心依赖

渠道集成

  • @whiskeysockets/baileys - WhatsApp Web
  • grammy - Telegram Bot API
  • @slack/bolt - Slack
  • discord.js - Discord
  • @signalapp/libsignal - Signal

Web 框架

  • hono - HTTP 服务器
  • @hono/node-server - Node.js 适配器

AI/ML

  • @anthropic-ai/sdk - Anthropic API
  • openai - OpenAI API
  • @google-cloud/vertexai - Google Vertex AI

工具库

  • zod - 数据验证
  • jiti - 动态 TypeScript 执行
  • json5 - JSON 配置解析

开发工具

  • 构建: tsdown (TypeScript 编译器)
  • 检查: oxlint (快速 linter)
  • 格式: oxfmt (代码格式化)
  • 测试: vitest (测试框架)
  • 包管理: pnpm (包管理器)

设计模式应用

依赖注入模式

目的: 解耦组件依赖,提高可测试性

// 依赖工厂 (src/cli/deps.ts)
export function createDefaultDeps(): CliDeps {
  return {
    sendMessageWhatsApp,
    sendMessageTelegram,
    sendMessageDiscord,
    // ...
  };
}

// 使用注入的依赖
export async function handleMessage(
  message: Message,
  deps: CliDeps = createDefaultDeps()
) {
  await deps.sendMessageTelegram(message);
}

策略模式

目的: 统一接口,多种实现

渠道发送策略:

// 每个渠道独立实现
interface MessageSender {
  send(message: Message, options: SendOptions): Promise<void>;
}

class TelegramSender implements MessageSender { /* ... */ }
class WhatsAppSender implements MessageSender { /* ... */ }

Provider 策略:

interface Provider {
  baseUrl: string;
  api: "openai-completions" | "anthropic-messages";
  models: ModelDefinition[];
}

class OpenAIProvider implements Provider { /* ... */ }
class AnthropicProvider implements Provider { /* ... */ }

工厂模式

目的: 封装对象创建逻辑

// Provider 工厂
export function buildMinimaxProvider(): ProviderConfig {
  return {
    baseUrl: MINIMAX_API_BASE_URL,
    api: "openai-completions",
    models: [/* 模型列表 */],
  };
}

// 会话工厂
export function createChatRunState(): ChatRunState {
  return {
    registry: createChatRunRegistry(),
    buffers: new Map(),
    deltaSentAt: new Map(),
    abortedRuns: new Map(),
  };
}

观察者模式

目的: 事件驱动,松耦合通信

// 事件系统 (src/infra/agent-events.ts)
type AgentListener = (event: AgentEventPayload) => void;

const listeners: AgentListener[] = [];

export function onAgentEvent(listener: AgentListener) {
  listeners.push(listener);
}

export function emitAgentEvent(event: AgentEventPayload) {
  for (const listener of listeners) {
    listener(event);
  }
}

适配器模式

目的: 统一不同渠道的接口

// 渠道适配器
export type ChannelMessagingAdapter = {
  sendText: (params: SendTextParams) => Promise<void>;
  sendMedia: (params: SendMediaParams) => Promise<void>;
  editMessage: (params: EditParams) => Promise<void>;
  deleteMessage: (params: DeleteParams) => Promise<void>;
};

// 每个渠道实现适配器
const telegramAdapter: ChannelMessagingAdapter = {
  sendText: async (params) => { /* Telegram 实现 */ },
  sendMedia: async (params) => { /* Telegram 实现 */ },
  // ...
};

错误处理与容错

错误分类

// 错误代码提取
export function extractErrorCode(err: unknown): string | undefined {
  if (!err || typeof err !== "object") return undefined;
  const code = (err as { code?: unknown }).code;
  if (typeof code === "string") return code;
  if (typeof code === "number") return String(code);
  return undefined;
}

重试机制

指数退避重试:

export type RetryConfig = {
  attempts?: number;        // 默认 3 次
  minDelayMs?: number;      // 最小延迟 300ms
  maxDelayMs?: number;      // 最大延迟 30s
  jitter?: number;         // 随机抖动 0-1
  shouldRetry?: (err: unknown) => boolean;
};

// 延迟计算: delay = minDelayMs * 2 ** (attempt - 1) + jitter

渠道特定错误处理

渠道 错误处理策略
Discord 权限错误自动降级,静默失败
Signal 网络错误自动重连
WhatsApp 连接断开自动重连
iMessage 设备未激活状态检测

并发与异步处理

消息去重

// src/infra/dedupe.ts
const messageDedupe = new Map<string, MessageEntry>();

export function shouldProcessMessage(
  messageId: string,
  accountId: string
): boolean {
  const key = `${messageId}:${accountId}`;
  if (messageDedupe.has(key)) return false;

  messageDedupe.set(key, { timestamp: Date.now() });
  return true;
}

节流机制

// src/auto-reply/inbound-debounce.ts
export function createInboundDebouncer(
  channel: ChannelId,
  accountId: string
) {
  return new Debouncer({
    delayMs: resolveInboundDebounceMs(channel),
    maxPending: 10,
  });
}

活动跟踪

// src/infra/channel-activity.ts
const activity = new Map<string, ActivityEntry>();

export function recordChannelActivity(params: {
  channel: ChannelId;
  accountId?: string;
  direction: "inbound" | "outbound";
  at?: number;
}) {
  const entry = ensureEntry(params.channel, params.accountId);
  entry[`${params.direction}At`] = params.at || Date.now();
}

构建与部署

构建流程

# 安装依赖
pnpm install

# 类型检查
pnpm tsgo

# 代码检查
pnpm check

# 构建
pnpm build

# 测试
pnpm test

macOS 应用打包

# 打包 macOS 应用
scripts/package-mac-app.sh

# 签名和公证
codesign --sign ... OpenClaw.app
xcrun notarytool submit OpenClaw.app.dmg ...

架构优势总结

技术优势

特性 说明
高度模块化 清晰的模块边界,易于维护和扩展
插件化设计 支持动态扩展渠道和功能
类型安全 全面的 TypeScript 类型定义
事件驱动 松耦合的组件通信
配置驱动 通过配置文件控制行为,无需修改代码

运维优势

特性 说明
本地优先 数据存储在用户设备,保护隐私
跨平台支持 iOS、Android、macOS 原生应用
完整测试 单元、集成、E2E 测试全覆盖
生产就绪 包含错误处理、重试、降级机制

开发体验

特性 说明
快速开发 Bun 支持,毫秒级启动
代码质量 Oxlint + Oxfmt 自动检查和格式化
清晰文档 详细的代码注释和文档
开发工具 完善的 CLI 工具链

相关链接

  • OpenClaw GitHub: https://github.com/openclaw/openclaw
  • 项目文档: https://openclaw.dev