---
title: "02 · 一條訊息的旅程"
description: "拆解一條訊息從渠道進入 OpenClaw 到 Agent 回覆的完整鏈路，包括路由、session、佇列、上下文、工具和回覆分塊。"
verifiedAt: "2026-05-06"
---

你在 Telegram、Discord 或 Slack 裡發一句：“幫我查一下伺服器狀態。”

表面上看，這是一次普通聊天。實際上，這條訊息進入 OpenClaw 之後，會經過渠道標準化、路由、session 定位、佇列、上下文組裝、模型呼叫、工具迴圈、回覆投遞等多個階段。

理解這條路徑的價值很直接：以後 Agent 不回覆、回覆重複、答非所問、群聊亂觸發、長回覆切壞，你知道該查哪一層，而不是隻說“AI 壞了”。

> [!TIP]
> 這一篇的核心不是背流程，而是建立排錯順序：入口、許可權、路由、session、佇列、context，再到模型和工具。

## 1. 全鏈路先看一遍

OpenClaw 官方訊息文件把高層流程概括成：inbound message → routing/bindings → session key → queue → agent run → outbound replies。展開後可以這樣理解：

```mermaid
flowchart TD
    Inbound[外部訊息] --> Channel[Channel 標準化]
    Channel --> Policy[DM / group / mention 策略]
    Policy --> Routing[Binding 路由]
    Routing --> Session[Session key]
    Session --> Queue[Queue / steer / followup]
    Queue --> Context[Context 組裝]
    Context --> Model[模型呼叫]
    Model --> Tools{需要工具嗎}
    Tools -->|是| ToolRun[工具執行]
    ToolRun --> Context
    Tools -->|否| Reply[回覆生成]
    Reply --> Chunk[Streaming / chunking]
    Chunk --> Outbound[發回原渠道]
```

這條鏈路裡，真正需要模型參與的主要是模型呼叫和工具迴圈。前面的路由、session、佇列，大多是確定性系統邏輯。多數“訊息沒到”問題，不是模型能力問題，而是入口、路由或許可權問題。

## 2. 八個階段

| 階段 | 系統在做什麼 | 常見故障 |
| --- | --- | --- |
| Channel 標準化 | 把 Telegram、Slack、Discord 等平臺訊息轉成內部格式 | channel auth、賬號狀態、平臺 webhook |
| 訪問策略 | 判斷 DM、群組、mention、allowlist、pairing 是否允許觸發 | 群聊不回、私信被拒絕 |
| Binding 路由 | 按 channel、account、peer、team、guild 等規則選 Agent | 發給了錯誤 Agent |
| Session 定位 | 用 session key 找到對話桶和 transcript | 上下文串臺、歷史丟失 |
| Queue 處理 | 當前 session 忙時決定 steer、排隊、合併或中斷 | 回覆延遲、重複回覆 |
| Context 組裝 | 把系統提示、workspace、記憶、歷史、當前訊息拼成輸入 | 答非所問、忘記規則 |
| Agent run | 模型推理，必要時呼叫工具，多輪迴圈 | 卡住、超時、工具失敗 |
| Outbound 投遞 | 分塊、流式、執行緒回覆、發回原渠道 | 長訊息切壞、發錯執行緒 |

新手排錯時不要從第 7 階段開始。先確認前 4 個階段：訊息有沒有進來、是否允許觸發、路由到哪個 Agent、session key 是哪個。

> [!IMPORTANT]
> 多數“Agent 沒反應”的問題，不在模型，而在訊息是否進來、是否被允許觸發、是否路由到正確 Agent。

## 3. Channel 標準化：先把平臺差異抹平

不同渠道的訊息格式完全不同。Telegram 有 chat id、message id、topic；Slack 有 team、channel、thread；Discord 有 guild、channel、author、thread。Gateway 不能讓後面的 Agent 分別理解每個平臺的原始格式。

Channel 層的職責是把外部訊息統一成 OpenClaw 能處理的內部訊息，並保留必要的路由後設資料：

- sender / user id 主要影響 DM allowlist、pairing、session key。
- group / room / channel id 主要影響群組策略、binding、session key。
- thread / topic id 主要影響執行緒或 topic 隔離。
- accountId 主要影響多賬號隔離和預設賬號選擇。
- message id 主要影響去重和 reply threading。
- text / media / reply context 會進入當前 prompt、附件和引用上下文。

這一步一般不需要 AI 判斷。它越確定，後面的行為越穩定。

## 4. 訪問策略：不是每條訊息都應該觸發 Agent

訊息標準化之後，系統先判斷這條訊息有沒有資格觸發 Agent：

- 私信不回：看 DM policy、pairing、allowFrom。
- 群裡不回：看 group policy、group allowlist。
- 群裡隨便一句就觸發：看 mention gating 是否配置。
- 多賬號訊息混亂：看 accountId 和 defaultAccount。
- 執行緒回覆不對：看 thread / topic 解析和 replyToMode。

這一層的目標不是“儘量多回復”，而是“只在該回復的時候回覆”。OpenClaw 面向的是能呼叫工具的 Agent，入口預設應該收緊。

## 5. Binding 路由：模型不決定訊息給誰

OpenClaw 路由是確定性的。官方 channel routing 文件列出的匹配順序包括 exact peer、parent peer、Discord guild / roles、Slack team、account、channel、default agent 等。

```mermaid
flowchart TD
    Msg[標準化訊息] --> Exact[exact peer]
    Exact --> Parent[parent peer / thread]
    Parent --> Guild[Discord guild / roles]
    Guild --> Team[Slack team]
    Team --> Account[accountId]
    Account --> Channel[channel match]
    Channel --> Default[default agent]
```

| 路由條件 | 適合場景 |
| --- | --- |
| exact peer | 某個固定群、頻道、私信入口進指定 Agent |
| guild / roles | Discord 伺服器按角色分流 |
| teamId | Slack workspace 級分流 |
| accountId | 同一渠道多個賬號分流 |
| channel match | 所有 Telegram 或 Slack 入口統一進某 Agent |
| default agent | 沒匹配到規則時兜底 |

重要的是：路由不讓模型自由發揮。模型不應該決定“這條訊息交給誰”。如果這一步讓 AI 猜，系統就不可預測。

> [!NOTE]
> 路由越確定，系統越可審計。AI 負責生成回覆，配置負責決定訊息歸屬。

## 6. Session key：找到正確的對話桶

路由選出 Agent 之後，還要決定這條訊息屬於哪個 session。Session 是對話上下文和併發控制的基本單位。

常見 session key 形狀：

- Agent main session：`agent:{agentId}:main`。
- 群組：`agent:{agentId}:{channel}:group:{id}`。
- 頻道 / 房間：`agent:{agentId}:{channel}:channel:{id}`。
- Slack / Discord thread：在基礎 key 後追加 `:thread:{threadId}`。
- Telegram forum topic：在 group key 中包含 `:topic:{topicId}`。

session key 解決兩個問題：

- 上下文隔離：不同人、不同群、不同執行緒不要混在一起。
- 併發控制：同一個 session 同一時間只允許一個 active run。

很多“Agent 怎麼把 A 群的上下文帶到 B 群了”這類問題，本質都要回到 session key 設計。

## 7. Inbound dedupe 和 debounce

現實裡的訊息入口不乾淨。網路重連、平臺重試、使用者分多條傳送，都會讓系統收到比你想象更多的訊息。

### 7.1 去重解決重複投遞

Channel 可能重複投遞同一條訊息。OpenClaw 會用 channel、account、peer、session、message id 等資訊做短期快取，避免同一訊息觸發多次 agent run。

如果使用者說“怎麼回了兩次”，先看訊息 id 是否重複進入、channel 是否重連、Gateway 日誌是否顯示重複 run。

### 7.2 防抖解決分條傳送

使用者經常這樣發：

```text
帮我查一下
服务器状态
主要看 CPU 和内存
```

如果每一條都立刻觸發模型，系統會浪費三次呼叫，還可能因為第一條意圖不完整而答偏。`messages.inbound.debounceMs` 會把同一 sender 在短時間內的連續文本訊息合成一次 agent turn。

相關配置先記四個點：

- `messages.inbound.debounceMs`：全域性防抖視窗，預設常見寫法是 2000ms。
- `messages.inbound.byChannel.whatsapp`：WhatsApp 這類分條習慣明顯的平臺可以更長。
- media / attachments：通常立即 flush，不和純文本一樣等待。
- control commands：通常獨立處理，不應被普通訊息合併。

防抖不是越長越好。太短會重複處理，太長會讓使用者覺得系統慢。

## 8. Queue：Agent 正忙時怎麼辦

同一個 session 同時跑兩個 Agent turn 會破壞上下文一致性，所以 OpenClaw 用佇列保證同一 session 的執行被序列管理。

官方佇列文件裡，當前預設模式是 `steer`。常見模式可以這樣理解：

| 模式 | 行為 | 適合場景 |
| --- | --- | --- |
| `steer` | 把新訊息注入當前 run 的下一個模型邊界；不行就 fallback 到 followup | 使用者經常中途糾正方向 |
| `followup` | 當前 run 結束後逐條處理 | 每條訊息都應獨立響應 |
| `collect` | 當前 run 後把等待訊息合併為一次 followup | 使用者會連續補充上下文 |
| `steer-backlog` | 既嘗試 steer，也保留 followup | 需要即時性但要避免丟後續 |
| `interrupt` | 中斷當前 run，處理最新訊息 | 舊任務可拋棄的場景 |
| `queue` | legacy one-at-a-time steering | 只為相容舊行為 |

如果你看到 Agent “等很久才回”，不一定是模型慢，也可能是 session 正在排隊。看 Gateway 日誌、`openclaw status` 和任務狀態，比盲目調 prompt 更有用。

## 9. Context 組裝：AI 看到的遠不止你那句話

當訊息真正進入 Agent run，系統會把多種上下文拼起來：

- system prompt 定義執行規則、工具邊界、行為約束。
- workspace bootstrap 包括 `AGENTS.md`、`SOUL.md`、`TOOLS.md`、`USER.md` 等。
- memory 提供長期事實、偏好、近期記憶。
- session transcript 提供當前 session 歷史。
- group pending history 提供群聊中未觸發 run 但可作為背景的訊息。
- current message 是使用者這次真正要回復的內容。
- reply / forward metadata 提供被引用訊息、轉發上下文。

你發的一句話，通常只是最終輸入包的一小部分。Agent 答非所問時，不要只看使用者訊息，要看 system prompt、workspace 檔案、歷史 transcript 和 memory 有沒有汙染或缺失。

```mermaid
flowchart TD
    System[System prompt] --> Prompt[模型輸入]
    Workspace[Workspace files] --> Prompt
    Memory[Memory / notes] --> Prompt
    History[Session history] --> Prompt
    Current[Current message] --> Prompt
    Prompt --> Model[Model]
```

理解 context 組裝，是理解“為什麼同一句話有時快、有時慢、有時答偏”的關鍵。

> [!WARNING]
> Agent 答非所問時，不要只改 prompt。先看本輪 context 裡混進了什麼、缺了什麼、歷史有沒有汙染。

## 10. Agent run：模型、工具和多輪迴圈

模型第一次收到 context 後，不一定馬上給最終回覆。它可能決定呼叫工具：

1. 查狀態。
2. 讀取日誌。
3. 根據日誌再查程序。
4. 再生成結論。

每次工具結果都會回到 context，模型再決定下一步。這就是 Agent loop。

常見現象可以先這樣判斷：

- 一直轉圈：可能是工具執行慢、provider 慢、session 佇列未釋放。
- 反覆呼叫同一個工具：可能是指令不清、工具結果不足、loop detection 觸發前仍在嘗試。
- 工具失敗但 Agent 繼續：錯誤被當作工具結果回到模型，由模型決定替代路徑。
- 上下文突然變大：可能是工具輸出太長、歷史太長、workspace 檔案太重。

工具失敗不是系統崩潰。失敗資訊也是上下文的一部分。問題在於 Agent 是否能從錯誤裡找到下一步。

## 11. Streaming、chunking 和最終投遞

模型生成結果後，OpenClaw 還要把回覆發回原渠道。這裡有兩個容易混淆的概念：

- **Block streaming**：把已完成的文本塊作為正常 channel message 提前發出。
- **Preview streaming**：在 Telegram、Discord、Slack 等支援的渠道上更新臨時預覽訊息。

官方 streaming 文件強調：今天的 channel message 不是直接 token delta 流。它更像“文本塊或預覽訊息的漸進更新”。

長回覆還要做 chunking。Chunking 會尊重平臺文本長度限制，並儘量不要切壞 Markdown，尤其是 fenced code。切分順序通常從最自然到最後兜底：

1. paragraph。
2. newline。
3. sentence。
4. whitespace。
5. hard break。

如果長回覆在 Discord 或 Telegram 裡看起來很碎，先看 block streaming、chunk limits、coalescing 和 channel text limit，而不是先怪模型。

## 12. Silent reply：做了事但不打擾

OpenClaw 支援 silent reply。精確的 `NO_REPLY` / `no_reply` 表示不要發使用者可見文本。它適合內部 orchestration、群聊靜默、某些心跳或後臺事件。

但 silent reply 有邊界：

- direct conversation 預設不應悄悄吞掉所有回覆。
- 有媒體附件時，靜默文本可被去掉，但附件仍可能投遞。
- group / channel 和 internal orchestration 的預設策略不同。

使用者沒看到回覆，不一定代表 Agent 沒跑。要結合 logs、tasks、session transcript 判斷。

## 13. 常見故障怎麼定位

- 完全沒反應：優先查 Channel auth、Gateway 是否線上、DM/group policy、mention gating。
- 發給錯 Agent：優先查 bindings、accountId、peer、default agent。
- 上下文串臺：優先查 session key、thread/topic、dmScope、WebChat main session。
- 回覆重複：優先查 inbound dedupe、平臺重投遞、steer-backlog、block/preview 雙路徑。
- 使用者分三條導致三次回覆：優先查 inbound debounce 配置。
- Agent 很慢：優先查 context 大小、provider、工具耗時、session queue。
- 長回覆切得難看：優先查 chunk limit、block streaming、code fence、channel 限制。
- 群裡不該回復卻回覆：優先查 group allowlist、mentionPatterns、activation gating。

按階段定位，比調 prompt 更可靠。

## 14. 給 Agent 的實踐任務

如果你已經有 OpenClaw 環境，可以讓本地 Agent 幫你檢查訊息路徑：

```text
请只读检查 OpenClaw 消息管道：
1. 查看 openclaw status 和 gateway status，确认 Gateway 是否在线。
2. 读取 openclaw.json，列出 messages.inbound、messages.queue、bindings、channels 的关键设置。
3. 不打印任何 token、botToken、secret、auth profile。
4. 解释一条 Telegram 或 Slack 消息会路由到哪个 Agent，以及 session key 大概如何形成。
5. 如果当前配置有群聊入口，检查 allowlist、mention gating 和 pairing 边界。
```

沒有本地環境時，就讓 Agent 讀官方 messages、channel routing、queue、streaming 文件，按你的目標渠道生成一份排錯表。

## 15. 本章自檢

讀完這一章，你應該能回答：

1. 一條訊息進入 OpenClaw 後，哪幾步不需要模型參與？
2. Binding 路由為什麼必須是確定性的？
3. session key 解決了哪兩個問題？
4. dedupe、debounce、queue 分別解決什麼問題？
5. Agent 答非所問時，為什麼要檢查 context 而不是隻改使用者 prompt？
6. block streaming 和 preview streaming 有什麼區別？

## 16. 接下來去哪

<Cards>
  <Card href="/zh-Hant/docs/openclaw/understanding/03-agent-brain" title="03 · Agent 的大腦" description="繼續看模型如何在推理、工具呼叫、觀察結果和最終回覆之間迴圈。" />
  <Card href="/zh-Hant/docs/openclaw/understanding/01-ai-home" title="01 · 給 AI 一個家" description="回到 OpenClaw 的整體心智模型，理解 Gateway、Agent、Workspace 和 Channel 的分工。" />
  <Card href="/zh-Hant/docs/openclaw/official/01-gateway-runtime/channels" title="官方教程：Channels" description="對照官方配置口徑繼續看 channel、account、routing 和訊息入口。" />
</Cards>

## 17. 官方資料

- Messages：[https://docs.openclaw.ai/concepts/messages](https://docs.openclaw.ai/concepts/messages)
- Channel routing：[https://docs.openclaw.ai/channels/channel-routing](https://docs.openclaw.ai/channels/channel-routing)
- Command queue：[https://docs.openclaw.ai/concepts/queue](https://docs.openclaw.ai/concepts/queue)
- Streaming and chunking：[https://docs.openclaw.ai/concepts/streaming](https://docs.openclaw.ai/concepts/streaming)
