iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0

開場故事

你應該看過這種場景。

一開始大家都只是在講重點,會議很快、很清楚、很像有在往前走。可是聊到後面,歷史開始堆上來,前因後果越補越多,文件、截圖、工具輸出、舊決策、臨時修正全部擠進來。到最後不是沒資訊,而是資訊太多,誰都不知道現在到底該看哪一段。

AI Agent 也一樣。

當它越做越多,問題就不是「有沒有記住」而已,而是:

  • 要把多少東西帶進這一輪?
  • 哪些東西只是暫時有用?
  • 哪些東西要留在 transcript 裡?
  • 哪些東西可以先刪掉,不影響結果?
  • 什麼時候該摘要,什麼時候只要清掉工具輸出?

這就是第 9 天要看的事:

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

我想把這篇寫成「OpenClaw 怎麼在不丟失關鍵資訊的前提下,讓模型視窗維持可用」。

今天要解的問題

  • OpenClaw 眼中的 context 到底是什麼?
  • 為什麼記憶和上下文不是同一件事?
  • compactionpruning 的差別是什麼?
  • MEMORY.md、daily memory、tool results 各自該怎麼進場?
  • 上下文變長時,OpenClaw 是先刪東西、先摘要,還是先提醒寫記憶?

架構總覽

OpenClaw 對 context 的理解很直接:

Context = system prompt + conversation history + tool calls/results + attachments

也就是說,只要模型看得到,幾乎都算 context。

這裡最重要的不是名詞,而是邏輯:

  • context 是「這一輪模型真的收到什麼」
  • memory 是「可以存到磁碟、之後再撈回來的東西」

所以 context 是即時消耗品,memory 是可重載資產。

如果把這兩個混在一起,就很容易以為「只要有寫進記憶就沒問題」,但其實不是。記憶檔案可以存在磁碟上,context 卻還是會被 token window 卡住。

OpenClaw 的做法是把壓力拆成三種:

  1. 系統 prompt 會越來越肥
  2. 工具結果會越來越多
  3. 對話歷史會越來越長

然後分別用不同機制處理它們:

  • bootstrap / injected files 控制系統 prompt
  • pruning 控制工具結果
  • compaction 控制整段對話歷史
  • memory flush 則確保壓縮前重要內容先落地

這樣看起來比較複雜,但其實更接近真實問題。
因為「太長」不是一種單一病因,而是很多種肥胖一起發生。

原始碼節錄

先看最核心的定義。OpenClaw 明講了:context 就是這一輪送給模型的一切。

📄 文件:docs/concepts/context.md:10-16

"Context" is **everything OpenClaw sends to the model for a run**. It is bounded by the model's **context window** (token limit).

Beginner mental model:

- **System prompt** (OpenClaw-built): rules, tools, skills list, time/runtime, and injected workspace files.
- **Conversation history**: your messages + the assistant's messages for this session.
- **Tool calls/results + attachments**: command output, file reads, images/audio, etc.

這段很值得反覆看,因為它直接把 context 的邊界畫清楚了。

接著看系統 prompt 會被塞什麼。

📄 文件:docs/reference/token-use.md:14-47

OpenClaw assembles its own system prompt on every run. It includes:

- Tool list + short descriptions
- Skills list (metadata only; instructions load on demand with `read`)
- Self-update instructions
- Workspace + bootstrap files (`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md` when new, plus `MEMORY.md` when present)
- Time (UTC + user timezone)
- Reply tags + heartbeat behavior
- Runtime metadata (host/OS/model/thinking)

這裡的重點是:

  • MEMORY.md 會進 system prompt
  • memory/*.md 不會像 bootstrap 那樣每次全塞
  • 工具和技能本身也有成本

也就是說,OpenClaw 不是只有在聊天內容上做取捨,它連「系統自己要先說多少話」都要控制。

再看 daily memory 和 startupContext 的界線。

`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 每輪都灌進去
  • 只有 reset/startup 第一輪,才會先補最近的 daily memory

這就避免了最常見的問題:為了保留歷史,把每一輪都塞到快爆。

再看 compaction。

📄 文件:docs/concepts/compaction.md:9-9

Every model has a context window: the maximum number of tokens it can process. When a conversation approaches that limit, OpenClaw **compacts** older messages into a summary so the chat can continue.

📄 文件:docs/concepts/compaction.md:13-15

1. Older conversation turns are summarized into a compact entry.
2. The summary is saved in the session transcript.
3. Recent messages are kept intact.

也就是說,compaction 不是刪記錄,而是把舊對話壓縮成可延續的摘要。

這點很重要,因為它跟 pruning 不一樣。

Session pruning trims **old tool results** from the context before each LLM call. It reduces context bloat from accumulated tool outputs ... without rewriting normal conversation text.
| Pruning            | Compaction              |
| ------------------ | ----------------------- |
| Trims tool results | Summarizes conversation |
| No (per-request)   | Yes (in transcript)     |
| Tool results only  | Entire conversation     |

這裡的差別非常關鍵:

  • pruning 是瘦身工具輸出,讓每輪 prompt 不要被老結果拖垮
  • compaction 是整理整段對話,讓 transcript 自己變短、變可續接

再看壓縮前的保護機制。

Before compacting, OpenClaw automatically reminds the agent to save important notes to memory files. This prevents context loss.
Before compaction, OpenClaw can run a **silent memory flush** turn to store durable notes to disk.

這其實是在說同一件事:

  • 先把還沒寫進記憶檔的重點落地
  • 再去做摘要或壓縮

這是很務實的順序,因為壓縮最怕的就是把剛講到、但還沒保存的關鍵資訊一起折掉。

最後補一個更硬的實作細節:OpenClaw 還有 maxActiveTranscriptBytes 這種前置保護。

When `agents.defaults.compaction.maxActiveTranscriptBytes` is set, OpenClaw triggers normal local compaction before a run if the active JSONL reaches that size.

這表示它不只等 token 爆掉才處理,連本地 transcript 變太大也會提前拉警報。

白話拆解

1. context 不是記憶,context 是當下正在燒的燃料

這是最容易搞混的地方。

記憶可以存檔,context 不行。

模型每一輪看到的都是當下的 prompt 包裝,這包東西太大,就會燒更多 token,甚至直接超過 window。
所以 context 管的是「這次能不能塞得下」,不是「這些東西值不值得長期保存」。

2. 系統 prompt 不是越大越穩

很多人會直覺覺得:既然模型常常忘東忘西,那就把更多規則塞進 system prompt。

這聽起來合理,但實際上很容易過頭。

因為 system prompt 是每一輪都會被送進去的東西。你每多塞一段,都是每一輪都在付費、都在佔空間。

所以 OpenClaw 才會把 MEMORY.md 保持在「精選摘要」層,而不是讓它長成一本百科全書。

3. pruning 是清桌面,compaction 是整理檔案夾

這個比喻我覺得蠻準。

  • pruning:把桌上那些舊工具結果先收掉,讓你眼前空一點
  • compaction:把整個檔案夾整理成一份摘要,讓你之後還接得上

如果你只做 pruning,不做 compaction,對話歷史還是會一直長大。
如果你只做 compaction,不清工具結果,工具輸出還是會把 prompt 撐爆。

所以兩者是互補,不是替代。

4. OpenClaw 不想要「資訊全留」,它想要「必要資訊能續接」

這句是我對它設計最深的感受。

很多系統在面對 context 壓力時,第一反應是把東西藏起來。
OpenClaw 比較像在做維持秩序:

  • 重要且穩定的,留下來
  • 暫時需要的,先帶著
  • 太肥的工具結果,先瘦身
  • 太長的對話,先摘要
  • 還沒寫進記憶的重點,先 flush

它不是想把所有資訊都永久留住,而是想讓「還在工作中的資訊」保持可用。

5. 為什麼要先 flush 再 compact?

因為 compaction 是一種整理,不是補救。

你如果先壓縮,再回頭想「欸剛剛那個偏好好像很重要」,通常就晚了。

所以 OpenClaw 會先做 memory flush,讓重要內容先進檔案,再放心去做摘要。

這個順序很像你整理筆記時先把待辦寫到正式清單,再把舊草稿丟進歸檔箱。

6. 上下文太長的本質,不是「容量不夠」,而是「層次沒分開」

我覺得這是最值得記住的一點。

如果你把所有東西都塞進一個層,遲早會長到失控。
但如果你把東西分層:

  • 系統提示是底座
  • daily memory 是現場筆記
  • active memory 是臨場提醒
  • tool results 是可清理的暫時輸出
  • compaction 是對話摘要

那上下文就比較不會亂成一團。

OpenClaw 的每個機制,說穿了都在幫你做一件事:讓不同生命週期的資訊待在不同地方。

設計取捨

  • 好處是 context 壓力不會全靠單一機制硬扛
  • 好處是工具結果和對話歷史可以分別處理
  • 好處是壓縮前有 memory flush,降低資訊流失
  • 好處是 memory/*.md 不會每輪亂入,避免 bootstrap 過肥
  • 代價是整體概念比較多,不是單看一個設定就能懂
  • 代價是 pruning、compaction、memory flush 之間的界線要理解清楚,否則很容易誤判

如果換成最偷懶的做法,就是什麼都不分:

  • 工具結果不清
  • 對話不壓
  • 記憶全灌

短期看起來好像最簡單,長期就是 token 先死。

今天的結論

  • OpenClaw 的 context 是「這一輪模型實際收到的一切」
  • 記憶可以存盤,context 只能在 window 裡暫時存在
  • pruning 是清老工具結果,compaction 是壓縮整段對話
  • startupContext 只在 bare /new/reset 的第一輪補最近 daily memory
  • MEMORY.md 是長期底座,memory/*.md 平常不直接進 bootstrap
  • compaction 前有 memory flush,避免重要資訊被摘要吞掉
  • 上下文太長不是單一問題,而是多種不同生命週期的資訊擠在同一個層

下一步

第 8 天我們已經把短期記憶和長期記憶的上場順序排開了。

第 9 天再往前一步,就會碰到更現實的問題:

不是所有東西都該留,也不是所有東西都該摘要。
有些東西應該立刻清掉,有些東西應該先壓縮,有些東西則應該先寫進記憶。

下一篇我想接著看:

Agent 為什麼會忘記自己在做什麼?

因為當上下文夠長,真正危險的常常不是「沒資訊」,而是「資訊太多,反而忘了現在到底要做哪一步」。


上一篇
第 8 天:短期記憶和長期記憶,誰先說話
下一篇
第 10 天:Agent 為什麼會忘記自己在做什麼
系列文
30 天走進 OpenClaw:一個 AI Agent 的誕生、掙扎與進化14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言