本文為《AI 輔助維運工程:從 Claude Code 機制到企業落地》系列第 2 篇。前一篇談了為什麼 Claude Code 是不一樣的工具,這一篇開始進入它的運作核心。
為什麼先懂這個
你可能以為你在「跟 Claude Code 對話」。
實際上,你是在驅動一個迴圈。
這個差異不是修辭。搞懂之後,後面所有的疑問都會有答案:
- 為什麼同樣一句話,有時候 3 秒結束、有時候跑 5 分鐘?
- 為什麼 token 帳單會爆炸,而且完全看不出錢花在哪?
- 為什麼一個任務進行到一半會卡住?
- 為什麼「thinking…」有時候真的在想,有時候只是在處理資料?
這些問題的根源都在 Agent Loop。這篇文章不是教你怎麼用 Claude Code,是要你建立一個關於它運作方式的心智模型,這個模型會貫穿整個系列。
三句話版本的 Agent Loop
如果要用最精簡的方式描述,Claude Code 做的事情就是這三件:
- 接收輸入,組裝成模型看得懂的 prompt
- 呼叫模型,拿到回應
- 判斷要不要繼續,要繼續就執行工具,拿結果回到第 1 步
聽起來很簡單。但魔鬼在細節裡,尤其是第 3 步的「判斷要不要繼續」。這個判斷讓 Claude Code 從「問答工具」變成「任務執行者」。
一次對話實際發生了什麼
我們用一個具體情境拆解:你在 Claude Code 裡輸入「幫我看看今天早上 nginx 的錯誤日誌,有沒有 5xx 的異常」,然後按下 Enter。
接下來發生的事情,可以分成六個階段。
階段一:你按下 Enter 之後的 0.1 秒
訊息送進 Claude Code 的處理管線之前,先經過一道輸入處理:
- 如果你輸入的是 slash command(像
/compact、/init),會被攔截走另一條路徑 - 如果你附加了圖片或檔案,會被轉成對應的 message block
- 如果你用
@引用了檔案(@src/main.ts),會把檔案內容塞進 context - 純文字就直接進入下一步
這一步很快,但它決定了你送進去的不只是你打的那幾個字。
階段二:System Prompt 的組裝
這是很多人忽略的關鍵環節。
每次你送訊息,Claude Code 會動態組裝一個 system prompt,這個 prompt 由好幾個部分拼成:
[核心身份與工具說明] ← Claude Code 本身的 prompt,固定
[環境資訊] ← 作業系統、shell、目前工作目錄
[專案上下文] ← 你的 CLAUDE.md 和 @import 的檔案
[MCP 工具描述] ← 你裝的 MCP servers 的 tool schemas
[內建工具描述] ← Read/Write/Bash/Grep 等工具的說明
[Git 狀態] ← 目前 branch、uncommitted changes
[過去對話歷史] ← 如果是延續 session,過去的 turns 都在這
這個組裝順序和內容會影響兩件事:
- Token 消耗:每次送出的 prompt 越長,輸入 token 越多。
- 模型行為:你 CLAUDE.md 怎麼寫,直接決定模型會怎麼回應你。
這也是為什麼減少 CLAUDE.md 裡不必要的內容,我自己觀察是 token 優化裡很容易見效的一個手段。把 CLAUDE.md 寫成長篇大論,等於每一輪都在付那個長篇大論的錢。
階段三:API Call 與 Streaming
組裝好的 prompt 送到 Anthropic 的 API,模型開始回應。
你注意過嗎?Claude Code 的回應是一個字一個字跑出來的,不是整段突然出現。這叫做 streaming,模型一邊思考一邊吐字,Claude Code 一邊接一邊顯示。
Streaming 有幾個現實影響:
- 你可以在中途按 Esc 取消:模型還沒講完,你就可以打斷它,不用等它講完再操作。
- 延遲感知比較低:即使整個回應要 30 秒,你看到第一個字通常只要 1-2 秒。
- Tool use 也是 stream 的一部分:當模型決定要呼叫工具,那個指令也是 stream 出來的,Claude Code 接到就準備執行。
階段四:Tool 的識別與執行
這是 Agent Loop 最核心的一步。
模型的回應裡可能有兩種東西:
- 純文字:給你看的說明、分析、結論
- Tool Use Block:「我需要執行某個工具,請幫我跑」的指令
當 Claude Code 偵測到 tool use block,它會:
- 檢查這個工具是否在白名單(對應上一篇講的三道關卡)
- 如果需要你確認(ask 規則),跳出確認對話
- 實際執行這個工具(讀檔、跑 bash、呼叫 MCP 等)
- 把執行結果包成 tool_result,準備送回模型
用我們的 nginx 例子:
- 模型第一輪可能先發出
Bash: ls /var/log/nginx/想看有哪些 log 檔 - Claude Code 執行後,把結果送回模型
- 模型第二輪可能發出
Bash: grep -E " 5[0-9]{2} " /var/log/nginx/access.log | head -50篩出 5xx - 執行後結果再送回
- 模型第三輪可能已經分析完,直接用文字回答你
你看到的「Claude 幫我查完了」,其實是至少 3 次 API call + 2 次工具執行的結果。
階段五:判斷要不要繼續
這是 loop 的關鍵節點。
每一輪模型回應結束後,Claude Code 會問:回應裡還有 tool use block 嗎?
- 有 → 執行工具,把結果送回,進入下一輪
- 沒有(只有文字) → loop 結束,把控制權交還給你
這個判斷聽起來簡單,但它是整個 agentic 行為的基礎。模型自己決定「我需要更多資訊」或「我完成了」,不需要你每一步都按「繼續」。
階段六:終止條件
除了模型自主判斷完成,loop 還有幾個強制終止的條件:
- Max turns:預防無限迴圈,達到上限會停
- 使用者中斷:你按 Esc
- 權限拒絕:你拒絕了某個工具的 ask,而模型沒有備案
- 錯誤:API 失敗、tool 執行錯誤且模型無法處理
這解釋了為什麼你有時候覺得 Claude Code「沒做完就停了」 —— 它其實是碰到了某個終止條件。看錯誤訊息或 verbose mode 可以知道是哪一個。
一張圖總結:Agent Loop 的完整流程
你按下 Enter
│
▼
[輸入處理] slash command? 附件? @引用?
│
▼
[組裝 system prompt] 固定部分 + 環境 + CLAUDE.md + tools + git + 歷史
│
▼
┌─── 進入 Query Loop ───┐
│ │
│ [呼叫 API,streaming 回應]
│ │
│ ▼
│ [識別 tool_use block]
│ │
│ 有 ─┴─ 沒有
│ │ │
│ ▼ ▼
│ [執行工具] [結束 loop,回傳給你]
│ │
│ ▼
│ [結果送回模型]
│ │
│ └──→ (下一輪)
│
└────────────────────────┘
這就是每次你跟 Claude Code 互動時,底層真正發生的事。
Tool 執行:序列還是平行?
模型在一次回應中可以發出多個 tool use block。當這發生時,Claude Code 要決定:這些工具能不能同時跑?
判斷邏輯大致是:
| 情境 | 執行方式 | 原因 |
|---|---|---|
| 多個 Read 操作 | 平行 | 只讀,不互相影響 |
| 多個 Grep / Glob | 平行 | 搜尋也是只讀 |
| 多個 Bash command | 序列 | 可能有副作用(改檔案、改狀態) |
| Read + Write 同一個檔案 | 序列 | 必須先 Read 再 Write,有依賴 |
| 多個獨立的 Write | 通常序列 | 謹慎起見,避免競態 |
為什麼這個區分重要? 因為平行執行會大幅加速任務。當 Claude Code 一次叫 10 個 Read 去看 10 個檔案,平行跑和序列跑的體感差距是 10 倍以上。
這也是為什麼 Claude Code 有「Explore」這類唯讀 sub-agent —— 唯讀保證可以平行,速度快,而且不會搞壞東西。(Sub-agent 的主題會在第 4 篇展開)
這些機制對你實際操作的意義
搞懂 loop 之後,很多「奇怪的現象」都有答案了。
為什麼長任務會越跑越慢
每一輪 loop,Claude Code 都要把整段對話歷史重新送進 API。對話越長,每一輪要傳的東西越多,API 呼叫越慢,也越貴。
這就是為什麼到了某個臨界點,任務會明顯變慢。原因不是「AI 累了」,是 context 逼近上限,每一輪的 overhead 越來越大。
這個問題的解方就是 context 壓縮,下一篇會整個展開。
為什麼「thinking…」有時候很久
「thinking…」其實有兩種:
- 真的在 extended thinking:模型在做內部推理,這部分會花時間但也確實在產出思考
- 在處理 tool result:前一個工具剛跑完,結果很大(例如讀了一個 500 行的檔案),模型正在消化
如果你覺得 thinking 太久,可以開 verbose mode 看它到底在做什麼。通常第二種比較常見。
為什麼某些操作會卡住等你
這是權限系統介入的時刻。當模型想做的事情在 ask 規則裡,Claude Code 會跳出確認對話,loop 在你回應之前是停住的。
這不是 bug,是設計 —— 確保你對破壞性操作有最後一次確認機會。
為什麼同樣一句話,效果差很多
兩個使用者問一樣的問題,結果天差地遠的主因不是「模型不穩」,而是:
- CLAUDE.md 寫得不一樣
- 當前 working directory 不一樣
- 已經在 session 裡累積的 context 不一樣
- 裝的 MCP tools 不一樣
System prompt 的組裝階段(階段二)就決定了結果差異中很大一部分。這也是為什麼我覺得團隊裡把 CLAUDE.md 寫好、統一管理,通常會比讓每個人自己摸索更可預期一些。
我自己經歷的一次觀念轉換
我自己一開始使用 AI 助理的心理模型是這樣:
「我在問 AI 一個問題,它回答我。」
用 Claude Code 一段時間後,我自己慢慢轉成這樣:
「我啟動了一個迴圈,這個迴圈會執行多輪,直到達成我給的目標或觸發終止條件。我的任務是設計好這個迴圈的起點、邊界、和終止條件。」
這個轉換之後,我開始問自己不一樣的問題:
- 我這句 prompt 會讓 loop 跑幾輪?會不會太多?
- 這個任務需要的 context 是否都在 loop 開始時就備好了?
- 如果 loop 跑太久,我該怎麼設計 checkpoint?
- 什麼情況下應該主動終止 loop,換個方式再來?
這些是我自己覺得在「熟練使用 Claude Code」之後比較常想的事。
下一篇預告
搞懂 loop 之後,下一個繞不開的主題就是 context 管理。
在這篇裡我們看到:每一輪 loop 都要把整個 context 送進 API。當 context 逼近上限會發生什麼?Claude Code 怎麼在你不察覺的情況下,把空間清出來?
這個系統比表面看起來精巧 —— 有四層壓縮管線,每一層用不同的策略,該什麼時候哪一層啟動都有明確規則。
下一篇,我們把這個黑盒打開。
本篇重點整理
- Claude Code 不是對話工具,是任務執行迴圈 —— Agent Loop
- 每次你按 Enter,會經過六個階段:輸入處理 → 組裝 system prompt → API call → 識別 tool use → 執行工具 → 判斷是否繼續
- Loop 的終止由模型自主判斷或強制條件(max turns、權限拒絕、錯誤、使用者中斷)觸發
- Tool 可以平行或序列執行,唯讀類通常平行、有副作用的通常序列
- 長任務變慢的主因是 context 越來越大,每一輪 overhead 放大
- 心智模型上的轉換:從「我在問 AI」到「我在驅動一個迴圈」
本文作者:鄧景仁 (Scott Teng) | 資訊服務業 infra 工程師,專注於 Azure / Linux / 安全維運。如需討論可聯繫 st333117@gmail.com。
本系列所有內容為個人學習與實務心得整理,不代表任職機構立場。本文對 Claude Code 內部機制的描述,基於社群對 Claude Code 的公開分析材料與筆者實務觀察,並非 Anthropic 官方文件。