Skip to content

讓 agent 便宜又快:成本拆解、關鍵路徑與 harness 架構|Harvard CS2680 第 8 堂

2026年10月21日1 分鐘
TL;DRCS2680 第 8 堂(2026-10-07)分兩半。前半拆 agent 的帳單:成本是一條乘式,使用者數 × 每人 session 數 × 每個 session 的 turn 數 × 每個 turn 的 step 數 × 每個 step 的 token 數 × 每個 token 的價格,後四項是你能砍的。學生自己的 Claude Code 紀錄顯示,97.6% 的 token 是命中快取的重讀,所以「prefix 要穩定」比「prompt 要短」更重要。速度看的是關鍵路徑,不是每一步加總。後半比較三種 harness 架構(單體、模組化、微核心)與八個開源或商用 harness 的設計取向。本文用一張手算帳單示範:把時間戳放進 system prompt 開頭,同一個任務的帳單會從 23.6 單位變回 65 單位以上。

查詞與收藏

正在載入查詞工具…

🌏 English version

影片狀態:課程不錄影。 本文依公開投影片與課程筆記整理,數值例子為本站補充。來源說明

CS2680 第 8 堂在 2026 年 10 月 7 日上課,題目是〈Agent design V: cost-effective agents〉(投影片),配套的課程筆記是〈Cost-effective agents〉。前幾堂教你把 agent 做出來、量它好不好;這堂問的是,做出來的 agent 為什麼這麼貴、這麼慢,又該怎麼改。

這堂要回答三個問題:agent 的成本從哪來、該先砍哪一項?延遲卡在哪?harness 要組成什麼結構?讀完之後,你應該能拿一段 agent session 的 token 帳單,指出最大的成本因子,並提出一個不會拉低成功率的改法。

投影片分兩段,中間沒有過渡頁:成本與速度(p5–38),harness 架構與八個 harness 的比較(p39–53)。本文照這個順序分成兩半,用一句話接起來:省錢、加速的手段想清楚之後,下一個問題是這些手段要放進什麼樣的程式結構裡。這堂只談模型呼叫的花費,不算其他運算成本(p5)。

前半:成本與速度

成本是一條乘式

先回想 session 的結構:一個 session 有好幾個 turn,一個 turn 是你送出一句話到 agent 回覆你;一個 turn 裡又有好幾個 step,每個 step 是一次模型呼叫或一次工具呼叫(p6)。投影片把總成本寫成一條乘式(p7):

成本 = 使用者數 × 每人 session 數
     × 每個 session 的 turn 數 × 每個 turn 的 step 數 × 每個 step 的 token 數
     × 每個 token 的價格

前兩項是產品做得好、用的人多,要讓它長大。後四項是 agent 每次怎麼跑,要讓它變小。這堂接下來就是逐項看後四項。

學生自己的帳

講師拿修課學生在作業 1、作業 2 交上來的 Claude Code session 紀錄當例子,這是整堂最有說服力的數字:

量什麼作業 1作業 2頁
只有一句 prompt 的 session 比例68%75%p8
每個 turn 的 step 數(中位數)34p10
主 agent 每個 step 的 token 數(中位數)208K301Kp13
第 500 步左右的 context 大小670K650Kp14

最後一張圖最重要(p15),它拆開作業 1 全部 step 的 token。前兩欄是投影片的數字,最後一欄是本文把份額乘上價格比換算出來的。價格比照投影片寫的 1 : 10 : 50,沒算寫入快取的加價;照 Anthropic 5 分鐘快取的 1.25× 算,寫入的份額約 18%,cache read 仍約 68%:

類別token 份額價格比換算成金額的份額
命中快取的重讀(cache read)97.6%1約 71%
第一次送進去的新內容(cache write)2.0%10約 15%
模型輸出0.4%50約 15%

cache read 打了一折,仍是帳單最大的一塊。這和第 2 堂說的「花費大多落在命中快取的重讀上」是同一件事。

四個槓桿

少一點 turn。 第 k 個 turn 要重讀前面 k−1 個 turn,所以總成本大約隨 turn 數的平方成長(p9)。快取讓重讀變便宜,但重讀的量還是平方成長,只是係數變小。使用者回頭追問,多半是因為沒有計畫、做到一半停了、或沒檢查就交差。對應的做法是:動手前先確認目標與計畫、把任務拆成各有完成條件的子任務、交回之前先跑測試。

少一點 step。 每一次模型呼叫都要重讀整份 context,所以呼叫次數少就便宜(p11)。投影片的例子是同樣做三個動作:一次做一個要 4 次模型呼叫,先規劃、再一次發出 3 個平行工具呼叫只要 2 次。另外兩招是重用以前成功過的計畫與 skill,以及一開始就把需要的檔案讀進來,不要每步讀一個。

每個 step 少一點 token。 留在 context 裡的 token,之後每一步都要再付一次錢(p16)。input 這邊的做法,大多是第 4 堂講過的 context 管理。例如截掉用過的工具輸出、把舊對話摘要成狀態、只保留錯誤訊息而不是整份 log。大檔可以存到檔案裡只傳路徑,探索可以交給 subagent,只拿回一段摘要。output 這邊有三招(p18–19):

  • 在 prompt 裡講清楚長度與格式,例如「100 字以內」「只回 JSON」。
  • 在 API 設 max_tokens 上限。缺點是會在句子中間截斷,推理也可能先把額度用完。
  • 用只含必要欄位的 schema,並依步驟調整推理強度:查資料用低 effort,規劃與除錯用高 effort。

每個 token 便宜一點。 這裡有三條路:

  • 快取與批次。 投影片列出 Claude API 相對一般 input 的價格(p21):output 5×、一般 input 1×、批次 input 0.5×、命中快取的 input 0.1×、批次加快取 0.05×。對應的做法是讓 prefix(每次請求開頭那段相同的內容)保持穩定,例如 system prompt、工具定義、早期對話,等得起的工作(評估、回填、大量作業)丟批次。
  • 模型路由(p22)有三型。第一型是事先選:每個 turn 開始前用一個路由器挑模型。第二型是失敗才升級:先用便宜模型,檢查沒過再換強的。第三型是每步重選:依目前的軌跡與剩餘預算決定。難處在於,便宜模型的一個規劃錯誤,可能讓後面浪費很多步。
  • 系統面的技術:MoE、量化、蒸餾、speculative decoding、KV cache 最佳化、更快的 kernel 等,投影片只列名稱,留到 Part II(p23)。

p21 的倍率要對照現價看。下表是 2026-10-22 查 Anthropic 定價頁 的結果:

項目投影片 p212026-10-22 現價
output5×5×,各模型一致
批次 input0.5×0.5×,可以和快取折扣疊加
命中快取的 input0.1×多數模型 0.1×;Opus 5.5、Sonnet 5.5 是 0.05×,Fable 5.1、Mythos 5.1 是 0.025×
寫入快取沒列存 5 分鐘付 1.25×,存 1 小時付 2×

投影片的比例在大多數模型上仍然成立,最新幾款的快取更便宜。最後一列要特別注意:第一次存進快取要多付錢,所以只用一次的內容,標了快取反而虧。

先補一塊:prefix cache 什麼時候命中

快取的機制在 Part II 才講,但這堂的帳單分析都建立在它上面,這裡先講命中的條件。

模型每處理一段輸入,都會算出一份中間結果(KV cache)。下一次請求如果開頭一模一樣,服務端就能直接拿上次算好的那段,不必重算,計價也跟著打折(總覽的手算例子講過為什麼 agent 每步都要重讀)。關鍵字是「開頭」:從第一個 token 往後比,比到第一個不同的地方,後面就全部不算命中。

但 API 計價不是逐 token 比的。Anthropic 要你在請求裡用 cache_control 標出「快取到這裡」,這個位置叫快取標記(breakpoint)。快取只存在標記的位置;下一次請求從自己的標記往回找,看哪個位置有上次存過、而且到那裡為止完全相同的內容(Prompt caching 文件)。命中的單位是「到某個標記為止的整段」,標記之前就算有一部分相同,沒在那裡存過也不算。不想自己放標記,可以開自動快取,它會把標記放在最後一個能快取的區塊上。

兩家的官方文件都寫得很直接:

  • 順序固定。 Anthropic 把請求依 tools → system → messages 的順序排成一串再比對。工具定義排在最前面,所以改工具定義會讓整份快取失效;改 system prompt,工具定義那段不受影響,system 和後面的對話全部失效(Prompt caching 文件)。
  • 時間戳是頭號殺手。 Anthropic 文件舉的例子是:前五個區塊固定不變,第六個區塊每次都附上時間戳和使用者訊息,快取標記放在第六個區塊。時間一變,到標記為止的內容就不同;往回找時,前五個位置又從來沒存過,所以每次都在付寫入快取的錢,卻從來沒讀到過。解法是把標記移到第五個區塊,也就是最後一段不會變的內容上。自動快取有同樣的問題,因為它的標記正好落在會變的那段。OpenAI 也只在特定的邊界比對,它的建議是把時間戳、使用者專屬內容這類會變的東西放到最後,或移到後面的對話訊息裡(OpenAI Prompt caching 指南)。
  • 太短不快取,太久會過期。 Anthropic 的最短長度依模型是 512 到 4,096 token,預設存 5 分鐘、每次命中會重新計時;OpenAI 在 GPT-5.6 以後的模型最短是 1,024 token,預設存 30 分鐘。agent 等一個跑很久的工具,回來時快取可能已經過期;這時可以改用 1 小時的快取,寫入價是 2×。

課程筆記把這件事講成一句話:較短的 prompt 不一定較便宜,縮短或重排穩定的 prefix,可能把折扣一起拿掉(〈Lower serving cost without confusing it with fewer tokens〉一節)。一篇 2026 年的獨立評測(Don't Break the Cache)在三家廠商、500 多個 agent session 上量過:用對快取,API 費用省 41–80%。但不加區分地把整份 context 都標成快取,延遲有時反而變長。

手算一張帳單

這是本文的教學例子,接著總覽那個「修好失敗測試」的 5 步任務:開場 context 10,000 token,每一步工具結果與模型輸出讓 context 多 1,000 token,每次模型輸出 200 token。價格用 p21 的比例,1 單位 = 1,000 個一般 input token 的價錢;為了好算,先不計寫入快取的加價。

第幾次呼叫這次讀的 context不用快取prefix 穩定、有快取
110,00010.010.0(全部是新的)
211,00011.010,000×0.1 + 1,000×1 = 2.0
312,00012.011,000×0.1 + 1,000×1 = 2.1
413,00013.02.2
514,00014.02.3
input 小計60.018.6
output(5 次 × 200 token × 5 倍)5.05.0
合計65.023.6

prefix 穩定時,帳單是不用快取的 36%。現在把「現在時間:2026-10-07 14:03:27」放進 system prompt 的第一行。每次呼叫的 system prompt 都不同,比對在工具定義之後就斷了;工具定義那段沒有另外放快取標記,所以五次都沒有命中,帳單回到 65 單位。如果 harness 照樣把整段標成要快取,每次還要多付寫入的錢,以 Anthropic 的 1.25× 計是 80 單位,比完全不用快取還貴。

把寫入加價算進去,穩定 prefix 的版本是 27.1 單位,仍然不到一半。換成快取只收 0.05× 的 Opus 5.5,穩定 prefix 是 21.3 單位。

同一個 5 步任務:prefix 穩定 vs 開頭放時間戳
同一個 5 步任務:prefix 穩定 vs 開頭放時間戳prefix 穩定時,第 2 到 5 次呼叫只有新增的 1,000 token 付全價,input 合計 18.6 單位;system prompt 開頭放時間戳時每次都沒命中,合計 60.0 單位。 prefix 穩定,有快取 system prompt 開頭放時間戳 第 1 次 10.0 10.0 第 2 次 2.0 11.0 第 3 次 2.1 12.0 第 4 次 2.2 13.0 第 5 次 2.3 14.0 input 小計 18.6 input 小計 60.0 圖例 命中快取(0.1×) 付全價(1×)

本文教學例子。長條長度與這次讀進的 context 成正比;右側數字=這次的 input 費用,1 單位=1,000 個一般 input token 的價錢。快取命中照 p21 的 0.1× 計,未計寫入加價。

把這張帳單代回前面的乘式:1 個使用者、1 個 session、1 個 turn、5 個 step,每個 step 平均讀 12,000 token。前四項(使用者數、每人 session 數、每個 session 的 turn 數、每個 turn 的 step 數)都已經很小,帳單從 65 降到 23.6,靠的是最後一項:每個 token 的價格。換成 p13 那種每步讀 20 萬 token 的學生 session,最大的因子就變成每個 step 的 token 數。

這張帳單裡最大的一項,是第一次呼叫把 10,000 token 完整送進去。照這個例子的成長速度,大約從第 9 次呼叫起,cache read 的累計就超過這 10 單位,就像 p15 的學生紀錄那樣,任務越長,重讀越占大宗。所以改法有兩個方向。第一個不碰成功率:把會變的東西移出 prefix,讓快取命中。第二個是讓 context 長得慢一點,例如工具輸出只留需要的欄位,讓每一步要重讀的量變少;這一招要小心下一節講的反成本,砍掉的欄位之後若要用,得再讀一次。

自我檢查:有人為了讓模型知道「今天幾號」,把現在時間寫進 system prompt 的開頭。會有什麼後果?要怎麼改? 答:prefix 每次都不同,快取每次都失效,每一步都回到完整的 input 價格;如果還標了快取,每次都要付寫入的加價。改法是把時間放到 prompt 最後、放進使用者訊息,或只精確到日期,讓同一天的請求開頭相同。

每一項省錢都有反成本

投影片接著提醒,每一招都有代價,淨節省 = 省下的 - 反成本,兩者要在同一批任務上量(p25):

省錢手段反成本
壓縮 context被丟掉的檔案之後要重讀;摘要本身也會改寫快取
用便宜模型一個爛計畫可能多出很多步,或整個任務失敗
交給 subagent每個 subagent 都要重讀共用的檔案和指令
推測執行猜錯會燒 token,還會和正常工作搶同一批工具

課程筆記舉了一個比 $/成功任務 的例子:同樣 100 題,原版花 120 美元、成功 80 題,每次成功 1.50 美元;新版花 90 美元、成功 75 題,每次成功 1.20 美元,看起來比較好,但少完成 5 題。如果部署要求至少 80% 成功率,新版就不合格(〈Measure the whole episode〉一節)。第 1 堂說要看每次成功的花費,這裡補上限制:它要和成功率門檻一起看。第 7 堂的柏拉圖前緣,是同一件事的多指標版本。

另外兩頁是兩個習慣。第一,每個任務設預算上限,例如 10 美元、80 次模型呼叫、15 分鐘工具時間、每步最多重試 2 次;上限從過去成功任務的紀錄訂,例如 p95(最慢的 5%)的兩倍(p26,投影片註明數字只是示意)。停止條件還包括驗證通過、連續 N 步沒有新的測試通過、同一個錯誤一再出現。帶著摘要停下來的任務,比失控的任務便宜。第二,先問需不需要 LLM(p27):每次步驟都一樣就寫成腳本,輸入格式固定就用規則解析,只要一個標籤或分數就訓練小分類器。只有需要推理的步驟才交給模型。

讓 agent 變快:完成時間看關鍵路徑

快的 agent 通常也比較便宜,但不一定(p28)。依序執行時,完成時間約等於每一步加總;平行執行時,完成時間約等於關鍵路徑,也就是最長的那串互相等待的步驟(p29)。同一頁的兩個提醒是:便宜的小模型可能要多走幾步,反而更慢;平行化讓你少等,但總 token 變多。這和第 5 堂的粒度公式是同一個想法。

加速的手段分五類:

  • 模型服務:前半所有省錢的手段,也都省時間(p30)。
  • 編排(p31)有四招:
    • 非同步:工具在跑時先準備下一步。
    • 常駐 session:shell、瀏覽器一路開著不重開。
    • 串流接力:模型還沒講完就先發工具呼叫。
    • 放在一起:工具和模型跑在同一台機器上。
  • 工具本身(p32):build、測試、載入網頁常常比模型呼叫還久。重複的讀取與搜尋可以快取,重的運算丟到伺服器,卡住的呼叫設逾時。調模型之前,先量每一步花在工具上的時間。
  • 平行(p33):互不相依的工具呼叫在同一步一起發,互不相依的子任務交給平行的 subagent。只有互相獨立的工作能平行,共用狀態就需要合併步驟。
  • 推測執行(p34):用便宜的方法猜下一個動作,趁主模型還在想時先跑;猜中就省下等待,猜錯就丟掉,代價是一次白跑的呼叫。投影片說它適合「常猜中、而且動作能撤銷」的情況。

推測執行借的是 CPU 的直覺:處理器遇到分支時不等結果,先照猜測往下算,猜錯再退回。代表作 Speculative Actions(ICLR 2026)在遊戲、電商、網頁搜尋三類環境裡,下一個動作最多猜中 55%,延遲最多降 20%。投影片 p37 拿兩篇 2026 年的論文對照兩種猜法:PASTE 從過去的軌跡學規律,看到 search(q) 就預先發 visit(results[0].url);SPORK 讓同一個模型在推理途中分出一支,提早發出它看起來就要呼叫的工具。課程筆記補了一條規則:只讀或冪等(重做一次結果也一樣)的動作容易撤銷,會寫入的動作需要快照與回滾(〈Reduce waiting with a separate money budget〉一節)。

最後一頁是方法(p38):記錄每次呼叫、每個 token、每次工具與等待,找出成本與延遲的來源,一次只改一件事,再在同一批任務上重測成功率、花費與 p95 延遲。投影片這頁寫「Remember this for your Assignment 4!」;同一週開始的作業 3要做的也是這件事:模型當黑盒,優化它周圍的一切,成功率不能掉。

後半:harness 架構

前半的手段想清楚了,下一個問題是它們要放在哪裡。換模型路由要改哪個檔?sandbox 從 Docker 換成別的,要動到 agent 的主迴圈嗎?投影片用三個借自作業系統的名字回答。作業系統有把所有功能放在核心裡的「單體核心」,也有核心只管排程與通訊、其他功能交給外部服務的「微核心」;投影片把 harness 排成同樣的光譜(p40)。

三種架構

單體(monolithic)模組化(modular)微核心(microkernel)
怎麼組記憶、工具、context、規劃、執行全在同一個程式裡agent 仍然掌控迴圈,但透過介面取用各元件小小的 runtime 只管狀態、排程與安全,能力由外部服務提供
投影片的例子一個 CodingAgent class 自己 new 出 Memory、Tools、Plannermemory_provider=RedisMemory(),sandbox 從 Docker 換 Firecracker 只換一個 provider記憶、工具、執行各是獨立服務,可以跑在不同容器或機器上
好處好寫、好除錯、內部狀態好共享、開銷低元件好替換、好測試、第三方實作能接進來各服務獨立擴充、故障隔離、基礎設施可共用
代價換一個元件很難、元件互相綁死、隔離難做生命週期仍由主控者負責,協調邏輯會越來越複雜通訊開銷高、故障種類多、端到端除錯難、需要標準協定
適合單一 agentagent 框架多 agent 的基礎設施

(整理自 p41–45。)

p44 用「跑一段 Python」對照三者。單體在本機直接執行,步驟最少,但隔離很難做;模組化呼叫 SandboxProvider.run(code),換 provider 不必改 agent;微核心送出執行請求,由執行服務自己配置 sandbox、執行、回傳結果,sandbox 的生命週期歸它管。這一頁也說明了為什麼作業 2 那種一個檔案的 harness 好入門,但要讓很多 agent 共用 sandbox 時就不夠用。

八個 harness 的設計取向

p46 列了八個 harness,各用一句話說它的取向;之後七頁各講三個獨有的機制。Claude Code 只在總表出現,沒有自己的一頁。

harness誰做的投影片的一句話一個代表機制
Claude CodeAnthropic(不開源)包在 Claude 外面的政策層與型別化的 hook(沒有獨立頁)
Codex CLIOpenAI先 sandbox,再問人指令在沒有網路的 sandbox 裡跑,要出 sandbox 才請你核准;patch 格式由一份 Lark 文法(一種描述語法規則的格式)規定
DeepSeek HarnessDeepSeek什麼都是 plugin,連迴圈也是編輯用 compare-and-swap:檔案在模型上次讀取後變過,這次編輯就失敗
OpenCodeAnomaly(SST)session 伺服器加上很薄的客戶端TUI、SDK、網頁版都打同一個 OpenAPI 伺服器;每一步拍一次快照,/undo 能還原檔案
PiMario Zechner/Earendil小小的核心,用 TypeScript 擴充核心只有四個工具,沒有 MCP、subagent 與核准流程,其他功能都靠擴充
oh-my-piCan Bölük/Stencil LabsPi 的分支,把原生工具與 IDE 接進來hashline 編輯:用內容雜湊標記行,模型不必重打舊文字
OpenClawOpenClaw Foundation接聊天頻道的助理閘道壓縮 context 之前,先靜默地跑一輪,把帶日期的筆記寫下來
Hermes AgentNous Research會自己寫 skill 的 agent背景分出一支去改記憶與 skill;context 用到一半就開始壓縮,是八個裡最早的

(整理自 p46–53。)

這張表和前半接得起來(以下對應是本文整理):Hermes 提早壓縮、OpenClaw 壓縮前先記筆記,處理的是前半講的 context 成本;Codex 先進 sandbox、DeepSeek Harness 的 compare-and-swap,處理的是 p44 的執行隔離與並行寫入。投影片沒有替八個 harness 排名,重點是看懂每個設計在解哪個問題。

綜合自我檢查

  1. 一個 session 只有 1 個 turn,但這個 turn 走了 40 步,主 agent 每步讀 200K token,其中 97.6% 是 cache read。成本乘式的六個因子裡,該先動哪個? 判準:前兩項(使用者數、session 數)不砍;turn 已經是 1。先看 step 數(獨立的工具呼叫一次發、先規劃再動手)與每步 token 數(截掉用過的工具輸出、把探索交給 subagent)。單價已經靠快取壓得很低,再壓只能換模型,那要先量成功率。
  2. 上週一個 agent 的 cache read 占 input token 的 95%,這週掉到 20%,總花費翻倍。最可能是什麼原因?先查哪裡? 判準:答出 prefix 被改動了。先比對兩週 system prompt、工具定義的差異,看有沒有新加的時間戳、隨機 id、每次排序不同的工具清單,或有人改了工具描述。工具定義一變,整份快取都失效。
  3. 你想把 agent 的每個 step 從 Opus 換成便宜的模型。投影片提醒的最大風險是什麼?要量哪些數字才能下結論? 判準:答出便宜模型的一個規劃錯誤可能讓後面多走很多步、甚至任務失敗(p22、p25)。要在同一批任務上比成功率、總花費(含失敗與重試)、p95 延遲,並確認成功率沒有掉到門檻以下,不能只看每個 token 的單價。
  4. 三個 agent 平行修三個 bug,完成時間從 50 分鐘降到 20 分鐘,但帳單多了三成。這算優化成功嗎? 判準:答出這是用錢買時間,不是省錢(課程筆記:「快 20%、貴 30%」是買了延遲)。有沒有成功要看需求:有回應時間要求就值得,否則不划算。報告時要把延遲和花費分開寫。

延伸閱讀

課程影片來源

  • 課程不錄影(policy 頁)。
  • 底本:第 8 堂投影片(PDF 頁序 p5–53)與課程筆記〈Cost-effective agents〉,2026-10-22 讀取。頁碼一律用 PDF 頁序。
  • 計價與快取規則對照 2026-10-22 的 Anthropic 定價頁、Prompt caching 文件與 OpenAI Prompt caching 指南;與投影片不同之處已在正文標出。八個 harness 的機制對照各 repo 與官方文件;投影片引用的論文數字回原文核對。〈Don't Break the Cache〉是本站補充的來源。
  • 手算帳單與它的圖、cache 份額換算成金額的比例、各自我檢查的答案是本站補充,不是課堂內容。

參考資料