Claude Agent SDK 深度解析:Anthropic 的 CLI-Driven Agent 建構框架
Claude Agent SDK 是 Anthropic 官方發佈的 Agent 建構框架,前身為 Claude Code SDK,於 2026 年初正式更名,以反映其不再局限於程式碼任務,而是涵蓋所有領域的 Agent 建構能力。本文將從原始碼角度,深入剖析這個框架的核心設計:CLI-Driven 架構、控制協議、Hook 系統、MCP 整合、權限模型,以及 TypeScript 與 Python 雙版本的差異。
一、定位與架構概覽
SDK 不是 API 包裝器
理解 Claude Agent SDK 最關鍵的一點:它並不直接呼叫 Anthropic API。整個 SDK 的核心架構是一個三層模型:
開發者應用程式
|
Claude Agent SDK (TypeScript / Python)
|
Claude Code CLI (子進程)
|
Anthropic API (Claude 模型)
SDK 啟動一個 Claude Code CLI 子進程,透過 stdin/stdout 的 JSON 串流協議與之通訊。Claude Code CLI 內部才是真正與 Anthropic API 交互的核心。這意味著 SDK 使用者獲得的是完整的 Claude Code 能力——包括所有內建工具(Bash、Read、Write、Edit、Grep、Glob 等)、MCP 整合、安全沙箱、權限管理——而非僅是一個 API 呼叫包裝器。
雙版本發行
| 項目 | TypeScript 版 | Python 版 |
|---|---|---|
| 套件 | @anthropic-ai/claude-agent-sdk (npm) | claude-agent-sdk (PyPI) |
| 版本 | v0.2.49 | v0.1.39 |
| 原始碼 | 閉源(npm 封裝發布) | 開源(完整原始碼在 GitHub) |
| 非同步庫 | 原生 Promise/async | anyio(相容 asyncio 和 trio) |
兩個 SDK 追蹤同一個 Claude Code CLI 版本(v2.1.49),確保功能對等。Python SDK 因為完全開源,是深入理解內部實作的最佳入口。
分層架構(Python SDK)
從原始碼結構來看,Python SDK 的分層設計清晰:
使用者程式碼
|
┌───────────────┼───────────────┐
v v v
query() ClaudeSDKClient Transport (抽象)
| | |
v v v
InternalClient --> Query --> SubprocessCLITransport
| | |
v v v
parse_message 控制協議 CLI 子進程 (stdin/stdout)
(Hook/MCP/
Permission)
其中 Transport 是抽象基類,允許自訂傳輸層(例如連接遠端 Claude Code 實例);Query 則是控制協議處理的核心,負責雙向的 JSON 控制訊息路由。
二、雙介面設計
SDK 提供兩種使用模式,分別對應不同的使用場景。
2.1 query() — 一次性查詢
from claude_agent_sdk import query, ClaudeAgentOptions
async for message in query(
prompt="Analyze the codebase structure",
options=ClaudeAgentOptions(
system_prompt="You are a code analyst",
max_turns=3,
)
):
print(message)
query() 是單向串流介面:發送提示,接收所有回應。每次查詢獨立,無法在執行中發送後續訊息。適合自動化腳本、CI/CD 流程、批量處理等場景。
值得注意的是,即使是 query(),底層也使用串流模式(--input-format stream-json),因為需要透過 initialize 控制請求發送 Agent 定義等大型配置。
2.2 ClaudeSDKClient — 互動式客戶端
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
async with ClaudeSDKClient(options=ClaudeAgentOptions(
allowed_tools=["Bash", "Read"],
)) as client:
# 第一輪對話
await client.query("What files are in this directory?")
async for msg in client.receive_response():
print(msg)
# 根據回應追問
await client.query("Tell me more about the largest file")
async for msg in client.receive_response():
print(msg)
ClaudeSDKClient 支援雙向通訊、有狀態的對話上下文、任務中斷(await client.interrupt()),以及動態控制——可在對話進行中改變權限模式或模型。額外提供 get_mcp_status()(查詢 MCP 伺服器連線狀態)、rewind_files()(檔案回溯)等高階功能。
三、Agent Loop 與控制協議
回合制執行模型
Agent SDK 的核心是基於回合的(turn-based)執行模型:
使用者提示 -> Claude 思考 -> 工具呼叫 -> 工具執行 -> Claude 評估結果 ->
-> 更多工具呼叫... -> 最終回應 -> ResultMessage
整個過程中,SDK 接收到的訊息類型包括:
- SystemMessage(
subtype: "init"):初始化訊息,包含可用工具與 Agent 列表 - AssistantMessage:Claude 的回應,可包含
TextBlock、ThinkingBlock、ToolUseBlock、ToolResultBlock - ResultMessage:最終結果,包含執行時長、總成本、Token 使用量、會話 ID 等
雙向控制協議
SDK 與 CLI 之間的通訊不僅僅是單向的提示與回應,還包含雙向的控制協議。這是整個架構中最精巧的設計之一。
SDK 發送給 CLI 的控制請求:
initialize:發送 hooks、agents 配置interrupt:中斷當前任務set_permission_mode:改變權限模式set_model:動態切換模型
CLI 發送給 SDK 的控制請求:
can_use_tool:工具權限查詢(需 SDK 回應 allow/deny)hook_callback:觸發 Hook 回呼mcp_message:SDK MCP 伺服器的工具呼叫
每個控制請求都有唯一的 request_id,SDK 使用 anyio.Event 等待對應的回應,超時機制則防止死鎖。核心實作在 _internal/query.py 中的 _read_messages() 方法:
async def _read_messages(self) -> None:
async for message in self.transport.read_messages():
msg_type = message.get("type")
if msg_type == "control_response":
# 路由控制回應到等待中的請求
request_id = response.get("request_id")
if request_id in self.pending_control_responses:
event = self.pending_control_responses[request_id]
self.pending_control_results[request_id] = response
event.set()
elif msg_type == "control_request":
# 處理來自 CLI 的控制請求(permission、hook、mcp)
self._tg.start_soon(self._handle_control_request, request)
elif msg_type == "result":
self._first_result_event.set()
await self._message_send.send(message)
else:
await self._message_send.send(message)
這段程式碼展示了 SDK 如何同時處理常規訊息串流和控制協議——常規訊息進入串流供使用者消費,控制請求則在背景任務中處理。
四、工具系統
4.1 內建工具
Claude Code CLI 提供完整的工具集,可透過選項精確控制:
# 指定可用工具列表
options = ClaudeAgentOptions(tools=["Read", "Glob", "Grep"])
# 使用預設 Claude Code 工具集
options = ClaudeAgentOptions(tools={"type": "preset", "preset": "claude_code"})
# 允許清單(跳過權限提示)
options = ClaudeAgentOptions(allowed_tools=["Bash", "Read"])
# 禁止清單
options = ClaudeAgentOptions(disallowed_tools=["Bash"])
內建工具涵蓋 Bash、Read、Write、Edit、MultiEdit、Glob、Grep、WebFetch、WebSearch 等,幾乎涵蓋了開發場景中所有的檔案與系統操作需求。
4.2 MCP 整合
MCP(Model Context Protocol)整合支援三種伺服器類型。
外部 MCP 伺服器(Stdio / HTTP):
options = ClaudeAgentOptions(
mcp_servers={
"calculator": {
"type": "stdio",
"command": "python",
"args": ["-m", "calculator_server"],
},
"remote": {
"type": "http",
"url": "http://localhost:8080",
"headers": {"Authorization": "Bearer ..."}
}
}
)
SDK MCP 伺服器(進程內,Python SDK 獨有):
from claude_agent_sdk import tool, create_sdk_mcp_server
@tool("add", "Add two numbers", {"a": float, "b": float})
async def add(args):
result = args["a"] + args["b"]
return {"content": [{"type": "text", "text": f"Result: {result}"}]}
server = create_sdk_mcp_server(name="calc", tools=[add])
options = ClaudeAgentOptions(
mcp_servers={"calc": server},
allowed_tools=["mcp__calc__add"],
)
SDK MCP 伺服器是 Python SDK 最獨特的設計。它不透過子進程通訊,而是直接在 Python 進程中執行。CLI 透過控制協議發送 mcp_message 請求,SDK 手動路由 JSONRPC 方法到 MCP Server 實例。這帶來幾個優勢:無需子進程管理、可直接存取應用程式狀態、更好的效能和除錯體驗。
然而原始碼中也標記了一個限制:Python MCP SDK 尚未提供 Transport 抽象(不像 TypeScript 的 server.connect(transport)),迫使 SDK 必須手動路由方法。目前僅支援 initialize、tools/list、tools/call 三種 JSONRPC 方法。
MCP 工具的命名遵循統一格式:mcp__{server_name}__{tool_name}。例如伺服器名 calc、工具名 add 對應 mcp__calc__add。
五、權限模型
權限模式
SDK 提供四種權限模式:
| 模式 | 行為 |
|---|---|
default | 危險工具需要確認 |
acceptEdits | 自動接受檔案編輯 |
plan | 規劃模式(只思考不執行) |
bypassPermissions | 略過所有權限檢查 |
細粒度權限回呼
除了全域模式,SDK 還支援更細粒度的 can_use_tool 回呼:
async def my_permission_callback(
tool_name: str,
input_data: dict,
context: ToolPermissionContext
) -> PermissionResultAllow | PermissionResultDeny:
if tool_name == "Bash" and "rm -rf" in input_data.get("command", ""):
return PermissionResultDeny(message="Dangerous command blocked")
return PermissionResultAllow(
updated_input=modified_input,
updated_permissions=[PermissionUpdate(
type="addRules",
rules=[PermissionRuleValue(tool_name="Bash", rule_content="echo *")],
behavior="allow",
destination="session",
)]
)
這個設計允許開發者在工具執行前攔截、修改輸入,甚至動態新增權限規則。配合 ClaudeSDKClient 的 set_permission_mode(),可以在對話過程中根據情境動態調整權限等級。
六、Hook 系統
Hook 系統是 SDK 中最強大的擴展機制之一,允許開發者在 Agent 生命週期的關鍵節點注入自訂邏輯。
Hook 事件類型
| 事件 | 觸發時機 | 典型用途 |
|---|---|---|
PreToolUse | 工具執行前 | 攔截、修改或阻止工具呼叫 |
PostToolUse | 工具執行後 | 審查工具輸出、提供額外上下文 |
PostToolUseFailure | 工具執行失敗後 | 錯誤處理與恢復 |
UserPromptSubmit | 使用者提示提交時 | 注入額外上下文 |
Stop | Agent 停止時 | 自訂停止行為 |
SubagentStart / SubagentStop | 子代理啟動/停止 | 監控子代理生命週期 |
配置與使用
options = ClaudeAgentOptions(
hooks={
"PreToolUse": [
HookMatcher(
matcher="Bash",
hooks=[check_command],
timeout=30.0,
),
],
"PostToolUse": [
HookMatcher(matcher="Bash", hooks=[review_output]),
],
"UserPromptSubmit": [
HookMatcher(matcher=None, hooks=[add_context]),
],
}
)
Hook 回呼可以返回豐富的控制指令:
# PreToolUse -- 阻止工具呼叫
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Blocked by policy",
"additionalContext": "...",
"updatedInput": {"command": "..."},
}
}
# 控制執行流
return {
"continue_": False,
"stopReason": "Critical error",
"suppressOutput": True,
}
內部實作細節
Hook 的工作流程為:SDK 在 initialize 請求中發送 Hook 配置(包含 matcher 與 callback_id 的映射),CLI 在適當時機發送 control_request(subtype: hook_callback),SDK 查找對應的 Python 函數並執行,最後將結果送回 CLI。
這裡有一個值得注意的細節:Python 的 async 和 continue 是保留關鍵字,SDK 使用 async_ 和 continue_ 作為 Python 端的欄位名,在發送給 CLI 時自動轉換:
def _convert_hook_output_for_cli(hook_output):
converted = {}
for key, value in hook_output.items():
if key == "async_":
converted["async"] = value
elif key == "continue_":
converted["continue"] = value
else:
converted[key] = value
return converted
七、子代理系統
SDK 支援定義專門化的子代理(Subagents),每個子代理擁有獨立的 prompt、工具集和模型設定:
options = ClaudeAgentOptions(
agents={
"code-reviewer": AgentDefinition(
description="Reviews code for best practices",
prompt="You are a code reviewer. Analyze for bugs and security...",
tools=["Read", "Grep"],
model="sonnet",
),
"doc-writer": AgentDefinition(
description="Writes documentation",
prompt="Write clear documentation with examples.",
tools=["Read", "Write", "Edit"],
),
}
)
除了程式化定義,也支援檔案系統定義——在 .claude/agents/ 目錄下放置 Markdown 檔案,需要啟用 setting_sources=["project"] 來載入。
Agent 定義透過 initialize 控制請求以 stdin 串流方式發送給 CLI,而非命令列引數,避免了作業系統的 ARG_MAX 長度限制問題。
八、TypeScript 與 Python 版本比較
功能差異
| 功能 | TypeScript | Python |
|---|---|---|
| v2 Session API | 有(unstable_v2_createSession) | 無 |
| Prompt Suggestions | promptSuggestion() 方法 | 尚未實作 |
| MCP Server 動態管理 | reconnectMcpServer()、toggleMcpServer() | 無 |
| 進程內 MCP 伺服器 | 無 | @tool 裝飾器 + create_sdk_mcp_server() |
| Task 系統 | 支援背景子代理管理 | 無 |
| Schema 驗證 | zod | TypedDict + dataclass |
| CLI 打包 | 分開安裝 | 直接打包在 wheel 中 |
TypeScript SDK 因為版本迭代更快(v0.2.x),在功能覆蓋上領先,尤其是 v2 Session API 提供了更簡潔的多輪對話介面、Task 系統支援背景子代理管理。而 Python SDK 的獨特優勢在於進程內 MCP 伺服器(無需子進程)和 anyio 雙生態支援(同時相容 asyncio 和 trio)。
API 風格對比
// TypeScript -- 使用 Query 物件
const q = await query({
prompt: "Analyze the code",
options: { systemPrompt: "You are a code analyst" }
});
for await (const message of q) {
console.log(message);
}
# Python -- 使用 async iterator
async for message in query(
prompt="Analyze the code",
options=ClaudeAgentOptions(
system_prompt="You are a code analyst"
)
):
print(message)
兩者的設計理念一致,但在語言慣用法上各有所長。Python SDK 因為完全開源,對於需要深入理解內部機制的開發者而言是更好的學習入口。
九、技術亮點
Settings 預設隔離
v0.1.0 引入的破壞性變更:SDK 預設不載入任何 settings(settings.json、CLAUDE.md、斜線命令、子代理)。這個設計決策確保 SDK 應用在任何環境中都有可預測的行為:
# 預設:完全隔離,不載入任何設定
options = ClaudeAgentOptions()
# 明確載入專案設定
options = ClaudeAgentOptions(setting_sources=["user", "project"])
這對 CI/CD、測試、生產環境部署特別重要,避免了因環境差異導致的不可預期行為。
JSON 投機性解碼
Transport 層的一個巧妙設計——面對 CLI 輸出可能截斷長行的問題,使用投機性 JSON 解碼:
json_buffer += json_line
try:
data = json.loads(json_buffer)
json_buffer = ""
yield data
except json.JSONDecodeError:
continue # 繼續累積直到完整 JSON
配合最大 1MB 的緩衝區上限和 anyio.Lock 保護 stdin 寫入,確保了通訊層的穩定性。
費用與資源控制
SDK 提供多維度的資源控制機制:
options = ClaudeAgentOptions(
max_budget_usd=0.10,
max_turns=5,
thinking={"type": "enabled", "budget_tokens": 32000},
effort="high",
)
結合 ResultMessage 中的 total_cost_usd 和 usage 欄位,開發者可以精確追蹤每次 Agent 執行的成本。
十、限制與展望
當前限制
- CLI 進程依賴:SDK 必須依賴 Claude Code CLI 子進程,帶來額外的進程開銷,除錯時需理解兩層架構
- SDK MCP 方法有限:目前只支援
initialize、tools/list、tools/call,不支援 MCP 的 resources、prompts 等進階功能 - 非同步上下文限制:
ClaudeSDKClient不能跨不同的 async 上下文使用 - 取消支援不完整:
control_cancel_request的處理標記為 TODO;Hook 和 Permission 的signal欄位標記為 “Future: abort signal support” - Python 版本落後:Python SDK(v0.1.x)的功能始終略落後 TypeScript SDK(v0.2.x)
架構決策的取捨
以 CLI 作為核心而非直接呼叫 API,是一個具有深遠影響的架構決策。好處是使用者自動繼承 Claude Code 的完整能力、安全機制和工具沙箱,Claude Code 團隊也可以獨立更新 CLI 而不需修改 SDK。代價則是進程管理的複雜度、版本相容性的維護成本,以及除錯時的額外認知負擔。
適用場景
根據 SDK 的設計特點,它特別適合以下場景:
- 自動化工作流:程式碼審查、文件生成、測試生成等需要完整開發工具鏈的任務
- CI/CD 整合:利用 Settings 隔離和費用控制,實現可預測的自動化部署
- 自訂 AI Agent:透過 Hook + MCP 工具 + 子代理系統,建構特定領域的 Agent
- 互動式應用:使用
ClaudeSDKClient建構需要多輪對話的 AI 應用
Claude Agent SDK 展現了 Anthropic 在 Agent 建構領域的一個獨特路線:不是從零開始設計抽象的 Agent 框架,而是將已經在生產環境中驗證過的 Claude Code 能力,透過精心設計的控制協議開放給開發者。這種「先有成熟產品、再抽象出 SDK」的策略,使得 SDK 在工具完整性和穩定性上具有天然優勢,同時也帶來了與 CLI 緊密耦合的架構特質。