本文為《AI 輔助維運工程:從 Claude Code 機制到企業落地》系列第 3 篇。前一篇談了 Agent Loop,這一篇會進入這個系列裡技術密度較高的主題。如果你之前對「為什麼我的 context 會突然不夠用」、「
/compact到底何時該按」、「Claude 為什麼突然開始忘東西」這些問題感到困惑,這篇會把這些機制一起拆開來看。
為什麼需要整整一篇寫這件事
前一篇講了 Agent Loop —— 每一輪模型呼叫,都要把整段對話歷史送進 API。
這件事在對話短的時候沒人會在意。但當任務開始變長:
- 一個跨 10 個檔案的重構
- 一次完整的事件排查
- 一份規格文件從草稿到定稿的對話
你會發現一個令人焦慮的現象:Claude Code 開始回應變慢、帳單變貴、有時候甚至主動告訴你「context 快滿了」。
根本原因在於 context window 的物理上限。以目前主流的 Claude 模型來說:
- 舊一代模型(例如 Sonnet 4、Sonnet 4.5):上限 200K tokens
- 新一代模型(Opus 4.6 / 4.7、Sonnet 4.6):上限提升到 1M tokens,且自 2026 年 3 月起已 GA 無溢價
聽起來 1M 似乎什麼煩惱都沒了?實際沒這麼簡單 —— 稍後會有一節專門談「1M 不是萬靈丹」。這裡先建立一個共識:不論你用哪一代模型,壓縮管線的設計原理都一樣,只是觸發閾值不同。
一個五小時的維運任務,搭配幾份被讀進 context 的大型設定檔,即使在 200K 窗口也會消耗得比你想像快。
如果 Claude Code 對這件事不做任何處理,用戶體驗會是這樣:
使用到 80%:正常 80% → 95%:越來越慢,因為每一輪都在傳巨量 context 95% → 100%:API 開始拒絕,因為超過模型上限 100% 之後:session 直接掛掉,你要從頭來過
所以 Claude Code 設計了一套系統,在你不察覺的情況下,持續清理 context 空間。這套系統有四層,每一層用不同策略,對 token 的衝擊從「幾乎零成本」到「呼叫一次 API 做摘要」不等。
這篇文章要做的,就是把這四層攤開來。
為什麼不能只用一種壓縮策略
你可能會想:為什麼不直接一招?等 context 滿了再叫模型摘要不就好?
這會有兩個問題。
問題一:摘要本身很貴。讓模型把 100K tokens 的對話摘成 20K tokens,這個動作就要再花一次 API call,還要花 output token 產生那 20K 摘要。如果每隔幾輪就做一次,光摘要就吃光你的預算。
問題二:過早摘要會丟失資訊。你不會希望一個還在處理中的子任務被摘成三句話 —— 模型會失去它需要的細節,回應品質直接掉下來。
合理的設計是:先用最便宜的手段釋放空間,真的不夠了再用昂貴的手段。這就是四層管線的核心思想。
四層管線的全景
在每一輪 Agent Loop 準備呼叫 API 之前,Claude Code 會依序跑過下面這些階段:
┌─────────────────────────────────────────────┐
│ Pre-pipeline: Tool Result Budget │ ← 過大 tool result 的預先處理
└─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Layer 1: Snip Compact │ ← 零成本修剪
└─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Layer 2: Micro Compact │ ← tool result 壓縮
└─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Layer 3: Context Collapse │ ← 投射式壓縮
└─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Layer 4: Auto Compact │ ← API 摘要(最貴)
└─────────────────────────────────────────────┘
│
▼
[送進 API 呼叫模型]
每一層都有它啟動的條件、代價、和清出空間的能力。我們一層一層拆。
Pre-pipeline:Tool Result Budget
這一層嚴格來說不是壓縮,是預防性措施。
場景:Claude Code 執行了一個 Bash: cat /var/log/nginx/access.log,檔案有 80MB。如果這 80MB 整個塞進 context,後面的管線會瞬間爆炸。
Tool Result Budget 做的事就是在 tool 執行結果進入 context 之前,先判斷它的大小。超過門檻的,會被內容替換(content replacement)—— 把原始龐大結果換成一個摘要訊息,原始內容寫入磁碟保留,context 裡只放一個引用。
這個設計很精巧的一點是:替換狀態跨壓縮持久化。也就是說,即使後面 Layer 4 做了大摘要,這個「被替換過的 tool result」的記憶不會丟失,模型還是知道「剛才跑了那個指令,結果很大被外存了」。
對你的影響:你不太需要關心這一層,它自動運作。但知道它存在有一個好處 —— 當你看到 tool result 被標記「truncated」時,那不是 bug,是這個機制在保護你。
Layer 1:Snip Compact(零成本修剪)
接下來進入壓縮管線的第一層,也是最便宜的一層。
Snip Compact 做的事情可以用一句話概括:把舊的、明顯可以丟的片段直接刪掉。
什麼叫「明顯可以丟」?典型的例子:
- 很多輪之前的一個
Bash: ls指令和它的輸出 - 已經被後續行為覆蓋的舊檔案讀取結果
- 使用者已經明確說「這個不用了」的段落
這一層的關鍵特徵是 「零成本」 —— 它不呼叫 API、不做推理、只是按規則把某些 message 從 context 移除。計算開銷幾乎為零,釋放的空間卻可能非常可觀。
類比:就像你整理辦公桌時,先把明顯沒用的廢紙丟掉,還沒開始動需要判斷的東西。
Snip Compact 在每一輪都會跑,永遠是第一道防線。你幾乎察覺不到它在作用,但它默默為你省了大量空間。
Layer 2:Micro Compact(tool result 壓縮)
第二層開始有點技巧了。
Micro Compact 聚焦在處理 tool result。上一層刪了能直接丟的,但有些 tool result 還有價值 —— 模型可能之後要引用 —— 只是詳細程度過頭了。
舉例:你讓 Claude Code 讀了一個 500 行的設定檔,它讀完後做了分析,已經從裡面抽出重點。兩輪之後,完整的 500 行內容還佔著 context。這時候 Micro Compact 會做的事情是:
保留這個 tool result 的「殼」(它的 tool_use_id、它是哪個 tool、執行成功與否),但把詳細的內容替換成一個摘要。
關鍵設計:Micro Compact 以 tool_use_id 為單位運作,不拆解內容、不重組訊息結構。這讓它可以跟其他層安全組合 —— 它的處理不會影響訊息格式的完整性。
相較於 Layer 1:Layer 1 是「整段丟」,Layer 2 是「保留外層、壓縮內容」。Layer 2 的成本比 Layer 1 高一點(要產生摘要),但保留了可追溯性 —— 模型仍然知道「我剛才讀過某個檔案」。
Layer 3:Context Collapse(投射式壓縮)
這一層的設計最巧妙,也最難懂。
一般壓縮的做法是「修改 context 本身」—— 刪掉某些東西、取代某些內容。但這有個風險:修改是不可逆的。你丟掉的東西,就真的丟了。
Context Collapse 採用完全不同的思路:不修改底層的訊息歷史,而是建立一個「投射視圖」(projective view)。
用一個比喻:
想像你的對話歷史是一棟三層樓的書櫃,整整齊齊放著所有 message。 傳統壓縮是把某幾本書從書櫃搬走、直接丟掉。 Context Collapse 是在書櫃前面加一片毛玻璃 —— 書櫃本身沒變,但從外面看,某些書被遮住了,只看得到一個整體的輪廓。
這個設計的好處是:
- 可還原:必要時可以把毛玻璃拿掉,完整歷史還在
- 適合長 session:即使做了多次 collapse,底層訊息仍然保存
- 給模型一個「精華版」:模型看到的是投射後的版本,而不是原始的完整對話
Context Collapse 的觸發有兩個門檻:
- 到達 90% 時:開始做 collapse commit(把舊的 message 封存進 collapse log)
- 到達 95% 時:進入 blocking 模式,禁止新的 tool 執行,避免 context 爆炸
Context Collapse 是一個功能開關(feature flag),不是所有版本的 Claude Code 都預設啟用。如果啟用了,它會取代 Layer 4 的工作(兩者互斥)。
對你的影響:如果你的版本啟用了這層,你會發現長 session 的品質比舊版本明顯穩定。但如果沒啟用,接下來的 Layer 4 就是最後防線。
Layer 4:Auto Compact(最重的手段)
前三層都還沒能把空間清出來夠用?好,Auto Compact 登場。
這是最貴、也最強的一層。它的做法是:
- 開一個分叉的 agent(forked agent)
- 這個 agent 的任務就是:把到目前為止的對話歷史,摘要成一段簡短的文字
- 把原本的對話歷史替換成這段摘要
- 繼續跑主 session
本質上,這是花一次 API call 去換 context 空間。成本高,但效果也最顯著 —— 幾十萬 tokens 可以瞬間被壓成幾千 tokens。
閾值的數學
Auto Compact 什麼時候觸發?這有明確的公式:
effective_window = context_window - 20,000 ← 保留給摘要輸出的空間
threshold = effective_window - 13,000 ← 再留一個緩衝
套用到不同的 context window:
200K 窗口(Sonnet 4 / 4.5 等舊一代模型):
effective_window = 200,000 - 20,000 = 180,000
threshold = 180,000 - 13,000 = 167,000 ← 約 83.5%
意思是:當 context 用到 167K 左右時,Auto Compact 自動觸發。
1M 窗口(Sonnet 4.6、Opus 4.6 / 4.7):
effective_window = 1,000,000 - 20,000 = 980,000
threshold = 980,000 - 13,000 = 967,000 ← 約 96.7%
也就是說,1M 模型要撐到 967K 才會觸發 Auto Compact。實務上大多數 session 根本打不到這個數字,Auto Compact 在 1M 模型上幾乎不會被自動觸發。
為什麼都留 20K 給摘要?因為摘要本身也是 output tokens,也要在 context 裡佔位置。如果不預留,摘要還沒生出來就超標了。這個設計不隨 window 大小變。
要查自己目前的 window 大小,在 Claude Code 裡輸入 /context 指令,它會回傳 Xk/200k 或 Xk/1000k 的格式告訴你。
互斥規則
Auto Compact 有幾個情況不會觸發,原因都很務實:
| 情境 | 為什麼不觸發 |
|---|---|
正在做 /compact 或 session memory 操作 | 避免遞迴(本身就是 compact agent) |
| Context Collapse 已啟用 | Layer 3 已經在做這件事 |
| Reactive Compact 模式 | 等 API 真的回傳「context 太長」錯誤才處理 |
| 連續失敗超過 3 次 | Circuit breaker,避免無限重試 |
那個 3 次連續失敗 circuit breaker 很值得一提 —— 它的存在是因為沒這個機制的時候,曾經有 session 連續失敗 50 多次,浪費了大量 API 呼叫。工程設計常常是這樣:一個看似簡單的保護機制,背後都是血淚史。
Session Memory:被忽略的精巧設計
Layer 4 有個優先嘗試的輕量版,叫 Session Memory Compaction。
相較於「開一個 agent 做全摘要」,Session Memory 更像「智慧修剪」—— 它不重新生成內容,而是有策略地挑選哪些 message 保留、哪些捨棄,試圖在不花一次 API call 的情況下達到目標。
觸發順序是:Session Memory 先試 → 失敗才走 full compact。這又是一個「便宜的先試,貴的最後上」的設計。
為什麼這樣排序:一個簡單的經濟學
回頭看這四層,你會發現它們的排列是有嚴格邏輯的:
| 層級 | 成本 | 空間釋放量 | 資訊損失 |
|---|---|---|---|
| Pre-pipeline | 低 | 視 tool result 大小 | 最小(可還原) |
| Layer 1 Snip | 接近零 | 小到中 | 小(丟的是舊東西) |
| Layer 2 Micro | 低 | 中 | 小(保留摘要) |
| Layer 3 Collapse | 中 | 大 | 最小(投射式) |
| Layer 4 Auto | 高 | 最大 | 中至大(看摘要品質) |
從成本最低的開始試,能釋放多少算多少;前面的不夠用,才動用更貴的手段。
這就是這套系統背後的思路:對我而言,把 context 當成需要主動管理的資源,比交給運氣靈光來得安心一些。
1M 不是萬靈丹:你該知道的真相
看到這裡你可能想:「那我只要用 1M 模型,這四層壓縮我幾乎不用管了?」
技術上成立,但實務上要打一個大問號。
模型的 recall 能力會隨 context 膨脹衰減
window 變大 ≠ 模型能好好使用全部空間。
Anthropic 公佈的 MRCR(multi-needle retrieval)測試結果:
| 模型 | 256K 時的 recall | 1M 時的 recall |
|---|---|---|
| Opus 4.6 / 4.7 | 93% | ~76–78% |
| Sonnet 4.5(舊款) | — | 18.5%(不建議用) |
| Sonnet 4.6 | 未公佈 | 未公佈 |
白話翻譯:你塞越多 context 進去,模型忘記東西的機率越高。即使技術上 window 能裝,模型的注意力會被稀釋。
實務上多數 session 根本用不到 1M
根據社群的實測觀察,大多數 Claude Code session 峰值落在 80K–120K tokens。真正需要用到 500K 以上的場景不多,通常是:
- 跨多個大型 codebase 的全域重構
- 一次讀入幾十份長篇文件做綜合分析
- 超長時間的自主 agent 任務(連續跑幾小時)
日常維運、除錯、寫規格這類工作,200K 都綽綽有餘。
1M 模型最實際的價值:降低 compact 頻率,不是撐更久
比較合理的用法不是「把 1M 塞滿」,而是:
- 在 80K–150K 的正常使用範圍內,讓你不用頻繁擔心壓縮觸發
- 遇到偶發的大型任務,不用馬上切 session 或
/compact - 多一點彈性去讀幾個額外的參考檔案
換句話說,1M 是把「context 緊張」這件事推到後景,而不是讓你可以永遠不管它。
如果你在用 Pro 方案
Max / Team / Enterprise 方案是自動啟用 1M。Pro 方案需要手動執行 /extra-usage 才會開啟 —— 這是 Anthropic 有意識的設計,讓付費層級自然區分。
如果你在 Pro 而沒跑過 /extra-usage,你現在用的是 200K,不是 1M。可以用 /context 確認當下狀態。
環境變數可以強制關閉
少數場景你可能想強制只用 200K(例如為了控制成本、或在舊模型間切換時保持一致),可以設:
export CLAUDE_CODE_DISABLE_1M_CONTEXT=1
設了之後,model picker 不會出現 1M 選項。適合團隊統一環境配置時使用。
使用者能做什麼:主動 vs 被動
理論講完,來講實務。作為使用者,你不用去控制這四層(它們自動運作),但你有主動權在幾個關鍵時刻可以介入。
時機一:子任務結束時,主動 /compact
很多人以為 /compact 只在 context 快滿時才要用。這是我自己一開始也誤解的地方。
更聰明的用法是:每次完成一個子任務後,主動執行 /compact。
為什麼?因為自動觸發永遠是被動的 —— 要等到真的快滿了才動。而你完成一個子任務時,你最知道:
- 哪些前面的細節可以丟(「已經完成,結果正常」)
- 哪些需要保留(「這個決策後面還要用」)
- 下一個子任務需要什麼 context 基礎
這時候主動 /compact 並帶上 custom instruction,可能會比自動摘要更貼近你的需求。
範例:
/compact 重點保留:檔案修改清單、錯誤修正紀錄、未完成的 TODO。
可以丟掉:一般探索性的 bash 輸出、已經確認正確的讀檔結果。
時機二:切 session,不要依賴壓縮
壓縮再強,也比不上「開新 session」乾淨。
當你要換一個完全不同的任務(例如從「debug production」切到「寫下週的週報」),最好的做法不是在同一個 session 裡繼續,而是:
- 把當前進度寫進一個檔案(例如
PROJECT_STATUS.md) - 結束當前 session
- 開新的,從頭讀那個檔案作為起點
這比指望四層壓縮都要來得乾淨一些。
時機三:知道何時該停
有一個啟示來自前面的 3 次失敗 circuit breaker:如果 Claude Code 開始頻繁觸發 Auto Compact,那是警訊。
頻繁觸發代表你的任務規模已經超過 session 能舒服處理的範圍。這時候該做的不是「讓它繼續撐」,而是:
- 切分任務(拆成幾個小任務分 session 做)
- 檢查你的 CLAUDE.md 是不是寫得太長
- 檢查你是不是讀了一堆其實不需要的檔案進來
長 session 的壓力累積是真實存在的。管理 context 的最好方法,是從一開始就不要讓它膨脹。
幾個容易踩的雷
雷一:以為 /compact 是魔法按鈕
/compact 會丟資訊。即使你寫了 custom instruction,摘要還是會漏細節。該備份的關鍵結論,請寫進檔案。
雷二:在重要決策前觸發壓縮
如果 Claude Code 正在做一個關鍵判斷(例如「要刪哪些檔案」),不要在這時候手動 /compact —— 它可能把剛才的分析摘掉了,決策品質會受影響。等決策完成再壓縮。
雷三:盲目追求「context 撐越久越好」
有些人把「能不能不用壓縮撐完一個 8 小時 session」當成成就。這是誤解。能把任務切成小塊分段做,每段乾淨結束,才是更好的工程實踐。
一個我自己偏好的心態
四層壓縮聽起來很複雜,但它主要提醒一個觀念:
Context 是工程資源,不是取之不盡的倉庫。
你用任何工具時都有資源觀念 —— 記憶體、磁碟、網路頻寬都有上限。AI 助理的 context 也一樣,只是它太新,大家還沒建立習慣。
有這個觀念之後,我自己覺得一些選擇變得比較自然:
- 不會寫 10 頁的 CLAUDE.md
- 不會把整個 codebase 丟進對話
- 會主動切 session
- 會在關鍵時刻
/compact - 會把結論寫進檔案,而不是記在對話裡
這些習慣累積起來,我覺得是「比較熟練使用 Claude Code」跟「一直踩雷」之間一個比較明顯的分野。
下一篇預告
接下來第 4 篇要談另一個常被混淆的主題:Sub-agent 與 Agent Team。
這兩個概念一直被工程師當成同一件事,實際上它們解決的是完全不同的問題 —— 一個是「怎麼讓 AI 跑得更快」,另一個是「怎麼讓 AI 聽話、有紀律」。
下一篇我們釐清這個誤會,並示範它們怎麼搭配使用。
本篇重點整理
- Claude Code 的 context 管理不是黑盒,是一套四層的壓縮管線,從便宜到昂貴依序嘗試
- Pre-pipeline:處理過大的 tool result,防止污染整個管線
- Layer 1 Snip:零成本修剪,刪掉明顯可丟的舊片段
- Layer 2 Micro:以 tool_use_id 為單位壓縮 tool result,保留外殼丟掉內容
- Layer 3 Collapse:投射式壓縮,建立 view 而不修改底層 —— 最巧妙的一層
- Layer 4 Auto Compact:最貴的手段,用一次 API call 換大量空間;閾值約 window 的 83.5%(200K)或 96.7%(1M)
- Session Memory:Layer 4 會先試的輕量版,不呼叫 API 就能做修剪
- 1M 不是萬靈丹:window 變大但模型 recall 能力會衰減,實務多數 session 根本用不到 1M
- 主動介入時機:子任務結束時
/compact、切 session 而不硬撐、知道何時該拆任務 - 核心觀念:把 context 當工程資源管理,而不是賭運氣
本文作者:鄧景仁 (Scott Teng) | 資訊服務業 infra 工程師,專注於 Azure / Linux / 安全維運。如需討論可聯繫 st333117@gmail.com。
本系列所有內容為個人學習與實務心得整理,不代表任職機構立場。本文對 Claude Code 內部機制的描述,基於社群對 Claude Code 的公開分析材料與筆者實務觀察,並非 Anthropic 官方文件。具體閾值與行為可能隨版本演進。