Agent 架構:loop、工具、記憶、規劃
你已經玩過 Claude API,知道怎麼發一個請求、拿回一段文字。但某一天你想做的事情,一個來回搞不定:要先查資料、再整理、再寫入檔案、再回來問你要不要繼續——這時候你寫的程式開始變成一個 while 迴圈,裡面塞了條件判斷、工具呼叫、錯誤處理,愈來愈複雜,愈來愈難維護。
這就是從「呼叫 LLM」到「開發 Agent」的分水嶺。Agent 不是一個酷炫的詞彙,是一種程式架構:讓模型在迴圈裡自主決定下一步,直到任務完成。架構搞懂了,後面每一課才不會只是照著做卻不知道為什麼。
這堂學什麼
- Agent loop 是什麼、為什麼它是 agent 的核心
- 四大組件:LLM、工具(Tool)、記憶(Memory)、規劃(Planning)的職責分工
- Single-turn vs 長任務 agent:適合場景的判斷標準
- 2026 框架生態:自寫 loop、Claude Agent SDK、LangGraph、CrewAI——每個適合什麼情境
- 何時不該用 agent:誠實評估,避免過度工程
觀念一:Agent Loop 是什麼
傳統的 LLM 呼叫是單向的:你給 prompt,它給答案,結束。Agent 的差異在於加了一個迴圈:模型的輸出不直接給使用者,而是先問「我需要用什麼工具」,工具執行後結果放回 context,模型再判斷,直到它認為任務完成再輸出最終答案。

這個「判斷 → 執行 → 觀察」的三步,就是 ReAct(Reasoning + Acting)模式——2023 年 Google 的論文奠基,現在已是業界標準。你後面用任何框架,底層跑的都是這個迴圈。
關鍵認知:agent 和你手寫的 for-loop 最大的差別,是由模型決定迴圈什麼時候結束,不是你的 code 決定。這帶來彈性,也帶來不確定性——這是這門課會一再回應的核心張力。
觀念二:四大核心組件
把任何 agent 系統拆開來,都由四個組件組成:

LLM:決策引擎
模型是整個系統的大腦。它讀 context、判斷下一步、決定呼叫哪個工具、最後輸出結果。在 2026 年,claude-sonnet-4-6 是主流 agent 模型選擇:Sonnet 速度快、成本低(input/output 每百萬 token 約 $3/$15),適合多步驟但每步不太複雜的任務;Claude Opus 4.8 推理強、但 token 較貴($5/$25),適合規劃和判斷要求高的環節。不要用同一個模型做所有事——第 4 課的 orchestrator 模式會回來討論這點。
工具:感知與執行的雙手
工具是 agent 能做的「動作清單」。沒有工具,agent 等於被關在上下文視窗裡只能說話。工具分兩種:
- 讀取類(低風險):搜尋、讀檔、查 API——agent 的感知系統
- 寫入類(有副作用):寫檔、傳 API 請求、執行終端指令——agent 的行動系統
工具設計是 agent 好壞最重要的決定因素——這是第 2 課的主題,先記住這句話。
記憶:對抗遺忘的機制
LLM 沒有持久記憶,只有 context window。記憶是你在 agent 架構層做的設計:
| 記憶類型 | 儲存位置 | 適合什麼 |
|---|---|---|
| 工作記憶 | context window | 當前任務的所有資訊 |
| 短期記憶 | 對話歷史 | 同一次執行內的多輪互動 |
| 長期記憶 | 外部資料庫(向量 DB 或 KV) | 跨任務的使用者偏好、知識庫 |
| 程序記憶 | system prompt / 固定工具 | agent 的技能和規則 |
主流 agent 模型如 Claude Sonnet 4.6、Opus 4.8 的 context window 已達 1M tokens(Haiku 4.5 則是 200k)。看起來很大,但一個多步驟任務的工具呼叫結果會不斷累積,而且 context 愈長、每一輪的 input token 費用就愈高——context 管理是長任務 agent 最常踩的坑之一,第 3 課會有實作。
規劃:把複雜目標拆成可執行步驟
複雜任務需要規劃。兩種主要模式:
- ReAct:邊想邊做,每一步根據上一步結果決定下一步。適合探索性、不確定路徑的任務
- Plan-and-Execute:先生成完整計劃,再逐步執行。適合結構清楚、步驟可預知的任務
兩者不互斥。很多生產 agent 會先用 Plan-and-Execute 拆任務,每個子任務再用 ReAct 執行。
觀念三:Single-turn vs 長任務 Agent
不是所有 agent 都需要長時間跑。區分清楚,避免過度設計:

Single-turn agent 適合:回答需要一次工具呼叫輔助的問題(搜尋後彙整、讀檔後分析)。失敗代價低,重跑一次即可。大多數你現在用到的 chatbot with tools 都是這個層級。
長任務 agent 適合:自動化研究報告、程式碼審查與修改、多步驟資料處理流程。特徵是:任務時間超過一分鐘、可能需要中途問使用者、失敗後需要從某個 checkpoint 繼續而不是重跑全程。這類 agent 需要設計記憶持久化和 human-in-the-loop 的介入點。
判斷標準:你能在一個 prompt 裡說清楚「完成的定義」嗎? 如果不能,就是長任務 agent 的領域。
觀念四:2026 框架生態盤點

選項一:自寫 Agent Loop(用 Anthropic Client SDK)
最透明、最可控。你自己寫迴圈、自己管理工具呼叫、自己決定何時結束。
import anthropic
client = anthropic.Anthropic()
tools = [
{
"name": "search_web",
"description": "搜尋網路取得最新資訊",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "搜尋關鍵字"}
},
"required": ["query"]
}
}
]
messages = [{"role": "user", "content": "2026 年最受歡迎的三個 AI agent 框架是什麼?"}]
# Agent loop:最多跑 10 輪防止無限迴圈
for _ in range(10):
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
tools=tools,
messages=messages
)
# 判斷是否結束
if response.stop_reason == "end_turn":
# 取最後一個文字 block 作為最終答案
for block in response.content:
if block.type == "text":
print("最終答案:", block.text)
break
# 處理工具呼叫
if response.stop_reason == "tool_use":
messages.append({"role": "assistant", "content": response.content})
tool_results = []
for block in response.content:
if block.type == "tool_use":
# 這裡換成你真正的工具執行邏輯
result = f"[工具 {block.name} 的執行結果,query={block.input.get('query', '')}]"
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result
})
messages.append({"role": "user", "content": tool_results})
適合情境:理解底層運作、一次性腳本、對框架有強烈控制需求、不想引入額外依賴。
選項二:Claude Agent SDK(Anthropic 官方)
2025 年 9 月從 Claude Code SDK 改名。它把 agent loop 封裝起來,你給目標和工具清單,SDK 自己跑到完。Python package 名稱是 claude-agent-sdk,需要 Python 3.10+。
pip install claude-agent-sdk
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
options = ClaudeAgentOptions(
system_prompt="你是一個嚴謹的研究助理,回答要有具體數字和來源。",
allowed_tools=["WebSearch", "WebFetch"], # 使用內建工具
model="claude-sonnet-4-6",
)
full_text = ""
# query() 是 async generator,逐事件串流
async for event in query(
"整理 2026 年三大 AI agent 框架的 GitHub star 數與各自定位",
options=options
):
# event.type 可能是 "assistant"、"tool_use"、"tool_result"、"result"
if event.type == "assistant":
for block in event.message.content:
if hasattr(block, "text"):
full_text += block.text
print(full_text)
asyncio.run(main())
內建工具:Read、Write、Edit、Bash、Glob、Grep、WebSearch、WebFetch、AskUserQuestion——開箱即用。
費用注意:Claude Agent SDK 的計費基礎就是 token,按你選的模型 input/output 單價計算(Sonnet 4.6 約 $3/$15、Opus 4.8 約 $5/$25 per million tokens)。跑長任務前先估算一次執行的預期 token 用量、再乘上單價,確認商業模式能負擔再動工——一個多步驟研究 agent 一次跑下來吃掉幾萬 token 是常態。
適合情境:在 Claude Code 生態系裡做自動化、需要和 MCP 工具整合、要快速出原型的工程師。
選項三:LangGraph
2026 年生產環境採用度最高、社群討論最熱的 agent 框架之一。核心概念是「狀態圖」:你用節點(Node)和邊(Edge)定義工作流程,每個節點是一個函式,狀態在節點間流動。最強的特性是內建 checkpoint——任務跑到一半可以暫停、持久化狀態、稍後繼續,甚至插入 human-in-the-loop。
適合:複雜的多步驟工作流、需要狀態持久化、需要明確定義執行圖的生產系統。學習曲線比 Claude Agent SDK 陡。
選項四:CrewAI
最低學習曲線的框架。用「角色」(Agent)和「任務」(Task)組成「船員」(Crew),20 行 code 就能讓多個 agent 分工協作。2026 年已加入 A2A(Agent-to-Agent)協定支援。
適合:快速驗證多代理協作的概念、原型開發、不需要精細控制執行流程的場景。
怎麼選:課程第 3 課深入 Claude Agent SDK 實戰,第 4 課的多代理架構會示範 LangGraph 的做法。這堂先建認知,不要急著選邊站。
觀念五:何時不該用 Agent
這是很多課程省略的誠實段落。Agent 的彈性來自模型決策,但模型決策帶來的是不確定性和成本。以下幾種情況你不該用 agent:
1. 任務有明確的確定性流程
如果你的任務可以寫成一個固定的流程圖——A → B → C,每個步驟的輸入輸出完全確定——那就用確定性的程式(函式、API、資料庫),不要用 agent。LLM 介入只會增加錯誤率和成本。
2. 延遲容忍度低
Agent loop 每次迭代都有模型推論的延遲,幾秒到幾十秒不等。如果你的使用情境要求毫秒回應(例如即時交易、遊戲),agent 不是正確工具。
3. 預算極度有限
長任務 agent 一次執行可能消耗幾萬 token。如果你的應用量大、利潤薄,先算清楚每次執行的預期 token 用量乘以模型單價,確認商業模式能負擔再動工。
4. 工具副作用無法回滾
如果 agent 能執行刪除資料庫、發送不可撤回的訊息等操作,一旦 agent 判斷錯誤,損失無法挽回。這種情境要在工具層加強確認機制(human-in-the-loop),或根本不讓 agent 直接執行這類操作。
手把手實戰:從 API 到第一個 Agent Loop
實戰目標:用 Claude Agent SDK 寫一個能搜尋網路、整理結果、寫入 Markdown 檔案的迷你研究 agent。
安裝環境
建立虛擬環境並安裝套件:
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install claude-agent-sdk anthropic
確認版本(2026 年 7 月時的穩定版):
python -c "import claude_agent_sdk; print(claude_agent_sdk.__version__)"
# 應看到 0.x.x 或更新版本
設定 API 金鑰。不要把金鑰寫進程式碼,用環境變數:
export ANTHROPIC_API_KEY="sk-ant-..." # 放進 .env 並加進 .gitignore
寫你的第一個 Agent
新增 research_agent.py:
import asyncio
import os
from pathlib import Path
from claude_agent_sdk import query, ClaudeAgentOptions
SYSTEM_PROMPT = """你是一個嚴謹的技術研究助理。
工作流程:
1. 先用 WebSearch 搜尋相關資訊
2. 用 WebFetch 取得重要頁面的完整內容
3. 整理成結構清晰的 Markdown 報告
4. 用 Write 工具把報告存到指定路徑
5. 確認儲存成功後回報「完成」
回報時要包含:你實際查到的資料來源網址。"""
async def run_research(topic: str, output_path: str) -> str:
"""執行研究任務,回傳最終輸出文字"""
options = ClaudeAgentOptions(
system_prompt=SYSTEM_PROMPT,
allowed_tools=["WebSearch", "WebFetch", "Write"],
model="claude-sonnet-4-6",
max_turns=15, # 防止無限迴圈,15 輪足夠大多數研究任務
)
task = f"主題:「{topic}」\n輸出檔案路徑:{output_path}\n請開始研究並產出報告。"
result_text = ""
turn_count = 0
async for event in query(task, options=options):
turn_count += 1
print(f"[turn {turn_count}] event.type={event.type}", flush=True)
# 最終輸出
if event.type == "result":
result_text = event.result or ""
return result_text
if __name__ == "__main__":
topic = "2026 年 AI agent 框架生態:LangGraph、CrewAI、Claude Agent SDK 比較"
output = "./report.md"
print(f"開始研究:「{topic}」")
result = asyncio.run(run_research(topic, output))
print("\n=== Agent 完成 ===")
print(result)
if Path(output).exists():
print(f"\n報告已存到 {output}({Path(output).stat().st_size} bytes)")
跑起來:
python research_agent.py
你會看到 agent 一步一步工作:先搜尋、再抓頁面、最後寫檔。整個過程不需要你介入。
加入自訂工具(搭配 Client SDK)
當你需要 Agent SDK 沒有內建的工具(例如查你自己的資料庫),可以用 Client SDK 自寫 loop 並加入自訂工具:
import anthropic
import sqlite3
client = anthropic.Anthropic()
def query_local_db(sql: str) -> str:
"""查詢本機 SQLite 資料庫"""
try:
conn = sqlite3.connect("my_data.db")
cursor = conn.execute(sql)
rows = cursor.fetchall()
columns = [desc[0] for desc in cursor.description]
conn.close()
result = [dict(zip(columns, row)) for row in rows]
return str(result)
except Exception as e:
return f"查詢失敗:{e}"
# 工具定義:名稱、說明、JSON schema 缺一不可
tools = [
{
"name": "query_local_db",
"description": "查詢本機資料庫取得業務資料。只允許 SELECT 語句,不允許任何寫入操作。",
"input_schema": {
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "要執行的 SELECT SQL 語句"
}
},
"required": ["sql"]
}
}
]
# 工具執行分發器
def execute_tool(name: str, inputs: dict) -> str:
if name == "query_local_db":
return query_local_db(inputs["sql"])
return f"未知工具:{name}"
def run_agent(user_message: str, max_turns: int = 10) -> str:
messages = [{"role": "user", "content": user_message}]
for turn in range(max_turns):
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
tools=tools,
messages=messages
)
if response.stop_reason == "end_turn":
for block in response.content:
if block.type == "text":
return block.text
return ""
if response.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": result
})
messages.append({"role": "user", "content": tool_results})
return "超過最大迴圈次數,任務未完成"
# 使用
answer = run_agent("查出銷售金額最高的前三個產品")
print(answer)
工具定義中的 description 欄位非常關鍵——模型完全依賴這個欄位決定什麼時候、怎麼用這個工具。第 2 課會深入工具設計的眉角。
觀察 Context 的壓力
執行研究 agent 時,在迴圈裡加上 token 計數:
async for event in query(task, options=options):
# Claude Agent SDK 的 event 上有 usage 資訊
if hasattr(event, "usage") and event.usage:
print(
f" input_tokens={event.usage.input_tokens} "
f"output_tokens={event.usage.output_tokens}"
)
你會發現:每一輪的 input_tokens 都在增長,因為整個對話歷史都要帶進去。跑到第 10 輪時,input_tokens 可能已經是第 1 輪的五倍以上。這就是為什麼長任務 agent 必須設計記憶管理策略,而不是一股腦把所有工具結果塞進 context。

常見坑
坑 1:StopIteration: max_turns reached 或任務無限迴圈
症狀:agent 跑了很久都不結束,或直接丟出達到最大輪次的例外。原因通常是工具定義不清,模型不知道什麼時候「算完成」:例如工具回傳的格式讓模型搞不清楚是成功還是失敗,它就一直重試。
解法:在工具的回傳值裡加上明確的狀態欄位({"status": "success", "data": ...} 或 {"status": "error", "reason": "..."}),讓模型有清楚的訊號判斷繼續還是停止。同時在 system prompt 裡明確定義「完成的標準」。
坑 2:anthropic.APIStatusError: 400 {"type":"error","error":{"type":"invalid_request_error","message":"tool_use and tool_result blocks must alternate"}}
症狀:自寫 loop 時,某個迴圈丟出這個 400 錯誤。原因:你在組裝 messages 陣列時順序錯了——tool_use block 一定要在 assistant 訊息裡,對應的 tool_result 一定要在緊接著的 user 訊息裡,兩者必須對應、不能缺漏。
解法:把 assistant 的完整 response.content(包含所有 tool_use block)完整放進 messages,再把所有 tool result 一起放進下一個 user 訊息——不要分開傳,也不要只傳部分。
坑 3:工具執行成功但 agent 繼續重試,說「沒有拿到結果」
症狀:你的工具明明回傳了資料,agent 卻在下一輪說「我沒有收到工具的結果」然後再次呼叫同一個工具。原因:工具回傳值是 None 或空字串。模型收到空的 tool_result,視同工具失敗。
解法:確保工具函式在任何情況下都回傳非空字串。即使查不到資料,也要回傳 "查詢成功,結果為空列表" 而不是 "" 或 None。
坑 4:Python 3.9 以下安裝 claude-agent-sdk 失敗
ERROR: Could not find a version that satisfies the requirement claude-agent-sdk
ERROR: No matching distribution found for claude-agent-sdk
Claude Agent SDK 需要 Python 3.10+。用 python --version 確認版本,建議用 pyenv 管理多版本 Python:
pyenv install 3.12.0
pyenv local 3.12.0
python -m venv .venv
作業
- 跑通實戰第 2 步:執行
research_agent.py,把任何你感興趣的技術主題換進topic變數,確認 agent 能自主搜尋並寫出 Markdown 報告。 - 觀察 loop:在程式裡印出每一個
event.type,記錄一次完整任務觸發了幾次tool_use、幾次tool_result。理解這個數字和任務複雜度的關係。 - 框架評估:根據今天學的判斷標準,想一個你工作或專案裡「最近讓你頭痛的重複性任務」,問自己:它適合用 agent 解決嗎?如果適合,你會選哪個框架?把判斷理由寫下來(不用寫程式,就是文字)。
下一課預告
架構懂了,但你的 agent 有沒有辦法把事情做好,九成取決於工具設計得好不好。工具名稱寫得模糊,模型就不知道什麼時候該用;工具回傳的格式太吵,context 就快速填滿;工具沒有做好錯誤處理,agent 就容易死在奇怪的地方。
第 2 課「工具設計:agent 好壞的第一決定因素」會帶你從工具 schema 設計、輸入驗證、回傳格式、副作用控制到 MCP 工具整合——每個細節都有對應的「寫壞了會怎樣」案例。工具設計的好壞,比你選什麼框架更決定 agent 的實際表現。