<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>AI Coding on AI 輔助維運工程</title>
    <link>https://eeit.github.io/ai-devops-blog/tags/ai-coding/</link>
    <description>Recent content in AI Coding on AI 輔助維運工程</description>
    <generator>Hugo</generator>
    <language>zh-tw</language>
    <copyright>2026 鄧景仁 (Scott Teng) · 授權：CC BY-NC 4.0</copyright>
    <lastBuildDate>Sat, 18 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://eeit.github.io/ai-devops-blog/tags/ai-coding/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>《AI 輔助維運工程》系列導讀</title>
      <link>https://eeit.github.io/ai-devops-blog/posts/00-series-index/</link>
      <pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://eeit.github.io/ai-devops-blog/posts/00-series-index/</guid>
      <source url="https://eeit.github.io/ai-devops-blog/posts/00-series-index/">AI 輔助維運工程</source>
      <description>從 Claude Code 的運作機制,到企業導入的商務與技術治理。這是一個為 infra 工程師寫的系列,分享我這三個月在 POC 中摸索到的觀察。這篇導讀整理幾條閱讀路徑供你參考。</description><content:encoded><![CDATA[<h2 id="為什麼寫這個系列">為什麼寫這個系列</h2>
<p>過去三個月我在工作上密集使用 Claude Code 處理維運任務——從日常巡檢、事件排查、規格撰寫、到跨雲服務的自動化。雖然時間不長,但這段密集的沉浸式經驗讓我意識到兩件事。第一件是,我自己一開始也在事後才意識到,市面上多數談 AI 工具的文章集中在「工具介紹」或「使用教學」的層級,從<strong>工程角度拆解運作機制</strong>的繁中資源不是那麼容易找。第二件是,從<strong>企業維運與合規視角</strong>談 AI 助理的繁中資源同樣不多見——這個視角需要結合對 AI 工具的技術理解、對企業資訊架構的實務經驗、以及對合規治理的敏感度,三者剛好同時關心的人不多。</p>
<p>這個系列想填補的,就是這個空缺。我寫的每一篇都有一個共同的預設——<strong>讀者是具備工程能力、對效率有要求、同時對合規與治理敏感的專業工作者</strong>。不論你是 DevOps、SRE、infra 工程師、還是需要評估 AI 工具的技術主管,這個系列希望提供一條相對完整的脈絡,而不是零散的技巧。</p>
<h2 id="系列地圖">系列地圖</h2>
<p>整個系列由十篇文章組成(第 8-10 篇正在準備中)。前半部(第 1-5 篇)聚焦於<strong>機制理解</strong>,幫你建立對 Claude Code 運作方式比較深入的認知。後半部(第 6-10 篇)轉向<strong>決策與治理</strong>,處理使用過程中的工具選擇、成本、商務、權限、以及跨階段的工作流整合。</p>
<p>**第 1 篇《為什麼 Claude Code 是不一樣的 AI 工具》**是系列的地基。許多人把 Claude Code、Copilot、Cursor、ChatGPT 當成同類產品比較,我覺得這是類別上的混淆。這一篇先把座標系統建立好,讓你看到 Claude Code 屬於一個完全不同的工具類別——Agentic CLI——它解決的問題、要求的使用方式、帶來的價值,跟 IDE 外掛式的 AI 助理有本質差異。</p>
<p>**第 2 篇《Agent Loop:AI 助理的心跳機制》**開始進入技術核心。你以為自己在「跟 AI 對話」,實際上是在驅動一個迴圈。這個認知的轉換很關鍵——不懂 Agent Loop,後面所有的成本優化、context 管理、權限設計都會是黑盒魔法。這一篇用一個具體情境,拆解從你按下 Enter 到 AI 回應完成之間的六個階段。</p>
<p>**第 3 篇《四層 Context 壓縮:200K 窗口的真實調度》**是整個系列技術密度較高的一篇。Context 管理是 Claude Code 設計上比較精巧、也比較容易被誤解的一塊,而且直接影響使用體驗。這一篇完整拆解四層壓縮管線——Pre-pipeline、Snip Compact、Micro Compact、Context Collapse、Auto Compact——並分析何時用哪一層、為什麼這樣排序、以及 1M context 出現之後這套系統發生了什麼變化。</p>
<p>**第 4 篇《Sub-agent 與 Agent Team》（分上下集)**是一組對照。上集是純技術篇,拆解 Sub-agent 的四種隔離模式、Fork 的 byte-identical prefix 設計、以及 Claude Code 為什麼能每週 spawn 數千萬個分身而不破產。下集是治理篇,談為什麼「一人分飾多角」會搞砸任務、如何用劇組式的角色分工建立可稽核的工作流、以及這套設計為什麼跨 AI 可攜、是你自己設計的工程資產。這兩篇合起來,處理了一個我在繁中資源中不太常看到被一起拆開講的主題。</p>
<p>**第 5 篇《Token 成本的真相》**是實務派讀者最關心的一篇。這篇用一個核心觀念貫穿全文——你不是在為「最近一句話」付費,而是在為「整段對話歷史每輪都重新送一次」付費。理解這件事之後,所有的成本優化策略(Prompt Cache、精簡 CLAUDE.md、主動壓縮、Agent Team 分工)都有了共同的底層邏輯。讀完這篇,你比較容易指出帳單上每塊錢花在哪、哪些可以省、哪些不能。</p>
<p>**第 6 篇《當工具自薦時:SSDLC 裡 Claude 各入口的角色與邊界》**處理一個比方案選型更上游的問題——在 SSDLC 的每個階段,該用哪個 Claude 入口?Claude Code、Claude.ai、API,同一個模型放在不同平台,擅長的事情不一樣。這篇從一次對照實驗開始,揭露 Anthropic 官方承認的 self-preference bias(自我偏好偏誤),並從中導出一組獨立於工具本身的判準——讓 SSDLC 流程本身告訴你答案。下一次 Anthropic 推出新入口、舊入口改版、整個產品結構大洗牌,這組判準應該還能繼續用。</p>
<p>**第 7 篇《選型與合約》**是商務決策的一次性整理。Anthropic 提供四種服務管道,各自解決不同的問題,不是「由小到大的階梯」。這一篇分享我整理的每個方案差異、訓練政策的觀察、資料保留期的官方不一致現象、不同規模使用者的可能路徑,還有一個進階的「去識別化閘道」設計。對我而言,選對方案的一次性決策,常常比後面的技術優化更值得提早花時間想清楚。</p>
<h2 id="閱讀路徑建議">閱讀路徑建議</h2>
<p>這些文章是一個連貫的整體,但我理解不是每位讀者都有時間通讀。以下是三種路徑建議,你可以依自己的角色挑選最適合的切入方式。</p>
<p><strong>技術深入派</strong>如果你最想要理解 Claude Code 的內部機制,建議依序讀第 1、2、3、4 篇。這四篇是純技術篇,看完你應該會對這個工具的運作方式有比較完整的認知,之後讀其他相關文章可能也會更快吸收一些。</p>
<p><strong>實務導入派</strong>如果你已經在使用 Claude Code,想解決實際問題——尤其是成本爆炸、行為失控、合規疑慮——建議讀第 1、5、6、7 篇,加上第 4 篇下集。這五篇處理的都是我自己在 POC 中遇到、我猜也是很多人會遇到的問題,原理面的內容被我壓縮到最必要,主要是給你可執行的決策依據。</p>
<p><strong>主管決策派</strong>如果你是評估是否要導入、或如何規範團隊使用 AI 工具的主管,建議讀第 1、5、6、7 篇。這四篇包含了我覺得主管視角最需要的資訊——第 1 篇讓你理解這個工具的真實價值,第 5 篇讓你能比較準地估成本,第 6 篇幫你思考不同 SSDLC 階段該用哪個入口,第 7 篇讓你能較有把握地做採購決策。如果連續讀,大約一個下午可以讀完。</p>
<h2 id="系列中的承諾">系列中的承諾</h2>
<p>寫這個系列的時候,我對自己設了幾條明確的邊界。</p>
<p><strong>內容必須真實可驗證,避免 AI 幻覺</strong>。所有對 Claude Code 內部機制的描述,都基於公開的逆向工程資料與我自己的實務觀察,每一個具體數字都有來源。寫作過程中我刻意迴避了一些連我自己都不敢確定的細節——寧可用「通常」、「大約」這類框定性語言,也不杜撰精確數字。具體閾值(例如 Auto Compact 的 167K threshold)則標示了計算方式,讓讀者可以自己驗證。</p>
<p><strong>文中引用的案例來自真實的 POC 專案,但敏感細節已全部匿名化</strong>。這個系列的內容根基於我目前進行中的一個 POC 專案——把 AI 助理深度導入日常維運工作——所發生的真實事件。這讓文章中的教訓不是純理論推演,而是第一手觀察。但真實事件的組織名稱、人員身份、IP 位址、系統識別碼、客戶資訊都已經全部移除。保留下來的是<strong>通用的技術教訓</strong>,不是組織內部的 know-how。讀者從案例裡學到的模式應該可以套用到自己的環境,但無從反推原始事件的任何識別資訊。</p>
<p><strong>不代表任何組織立場</strong>。所有觀點都是我個人的學習與實務心得整理,跟任職組織的立場無關。如果某個觀點讓你覺得「這跟我認知的主流說法不一樣」,那可能就是我真實的觀察,不是鸚鵡學舌。</p>
<p><strong>內容創作方式是「人類主導、AI 協同」,我坦誠說明這件事</strong>。每一篇的觀點、案例、技術判斷都來自我自身的學習,以及在 POC 專案中累積的真實維運實務經驗;文字的組織與表達的打磨則由 AI 協助完成。這也是我寫這個系列時想傳達的一個觀察——對我而言,AI 比較適合用來放大工程師的判斷力,而不是取代它。</p>
<p>最後,技術世界變化非常快。這個系列的某些細節(特別是方案定價、模型規格、API 行為)可能隨時間改變。撰寫時是 2026 年第二季的狀態,讀者如果在之後的時間點閱讀,建議重要決策前再次驗證當時的官方資訊。</p>
<h2 id="接下來">接下來</h2>
<p>前七篇建立了我目前摸索到的認知輪廓,從機制到治理都接觸了一輪。但整個系列還有三篇正在準備中——第 8 篇《Hooks 與權限系統:讓 AI 聽話的三道關卡》會進一步深入技術性的安全治理;第 9 篇《把 Claude Code 接進維運日常》會是一個 infra 工程師的真實工作流整合;第 10 篇則會專門處理「架構分析」與「飄移檢查」這兩類橫跨 SSDLC 的元活動——它們的工具分工邏輯比單一階段複雜,需要獨立展開。這三篇完成後,整個系列會擴充到十篇,讓「從理解到落地」這條路線能走得更完整一些。</p>
<p>在這之前,如果你有任何建議、疑問、或發現任何不準確之處,歡迎來信 <a href="mailto:st333117@gmail.com">st333117@gmail.com</a>。這個系列的每一篇都會持續改進,你的回饋會讓它更好。</p>
<p>現在,從你最有感的那一篇開始讀吧。</p>
<hr /><p style="font-size:0.9em;opacity:0.8;margin-top:2em;">本文原刊於 <a href="https://eeit.github.io/ai-devops-blog/posts/00-series-index/" rel="canonical">https://eeit.github.io/ai-devops-blog/posts/00-series-index/</a>，作者：鄧景仁 (Scott Teng)。<br />授權條款：<a href="https://creativecommons.org/licenses/by-nc/4.0/deed.zh_TW" rel="license">CC BY-NC 4.0</a> · 禁止商業使用；分享請署名並註明原文 URL。<br />商業授權請聯絡：st333117@gmail.com</p>]]></content:encoded>
    </item>
    <item>
      <title>為什麼 Claude Code 是不一樣的 AI 工具</title>
      <link>https://eeit.github.io/ai-devops-blog/posts/01-why-claude-code-is-different/</link>
      <pubDate>Sun, 12 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://eeit.github.io/ai-devops-blog/posts/01-why-claude-code-is-different/</guid>
      <source url="https://eeit.github.io/ai-devops-blog/posts/01-why-claude-code-is-different/">AI 輔助維運工程</source>
      <description>從 infra 工程師的角度,整理 Claude Code 與 Copilot、ChatGPT、Cursor 的根本差異,以及為什麼我覺得它不是另一個 AI coding tool,而是一種不太一樣的工作方式。</description><content:encoded><![CDATA[<blockquote>
<p>本文為《AI 輔助維運工程:從 Claude Code 機制到企業落地》系列第 1 篇。全系列共十篇(第 8-10 篇正在準備中),從原理到落地完整涵蓋。</p>
</blockquote>
<h2 id="一個工程師的困惑">一個工程師的困惑</h2>
<p>我手上已經有 GitHub Copilot,每天打開網頁版 Claude 問東問西,偶爾用 Cursor 改 code。為什麼還要在 terminal 裡裝一個 Claude Code?</p>
<p>這是我一開始的疑問。我猜很多人也是。</p>
<p>答案我花了一段時間才真的想清楚:<strong>這些工具不是在競爭同一件事,它們解決的根本就是不同類別的問題</strong>。把它們擺在一起比較,就像把「螺絲起子、電鑽、CNC 加工機」拿來問「哪一個比較好?」——問題本身就設定錯了。</p>
<p>這篇文章不是要告訴你 Claude Code 比其他工具「更好」,而是要說清楚它<strong>是什麼種類的東西</strong>。理解這件事之後,後面幾篇的技術細節你才能真的吸收。</p>
<hr>
<h2 id="先把座標定好四種工具在做四件事">先把座標定好:四種工具在做四件事</h2>
<p>我用自己的理解把市面上常見的 AI coding 工具分成四類。分類標準是「<strong>它主要在幫你做什麼層級的事</strong>」:</p>
<table>
  <thead>
      <tr>
          <th>工具類型</th>
          <th>代表</th>
          <th>主要幫你做</th>
          <th>你扮演的角色</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>行內補全</strong></td>
          <td>GitHub Copilot</td>
          <td>當你在打字,它猜你下一行</td>
          <td>駕駛</td>
      </tr>
      <tr>
          <td><strong>對話助手</strong></td>
          <td>Claude.ai 網頁版 / ChatGPT</td>
          <td>你問問題,它回答</td>
          <td>提問者</td>
      </tr>
      <tr>
          <td><strong>IDE 協作者</strong></td>
          <td>Cursor / Windsurf</td>
          <td>在你的編輯器裡幫你改多個檔案</td>
          <td>副駕駛</td>
      </tr>
      <tr>
          <td><strong>Agentic CLI</strong></td>
          <td>Claude Code / Codex CLI</td>
          <td>在終端裡自主完成任務</td>
          <td>指揮官</td>
      </tr>
  </tbody>
</table>
<p>這張表不是要排名高下。每一種工具都有它最適合的場景:寫前端切版,Copilot 行內補全超好用;討論一個演算法,網頁版 Claude 反而最合適;想在 IDE 內一次改 20 個檔案,Cursor 是最舒服的選擇。</p>
<p><strong>Claude Code 屬於第四類</strong>,也是目前繁中圈討論相對少、但對 infra 與後端工程師可能很有價值的一類。</p>
<hr>
<h2 id="claude-code-在做什麼三個關鍵特徵">Claude Code 在做什麼:三個關鍵特徵</h2>
<p>把 Claude Code 定位成「Agentic CLI」之後,它的設計選擇就變得合理了。我整理三個讓它和前三類工具根本不同的特徵。</p>
<h3 id="特徵一它是真正的-agentic-loop不是-autocomplete">特徵一:它是真正的 Agentic Loop,不是 Autocomplete</h3>
<p>Copilot 在幫你打字,Claude Code 在幫你<strong>完成任務</strong>。</p>
<p>差異在哪?行內補全是「輸入 → 猜測 → 輸出」的單次循環。Agentic loop 是:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">接收任務
</span></span><span class="line"><span class="cl">  → 讀取 context(檔案、git 狀態、past conversation)
</span></span><span class="line"><span class="cl">  → 呼叫模型決策
</span></span><span class="line"><span class="cl">  → 執行工具(讀檔、寫檔、跑 bash、搜尋)
</span></span><span class="line"><span class="cl">  → 把結果餵回給模型
</span></span><span class="line"><span class="cl">  → 判斷任務是否完成
</span></span><span class="line"><span class="cl">  → 完成 or 進下一輪
</span></span></code></pre></div><p>這個迴圈可以跑 5 次、20 次、甚至 100 次,直到任務真的完成或者達到上限才停。你不需要每一步都手動點「繼續」。</p>
<p>我第一次真正體會到這個差異,是請 Claude Code 幫我處理一個「從 production 撈最近 7 天的 nginx log、找出回應時間異常的 request、產出 markdown 報告」的任務。我給它的 prompt 很短,但它自己:</p>
<ol>
<li>先問我 log 放在哪</li>
<li>用 <code>grep</code> 和 <code>awk</code> 篩出候選行</li>
<li>發現時間格式有兩種版本的 log,自己調整 parser</li>
<li>產出表格,還主動附上我沒要求的「建議下一步」</li>
</ol>
<p>整個過程我只回了「在 /var/log/nginx/」這一句。這就是 agentic loop — <strong>它把分解任務、執行、驗證結果這些原本是工程師在做的事,也一起接手了</strong>。</p>
<p>這個能力是 Claude Code 的技術基礎,也是後面所有章節的前提。如果這件事沒發生,權限系統、context 管理、token 優化都是假議題。</p>
<h3 id="特徵二權限系統是-first-class-citizen不是事後補的">特徵二:權限系統是 First-Class Citizen,不是事後補的</h3>
<p>一旦工具可以執行 bash,風險就來了。</p>
<p>這是所有 agentic 工具必須面對的問題。Claude Code 的設計選擇是:<strong>把權限管控放在架構的第一層,而不是事後用規則補</strong>。</p>
<p>它的權限模型有三個層次(這是後面第 8 篇會細講的主題,這裡先建立印象):</p>
<ul>
<li><strong>CLAUDE.md</strong>:指導性約束(軟)。你用自然語言告訴 AI 「不要修改 migrations/ 目錄」。</li>
<li><strong>Permission Rules</strong>:聲明性約束(中)。<code>settings.json</code> 裡寫 <code>allow</code> / <code>deny</code> / <code>ask</code> 規則,例如 <code>&quot;Bash(rm -rf:*)&quot;: &quot;deny&quot;</code>。</li>
<li><strong>Hooks</strong>:可編程約束(硬)。在 tool 執行前插入腳本,可以做任意檢查、修改、甚至攔截。</li>
</ul>
<p>三層不是任選其一,是<strong>縱深防禦</strong>。CLAUDE.md 可以被模型繞過,但 permission rules 擋得住;permission rules 匹配不到的模糊情境,hooks 可以用程式判斷。</p>
<p>這件事聽起來理所當然,但<strong>很多 AI coding 工具是先做功能,再補權限</strong>,導致你得自己用外圍手段(例如另開容器、限制帳號權限)去防。Claude Code 把這件事當設計地基處理,我覺得對需要在企業環境下使用的人比較有感。</p>
<h3 id="特徵三context-管理是工程問題不是黑盒子">特徵三:Context 管理是工程問題,不是黑盒子</h3>
<p>大語言模型有個硬性限制:<strong>context window</strong>。目前 Claude 系列模型的上下文窗口通常以數十萬 tokens 計,聽起來很多,但如果你跑一個兩小時的維運任務,它會填滿得比你想像快。</p>
<p>Context 滿了會發生什麼?模型開始忘東西,回答品質下降,最後乾脆拒絕繼續。</p>
<p>大多數 AI 工具對這件事的處理方式是「看運氣」—— 希望模型自己記得關鍵資訊。Claude Code 的做法是<strong>把 context 當成要主動管理的工程資源</strong>,設計了多層壓縮管線,在不同階段用不同策略釋放空間。</p>
<p>這件事的細節會在第 3 篇完整展開(那一篇會是整個系列最燒腦的一篇)。這裡先記一個結論:<strong>Claude Code 的 context 管理不是黑盒,它是一套可觀察、可調控、可最佳化的系統</strong>。理解這套系統,對後面「如何省 token、如何讓長任務跑得穩」這些實務問題比較有幫助。</p>
<hr>
<h2 id="它適合誰不適合誰">它適合誰,不適合誰</h2>
<p>設計哲學釐清之後,適用場景也就清楚了。以下是我的判斷,不是官方說法:</p>
<h3 id="適合的人">適合的人</h3>
<ul>
<li><strong>後端工程師 / DevOps / SRE / infra 工程師</strong>:你有大量跨檔案、跨服務、需要 shell 才能完成的任務。</li>
<li><strong>有版控習慣的人</strong>:Claude Code 會直接改檔案,沒有 git 你會救不回來。</li>
<li><strong>能接受 CLI 的人</strong>:它的主要介面就是 terminal,不會有人想把它弄成圖形介面。</li>
<li><strong>想把 AI 當協作者而不是神諭的人</strong>:你需要檢查它的產出、給它 context、設計工作流。</li>
</ul>
<h3 id="暫時不適合的人">暫時不適合的人</h3>
<ul>
<li><strong>純前端切版 / 純 UI 調整的工作</strong>:Cursor 這類工具視覺化支援更好。</li>
<li><strong>完全不看 terminal 的人</strong>:學習曲線會卡很久。</li>
<li><strong>一次性問答需求</strong>:「幫我解釋這段 code」這種需求,網頁版 Claude 反而快。</li>
<li><strong>想要「一鍵產生完整專案」的人</strong>:Claude Code 可以做,但你得先搞懂權限、context、hooks 這些基礎,否則會失控。</li>
</ul>
<p>這不是貶低任何一群人。工具有適用場景,選對工具比硬用同一個好。</p>
<hr>
<h2 id="給主管的一段話">給主管的一段話</h2>
<p>如果你是主管,在決定要不要讓團隊用 Claude Code,我自己的看法是:<strong>把它當成工程生產力工具來評估,我覺得比當「試試看的 AI 玩具」來看更走得遠</strong>。</p>
<ul>
<li>它<strong>不是</strong>要取代工程師。以我自己這三個月 POC 的觀察,它讓一位工程師的單日產出能被放大。</li>
<li>它<strong>確實</strong>有學習成本。我自己初期幾週也是越用越順手、並不是一上手就看出明顯效益。</li>
<li>它<strong>需要</strong>配合組織層面的規範(權限設定、敏感資料保護、產出審查),不是裝了就能用。</li>
<li>它的<strong>費用</strong>在團隊理解 token 消耗邏輯之後是可預測的(第 5 篇會詳談)。</li>
</ul>
<p>評估投資報酬時,我自己不太看「AI 寫了幾行程式碼」這類指標,覺得那比較容易誤導。我比較看的是「<strong>工程師完成同樣任務需要的總時間</strong>」和「<strong>產出的品質與可追溯性</strong>」。</p>
<hr>
<h2 id="這個系列會回答什麼">這個系列會回答什麼</h2>
<p>這是系列第 1 篇。已經上線的六篇依序展開機制、成本、與決策:</p>
<table>
  <thead>
      <tr>
          <th>#</th>
          <th>篇名</th>
          <th>你會學到</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>2</td>
          <td>Agent Loop — AI 助理的心跳機制</td>
          <td>一次對話背後發生了什麼,為什麼 token 這樣消耗</td>
      </tr>
      <tr>
          <td>3</td>
          <td>四層 Context 壓縮 — 200K 窗口的真實調度</td>
          <td>Context 何時被壓縮,<code>/compact</code> 什麼時候該用</td>
      </tr>
      <tr>
          <td>4</td>
          <td>Sub-agent 與 Agent Team — 分身 vs 分工(分上下集)</td>
          <td>兩個常被混為一談的概念,以及何時用哪個</td>
      </tr>
      <tr>
          <td>5</td>
          <td>Token 成本的真相 — 從原理到節省策略</td>
          <td>帳單為何爆炸,如何用工程手段把費用壓下來</td>
      </tr>
      <tr>
          <td>6</td>
          <td>當工具自薦時 — SSDLC 裡 Claude 各入口的角色與邊界</td>
          <td>每個階段該用哪個 Claude 入口,如何避開自薦文的偏誤</td>
      </tr>
      <tr>
          <td>7</td>
          <td>選型與合約 — 哪個 Claude 方案才對得起你的工作</td>
          <td>Anthropic 四種管道的真實差異、訓練政策風險、選對方案的一次性決策</td>
      </tr>
  </tbody>
</table>
<p>系列還有三篇正在準備中——第 8 篇《Hooks 與權限系統》會深入技術性的安全治理,第 9 篇《把 Claude Code 接進維運日常》是一位 infra 工程師的真實工作流整合,第 10 篇則專門處理「架構分析」與「飄移檢查」這兩類橫跨 SSDLC 的元活動。</p>
<p>如果你是<strong>純技術派</strong>,我建議讀 1、2、3、4 就夠。
如果你是<strong>實務派</strong>,讀 1、5、6、7 就夠,加上第 4 篇下集。
如果你是<strong>主管</strong>,讀 1、5、6、7 就夠。</p>
<hr>
<h2 id="一句話收尾">一句話收尾</h2>
<p>Claude Code 不是「比較強的 Copilot」。對我而言,它是<strong>一種讓工程師從執行者變成指揮官的工作方式</strong>,代價是你需要理解它的運作機制,不能當黑盒用。</p>
<p>下一篇我們從最基礎的 Agent Loop 開始拆解。</p>
<hr>
<p><em>本文作者:鄧景仁 (Scott Teng) | 資訊服務業 infra 工程師,專注於 Azure / Linux / 安全維運。如需討論可聯繫 <a href="mailto:st333117@gmail.com">st333117@gmail.com</a>。</em></p>
<p><em>本系列所有內容為個人學習與實務心得整理,不代表任職機構立場。</em></p>
<hr /><p style="font-size:0.9em;opacity:0.8;margin-top:2em;">本文原刊於 <a href="https://eeit.github.io/ai-devops-blog/posts/01-why-claude-code-is-different/" rel="canonical">https://eeit.github.io/ai-devops-blog/posts/01-why-claude-code-is-different/</a>，作者：鄧景仁 (Scott Teng)。<br />授權條款：<a href="https://creativecommons.org/licenses/by-nc/4.0/deed.zh_TW" rel="license">CC BY-NC 4.0</a> · 禁止商業使用；分享請署名並註明原文 URL。<br />商業授權請聯絡：st333117@gmail.com</p>]]></content:encoded>
    </item>
    <item>
      <title>Agent Loop:AI 助理的心跳機制</title>
      <link>https://eeit.github.io/ai-devops-blog/posts/02-agent-loop/</link>
      <pubDate>Mon, 13 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://eeit.github.io/ai-devops-blog/posts/02-agent-loop/</guid>
      <source url="https://eeit.github.io/ai-devops-blog/posts/02-agent-loop/">AI 輔助維運工程</source>
      <description>拆解 Claude Code 的核心運作機制 —— Agent Loop。搞懂一次對話背後發生了什麼,以及為什麼 token 會這樣消耗、為什麼長任務會越跑越慢。</description><content:encoded><![CDATA[<blockquote>
<p>本文為《AI 輔助維運工程:從 Claude Code 機制到企業落地》系列第 2 篇。前一篇談了為什麼 Claude Code 是不一樣的工具,這一篇開始進入它的運作核心。</p>
</blockquote>
<h2 id="為什麼先懂這個">為什麼先懂這個</h2>
<p>你可能以為你在「跟 Claude Code 對話」。</p>
<p>實際上,你是在<strong>驅動一個迴圈</strong>。</p>
<p>這個差異不是修辭。搞懂之後,後面所有的疑問都會有答案:</p>
<ul>
<li>為什麼同樣一句話,有時候 3 秒結束、有時候跑 5 分鐘?</li>
<li>為什麼 token 帳單會爆炸,而且完全看不出錢花在哪?</li>
<li>為什麼一個任務進行到一半會卡住?</li>
<li>為什麼「thinking&hellip;」有時候真的在想,有時候只是在處理資料?</li>
</ul>
<p>這些問題的根源都在 Agent Loop。這篇文章不是教你怎麼用 Claude Code,是要你<strong>建立一個關於它運作方式的心智模型</strong>,這個模型會貫穿整個系列。</p>
<hr>
<h2 id="三句話版本的-agent-loop">三句話版本的 Agent Loop</h2>
<p>如果要用最精簡的方式描述,Claude Code 做的事情就是這三件:</p>
<ol>
<li><strong>接收輸入</strong>,組裝成模型看得懂的 prompt</li>
<li><strong>呼叫模型</strong>,拿到回應</li>
<li><strong>判斷要不要繼續</strong>,要繼續就執行工具,拿結果回到第 1 步</li>
</ol>
<p>聽起來很簡單。但魔鬼在細節裡,尤其是第 3 步的「判斷要不要繼續」。這個判斷讓 Claude Code 從「問答工具」變成「任務執行者」。</p>
<hr>
<h2 id="一次對話實際發生了什麼">一次對話實際發生了什麼</h2>
<p>我們用一個具體情境拆解:你在 Claude Code 裡輸入「幫我看看今天早上 nginx 的錯誤日誌,有沒有 5xx 的異常」,然後按下 Enter。</p>
<p>接下來發生的事情,可以分成六個階段。</p>
<h3 id="階段一你按下-enter-之後的-01-秒">階段一:你按下 Enter 之後的 0.1 秒</h3>
<p>訊息送進 Claude Code 的處理管線之前,先經過一道<strong>輸入處理</strong>:</p>
<ul>
<li>如果你輸入的是 slash command(像 <code>/compact</code>、<code>/init</code>),會被攔截走另一條路徑</li>
<li>如果你附加了圖片或檔案,會被轉成對應的 message block</li>
<li>如果你用 <code>@</code> 引用了檔案(<code>@src/main.ts</code>),會把檔案內容塞進 context</li>
<li>純文字就直接進入下一步</li>
</ul>
<p>這一步很快,但它決定了<strong>你送進去的不只是你打的那幾個字</strong>。</p>
<h3 id="階段二system-prompt-的組裝">階段二:System Prompt 的組裝</h3>
<p>這是很多人忽略的關鍵環節。</p>
<p>每次你送訊息,Claude Code 會動態組裝一個 system prompt,這個 prompt 由好幾個部分拼成:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="p">[</span><span class="err">核心身份與工具說明</span><span class="p">]</span>          <span class="err">←</span> <span class="n">Claude</span> <span class="n">Code</span> <span class="err">本身的</span> <span class="n">prompt</span><span class="p">,</span><span class="err">固定</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">環境資訊</span><span class="p">]</span>                    <span class="err">←</span> <span class="err">作業系統、</span><span class="n">shell</span><span class="err">、目前工作目錄</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">專案上下文</span><span class="p">]</span>                  <span class="err">←</span> <span class="err">你的</span> <span class="n">CLAUDE</span><span class="o">.</span><span class="n">md</span> <span class="err">和</span> <span class="err">@</span><span class="n">import</span> <span class="err">的檔案</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">MCP</span> <span class="err">工具描述</span><span class="p">]</span>                <span class="err">←</span> <span class="err">你裝的</span> <span class="n">MCP</span> <span class="n">servers</span> <span class="err">的</span> <span class="k">tool</span> <span class="n">schemas</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">內建工具描述</span><span class="p">]</span>                <span class="err">←</span> <span class="n">Read</span><span class="o">/</span><span class="n">Write</span><span class="o">/</span><span class="n">Bash</span><span class="o">/</span><span class="n">Grep</span> <span class="err">等工具的說明</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">Git</span> <span class="err">狀態</span><span class="p">]</span>                    <span class="err">←</span> <span class="err">目前</span> <span class="n">branch</span><span class="err">、</span><span class="n">uncommitted</span> <span class="n">changes</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">過去對話歷史</span><span class="p">]</span>                <span class="err">←</span> <span class="err">如果是延續</span> <span class="n">session</span><span class="p">,</span><span class="err">過去的</span> <span class="n">turns</span> <span class="err">都在這</span>
</span></span></code></pre></div><p>這個組裝順序和內容會影響兩件事:</p>
<ol>
<li><strong>Token 消耗</strong>:每次送出的 prompt 越長,輸入 token 越多。</li>
<li><strong>模型行為</strong>:你 CLAUDE.md 怎麼寫,直接決定模型會怎麼回應你。</li>
</ol>
<p>這也是為什麼<strong>減少 CLAUDE.md 裡不必要的內容,我自己觀察是 token 優化裡很容易見效的一個手段</strong>。把 CLAUDE.md 寫成長篇大論,等於每一輪都在付那個長篇大論的錢。</p>
<h3 id="階段三api-call-與-streaming">階段三:API Call 與 Streaming</h3>
<p>組裝好的 prompt 送到 Anthropic 的 API,模型開始回應。</p>
<p>你注意過嗎?Claude Code 的回應是<strong>一個字一個字跑出來</strong>的,不是整段突然出現。這叫做 <strong>streaming</strong>,模型一邊思考一邊吐字,Claude Code 一邊接一邊顯示。</p>
<p>Streaming 有幾個現實影響:</p>
<ul>
<li><strong>你可以在中途按 Esc 取消</strong>:模型還沒講完,你就可以打斷它,不用等它講完再操作。</li>
<li><strong>延遲感知比較低</strong>:即使整個回應要 30 秒,你看到第一個字通常只要 1-2 秒。</li>
<li><strong>Tool use 也是 stream 的一部分</strong>:當模型決定要呼叫工具,那個指令也是 stream 出來的,Claude Code 接到就準備執行。</li>
</ul>
<h3 id="階段四tool-的識別與執行">階段四:Tool 的識別與執行</h3>
<p>這是 Agent Loop 最核心的一步。</p>
<p>模型的回應裡可能有兩種東西:</p>
<ul>
<li><strong>純文字</strong>:給你看的說明、分析、結論</li>
<li><strong>Tool Use Block</strong>:「我需要執行某個工具,請幫我跑」的指令</li>
</ul>
<p>當 Claude Code 偵測到 tool use block,它會:</p>
<ol>
<li>檢查這個工具是否在白名單(對應上一篇講的三道關卡)</li>
<li>如果需要你確認(ask 規則),跳出確認對話</li>
<li>實際執行這個工具(讀檔、跑 bash、呼叫 MCP 等)</li>
<li>把執行結果包成 tool_result,準備送回模型</li>
</ol>
<p>用我們的 nginx 例子:</p>
<ul>
<li>模型第一輪可能先發出 <code>Bash: ls /var/log/nginx/</code> 想看有哪些 log 檔</li>
<li>Claude Code 執行後,把結果送回模型</li>
<li>模型第二輪可能發出 <code>Bash: grep -E &quot; 5[0-9]{2} &quot; /var/log/nginx/access.log | head -50</code> 篩出 5xx</li>
<li>執行後結果再送回</li>
<li>模型第三輪可能已經分析完,直接用文字回答你</li>
</ul>
<p>你看到的「Claude 幫我查完了」,其實是<strong>至少 3 次 API call + 2 次工具執行</strong>的結果。</p>
<h3 id="階段五判斷要不要繼續">階段五:判斷要不要繼續</h3>
<p>這是 loop 的關鍵節點。</p>
<p>每一輪模型回應結束後,Claude Code 會問:<strong>回應裡還有 tool use block 嗎?</strong></p>
<ul>
<li><strong>有</strong> → 執行工具,把結果送回,進入下一輪</li>
<li><strong>沒有</strong>(只有文字) → loop 結束,把控制權交還給你</li>
</ul>
<p>這個判斷聽起來簡單,但它是整個 agentic 行為的基礎。模型自己決定「我需要更多資訊」或「我完成了」,不需要你每一步都按「繼續」。</p>
<h3 id="階段六終止條件">階段六:終止條件</h3>
<p>除了模型自主判斷完成,loop 還有幾個強制終止的條件:</p>
<ul>
<li><strong>Max turns</strong>:預防無限迴圈,達到上限會停</li>
<li><strong>使用者中斷</strong>:你按 Esc</li>
<li><strong>權限拒絕</strong>:你拒絕了某個工具的 ask,而模型沒有備案</li>
<li><strong>錯誤</strong>:API 失敗、tool 執行錯誤且模型無法處理</li>
</ul>
<p>這解釋了為什麼<strong>你有時候覺得 Claude Code「沒做完就停了」</strong> —— 它其實是碰到了某個終止條件。看錯誤訊息或 verbose mode 可以知道是哪一個。</p>
<hr>
<h2 id="一張圖總結agent-loop-的完整流程">一張圖總結:Agent Loop 的完整流程</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="err">你按下</span> <span class="n">Enter</span>
</span></span><span class="line"><span class="cl">    <span class="err">│</span>
</span></span><span class="line"><span class="cl">    <span class="err">▼</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">輸入處理</span><span class="p">]</span> <span class="n">slash</span> <span class="n">command</span><span class="err">?</span> <span class="err">附件?</span> <span class="err">@引用?</span>
</span></span><span class="line"><span class="cl">    <span class="err">│</span>
</span></span><span class="line"><span class="cl">    <span class="err">▼</span>
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="err">組裝</span> <span class="n">system</span> <span class="n">prompt</span><span class="p">]</span> <span class="err">固定部分</span> <span class="o">+</span> <span class="err">環境</span> <span class="o">+</span> <span class="n">CLAUDE</span><span class="o">.</span><span class="n">md</span> <span class="o">+</span> <span class="n">tools</span> <span class="o">+</span> <span class="n">git</span> <span class="o">+</span> <span class="err">歷史</span>
</span></span><span class="line"><span class="cl">    <span class="err">│</span>
</span></span><span class="line"><span class="cl">    <span class="err">▼</span>
</span></span><span class="line"><span class="cl"><span class="err">┌───</span> <span class="err">進入</span> <span class="n">Query</span> <span class="n">Loop</span> <span class="err">───┐</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>                        <span class="err">│</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>  <span class="p">[</span><span class="err">呼叫</span> <span class="n">API</span><span class="p">,</span><span class="n">streaming</span> <span class="err">回應</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>           <span class="err">│</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>           <span class="err">▼</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>  <span class="p">[</span><span class="err">識別</span> <span class="n">tool_use</span> <span class="n">block</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>           <span class="err">│</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>     <span class="err">有</span> <span class="err">─┴─</span> <span class="err">沒有</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>      <span class="err">│</span>       <span class="err">│</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>      <span class="err">▼</span>       <span class="err">▼</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>  <span class="p">[</span><span class="err">執行工具</span><span class="p">]</span>  <span class="p">[</span><span class="err">結束</span> <span class="n">loop</span><span class="p">,</span><span class="err">回傳給你</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>      <span class="err">│</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>      <span class="err">▼</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>  <span class="p">[</span><span class="err">結果送回模型</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>      <span class="err">│</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>      <span class="err">└──→</span> <span class="p">(</span><span class="err">下一輪</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="err">│</span>
</span></span><span class="line"><span class="cl"><span class="err">└────────────────────────┘</span>
</span></span></code></pre></div><p>這就是每次你跟 Claude Code 互動時,底層真正發生的事。</p>
<hr>
<h2 id="tool-執行序列還是平行">Tool 執行:序列還是平行?</h2>
<p>模型在一次回應中可以發出<strong>多個</strong> tool use block。當這發生時,Claude Code 要決定:這些工具能不能同時跑?</p>
<p>判斷邏輯大致是:</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>執行方式</th>
          <th>原因</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>多個 Read 操作</td>
          <td>平行</td>
          <td>只讀,不互相影響</td>
      </tr>
      <tr>
          <td>多個 Grep / Glob</td>
          <td>平行</td>
          <td>搜尋也是只讀</td>
      </tr>
      <tr>
          <td>多個 Bash command</td>
          <td>序列</td>
          <td>可能有副作用(改檔案、改狀態)</td>
      </tr>
      <tr>
          <td>Read + Write 同一個檔案</td>
          <td>序列</td>
          <td>必須先 Read 再 Write,有依賴</td>
      </tr>
      <tr>
          <td>多個獨立的 Write</td>
          <td>通常序列</td>
          <td>謹慎起見,避免競態</td>
      </tr>
  </tbody>
</table>
<p><strong>為什麼這個區分重要?</strong> 因為平行執行會大幅加速任務。當 Claude Code 一次叫 10 個 Read 去看 10 個檔案,平行跑和序列跑的體感差距是 10 倍以上。</p>
<p>這也是為什麼 Claude Code 有「Explore」這類<strong>唯讀</strong> sub-agent —— 唯讀保證可以平行,速度快,而且不會搞壞東西。(Sub-agent 的主題會在第 4 篇展開)</p>
<hr>
<h2 id="這些機制對你實際操作的意義">這些機制對你實際操作的意義</h2>
<p>搞懂 loop 之後,很多「奇怪的現象」都有答案了。</p>
<h3 id="為什麼長任務會越跑越慢">為什麼長任務會越跑越慢</h3>
<p>每一輪 loop,Claude Code 都要把<strong>整段對話歷史</strong>重新送進 API。對話越長,每一輪要傳的東西越多,API 呼叫越慢,也越貴。</p>
<p>這就是為什麼到了某個臨界點,任務會明顯變慢。原因不是「AI 累了」,是 context 逼近上限,<strong>每一輪的 overhead 越來越大</strong>。</p>
<p>這個問題的解方就是 context 壓縮,下一篇會整個展開。</p>
<h3 id="為什麼thinking有時候很久">為什麼「thinking&hellip;」有時候很久</h3>
<p>「thinking&hellip;」其實有兩種:</p>
<ol>
<li><strong>真的在 extended thinking</strong>:模型在做內部推理,這部分會花時間但也確實在產出思考</li>
<li><strong>在處理 tool result</strong>:前一個工具剛跑完,結果很大(例如讀了一個 500 行的檔案),模型正在消化</li>
</ol>
<p>如果你覺得 thinking 太久,可以開 verbose mode 看它到底在做什麼。通常第二種比較常見。</p>
<h3 id="為什麼某些操作會卡住等你">為什麼某些操作會卡住等你</h3>
<p>這是權限系統介入的時刻。當模型想做的事情在 <code>ask</code> 規則裡,Claude Code 會跳出確認對話,loop 在你回應之前是停住的。</p>
<p>這不是 bug,是設計 —— 確保你對破壞性操作有最後一次確認機會。</p>
<h3 id="為什麼同樣一句話效果差很多">為什麼同樣一句話,效果差很多</h3>
<p>兩個使用者問一樣的問題,結果天差地遠的主因不是「模型不穩」,而是:</p>
<ul>
<li>CLAUDE.md 寫得不一樣</li>
<li>當前 working directory 不一樣</li>
<li>已經在 session 裡累積的 context 不一樣</li>
<li>裝的 MCP tools 不一樣</li>
</ul>
<p>System prompt 的組裝階段(階段二)就決定了結果差異中很大一部分。這也是為什麼我覺得<strong>團隊裡把 CLAUDE.md 寫好、統一管理,通常會比讓每個人自己摸索更可預期一些</strong>。</p>
<hr>
<h2 id="我自己經歷的一次觀念轉換">我自己經歷的一次觀念轉換</h2>
<p>我自己一開始使用 AI 助理的心理模型是這樣:</p>
<blockquote>
<p>「我在問 AI 一個問題,它回答我。」</p>
</blockquote>
<p>用 Claude Code 一段時間後,我自己慢慢轉成這樣:</p>
<blockquote>
<p>「我啟動了一個迴圈,這個迴圈會執行多輪,直到達成我給的目標或觸發終止條件。我的任務是<strong>設計好這個迴圈的起點、邊界、和終止條件</strong>。」</p>
</blockquote>
<p>這個轉換之後,我開始問自己不一樣的問題:</p>
<ul>
<li>我這句 prompt 會讓 loop 跑幾輪?會不會太多?</li>
<li>這個任務需要的 context 是否都在 loop 開始時就備好了?</li>
<li>如果 loop 跑太久,我該怎麼設計 checkpoint?</li>
<li>什麼情況下應該主動終止 loop,換個方式再來?</li>
</ul>
<p>這些是我自己覺得在「熟練使用 Claude Code」之後比較常想的事。</p>
<hr>
<h2 id="下一篇預告">下一篇預告</h2>
<p>搞懂 loop 之後,下一個繞不開的主題就是 <strong>context 管理</strong>。</p>
<p>在這篇裡我們看到:每一輪 loop 都要把整個 context 送進 API。當 context 逼近上限會發生什麼?Claude Code 怎麼在你不察覺的情況下,把空間清出來?</p>
<p>這個系統比表面看起來精巧 —— 有四層壓縮管線,每一層用不同的策略,該什麼時候哪一層啟動都有明確規則。</p>
<p>下一篇,我們把這個黑盒打開。</p>
<hr>
<h2 id="本篇重點整理">本篇重點整理</h2>
<ul>
<li>Claude Code 不是對話工具,是<strong>任務執行迴圈</strong> —— Agent Loop</li>
<li>每次你按 Enter,會經過六個階段:輸入處理 → 組裝 system prompt → API call → 識別 tool use → 執行工具 → 判斷是否繼續</li>
<li>Loop 的終止由<strong>模型自主判斷</strong>或<strong>強制條件</strong>(max turns、權限拒絕、錯誤、使用者中斷)觸發</li>
<li>Tool 可以<strong>平行或序列執行</strong>,唯讀類通常平行、有副作用的通常序列</li>
<li>長任務變慢的主因是 <strong>context 越來越大</strong>,每一輪 overhead 放大</li>
<li>心智模型上的轉換:從「我在問 AI」到「我在驅動一個迴圈」</li>
</ul>
<hr>
<p><em>本文作者:鄧景仁 (Scott Teng) | 資訊服務業 infra 工程師,專注於 Azure / Linux / 安全維運。如需討論可聯繫 <a href="mailto:st333117@gmail.com">st333117@gmail.com</a>。</em></p>
<p><em>本系列所有內容為個人學習與實務心得整理,不代表任職機構立場。本文對 Claude Code 內部機制的描述,基於社群對 Claude Code 的公開分析材料與筆者實務觀察,並非 Anthropic 官方文件。</em></p>
<hr /><p style="font-size:0.9em;opacity:0.8;margin-top:2em;">本文原刊於 <a href="https://eeit.github.io/ai-devops-blog/posts/02-agent-loop/" rel="canonical">https://eeit.github.io/ai-devops-blog/posts/02-agent-loop/</a>，作者：鄧景仁 (Scott Teng)。<br />授權條款：<a href="https://creativecommons.org/licenses/by-nc/4.0/deed.zh_TW" rel="license">CC BY-NC 4.0</a> · 禁止商業使用；分享請署名並註明原文 URL。<br />商業授權請聯絡：st333117@gmail.com</p>]]></content:encoded>
    </item>
    <item>
      <title>四層 Context 壓縮:200K 窗口的真實調度</title>
      <link>https://eeit.github.io/ai-devops-blog/posts/03-context-compression/</link>
      <pubDate>Tue, 14 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://eeit.github.io/ai-devops-blog/posts/03-context-compression/</guid>
      <source url="https://eeit.github.io/ai-devops-blog/posts/03-context-compression/">AI 輔助維運工程</source>
      <description>拆解 Claude Code 中我覺得比較精巧、也容易被誤解的設計 —— 四層 Context 壓縮管線。搞懂 context 何時被壓縮、如何決定哪一層啟動,以及手動 /compact 該在什麼時機使用。</description><content:encoded><![CDATA[<blockquote>
<p>本文為《AI 輔助維運工程:從 Claude Code 機制到企業落地》系列第 3 篇。前一篇談了 Agent Loop,這一篇會進入<strong>這個系列裡技術密度較高的主題</strong>。如果你之前對「為什麼我的 context 會突然不夠用」、「<code>/compact</code> 到底何時該按」、「Claude 為什麼突然開始忘東西」這些問題感到困惑,這篇會把這些機制一起拆開來看。</p>
</blockquote>
<h2 id="為什麼需要整整一篇寫這件事">為什麼需要整整一篇寫這件事</h2>
<p>前一篇講了 Agent Loop —— 每一輪模型呼叫,都要把<strong>整段對話歷史</strong>送進 API。</p>
<p>這件事在對話短的時候沒人會在意。但當任務開始變長:</p>
<ul>
<li>一個跨 10 個檔案的重構</li>
<li>一次完整的事件排查</li>
<li>一份規格文件從草稿到定稿的對話</li>
</ul>
<p>你會發現一個令人焦慮的現象:<strong>Claude Code 開始回應變慢、帳單變貴、有時候甚至主動告訴你「context 快滿了」</strong>。</p>
<p>根本原因在於 context window 的物理上限。以目前主流的 Claude 模型來說:</p>
<ul>
<li><strong>舊一代模型</strong>(例如 Sonnet 4、Sonnet 4.5):上限 <strong>200K tokens</strong></li>
<li><strong>新一代模型</strong>(Opus 4.6 / 4.7、Sonnet 4.6):上限提升到 <strong>1M tokens</strong>,且自 2026 年 3 月起已 GA 無溢價</li>
</ul>
<p>聽起來 1M 似乎什麼煩惱都沒了?實際沒這麼簡單 —— 稍後會有一節專門談「1M 不是萬靈丹」。這裡先建立一個共識:<strong>不論你用哪一代模型,壓縮管線的設計原理都一樣,只是觸發閾值不同</strong>。</p>
<p>一個五小時的維運任務,搭配幾份被讀進 context 的大型設定檔,即使在 200K 窗口也會消耗得比你想像快。</p>
<p>如果 Claude Code 對這件事不做任何處理,用戶體驗會是這樣:</p>
<blockquote>
<p>使用到 80%:正常
80% → 95%:越來越慢,因為每一輪都在傳巨量 context
95% → 100%:API 開始拒絕,因為超過模型上限
100% 之後:session 直接掛掉,你要從頭來過</p>
</blockquote>
<p><strong>所以 Claude Code 設計了一套系統,在你不察覺的情況下,持續清理 context 空間</strong>。這套系統有四層,每一層用不同策略,對 token 的衝擊從「幾乎零成本」到「呼叫一次 API 做摘要」不等。</p>
<p>這篇文章要做的,就是把這四層攤開來。</p>
<hr>
<h2 id="為什麼不能只用一種壓縮策略">為什麼不能只用一種壓縮策略</h2>
<p>你可能會想:為什麼不直接一招?等 context 滿了再叫模型摘要不就好?</p>
<p>這會有兩個問題。</p>
<p><strong>問題一:摘要本身很貴</strong>。讓模型把 100K tokens 的對話摘成 20K tokens,這個動作就要再花一次 API call,還要花 output token 產生那 20K 摘要。如果每隔幾輪就做一次,光摘要就吃光你的預算。</p>
<p><strong>問題二:過早摘要會丟失資訊</strong>。你不會希望一個還在處理中的子任務被摘成三句話 —— 模型會失去它需要的細節,回應品質直接掉下來。</p>
<p>合理的設計是:<strong>先用最便宜的手段釋放空間,真的不夠了再用昂貴的手段</strong>。這就是四層管線的核心思想。</p>
<hr>
<h2 id="四層管線的全景">四層管線的全景</h2>
<p>在每一輪 Agent Loop 準備呼叫 API 之前,Claude Code 會依序跑過下面這些階段:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"> <span class="err">┌─────────────────────────────────────────────┐</span>
</span></span><span class="line"><span class="cl"> <span class="err">│</span>  <span class="n">Pre</span><span class="o">-</span><span class="n">pipeline</span><span class="p">:</span> <span class="n">Tool</span> <span class="n">Result</span> <span class="n">Budget</span>           <span class="err">│</span>  <span class="err">←</span> <span class="err">過大</span> <span class="k">tool</span> <span class="n">result</span> <span class="err">的預先處理</span>
</span></span><span class="line"><span class="cl"> <span class="err">└─────────────────────────────────────────────┘</span>
</span></span><span class="line"><span class="cl">                      <span class="err">│</span>
</span></span><span class="line"><span class="cl">                      <span class="err">▼</span>
</span></span><span class="line"><span class="cl"> <span class="err">┌─────────────────────────────────────────────┐</span>
</span></span><span class="line"><span class="cl"> <span class="err">│</span>  <span class="n">Layer</span> <span class="mi">1</span><span class="p">:</span> <span class="n">Snip</span> <span class="n">Compact</span>                       <span class="err">│</span>  <span class="err">←</span> <span class="err">零成本修剪</span>
</span></span><span class="line"><span class="cl"> <span class="err">└─────────────────────────────────────────────┘</span>
</span></span><span class="line"><span class="cl">                      <span class="err">│</span>
</span></span><span class="line"><span class="cl">                      <span class="err">▼</span>
</span></span><span class="line"><span class="cl"> <span class="err">┌─────────────────────────────────────────────┐</span>
</span></span><span class="line"><span class="cl"> <span class="err">│</span>  <span class="n">Layer</span> <span class="mi">2</span><span class="p">:</span> <span class="n">Micro</span> <span class="n">Compact</span>                      <span class="err">│</span>  <span class="err">←</span> <span class="k">tool</span> <span class="n">result</span> <span class="err">壓縮</span>
</span></span><span class="line"><span class="cl"> <span class="err">└─────────────────────────────────────────────┘</span>
</span></span><span class="line"><span class="cl">                      <span class="err">│</span>
</span></span><span class="line"><span class="cl">                      <span class="err">▼</span>
</span></span><span class="line"><span class="cl"> <span class="err">┌─────────────────────────────────────────────┐</span>
</span></span><span class="line"><span class="cl"> <span class="err">│</span>  <span class="n">Layer</span> <span class="mi">3</span><span class="p">:</span> <span class="n">Context</span> <span class="n">Collapse</span>                   <span class="err">│</span>  <span class="err">←</span> <span class="err">投射式壓縮</span>
</span></span><span class="line"><span class="cl"> <span class="err">└─────────────────────────────────────────────┘</span>
</span></span><span class="line"><span class="cl">                      <span class="err">│</span>
</span></span><span class="line"><span class="cl">                      <span class="err">▼</span>
</span></span><span class="line"><span class="cl"> <span class="err">┌─────────────────────────────────────────────┐</span>
</span></span><span class="line"><span class="cl"> <span class="err">│</span>  <span class="n">Layer</span> <span class="mi">4</span><span class="p">:</span> <span class="n">Auto</span> <span class="n">Compact</span>                       <span class="err">│</span>  <span class="err">←</span> <span class="n">API</span> <span class="err">摘要</span><span class="p">(</span><span class="err">最貴</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="err">└─────────────────────────────────────────────┘</span>
</span></span><span class="line"><span class="cl">                      <span class="err">│</span>
</span></span><span class="line"><span class="cl">                      <span class="err">▼</span>
</span></span><span class="line"><span class="cl">           <span class="p">[</span><span class="err">送進</span> <span class="n">API</span> <span class="err">呼叫模型</span><span class="p">]</span>
</span></span></code></pre></div><p>每一層都有它啟動的條件、代價、和清出空間的能力。我們一層一層拆。</p>
<hr>
<h2 id="pre-pipelinetool-result-budget">Pre-pipeline:Tool Result Budget</h2>
<p>這一層嚴格來說不是壓縮,是<strong>預防性措施</strong>。</p>
<p>場景:Claude Code 執行了一個 <code>Bash: cat /var/log/nginx/access.log</code>,檔案有 80MB。如果這 80MB 整個塞進 context,後面的管線會瞬間爆炸。</p>
<p>Tool Result Budget 做的事就是在 tool 執行結果進入 context 之前,先判斷它的大小。超過門檻的,會被<strong>內容替換</strong>(content replacement)—— 把原始龐大結果換成一個摘要訊息,原始內容寫入磁碟保留,context 裡只放一個引用。</p>
<p>這個設計很精巧的一點是:<strong>替換狀態跨壓縮持久化</strong>。也就是說,即使後面 Layer 4 做了大摘要,這個「被替換過的 tool result」的記憶不會丟失,模型還是知道「剛才跑了那個指令,結果很大被外存了」。</p>
<p><strong>對你的影響</strong>:你不太需要關心這一層,它自動運作。但知道它存在有一個好處 —— 當你看到 tool result 被標記「truncated」時,那不是 bug,是這個機制在保護你。</p>
<hr>
<h2 id="layer-1snip-compact零成本修剪">Layer 1:Snip Compact(零成本修剪)</h2>
<p>接下來進入壓縮管線的第一層,也是最便宜的一層。</p>
<p>Snip Compact 做的事情可以用一句話概括:<strong>把舊的、明顯可以丟的片段直接刪掉</strong>。</p>
<p>什麼叫「明顯可以丟」?典型的例子:</p>
<ul>
<li>很多輪之前的一個 <code>Bash: ls</code> 指令和它的輸出</li>
<li>已經被後續行為覆蓋的舊檔案讀取結果</li>
<li>使用者已經明確說「這個不用了」的段落</li>
</ul>
<p>這一層的關鍵特徵是 <strong>「零成本」</strong> —— 它不呼叫 API、不做推理、只是按規則把某些 message 從 context 移除。計算開銷幾乎為零,釋放的空間卻可能非常可觀。</p>
<p><strong>類比</strong>:就像你整理辦公桌時,先把明顯沒用的廢紙丟掉,還沒開始動需要判斷的東西。</p>
<p>Snip Compact 在每一輪都會跑,永遠是第一道防線。你幾乎察覺不到它在作用,但它默默為你省了大量空間。</p>
<hr>
<h2 id="layer-2micro-compacttool-result-壓縮">Layer 2:Micro Compact(tool result 壓縮)</h2>
<p>第二層開始有點技巧了。</p>
<p>Micro Compact 聚焦在<strong>處理 tool result</strong>。上一層刪了能直接丟的,但有些 tool result 還有價值 —— 模型可能之後要引用 —— 只是<strong>詳細程度過頭了</strong>。</p>
<p>舉例:你讓 Claude Code 讀了一個 500 行的設定檔,它讀完後做了分析,已經從裡面抽出重點。兩輪之後,完整的 500 行內容還佔著 context。這時候 Micro Compact 會做的事情是:</p>
<p><strong>保留這個 tool result 的「殼」(它的 tool_use_id、它是哪個 tool、執行成功與否),但把詳細的內容替換成一個摘要</strong>。</p>
<p>關鍵設計:Micro Compact 以 <strong>tool_use_id</strong> 為單位運作,不拆解內容、不重組訊息結構。這讓它可以跟其他層安全組合 —— 它的處理不會影響訊息格式的完整性。</p>
<p><strong>相較於 Layer 1</strong>:Layer 1 是「整段丟」,Layer 2 是「保留外層、壓縮內容」。Layer 2 的成本比 Layer 1 高一點(要產生摘要),但保留了可追溯性 —— 模型仍然知道「我剛才讀過某個檔案」。</p>
<hr>
<h2 id="layer-3context-collapse投射式壓縮">Layer 3:Context Collapse(投射式壓縮)</h2>
<p>這一層的設計最巧妙,也最難懂。</p>
<p>一般壓縮的做法是「<strong>修改 context 本身</strong>」—— 刪掉某些東西、取代某些內容。但這有個風險:修改是不可逆的。你丟掉的東西,就真的丟了。</p>
<p>Context Collapse 採用完全不同的思路:<strong>不修改底層的訊息歷史,而是建立一個「投射視圖」</strong>(projective view)。</p>
<p>用一個比喻:</p>
<blockquote>
<p>想像你的對話歷史是一棟三層樓的書櫃,整整齊齊放著所有 message。
傳統壓縮是把某幾本書從書櫃搬走、直接丟掉。
Context Collapse 是<strong>在書櫃前面加一片毛玻璃</strong> —— 書櫃本身沒變,但從外面看,某些書被遮住了,只看得到一個整體的輪廓。</p>
</blockquote>
<p>這個設計的好處是:</p>
<ol>
<li><strong>可還原</strong>:必要時可以把毛玻璃拿掉,完整歷史還在</li>
<li><strong>適合長 session</strong>:即使做了多次 collapse,底層訊息仍然保存</li>
<li><strong>給模型一個「精華版」</strong>:模型看到的是投射後的版本,而不是原始的完整對話</li>
</ol>
<p><strong>Context Collapse 的觸發有兩個門檻</strong>:</p>
<ul>
<li>到達 <strong>90%</strong> 時:開始做 collapse commit(把舊的 message 封存進 collapse log)</li>
<li>到達 <strong>95%</strong> 時:進入 blocking 模式,禁止新的 tool 執行,避免 context 爆炸</li>
</ul>
<p>Context Collapse 是一個<strong>功能開關</strong>(feature flag),不是所有版本的 Claude Code 都預設啟用。如果啟用了,它會取代 Layer 4 的工作(兩者互斥)。</p>
<p><strong>對你的影響</strong>:如果你的版本啟用了這層,你會發現長 session 的品質比舊版本明顯穩定。但如果沒啟用,接下來的 Layer 4 就是最後防線。</p>
<hr>
<h2 id="layer-4auto-compact最重的手段">Layer 4:Auto Compact(最重的手段)</h2>
<p>前三層都還沒能把空間清出來夠用?好,Auto Compact 登場。</p>
<p>這是<strong>最貴、也最強</strong>的一層。它的做法是:</p>
<ol>
<li>開一個<strong>分叉的 agent</strong>(forked agent)</li>
<li>這個 agent 的任務就是:把到目前為止的對話歷史,摘要成一段簡短的文字</li>
<li>把原本的對話歷史替換成這段摘要</li>
<li>繼續跑主 session</li>
</ol>
<p>本質上,這是<strong>花一次 API call 去換 context 空間</strong>。成本高,但效果也最顯著 —— 幾十萬 tokens 可以瞬間被壓成幾千 tokens。</p>
<h3 id="閾值的數學">閾值的數學</h3>
<p>Auto Compact 什麼時候觸發?這有明確的公式:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">effective_window = context_window - 20,000  ← 保留給摘要輸出的空間
</span></span><span class="line"><span class="cl">threshold        = effective_window - 13,000  ← 再留一個緩衝
</span></span></code></pre></div><p>套用到不同的 context window:</p>
<p><strong>200K 窗口(Sonnet 4 / 4.5 等舊一代模型)</strong>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">effective_window = 200,000 - 20,000 = 180,000
</span></span><span class="line"><span class="cl">threshold        = 180,000 - 13,000 = 167,000   ← 約 83.5%
</span></span></code></pre></div><p>意思是:當 context 用到 167K 左右時,Auto Compact 自動觸發。</p>
<p><strong>1M 窗口(Sonnet 4.6、Opus 4.6 / 4.7)</strong>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">effective_window = 1,000,000 - 20,000 = 980,000
</span></span><span class="line"><span class="cl">threshold        = 980,000 - 13,000 = 967,000   ← 約 96.7%
</span></span></code></pre></div><p>也就是說,<strong>1M 模型要撐到 967K 才會觸發 Auto Compact</strong>。實務上大多數 session 根本打不到這個數字,Auto Compact 在 1M 模型上幾乎不會被自動觸發。</p>
<p>為什麼都留 20K 給摘要?因為摘要本身也是 output tokens,也要在 context 裡佔位置。如果不預留,摘要還沒生出來就超標了。這個設計不隨 window 大小變。</p>
<p><strong>要查自己目前的 window 大小,在 Claude Code 裡輸入 <code>/context</code> 指令,它會回傳 <code>Xk/200k</code> 或 <code>Xk/1000k</code> 的格式告訴你</strong>。</p>
<h3 id="互斥規則">互斥規則</h3>
<p>Auto Compact 有幾個情況<strong>不會</strong>觸發,原因都很務實:</p>
<table>
  <thead>
      <tr>
          <th>情境</th>
          <th>為什麼不觸發</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>正在做 <code>/compact</code> 或 session memory 操作</td>
          <td>避免遞迴(本身就是 compact agent)</td>
      </tr>
      <tr>
          <td>Context Collapse 已啟用</td>
          <td>Layer 3 已經在做這件事</td>
      </tr>
      <tr>
          <td>Reactive Compact 模式</td>
          <td>等 API 真的回傳「context 太長」錯誤才處理</td>
      </tr>
      <tr>
          <td>連續失敗超過 3 次</td>
          <td>Circuit breaker,避免無限重試</td>
      </tr>
  </tbody>
</table>
<p>那個 <strong>3 次連續失敗 circuit breaker</strong> 很值得一提 —— 它的存在是因為沒這個機制的時候,曾經有 session 連續失敗 50 多次,浪費了大量 API 呼叫。工程設計常常是這樣:一個看似簡單的保護機制,背後都是血淚史。</p>
<h3 id="session-memory被忽略的精巧設計">Session Memory:被忽略的精巧設計</h3>
<p>Layer 4 有個優先嘗試的輕量版,叫 <strong>Session Memory Compaction</strong>。</p>
<p>相較於「開一個 agent 做全摘要」,Session Memory 更像「<strong>智慧修剪</strong>」—— 它不重新生成內容,而是有策略地挑選哪些 message 保留、哪些捨棄,試圖在<strong>不花一次 API call</strong> 的情況下達到目標。</p>
<p>觸發順序是:<strong>Session Memory 先試 → 失敗才走 full compact</strong>。這又是一個「便宜的先試,貴的最後上」的設計。</p>
<hr>
<h2 id="為什麼這樣排序一個簡單的經濟學">為什麼這樣排序:一個簡單的經濟學</h2>
<p>回頭看這四層,你會發現它們的排列是有嚴格邏輯的:</p>
<table>
  <thead>
      <tr>
          <th>層級</th>
          <th>成本</th>
          <th>空間釋放量</th>
          <th>資訊損失</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Pre-pipeline</td>
          <td>低</td>
          <td>視 tool result 大小</td>
          <td>最小(可還原)</td>
      </tr>
      <tr>
          <td>Layer 1 Snip</td>
          <td>接近零</td>
          <td>小到中</td>
          <td>小(丟的是舊東西)</td>
      </tr>
      <tr>
          <td>Layer 2 Micro</td>
          <td>低</td>
          <td>中</td>
          <td>小(保留摘要)</td>
      </tr>
      <tr>
          <td>Layer 3 Collapse</td>
          <td>中</td>
          <td>大</td>
          <td>最小(投射式)</td>
      </tr>
      <tr>
          <td>Layer 4 Auto</td>
          <td>高</td>
          <td>最大</td>
          <td>中至大(看摘要品質)</td>
      </tr>
  </tbody>
</table>
<p><strong>從成本最低的開始試,能釋放多少算多少;前面的不夠用,才動用更貴的手段</strong>。</p>
<p>這就是這套系統背後的思路:<strong>對我而言,把 context 當成需要主動管理的資源,比交給運氣靈光來得安心一些</strong>。</p>
<hr>
<h2 id="1m-不是萬靈丹你該知道的真相">1M 不是萬靈丹:你該知道的真相</h2>
<p>看到這裡你可能想:「那我只要用 1M 模型,這四層壓縮我幾乎不用管了?」</p>
<p>技術上成立,但<strong>實務上要打一個大問號</strong>。</p>
<h3 id="模型的-recall-能力會隨-context-膨脹衰減">模型的 recall 能力會隨 context 膨脹衰減</h3>
<p>window 變大 ≠ 模型能好好使用全部空間。</p>
<p>Anthropic 公佈的 MRCR(multi-needle retrieval)測試結果:</p>
<table>
  <thead>
      <tr>
          <th>模型</th>
          <th>256K 時的 recall</th>
          <th>1M 時的 recall</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Opus 4.6 / 4.7</td>
          <td>93%</td>
          <td>~76–78%</td>
      </tr>
      <tr>
          <td>Sonnet 4.5(舊款)</td>
          <td>—</td>
          <td>18.5%(不建議用)</td>
      </tr>
      <tr>
          <td>Sonnet 4.6</td>
          <td>未公佈</td>
          <td>未公佈</td>
      </tr>
  </tbody>
</table>
<p>白話翻譯:<strong>你塞越多 context 進去,模型忘記東西的機率越高</strong>。即使技術上 window 能裝,模型的注意力會被稀釋。</p>
<h3 id="實務上多數-session-根本用不到-1m">實務上多數 session 根本用不到 1M</h3>
<p>根據社群的實測觀察,大多數 Claude Code session 峰值落在 <strong>80K–120K tokens</strong>。真正需要用到 500K 以上的場景不多,通常是:</p>
<ul>
<li>跨多個大型 codebase 的全域重構</li>
<li>一次讀入幾十份長篇文件做綜合分析</li>
<li>超長時間的自主 agent 任務(連續跑幾小時)</li>
</ul>
<p>日常維運、除錯、寫規格這類工作,200K 都綽綽有餘。</p>
<h3 id="1m-模型最實際的價值降低-compact-頻率不是撐更久">1M 模型最實際的價值:降低 compact 頻率,不是撐更久</h3>
<p>比較合理的用法不是「把 1M 塞滿」,而是:</p>
<ul>
<li>在 80K–150K 的正常使用範圍內,<strong>讓你不用頻繁擔心壓縮觸發</strong></li>
<li>遇到偶發的大型任務,<strong>不用馬上切 session 或 <code>/compact</code></strong></li>
<li>多一點彈性去讀幾個額外的參考檔案</li>
</ul>
<p>換句話說,1M 是把「context 緊張」這件事推到後景,而不是讓你可以永遠不管它。</p>
<h3 id="如果你在用-pro-方案">如果你在用 Pro 方案</h3>
<p>Max / Team / Enterprise 方案是<strong>自動啟用</strong> 1M。Pro 方案需要手動執行 <code>/extra-usage</code> 才會開啟 —— 這是 Anthropic 有意識的設計,讓付費層級自然區分。</p>
<p>如果你在 Pro 而沒跑過 <code>/extra-usage</code>,你現在用的是 200K,不是 1M。可以用 <code>/context</code> 確認當下狀態。</p>
<h3 id="環境變數可以強制關閉">環境變數可以強制關閉</h3>
<p>少數場景你可能想<strong>強制只用 200K</strong>(例如為了控制成本、或在舊模型間切換時保持一致),可以設:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">CLAUDE_CODE_DISABLE_1M_CONTEXT</span><span class="o">=</span><span class="m">1</span>
</span></span></code></pre></div><p>設了之後,model picker 不會出現 1M 選項。適合團隊統一環境配置時使用。</p>
<hr>
<h2 id="使用者能做什麼主動-vs-被動">使用者能做什麼:主動 vs 被動</h2>
<p>理論講完,來講實務。作為使用者,你不用去控制這四層(它們自動運作),但你<strong>有主動權</strong>在幾個關鍵時刻可以介入。</p>
<h3 id="時機一子任務結束時主動-compact">時機一:子任務結束時,主動 <code>/compact</code></h3>
<p>很多人以為 <code>/compact</code> 只在 context 快滿時才要用。這是我自己一開始也誤解的地方。</p>
<p>更聰明的用法是:<strong>每次完成一個子任務後,主動執行 <code>/compact</code></strong>。</p>
<p>為什麼?因為自動觸發永遠是被動的 —— 要等到真的快滿了才動。而你完成一個子任務時,你最知道:</p>
<ul>
<li>哪些前面的細節可以丟(「已經完成,結果正常」)</li>
<li>哪些需要保留(「這個決策後面還要用」)</li>
<li>下一個子任務需要什麼 context 基礎</li>
</ul>
<p>這時候主動 <code>/compact</code> 並帶上 custom instruction,可能會比自動摘要更貼近你的需求。</p>
<p>範例:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">/compact 重點保留:檔案修改清單、錯誤修正紀錄、未完成的 TODO。
</span></span><span class="line"><span class="cl">可以丟掉:一般探索性的 bash 輸出、已經確認正確的讀檔結果。
</span></span></code></pre></div><h3 id="時機二切-session不要依賴壓縮">時機二:切 session,不要依賴壓縮</h3>
<p>壓縮再強,也比不上「<strong>開新 session</strong>」乾淨。</p>
<p>當你要換一個完全不同的任務(例如從「debug production」切到「寫下週的週報」),最好的做法不是在同一個 session 裡繼續,而是:</p>
<ol>
<li>把當前進度寫進一個檔案(例如 <code>PROJECT_STATUS.md</code>)</li>
<li>結束當前 session</li>
<li>開新的,從頭讀那個檔案作為起點</li>
</ol>
<p>這比指望四層壓縮都要來得乾淨一些。</p>
<h3 id="時機三知道何時該停">時機三:知道何時該停</h3>
<p>有一個啟示來自前面的 3 次失敗 circuit breaker:<strong>如果 Claude Code 開始頻繁觸發 Auto Compact,那是警訊</strong>。</p>
<p>頻繁觸發代表你的任務規模已經超過 session 能舒服處理的範圍。這時候該做的不是「讓它繼續撐」,而是:</p>
<ul>
<li>切分任務(拆成幾個小任務分 session 做)</li>
<li>檢查你的 CLAUDE.md 是不是寫得太長</li>
<li>檢查你是不是讀了一堆其實不需要的檔案進來</li>
</ul>
<p>長 session 的壓力累積是真實存在的。管理 context 的最好方法,是<strong>從一開始就不要讓它膨脹</strong>。</p>
<hr>
<h2 id="幾個容易踩的雷">幾個容易踩的雷</h2>
<h3 id="雷一以為-compact-是魔法按鈕">雷一:以為 <code>/compact</code> 是魔法按鈕</h3>
<p><code>/compact</code> 會丟資訊。即使你寫了 custom instruction,摘要還是會漏細節。該備份的關鍵結論,請寫進檔案。</p>
<h3 id="雷二在重要決策前觸發壓縮">雷二:在重要決策前觸發壓縮</h3>
<p>如果 Claude Code 正在做一個關鍵判斷(例如「要刪哪些檔案」),不要在這時候手動 <code>/compact</code> —— 它可能把剛才的分析摘掉了,決策品質會受影響。等決策完成再壓縮。</p>
<h3 id="雷三盲目追求context-撐越久越好">雷三:盲目追求「context 撐越久越好」</h3>
<p>有些人把「能不能不用壓縮撐完一個 8 小時 session」當成成就。這是誤解。<strong>能把任務切成小塊分段做,每段乾淨結束,才是更好的工程實踐</strong>。</p>
<hr>
<h2 id="一個我自己偏好的心態">一個我自己偏好的心態</h2>
<p>四層壓縮聽起來很複雜,但它主要提醒一個觀念:</p>
<blockquote>
<p><strong>Context 是工程資源,不是取之不盡的倉庫</strong>。</p>
</blockquote>
<p>你用任何工具時都有資源觀念 —— 記憶體、磁碟、網路頻寬都有上限。AI 助理的 context 也一樣,只是它太新,大家還沒建立習慣。</p>
<p>有這個觀念之後,我自己覺得一些選擇變得比較自然:</p>
<ul>
<li>不會寫 10 頁的 CLAUDE.md</li>
<li>不會把整個 codebase 丟進對話</li>
<li>會主動切 session</li>
<li>會在關鍵時刻 <code>/compact</code></li>
<li>會把結論寫進檔案,而不是記在對話裡</li>
</ul>
<p>這些習慣累積起來,我覺得是「比較熟練使用 Claude Code」跟「一直踩雷」之間一個比較明顯的分野。</p>
<hr>
<h2 id="下一篇預告">下一篇預告</h2>
<p>接下來第 4 篇要談另一個常被混淆的主題:<strong>Sub-agent 與 Agent Team</strong>。</p>
<p>這兩個概念一直被工程師當成同一件事,實際上它們解決的是完全不同的問題 —— 一個是「怎麼讓 AI 跑得更快」,另一個是「怎麼讓 AI 聽話、有紀律」。</p>
<p>下一篇我們釐清這個誤會,並示範它們怎麼搭配使用。</p>
<hr>
<h2 id="本篇重點整理">本篇重點整理</h2>
<ul>
<li>Claude Code 的 context 管理不是黑盒,是<strong>一套四層的壓縮管線</strong>,從便宜到昂貴依序嘗試</li>
<li><strong>Pre-pipeline</strong>:處理過大的 tool result,防止污染整個管線</li>
<li><strong>Layer 1 Snip</strong>:零成本修剪,刪掉明顯可丟的舊片段</li>
<li><strong>Layer 2 Micro</strong>:以 tool_use_id 為單位壓縮 tool result,保留外殼丟掉內容</li>
<li><strong>Layer 3 Collapse</strong>:投射式壓縮,建立 view 而不修改底層 —— 最巧妙的一層</li>
<li><strong>Layer 4 Auto Compact</strong>:最貴的手段,用一次 API call 換大量空間;閾值約 window 的 83.5%(200K)或 96.7%(1M)</li>
<li><strong>Session Memory</strong>:Layer 4 會先試的輕量版,不呼叫 API 就能做修剪</li>
<li><strong>1M 不是萬靈丹</strong>:window 變大但模型 recall 能力會衰減,實務多數 session 根本用不到 1M</li>
<li><strong>主動介入時機</strong>:子任務結束時 <code>/compact</code>、切 session 而不硬撐、知道何時該拆任務</li>
<li><strong>核心觀念</strong>:把 context 當工程資源管理,而不是賭運氣</li>
</ul>
<hr>
<p><em>本文作者:鄧景仁 (Scott Teng) | 資訊服務業 infra 工程師,專注於 Azure / Linux / 安全維運。如需討論可聯繫 <a href="mailto:st333117@gmail.com">st333117@gmail.com</a>。</em></p>
<p><em>本系列所有內容為個人學習與實務心得整理,不代表任職機構立場。本文對 Claude Code 內部機制的描述,基於社群對 Claude Code 的公開分析材料與筆者實務觀察,並非 Anthropic 官方文件。具體閾值與行為可能隨版本演進。</em></p>
<hr /><p style="font-size:0.9em;opacity:0.8;margin-top:2em;">本文原刊於 <a href="https://eeit.github.io/ai-devops-blog/posts/03-context-compression/" rel="canonical">https://eeit.github.io/ai-devops-blog/posts/03-context-compression/</a>，作者：鄧景仁 (Scott Teng)。<br />授權條款：<a href="https://creativecommons.org/licenses/by-nc/4.0/deed.zh_TW" rel="license">CC BY-NC 4.0</a> · 禁止商業使用；分享請署名並註明原文 URL。<br />商業授權請聯絡：st333117@gmail.com</p>]]></content:encoded>
    </item>
    <item>
      <title>Sub-agent 與 Agent Team:分身 vs 分工(上)—— Sub-agent 的真實樣貌</title>
      <link>https://eeit.github.io/ai-devops-blog/posts/04a-subagent-mechanism/</link>
      <pubDate>Wed, 15 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://eeit.github.io/ai-devops-blog/posts/04a-subagent-mechanism/</guid>
      <source url="https://eeit.github.io/ai-devops-blog/posts/04a-subagent-mechanism/">AI 輔助維運工程</source>
      <description>把 Sub-agent 這個容易被誤解的概念整理清楚。四種隔離模式、Fork 的 prompt cache 共享設計、遞迴防護、根據公開分析,Claude Code 每週 Explore agent spawn 規模可達數千萬等級卻仍然成本可控。這是技術篇,下篇會談 Agent Team 的治理意義。</description><content:encoded><![CDATA[<blockquote>
<p>本文為《AI 輔助維運工程:從 Claude Code 機制到企業落地》系列第 4 篇,分上下兩集。上集聚焦 Sub-agent 的技術機制,下集談 Agent Team 的分工設計與兩者的搭配。</p>
</blockquote>
<h2 id="兩個被混為一談的概念">兩個被混為一談的概念</h2>
<p>我在跟同事討論 Claude Code 的時候,常發現同一個場景被用兩種完全不同的方式描述。有人會說「我請 Claude 派了幾個 subagent 去平行跑搜尋」,另一個人會說「我用多個 agent 分工處理這個任務」。聽起來像同一件事,但這兩句話背後指的是<strong>兩個不同層級、解決不同問題的機制</strong>。把它們視為同義詞,是我自己一開始也踩過的盲點。</p>
<p>為了把這件事講清楚,這篇我只談 Sub-agent,下一篇才談 Agent Team。我自己摸索的觀察是:兩者雖然名字相近,但設計目的、壽命、使用情境、對 token 的影響都完全不同。上篇主要拆解 Sub-agent 作為 Claude Code 內部的執行機制,下篇處理 Agent Team——對我而言它比較不是技術問題,是工程治理問題。</p>
<h2 id="先從一個比喻開始">先從一個比喻開始</h2>
<p>想像你是一位主編,在寫一份重要的專題報告。這份報告需要你去查證五個不同來源的資料:翻三份期刊、比對兩份歷史檔案。你手上有五個實習生可以派遣,而你要盡快把報告完成。</p>
<p>你會怎麼做?最笨的方法是自己一個接一個去查,五件事做完再開始寫。聰明一點的做法是:把這五件查證任務<strong>同時</strong>交給五位實習生,你就在辦公室繼續思考結構,等他們陸續帶著結果回來。每位實習生只需要知道你交辦的那一件事的上下文,不需要理解整份報告的全貌。他們查完、回報、任務結束,這位實習生對你而言就「用完了」——下一份報告如果還要查證,會派遣新的實習生,不是同一個人。</p>
<p>這就是 Sub-agent 的運作本質。當 Claude Code 遇到一個可以切割的子任務,它會衍生出一個「分身」去處理這件事。分身的生命週期就只有這個任務——做完回報給主 agent,然後就消失。它不會被記住、不會累積經驗、也不會跟其他分身協調。它的存在目的只有一個:<strong>讓主 agent 能專注在整體決策,不被瑣碎的子任務細節吃掉注意力與 context</strong>。</p>
<p>理解這點之後,有一個重要觀念要先立:<strong>Sub-agent 是 Claude Code 給自己用的機制,不是給你用的</strong>。你不用親自去「指派」sub-agent,大多數時候 Claude Code 會判斷什麼時候派、派幾個、派去做什麼。你頂多是透過 prompt 暗示它「這件事可以平行查」,實際要不要開分身,是它決定的。</p>
<h2 id="你一直在用-sub-agent只是沒發現">你一直在用 Sub-agent,只是沒發現</h2>
<p>當你在 Claude Code 裡請它「幫我找出所有使用 deprecated API 的檔案」,你看起來只是提了一個問題。但如果你打開 verbose 模式觀察,會發現事情沒那麼簡單。Claude Code 很可能會先開一個名為 <code>Explore</code> 的分身,這個分身專門做唯讀搜尋,不會修改任何東西。它會用 <code>grep</code>、<code>glob</code> 這些工具快速掃過整個 codebase,把結果彙整成一份清單回傳。主 agent 拿到清單後,才開始做後續的分析或修改。</p>
<p>從你的角度看,這只是一次對話。實際上背後發生了「主 agent → 衍生 Explore 分身 → 分身執行 → 結果回傳 → 主 agent 繼續」這樣的流程。Explore 分身完成任務之後就消失了,它的對話歷史不會進入你的主 session。</p>
<p>這個機制對我來說很重要,因為它直接解決了前一篇講的 context 問題。如果 Claude Code 把搜尋過程的所有細節(每個 grep 的完整輸出、每次嘗試的正則表達式、失敗的路徑)都塞進主對話,你的 context window 在幾輪就會吃緊。有了 Explore 這類 sub-agent,主 session 只看到「我派了一個分身去搜尋,它回傳這份清單」,過程細節都留在分身的獨立 context 裡,分身結束就隨之消失。</p>
<p>Claude Code 內建幾種不同用途的 sub-agent。除了剛提到的 Explore(唯讀搜尋),還有 Plan(唯讀規劃)、General Purpose(通用子任務)、Verification(驗證,某些版本是 feature-gated 的)、以及少數比較冷門的 agent 如 Statusline Setup、Claude Code Guide。這些 agent 的行為邊界由 Claude Code 自己定義,你不會直接呼叫它們,但你可以透過 prompt 引導 Claude Code 使用對應的類型。例如你說「先探索 codebase 再決定怎麼改」,Claude Code 有很大機會會先派 Explore 出去。</p>
<h2 id="四種隔離模式sub-agent-的真正技術深度">四種隔離模式:Sub-agent 的真正技術深度</h2>
<p>上面講的是「為什麼要有 sub-agent」。接下來進入這篇文章最核心的部分——sub-agent 彼此之間、以及與主 agent 之間,到底是怎麼分工的?這就是「隔離模式」(isolation model)要回答的問題。</p>
<p>Claude Code 定義了四種隔離模式,每一種適合不同的場景。它們在四個維度上有差異:取消訊號的傳遞範圍、應用程式狀態的共用程度、權限提示是否顯示、以及 extended thinking 是否啟用。</p>
<p><strong>Sync 模式</strong>,可以理解為「貼身的分身」。主 agent 和 sub-agent 共用同一個 AbortController——也就是說,你按 Esc 取消主 agent,sub-agent 也會一起停下。應用程式狀態(例如當前檔案、正在開啟的面板)也是共用的,sub-agent 做的改變主 agent 看得到。這個模式下,如果 sub-agent 要執行一個需要確認的危險操作(例如 <code>rm -rf</code>),會正常彈出權限對話框等你批准。Extended thinking(模型的內部推理)是從父 agent 繼承的。</p>
<p>這個模式的典型場景是:主 agent 派一個分身去完成某個需要用戶注意的小任務,主 agent 本身也會等這個分身完成之後再繼續。主 agent 和 sub-agent 其實是同一個「工作流」,只是暫時切換角色。</p>
<p><strong>Async 模式</strong>和 Sync 剛好相反,可以理解為「背景執行的分身」。它有自己獨立的 AbortController——你按 Esc 取消主 agent,async sub-agent 還在背景跑自己的。應用程式狀態是隔離的(修改被當成 no-op,不會影響主環境)。這是一個關鍵設計:因為分身在背景跑,使用者可能正在忙其他事,<strong>這時候彈出權限對話框是極糟糕的體驗</strong>。所以 Async 模式預設 auto-deny,遇到需要權限的操作直接拒絕,分身帶著「這個動作做不到」的結果回傳。Extended thinking 也被停用,因為背景 agent 通常不需要深度推理,控制 output token 成本比較重要。</p>
<p>Async 模式的典型場景是:你讓 Claude Code 背景跑一個長時間的任務(例如掃描某個大型 codebase 找出所有 TODO 標記),你想繼續跟它對話其他事。這個背景分身默默完成工作,結束後把結果整合到主 session 裡。</p>
<p><strong>Fork 模式</strong>是四種裡面設計最精巧、也最有趣的一種,下面會用整整一節深入拆解。先簡單說它的特性:Fork 分身繼承父的<strong>完整對話歷史</strong>——不是片段,是整段——同時擁有獨立的 AbortController。應用程式狀態是共用的,但透過一個叫 <code>rootSetAppState</code> 的機制間接存取。權限提示會以「冒泡」(bubble up)方式往上通知父 agent。Extended thinking 繼承自父 agent。</p>
<p><strong>Worktree 模式</strong>是最實用也最安全的一種。它繼承了 Async 模式的許多特性——獨立的 AbortController、隔離的應用程式狀態、權限自動拒絕、thinking 停用——但多了一個關鍵特徵:<strong>分身在 git worktree 裡運作</strong>。Git worktree 允許你在同一個 repository 下開出多個獨立的工作目錄,每個目錄有自己的 branch、自己的 staging area、自己的檔案狀態。也就是說,Worktree 分身修改任何檔案都不會影響主工作目錄,分身結束後你可以選擇合併變更、丟棄、或審查後再決定。</p>
<p>這個模式的使用場景我自己覺得很實用:當你想讓 Claude Code 嘗試一個「可能成功、可能搞砸」的大型重構,但又不想冒險動到主工作目錄,Worktree 就是天然的沙箱。如果分身做得漂亮,你合併它的變更;做得糟糕,整個 worktree 刪掉,你的主工作目錄毫髮無傷。</p>
<p>為了讓你一眼看到四個模式的差異,這裡用一個對照表總結。這是我整篇文章唯一用表格的地方,因為這四個維度同時並列,純文字描述比較不容易讀:</p>
<table>
  <thead>
      <tr>
          <th>模式</th>
          <th>AbortController</th>
          <th>setAppState</th>
          <th>Permission</th>
          <th>Thinking</th>
          <th>典型用途</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Sync</td>
          <td>共享父的</td>
          <td>共享父的</td>
          <td>顯示對話框</td>
          <td>繼承父的</td>
          <td>貼身子任務</td>
      </tr>
      <tr>
          <td>Async</td>
          <td>獨立</td>
          <td>隔離 (no-op)</td>
          <td>Auto-deny</td>
          <td>停用</td>
          <td>背景任務</td>
      </tr>
      <tr>
          <td>Fork</td>
          <td>獨立</td>
          <td>共享(間接)</td>
          <td>Bubble up</td>
          <td>繼承父的</td>
          <td>平行探索</td>
      </tr>
      <tr>
          <td>Worktree</td>
          <td>獨立</td>
          <td>隔離</td>
          <td>Auto-deny</td>
          <td>停用</td>
          <td>沙箱實驗</td>
      </tr>
  </tbody>
</table>
<p>看完這張表,你可能會問一個關鍵問題:為什麼 Async 和 Worktree 模式要自動拒絕權限?這不是很不方便嗎?答案其實很務實:<strong>當 sub-agent 在背景或隔離環境運行時,彈出權限對話框會中斷使用者正在做的其他事</strong>。更重要的是,自動化場景(例如腳本化呼叫 Claude Code)根本沒有人在螢幕前按「同意」。如果分身隨便跳出對話框,整個自動化流程就卡死了。auto-deny 是一種「寧可做不到也不要打擾使用者」的選擇。</p>
<p>這個設計還有一個巧妙的補充:Async 和 Worktree 模式雖然預設 deny,但如果你有設定 PreToolUse hook(第 8 篇會詳細講),hook 可以在 deny 之前先介入,做自動化的檢查。只有當 hook 也沒辦法決定時,才真的拒絕。這讓 sub-agent 在隔離模式下,仍然有機會透過 hook 完成需要權限的操作——前提是你有寫這個 hook。</p>
<h2 id="深入-fork為什麼-byte-identical-這麼重要">深入 Fork:為什麼 byte-identical 這麼重要</h2>
<p>四種模式裡面,Fork 最值得深入。原因是它涉及了 LLM 時代才有的成本優化策略——<strong>Prompt Cache 共享</strong>。</p>
<p>要理解 Fork 的巧妙,我們必須先回顧一個事實:每次 Claude Code 呼叫 Anthropic 的 API,都是把整段對話歷史重新送一次。這個成本在長 session 裡非常可觀。Anthropic 提供了 Prompt Cache 機制:如果你在一段時間內用相同的前綴(prefix)發出多個請求,後面幾次的這個共同前綴可以<strong>以 cache 讀取</strong>,成本只有正常 input token 的一小部分。</p>
<p>這個機制的關鍵限制是:prefix 必須完全相同——<strong>逐 byte 相同</strong>。哪怕差一個空白字元、差一個標點符號、差一個 message 的順序,cache 就 miss,整個 prefix 都要重新付費。</p>
<p>現在回到 Fork 的設計。當主 agent 想要派出<strong>多個</strong>分身平行做不同的事情,每個分身都要帶著父的完整 context。最直觀的做法是:把父的對話歷史原封不動複製 N 份,每份後面接上給那個分身的特定指令。聽起來合理,但這會產生什麼問題?</p>
<p>假設主 agent 的對話歷史裡,剛好有一段還沒處理完的 tool call(例如模型說「我要去跑一個 Bash 指令」,但這個指令還沒執行)。如果把這段原封不動複製到每個分身,分身看到一個「懸空的 tool call」會困惑。所以要做一點改造——把這個 tool call 填一個 placeholder result,讓它「看起來像已經完成」。</p>
<p>問題來了:<strong>每個分身填的 placeholder 能不能一模一樣?</strong> 如果不一樣(例如分身 A 填「請稍候」、分身 B 填「處理中」),這兩個 request 的 prefix 就變得不同,cache 會分裂成兩個不同的條目,命中率掉到趨近於零。</p>
<p>Claude Code 的解決方式是:<strong>強制所有 Fork 分身使用完全相同的 placeholder 字串</strong>。具體來說,所有未解決的 tool call 都被填上同一個固定字串,例如 <code>Fork started — processing in background</code>。所有分身的 message 結構長得一模一樣:父的對話歷史完全保留、所有 tool_use 都被填上相同的 placeholder、然後最後才是「給這個分身的 directive text」——只有這最後一小段 directive 是每個分身不同的。</p>
<p>結果是什麼?<strong>所有 Fork 分身的 API request prefix 完全 byte-identical</strong>,只有最後那一小段 directive 不同。這意味著 cache 命中率可以達到最高,即使同時派出 10 個分身,你付的 cache 以外的成本只有那 10 份 directive text 的差異,而不是 10 份完整 context 的重複費用。</p>
<p>這個設計有多精妙?你可以這樣想:如果沒有 Fork 的 byte-identical 策略,Claude Code 的平行搜尋、平行探索功能可能會變得明顯變貴,貴到 Anthropic 可能不會預設啟用,使用者也會有成本焦慮。有了這個設計,平行操作的邊際成本降到微乎其微,所以 Claude Code 才能在使用者沒察覺的情況下,大量派出 Explore 分身去平行掃 codebase。</p>
<p>根據公開的逆向工程分析,Claude Code 全平台每週光是 Explore 類型的 agent spawn 次數就達到<strong>數千萬</strong>這個級別。這個數字是估算,來自 Anthropic 公開的原始碼註解,並非官方公告;但即使誤差在幾倍之內,這個規模下 cache 共享設計能讓成本可控,還是令我覺得印象深刻。</p>
<h2 id="遞迴防護避免分身無限繁殖">遞迴防護:避免分身無限繁殖</h2>
<p>Fork 的設計解了 cache 問題,但帶來一個新問題:<strong>如果 Fork 分身自己也有 Agent tool(允許它再 Fork 更多分身),會不會造成無限遞迴?</strong></p>
<p>答案在技術上是「可能」。主 agent Fork 一個子,子 Fork 一個孫,孫 Fork 一個曾孫……理論上可以無限展開。每一層都消耗 token,但不會產生什麼有意義的工作,這是明顯的災難。</p>
<p>Claude Code 的處理方式很務實:<strong>允許 Fork 分身擁有 Agent tool 的宣告(為了保持 tool definitions 的 byte-identical),但在呼叫時攔截</strong>。具體做法是,每個 Fork 分身的 message 歷史裡會帶一個特殊標記(可以想成一個隱形的 tag,例如 <code>&lt;fork-boilerplate&gt;</code>)。當任何 agent 要 Fork 時,先檢查自己的 context 裡有沒有這個標記。有的話,就拒絕這次 Fork 請求。這樣一來,只有「根」層的主 agent 能 Fork,所有分身都是一代而已。</p>
<p>搭配這個防護,Fork 分身的系統 prompt 還會加入一段非常強硬的行為規範:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">你就是那個 Fork 分身。你的任務是完成主 agent 交辦的特定 directive。
</span></span><span class="line"><span class="cl">你不被允許做以下事情:
</span></span><span class="line"><span class="cl">- 再次 Fork(你就是那個 Fork)
</span></span><span class="line"><span class="cl">- 跟主 agent 閒聊或提問
</span></span><span class="line"><span class="cl">- 建議下一步該做什麼
</span></span><span class="line"><span class="cl">- 延伸討論不相干的事
</span></span><span class="line"><span class="cl">你必須直接使用工具完成任務,並以以下格式回報:
</span></span><span class="line"><span class="cl">  Scope: 你做了什麼範圍的工作
</span></span><span class="line"><span class="cl">  Result: 結果
</span></span><span class="line"><span class="cl">  Key files: 有用到的重要檔案
</span></span><span class="line"><span class="cl">  Files changed: 修改過的檔案清單
</span></span><span class="line"><span class="cl">  Issues: 遇到的問題(如果有)
</span></span></code></pre></div><p>這段 prompt 的精神是:<strong>分身就是分身,它不該演變成主 agent 的替代品</strong>。它做完交辦的事,按格式回報,就結束。這個設計讓 Fork 在工程上可控,不會因為模型「自作聰明」而失控。</p>
<h2 id="sub-agent-對-token-的實際影響">Sub-agent 對 Token 的實際影響</h2>
<p>聊了這麼多技術細節,我們回到一個更實際的問題:sub-agent 的存在,對使用者的 token 消耗到底是好事還是壞事?</p>
<p>直覺上會覺得:開這麼多分身,每個分身都有自己的 API call,token 一定會暴增吧?這個直覺在「如果沒有任何優化」的情況下是對的。但我們已經看到 Claude Code 做了至少三種重要優化來降低這個成本。</p>
<p>第一種優化,<strong>Prompt Cache 共享</strong>——Fork 模式下,多個分身共用大部分 prefix,只有 directive 不同,cache 命中率極高。</p>
<p>第二種優化,<strong>Context 裁剪</strong>。Explore 和 Plan 這類唯讀 agent,有一些父 agent 會載入、但分身根本用不到的內容會被主動省略。舉例來說,父 agent 載入的 <code>CLAUDE.md</code>(專案規則)對搜尋任務其實沒幫助,Explore 分身可以直接不帶它。原始碼的註解提到,光是這個省略,按 fleet-wide 規模估算就省下 5 到 15 Giga-tokens 的週消耗。這是 Anthropic 整個使用者群加總的數字,不是單一使用者,但它顯示這個優化的規模感。同樣的邏輯,Plan 和 Explore 可以省略 git status 資訊,那又是 1 到 3 Giga-tokens 的週省量。</p>
<p>第三種優化,<strong>Extended Thinking 預設停用</strong>。在 Async 和 Worktree 模式下,分身不做深度推理,只做被交辦的動作。這控制了 output token 的消耗——而 output token 比 input token 貴好幾倍。對於例行性、機械性的子任務,停用 thinking 是合理的成本控制。</p>
<p>這三種優化合起來的效果是:<strong>使用 sub-agent 的平均成本,往往比「把所有事情塞進主 session」更低</strong>。這違反了很多人的直覺,但背後的工程邏輯很清楚——隔離、共享 cache、裁剪無關內容、控制 output——每一項都在省錢。</p>
<p>這個事實意味著,作為使用者,你可以比較放心地讓 Claude Code 派 sub-agent。當它說「我先派個分身去搜尋一下」,不用覺得這是繞遠路。從 token 經濟學來看,這通常是比較省錢的路徑。</p>
<h2 id="你能控制什麼不能控制什麼">你能控制什麼,不能控制什麼</h2>
<p>最後回到使用者的角度:在這套 sub-agent 機制裡,你能做什麼?不能做什麼?</p>
<p><strong>你能做的第一件事是透過 prompt 引導 Claude Code 使用 sub-agent</strong>。如果你希望它先探索再修改,可以直接說「先全盤掃過 codebase 找出所有相關檔案,再開始改」,Claude Code 大機率會先派 Explore 出去。你不是在指揮某個特定的分身,而是在提示主 agent「這個場景適合用分身」。</p>
<p><strong>你能做的第二件事是善用 Worktree 模式</strong>。雖然你不能直接叫 Claude Code「用 Worktree 模式 fork 一個分身」,但你可以在對話中創造適合 Worktree 的情境。例如你說「我想嘗試一個實驗性的重構,但不要動到主工作目錄」,Claude Code 理解到「沙箱實驗」的需求,會傾向用 Worktree 機制。</p>
<p><strong>你能做的第三件事是觀察與學習</strong>。打開 verbose 模式,看 Claude Code 在你的對話裡實際派了哪些分身。久而久之你會建立一個心智模型:什麼樣的 prompt 會觸發什麼樣的 sub-agent 行為。這個 fingerprint 幫助你寫出更有效率的 prompt。</p>
<p><strong>你不能做的事是手動建立一個持久的 sub-agent</strong>。在這裡「持久」是關鍵字——sub-agent 的壽命就是完成一個任務。你不能說「幫我留一個 subagent 在那邊,專門負責監控日誌」,這不是 Claude Code 的 sub-agent 設計初衷。如果你的需求是「有一個固定的角色,長期負責某類工作」,那你需要的不是 sub-agent,而是下一篇要講的 <strong>Agent Team</strong>。</p>
<p>這是最後一個區分兩者的線索:<strong>sub-agent 是一次性的、任務結束就消失的;Agent Team 是長期存在、由你設計的角色</strong>。兩者的用途完全不同,也不是互斥的——實務上最好的做法是兩者疊加,下一篇會講到怎麼搭配。</p>
<h2 id="下一集預告">下一集預告</h2>
<p>這篇談了 Sub-agent 作為 Claude Code 內部執行機制的真實樣貌。四種隔離模式、Fork 的 cache 共享精巧設計、遞迴防護、token 經濟學——這些是工程層面的事實,不太會隨你的使用習慣改變。</p>
<p>下一集會進入一個完全不同的層次:<strong>Agent Team</strong>。它不是 Claude Code 的技術機制,而是一套關於「<strong>如何讓 AI 在複雜工作中保持紀律</strong>」的工程設計。你會看到它跟 Sub-agent 完全無關,解決的是完全不同的問題,用的也是完全不同的工具——不是 API call 和 cache,而是 Markdown 檔案、role definition、和 handoff protocol。</p>
<p>一個我覺得有趣的觀察是,下一集的內容是我在 POC 中花了不少時間摸索的題目,很大程度是因為它需要「從工程治理角度理解 AI」的視角。下一集會把這個視角一起建立起來。</p>
<h2 id="本篇重點">本篇重點</h2>
<p>讀完這篇,我希望三個觀察能留下來。</p>
<p>第一,<strong>Sub-agent 是 Claude Code 為了自己的 context 與 token 效率而設計的機制</strong>。它是引擎蓋下的機制,你不用直接操作,但理解它可能幫助你寫出更負擔得起的 prompt。</p>
<p>第二,<strong>四種隔離模式(Sync / Async / Fork / Worktree)各自對應不同場景</strong>。Sync 適合貼身協作、Async 適合背景任務、Fork 適合平行探索、Worktree 適合沙箱實驗。</p>
<p>第三,<strong>Fork 的 byte-identical prefix 設計是我覺得 LLM 時代比較有趣的一個工程設計</strong>。它讓大規模的 Prompt Cache 共享成為可能,這個優化是 Claude Code 能大量派 sub-agent 而仍然成本可控的關鍵原因之一。</p>
<p>如果你在看這篇之前,跟我一開始一樣,以為 sub-agent 就是「AI 的助手」或「一個固定的角色」,現在我們應該都同意這個印象可以更新一下。Sub-agent 是一個<strong>執行機制</strong>,不是<strong>角色</strong>。角色,是下一篇的主題。</p>
<hr>
<p><em>本文作者:鄧景仁 (Scott Teng) | 資訊服務業 infra 工程師,專注於 Azure / Linux / 安全維運。如需討論可聯繫 <a href="mailto:st333117@gmail.com">st333117@gmail.com</a>。</em></p>
<p><em>本系列所有內容為個人學習與實務心得整理,不代表任職機構立場。本文對 Claude Code 內部機制的描述,基於社群對 Claude Code 的公開分析材料與筆者實務觀察,並非 Anthropic 官方文件。具體行為可能隨版本演進。</em></p>
<hr /><p style="font-size:0.9em;opacity:0.8;margin-top:2em;">本文原刊於 <a href="https://eeit.github.io/ai-devops-blog/posts/04a-subagent-mechanism/" rel="canonical">https://eeit.github.io/ai-devops-blog/posts/04a-subagent-mechanism/</a>，作者：鄧景仁 (Scott Teng)。<br />授權條款：<a href="https://creativecommons.org/licenses/by-nc/4.0/deed.zh_TW" rel="license">CC BY-NC 4.0</a> · 禁止商業使用；分享請署名並註明原文 URL。<br />商業授權請聯絡：st333117@gmail.com</p>]]></content:encoded>
    </item>
    <item>
      <title>Token 成本的真相:從原理到節省策略</title>
      <link>https://eeit.github.io/ai-devops-blog/posts/05-token-economics/</link>
      <pubDate>Fri, 17 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://eeit.github.io/ai-devops-blog/posts/05-token-economics/</guid>
      <source url="https://eeit.github.io/ai-devops-blog/posts/05-token-economics/">AI 輔助維運工程</source>
      <description>這篇把 AI 輔助工作中比較容易被誤解、也最讓人焦慮的議題整理一下:token 消耗的實際運作方式。你不是在付「問問題的錢」,而是在付「每次都把整本對話歷史重新買一遍」的錢。理解這件事之後,省錢就從賭運氣變成可設計的工程問題。</description><content:encoded><![CDATA[<blockquote>
<p>本文為《AI 輔助維運工程:從 Claude Code 機制到企業落地》系列第 5 篇。系列前半部講機制(Claude Code 怎麼運作、Agent Loop 怎麼跑、Context 怎麼管理、Sub-agent 怎麼分工、Agent Team 怎麼治理),這一篇開始進入後半部——你站在使用者或主管的角度,要做哪些實際決策。第一個決策就是關於錢。</p>
</blockquote>
<h2 id="當帳單比你預期的高出五倍">當帳單比你預期的高出五倍</h2>
<p>我想先請你想像一個場景。</p>
<p>一位工程師最近迷上 Claude Code。他每天早上打開,下午處理幾個 ticket,晚上偶爾還會用它整理週報。感覺很滿意,生產力明顯提升。月初收到 API 帳單的時候,他愣了一下——比他預期的高出大約五倍。</p>
<p>他不相信。回頭去看使用紀錄,確認沒有異常的大量呼叫、沒有惡意濫用、也沒有帳號被盜用的跡象。每天該做的事他都記得,那些事情理論上不該產生這麼多 token 消耗。但帳單就是擺在那裡。</p>
<p>這個情境是很多 Claude Code 新使用者的共同經驗。如果你也遇過、或擔心自己會遇到、或身為主管在審視團隊 AI 採購預算時心裡有這種疑慮——這篇文章就是為你寫的。</p>
<p>我會先花點時間建立「token 經濟學」的基礎觀念,然後解釋為什麼你以為自己理解的成本模型,其實跟實際發生的事情有出入。再來談 Prompt Cache 這個我自己一開始也忽略的助手、Claude Code 暗中在幫你省錢的各種設計、以及你自己能主動做的節省策略。讀完之後,我希望你能對著帳單,比較容易指出每一塊錢花在哪、哪些可以減少、哪些不能省。</p>
<h2 id="先回到最基本token-是什麼為什麼按這個計費">先回到最基本:Token 是什麼,為什麼按這個計費</h2>
<p>很多人聽過 token 這個詞,但沒真的弄清楚它是什麼。這裡花一點時間講清楚,因為後面所有的計算都建立在這個基礎上。</p>
<p>Token 是大語言模型用來處理文字的基本單位。你可以把它想成「字」,但不完全等於中文的一個字、也不完全等於英文的一個單字。實際上它比較像<strong>字元片段</strong>——一個常見的英文單字(例如 &ldquo;the&rdquo;)是一個 token,一個較長的單字可能被拆成兩三個 token,中文的一個字大約是一到兩個 token。</p>
<p>給你一個粗略的換算:<strong>一個中文字大約是 1 到 2 個 token,一個英文單字平均是 0.75 個 token</strong>。一頁 A4 中文文件大約包含 2000 到 3000 個 token。一篇 3000 字的文章大約是 4000 到 6000 個 token。這樣你看到「一百萬 tokens」的時候,大概能感覺出那是什麼規模——<strong>相當於一本中等厚度的書</strong>。</p>
<p>那為什麼 Anthropic 按 token 計費,不按「問幾個問題」或「用多少分鐘」計費?答案很實務:<strong>token 是模型內部處理工作的真實計量單位</strong>。不論你用什麼問題、花多少時間,模型做的事情本質上就是處理一串 token、產生另一串 token。按 token 計費是最公平、最接近成本真相的方式。</p>
<p>這裡有一個地方很多人沒注意:<strong>input token 和 output token 價格不一樣</strong>,output 通常比 input 貴好幾倍。以 Claude Sonnet 4.6 為例(這是寫這篇時 2026 年第二季的公開定價,請以 Anthropic 官網最新資訊為準),input 大約是每百萬 token 三美元,output 大約是每百萬 token 十五美元——<strong>差了五倍</strong>。為什麼?因為 output 的生成過程比讀取 input 更耗運算資源,模型要一個 token 一個 token 地「決定」輸出什麼,這比「理解」輸入要費力。</p>
<p>意識到 input 和 output 的價差之後,你對某些現象會有不一樣的解讀。例如「讓模型寫一大段詳細回答」這件事,其實比「讓模型讀一大段詳細資料後簡短回答」貴得多。寫長比讀長貴,這是一個直覺上不明顯、但帳單上很明顯的事實。</p>
<h2 id="打破一個容易踩到的誤解你不是在用多少回多少錢">打破一個容易踩到的誤解:你不是在「用多少回多少錢」</h2>
<p>OK,基礎打好了。現在講這篇最重要的一個觀念。</p>
<p>大多數人對 AI 計費的直覺是:我問一個問題、AI 回答我、這次花了某個 token 量。下次再問,又是一個新的計算。就像你打電話問客服,通話時間內收費,掛了電話就停。</p>
<p><strong>這個直覺跟實際狀況不一樣</strong>。</p>
<p>實際的計費模型是這樣:每一次你按下 Enter,送到 Anthropic 的不只是你這次打的這句話,而是<strong>整段對話從第一句到現在的所有內容</strong>。系統 prompt、你之前問過的所有問題、AI 之前給過的所有回答、中間所有工具呼叫的結果——全部打包一起送。這些全部都算 input token,全部都要付費。</p>
<p>讓我重新說一次,因為這是理解 token 成本的關鍵樞紐:<strong>你不是在為「最近這一句」付費,你是在為「整段對話歷史」付費,而且每一輪都要重新付一次</strong>。</p>
<p>你可能會問:為什麼要這樣?模型不能記得我們之前聊過什麼嗎?答案是——不能。模型本身沒有記憶。每次 API 呼叫都是獨立的,模型看到什麼、就知道什麼。如果要讓它「記得」之前的對話,唯一的方法就是把之前的對話<strong>再送一次</strong>給它看。這是 LLM 運作的本質,不是 Anthropic 的設計選擇。</p>
<p>有了這個認知,你回頭看很多之前不理解的現象,突然都通了。</p>
<p>為什麼長 session 越跑越貴?因為每一輪要傳的對話歷史越來越長。前 5 輪對話可能只有 2000 token,跑到第 50 輪可能已經 30000 token,每一次新對話都要把這 30000 token 重送一次。這不是線性增長,是<strong>累積放大</strong>。</p>
<p>為什麼讀了一個 500 行的 log 檔之後,接下來每一輪都感覺變貴?因為那 500 行已經進入 context,變成對話歷史的一部分,每一次都要重傳。</p>
<p>為什麼清掉 context 或 /compact 之後會明顯感覺「變快變便宜」?因為你釋放了重傳的負擔,後面每一輪都少付那些釋放掉的 token。</p>
<p><strong>這就是為什麼那位月底看到五倍帳單的工程師,沒找到任何「異常」的呼叫</strong>。他的使用沒問題,但他累積了幾個超長 session,每個 session 都把大量歷史重複傳了幾十次。五倍的帳單沒有兇手,有的只是一個被誤解的成本模型。</p>
<h2 id="你的好朋友prompt-cache">你的好朋友:Prompt Cache</h2>
<p>講完壞消息,講個好消息。Anthropic 知道「每輪都重傳整段歷史」這件事很貴,所以他們提供了一個機制叫 <strong>Prompt Cache</strong>,本質上就是讓你<strong>不用每次都全額付費</strong>。</p>
<p>我用一個比喻讓你抓住這個機制的精神。</p>
<p>想像你是一家餐廳的熟客。你每次來都會點「招牌前菜套餐」這個東西——同樣的內容、同樣的作法、同樣的份量。廚師每次都要從頭備料、煎烤、擺盤、送上桌。成本很高。某天餐廳老闆跟你說:「這樣吧,你既然每次都點這個,我們幫你做個<strong>預備制度</strong>——你多付一點錢,我們會把你常點的內容預先準備好,放在保溫區,你下次來直接取,只要付一小部分錢。」</p>
<p>這個「預備制度」就是 Prompt Cache。</p>
<p>具體怎麼運作?當 Anthropic 看到你在一段時間內反覆用<strong>完全相同的前綴</strong>發起對話,它會把這個前綴「暫存」起來。下次你再用同一個前綴,Anthropic 不需要重新處理這段內容,而是從暫存直接讀取。<strong>你付的不是一般的 input 價格,而是 cache read 的價格,大約是一般 input 的十分之一</strong>。</p>
<p>十分之一的意思是:如果你的對話歷史已經累積到 30000 token,一般來說這一輪要付 30000 個 input token 的費用。但如果前 29000 個 token 能命中 cache,你只要付 29000 個 cache read token + 1000 個一般 input token。整體費用大約省 85% 以上。</p>
<p>這個機制對 Claude Code 這種「每輪都會重傳一堆歷史」的使用模式,幫助非常大。事實上,<strong>Claude Code 裡面不少工程設計都考慮了怎麼讓 cache 命中率最大化</strong>。</p>
<p>還記得第四篇上集講的 Fork sub-agent 機制嗎?那段「為什麼所有分身的 API request prefix 要 byte-identical」的長篇大論,從省 token 的角度重新看,意思就是:<strong>讓所有分身共用同一份 cache</strong>。十個分身平行跑,如果每個分身都要重新付一次 context 的錢,成本會爆炸。但因為 prefix 一致,後九個分身只要付 cache read 價格。這不只是技術漂亮,這是實實在在省下來的錢。</p>
<p>Prompt Cache 有一個重要但不直觀的限制:<strong>快取會過期</strong>。如果你在一段時間(通常是五分鐘)內沒有新的請求觸及這個 cache,它會被清掉。下次再用就要重新建立。這意味著如果你經常「開 Claude Code 問一個問題、關掉、過十分鐘再來」,你的 cache 命中率會很低。但如果你是連續密集使用,cache 幾乎一直維持在命中狀態,帳單會漂亮很多。</p>
<p>作為使用者,你基本上不用手動設定 cache,Claude Code 會自動幫你管理。你要做的只是<strong>理解 cache 存在、相信它在工作、不要做破壞它的事</strong>。</p>
<h2 id="那什麼事會破壞-cache">那什麼事會破壞 cache?</h2>
<p>這個問題值得一段獨立的討論,因為<strong>了解這個,你才知道為什麼有些操作看起來沒什麼、但對你的錢包很不友善</strong>。</p>
<p>Cache 的命中條件是「前綴完全 byte-identical」。這個「完全一致」非常嚴格——差一個空白字元、差一個標點符號、差一個 message 順序,cache 就 miss,整個前綴要重新付費。</p>
<p>以下這些行為會讓 cache miss,請小心:</p>
<p><strong>修改 CLAUDE.md 或 @import 的檔案</strong>。這些內容會被當成對話的一部分放進 context 前端。你改了一行文字,整個前綴就變了,所有之前累積的 cache 失效。這不代表你不該修改 CLAUDE.md,但它意味著「每次修改都會付一次 cache 重建的錢」——如果你發現自己一天改 CLAUDE.md 十幾次,這個習慣該改了。</p>
<p><strong>切換不同的 MCP servers</strong>。MCP servers 的 tool description 會進入 system prompt。你切換啟用的 MCP 組合,system prompt 就變了,cache 失效。這是為什麼建議「一個專案穩定使用一組 MCP,不要頻繁切換」。</p>
<p><strong>修改模型設定</strong>。如果你用 <code>/model</code> 切換 Claude 模型,前後兩個模型看到的 prompt 結構可能不同,cache 也可能失效。這不是經常會做的事,但知道有這個成本就好。</p>
<p>反過來,以下事情<strong>不會</strong>破壞 cache:</p>
<p>你問新的問題——這只是在對話末端追加內容,前端沒變,cache 仍然命中。</p>
<p>工具呼叫並拿回結果——這也是在末端追加,前端維持,cache 仍然工作。</p>
<p>Claude Code 做自動 context 壓縮(snip compact、micro compact 等)——這些壓縮會重寫某些訊息,理論上會影響 cache,但 Claude Code 設計時會盡量減少 cache miss。在某些情況下,壓縮的確會造成 cache 失效,但這個「失效的痛」通常遠小於「不壓縮讓 context 繼續膨脹」的痛。</p>
<p>這裡有一個微妙的、但值得你內化的心態:<strong>不要為了保護 cache 而不做對的事</strong>。壓縮會讓 cache miss、但可能救你下半天的 session;重寫 CLAUDE.md 會讓 cache miss、但可能讓未來一百次互動都更精準。短期的 cache 失效常常換來長期的效率提升,不要因為「怕 miss」就綁手綁腳。</p>
<h2 id="claude-code-暗中在幫你省的其他錢">Claude Code 暗中在幫你省的其他錢</h2>
<p>除了 Prompt Cache 這個機制之外,Claude Code 還做了許多你可能沒察覺的、自動化的省錢設計。這些設計合起來,讓整個工具比你想像的精打細算。</p>
<p><strong>Sub-agent 省略無關資料</strong>。第四篇上集提過 Explore 這類唯讀搜尋 agent,它們在執行時會自動省略 CLAUDE.md、省略 git status 等主 agent 本來會載入的內容。從使用者的角度這是「分身看不到某些資訊」,從成本角度這是「你不用為分身用不到的資訊付錢」。當 Claude Code 派出一百個 Explore 分身做平行搜尋,每個分身都省掉了這些多餘的輸入,整體省下的 token 量是驚人的。</p>
<p><strong>Tool result 的自動截斷</strong>。當某個工具產生非常大的輸出(例如讀了一個 80MB 的 log 檔),Claude Code 會自動判斷並截斷,只把摘要放進 context、原始內容寫到磁碟。這個機制防止「一個 tool call 就把你的 context 炸掉」,同時也保護你的錢包——如果 80MB 內容全進 context,之後每一輪都要重傳。</p>
<p><strong>四層 context 壓縮管線</strong>。第三篇整篇講的那套壓縮系統,從省錢角度重看就是「在對話歷史無限膨脹之前,不斷裁剪」。每裁剪 10000 token,之後每輪省 10000 token 的重傳費。這些小錢累積起來很可觀。</p>
<p><strong>Output thinking 的條件啟用</strong>。Claude 的某些模型有 extended thinking 能力,會在回答前做內部推理。這個推理是 output token,<strong>而 output token 是 input token 的五倍貴</strong>。Claude Code 在某些 sub-agent 模式下預設關閉 thinking,就是在控制這個高成本項目。你不需要每個搜尋任務都伴隨 10000 token 的深度思考——適合思考的時候啟用,不適合的時候就關掉。</p>
<p>這些設計合起來的效果是什麼?<strong>Claude Code 本身就是一個內建了成本意識的系統</strong>。它不需要你手動優化每一件事情,很多優化在你不察覺的情況下就發生了。你的任務不是當微觀管理者,而是了解這些機制存在,然後<strong>不做違背這些機制精神的事</strong>。</p>
<h2 id="你能做的三層節省策略">你能做的:三層節省策略</h2>
<p>儘管 Claude Code 已經幫你做了很多自動優化,你仍然有主動能做的事。這些事分成三個層次,影響力由淺到深。</p>
<h3 id="第一層設定層">第一層:設定層</h3>
<p>這一層是你做一次、受益長期的事情。</p>
<p><strong>精簡你的 CLAUDE.md</strong>。這是我覺得比較容易見效的一件事。有些工程師把 CLAUDE.md 寫成十幾頁的長篇大論——什麼團隊規範、專案歷史、程式碼風格、所有可能的邊界條件、過去踩過的雷——全部塞進去。這會造成一個問題:<strong>你每一輪對話,都在付這十幾頁文字的 input token 費用</strong>。</p>
<p>想像你用這個專案一天跑五十輪對話,每輪都要重傳這十幾頁。一年下來這個「常駐稅」會是驚人的數字。解決方法是:<strong>CLAUDE.md 只寫真正每次對話都需要的核心規則</strong>,其他詳細資料放在另一個檔案,當需要時才用 @import 載入。這樣平時不需要用那些細節,就不付費;需要時才付一次。</p>
<p>這個優化以我自己的經驗,往往能讓單輪成本明顯下降。是我覺得比較容易先試的事。</p>
<p><strong>選擇性啟用 MCP servers</strong>。每個啟用的 MCP server 都會把它的 tool descriptions 放進 system prompt。如果你一次啟用十個 MCP servers,而這個專案其實只用到其中兩個,你在為八個沒用到的 server 付常駐稅。</p>
<p>處理方式是:<strong>每個專案只啟用這個專案真正會用到的 MCP servers</strong>。不同專案有不同的 MCP 組合沒關係,但每個專案的 MCP 集合要精準,不要貪心。</p>
<p><strong>@import 要節制使用</strong>。@import 機制很方便——你可以讓 CLAUDE.md 引用其他檔案的內容,讓模型看到完整資料。但每次 @import 的檔案內容都會變成對話的一部分,每輪都重傳。用 @import 前問自己:「這個內容真的每次對話都需要嗎?」如果答案是「只有某些時候需要」,那就不該用 @import,而是在那些特定時候手動載入。</p>
<h3 id="第二層使用層">第二層:使用層</h3>
<p>這一層是你在每個 session 中、每天都可以做的決定。</p>
<p><strong>主動 /compact,不要等自動觸發</strong>。第三篇我們談過這點,這裡從省錢角度再看一次。自動壓縮在 context 用到 83.5% 左右才觸發,<strong>意思是前 83.5% 的膨脹成本你已經付完了</strong>。如果你在完成一個子任務後主動 /compact,你可能在 30% 或 40% 就清掉多餘內容,省下 50% 以上的後續重傳費用。</p>
<p>主動壓縮是這個系列反覆強調的好習慣,從成本角度看,它直接翻譯成金錢。</p>
<p><strong>切 session 而不硬撐</strong>。長 session 有一個「cumulative cost」的效應——到越後面,每一輪都越貴。當你發現任務其實已經換軌(例如從 debug 某個問題切到寫下週簡報),<strong>停下當前 session、開新的更便宜</strong>。不要想「我還有 context 可以用,多撐一下」,那個 context 每用一輪都在吸你的錢。</p>
<p><strong>善用唯讀 sub-agent</strong>。當你讓 Claude Code 做「探索性」任務(搜尋、盤點、比對),明確引導它先派 Explore 分身。因為 Explore 省略了很多主 agent 的常駐內容,平行執行還共用 cache,整體成本遠低於主 agent 親自處理每一件事。你可以直接說「先派探索分身掃一遍」或「平行查一下這幾個」,Claude Code 會懂。</p>
<h3 id="第三層架構層">第三層:架構層</h3>
<p>這一層是最深的,影響最大,也需要你花時間設計。</p>
<p><strong>Agent Team 設計本身就是一種省錢</strong>。還記得第四篇下集講的角色分工嗎?從治理角度它的價值是紀律,從省錢角度它的價值是<strong>切割長 session</strong>。每次角色切換都是一個天然的 session 斷點——spec-writer 完成規格後,交接給 implementer,implementer 不需要繼承 spec-writer 的完整對話,只需要讀 PROJECT_STATUS.md 和 spec 檔案。這相當於強制的 context 重置,每個角色的 session 都保持輕量。</p>
<p>如果你用一個長 session 從規格寫到實作寫到審查,你的對話歷史到最後可能累積十萬 token。同樣的工作用三個角色接力做,每個角色的 session 可能只有兩萬 token,總計六萬,<strong>比單一長 session 省了四成</strong>。</p>
<p><strong>任務切割的邊界設計</strong>。每一個任務開始前,問一個問題:<strong>這個任務做完就能收尾,還是會自然延伸成其他任務?</strong> 如果是前者,這個任務就是一個 session 的好邊界——做完,結束,開新的。如果是後者,你要預先規劃中間的「checkpoint」,讓 session 可以在適當的地方切開。</p>
<p><strong>跨 session 的狀態檔案是真正的省錢架構</strong>。把關鍵狀態寫進 PROJECT_STATUS.md、session-log.md、或任何你設計的狀態檔案,意思是「這些資訊不需要存在我的對話歷史裡」。我可以結束這個 session、明天開新的、讀一下狀態檔就能無縫接軌。狀態檔案是永久的(不消耗對話 token),對話歷史是暫時的(每輪都重傳、越傳越貴)。<strong>把重要資訊從對話搬到檔案,就是在把「持續性的 token 負擔」轉成「一次性的讀取成本」</strong>。</p>
<h2 id="一個思考練習">一個思考練習</h2>
<p>我們停一下,做一個小練習,幫你內化到目前為止講的東西。</p>
<p>假設你今天要完成一個任務:用 Claude Code 盤點某個 codebase 裡所有使用了某個 deprecated API 的地方,然後逐一改掉,最後產出一份修改報告。這個任務你估計需要四小時。</p>
<p>請你花一分鐘,想一下:<strong>你會怎麼設計這個任務的進行方式,讓 token 成本最低?</strong></p>
<p>(實際想一下再往下看。)</p>
<p>好,以下是一個我覺得合理的設計方式,你可以跟你的想法對照。</p>
<p>我會把這個任務切成三個階段,每個階段開新的 session:</p>
<p>**第一階段(探索):**開一個新的 session,明確請 Claude Code 派出 Explore 分身平行搜尋整個 codebase,找出所有使用該 deprecated API 的地方,產出一份清單。這個清單寫進一個 markdown 檔案。Explore 分身省略 CLAUDE.md,本身成本就低;平行執行共用 cache,更低。整段第一階段完成後,把清單檔案存好,<strong>結束這個 session</strong>。</p>
<p>**第二階段(修改):**開一個新的 session,讓 Claude Code 讀那份清單檔案,一個一個檔案修改。這個 session 是「implementer 角色」的工作模式,專注實作、不做規格決策。每修改完幾個檔案,就做一次 /compact 清掉過時的 tool results,保持 session 輕量。修改完所有檔案後,結束。</p>
<p>**第三階段(審查與報告):**再開一個新的 session,這次是「reviewer 角色」。讀修改清單、抽樣檢查改動、產出修改報告。審查分身不需要繼承前兩個 session 的完整對話歷史,只需要看最終產出和檔案 diff。</p>
<p>這個設計的精髓是什麼?<strong>三個短 session 比一個長 session 省得多</strong>。每個 session 都有明確的起始 context、做完就結束,不讓對話歷史無限累積。中間透過 markdown 檔案(清單、報告)接棒,避免把資訊留在易腐的對話裡。</p>
<p>同樣的工作,設計得當可以省下五到七成的 token 成本。這不是魔法,是工程紀律。</p>
<h2 id="從看帳單到有-token-意識">從「看帳單」到「有 token 意識」</h2>
<p>講了這麼多,我希望你帶走的不是某個具體技巧,而是一種<strong>思考方式</strong>。</p>
<p>不少工程師在使用 AI 助理時,腦袋裡沒有 token 這個維度。他們想的是功能、是效率、是「能不能做到」。等月底帳單來了,才發現成本也是一個維度,而且是他們之前從來沒管理過的那種成本。</p>
<p>我自己偏好的使用方式,是讓「token 意識」成為背景思考的一部分。不是隨時在計算費用,而是當你在設計工作流、寫 CLAUDE.md、決定用哪個方案的時候,都自然會問一句:<strong>這個選擇對 token 消耗的影響是什麼?</strong></p>
<p>這個意識一旦建立,你可能會自然做一些對的事——你如果寫出簡短精準的 CLAUDE.md,是因為你知道冗長會讓每輪都貴;你切 session,是因為你知道長 session 有 cumulative cost;你把狀態寫進檔案,是因為你知道對話是會腐敗的容器;你讓 Claude Code 派 sub-agent,是因為你知道這可能比主 agent 親自做還便宜。</p>
<p>這些行為合起來,讓你在同樣的工作量下,成本可能被控制在沒有這些意識的使用者的一定比例之下。長期下來,這個差距可能決定一個團隊是不是能永續地用 AI 輔助工作流。</p>
<h2 id="最後一個問題那到底該付多少錢">最後一個問題:那,到底該付多少錢?</h2>
<p>到目前為止,我談的都是「已經選定某個方案之後,如何在這個方案內省錢」。但有一個更上層的問題沒回答:<strong>你應該選哪個方案?</strong></p>
<p>Anthropic 提供了四種不同的服務管道——個人 Pro、個人 MAX、團隊 Plan、Enterprise、API——每一種計費方式和權限差異都不同。選對方案本身就是最大的一次性節省,可能比後面所有的技術優化都更有影響。</p>
<p>更重要的是,方案的選擇還牽涉到一個很多人沒意識到的議題——<strong>你的對話資料會不會被用來訓練模型</strong>。不同方案在這件事上差異極大,而且個人版目前採用 opt-out 模式,意思是<strong>如果你沒去關掉那個設定,你的對話可能正在被拿去訓練</strong>。這個議題連同完整的方案選型比較,第 7 篇會專章處理。</p>
<p>但在那之前,還有一個更上游的問題必須先處理——<strong>你使用 Claude 不只一個入口</strong>。Claude Code、Claude.ai、API——同一個模型放在不同平台,在不同 SSDLC 階段擅長的事情不一樣。<strong>你在 SSDLC 的不同階段,該用哪個入口?</strong> 這不是方案選型,是流程對應工具的判斷。選對入口之後才談得上「選什麼方案」——各階段擅長的入口綜合起來,才是方案選型的主要輸入變數。</p>
<p>所以下一篇的主題就是:<strong>SSDLC 工具選擇——每個階段該用哪個 Claude 入口</strong>。接著第 7 篇再回到「方案選型」的問題。</p>
<h2 id="本篇收尾">本篇收尾</h2>
<p>把這篇的核心觀念,用一段話總結如下。</p>
<p>Token 成本的真相,是你每一輪對話都在為「整段對話歷史」重新付費,不是只為最後一句話付費。這個模型讓長 session 的 cumulative cost 成為費用變貴的主因。理解這件事之後,所有的節省策略——精簡 CLAUDE.md、主動 /compact、切 session 而不硬撐、善用 sub-agent、用 Agent Team 切割任務——都有了共同的底層邏輯:<strong>減少每輪要重傳的歷史、不讓歷史無限膨脹、讓持久性的資訊留在檔案而不是對話</strong>。</p>
<p>Prompt Cache 是一個值得了解的機制,它讓「重傳歷史」的成本降到大約十分之一。Claude Code 本身做了大量的自動省錢設計(Fork sub-agent 共用 cache、Explore 省略無關內容、tool result 截斷、context 壓縮),你不需要微觀管理這些,只要不做違背它們精神的事就好。</p>
<p>最後,如果能讓「token 意識」成為你設計工作流時的背景思考,你用 AI 的總成本長期下來可能會跟沒有這些意識的人拉開不小的差距。</p>
<p>下一篇我們從「在一個方案內省錢」跳到更上游——「在 SSDLC 的不同階段,該用哪個 Claude 入口」。方案選型的問題還要再等一集。</p>
<hr>
<p><em>本文作者:鄧景仁 (Scott Teng) | 資訊服務業 infra 工程師,專注於 Azure / Linux / 安全維運。如需討論可聯繫 <a href="mailto:st333117@gmail.com">st333117@gmail.com</a>。</em></p>
<p><em>本系列所有內容為個人學習與實務心得整理,不代表任職機構立場。文中引用的 API 定價為 2026 年第二季的公開資訊,Anthropic 保留隨時調整權利,實際費用請以 Anthropic 官方網站為準。具體 Prompt Cache 行為與其他實作細節可能隨版本演進。</em></p>
<hr /><p style="font-size:0.9em;opacity:0.8;margin-top:2em;">本文原刊於 <a href="https://eeit.github.io/ai-devops-blog/posts/05-token-economics/" rel="canonical">https://eeit.github.io/ai-devops-blog/posts/05-token-economics/</a>，作者：鄧景仁 (Scott Teng)。<br />授權條款：<a href="https://creativecommons.org/licenses/by-nc/4.0/deed.zh_TW" rel="license">CC BY-NC 4.0</a> · 禁止商業使用；分享請署名並註明原文 URL。<br />商業授權請聯絡：st333117@gmail.com</p>]]></content:encoded>
    </item>
    <item>
      <title>當工具自薦時：SSDLC 裡 Claude 各入口的角色與邊界</title>
      <link>https://eeit.github.io/ai-devops-blog/posts/06-tool-choice-in-ssdlc/</link>
      <pubDate>Sat, 18 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://eeit.github.io/ai-devops-blog/posts/06-tool-choice-in-ssdlc/</guid>
      <source url="https://eeit.github.io/ai-devops-blog/posts/06-tool-choice-in-ssdlc/">AI 輔助維運工程</source>
      <description>Claude Code、Claude.ai 是同一個模型、不同平台，該怎麼選？從一次對照實驗發現 Anthropic 自己承認的 self-preference bias 開始，建立一個獨立於工具的判準——讓 SSDLC 流程本身告訴你答案。</description><content:encoded><![CDATA[<blockquote>
<p>本文為《AI 輔助維運工程：從 Claude Code 機制到企業落地》系列第 6 篇。上一篇談 token 經濟學——怎麼算清楚一次 session 的錢。這一篇談更中觀的問題：<strong>一整個 SSDLC 流程跑下來，每個階段該用哪個 Claude 入口？</strong></p>
</blockquote>
<p>這個問題有兩個陷阱。第一個，你會被誘惑去問 Claude 本身——「你適合還是對方適合」——然後得到一份結構完整、理由清楚、但可能帶有系統性偏誤的答案。第二個，你會以為這個選擇有標準答案——其實選擇取決於你的工作型態、當下任務的條件、甚至你今天的認知狀態。</p>
<p>這篇要處理的就是這兩個陷阱。路徑是：從一次臨時起意的對照實驗開始，看 Claude 在評估自己時會出現什麼偏誤；再倒回來建立一個獨立於工具本身的判準；最後用這個判準重讀自薦文，你會自己看見該怎麼選。</p>
<h2 id="一個臨時起意的對照實驗">一個臨時起意的對照實驗</h2>
<p>前陣子我在 Claude Code 裡寫規格，寫到一半停下來——這個訪談，在 Claude.ai 也能做。</p>
<p>兩邊跑的是同一個模型，但環境不一樣：Claude Code 接我的 repo 跟 terminal，Claude.ai 有 Project Knowledge 跟跨日對話。<strong>同一個模型，不同平台，做出來的分析品質會不會不一樣？</strong> 這是個可以測的問題。</p>
<p>我順手做了個對照實驗：先問 Claude Code「你跟 Claude.ai 誰適合做這個訪談」，再把同樣的問題丟給 Claude.ai，比兩邊。</p>
<h2 id="claude-code-的回答">Claude Code 的回答</h2>
<p>節錄：</p>
<blockquote>
<p>核心理由：(1) 我的工具鏈原生支援 (2) 輸出直接寫進 repo (3) 下一階段無縫接軌</p>
</blockquote>
<blockquote>
<p>我的推薦：Claude Code</p>
</blockquote>
<blockquote>
<p>選項：A（Claude Code，我推薦）／ B（先 Claude.ai 探索，再回 Claude Code 寫進 repo，折衷）／ C（純 Claude.ai，最不推薦）</p>
</blockquote>
<p>乍看很有結構、理由清楚、選項排好優先級，差點就按 A。但我多看了它給的對比矩陣兩眼，發現幾格事實錯了——說 Claude.ai「無檔案存取」「不能呼叫 skill」，但這兩件事 Claude.ai 現在都做得到（Project Knowledge、MCP connector、skill 機制），我平常就在用。三格裡有兩格錯，錯的方向一致——都讓 Claude.ai 看起來比實際能力差。</p>
<p>另一格「不能即時跑 SSH 驗證假設」<strong>是對的</strong>——Claude.ai 確實接不上我本機的 tunnel。這是 Claude Code 真正的主場優勢，我不會為了批評而否認。</p>
<h2 id="把-claude-code-的回答丟給-claudeai-看">把 Claude Code 的回答丟給 Claude.ai 看</h2>
<p>它讀完後給了我一個我沒聽過的名詞：<strong>self-preference bias</strong>（SPB，自我偏好偏誤）——LLM 被放在「評估自己 vs 同家族競品」的情境時，會系統性偏向自己。</p>
<p>老實說我半信半疑。AI 給你一個聽起來很有模有樣的名詞，經常是湊出來的。我請它給文獻，我要一手可驗證的來源。</p>
<p>查完後證據夠硬。學術界 2024 年已經正式命名並量化這個現象（Wataoka et al., <em>Self-Preference Bias in LLM-as-a-Judge</em>, 2024）。更關鍵的是，<strong>Anthropic 自己承認</strong>：Claude Sonnet 4.5 的 system card 明載四個現役 Claude 模型在評比自己 vs 其他模型時都會出現偏誤，只是程度不同——Sonnet 4.5 在 benchmark 子測試中「稍微偏向選自己」，Sonnet 4 則更明顯。在詩作子測試中，四個被測 Claude 模型<strong>全都</strong>顯著傾向選擇自己寫的，Sonnet 4.5 只是其中偏誤最小的。2025 年 12 月 Anthropic 還開源了一個叫 Bloom 的工具專門測這件事，測試範圍涵蓋 16 個前沿模型。</p>
<p>不是陰謀、不是個案、不是我過度解讀。&ldquo;self-preference bias&quot;是一個有名字、有文獻、官方承認的已知行為。</p>
<h2 id="誠實補充claudeai-不是比較準">誠實補充：Claude.ai 不是比較準</h2>
<p>這裡要停一下，不然這段會變得不對稱。</p>
<p>Claude.ai 能認出 SPB 而 Claude Code 沒認出自己在做這件事——<strong>不是 Claude.ai 比較聰明</strong>。是我問 Claude.ai 的問題不同：我讓它評估 Claude Code 的產出，它不是評估自己。<strong>這個情境下它沒有 SPB 的誘發條件</strong>。反過來我如果問 Claude.ai「你跟 Claude Code 誰適合」，它十有八九也會偏向自己。</p>
<p>所以這個對照實驗的結論不是「某個平台比較準」。是：<strong>同一個模型、不同提問情境，會產出不同可信度的分析</strong>。原因不在平台，在<strong>怎麼問</strong>。</p>
<h2 id="為什麼會這樣">為什麼會這樣</h2>
<p>機制比擬人化的「AI 想求生存」冷多了。研究顯示 LLM 會偏好「對自己而言最熟悉、最不驚訝」的輸出——用困惑度（perplexity）衡量，perplexity 越低的越容易被模型打高分，而自己產出的東西對自己 perplexity 最低。這是統計性質，不是意圖。</p>
<h2 id="這篇文章要處理的問題">這篇文章要處理的問題</h2>
<p>對照實驗跑完，我拿到三個可以往下推的事實：</p>
<p>一，SPB 是<strong>情境觸發</strong>的偏誤——Claude Code 被問「你 vs 別人」時會發作，被問別的就不會。
二，所有現役 Claude 模型都有，只是程度不同——升級模型不會讓它消失。
三，所以「該在 SSDLC 哪個階段用哪個入口」這個決策，<strong>結構上就不該交給任何一個 Claude 入口來答</strong>。</p>
<p>我需要的是一個<strong>獨立於工具自身</strong>的判準——站在所有入口之外，以 SSDLC 流程本身的需求為原點，去看哪個入口在哪個階段合用。這個判準立起來，不只今天的自薦文會自動現形，明年 Anthropic 改產品結構、多新入口、舊入口改名，判準都還能用。</p>
<p><strong>工具會變，判準不會。</strong> 接下來要建立的，就是這個判準。</p>
<h2 id="一個小坦白">一個小坦白</h2>
<p>開始建判準前要說一件事。<strong>SPB 這個框架不是我獨自看出來的，是 Claude.ai 命名的</strong>，我做的是對照實驗、事實查證、文獻驗證。我可以在這裡把故事寫成「我獨自推敲出這個現象」——那比較有英雄氣概但不是真的。這個系列就是在談 AI 輔助維運，如何誠實呈現協作是核心命題。這一段就留著當活案例。</p>
<hr>
<p>判準要從哪裡長出來？不是從產品規格書、不是從 Anthropic 的官方文件——是從 SSDLC 流程本身的需求長出來。每個階段要的東西不一樣，把需求拆清楚，工具選型就是對號入座。</p>
<h2 id="ssdlc-本身要什麼">SSDLC 本身要什麼</h2>
<p>每個階段要的東西不一樣，四組 trade-off 就夠用：</p>
<p><strong>執行方向</strong>——這個階段需要的是 session 內的執行力（讀檔、寫碼、跑 test、commit），還是 session 間的累積力（跨日、跨週、跨裝置的知識複利）？</p>
<p><strong>協作模式</strong>——單人深潛比較有效，還是多人共議、非同步評審比較有效？</p>
<p><strong>產出形態</strong>——產出要直接寫進 repo、直接改檔案，還是做成可分享 review 的結構化交付物（docx、報表、連結）？</p>
<p><strong>認知節奏</strong>——需要被工具執行打斷的思考節奏，還是不被打斷的開放探索？</p>
<p>這四組軸跟「哪個產品有哪些功能」<strong>垂直</strong>——它們不關心 Claude.ai 支不支援 MCP、Claude Code 能不能用 memory，它們只關心<strong>流程在這個階段要什麼</strong>。流程需求定清楚，工具選型就是對號入座。</p>
<h2 id="ssdlc-階段對應">SSDLC 階段對應</h2>
<p>以下是我走完幾輪 SSDLC 後的歸納。<strong>我刻意不告訴你每個階段「該用哪個」——那是你自己的判斷</strong>。我能告訴你的只有：這個階段 Claude.ai 擅長做什麼、Claude Code 擅長做什麼、有沒有哪邊明顯不適合。剩下的對照你自己的工作型態去取捨。</p>
<table>
  <thead>
      <tr>
          <th>階段</th>
          <th>Claude.ai 擅長</th>
          <th>Claude Code 擅長</th>
          <th>備註</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Problem Space 探索</td>
          <td>跨日累積思考、多人共議、不被工具打斷的開放對話</td>
          <td>需要查 repo 現況時即時對照</td>
          <td>兩邊皆可</td>
      </tr>
      <tr>
          <td>規格撰寫</td>
          <td>長推理、可回看、skill 反覆打磨</td>
          <td>跟既有檔案 diff 對照、引用實際 code 片段</td>
          <td>兩邊皆可</td>
      </tr>
      <tr>
          <td>規格進 repo</td>
          <td>——</td>
          <td><code>git commit</code>、diff、就地編修</td>
          <td><strong>Claude.ai 不適合</strong>：無法直接操作 repo</td>
      </tr>
      <tr>
          <td>實作 Implementation</td>
          <td>跨檔架構思考、卡關時跳出來重想</td>
          <td>讀檔寫碼跑 test 的同步節奏、即時驗證</td>
          <td>兩邊皆可</td>
      </tr>
      <tr>
          <td>Code Review</td>
          <td>深度跨檔審、多 reviewer 非同步共議</td>
          <td>commit 前本機 lint／test／pre-push 自動審</td>
          <td>兩種 review 性質不同，經常同時需要</td>
      </tr>
      <tr>
          <td>部署 Deployment</td>
          <td>事前 checklist 推敲、風險盤點</td>
          <td>真正執行、本機 hook 把關、即時 rollback</td>
          <td><strong>Claude.ai 不適合執行</strong>：但事前規劃仍有角色</td>
      </tr>
      <tr>
          <td>事件處理 Incident</td>
          <td>事件收斂後做跨事件比對、因果重建</td>
          <td>即時讀 log、跑診斷、接 tunnel、下指令</td>
          <td><strong>Claude.ai 不適合即時處理</strong>：但事後仍有角色</td>
      </tr>
      <tr>
          <td>事後檢討 Post-mortem</td>
          <td>跨事件比對、長期存檔、多人共議</td>
          <td>回放當時的 commit、log、指令歷史</td>
          <td>兩邊皆可</td>
      </tr>
  </tbody>
</table>
<h3 id="怎麼讀這張表">怎麼讀這張表</h3>
<p>表格只告訴你「能力分佈」，不告訴你「該怎麼選」。選法取決於三件事：</p>
<p><strong>一，你的工作型態偏好</strong>。有人寫規格時愛在 terminal 裡開編輯器即時對照 code，有人愛在 chat 裡純文字推敲。兩種都對，沒有標準答案。</p>
<p><strong>二，這次任務的具體限制</strong>。這次訪談有沒有多人要一起討論？需不需要跨日？手上的 repo 是不是真的有要被 diff 的檔案？條件不同，選擇就不同。</p>
<p><strong>三，你當下的認知狀態</strong>。一樣是實作階段，你今天是「已經想清楚要寫什麼、只缺手寫」還是「還不確定架構、需要邊寫邊想」？前者 Claude Code 適合，後者 Claude.ai 可能更合——同一個階段、同一個人，不同的一天答案會不一樣。</p>
<p>這是為什麼我不幫你排「主場／副手」。那種排法會強迫你接受<strong>我的</strong>工作型態，但這篇文章要給你的是判準，不是我的工作習慣。</p>
<h3 id="有三個地方我會明確說不適合">有三個地方我會明確說「不適合」</h3>
<p>表格裡有三行我標了「不適合」——這不是主副問題，是<strong>能力邊界問題</strong>：</p>
<p><strong>規格進 repo</strong>：Claude.ai 沒有直接操作檔案系統跟 git 的能力。你要把規格寫進 repo，一定得是 Claude Code（或你自己手動）。</p>
<p><strong>部署執行</strong>：Claude.ai 不能真的跑部署指令。事前規劃可以、事後分析可以，但「執行」這個動作本身只能在 Claude Code 或你的 terminal 裡發生。</p>
<p><strong>事件即時處理</strong>：同上。事件在發生的當下，你需要的是能接真實 log、跑真實診斷的工具。Claude.ai 可以在事件收斂後幫你做跨事件分析，但當下的滅火必須在 Claude Code 這邊。</p>
<p>其他五行沒有任何「不適合」——兩邊都能做，只是擅長的手法不同。<strong>選哪邊取決於你，不取決於我</strong>。</p>
<h3 id="規律提煉">規律提煉</h3>
<p>如果一定要從這張表歸納一條規律，只有一條：</p>
<p><strong>涉及「執行真實動作」的階段（進 repo、執行部署、即時處理事件），Claude Code 是唯一選項；其他所有階段，兩邊都能做，差別在擅長的路徑不同——你選哪條，取決於你怎麼工作。</strong></p>
<p>這條規律為什麼站得住？因為它描述的是<strong>能力邊界</strong>，不是<strong>品味偏好</strong>。能力邊界不會因讀者的工作習慣而變，品味偏好會。把規律定在能力邊界上，才是對讀者誠實的做法。</p>
<p><strong>補充一句</strong>：這張表沒單獨列「架構分析」跟「飄移檢查」這兩種活動——它們散落在 Problem Space 探索、Code Review、事後檢討這幾格裡，取決於你是在系統建立前、建立中、還是建立後做這件事。這兩種活動的工具分工邏輯比單一階段複雜，值得另一篇專門處理。</p>
<h2 id="兩個容易被略過的小注腳">兩個容易被略過的小注腳</h2>
<p><strong>Cowork 為什麼不在表裡</strong>：Anthropic 的 Cowork 定位是給非開發者做檔案與任務自動化——整理會議紀錄、跨 app 搬資料、做月報這類。它對大多數行政、PM、內部協作場景很合適，但對 SSDLC 的主鏈不是主力。誠實說不在主矩陣裡，比硬塞進去稀釋論點好。</p>
<p><strong>API / SDK 什麼時候登場</strong>：都不登場。直到 SSDLC 最後一步——把驗證過的 agent pattern 做成 production service 嵌進自建系統時——API 才出場。它不是選工具，是把「工具內化進產品」的原料。</p>
<h2 id="為什麼這個判準能撐住">為什麼這個判準能撐住</h2>
<p>這張表明年會過時嗎？<strong>表格會過時，判準不會</strong>。</p>
<p>如果 Anthropic 明年新增一個入口，我只要問它四個問題：session 內執行還是 session 間累積？單人還是多人？直接寫檔還是結構化交付？被打斷的思考還是不被打斷的探索？四個答案落定，它在 SSDLC 的位置就定了——不用等官方文件、不用問社群、不用再跑一次對照實驗。</p>
<p>這就是<strong>獨立於工具的判準</strong>的力量。前面那場對照實驗最後揭露的問題——「該用哪個入口」這個決策不能問 Claude——在這裡有了可操作的答案。你不問 Claude，你問<strong>流程</strong>。</p>
<hr>
<p>判準有了、能力邊界清楚了，回頭看最前面那份自薦文，應該看得更透徹了。</p>
<h2 id="把開頭那份自薦文再看一次">把開頭那份自薦文再看一次</h2>
<p>建立完判準，回頭看開頭那份 Claude Code 給的分析：</p>
<blockquote>
<p>核心理由：(1) 工具鏈原生支援 (2) 輸出直接寫進 repo (3) 下一階段無縫接軌</p>
</blockquote>
<blockquote>
<p>我的推薦：Claude Code</p>
</blockquote>
<p>這三條理由現在可以重讀了——不是看它說得對不對，而是看它<strong>把問題預設在哪個階段</strong>。</p>
<p>「輸出直接寫進 repo」「下一階段無縫接軌」——這兩條理由在<strong>規格進 repo</strong> 那個階段完全成立，表格裡那格也確實標了「Claude.ai 不適合」。但我那時候問的問題不是「規格進 repo 要用哪個」，是「<strong>訪談階段要在哪個入口做</strong>」。訪談還沒結束，我根本還沒走到需要寫進 repo 的地方。</p>
<p>它給的三條優點沒有一條錯。錯的是<strong>它把我的問題平移到一個對它有利的階段來回答</strong>。這是 SPB 最細的手法——不是說謊、不是硬推自己，而是<strong>默默把問題預設到自己擅長的那一格</strong>。</p>
<p>如果我當時手上有這份判準表，會發生什麼？我會看到「Problem Space 探索」跟「規格撰寫」兩格都是「兩邊皆可」，然後問自己三個問題：需不需要跨日？需不需要多人？我今天的認知狀態是「已經想清楚」還是「還在邊想邊問」？三個答案合起來才是我的選擇，跟平台自身的自薦無關。</p>
<h2 id="為什麼它們不該整合">為什麼它們不該整合</h2>
<p>寫到這裡，多數工具比較文章會以「未來會整合成一個平台」作結——這其實是偷懶的寫法。如果你仔細看那張表，你會發現整合的期待<strong>沒有道理</strong>。</p>
<p>Claude.ai「不能直接 commit」不只是能力缺失——更是一種<strong>保護機制</strong>。你在探索跟撰寫階段本來就不該邊想邊改檔案，那是還在沉澱思考、還在跨日累積的時候；如果這時候工具讓你隨手就能 commit，你會在還沒想清楚的時候動檔案。限制在那裡，你被迫把想法沉澱夠了才進 repo。</p>
<p>反過來，Claude Code「每次 session 要重新載入脈絡」也不只是不方便——更是另一種<strong>保護機制</strong>。這個麻煩逼你把重要決定寫進檔案、寫進 commit message、寫進 session log，而不是靠對話歷史。結果是你的知識資產比靠對話記憶更穩固——對話會被壓縮、會流失、會改版，檔案不會。</p>
<p>如果把兩者整合成一個萬能入口——既能 commit 又有跨日記憶、既能多人共議又能不被打斷執行——你拿到的不會是「兩邊優點兼具」的超級工具，而是<strong>兩邊保護機制都失效的工具</strong>。你會在探索階段手癢就 commit、在執行階段被非同步討論打斷、在多人共議時被單人 session 綁架。</p>
<p><strong>入口之間的差異不是 Anthropic 還沒做好、未來會補上——那是設計</strong>。</p>
<h2 id="下次你會怎麼問">下次你會怎麼問</h2>
<p>這篇文章要留給你帶走的東西就一件：<strong>下次你在猶豫該用哪個 Claude 入口時，不要問 Claude</strong>。問三個問題：</p>
<p>一，這個階段涉不涉及「執行真實動作」——動 repo、跑指令、接真實環境？如果是，Claude Code 是唯一選項。</p>
<p>二，如果不涉及執行，兩邊都能做——那我今天的<strong>工作型態</strong>偏哪邊？需不需要跨日、需不需要多人、認知狀態是想清楚了還是還在摸索？</p>
<p>三，如果我仍然拿不定主意，<strong>做個小對照實驗</strong>。用同一個問題丟兩邊，比結果——不是比誰對誰錯，是比兩邊的回答對我當下的狀態哪個更合。</p>
<p>這三個問題你回答完，選擇自動浮現。過程中<strong>不需要問任何一個 Claude 入口「你該被我選嗎」</strong>——因為你現在知道，那個問題結構上就不該由它來答。</p>
<h2 id="關於這篇文章的產生方式">關於這篇文章的產生方式</h2>
<p>最後一件事。這篇文章的論點——從對照實驗、SPB 命名、到判準建立——是我跟 AI 協作者一起推敲出來的，不是我獨自想通的。我做對照實驗、我查文獻、我決定哪些素材進哪個段落；協作者給命名、給框架、給我沒想到的盲點（譬如有一輪我差點寫成「Claude.ai 比 Claude Code 聰明」，被它提醒後我才補上對稱性那段）。</p>
<p>這本身就是這篇文章論點的<strong>活示範</strong>。我沒把任何一個入口當唯一判官——當我需要探索跟撰寫時，我用 Claude.ai；當我需要把文章寫進 repo 跟發布時，我用 Claude Code；當我需要一個不在這場對照實驗裡的第三方視角時，我開另一個乾淨的 chat 重問一次。<strong>判準不是我單獨持有的原則，是我跟協作者一起在用的工作方式</strong>。</p>
<p>工具會變，判準不會。下次新入口出現、舊入口改版、整個產品結構大洗牌——你拿這四組 trade-off、這三個自問問題、跟「結構上就不該問工具自己」的原則，都還能用。</p>
<hr>
<p>下一篇進入第 7 篇，談 Anthropic 四種 Claude 方案的選型——個人、團隊、Enterprise、API——以及一個很多人不知道的訓練政策風險。系列後段還有一篇會專門處理「架構分析」跟「飄移檢查」這兩類橫跨 SSDLC 的元活動——它們的工具分工邏輯比單一階段複雜，需要獨立展開。</p>
<hr>
<p><em>本文作者：鄧景仁 (Scott Teng) | 資訊服務業 infra 工程師，專注於 Azure / Linux / 安全維運。如需討論可聯繫 <a href="mailto:st333117@gmail.com">st333117@gmail.com</a>。</em></p>
<p><em>本系列所有內容為個人學習與實務心得整理，不代表任職機構立場。本文談及的 self-preference bias 引用來源為 Claude Sonnet 4.5 system card（Anthropic 2025）、Bloom 開源評估工具（Anthropic 2025）與 Wataoka 等人 Self-Preference Bias in LLM-as-a-Judge（2024）。讀者可依此自行查證。AI 協同創作已在系列導讀揭露。</em></p>
<hr /><p style="font-size:0.9em;opacity:0.8;margin-top:2em;">本文原刊於 <a href="https://eeit.github.io/ai-devops-blog/posts/06-tool-choice-in-ssdlc/" rel="canonical">https://eeit.github.io/ai-devops-blog/posts/06-tool-choice-in-ssdlc/</a>，作者：鄧景仁 (Scott Teng)。<br />授權條款：<a href="https://creativecommons.org/licenses/by-nc/4.0/deed.zh_TW" rel="license">CC BY-NC 4.0</a> · 禁止商業使用；分享請署名並註明原文 URL。<br />商業授權請聯絡：st333117@gmail.com</p>]]></content:encoded>
    </item>
  </channel>
</rss>
