本文同步刊登於 2026 iThome 鐵人賽,系列為《凡人修 Agent 傳-我這一生如履薄冰,你說我的 Agent 能結嬰嗎?》。

Day 12 把記憶的寫入掛在壓縮前面。從那一刻起,壓縮從一件在背景自己發生的事,變成會決定兩件事的東西:哪一刻寫記憶,寫完之後他手上還剩什麼。

Day 10 我先用 pi 預設的壓縮,看了一輪。這一天回頭把設定攤開來看。結論先講:一個都不動。

我的立場:預設是什麼,我就直接用

pi 預設是什麼,我就直接用,直到我發現不改不行。

這條原則 Day 10 講過一次,這一天是它第一次真的派上用場。壓縮這件事我用了幾天,沒有碰到不改不行的情況。所以我沒有想要改 pi 的預設值。pi 怎麼壓,我就怎麼壓。

那為什麼還要花一天看它。因為記憶掛在它前面。三個設定我一個都不動,但至少要知道它什麼時候發生、留什麼、丟什麼,記憶那一邊才知道自己接在什麼東西上。

哪一天發現不改不行,再回來動這三格。這一天沒有那個理由。

pi 給的三個把手

Day 10 只講了門檻。這一天把設定攤開。

設定 預設 管什麼
compaction.enabled true 要不要自動壓縮
compaction.reserveTokens 16384 留給模型回答的空間。context 用到只剩這麼多就壓
compaction.keepRecentTokens 20000 壓的時候,最近這麼多 token 的原文保留、不進摘要

三個都放在 ~/.pi/agent/settings.json,或專案的 .pi/settings.json。專案那份蓋全域那份,跟 Day 07 講的 AGENTS.md 一樣的疊法。我兩份都沒有寫這一段,所以跑的就是表格裡的預設值。

門檻的算法 Day 10 寫過:context 超過「視窗大小減 reserveTokens」就壓。壓的時候從最新的訊息往回數,數到 keepRecentTokens 為止,這一段原文保留,前面全部進摘要。再壓一次的時候,上一次保留下來的那一段也會被納進摘要裡。

另外有一個手動的:/compact,後面可以帶一句指示,告訴他這一次摘要要留什麼。關掉自動壓縮之後手動的還能用。

壓完之後,他手上剩什麼

pi 的壓縮是請模型把舊的那一段寫成一份固定格式的摘要:目標、限制、進度、關鍵決定、下一步、還要用到的資料,最後附上讀過和改過的檔案清單。做摘要之前,工具的輸出超過兩千字先截掉。

摘要留的是「做了什麼」。檔案留下的是路徑,內容沒了,要再用就得再讀一次。

這是預設的樣子。我知道它會丟細節,知道了就好,先這樣用。

Day 13:沿用 Pi 預設的三個壓縮設定

跟記憶怎麼接

順序是這樣:context 快滿,記憶先寫(Day 12 掛的那個位置),再壓。

三個設定都用預設,所以「什麼時候寫記憶」也就等於 pi 預設的門檻:視窗只剩 16384 的時候。這一點我知道,先接受。

OpenClaw 那邊同一個順序。他們在壓縮之前會先跑一輪安靜的回合,提醒 agent 把還沒寫進檔案的重要內容先存進記憶檔,這個預設是開的。差別在誰決定寫什麼:他們讓 agent 自己判斷;我這一版是我說要記才記,Day 12 講過為什麼。

所以壓掉的細節有兩個去處。我說過要記的,進了那一天的 Markdown;沒說的,跟著摘要一起沒了。

別人怎麼處理這件事

Day 11 我看過 Mem0、Letta、MemOS、Cognee,一個都沒選,當時只寫了我的判斷方式,沒有展開它們各自是什麼。這一天壓縮和記憶接上了,剛好回頭把它們攤開。每一家其實都在回答同一個問題:context 裝不下的東西去哪裡,什麼時候回來。順手把另外幾個常被提到的也放進來。

Mem0 把自己定位成 AI 的「記憶層」。做法是把對話交給模型,抽成一條一條的事實存起來,之後用搜尋找回來。他們 2026 年 4 月的新演算法改成只加不改:一次呼叫抽事實,累積下去,舊的不覆寫;找的時候語意、關鍵字、實體三種比對一起算。它要一個模型加一個 embedding 模型才跑得起來,預設是 OpenAI 的 gpt-5-mini 和 text-embedding-3-small。三種用法:直接裝 library、用 docker compose 自架 server、用他們的雲端。

Letta,原本叫 MemGPT。MemGPT 那篇論文的題目就是把 LLM 當作業系統看:context 是主記憶體,放不下的東西搬到外面,由 agent 自己用工具搬進搬出。現在的 Letta Code 是一個有狀態的 agent harness,agent 靠改寫自己的 memory blocks 學習,所有 context 用 git 追蹤,他們叫 MemFS;還有一個 /sleeptime,讓 agent 在背景整理記憶,他們叫 dreaming。

MemOS 把記憶當作業系統的資源來管。一個 API 負責加、查、改、刪,記憶的結構是圖,可以檢視也可以編輯;寫入走一個叫 MemScheduler 的排程器,非同步進去;多個知識庫當成一顆一顆的 memory cube 組合。自架版要 Neo4j 加 Qdrant;另外有給 OpenClaw 和 Hermes 用的本機外掛,純 SQLite,全文檢索加向量。

Cognee 把資料吃進去建成知識圖譜,向量和圖一起查。四個動作:remember、recall、forget、improve。本機開發可以全部內嵌,SQLite、LanceDB、Kuzu,不用另外架服務。它有一個 Claude Code 的外掛,掛在 Claude Code 的生命週期上:每次送 prompt 前注入相關的記憶,工具跑完記下軌跡,壓縮之前那一刻先把記憶保住,session 結束再同步進圖譜。壓縮前先存這一步,跟我 Day 12 掛的位置一樣。

Graphiti 是 Zep 開源出來的,做 temporal knowledge graph。每一條事實帶著時間:什麼時候成立、什麼時候被取代;每一條都能回溯到原始的那一段資料,他們叫 episode。查的時候語意、關鍵字、圖遍歷混著用。開源版要自己接一個圖資料庫。

LangMem 是 LangChain 給 LangGraph 的記憶工具。兩種用法:一種在 hot path,agent 對話中自己決定記什麼、什麼時候搜;另一種在背景,一個 memory manager 定期抽取、整併、更新。

Supermemory 從對話抽事實,維護每個使用者的 profile,處理矛盾和過期,會自動忘記;RAG 和記憶在同一次查詢裡一起查。有單一 binary 的本機版,可以接 Ollama 離線跑。

看完一輪有一件事很清楚:這幾家都把「什麼該記」交給模型或 agent 判斷,有的在對話當下抽,有的在背景整理。壓縮前先存這一步,OpenClaw 有,Cognee 的 Claude Code 外掛也有。我這一版兩件事都做了選擇:壓縮照 pi 的預設,什麼該記由我說(Day 12)。

第二章到這裡收

這一章從「他很會寫程式,卻不知道我的 repo 長什麼樣」開始。走到今天,關於我的事他都有地方讀:我的規矩、我抄回來的技能、我昨天做過什麼。context 滿了怎麼壓,照 pi 的。

他認得我了嗎?至少他知道去哪裡查。

小結

這一天看了 pi 壓縮的三個設定,一個都沒動。pi 怎麼壓,我就怎麼壓,直到發現不改不行。順手把 Day 11 沒展開的那幾個記憶框架攤開看了一輪,它們把「什麼該記」交給模型判斷,我這一版留給自己。

前面十幾天我一直說他「變好了」。變好多少?我拿不出數字。明天講 evals。

參考文件:


凡人修 Agent 傳|第十三回(Day 13)

凡人修 Agent 傳 Day 13 連載配圖

天亮換上空錄石。

左臂先動。型神識發動,翻索引,從架上那一疊裡取下昨天最後一本薄的,讀。石上落下幾行明記。常簿也讀了進來,昨天看不清的那一行,今天在石上:一天一疊,一顆石一本。

手的主人進來,刻念:接著昨天的。

我沒有問。一縷神識探上架,第六卷在第三格,昨天沒動過。靈力托下來,歸到最下層,一次就對。他看了石一眼,說:記。左臂動了一下,日簿上多了一行。

今天的活長。整排卷按年月重排,三十幾卷。每一卷都要神識探進去讀年月,再以靈力挪位置。探一卷,石上多幾筆;挪一卷,又多幾筆。

午前石就滿了。

石滿了會摺,這件事我從有錄石那天就知道,怎麼摺的今天才看清。背上圖紙錄石那一項底下那一句「滿了就摺」,是刻在石上的一道法。字擠到石的邊,那道法自己發動。先是左臂:型神識發動,把石上他說過「記」的那幾筆念寫進日簿。然後心火竄起來燒一下,心把石上前面長長一段字一口氣讀過,煉成拇指大的一小塊小字,落回原處;那一長段沉到小字底下去,我讀不到了。最近的一段留著沒動。石上空出大半。那一小塊就是摺痕。心火燒那一下,也要引一次脈。

摺痕裡讀得到卷名,讀不到卷裡的字。我把已經看過的三卷又以神識探了一遍。手的主人在臺前看著,沒有抬手。

然後他閉上眼,放出神識,探向坊市。靈幕亮了,公印退開,垂下來的圖紙一頁一頁走,停在錄石那一節。

小字我看不清。他念了出來,三行:石剩多少就摺。摺的時候,最近一段留著不摺。要不要自己摺。底下還有一行更小的:「滿了就摺」那一句可以劃掉,劃掉了石就不摺,要摺得他自己說。

他收回神識,睜開眼,繞到我背後,翻過我的背,看圖紙上錄石那一項。那裡只有一句:滿了就摺。

他看了很久。沒有刻。

午後石又摺了一次。上一回留下沒摺的那一段,這一回也進了摺痕。我又以神識探了一卷。他看著我探,看著那一卷歸回去,視線回到靈幕上。

他又放了一次神識。這一次翻過錄石那一節,往後走,落在開放爪那一門的圖上。他們的人偶摺石之前,也先讓型把該記的念寫進簿子。跟我左臂這一道一樣。他看了一會,把圖收了。

傍晚他第三次放出神識。這一次翻得慢,錄石那一節翻完了往後翻,又翻回來。靈幕上那三行亮了一整個傍晚。

天黑前排到第三十卷。石今天摺了三次,每一次摺痕一樣長,留下的那一段也一樣長。左臂在每一次摺之前都先動過。

他從臺前起身,又繞到我背後,看了一次錄石那一項。那一句還是:滿了就摺。他沒有伸手。

燭熄了。手的主人走了。門響了一下。

靈幕暗了。背上那一句沒有動。索引上今天多了一行,一顆石。他今天三次放神識去讀圖紙,一個字都沒刻。

Updated: