Skip to content

第二章 整體架構解析

在第一章,我們從設計哲學的角度理解了 OpenClaw 的核心定位:本地優先、智能體循環、工具驅動。這些選擇回答了"爲什麼"的問題。

現在我們要回答"是什麼"的問題——這些設計是如何在代碼層面落地的?當你啓動 openclaw gateway 後,系統內部到底在發生什麼?

1. 從一個問題開始

想象一下這個場景:

你正在使用 OpenClaw,突然遇到了奇怪的行爲。你讓它"查找項目裏所有 TODO 註釋",它卻回覆"我找不到任何文件"。你知道項目裏明明有幾十個 TODO,問題出在哪裏?

作爲用戶,你只能換個說法再試一次。但如果你理解架構,你就能定位問題:

  • 是 Gateway 沒有正確接收你的消息?
  • 是 Command Queue 把消息路由到了錯誤的會話?
  • 是 Agent 調用了 Glob 但模式匹配失敗?
  • 還是 LLM 返回的結果解析出錯?

這就是本章的目標:從"再試一次"到"我知道爲什麼"。


2. 架構全景:WebSocket Gateway

OpenClaw 採用 WebSocket Gateway 架構,核心組件包括:

  ┌─────────────────────────────────────────────────────────────┐
  │                      Clients                                │
  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
  │  │  Control UI │  │    CLI      │  │   Web Dashboard     │  │
  │  │   (macOS)   │  │  (Terminal) │  │    (Browser)        │  │
  │  └─────────────┘  └─────────────┘  └─────────────────────┘  │
  └─────────────────────────────────────────────────────────────┘

                                │ HTTP / WebSocket

  ┌─────────────────────────────────────────────────────────────┐
  │                     Gateway (WebSocket)                     │
  │ ┌─────────────────────────────────────────────────────────┐ │
  │ │              Message Router & Session Mgr               │ │
  │ └─────────────────────────────────────────────────────────┘ │
  └─────────────────────────────────────────────────────────────┘
         ▲                    ▲                    ▲
         │                    │                    │
  ┌─────────────┐    ┌─────────────┐    ┌─────────────────────┐
  │  Telegram   │    │   Discord   │    │  WhatsApp (Baileys) │
  │   Channel   │    │   Channel   │    │      Channel        │
  │  (extension)│    │  (extension)│    │    (built-in)       │
  └─────────────┘    └─────────────┘    └─────────────────────┘
         ▲                    ▲                    ▲
         │                    │                    │
     Telegram            Discord API           WhatsApp Web
      Bot API            (HTTP/WebSocket)       (WebSocket)

                              │ node.invoke (WebSocket)

  ┌─────────────────────────────────────────────────────────────┐
  │                      Nodes (Device Agents)                  │
  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
  │  │  macOS Node │  │   iOS Node  │  │   Android Node      │  │
  │  │(system.run) │  │(camera.snap)│  │  (screen.record)    │  │
  │  └─────────────┘  └─────────────┘  └─────────────────────┘  │
  └─────────────────────────────────────────────────────────────┘

一條消息的典型生命週期:

  1. 用戶通過 Telegram/Discord/Slack 等渠道發送消息
  2. Gateway 接收消息,通過對應平臺的 SDK 處理
  3. 消息進入 Command Queue,按會話排隊
  4. Agent 取出消息,進入 Agent Loop 進行決策
  5. 需要時調用 LLM,需要時調用工具(read、write、edit、exec)
  6. 結果通過 Gateway 返回給用戶

3. Gateway:統一入口與多平臺接入

3.1 爲什麼需要 Gateway

Gateway 是 OpenClaw 的唯一入口點,負責管理所有消息渠道和控制平面客戶端。

如果沒有 Gateway,每個渠道都需要獨立的連接管理、身份驗證和消息處理邏輯,這會導致:

  • 複雜度爆炸:每加一個渠道,核心代碼都要改一次
  • 狀態分散:WhatsApp 會話、Telegram 連接分散管理
  • 安全風險:多個入口點意味着多個攻擊面

Gateway 通過統一 WebSocket 接口解決了這些問題。

3.2 多平臺接入

OpenClaw 直接使用各平臺的 SDK 接入,而非自行實現協議:

平臺接入方式
TelegramWebhook / 長輪詢
DiscordWebSocket
SlackEvents API / WebSocket
WhatsAppWebSocket
WebChatWebSocket

這些 SDK 負責處理平臺特定的協議細節,Gateway 專注於消息路由和會話管理。

3.3 連接模式與內網部署

不同渠道的接入方式差異很大:

模式原理實時性公網要求
Webhook平臺主動 HTTP 請求需要公網地址
WebSocketGateway 主動保持長連接不需要
長輪詢Gateway 定期查詢不需要

對於 Webhook 模式,大多數個人用戶沒有公網服務器。解決方案包括:

  • Tailscale:推薦方案,建立加密 mesh 網絡
  • SSH 隧道:建立端口轉發隧道

這讓 OpenClaw 可以安全地運行在內網服務器甚至筆記本上,而不需要公網 IP。

3.4 身份識別與會話隔離

Gateway 負責進行路由尋址。不同平臺的用戶 ID 格式各異,但都遵循統一規範:

  • agent:main:telegram:123456789🧵42 - Telegram 話題線程
  • agent:main:discord:channel:987654321 - Discord 頻道
  • agent:main:whatsapp:dm:+15551234567 - WhatsApp 私聊
  • agent:ops:slack:cron:job:daily-report:run:uuid - Cron 任務會話

這個統一的身份標識決定了消息進入哪個會話(Session),是實現多用戶隔離的基礎。不同用戶的消息被路由到獨立的處理隊列中,不會混淆。


4. Command Queue:命令隊列與併發控制

4.1 爲什麼需要 Command Queue

直接讓 Gateway 調用 Agent 會有三個問題:

問題後果Command Queue 的解決
併發衝突多個消息同時處理導致資源競爭按會話序列化處理
無緩衝高峯期消息湧入導致崩潰提供隊列緩衝
難以控制無法控制並行度可配置併發上限

Command Queue 是一個進程內隊列,基於"泳道"模型實現併發控制,純 TypeScript 實現,無外部依賴。

4.2 泳道模型:併發與順序的平衡

Command Queue 的核心設計是 泳道模型

  泳道內:串行保證(按 Session Key)       泳道間:並行處理
  ┌──────────────────────────┐            ┌──────────┐ ┌──────────┐
  │ Session A 的消息隊列      │            │ 泳道 A   │ │ 泳道 B   │
  │ ──────────────────────── │            │(SessionA)│ │(SessionB)│
  │ 1. 創建 report           │            │ ──────── │ │ ──────── │
  │ 2. 寫入內容 ←─────────────┼── 排隊等待  │ 長任務   │ │ 短查詢   │
  └──────────────────────────┘            │ (5分鐘)  │ │ (1秒)    │
                                          │ ──────── │ │ ──────── │
                                          │          │ │ 立即響應 │
                                          └──────────┘ └──────────┘

泳道內的串行保證:同一用戶的消息按順序處理。比如用戶連續發送"創建 report.txt"和"寫入內容",第二條會等待第一條完成後再執行,防止因文件不存在而失敗。

泳道間的並行處理:不同用戶互不等待。Session A 的 5 分鐘代碼分析不會阻塞Session B 的天氣查詢。

4.3 消息處理方式

Command Queue 支持多種消息處理方式,可通過配置或命令切換:

方式行爲適用場景
collect(默認)合併所有隊列消息爲單條跟進大多數場景
steer立即注入當前運行需要實時干預
followup排隊等待下一輪順序處理
steer-backlog立即注入 + 保留跟進複雜交互
steer+backlog與 steer-backlog 類似複雜交互
queue標準隊列模式順序處理
interrupt中斷當前運行緊急干預

配置示例(openclaw.json):

json5
{
  messages: {
    queue: {
      mode: "collect",
      debounceMs: 等待毫秒數,
      cap: 隊列長度上限,
      drop: "summarize",
      byChannel: { discord: "collect" },
    },
  },
}

會話內臨時切換:發送 /queue steer/queue collect

4.4 隊列選項

  • debounceMs:等待安靜期後開始處理(防止"繼續、繼續"的連續消息)
  • cap:每會話最大隊列長度
  • drop:溢出策略(old 丟棄舊消息 / new 丟棄新消息 / summarize 生成摘要)

5. Agent:決策核心與 Agent Loop

5.1 不是腳本,是循環

消息通過 Command Queue 後,到達系統的"大腦"——Agent。Agent 是 OpenClaw 最核心的組件,負責理解用戶需求、規劃任務、選擇工具、協調執行。

傳統的程序是線性的:輸入、處理、輸出。Agent 不是線性的,它是循環的。這個循環被稱爲 Agent Loop(智能體循環)。

Agent Loop 的工作流程:

        ┌──────────┐
        │  觀察     │◄──────────────────────────┐
        │ (Observe)│                           │
        └────┬─────┘                           │
             │ 接收當前狀態                      │
             │ (用戶輸入、工具結果、環境信息)       │
             ▼                                 │
        ┌──────────┐     ┌──────────┐          │
        │  思考     │────►│  行動    │          │
        │ (Think)  │     │  (Act)   │          │
        └──────────┘     └────┬─────┘          │
                              │                │
                              │ 執行決策        │
                              │ (調用工具/回覆)  │
                              └────────────────┘

循環持續進行,直到:

  • 任務完成 → 生成最終回覆
  • 遇到錯誤 → 無法繼續
  • 達到最大循環次數 → 強制終止

這就是 OpenClaw 能處理複雜任務的原因。它不是一次性生成答案,而是像人類一樣,一步步探索、驗證、調整,直到達成目標。

5.2 工具選擇:如何讓 LLM 做出正確決策

在每次思考階段,Agent 需要讓 LLM 選擇工具。Agent 會把當前狀態、可用工具列表(包含每個工具的名稱、描述和參數格式)發送給 LLM,LLM 根據任務需求選擇最合適的工具並生成參數。

這個過程面臨的三個挑戰:

挑戰問題描述解決方案
描述質量LLM 根據描述理解工具,模糊描述導致錯誤選擇精心設計工具描述
上下文限制工具多時佔用大量上下文空間智能選擇展示哪些工具
幻覺錯誤LLM "幻覺"出不存在的工具或格式錯誤驗證白名單,錯誤反饋

5.3 狀態管理:記憶的維護

Agent 需要維護狀態才能進行多輪推理。狀態包括:

  • 對話歷史:用戶和 Agent 之前的交互記錄,作爲短期記憶讓 Agent 理解上下文
  • 工具結果:最近調用的工具及其返回值,成爲下一次思考的依據
  • 環境信息:當前工作目錄、系統狀態、用戶偏好等

狀態管理的一個核心挑戰是上下文窗口限制。LLM 能處理的文本長度是有限的(比如 4K、8K、128K Token)。當對話變長或任務變複雜時,狀態可能超出這個限制。

Agent 採用了幾種策略來應對:

  • 截斷:丟棄或壓縮最舊的對話歷史,重點保留最近的若干輪
  • 摘要:對早期的對話進行壓縮,用更短的文本保留關鍵信息
  • 提取:將重要的事實(如用戶偏好)提取出來,存儲到長期記憶(MEMORY.md)中

5.4 安全邊界

Agent 具有調用工具執行任意操作的能力,這既是優勢也是風險。OpenClaw 設計了三層安全機制:

  • Security 模式deny / allowlist / full 三級控制
  • Ask 模式off / on-miss / always 確認級別
  • Safe Bins:stdin-only 工具限制

6. LLM 集成與錯誤處理

6.1 多模型支持

Agent 做出了決策,但它需要調用外部的 LLM 來獲得推理能力。

OpenClaw 支持接入多種 LLM,包括 OpenAI 的 GPT 系列、Anthropic 的 Claude、Google 的 Gemini,以及本地模型。系統負責屏蔽它們的差異:

  • 封裝不同的 API 格式
  • 適配不同的能力(有的支持函數調用,有的不支持)
  • 管理故障轉移(當主模型不可用時自動切換到備用模型)

6.2 錯誤處理與自愈

LLM 的輸出是不確定的,經常會遇到各種問題。系統實現三層錯誤自愈機制:

問題處理方式示例
格式錯誤自動修復{ "tool": "bash" → 補全 }
模型故障切換認證檔案或使用備用模型換一個Key或換一個模型
網絡超時指數退避重試自動重試

這種機制讓 OpenClaw 在面對不穩定的模型輸出時,依然能保持極高的任務成功率。

6.3 Token 管理與成本控制

每次調用 LLM 都會產生 Token 消耗,系統從四個方面管理成本:

策略作用
用量統計記錄每次調用的 input/output Token
預算控制設置上限,接近時發出警告
提示詞壓縮壓縮舊對話,保留新消息
響應緩存緩存重複查詢,避免重複調用

7. 場景化理解:當 things go wrong

理解了架構之後,讓我們看看幾個真實場景中如何定位問題。

場景一:消息沒有響應

你發送了一條消息,Agent 完全沒有反應。

排查思路

  1. 檢查 Gateway:日誌中是否收到了消息?如果沒有,檢查網絡連接和渠道配置。
  2. 檢查 Command Queue:消息是否進入了正確的泳道?隊列是否堆積?
  3. 檢查 Agent:是否正在處理其他消息?是否陷入了長時間循環?

常見原因

  • Gateway 的 WebSocket 連接斷開,沒有重連成功
  • Command Queue 已滿,新消息被延遲處理
  • Agent 正在處理一個耗時任務,你的消息在泳道中排隊等待
場景二:響應非常慢

一條簡單的查詢等了十幾秒纔回復。

排查思路

  1. Gateway 到 Queue:通常是毫秒級,不會是瓶頸
  2. Queue 排隊:檢查是否有其他消息在隊列中等待
  3. Agent 處理:檢查 Agent Loop 輪數,是否在反覆嘗試
  4. LLM 調用:檢查 LLM 的響應時間,是否模型過載

常見原因

  • LLM 服務響應慢(尤其是高峯期)
  • Agent 陷入工具調用的循環,反覆嘗試失敗的命令
  • 上下文過長,每次調用都攜帶大量歷史記錄
場景三:工具選擇錯誤

你讓它查找文件,它卻一直用 Bash 運行 find 命令,而不是更適合的 Glob。

排查思路

  1. 工具描述:系統提示詞中 Glob 的描述是否清晰?
  2. 上下文限制:是否因爲工具太多,Glob 沒有被展示給 LLM?
  3. 歷史慣性:是否之前的對話讓 LLM 形成了使用 Bash 的習慣?

解決方案

  • 在 TOOLS.md 中明確描述 Glob 的適用場景
  • 如果工具太多,考慮精簡可用工具列表
  • 在對話中明確提示"請使用 Glob 工具"

8. 組件協作示例

消息旅程(用戶發送:"查找所有包含 TODO 的 Python 文件"):

Step 1: Gateway          Step 2: Command Queue     Step 3: Agent (Loop)
───────────────          ───────────────────       ─────────────────────
Telegram SDK ─────▶      確定會話標識              第1輪:觀察 → 思考 → 行動
提取消息內容      ───▶    放入隊列 ─────────▶       (調用Glob) 得50個文件
                         調度給Agent               第2輪:觀察 → 思考 → 行動
                                                   (調用Grep) 得12個匹配
                                                   第3輪:觀察 → 思考 → 行動
                                                   任務完成,生成回覆

Step 4: Command Queue    Step 5: Gateway
───────────────────      ───────────────
回覆放入隊列  ─────────▶   通過 Telegram SDK
                          發送給用戶

異常處理

  • Gateway 網絡問題 → 重試或返回錯誤
  • Queue 溢出 → 根據 drop 策略處理
  • Agent 死循環 → Tool Loop Detection 終止
  • LLM 拒絕 → 錯誤自愈重試

9. 消息通信格式

Gateway 與客戶端之間的通信使用標準的消息格式:

typescript
type 消息類型 = "lifecycle" | "tool" | "assistant" | "error" | (string & {});

type 消息內容 = {
  runId: string;           // 運行ID
  seq: number;             // 序列號(嚴格遞增)
  stream: 消息類型;         // 消息類型
  ts: number;              // 時間戳(毫秒)
  data: Record<string, unknown>; // 消息數據
  sessionKey?: string;     // 會話標識
};

消息類型說明:

  • lifecycle:運行生命週期事件(開始、結束)
  • tool:工具調用事件
  • assistant:助手回覆事件
  • error:錯誤事件
  • compaction:狀態壓縮事件
  • (string & {}):允許擴展其他自定義消息類型

10. 本章小結

通過這一章,我們從架構層面理解了 OpenClaw 的核心組件:

組件核心職責解決的關鍵問題
GatewayWebSocket 網關,管理所有渠道連接統一入口、多平臺接入、身份識別
Command Queue命令隊列,按會話序列化處理併發控制、順序保證、流量緩衝
Agent理解需求、規劃任務、選擇工具Agent Loop 決策、狀態管理、安全邊界
LLM 集成連接多種模型,處理錯誤與重試多模型適配、錯誤自愈、Token 管理

這些組件通過定義良好的協議協同工作,構成了 OpenClaw 的"數字大腦"。

架構設計的核心洞察

OpenClaw 的架構體現了"關注點分離"的設計原則。每個組件只負責一件事,並且把這件事做好:

  • Gateway 只關心如何接收和路由消息,不關心消息如何處理
  • Command Queue 只關心如何排隊和調度,不關心消息內容是什麼
  • Agent 只關心如何決策和行動,不關心消息從哪裏來
  • LLM 集成 只關心如何調用模型,不關心調用的結果如何使用

這種分離帶來了極大的靈活性。你可以:

  • 接入新的渠道,而不影響其他組件
  • 使用不同的 LLM,Agent 的邏輯完全不用修改
  • 在一臺機器上運行多個實例,共享同一個 Gateway

理解了這個架構,你就能診斷問題發生在哪個環節:

  • 消息沒收到是 Gateway 的問題
  • 消息沒處理是 Queue 或 Agent 的問題
  • 回覆質量差是 LLM 或 Agent 的問題

在下一章,我們將深入 Agent 的"靈魂"——提示詞系統。你會看到 SOUL.md、USER.md、TOOLS.md 等文件如何被組合成系統提示詞,熱更新機制如何讓修改立即生效,以及如何通過調整提示詞精細控制 Agent 行爲。