如何在CLI工作流程中降低Agent的Token成本

一份實用指南,介紹如何透過輸出壓縮、指令整潔和上下文管理來降低CLI工作流程中Agent的Token成本。

By Dora 3 min read

我是 Dora。上個月我透過 Claude Code 執行了一個 npm test,看著 agent 還沒說一個字,session 就燒掉了大約 12,000 個輸入 token。測試輸出有 400 行,其中真正重要的也許只有 30 行。其餘的——棄用警告、依賴套件雜訊、Jest 的進度點——全部都直接塞進模型的 context。我為每一個 byte 付了錢。

那時我停止把 token 視為「模型自己處理的事」,開始把它們當成一個我正在不斷洩漏的預算。如果你在 Claude Code、Gemini CLI 或任何類似工具上執行 agentic CLI 工作流程,這很可能就是你最大的成本項目——解法不是換個更好的模型,而是更好的使用習慣。Anthropic 自己的成本管理文件說得很直白:token 成本隨著 context 大小而增加,而大多數的優化都發生在模型看到資料之前。這篇文章談的是如何在不失去必要除錯訊號的前提下,降低 CLI 工作流程中的 agent token 成本。

CLI 工作流程在哪裡浪費 Token

在修正任何問題之前,我必須先找出漏洞在哪裡。有兩種模式特別突出,而且在我審查過的幾乎所有 CLI 工作流程中都會出現。

冗長的指令與不相關的輸出

終端機指令是為了讓人類快速掃描螢幕而設計的,不是為了讓 LLM 逐 byte 閱讀。git status 會印出模型根本不需要的 ANSI 色碼。npm install 會倒出一千行的依賴樹,而模型早就知道這些了。next build 會把自己的進度回應十五秒。這些全都不值得佔用 context window 的空間。

實際數字比帳面上看起來還糟。一個中型 Rust 專案跑一次 cargo test,可以產生 8,000 到 15,000 個 token 的輸出,其中大部分是編譯雜訊。當 agent 讀完這些只是為了找到一個失敗的斷言,你已經用 Opus 的費率為串流一份建置日誌付了錢。

這也是為什麼 rtk 和 tokf 這類社群專案會存在——它們介於 shell 和 agent 之間,在內容進入 context 之前就過濾掉樣板文字,並回報在常見指令上節省了 70–90% 的數字。不管你用不用包裝工具,原則都是一樣的:原始終端機輸出不是 LLM 可以直接使用的資料。

Context 的累積與重複讀取

第二個漏洞更隱微。agent 每次進行的工具呼叫——讀取檔案、grep、bash 指令——都會留在對話歷程中。到了第十輪,模型每次請求都要重新處理九輪過時的輸出。Anthropic 自己針對 Claude Code 品質問題的 4 月事後檢討報告正好描述了這個動態:一個快取 bug 導致思考歷程在各輪之間不斷累積,在有人注意到之前,token 用量已膨脹了 10 到 20 倍。即使沒有 bug,這也是預設行為。session 越長,費用越高。

我檢查了自己一個使用了一週的 session。agent 讀了同一份 package.json 四次。這些重複讀取沒有增加任何資訊——檔案根本沒有變動。它們只是 agent 不知道自己已經知道什麼的產物。

步驟一:壓縮雜訊輸出

成本最低的修正方式,遠超其他任何方式,就是一開始就防止垃圾資料進入 context。按優先順序排列三條規則:

在來源端過濾,而非事後處理。 agent 執行的不是 npm test,而是 npm test --silent 2>&1 | grep -E "(FAIL|PASS|Error)"。不是 git status,而是 git status --short。不是 cargo build,而是 cargo build --quiet 2>&1 | tail -20。這沒什麼聰明的地方,純粹是紀律。agent 得到的是失敗的測試、被修改的檔案、實際的錯誤——僅此而已。

在 harness 層級限制工具輸出。 Claude Code 允許你設定每次工具輸出的最大大小。我把自己的上限調到每次呼叫 8,000 個字元。當指令超出時,agent 會收到截斷通知,並自行決定是否要細化查詢。光是這個設定,就幫我省下比其他所有更改加總還要多的 token。

當上游工具無法安靜時,使用 CLI 代理。 有些指令根本沒有值得使用的靜音旗標——next build、webpack、任何基於 Java 的工具。對這些工具而言,一個能過濾掉已知樣板的包裝工具是值得花時間設置的。rtk/tokf 系列工具可以通用地處理這個問題;你也可以針對最困擾你的三個指令寫一個 30 行的 bash 函式。

這裡有個真實的取捨。過度激進的壓縮可能隱藏除錯訊號。 當建置因為過濾器過濾掉的原因而失敗時——一個變成錯誤的棄用警告、一個埋在第 847 行的不明顯設定問題——agent 拿到的是一個更短、用處更少的畫面。我遇過兩次。兩次的解法都是放寬某條過濾規則,而不是放棄整個策略。

步驟二:在 Context 進入模型之前加以限制

輸出過濾處理的是每輪新進入的 token。Context 紀律處理的是已經在 session 內部累積的 token。這是兩個不同的問題。

兩個最重要的指令,都直接來自 Anthropic 的 Claude Code 最佳實踐/clear/compact/clear 完全重置 session——適合切換到不相關的任務時使用。/compact 在保留關鍵決策和當前狀態的同時,摘要較早的歷程——適合任務持續進行、但早期的探索已不再重要時使用。Claude Code 在接近 context 上限時會自動壓縮,但等到那個觸發點通常已經太晚了。那時你已經為幾輪的膨脹費率付了錢。

我目前的習慣:每到自然的任務邊界就執行 /compact,並附上說明,例如 /compact Focus on the failing test and the recent file edits。說明很重要。沒有說明,壓縮就會大致地摘要所有內容。有了說明,agent 就能保留下一階段最重要的部分。

對於基於 API 的 agent(不是 CLI 訂閱版),Anthropic 的context 編輯文件描述了一個更嚴格的機制:clear_tool_uses_20250919 在 context 超過閾值後會自動清除舊的工具結果。agent 保留對話,但失去它已經處理過的原始輸出。對於長期性的 agentic 任務,這是正確的預設設定。

有一點我想特別提醒:臃腫的 CLAUDE.md 是一種永久性的稅。它每輪、每個 session 都會載入,永遠如此。我把自己的 CLAUDE.md 從約 280 行精簡到約 90 行。每輪的 token 計數明顯下降,而 agent 的行為在任何我能衡量的面向上都沒有改變。

步驟三:重新設計 Agent 工具以降低浪費

前兩個步驟是戰術性的。這一步是結構性的,也是持久節省的所在。

設計能輸出 LLM 友好內容的工具。 社群驅動的 CLI Spec 對此的論述比我更好:專為 agent 設計的指令應支援 --output 旗標、將資料(stdout)與診斷資訊(stderr)分開,並提供分頁而非傾倒無邊界的 JSON。如果你正在建構 agent 會呼叫的內部 CLI,請遵循該規範。如果你使用的外部 CLI 不符合規範,就包裝它。

優先使用窄工具,而非廣工具。 一個回傳三個結構化欄位的 git_status_summary 函式,勝過讓 agent 執行原始的 git status 然後解析輸出。模型需要進行的每一層解析,都是 token 被燒在翻譯而非推理上的一層。我把最常用的四個指令轉換成回傳 JSON 的薄 Python 包裝器。這些操作的往返 token 使用量下降了約 60%。

對讀取密集型任務使用子 agent Claude Code 的子 agent 功能為「掃描 repo 並摘要認證流程」這類任務執行獨立的 context。結果以緊湊的摘要形式回傳——而不是子 agent 實際讀取的 40 個檔案。主對話永遠看不到原始資料。對於探索密集型任務,這是目前可用的單一最大結構性收益。

根據工作選擇合適的模型。 Opus 4.7 令人印象深刻,也很昂貴。大多數 CLI 工作——檔案編輯、測試修復、例行重構——在 Sonnet 上執行得很好,每個 token 的費用約為 Opus 的 40%。值得注意的是:Opus 4.7 的新 tokenizer 對相同的文字可能產生比早期模型多達 35% 的 token,這使成本差距進一步擴大。

坦誠的注意事項:先測量再優化,優化後再測量。 我在更改任何設定之前,用 /cost(API)或 /usage(訂閱)建立了一週的基準線,然後在每次更改後重新測量。我的兩個「優化」結果證明什麼可衡量的效果都沒有。沒有基準線,你只是在猜測。

常見問題

為什麼終端機工作流程會消耗這麼多 token?

因為終端機輸出是為人類設計的,而 agent 是按 byte 付費的。一個典型的建置指令會發出數千行模型不需要的進度、警告和樣板文字。加上從未重置的對話歷程,以及跨輪累積的工具結果,你就會得到在真正的工作開始之前就燒完 context 預算的 session。

輸出壓縮能幫多少忙?

根據我的測量,在測試執行、建置和 git 操作上,指令層級的過濾加上輸出上限,可以將每輪的輸入 token 減少 40–60%。rtk 等社群包裝工具在特定指令上回報了 80–90% 的降幅,不過這些數字假設的是最糟糕情況的冗長輸出。實際的收益取決於你的 agent 最常執行哪些指令。審查前五名,修正這些,大部分的節省效果就會立即顯現。

團隊應該先優化什麼?

按此順序:工具輸出上限、/clear/compact 的使用紀律、模型選擇。輸出上限是一次性的設定變更,後續零成本。Session 衛生是一種習慣,但一旦養成就是免費的。模型選擇是最容易被忽視的收益——當大多數任務在 Sonnet 上就能執行良好,卻把所有事情都跑在 Opus 上,是一個安靜但龐大的漏洞。

token 優化什麼時候會損害除錯品質?

當你壓縮到 agent 看不出哪裡壞掉的程度時。一個被截斷的堆疊追蹤、一個被過濾掉的棄用警告、一個隱藏了真實錯誤的 --quiet 旗標——這些都讓我浪費了真實的時間。我遵循的模式是:對例行指令(git statusnpm install、成功的測試執行)積極壓縮,對已知失敗或不熟悉的操作保留冗長輸出。如果你發現自己為了除錯而必須不帶過濾器重新執行指令,那是過濾器的問題,不是策略的問題。

結論

CLI 工作流程中的 token 成本不是模型問題,而是管道問題。大部分的花費消失在終端機指令所發出的內容,與模型真正需要用來推理的內容之間的落差——而這個落差可以透過輸出過濾、context 紀律,以及尊重另一端 agent 的工具設計來修正。

我已經執行上述設置大約六週了。Claude Code 的每日 token 消耗量下降了約 55%,agent 延遲也因 context 變小而改善,工作流程在除錯時感覺也不那麼雜亂了。這些數字並非普世適用——你的基準線和前五名指令會有所不同。但模式是成立的:控制什麼進入 context,控制什麼留在 context 中,讓模型把預算花在推理上,而不是閱讀建置日誌。

這就是我的資料截止點。壓縮層持續演進,Anthropic 的 tokenizer 變更意味著這些數字有其有效期限。值得每季重新建立基準線。

相關文章: