iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0

開場故事

你有沒有遇過這種人:

你們明明昨天才聊過,他今天一開口就像完全沒這回事;但當你提醒他「昨天不是講過嗎」,他又能立刻接上前因後果,甚至還順手把你忘掉的小細節補回來。

這種人通常不是記性特別好,而是他知道什麼時候該翻舊帳、什麼時候該先看眼前。

OpenClaw 的記憶系統也很像這樣。

它不是把所有東西塞成一團,而是把記憶切成幾個層次:

  • 有些是剛發生、還很熱的短期記憶
  • 有些是穩定、值得長期保留的長期記憶
  • 有些只在這一輪對話裡有用
  • 有些要先補進來,模型才知道現在在講什麼

所以第 8 天我想問的不是「OpenClaw 有沒有記憶」,而是:

  • 短期記憶和長期記憶,誰先說話?
  • /new 之後第一輪,到底先載入什麼?
  • active-memory 是在什麼位置插隊進來的?
  • MEMORY.mdmemory/*.md 是怎麼分工的?
  • 如果兩邊講法不同,模型最後要相信誰?

這一篇我想把它寫成「OpenClaw 怎麼安排記憶的上場順序」。

今天要解的問題

  • OpenClaw 的短期記憶、長期記憶、召回記憶各自在哪一層?
  • /new/reset 後,第一輪會先看到什麼?
  • startupContext 為什麼只管 bare reset 的第一輪?
  • active-memory 在主回覆前做了什麼?
  • MEMORY.md、daily notes、dreaming promotion 的先後順序是什麼?
  • 當短期和長期記憶衝突時,系統偏向哪一邊?

架構總覽

如果把 OpenClaw 的記憶想成一場會議,那它不是只有一個發言人。

它比較像是三個不同資歷的人輪流講話:

  1. 先上場的是短期記憶,因為它最接近現場
  2. 再來是 active memory,負責在主回覆前補上必要背景
  3. 最後才是長期記憶,提供穩定規則和背景基調

但這裡有個很重要的細節:

  • 短期記憶不是永遠比長期記憶重要
  • 長期記憶也不是每次都要壓過短期現況
  • 真正的優先順序,是「誰更接近這一輪問題的時間點」

OpenClaw 把這件事拆得很細。

MEMORY.md 是長期摘要,通常會被納入基礎上下文。
memory/YYYY-MM-DD.md 是日常筆記,正常情況下不會每輪都灌進 prompt,而是在需要時由工具或啟動前導拉進來。
agents.defaults.startupContext 則是在 bare /new/reset 的第一輪,先把最近幾天的 daily memory 預載進去。
active-memory 則更進一步,它在主回覆前先跑一次 recall,看看要不要補上過去的偏好、決策或上下文。

所以如果你問「誰先說話」,答案其實是:

  • 在新 session 的第一輪,短期記憶先說
  • 在一般互動裡,主上下文先說
  • 如果 active memory 有東西,它會在主回覆前補一句
  • 長期記憶則一直在後面當底色

這不像傳統那種「一層覆蓋另一層」。
它比較像一個有時間感的會議流程。

原始碼節錄

先看最直接的證據:startupContext 是專門為 bare /new/reset 做的第一輪前導,而且它會把最近幾天的 daily memory 帶進來。

`agents.defaults.startupContext.*`                             | One-shot reset/startup model-run prelude, including recent daily `memory/*.md` files. Bare chat `/new` and `/reset` are acknowledged without invoking the model

再看設定本身。

📄 文件:docs/gateway/config-agents.md:209-209

{
  agents: {
    defaults: {
      startupContext: {
        enabled: true,
        applyOn: ["new", "reset"],
        dailyMemoryDays: 2,
        maxFileBytes: 16384,
        maxFileChars: 1200,
        maxTotalChars: 2800,
      },
    },
  },
}

這裡其實已經把先後順序講得很清楚了:

  • startupContext 不是一般每輪都跑的東西
  • 它只在 reset / startup 那一輪出場
  • 它讀的是最近的 daily memory,不是整個歷史
  • 而且還有限額,代表它不是要塞爆上下文,而是要先補必要的現場資料

這像什麼?

像你早上進會議前先看昨天的會議記錄,不是把整個公司成立史從頭翻一遍。

再看 MEMORY.md 的位置。

Workspace + bootstrap files (`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md` when new, plus `MEMORY.md` when present).

這表示 MEMORY.md 是直接屬於系統 prompt 的一部分。
它不是要等你查才出現,而是作為整體上下文的一塊固定底座存在。

但 daily memory 不是這樣。

`memory/*.md` daily files are not part of the normal bootstrap prompt; they stay on-demand via memory tools on ordinary turns. Reset/startup model runs can prepend a one-shot startup-context block with recent daily memory for that first turn.

這一段很重要。

它等於在告訴你:

  • daily memory 平常不直接灌進每一輪 prompt
  • 只有在重置或啟動的那一輪,才會被當成 startup prelude
  • 其他時候,要嘛靠 memory tools,要嘛靠 active memory

這就形成了很清楚的分工。

再看 active memory 的位置。

Active memory is an optional bundled plugin that runs a blocking memory recall sub-agent before the main reply, for eligible conversational sessions.

它不是在 main reply 之後才補充,也不是等模型回完再回頭修正,而是先做一次 recall,再決定主回答要帶什麼背景。

這就是它和 startupContext 最大的差異:

  • startupContext 是先把近期日常資料放進第一輪
  • active memory 是在每一輪主回答前做一次有條件的 recall
  • MEMORY.md 則是穩定存在的長期底座

如果要把順序濃縮成一句話,大概是:

長期記憶定基調,短期記憶補現場,active memory 補背景,主回覆再正式開講

最後看長期記憶怎麼來。

📄 文件:docs/concepts/dreaming.md:11-22

Dreaming is the background memory consolidation system in `memory-core`. It moves strong short-term signals into durable memory while keeping the process explainable and reviewable.

Long-term promotion still writes only to `MEMORY.md`.

這裡把短期和長期的分工講死了:

  • 短期信號先累積
  • dreaming 再挑出值得留下的東西
  • 真的過關了,才進 MEMORY.md

所以長期記憶不是「比較舊的短期記憶」。
它是經過挑選、穩定下來、足以反覆引用的結論。

白話拆解

1. MEMORY.md 像背景音,不是廣播

我很喜歡把 MEMORY.md 想成背景音樂。

它一直在,但不會每秒都跳出來搶話。
它提供的是整體氛圍,像使用者偏好、長期規則、穩定決策。

例如:

  • 這個人通常喜歡什麼風格
  • 某些功能以前怎麼選的
  • 哪些限制是長期有效的

這些內容不一定是當下最新的事,但它們會影響模型怎麼理解整個任務。

2. daily memory 像桌上的便條紙

memory/YYYY-MM-DD.md 比較像便條紙。

你今天在那裡寫了很多臨時資訊:

  • 這個 hook 的輸出長這樣
  • 這個 bug 剛剛怎麼冒出來
  • 這個設計其實有另一種走法

這些東西不一定值得永遠留下,但如果隔天還要接著做,它們就很重要。

所以 short-term memory 的核心價值不是保存永久真理,而是讓你不必每次都從零開始。

3. startupContext 的工作,是讓第一輪不要失憶

很多系統的第一輪最容易出現一種尷尬:

模型剛醒來,卻不知道你今天想接哪個話題。

OpenClaw 的 startupContext 就是來補這一刀的。
它只在 bare reset 的第一輪,把最近幾天的 daily memory 先放進去,讓模型不是空著腦袋開始。

這樣它才知道:

  • 昨天做到哪
  • 今天可能要接哪個方向
  • 有哪些最近才出現的重要限制

這很像你打開電腦先看昨天的 TODO,而不是先從公司制度總表讀起。

4. active memory 像臨場提醒,不像永久筆記

如果說 startupContext 是「開場前的 briefing」,那 active memory 就是「你講到一半時,旁邊有人適時提醒你上次講過什麼」。

它不是每次都出聲。
它只在 eligible session 裡跑,而且還有 timeout、模型、prompt style、tool allowlist 這些限制。

所以它比較像臨場輔助,而不是資料庫本身。

這點很關鍵,因為它避免了兩個極端:

  • 一種是完全不管過去,永遠重來
  • 另一種是每一句話都把所有歷史翻出來,搞得現在的問題被舊東西淹沒

5. 長期和短期衝突時,OpenClaw 不會用「年資」暴力壓人

這是我認為最成熟的一點。

OpenClaw 沒有設計成「長期記憶永遠贏」。
它更像是在做判斷:

  • 長期記憶提供穩定方向
  • 短期記憶提供最新狀態
  • 模型要看哪一個比較像「這一輪真正需要的真相」

例如,MEMORY.md 可能記得某個人一向偏好簡潔寫法;但如果今天這個專案明確要求要寫成完整報告,那短期上下文就該優先。

這不是忘記長期記憶,而是知道長期記憶不能把現場現況蓋掉。

6. promotion 的意思不是「比較重要就立刻升級」

dreaming 的存在,讓短期和長期之間多了一道緩衝。

不是今天剛聊到的東西馬上就進 MEMORY.md
它要先累積信號、通過門檻、被判定有持續價值,才會升級。

這就很像你不會因為一場會議講到某個點,就立刻把它寫進公司章程。
你會先觀察它是不是反覆出現、是不是值得長期保留、是不是之後還會用到。

OpenClaw 的記憶優先順序,本質上就是這種「先觀察,再定案」。

設計取捨

  • 好處是第一輪不會完全失憶,startupContext 能補回最近現場
  • 好處是 active-memory 讓每輪回答前都有一次有條件的 recall
  • 好處是 MEMORY.md 保持穩定,不會被日常噪音污染
  • 好處是 short-term 和 long-term 中間有 dreaming 緩衝層
  • 代價是流程比較多,理解起來沒有單一記憶庫那麼直覺
  • 代價是不同層的內容有時會重疊,模型必須自己判斷哪個更適合當下

如果換成簡化版做法,把所有東西都丟進同一個上下文,短期看起來很省事。
但長期會變成:

  • 太吵
  • 太長
  • 太難更新
  • 太容易把「最近」和「重要」混在一起

OpenClaw 顯然不想用這種方式工作。

今天的結論

  • MEMORY.md 是長期記憶的底座,提供穩定背景與長期偏好
  • memory/YYYY-MM-DD.md 是短期記憶,記住現場、方便續接
  • startupContext 只在 bare /new/reset 的第一輪把最近 daily memory 拉進來
  • active-memory 會在主回覆前先做一次 blocking recall,補必要背景
  • dreaming 負責把真正有價值的短期信號慢慢升級成長期記憶
  • 短期和長期不是誰永遠壓誰,而是誰更貼近當下問題就先出聲

下一步

第 7 天我們看的是 OpenClaw 怎麼記對的東西。

第 8 天往前推一點,就變成另一個更實際的問題:

它不是只有記不記得,而是要安排誰先講、誰後講、誰只是備用資料。

這其實很像真實工作的場景。
你不是每次都要翻最完整的歷史,反而常常只需要:

  • 最近發生了什麼
  • 這次要接哪一段
  • 長期規則有沒有變

下一篇我想接著往下看:

上下文太長怎麼辦?OpenClaw 的取捨

因為當記憶越來越會說話,下一個問題就會來得很自然:
到底要把多少東西塞進模型的視窗裡,才不會又記得太多、又看得太少?


上一篇
第 7 天:記憶不是記越多越好,而是記對的東西
下一篇
第 9 天:上下文太長怎麼辦,OpenClaw 的取捨
系列文
30 天走進 OpenClaw:一個 AI Agent 的誕生、掙扎與進化14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言