A
返回 AI 知識
AI 知識2026/05/13 君澤智庫研究員 Bryan Chan19 分鐘閱讀

跨渠道記憶中樞(Memory Hub):OpenClaw Agent 的記憶系統架構設計全紀錄

從「每日遺忘」到「跨渠道自動整合」:完整記錄 UltraClaw 記憶系統的架構演進、Session 隔離問題、時區邊界 Bug、三層防護機制,以及 Cron 自動化整合管線。

緣起:為什麼 Agent 每天都會「忘記」?

凌晨 4:00,Auto-Dream Cron Job 如期運行。它檢查了過去三天的 daily log,發現所有檔案都已經標記了 <!-- consolidated -->,然後報告:

🌙 No new content today — skipped consolidation

但事實是:當日用戶在微信與 Agent 進行了 35 條對話,涵蓋電郵監控修復、DBS 銀行搜索、新材料上市公司調研、搜索引擎配置、Cross Search 插件設計等大量任務。

所有這些對話都完整保存在 Session Log(185MB, 380+ 檔案)中,但沒有一條被寫入結構化的 Daily Log

這不是單一 Bug,而是一個系統性的架構缺陷。本文完整記錄了從發現問題到建立完整解決方案的過程。


一、問題全景:三個層面的系統性缺陷

經過完整調查,我們發現了三個獨立但互相疊加的技術問題:

1.1 架構層面:跨渠道 Session 隔離

OpenClaw 使用 dmScope: "per-channel-peer" 配置,每個渠道(飛書、微信、WhatsApp)生成完全獨立的 Session:

微信 Session (249c2bce)    飛書 Session (9780b3c4)    WhatsApp Session
      │                           │                        │
  Agent 微信分身              Agent 飛書分身            Agent WA 分身
      │                           │                        │
   只看到微信對話              只看到飛書對話           只看到 WA 對話
      │                           │                        │
  ❌ 不知道飛書做了什麼        ❌ 不知道微信做了什麼      ❌ 不知道任何渠道

關鍵發現: sessions_list API 只能返回當前渠道的 Session。即使微信有 101 個歷史 Session,飛書 Agent 調用 API 時返回 0 個微信 Session。

1.2 流程層面:Daily Log 寫入無強制機制

Daily Log 寫入依賴 Agent 自願執行。AGENTS.md 有「做完就寫」的規則,但當 Agent 專注於實際任務(寫 Code、部署、分析數據)時,Context Window 被工作內容填滿,「寫日誌」這個 Meta-Task 自然被忽略。

數據證明了這一點:

指標 Session Log Daily Log 流失率
檔案數量 380 6 98.4%
總大小 185MB ~15KB 99.99%
當日內容 178 次交流 2 條記錄 98.9%

1.3 實作層面:時區邊界 Bug

Cron Job 運行在 HKT 時區,Session JSONL 使用 UTC 時間戳。在 HKT 00:00-08:00 期間,UTC 日期仍是前一天:

HKT:  May 12 22:00 ──────── May 13 00:00 ──────── May 13 08:00
UTC:  May 12 14:00 ──────── May 12 16:00 ──────── May 13 00:00
       │                      │
  用戶在微信聊天          Cron 運行,grep "2026-05-13"
  Session: "2026-05-12"   但 Session 全是 "2026-05-12"
                          → 0 match → 漏!

二、記憶架構設計:三層模型

為解決上述問題,我們設計了一個三層記憶模型,每層有不同的儲存格式、寫入機制和保障策略:

┌─────────────────────────────────────────────────┐
│ 第1層:Session Log(系統自動保存)                │
│ agents/main/sessions/*.jsonl · 185MB · 380 files │
│ ✅ 每次對話自動保存,完整無遺漏                    │
│ ⚠️ 原始 JSONL 格式,需要程式化讀取               │
├─────────────────────────────────────────────────┤
│ 第2層:Daily Log(跨渠道手動/自動整合)            │
│ memory/daily/YYYY-MM-DD.md · Markdown            │
│ ⚡ 三層防護:任務即寫 → Session 檢查 → Cron 兜底  │
│ 📝 結構化 Markdown,人類可讀                      │
├─────────────────────────────────────────────────┤
│ 第3層:MEMORY.md(長期記憶整合)                   │
│ MEMORY.md · 凌晨 4:00 自動整合                   │
│ 🧠 只合併已 consolidated 的 daily log             │
│ 🔴 若第2層空白 → 第3層也空白(致命依賴)           │
└─────────────────────────────────────────────────┘

關鍵設計決策

為什麼不把所有渠道合併到一個 Session?

去掉 per-channel-peer 會導致不同渠道的上下文混雜。例如微信的工作對話和飛書的技術討論會互相污染 Context Window,反而降低效率。

為什麼不讓 Auto-Dream 直接讀 Session Log?

Session Log 是原始 JSONL(185MB),包含大量 Tool Call、System Event、Model Change 等噪音。直接從中提取有意義的用戶對話需要複雜的 NLP 處理,不如在寫入 Daily Log 時就做好結構化。


三、三層防護機制

為確保 Daily Log(第2層)不再遺漏,我們設計了三層防護,每層有不同的觸發時機和可靠性:

層級 觸發時機 執行者 優點 缺點
1️⃣ 任務級 每完成一個有意義任務後立即 當前 Session Agent 有上下文,最準確 依賴 Agent 自律
2️⃣ Session 結束 回覆最後一條用戶消息前 當前 Session Agent 剛做完,記憶猶新 可能忘記
3️⃣ Cron 兜底 每 2 小時自動運行 獨立 Isolated Session 自動化,不遺漏 無上下文,只能提取文字摘要

觸發規則:什麼是「有意義的任務」?

✅ 必須寫入:
- 部署網站、修復 Bug
- 撰寫報告、分析數據
- 創建/修改檔案、配置系統
- 搜索 + 整理資訊
- 安裝/設定工具、建立 Cron Job
- 任何耗費 >2 個 Tool Call 的操作

❌ 不需寫入:
- 簡單問答(「早晨」「OK」)
- 純閒聊

設計原則:防禦深度

任務即寫 (Layer 1) ──→ 漏了?
Session 檢查 (Layer 2) ──→ 又漏了?
Cron 兜底 (Layer 3) ──→ 絕不漏!

四、跨渠道整合管線

4.1 為什麼不能用 API?

dmScope: "per-channel-peer" 限制了 sessions_list API 只能返回當前渠道的 Session。從飛書無法發現微信的 Session。

4.2 解決方案:檔案系統級別掃描

Cron Job 直接讀取 agents/main/sessions/*.jsonl 檔案:

  • find -mmin -240 找最近 4 小時修改過的 Session
  • 用 Pattern Matching 識別渠道(先檢查微信/WhatsApp,最後檢查飛書避免誤判)
  • 提取用戶訊息,寫入共享 Daily Log

4.3 渠道識別策略

渠道 識別 Pattern 優先級
微信 openclaw-weixin@tencent-weixin 最高
WhatsApp whatsapp
飛書 feishuou_142d6f(排除以上) 最低

⚠️ 踩坑教訓: 不能直接用 ou_142d6f... 識別飛書,因為微信 Session 的 Delivery Config 中也包含此 ID(Cron Job 會引用它)。必須用排他性順序匹配。

4.4 完整管線架構

 微信 Agent          飛書 Agent          WhatsApp Agent
     │                    │                     │
     │  ① 做完即寫        │  ① 做完即寫         │  ① 做完即寫
     │                    │                     │
     └──────────┬─────────┴──────────┬──────────┘
                │                    │
          共享 Daily Log      ② Cron 每2h 跨渠道掃描
     (memory/daily/YYYY-MM-DD.md)  ← 檔案系統讀取
                │              所有渠道 Session JSONL
          ③ 凌晨4:00 Auto-Dream
                │
            MEMORY.md(長期記憶)

五、時區邊界問題深度分析

5.1 問題重現

Cron Job 在 HKT 00:01 運行,執行以下邏輯:

# 原始程式碼(有 Bug)
if grep -q "$(date +%Y-%m-%d)" "$SESSION_FILE"; then
  echo "ACTIVE"
fi

此時:

  • date +%Y-%m-%d 輸出 2026-05-13(HKT)
  • Session JSONL 的時間戳是 2026-05-12T14:34:00Z(UTC)
  • grep "2026-05-13"0 個匹配
  • 結論:「無活躍 Session」→ 漏!

5.2 為什麼要 8 小時?

HKT 比 UTC 快 8 小時(UTC+8)。這意味著每天的 00:00-08:00 HKT,UTC 還在「昨天」。這 8 小時的窗口內,所有基於日期的 Session 匹配都會失效。

HKT 00:00 → UTC 還停留在前一天 16:00
HKT 04:00 → UTC 還停留在前一天 20:00
HKT 07:59 → UTC 還停留在前一天 23:59
HKT 08:00 → UTC 終於到了今天 00:00 ✅

5.3 修復方案:三日期匹配

# 修正後的程式碼
HKT_TODAY=$(TZ='Asia/Hong_Kong' date +%Y-%m-%d)
UTC_TODAY=$(date -u +%Y-%m-%d)
UTC_YESTERDAY=$(date -u -v-1d +%Y-%m-%d)

if grep -qE "$HKT_TODAY|$UTC_TODAY|$UTC_YESTERDAY" "$SESSION_FILE"; then
  echo "ACTIVE"  # 覆蓋所有時區邊界情況
fi

三個日期的 OR 匹配確保無論 Cron 何時運行,至少一個日期能命中 Session 中的時間戳。

5.4 額外修復:find -newer 依賴問題

原始的 find -newer memory/daily/$(date +%Y-%m-%d).md 在當日 Daily Log 尚未建立時行為不確定。改用:

find ... -mmin -240  # 過去 4 小時內修改過的檔案(無外部依賴)

六、Cron 管線設計

6.1 兩個 Cron Job 的分工

Cron Job 頻率 功能 Timeout
daily-log-autocheck 每 2 小時 跨渠道掃描 Session → 補寫 Daily Log 300s
auto-memory-dream 每日 04:00 從 Daily Log 整合 → MEMORY.md + 推送報告 600s

6.2 每日運行時間線(HKT)

00:00 ─ autocheck
02:00 ─ autocheck
04:00 ─ autocheck + auto-memory-dream(雙重保險)
06:00 ─ autocheck
08:00 ─ autocheck
10:00 ─ autocheck
12:00 ─ autocheck
14:00 ─ autocheck
16:00 ─ autocheck
18:00 ─ autocheck
20:00 ─ autocheck
22:00 ─ autocheck

每日 13 次記憶檢查,確保 2 小時內的對話不遺漏。

6.3 Autocheck 執行流程

Step 1: 計算三個日期 (HKT_TODAY + UTC_TODAY + UTC_YESTERDAY)
    ↓
Step 2: find -mmin -240 找最近 4 小時活躍 Session
    ↓
Step 3: 三日期 grep 過濾(時區安全)
    ↓
Step 4: Pattern Match 識別渠道(排他性順序)
    ↓
Step 5: 提取用戶訊息 → 追加到 Daily Log(追加模式)
    ↓
Step 6: 靜默結束(無新內容不報告)

七、系統監控與健康指標

7.1 健康檢查項目

指標 檢查方式 正常值
Daily Log 存在 ls memory/daily/$(date +%Y-%m-%d).md 必須存在
Daily Log 大小 wc -c >500 bytes
Session 涵蓋率 對比 Session 數量 vs Daily Log 條目 >80%
Cron 運行狀態 openclaw cron list lastRunStatus = ok
Dream Streak dream-log.md 連續天數

7.2 當前狀態

在本次修復完成後:

  • 📊 記憶庫:~370 條記錄
  • 🏥 健康度:75/100(之前因 Daily Log 缺失偏低,將逐步回升)
  • 🔥 Dream Streak:24 天連續
  • ⏱️ 記憶延遲:從「完全遺漏」降至 <2 小時

八、踩坑全記錄

本次記憶系統建設過程中遇到的 6 個關鍵問題:

# 問題 嚴重度 根因 修復
1 Session 結束無 Checkpoint 致完全失憶 🔴 致命 Meta-task 無自動觸發 三層防護機制
2 誤判微信 Plugin 狀態 🔴 高 Config warning ≠ 實際狀態 先查數據再下結論
3 sessions_list API 跨渠道盲點 🔴 高 per-channel-peer 隔離 檔案系統直接讀取
4 Channel Pattern 誤判 🟡 中 匹配順序不排他 排他性順序
5 UTC/HKT 時區邊界漏失 🔴 致命 單日期 grep 三日期 OR 匹配
6 find -newer 依賴不存在檔案 🟡 中 外部檔案依賴 -mmin -240

核心設計原則總結

原則 說明
防禦深度 單層失效不影響整體(三層防護)
檔案系統 > API 跨渠道時直接讀檔案,不依賴受限 API
時間範圍 > 日期比對 -mmin -240-newer 更可靠
多日期匹配 跨時區場景必須兼容 UTC 和本地時間
排他性匹配 Pattern 匹配先具體後泛化,避免誤判
先驗證再結論 Config warning ≠ 實際狀態,先查數據

九、與 OpenClaw Auto-Dream 的協作

Memory Hub 是 Auto-Dream 的前置保障層

  • Memory Hub → 確保 Daily Log 完整(多渠道 + 跨日邊界)
  • Auto-Dream → 從完整 Daily Log 整合入長期記憶
Memory Hub(第2層保障)         Auto-Dream(第3層整合)
┌──────────────────────┐       ┌──────────────────────┐
│ 跨渠道掃描           │       │ 讀取 Daily Log       │
│ 時區安全             │  ──→  │ 提煉關鍵決策         │
│ 自動補寫             │       │ 更新 MEMORY.md       │
│ 2小時內保證完整      │       │ 推送整合報告         │
└──────────────────────┘       └──────────────────────┘

兩者協作形成完整記憶管道:從 Session Log → Daily Log → MEMORY.md,從即時記錄到長期記憶,層層保障。


結語

這次 Memory Hub 的建設源於一個看似簡單的問題:「為什麼 Agent 每天都會忘記?」。深入調查後發現,這不是單一 Bug,而是架構設計、流程機制、時區處理三個層面的系統性問題疊加。

最終方案的核心思想是 防禦深度:不依賴任何單一機制,而是通過任務即寫、Session 檢查、Cron 兜底三層防護,確保無論哪層失效,下一層都會補上。

更重要的是,我們學會了 先查數據、再下結論。從 Config Warning 誤判微信 Plugin 狀態,到時區邊界 Bug 的發現,每個問題的解決都來自於直接檢查 Session JSONL 檔案的原始數據,而不是依賴表面的錯誤訊息。

這套系統目前已在 UltraClaw 上運行,每日 13 次跨渠道自動整合,等待時間的考驗。