Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
337 changes: 337 additions & 0 deletions usecases/auto-dream-memory-consolidation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,337 @@
# usecases: Auto Dream — 自動化記憶整理系統
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

此處建議補上錯誤處理/回傳值檢查:目前若上游回傳非預期格式,可能導致後續流程拋出非預期例外或產生難以追蹤的狀態。


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

請確認此變更是否有對應測試(至少涵蓋:正常路徑、空值/缺值、以及外部依賴失敗)。若目前未涵蓋,建議補上以避免回歸。

**對應版本:** OpenClaw ≥ 2026.3.7(需要 cron isolated session 支持)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

此處的抽象與命名建議再明確一些:請補充註解/文件說明設計意圖與假設前提,避免後續維護時誤用或改壞。

**相關 issue:** [openclaw/openclaw#43002](https://github.com/openclaw/openclaw/issues/43002)
**作者:** wangyuyan-agent
**實測日期:** 2026-03-28

---

## 問題定義

OpenClaw 的記憶系統是兩層架構:

- `memory/YYYY-MM-DD.md` — 每日流水日誌(短期)
- `MEMORY.md` — 長期精煉記憶

但這兩層之間的搬運完全靠手動——agent 必須被明確提醒才會整理記憶。日誌只進不出,越堆越大;MEMORY.md 靠手動維護,品質不穩定;沒有任何自動機制識別哪些資訊值得長期保留。

這個問題在官方 issue #43002 有明確記錄,但目前尚無內建解法。本文提供一套**可直接部署的社群實作方案**。

---

## 設計哲學

三個核心原則:

1. **職責分離** — 記錄、整理、確認三個動作由三個獨立 job 完成,不混在一起
2. **加法優先** — 自動化只做新增和修訂,不做刪除;刪除需人類確認
3. **人在迴路** — 清理動作必須等主人確認,不自動執行破壞性操作

---

## 系統架構

```
昨天全天對話(本地時區 00:00 ~ 23:59)
▼ 凌晨 01:30(本地時區)
┌─────────────────────────────────┐
│ Log Job │
│ 依系統本地時區計算昨天日期 │
│ 抓昨日完整 session history │
│ 過濾 heartbeat / tool call │
│ 生成 memory/昨天.md │
│ 若已有手動記錄 → 追加 │
│ 標記:[自動生成 01:30] │
└────────────┬────────────────────┘
▼ 凌晨 03:00(本地時區)
┌─────────────────────────────────┐
│ Dream Job │
│ 讀 memory/昨天.md │
│ 手動記錄 → 優先升入 │
│ 自動記錄 → 按 MEMORY.md │
│ 現有主題甄別 │
│ 更新 MEMORY.md(只加不刪) │
│ 建立 pending-cleanup.md │
│ 備份 MEMORY.md.bak.YYYYMMDD │
└────────────┬────────────────────┘
▼ 上午 10:00(本地時區)
┌─────────────────────────────────┐
│ Confirm Job │
│ pending-cleanup 有內容? │
│ ├─ 否 → 靜默結束 │
│ └─ 是 → openfeedback 推送 │
│ 主人 approve → 執行清理 │
│ 主人 reject + 理由 → 調整 │
└─────────────────────────────────┘
```

**已知限制:** 凌晨 00:00 ~ 01:30 的對話,會在隔天的 Log Job 才被收入。這段時間的對話可以手動補記。

**時區說明:** 三個 job 的觸發時間用 `--tz` 指定(對應 VPS 所在時區);日期計算邏輯依賴系統本地時間,無需手動設定時區。**`--tz` 必須和 VPS 系統時區一致,否則觸發時間與日期計算會錯位。**

---

## DREAM.md 模板

在 `~/.openclaw/workspace/` 建立 `DREAM.md`,根據自己的情況調整「什麼值得升入」的規則後即可使用:

```markdown
# DREAM.md — 記憶整理規則

## 觸發機制

三個 cron job,職責分離:

- 凌晨 01:30(本地時區):Log Job — 抓昨天對話,生成 memory/昨天.md
- 凌晨 03:00(本地時區):Dream Job — 掃昨天日誌,升入 MEMORY.md,收集待清理
- 上午 10:00(本地時區):Confirm Job — openfeedback 讓主人確認待清理項目

## 日誌文件的兩種來源

**手動記錄**(agent 在主對話中主動寫入)
- 特點:已經過重要性判斷,質量較高
- Dream Job 處理:優先升入,不輕易覆蓋

**自動生成**(Log Job 凌晨 01:30 追加)
- 標誌:段落開頭有 [自動生成 01:30] 標記
- 特點:忠實記錄,未經篩選,信噪比較低
- Dream Job 處理:從中提取重要內容升入,其餘不升

兩者並存時:
- 與手動記錄重疊 → 以手動記錄為準,自動記錄部分跳過
- 手動記錄未覆蓋的重要事件 → 以 MEMORY.md 現有主題為基準甄別:
- 與現有主題相關 → 升入
- 完全無關的新主題 → 謹慎,不輕易升入,留日誌等主人手動確認

## 什麼值得升入 MEMORY.md

- 關於主人的新認知或新定性(人格特質、思維方式、重要事件)
- 重要的決策與共識(規則、邊界、流程)
- 關係或身份的改變
- 工具環境的重大變更(新安裝、新配置、新項目)
- 反覆出現的教訓或錯誤模式

## 什麼留在日誌,不升入 MEMORY.md

- 單次技術操作細節
- 過渡性狀態(等待中的 PR、臨時決策)
- 與 MEMORY.md 已有內容重複的資訊

## 什麼寫入 pending-cleanup

- 已過時的狀態描述
- 重複記錄了同一件事的不同版本(保留最新,舊版列入待清理)
- 細節過多、可壓縮的段落

## 備份規則

每次 Dream Job 執行前,自動備份:MEMORY.md.bak.YYYYMMDD
保留最近 7 份,更舊的自動刪除

## 安全邊界

- Dream Job:只讀日誌、只寫 MEMORY.md 和 pending-cleanup,不發通知
- Confirm Job:不自動執行清理,必須等主人確認
```

---

## 部署步驟

### 1. 確認 VPS 系統時區

```bash
timedatectl | grep "Time zone"
# 或
date +%Z
```

記下時區名稱,後續設定 `--tz` 時使用。

### 2. 建立 DREAM.md

把上方模板存入 `~/.openclaw/workspace/DREAM.md`,根據自己的情況調整「什麼值得升入」的規則。

### 3. 設定三個 cron job

將以下指令的 `Asia/Shanghai` 替換為你的 VPS 系統時區。

**Log Job(凌晨 01:30)**

```bash
openclaw cron add \
--name "auto-log" \
--cron "30 1 * * *" \
--tz "Asia/Shanghai" \
--session isolated \
--no-deliver \
--timeout-seconds 180 \
--message "你是一個對話日誌生成 agent。任務:把昨天(前一個完整日曆日)的對話記錄壓縮成人類可讀的日誌。

步驟:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This append-only behavior may not be idempotent if the Log Job is re-run manually or retried after a partial failure. It may be worth documenting a dedupe marker or a 'replace existing auto-generated section for that date' rule here, otherwise the same day can accumulate duplicate auto-log blocks.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The append behavior here may not be idempotent if the Log Job is re-run manually or retried after a partial failure. It may be safer to document a dedupe marker or a rule like replacing the existing auto-generated block for that date, otherwise the same day can accumulate duplicate auto-log sections.

1. 用系統本地時間計算昨天的日期(Python: (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')),不假設任何固定時區
2. 用 sessions_list 找昨天所有的 main session
3. 用 sessions_history 讀取各 session 的對話,只保留 role=user 和 role=assistant 的純對話,過濾掉:heartbeat、HEARTBEAT_OK、cron 觸發的 isolated session、工具呼叫細節
4. 把過濾後的對話整理成摘要,包含:主要話題、重要決策、值得記住的事件
5. 檢查 ~/.openclaw/workspace/memory/昨天日期.md 是否存在
- 若不存在:建立新文件,寫入摘要
- 若已存在(手動記錄):在文件末尾追加,段落開頭加 [自動生成 01:30] 標記
6. 不做任何重要性判斷,只做忠實記錄
靜默執行,不發通知。"
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using MEMORY.md.bak.YYYYMMDD means multiple Dream Job runs on the same day will overwrite the same backup. If reruns are part of the operational model, would it be safer to include time as well, for example YYYYMMDD-HHMMSS, or explicitly state that only one backup per day is kept?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using MEMORY.md.bak.YYYYMMDD means multiple Dream Job runs on the same day will overwrite the same backup. If reruns are expected operationally, including time in the filename, or explicitly stating that only one backup per day is kept, would make this easier to reason about.

**Dream Job(凌晨 03:00)**

```bash
openclaw cron add \
--name "auto-dream" \
--cron "0 3 * * *" \
--tz "Asia/Shanghai" \
--session isolated \
--no-deliver \
--timeout-seconds 300 \
--message "你是一個記憶整理 agent。按照 ~/.openclaw/workspace/DREAM.md 的 Dream Job 規則執行:
1. 用系統本地時間計算昨天的日期,讀取 ~/.openclaw/workspace/memory/昨天日期.md
2. 若不存在 → 在今天日誌記「Dream Job:無日誌,跳過」後結束
3. 執行前備份 MEMORY.md(保留最近 7 份,格式 MEMORY.md.bak.YYYYMMDD)
4. 按規則更新 MEMORY.md(只做新增和修訂,不刪除)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m a bit uneasy about clearing pending-cleanup even on reject. If the human rejects because one item needs adjustment rather than deletion, wiping the file here can make the proposed cleanup set disappear entirely. Preserving the file until the next successful confirm cycle, or marking items with status, may be safer operationally.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clearing pending-cleanup even on reject feels risky. If the human rejects because one item needs adjustment rather than deletion, wiping the file here can make the proposed cleanup set disappear entirely. Keeping the file until a successful confirm cycle, or marking items with status, may be safer operationally.

Comment on lines +173 to +201
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wangyuyan-agent 我補一個收斂式的觀察:目前幾個主要 concern(auto-log 的 dedupe / idempotency、同日 backup 命名、以及 reject 後 pending-cleanup 的處理)其實都在指向同一個操作面問題——這套流程的 rerun / retry semantics 到底是什麼。

usecases/auto-dream-memory-consolidation.md 第 173-201 行這段附近,建議補一小節把語義明寫出來:人工重跑、部分失敗後重試、或同日多次執行時,哪些產物是 append-only、哪些應該 replace / update-in-place、哪些狀態要保留到下一次成功 confirm cycle。

這樣可以把目前分散的幾個 edge case 收斂成一套明確的操作規則,讓這份 usecase 在實際部署時更容易安全落地。

5. 把建議清理的條目寫入 MEMORY.pending-cleanup.md
6. 在今天日誌記「Dream Job:已執行,升入N條,待清理M條」
靜默執行,不發通知。"
```

**Confirm Job(上午 10:00)**

```bash
openclaw cron add \
--name "auto-dream-confirm" \
--cron "0 10 * * *" \
--tz "Asia/Shanghai" \
--session isolated \
--no-deliver \
--timeout-seconds 3700 \
--message "你是一個記憶清理確認 agent。執行:
1. 讀取 ~/.openclaw/workspace/MEMORY.pending-cleanup.md
2. 若不存在或為空 → 靜默結束
3. 若有內容 → 用 openfeedback send 批量列出所有待清理條目,請 owner 確認。標題:「MEMORY 清理確認」,timeout 3600
4. 若 approved → 從 MEMORY.md 刪除對應條目,刪除 pending-cleanup 文件
5. 若 rejected + 理由 →
openfeedback 的 reject 回應包含可操作的文字理由(如「第2條保留,其餘刪除」)。
解讀理由,按條精確執行(刪指定條、保留其餘條),執行完畢後清空 pending-cleanup 文件。
若理由模糊無法判斷 → 保留文件,在開頭插入一行:
[上次確認:YYYY-MM-DD rejected,理由:<原文>,待人工處理]
靜默結束,明天重新推送。
6. timeout / 任務失敗 → 文件保留,明天重新推送"
```

---

## 實測記錄

**測試時間:** 2026-03-28,Linux VPS

**三個 job 手動觸發結果:**

| Job | 狀態 | 耗時 | 行為 |
|-----|------|------|------|
| auto-log | ✅ ok | 28s | 昨日無活躍 session,正確跳過 |
| auto-dream | ✅ ok | 31s | 昨日無日誌,正確識別跳過 |
| auto-dream-confirm | ✅ ok | 9s | 無 pending-cleanup,靜默結束 |

三個 job 均正確識別「無工作可做」並靜默結束,邏輯驗證通過。

---

## 與 Claude Code Auto Dream 的對比

| | Claude Code Auto Dream | 本方案 |
|---|---|---|
| 觸發方式 | 累積 5 個 session 後自動 | 每日定時(可調整) |
| 執行時機 | session 之間 | 凌晨閒置時段 |
| 使用者感知 | 完全無感 | Confirm Job 需回應 |
| 清理確認 | 自動 | 需人類 approve |
| 部署難度 | 內建,零配置 | 需手動設置三個 cron |

本方案的核心差異:**清理動作需要人類確認**,犧牲一點自動化換來更高的安全性。

---

## 多 Agent / 多 Channel 環境

每個 agent 的 session 獨立存放在各自的目錄下(`~/.openclaw/agents/<agent-id>/sessions/`)。`sessions_list` 只能看到**當前 agent 自己的 sessions**,無法跨 agent 抓取。

如果你同時運行多個 agent(例如 Telegram 主 agent + 飛書 agent),每個 agent 需要**各自部署一套三個 cron job**,分別指向各自的 workspace 路徑:

| Agent | Workspace 路徑 | 說明 |
|-------|--------------|------|
| 主 agent(如 Telegram) | `~/.openclaw/workspace/` | 預設路徑 |
| 其他 agent(如飛書) | `~/.openclaw/workspace-<agent-id>/` | 各自獨立 |

共用一套 job 無法跨 agent 抓取 session,會導致其他 agent 的對話記錄被遺漏。

---

## Rerun & Retry Semantics

Default behavior when jobs are re-run or retried:

| Job | Rerun behavior | Notes |
|-----|----------------|-------|
| Log Job | append-only, not idempotent | Designed to run once per day. A rerun appends a new `[auto-generated]` block to the same day's log — redundant but harmless; Dream Job processes it correctly |
| Dream Job | same-day backup is overwritten; MEMORY.md updates are idempotent | One pre-dream snapshot per day is sufficient for recovery. Same-day overwrite is intentional |
| Confirm Job | reject executes per-item based on reason; falls back to preserving the file if reason is ambiguous | No all-or-nothing clearing; cleanup always requires owner confirmation |

Design principle: prefer redundancy over data loss; all deletions require human confirmation.

---

## Operator Checklist

Before going live, verify the following:

**1. Timezone alignment**

Confirm your VPS system timezone matches your intended daily schedule:

```bash
timedatectl # or: date
```

The `--tz` flag anchors the cron schedule, but date calculations inside job prompts use system local time — both should be consistent.

**2. First-run dry-run**

Trigger each job manually and confirm expected behavior:

```bash
# Expect: creates or appends to memory/YYYY-MM-DD.md
openclaw cron trigger auto-log

# Expect: if no log exists for yesterday, silently skips
openclaw cron trigger auto-dream

# Expect: if no pending-cleanup exists, silently exits
openclaw cron trigger auto-dream-confirm
```

**3. Expected artifacts**

After normal operation, you should see:

| Artifact | Created by | Notes |
|----------|------------|-------|
| `memory/YYYY-MM-DD.md` | Log Job | One file per day; auto-generated blocks marked `[auto-generated HH:MM]` |
| `MEMORY.md` | Dream Job | Updated in-place; backup saved as `MEMORY.md.bak.YYYYMMDD` |
| `MEMORY.pending-cleanup.md` | Dream Job | Only present when items are awaiting owner confirmation; absent otherwise |

---

## 延伸方向

- **Phase 2**:Log Job 加入規則層預過濾(先程序過濾再 agent 分析),降低 token 消耗
- **Phase 3**:Dream Job 改用輕量模型(Gemini Flash / Claude Haiku),進一步降低成本
- **Phase 4**:Confirm Job 支持逐條確認模式,適合待清理條目較多的情況
Loading