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.49v0.1.39
原始碼閉源(npm 封裝發布)開源(完整原始碼在 GitHub)
非同步庫原生 Promise/asyncanyio(相容 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 的回應,可包含 TextBlockThinkingBlockToolUseBlockToolResultBlock
  • 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 必須手動路由方法。目前僅支援 initializetools/listtools/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",
        )]
    )

這個設計允許開發者在工具執行前攔截、修改輸入,甚至動態新增權限規則。配合 ClaudeSDKClientset_permission_mode(),可以在對話過程中根據情境動態調整權限等級。


六、Hook 系統

Hook 系統是 SDK 中最強大的擴展機制之一,允許開發者在 Agent 生命週期的關鍵節點注入自訂邏輯。

Hook 事件類型

事件觸發時機典型用途
PreToolUse工具執行前攔截、修改或阻止工具呼叫
PostToolUse工具執行後審查工具輸出、提供額外上下文
PostToolUseFailure工具執行失敗後錯誤處理與恢復
UserPromptSubmit使用者提示提交時注入額外上下文
StopAgent 停止時自訂停止行為
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 的 asynccontinue 是保留關鍵字,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 版本比較

功能差異

功能TypeScriptPython
v2 Session API有(unstable_v2_createSession
Prompt SuggestionspromptSuggestion() 方法尚未實作
MCP Server 動態管理reconnectMcpServer()toggleMcpServer()
進程內 MCP 伺服器@tool 裝飾器 + create_sdk_mcp_server()
Task 系統支援背景子代理管理
Schema 驗證zodTypedDict + 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.jsonCLAUDE.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_usdusage 欄位,開發者可以精確追蹤每次 Agent 執行的成本。


十、限制與展望

當前限制

  1. CLI 進程依賴:SDK 必須依賴 Claude Code CLI 子進程,帶來額外的進程開銷,除錯時需理解兩層架構
  2. SDK MCP 方法有限:目前只支援 initializetools/listtools/call,不支援 MCP 的 resources、prompts 等進階功能
  3. 非同步上下文限制:ClaudeSDKClient 不能跨不同的 async 上下文使用
  4. 取消支援不完整:control_cancel_request 的處理標記為 TODO;Hook 和 Permission 的 signal 欄位標記為 “Future: abort signal support”
  5. 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 緊密耦合的架構特質。