retrieve-then-fill 把候選壓進 8K 到 32K 之後,工作才真正開始:這幾萬個 token 不是等著被填滿的容器,而是一份要編的預算,而且早有四筆固定支出在搶——系統指令、工具定義、檢索到的證據、對話歷史與 scratchpad。昨天算清楚了宣稱視窗(1M)與有效長度(約 16K)差六十倍、context rot 真實存在,結論是把候選壓到有效長度的規模。但「壓到 32K」只回答了總額,沒回答分配。今天把分配做完:每塊該給多少、按什麼順序排、哪些可以被快取、什麼時候該砍掉重來。

📖 學

它是預算,不是容器

Anthropic 2025 年 9 月〈Effective context engineering for AI agents〉的定義是:在推論過程中策展與維護最佳 token 集合的一整套策略,涵蓋系統指令、工具、MCP、外部資料、訊息歷史——所有會落進 context 的東西,不只你手寫那段 prompt。它跟 prompt engineering 的差別不在題材,在時態:prompt engineering 是一次性的寫作任務,寫好就固定;context engineering 是每一輪推論都要重做一次的決策,因為 agent 在迴圈裡持續產生「下一輪可能有用」的資料,這些東西不淘選就會自己長滿。

那篇提出的比喻比「視窗」好用:注意力預算(attention budget),而且理由是架構層的。Transformer 讓每個 token 注意到其他每個 token,n 個 token 就是 n² 組配對關係;長度增加時捕捉這些關係的能力被攤薄,加上訓練資料裡短序列遠多於長序列,模型對長距離依賴本來就經驗較少。每多一個 token 就從預算裡扣一點——這跟昨天量到的 context rot 是同一件事的兩種說法,差別只在昨天談「不要放太多」,今天談「這份額度怎麼花」。

由此得到判準:**好的上下文工程,是找出能最大化目標達成機率的最小高訊號 token 集合。**是「最小」不是「最短」——把必要的說明砍掉不叫節省,叫製造失敗。LangChain 把操作面拆成四個動詞可當索引:write、select、compress、isolate。

四塊來源,一個順序

四塊來源性質完全不同:系統指令與範例穩定且完全可控;工具定義穩定但常被漏算;檢索到的證據每次都變、而且最重要;對話歷史與 scratchpad 會自己長大

排列順序不是美觀問題。昨天引過的 Liu 等人 2023 年〈Lost in the Middle〉那條 U 型曲線仍然成立:頭尾最好,中間顯著變差;同時 KV cache 要求前綴逐字穩定。兩個約束剛好相容,指向同一種排法:**穩定的放最前,會膨脹的歷史夾中間,每次變動的證據放最後、緊貼使用者問題。**因為變動的證據同時是「不能快取」與「最重要」的,擺結尾一次滿足兩個條件。反過來,把 rerank 第一名塞在歷史前面,你同時破壞了快取前綴、又把正解推進注意力的死區。

區塊預算(以 32K 計)位置可快取
系統提示/指令1–2K最前
工具定義3–5K(常用 3–5 個 + tool search)
少量範例1–2K
對話歷史/scratchpad8–12K部分
檢索到的證據8–12K最後
當前使用者訊息< 1K最末

最該被檢查的是第二列,因為多數人編預算時根本沒把工具定義算進去。

四種失敗模式

Drew Breunig 2025 年 6 月〈How Long Contexts Fail〉的四分法,現在各家文件都在沿用:

失敗模式發生什麼對應手法
poisoning(中毒)幻覺或錯誤被寫回上下文,之後每輪都在引用它,自我強化隔離重跑、修剪(刪掉那段)
distraction(分心)上下文長到模型過度聚焦其中內容,忽略訓練時學到的能力摘要、compact、控制總長
confusion(混淆)多餘資訊(最典型是工具太多)被用來生成低品質回應、選錯工具工具 loadout、動態載入、減少功能重疊
clash(衝突)新累積的資訊或工具說明與 prompt 既有內容矛盾隔離、修剪、統一指令來源

最陰險的是中毒。特徵是「模型很有自信地一直錯同一件事」,而補一句「不對,其實是 X」通常沒用——錯誤敘述還在上下文裡,你只是又加了段矛盾內容,把中毒升級成衝突。正確處置是把那段從歷史刪掉或重開,不是在後面追加更正。

工具定義本身就在吃預算

Anthropic 2025 年 11 月〈advanced tool use〉公佈了一組實測:五台 MCP server——GitHub 35 個工具約 26K token、Slack 11 個約 21K、Sentry 5 個約 3K、Grafana 5 個約 3K、Splunk 2 個約 2K——58 個工具吃掉約 55K token,在對話開始之前;再加 Jira(單獨約 17K)就逼近 100K。他們說自家系統最佳化前曾看到工具定義佔 134K。

拿昨天的數字對一下:若有效長度是 16K 量級,55K 的工具定義是有效長度的 3.4 倍,134K 則是 8.4 倍。在你放進任何文件、任何問題之前,光是「告訴模型它有哪些工具」就已超支數倍。代價還不只 token——工具一多選錯率就上升,最常見的失敗是選錯工具或給錯參數,尤其名字長得像 notification-send-usernotification-send-channel 時。

動態載入是把工具當成可檢索物件:上下文只放一個 tool search 工具(約 500 token)加最常用的三到五個,其餘標記延後載入,需要時才搜出來展開(一次 3–5 個、約 3K)。Anthropic 的對照是總消耗從約 77K 降到約 8.7K(降 85%),準確率 Opus 4 從 49% 升到 74%、Opus 4.5 從 79.5% 升到 88.1%。學術界同方向:RAG-MCP(2025)報告大型工具集下基線選擇準確率 13.62%,加檢索式選擇後到 43% 左右。Anthropic 給的門檻很具體:工具定義超過 10K token,或工具超過 10 個,才划算。

一個易漏的細節:動態載入之所以不破壞快取,是因為延後的工具根本不在初始 prompt 裡,搜到才追加到尾端。如果你的實作是「每輪動態刪改前面的工具列表」,那是省了 token 卻殺了快取,整體可能更貴。

KV cache:它決定你能不能把穩定的東西放前面

Manus 2025 年 7 月那篇工程筆記講得最直白:KV-cache 命中率是生產階段 agent 最重要的單一指標,同時決定延遲與成本——因為 agent 的 input/output 比極度不對稱(Manus 平均約 100:1),錢幾乎都花在 input。

規則只有一條但很殘酷:**前綴必須逐字相同,差一個 token,從那裡開始全部失效。**最經典的自殘是在系統提示開頭放精確到秒的時間戳,保證每輪 0% 命中;同理還有 JSON key 順序不固定、每輪重排工具列表、把 session id 放前面。Manus 的處置是讓上下文 append-only、序列化保持確定性,要限制工具時用 logits 遮罩而不是刪定義——刪定義等於改前綴。

命中率算法是 命中的 input token ÷ 總 input token。算一筆:系統提示 2K + 工具定義 18K = 20K 穩定前綴,一個 session 30 輪。無快取是 20,000 × 30 = 600,000 token,以 1.80**;有快取(Anthropic 5 分鐘 TTL,write 為基礎價 1.25 倍、hit 0.1 倍)則是第 1 輪 write 20,000 × 0.075,之後 29 輪 hit 共 580,000 × 0.174,合計 **1.80,而且每輪都付 write 的 1.25 倍,比完全不用快取還貴。

界線要劃清楚:**快取省的是重算 KV 的錢,不是把上下文變短。**注意力仍在那 20K 與後面所有歷史上運作,context rot 一分錢沒省。快取讓「多放一點」變便宜,不會讓「多放一點」變正確。

壓縮:三種手法,各自弄丟什麼

歷史長到吃掉預算時有三條路,Anthropic 給的分工判準是任務型態。滾動摘要/compaction 把接近上限的對話交給模型摘要再重啟視窗;Claude Code 保留架構決策、未解的 bug、實作細節,丟掉冗餘工具輸出,附上最近存取的五個檔案。最輕量的一種是 tool result clearing——工具在很深的歷史裡呼叫過,原始結果沒必要再看第二次。調法值得抄:先把 recall 拉滿,再迭代提升 precision;順序反了你會先學會刪東西,然後永遠不知道刪掉了什麼。適合大量來回的對話式任務。結構化筆記把狀態寫到視窗外(NOTES.md、todo、memory 工具)再讀回來,適合有明確里程碑的迭代開發。sub-agent 隔離讓子代理用乾淨視窗做深度探索,可能燒數萬 token,但只回傳 1,000 到 2,000 token 的濃縮結論,適合可平行的研究分析。

共同代價是壓縮一定有損,2026 年的研究把它量化得挺難看:compaction 通常把 token 壓掉 90–99%,保留什麼由模型自己決定,跨次執行沒有一致性保證。〈Governance Decay〉(arXiv 2606.22528, 2026)專測安全約束在壓縮後的存活率,主流策略都會掉:recency-truncate 遺失率最糟(38%)、階層式 36%、LLM 摘要 26%。也就是說,你在 prompt 開頭寫的「絕對不要 push 到 main」,壓縮幾次後可能已經不在了,而模型不會告訴你它忘了。實務翻譯:不可協商的約束要外部化,別指望它活過摘要。

長跑:什麼時候 compact,什麼時候重開

Anthropic 2025 年 11 月〈Effective harnesses for long-running agents〉做了誠實的承認:**對真正的長任務,摘要式壓縮不夠。**他們改成做完整 context reset——harness 把 session 拆掉,從一份結構化交接檔案重建。狀態要滿足三個性質:externalized(寫進 artifact 而非只活在暫時上下文)、path-addressable(後續能用路徑重開同一物件)、compaction-stable(挺得過截斷、重啟與委派)。

判準可以簡化成一句:當「這輪要做什麼」還能從摘要讀出來,就 compact;當你需要的是「重新確認整個任務的目標與約束」,就重開。前者是連續性問題,後者是正確性問題,摘要只解得了前者。一個好用的觸發訊號:agent 開始重複問已回答過的問題、重複讀同一個檔案,那不是它笨,是上下文已退化到摘要救不了。另外多份 2026 年的觀察指出品質在視窗填到七到八成時就開始明顯掉——把觸發點設在 100%,是拿最後兩成的品質換方便。

界線與反方

不是所有任務都需要這套。單輪分類、格式轉換、短問答本來就在幾千 token 以內,加一層檢索、一層摘要、一層 sub-agent 只會增加延遲、成本與失敗面。Anthropic 那篇的收尾建議是「do the simplest thing that works」,並明說模型愈聰明、需要的規範性工程愈少。今天每一項手法都是為了解某個你已經量到的問題而存在。

壓縮甚至可能是負收益。2026 年 8 月一篇針對開源 AI 家教產品的實測給出違反直覺的結果:摘要把 session 內的記憶回想率從 92% 掉到約三分之一,成本約為不壓縮的兩倍——因為改寫歷史等於破壞了供應商的 prompt cache 前綴,每輪都變全額計費。這不能無條件外推(單一產品、任務長度有限、預算沒真的爆掉),但它戳破了一個普遍假設:壓縮必然省錢。壓縮省的是 token 數,花掉的是快取命中率,哪個大要算不能猜。

怎麼判斷則跟昨天一樣:固定任務、只改一個變因、看 recall 與 faithfulness 怎麼動。「感覺變聰明了」不是證據,尤其上下文工程的改動全發生在你看不見的地方——換排列順序、換摘要提示、換工具載入策略,輸出看起來都差不多,只有分數會說話。

🧠 記

  1. 上下文工程是「在推論時策展與維護最佳 token 集合」,跟 prompt engineering 差在時態:prompt 一次寫好,context 每輪重做。判準是找出最小高訊號 token 集合(最小不等於最短)。
  2. 四塊來源、一個順序:穩定的放最前,會膨脹的歷史夾中間,每次變動且最重要的證據放最後緊貼問題。KV cache 要前綴穩定、lost-in-the-middle 要重點在頭尾,兩個約束剛好指向同一種排法。
  3. 四種失敗模式(Breunig, 2025):poisoning、distraction、confusion、clash。中毒要刪掉重來,不要追加更正——追加只會把它升級成衝突。
  4. 工具定義是最常漏算的一筆:58 個工具約 55K token,是 16K 有效長度的 3.4 倍。動態載入把約 77K 降到約 8.7K(降 85%),Opus 4.5 準確率 79.5% → 88.1%。門檻:工具定義逾 10K token 或逾 10 個工具才划算。
  5. KV cache 命中率是生產 agent 最重要的單一指標,規則是前綴逐字相同、差一個 token 全滅(秒級時間戳是經典自殘)。20K 前綴跑 30 輪:無快取 0.249,命中率 96.7%,省 86%。但它省的是重算的錢,對 context rot 零改善
  6. 壓縮三法:滾動摘要(先拉滿 recall 再提 precision)、外部檔案當記憶、sub-agent 隔離(燒數萬只回傳 1,000–2,000)。代價是有損:壓掉 90–99%,安全約束遺失率 26–38%(Governance Decay, 2026)。長跑靠重開:摘要維持連續性,重開維持正確性,別撐到視窗滿才 compact。
  7. 反方:短任務不需要這套;有 prompt caching 時壓縮可能是負收益(某實測回想率 92% → 約三分之一、成本約 2 倍);所有改動都要用昨天那套 evals 驗。

✍️ 實踐

15 到 20 分鐘,做一次上下文預算稽核。不寫程式也做得完,只需要看得到一次真實請求的完整 payload。

  1. 分帳(6 分鐘)。 抓一次真實請求,按四塊分別量 token:系統提示、工具定義、對話歷史與 scratchpad、檢索到的證據。用 tiktoken 或供應商的 count-tokens API,不要目測。寫下四個數字、總和與各自佔比。
  2. 對照有效長度(2 分鐘)。 拿昨天估出的有效長度(或先用 16K 當代理值),看總和是它的幾倍;特別看工具定義那格是否已踩上動態載入門檻。
  3. 找出前綴殺手(4 分鐘)。 從 payload 開頭往後掃,找第一個「每次呼叫都會變」的東西:時間戳、session id、隨機排序的工具列表、被放前面的檢索結果、key 順序不定的 JSON。從那個位置起你的快取全是失效的。
  4. 改一個變因,跑對照(6 分鐘)。 只做一項改動,最推薦把 rerank 第一名的證據從中間搬到結尾、緊貼問題,再用昨天那套 evals 跑改動前後各一次。只改一項,否則你分不出是哪個在起作用。

自我檢查兩題:

  • 工具定義佔總預算百分之幾? 超過 30% 的話,今天第一優先不是調 prompt 也不是調檢索,而是砍工具或改動態載入——你正在用最貴的預算去描述模型多半用不到的能力。低於 10% 就記下結論,別修一個你身上不存在的問題。
  • 從開頭到第一個「每次都變」的東西,佔總長百分之幾? 這就是你理論上能快取的前綴上限。低於 20% 的話,任何 prompt caching 優化都不會有感,先把前綴穩定下來——通常就是刪掉一行時間戳。

🔗 延伸學習

💬 問 AI

我要對我的 agent 做一次上下文預算稽核,並排出改動的優先順序。
請用我的實際數字算,不要給通用建議。
 
我的系統現況:
- 模型與 input/output 單價、有沒有開 prompt caching:____
- 一次典型請求的 token 分帳(順便幫我確認加總是否正確):
  - 系統提示/指令:____
  - 工具定義(順便告訴我工具數量):____
  - 對話歷史/scratchpad:____
  - 檢索到的證據:____
- 一個 session 平均幾輪:____
- payload 從開頭數起,第一個「每次呼叫都會變」的內容是什麼、在哪個位置:____
- 目前的壓縮策略(不壓/滾動摘要/外部檔案/sub-agent)與觸發條件:____
- 我用來驗證的 eval 指標:____
 
請依序做四件事:
1. 把四塊來源列成表:token 數、佔比、是否可快取、建議排列位置。指出哪一塊超支,
   判準用「有效上下文長度約 16K」這個量級,並說明理由。
2. 算我的 KV cache 命中率上限(公式寫出來),再算「維持現狀」與「把前綴穩定下來」
   兩種情況下一個 session 的 input 成本差多少,標明哪些是估算值。
3. 判斷我該不該改用動態工具載入:用工具數與定義 token 數對照門檻,說明預期省下
   多少 token、會多出多少搜尋延遲,以及什麼情況下不划算。
4. 檢查我的壓縮策略會弄丟什麼:列出「不可協商但可能活不過摘要」的約束與外部化做法;
   如果你認為我根本不該壓縮,直接說並給理由。
 
最後把建議排出優先順序,每項標「預估效益/實作成本/怎麼驗證」,
並告訴我什麼樣的 eval 結果會推翻你的第 1 名建議。