模組 1:核心 Agent 1 / 6
初階
Session 1 架構 Agent Loop 基礎
Agent Loop(代理迴圈)
理解驅動 Claude Code 的核心非同步訊息迴圈 — 它如何處理訊息、路由工具呼叫,以及決定何時停止。
2026年3月20日 · 18 分鐘閱讀
你將學到什麼
在第一堂課中,你將理解 Claude Code 的核心:Agent Loop。每一次互動 — 從簡單的「修復這個 bug」到複雜的多檔案重構 — 都流經這個迴圈。
完成後,你將了解:
- 訊息迴圈如何處理每一輪
stop_reason路由的意義及其重要性- 工具結果如何回饋到迴圈
- 為什麼這種架構能實現複雜的多步驟任務
問題是什麼
當你在 Claude Code 輸入提示時,會發生一件了不起的事:AI 不只是回應一次。它可以讀取檔案、執行命令、編輯程式碼,然後繼續 — 全部在單次互動中完成。怎麼做到的?
簡單的方式是請求-回應:
使用者 → AI → 回應(結束)
但 Claude Code 做了根本不同的事。它執行一個迴圈,持續運行直到 AI 決定完成:
使用者 → AI → 工具呼叫 → 結果 → AI → 工具呼叫 → 結果 → AI → 回應(結束)
這就是 Agent Loop。
如何運作
以下是核心架構的簡化版:
┌─────────────────────────────────────────┐
│ Agent Loop │
│ │
│ ┌──────────┐ │
│ │ 提示 │◄──── 使用者訊息 │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Claude │◄──── 系統提示 + │
│ │ API │ 訊息歷史 │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ stop_reason? │ │
│ └──┬───────┬───┘ │
│ │ │ │
│ "end_turn" "tool_use" │
│ │ │ │
│ ▼ ▼ │
│ 結束 ┌──────────┐ │
│ │ 執行 │ │
│ │ 工具 │ │
│ └────┬─────┘ │
│ │ │
│ │ 將結果加入訊息 │
│ │ │
│ └──────► 回到迴圈 ◄───────│
│ │
└──────────────────────────────────────────┘
關鍵的路由決策基於 stop_reason:
| stop_reason | 動作 | 含義 |
|---|---|---|
end_turn | 停止迴圈 | AI 完成了,返回回應給使用者 |
tool_use | 執行工具,回到迴圈 | AI 想在回應前使用工具 |
訊息陣列
迴圈維護一個持續增長的訊息陣列:
const messages = [
{ role: "user", content: "修復 auth.ts 的 bug" },
{ role: "assistant", content: [
{ type: "text", text: "讓我看看這個檔案..." },
{ type: "tool_use", id: "1", name: "Read", input: { file_path: "auth.ts" } }
]},
{ role: "user", content: [
{ type: "tool_result", tool_use_id: "1", content: "// 檔案內容..." }
]},
{ role: "assistant", content: [
{ type: "text", text: "我看到問題了..." },
{ type: "tool_use", id: "2", name: "Edit", input: { ... } }
]},
// ... 持續直到 stop_reason === "end_turn"
];
注意一個關鍵點:工具結果被注入為 user 訊息。這就是 AI 如何「看到」其操作的輸出。API 本身沒有工具執行的概念 — 它只看到訊息陣列在增長。
平行工具呼叫
在單一輪次中,Claude 可以同時請求多個工具呼叫:
{
"role": "assistant",
"content": [
{ "type": "tool_use", "id": "1", "name": "Read", "input": { "file_path": "src/a.ts" } },
{ "type": "tool_use", "id": "2", "name": "Read", "input": { "file_path": "src/b.ts" } },
{ "type": "tool_use", "id": "3", "name": "Read", "input": { "file_path": "src/c.ts" } }
]
}
Agent Loop 會平行執行這三個(在安全的情況下),然後將所有結果一起送回。這就是為什麼 Claude Code 可以一次讀取多個檔案。
關鍵洞見
Agent Loop 不是聊天機器人。 聊天機器人處理一條訊息並回應。Agent Loop 更像 Node.js 中的事件迴圈 — 它持續處理直到沒有更多事情要做。
這個區別很重要,因為:
- AI 控制流程。 它決定何時使用工具、何時停止。迴圈不會強制固定步驟數。
- 上下文會累積。 每個工具結果都加入訊息陣列,為 AI 的下一個決策提供更多資訊。
- 錯誤可以恢復。 如果工具失敗,錯誤成為工具結果。AI 可以讀取錯誤並嘗試不同的方法。
實作範例
以下是一個可以實驗的最小化 Agent Loop:
import anthropic
client = anthropic.Anthropic()
tools = [
{
"name": "read_file",
"description": "讀取檔案內容",
"input_schema": {
"type": "object",
"properties": {
"path": {"type": "string", "description": "要讀取的檔案路徑"}
},
"required": ["path"]
}
}
]
def execute_tool(name, input):
if name == "read_file":
try:
with open(input["path"]) as f:
return f.read()
except Exception as e:
return f"錯誤: {e}"
def agent_loop(user_message):
messages = [{"role": "user", "content": user_message}]
while True:
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
tools=tools,
messages=messages,
)
# 根據 stop_reason 路由
if response.stop_reason == "end_turn":
return [b.text for b in response.content if b.type == "text"]
# stop_reason == "tool_use" → 執行工具
messages.append({"role": "assistant", "content": response.content})
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": str(result),
})
messages.append({"role": "user", "content": tool_results})
前後對比
| 之前(聊天機器人) | 之後(Agent Loop) |
|---|---|
| 一個請求 → 一個回應 | 一個請求 → 多次工具呼叫 → 一個回應 |
| 固定互動模式 | AI 控制流程 |
| 沒有工具執行 | 工具在迴圈中執行 |
| 上下文是靜態的 | 上下文隨每個工具結果增長 |
| 錯誤是終止性的 | 錯誤可以恢復 |
下一堂課
現在你理解了迴圈,第 2 堂課將深入工具系統與權限 — Claude Code 如何決定暴露哪些工具、權限回呼如何運作,以及為什麼某些工具需要批准而其他不需要。