Claude API 的 context editing 與 memory tool 完整教學:清掉舊對話之前,先讓它把重點寫下來
2025 年 9 月 29 日,Anthropic 同一天推了兩個 beta。一個叫 memory tool,一個叫 context editing。當時多數人只注意到前者,因為「讓 AI 有記憶」聽起來比「自動清掉舊的工具結果」性感得多。
十個月後回頭看,這兩個功能的命運差很多。memory tool 已經在 2026 年 2 月 17 日轉正式版、不需要 beta header 了。context editing 到今天還是 beta。中間還冒出第三個主角,把前兩個的定位整個重排了一次。
這篇把這條時間線走完,順便把參數和踩坑點講清楚。
在那之前,這件事是你自己的問題
先講清楚問題長什麼樣,不然後面所有設計都看不出道理。
假設你寫一個 agent,它會呼叫搜尋工具。第一次搜尋回來 3,000 個 token,第二次又 3,000,跑到第三十次的時候,你的 messages 陣列裡塞了九萬個 token 的搜尋結果,其中二十七次的內容早就沒人要看了。可是它們還在,每一輪都要重新送給模型、重新計費。
2025 年 9 月之前,處理這件事完全是你的責任。你要自己算 token、自己決定砍哪幾輪、自己把砍掉的地方補一句說明,還要祈禱砍掉的那段裡面沒有後面會用到的東西。
用桌面來想這件事。你查資料的時候把二十份文件攤在桌上,真正需要同時看的大概三份。差別是實體桌子滿了你看得見,而 context 滿了是一個你事先沒感覺、撞上才知道的邊界。
第一版只會做一件事:把最舊的工具結果丟掉
初版的 context editing 只有一種策略,叫 tool result clearing,type 字串是 clear_tool_uses_20250919。最小的用法只要指定型別,其他全部吃預設值:
1 | response = client.beta.messages.create( |
那個 beta header 的日期是 2025-06-27,比功能上線日還早三個月。照抄就好,不要自己「修正」成上線日期,改了會過不去。
五個參數的預設值值得記,因為預設值本身就是一組設計判斷:
trigger 預設 100,000 input tokens,也就是超過十萬才開始清。它可以改用次數計,寫成 {"type": "tool_uses", "value": N}。
keep 預設 3。這裡的單位是 tool use 與 result 的配對次數,不是 token,很容易看錯。
clear_at_least 預設沒有值,單位是 token。exclude_tools 預設也沒有值,給它一個工具名稱陣列,裡面的工具永遠不清。
clear_tool_inputs 預設 false,意思是只清結果,模型原本發出的那個工具呼叫參數會留著。
clear_at_least 的語意是全篇最容易誤會的一個。它不是「至少清這麼多,不夠就盡量清」,而是「如果清不到這個量,整個策略就不套用」。這個設計是為了配合 prompt cache:清東西會讓快取的前綴失效,所以官方讓你設一個門檻,划不來就乾脆別動。
清掉的位置不會靜默消失,API 會放一段佔位文字,讓模型知道那裡原本有東西被移除了。清除順序是最舊的先清。
還有一個實作上最容易做錯的地方,官方特別寫了一節在講:你的 client 端不要跟著修改對話歷史。你維持完整的、沒被動過的歷史,清除是送進模型之前在 server 端發生的。你不需要、也不應該去同步那個被編輯過的版本。
完整參數長這樣:
1 | context_management={ |
一個月後,thinking 也可以清了
2025 年 10 月 28 日多了第二種策略,clear_thinking_20251015,管的是 thinking block。
它只有一個參數 keep,可以給 "all",也可以給 {"type": "thinking_turns", "value": N},N 必須大於 0。這裡有個容易看錯的單位:thinking_turns 數的是 assistant 的回合數,不是 thinking block 的數量。一個回合可能包含好幾個 thinking block,尤其在 interleaved thinking 的情況下,所以兩者不是一對一。
1 | context_management={ |
keep 的預設值依模型而異,這是這兩個功能裡唯一跟模型版本有關的細節。Opus 4.5 及之後、Sonnet 4.6 及之後預設保留全部先前的 thinking;Opus 4.1 及更早、Sonnet 4.5 及更早、Haiku 4.5 及更早則預設只保留最後一輪。官方直接給了建議:如果你的程式會跑在不同等級的模型上,把 keep 明寫出來,不要依賴各模型的預設值。
兩種策略可以一起用,但有一條硬規則:clear_thinking_20251015 必須排在 edits 陣列的第一項。這種「順序有意義」的 API 設計不常見,很值得先記下來,因為排錯了不會有語法錯誤幫你擋。
thinking 對快取的影響是雙向的。保留 thinking block 的時候快取是保住的,可以命中、可以省 input token;清除的時候,快取會從清除發生的那個點失效。所以 keep 要設多少,其實是在選「快取效能」還是「context 空間」。
中間那條後來被放棄的路
2025 年 11 月 24 日,Python 和 TypeScript SDK 加了 client-side compaction,在用 tool_runner 的時候自動摘要對話。
這條路現在不建議走了。compaction_control 這個參數已經在 Python、TypeScript、Ruby SDK 標記棄用,啟用時會噴 deprecation warning,未來版本會移除。
它被放棄的理由裡有一個很值得看,因為它是一個真實的計算錯誤。SDK 算對話長度的方式是把 input_tokens、cache_creation_input_tokens、cache_read_input_tokens、output_tokens 全加起來。問題是當你用 server-side 的工具時,cache_read_input_tokens 含的是那個工具內部好幾次 API 呼叫的累積值。官方舉的例子是 63,000 加 0 加 270,000 加 1,400 等於 334,400,而真實的 context 可能只有 63,000。結果就是 compaction 被過早觸發,明明還很空就開始摘要。
2026 年 2 月,主角換人
2026 年 2 月 5 日,compaction API 進 beta,edit type 是 compact_20260112,beta header 是 compact-2026-01-12。這次是 server-side 的。
十二天後,2026 年 2 月 17 日,memory tool 轉 GA,不再需要 beta header。
到這裡定位就重排完了。官方在 context editing 文件最上方直接表態:對大部分使用情境來說,server-side compaction 才是長對話的主要策略,而 context editing 這一頁的策略適用於「你需要更細緻地控制清掉哪些內容」的場景。
兩者的差別用一句話講完:一個是清除,一個是摘要。
清桌子跟寫會議記錄不是同一件事。清桌子快、便宜、不會扭曲任何東西,但被清掉的就是沒了。寫會議記錄會保住脈絡,代價是要有人(同一個模型)花時間讀完再寫,而且摘要總是會失真。
實作上還有一個差別很關鍵:context editing 你的 client 不用同步狀態,維持原始歷史就好;compaction 的回應會帶一個 compaction block,你必須原樣傳回。這是兩種完全不同的整合複雜度。
順帶提一個容易誤會的地方。context editing 目前支援的 edit 型別就只有 clear_tool_uses_20250919 和 clear_thinking_20251015 兩種,沒有第三種,也沒有被淘汰的舊型別。compact_20260112 雖然也放在 context_management.edits 裡,但它屬於另一個 feature、另一個 beta header,不算 context editing 的策略。這兩句話很像,混用會寫出錯的東西。
至於支援的模型,官方對 context editing 只有一句「所有支援的 Claude 模型」,沒有列表。memory tool 是「Claude 4 及之後的所有模型」。compaction 那邊倒是有明確清單,但那份清單不能套到 context editing 頭上。
memory tool:模型只會「請你」寫檔案
memory tool 最需要先講清楚的一件事:它是 client-side 的。
官方的說法是「Claude requests file operations, and your application executes them」。模型只是發出請求,實際的檔案操作是你的程式去做,儲存在哪裡、怎麼存、由誰控制,全部是你的。那個 /memories 路徑只是一個前綴,你的 handler 把它對應到真實的儲存體,可以是每個使用者一個目錄,也可以是資料庫裡的一批 key。
宣告方式極簡,整個設定就是這一行,name 必須是 memory,不需要自己定 input schema:
1 | tools=[{"type": "memory_20250818", "name": "memory"}] |
command 一共六個,這就是全集:view、create、str_replace、insert、delete、rename。幾個細節值得知道:str_replace 的 new_str 是選用的,省略就等於刪掉 old_str;insert 是插在 insert_line 之後,給 0 表示插在檔首;delete 和 rename 都不能對 /memories 本身操作,你的 handler 要自己拒絕。
有意思的是回傳字串不是硬規格。官方寫「Claude reads whatever text your tool result contains」,所以那些 File created successfully at: {path} 之類的訊息只是建議行為,你想回別的也可以。create 也一樣:官方參考實作是「檔案已存在就回錯誤」,但工具描述告訴模型 create 是「creates or overwrites」,所以你會收到對已存在路徑的 create 呼叫,改成覆寫是合理的實作選擇。
不想自己刻的話,四個 SDK 有 helper。Python 和 C# 是繼承 BetaAbstractMemoryTool,TypeScript 用 betaMemoryTool,Java 實作 BetaMemoryToolHandler。Python 和 TypeScript 另外附了現成的本機檔案系統版 BetaLocalFilesystemMemoryTool。Go 和 Ruby 沒有 helper,得自己跑 tool-use loop。
1 | import anthropic |
注意 helper 和 tool_runner 都掛在各 SDK 的 beta namespace 底下,即使 memory tool 本身已經 GA。
還有一件事我覺得最少人知道:只要你的 tools 裡出現 memory tool,API 會自動幫你在 system prompt 加一段 MEMORY PROTOCOL,你不用自己送。內容大意是「做任何事之前先 view 你的記憶目錄」,最後那句寫得很直白:
1 | ASSUME INTERRUPTION: Your context window might be reset at any moment, so you risk |
假設自己隨時會被中斷。這句話某種程度上就是整個功能的設計哲學。
兩個一起用,才是它們被設計出來的樣子
單獨看,context editing 是省 token 的工具,memory tool 是跨對話記憶的工具。合起來才會出現那個真正的機制:
1 | response = client.beta.messages.create( |
官方對這個組合的說明是關鍵:當 context 接近設定的清除門檻時,Claude 會收到一個自動警告,提醒它保存重要資訊,於是它可以在那些工具結果被清掉之前先寫進 memory 檔案。
回到桌子的比喻。清桌子的人要來之前先喊一聲「十分鐘後收桌」,你就有機會把還需要的東西抄到筆記本上。沒有那一聲,清桌子就只是單純的損失;有了那一聲,清除變成一個可以規劃的動作。
這也是為什麼「先學哪個」的答案是兩個一起學。memory tool 和 compaction 官方同樣建議併用:compaction 讓活躍的 context 保持精簡,memory 保住那些必須活過摘要的東西。
官方那三個百分比,容易引錯
網路上到處在傳「39% 和 84%」,但這兩個數字被引用的方式常常是錯的。它們出自 2025 年 9 月 29 日的官方公告,不在 API 文件頁上,而且全部是 Anthropic 內部評測,不是公開 benchmark。
39% 是 memory tool 加上 context editing 併用,相對 baseline 的表現提升。只用 context editing 的話是 29%。所以把 39% 說成「context editing 的效果」是錯的。
84% 完全是另一回事。它出自一個 100 回合的網路搜尋評測,指的是token 消耗的減少幅度,不是正確率提升。把它跟 39% 並列寫成「效果提升 39%、84%」,等於把兩個不同軸的指標黏在一起。
官方沒有公布這些評測的樣本數、baseline 設定與評測集細節。要引用就把「內部評測」四個字寫在句子裡。
會踩到的地方
prompt cache 是第一個。tool result clearing 只要清了東西,快取前綴就會失效,每次清除都會產生 cache write 成本,之後的請求才能重用新的前綴。這就是 clear_at_least 存在的理由:確認這次清除清得夠多,值得打掉快取。
clear_at_least 的門檻語意再說一次,因為真的很容易寫錯:達不到就整個策略不套用,不是清少一點。
memory tool 這邊最需要小心的是路徑穿越,官方用 Warning 等級標示。像 /memories/../../secrets.env 這種路徑可以摸到目錄外面的檔案,而執行檔案操作的是你的程式,所以驗證每一個 command 的每一個路徑是你的責任。官方建議的做法是所有路徑必須以 /memories 開頭、resolve 成 canonical form 之後確認還在目錄內、拒絕 ../ 和 ..\、注意 URL 編碼過的 %2e%2e%2f,Python 就用 pathlib 的 resolve() 配 relative_to()。
這裡有個很誠實的細節:官方自己的 Go、PHP、Ruby 範例是 in-memory 示範版,跳過了路徑驗證,文件也明寫正式環境的 handler 需要補上這些範例省略掉的驗證。照抄官方範例上線,這一刀就是自己挖的。
另外兩件小事。敏感資訊方面,Claude 通常會拒絕把敏感內容寫進 memory 檔案,但官方建議你要更強的保證就自己加一層過濾再寫檔。檔案大小要自己追蹤設上限,並限制 view 回傳的字元數,讓模型用 view_range 分頁讀。
怎麼確認它真的清了
這是我認為最該先寫進監控的部分。回應裡會多一個 context_management 欄位:
1 | "context_management": { |
串流的時候它出現在最後的 message_delta 事件裡,同樣掛在 context_management.applied_edits。
上線之前想先估效果的話,token counting 端點吃同一組 context_management 參數,回應會給 context_management.original_input_tokens,跟 input_tokens 相減就是省下來的量。這比直接上生產環境再看帳單便宜得多。
還沒走完的部分
把時間線攤開會看到一個有意思的現象:後上線的 compaction 已經被官方指定為主要策略,而早它四個月上線的 context editing 到今天還掛著 beta。
官方文件目前也還有沒說清楚的地方。context editing 沒有逐一的模型支援清單,只有一句「所有支援的 Claude 模型」。context editing 的策略和 compact_20260112 能不能放進同一個 edits 陣列併用,兩邊的文件都沒有範例,也沒有明文禁止。trigger 改用 tool_uses 型別時的預設次數是多少,文件只給了 input token 的那一個預設值。
這些空白通常會被下一版文件填掉,或者被某個人踩過之後寫在 issue 裡。如果你正在做長時間執行的 agent,那個「清除前的自動警告」值得先接起來試,它是這三個功能裡唯一一個把「遺忘」變成可規劃動作的機制。
誠實邊界:本文的參數、預設值、command 清單、回應欄位與那三個百分比,全部來自官方文件與 2025-09-29 官方公告的原文,查證日期 2026-08-04。我沒有實跑過每一種參數組合,尤其 clear_at_least 達不到門檻時的實際行為、以及跨模型 keep 預設值的差異,都是照文件敘述整理,沒有自己的實測輸出。文中標為「官方文件未說明」的部分就是查不到,不要當成我漏寫。
延伸閱讀:CLI 端的對應機制可以看 Claude Code 的 /compact:對話變慢變鈍前,先搞懂壓縮到底在丟什麼,快取那條線可以看 Prompt Caching:讓 Claude 別再重讀同一份文件。


































































































































































