Cross-Channel Memory Hub: A Full Record of the Memory System Architecture Design for OpenClaw Agent
Background: Why Does the Agent "Forget" Every Day?
At 4:00 a.m., the Auto-Dream Cron Job runs as scheduled. It checks the daily logs from the past three days, finds that all files have already been marked with <!-- consolidated -->, and then reports:
🌙 No new content today-skipped consolidation
But the fact is: that day the user had 35 conversations with the Agent on WeChat, covering email monitoring repairs, DBS bank searches, research on listed companies in new materials, search engine configuration, Cross Search plugin design, and many other tasks. All these conversations are fully preserved in the Session Log (185MB, 380+ files), but not a single one was written to the structured Daily Log.
This is not a single bug but a systemic architectural flaw. This article fully documents the process from discovering the problem to building a complete solution.
1. Problem Overview: Systemic Flaws at Three Levels
After a thorough investigation, we discovered three independent but compounding technical problems:
1.1 Architecture Level: Cross-Channel Session Isolation
OpenClaw uses the dmScope: "per-channel-peer" configuration, and each channel (Feishu, WeChat, WhatsApp) generates a completely independent Session:
WeChat Session (249c2bce) Feishu Session (9780b3c4) WhatsApp Session
│ │ │
Agent WeChat Clone Agent Feishu Clone Agent WA Clone
│ │ │
Only sees WeChat chats Only sees Feishu chats Only sees WA chats
│ │ │
❌ Doesn't know what Feishu did ❌ Doesn't know what WeChat did ❌ Doesn't know any channel
Key finding: The sessions_list API can only return Sessions from the current channel. Even if WeChat has 101 historical Sessions, when the Feishu Agent calls the API it returns 0 WeChat Sessions.
1.2 Process Level: No Mandatory Mechanism for Daily Log Writes
Daily Log writing depends on the Agent voluntarily doing it. AGENTS.md has a "write after finishing" rule, but when the Agent focuses on actual tasks (writing code, deploying, analyzing data), the Context Window is filled with work content, and the Meta-Task of "writing the log" is naturally ignored.
The data proves this:
| Metric | Session Log | Daily Log | Loss Rate |
|---|---|---|---|
| Number of files | 380 | 6 | 98.4% |
| Total size | 185MB | ~15KB | 99.99% |
| Daily content | 178 exchanges | 2 records | 98.9% |
1.3 Implementation Level: Time Zone Boundary Bug
The Cron Job runs in the HKT time zone, and Session JSONL uses UTC timestamps. During HKT 00:00-08:00, the UTC date is still the previous day:
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
│ │
User chats on WeChat Cron runs, grep "2026-05-13"
Session: "2026-05-12" but Session is all "2026-05-12"
→ 0 match → missed!
II. Memory Architecture Design: Three-Layer Model
To solve the above problems, we designed a three-layer memory model, where each layer has different storage formats, writing mechanisms, and safeguard strategies:
┌─────────────────────────────────────────────────┐
│ Layer 1: Session Log (system auto-saved) │
│ agents/main/sessions/*.jsonl · 185MB · 380 files │
│ ✅ Every conversation is automatically saved, complete with no omissions │
│ ⚠️ Raw JSONL format, requires programmatic reading │
├─────────────────────────────────────────────────┤
│ Layer 2: Daily Log (cross-channel manual/automatic integration) │
│ memory/daily/YYYY-MM-DD.md · Markdown │
│ ⚡ Three-layer protection: immediate task write → Session check → Cron fallback │
│ 📝 Structured Markdown, human-readable │
├─────────────────────────────────────────────────┤
│ Layer 3: MEMORY.md (long-term memory integration) │
│ MEMORY.md · Automatically integrated at 4:00 AM │
│ 🧠 Only merges already consolidated daily logs │
│ 🔴 If Layer 2 is blank → Layer 3 is also blank (fatal dependency) │
└─────────────────────────────────────────────────┘
Key Design Decisions
Why not merge all channels into a single Session?
Removing per-channel-peer will cause contexts from different channels to mix. For example, work conversations on WeChat and technical discussions on Feishu will contaminate each other's Context Window, actually reducing efficiency.
Why not let Auto-Dream read the Session Log directly?
Session Log is raw JSONL (185MB), containing a lot of noise such as Tool Call, System Event, Model Change, etc. Extracting meaningful user conversations directly from it requires complex NLP processing; it is better to structure it when writing to the Daily Log.
3. Three-Layer Protection Mechanism
To ensure Daily Log (Layer 2) no longer misses anything, we designed three layers of protection, each with different trigger timing and reliability:
| Layer | Trigger Timing | Executor | Advantages | Disadvantages |
|---|---|---|---|---|
| 1️⃣ Task-level | Immediately after completing each meaningful task | Current Session Agent | Has context, most accurate | Depends on Agent self-discipline |
| 2️⃣ Session End | Before replying to the last user message | Current Session Agent | Just finished, fresh in memory | May forget |
| 3️⃣ Cron Fallback | Automatically runs every 2 hours | Independent Isolated Session | Automated, no omissions | No context, can only extract text summaries |
Trigger Rules: What Is a "Meaningful Task"?
✅ Must write:
- Deploy websites, fix bugs
- Write reports, analyze data
- Create/modify files, configure systems
- Search + organize information
- Install/configure tools, create Cron Jobs
- Any operation that consumes >2 Tool Calls
❌ No need to write:
- Simple Q&A ("Morning", "OK")
- Pure chit-chat
Design Principle: Defense in Depth
Task-Level Write (Layer 1) ──→ Missed?
Session Check (Layer 2) ──→ Missed again?
Cron Fallback (Layer 3) ──→ Never miss!
4. Cross-Channel Integration Pipeline
4.1 Why Can't We Use the API?
dmScope: "per-channel-peer" restricts the sessions_list API to returning only Sessions from the current channel. From Feishu, WeChat Sessions cannot be discovered.
4.2 Solution: Filesystem-Level Scanning
The Cron Job directly reads agents/main/sessions/*.jsonl files:
- Uses
find -mmin -240to find Sessions modified in the last 4 hours - Uses pattern matching to identify the channel (check WeChat/WhatsApp first, and Feishu last to avoid misidentification)
- Extracts user messages and writes them to the shared Daily Log
4.3 Channel Identification Strategy
| Channel | Identification Pattern | Priority |
|---|---|---|
openclaw-weixin or @tencent-weixin | Highest | |
whatsapp | Medium | |
| Feishu | feishu or ou_142d6f (exclude the above) | Lowest |
⚠️ Lesson Learned: You cannot directly use ou_142d6f... to identify Feishu, because the Delivery Config of WeChat Sessions also contains this ID (the Cron Job references it). You must match using an exclusive order.
4.4 Complete Pipeline Architecture
WeChat Agent Feishu Agent WhatsApp Agent
│ │ │
│ ① Write when done │ ① Write when done │ ① Write when done
│ │ │
└──────────┬─────────┴──────────┬──────────┘
│ │
Shared Daily Log ② Cron every 2h cross-channel scan
(memory/daily/YYYY-MM-DD.md) ← Read from filesystem
│ All channels Session JSONL
③ 4:00 AM Auto-Dream
│
MEMORY.md (Long-term memory)
5. In-Depth Analysis of the Time Zone Boundary Problem
5.1 Reproducing the Problem
The Cron Job runs at 00:01 HKT and executes the following logic:
# Original source code (has Bug)
if grep -q "$(date +%Y-%m-%d)" "$SESSION_FILE"; then
echo "ACTIVE"
fi
At this point:
date +%Y-%m-%doutputs2026-05-13(HKT)- The Session JSONL timestamp is
2026-05-12T14:34:00Z(UTC) grep "2026-05-13"→ 0 matches- Conclusion: "No active Session" → Miss!
5.2 Why the 8-Hour Window?
HKT is 8 hours ahead of UTC (UTC+8). This means that every day during 00:00-08:00 HKT, UTC is still on the previous day. Within this 8-hour window, all date-based Session matching will fail.
HKT 00:00 → UTC is still at the previous day 16:00
HKT 04:00 → UTC is still at the previous day 20:00
HKT 07:59 → UTC is still at the previous day 23:59
HKT 08:00 → UTC has finally reached today 00:00 ✅
5.3 Fix: Three-Date Matching
# Corrected code
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" # Cover all time zone boundary cases
fi
The OR matching of the three dates ensures that no matter when the Cron runs, at least one date can match a timestamp in the Session.
5.4 Additional Fix: find -newer Dependency Issue
The original find -newer memory/daily/$(date +%Y-%m-%d).md has nondeterministic behavior when the current day's Daily Log has not yet been created. Use instead:
find ... -mmin -240 # Files modified within the past 4 hours (no external dependencies)
6. Cron Pipeline Design
6.1 Division of Responsibilities Between the Two Cron Jobs
| Cron Job | Frequency | Function | Timeout |
|---|---|---|---|
daily-log-autocheck | Every 2 hours | Cross-channel scan for Sessions → backfill Daily Log | 300s |
auto-memory-dream | Daily at 04:00 | Consolidate from Daily Log → MEMORY.md + push report | 600s |
6.2 Daily Run Timeline (HKT)
00:00 ─ autocheck
02:00 ─ autocheck
04:00 ─ autocheck + auto-memory-dream (double safeguard)
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 memory checks per day ensure that conversations within any 2-hour window are not missed.
6.3 Autocheck Execution Flow
Step 1: Calculate three dates (HKT_TODAY + UTC_TODAY + UTC_YESTERDAY)
↓
Step 2: find -mmin -240 to find Sessions active in the last 4 hours
↓
Step 3: grep filtering by three dates (timezone-safe)
↓
Step 4: Pattern Match to identify channel (exclusive order)
↓
Step 5: Extract user messages → append to Daily Log (append mode)
↓
Step 6: Exit silently (no report if there is no new content)
7. System Monitoring and Health Metrics
7.1 Health Check Items
| Metric | Check Method | Normal Value |
|---|---|---|
| Daily Log existence | ls memory/daily/$(date +%Y-%m-%d).md | Must exist |
| Daily Log size | wc -c | >500 bytes |
| Session coverage | Compare Session count vs Daily Log entries | >80% |
| Cron running status | openclaw cron list | lastRunStatus = ok |
| Dream Streak | dream-log.md | Consecutive days |
7.2 Current Status
After this repair is completed:
- 📊 Memory store: ~370 records
- 🏥 Health score: 75/100 (previously low due to missing Daily Log, will gradually recover)
- 🔥 Dream Streak: 24 consecutive days
- ⏱️ Memory latency: reduced from "complete omission" to <2 hours
8. Complete Pitfall Log
6 key issues encountered during the construction of this memory system:
| # | Issue | Severity | Root Cause | Fix |
|---|---|---|---|---|
| 1 | No Checkpoint at session end causes complete amnesia | 🔴 Fatal | Meta-task has no automatic trigger | Three-layer protection mechanism |
| 2 | Misjudged WeChat Plugin status | 🔴 High | Config warning ≠ actual status | Check data before drawing conclusions |
| 3 | sessions_list API cross-channel blind spot | 🔴 High | per-channel-peer isolation | Direct file system read |
| 4 | Channel Pattern misjudgment | 🟡 Medium | Match order is not exclusive | Exclusive ordering |
| 5 | UTC/HKT time zone boundary miss | 🔴 Fatal | Single-date grep | Three-date OR matching |
| 6 | find -newer depends on non-existent file | 🟡 Medium | External file dependency | -mmin -240 |
Summary of Core Design Principles
| Principle | Description |
|---|---|
| Defense in depth | Failure of a single layer does not affect the whole (three-layer protection) |
| File system > API | When crossing channels, read files directly instead of relying on restricted APIs |
| Time range > date comparison | -mmin -240 is more reliable than -newer |
| Multiple-date matching | Cross-time-zone scenarios must be compatible with UTC and local time |
| Exclusive matching | Pattern matching goes from specific to general to avoid misjudgment |
| Verify before concluding | Config warning ≠ actual status; check the data first |
9. Collaboration with OpenClaw Auto-Dream
Memory Hub is the upstream assurance layer for Auto-Dream:
- Memory Hub → Ensures the Daily Log is complete (multi-channel + cross-day boundaries)
- Auto-Dream → Integrates the complete Daily Log into long-term memory
Memory Hub (Layer 2 Protection) Auto-Dream (Layer 3 Integration)
┌──────────────────────┐ ┌──────────────────────┐
│ Cross-channel scan │ │ Read Daily Log │
│ Timezone safety │ ──→ │ Extract key decisions│
│ Auto backfill │ │ Update MEMORY.md │
│ Guaranteed within 2h │ │Push integrated report│
└──────────────────────┘ └──────────────────────┘
The two work together to form a complete memory pipeline: from Session Log → Daily Log → MEMORY.md, from real-time logging to long-term memory, with safeguards at every layer.
Conclusion
The construction of Memory Hub this time stemmed from a seemingly simple question: "Why does the Agent forget every day?" After deeper investigation, we found that this was not a single bug, but the compounding of systemic issues at three levels: architecture design, process mechanisms, and time zone handling.
The core idea of the final solution is defense in depth: not relying on any single mechanism, but ensuring through three layers of protection, task-triggered writes, Session checks, and Cron fallback, that no matter which layer fails, the next layer will fill the gap.
More importantly, we learned to check the data first, and then draw conclusions. From a Config Warning causing a misjudgment of the WeChat Plugin status, to discovering the time zone boundary bug, every problem was solved by directly inspecting the raw data in the Session JSONL files, rather than relying on surface-level error messages.
This system is currently running on UltraClaw, performing 13 cross-channel automated integrations daily, and awaiting the test of time.
More in Learn
- Complete LangChain Tutorial 2026: Building Enterprise-Grade LLM Applications from Scratch
- MemoryHub v2.0 System Architecture In-Depth Analysis: From Capture Daemon to MCP Real-Time Memory Capture
- May 2026 LLM API Pricing Landscape: Complete Comparison of DeepSeek, Qwen, GLM, Kimi, MiniMax, and Doubao
- OpenClaw Creator and Infrastructure Automation: From Full Podcast Workflow to Self-Healing Servers