Skip to main content
Hooks 是回調函數,在代理事件發生時執行您的程式碼,例如工具被呼叫、會話啟動或執行停止。使用 hooks,您可以:
  • 阻止危險操作在執行前,例如破壞性的 shell 命令或未授權的檔案存取
  • 記錄和稽核工具呼叫以進行合規性、除錯或分析
  • 轉換輸入和輸出以清理資料、注入認證或重定向檔案路徑
  • 要求人工批准敏感操作,例如資料庫寫入或 API 呼叫
  • 追蹤會話生命週期以管理狀態、清理資源或傳送通知

Hook 如何運作

1

事件觸發

agent 執行期間發生某事,SDK 觸發事件:工具即將被呼叫(PreToolUse)、工具返回結果(PostToolUse)、subagent 啟動或停止、agent 閒置或執行完成。請參閱完整事件列表。
2

SDK 收集已註冊的 hook

SDK 檢查為該事件類型註冊的 hook。這包括您在 options.hooks 中傳遞的回呼 hook,以及當相應的 settingSources 或 setting_sources 項目啟用時(預設 query() 選項即為啟用)來自設定檔的 shell 命令 hook。
3

matcher 篩選哪些 hook 執行

如果 hook 有 matcher 模式(例如 "Write|Edit"),SDK 會針對事件的目標(例如工具名稱)測試它。沒有 matcher 的 hook 會針對該類型的每個事件執行。
4

回呼函式執行

每個相符 hook 的回呼函式會接收有關正在發生之事的輸入:工具名稱、其引數、工作階段 ID 以及其他事件特定的詳細資訊。
5

您的回呼返回決定

執行任何操作(日誌、API 呼叫、驗證)後,您的回呼會返回輸出物件,告訴 agent 該做什麼:允許操作、阻止它、修改輸入或將上下文注入對話。
此範例註冊一個 PreToolUse hook(步驟 1),帶有 "Write|Edit" matcher(步驟 3),因此回呼會針對 Write 和 Edit 工具觸發。觸發時,回呼接收工具的輸入(步驟 4),檢查檔案路徑是否指向 .env 檔案,並返回 permissionDecision: "deny" 以阻止操作(步驟 5):
此 hook 會拒絕 file_path 以 /.env 結尾的 Write 或 Edit 呼叫,不分大小寫。在 Windows 上,file_path 使用反斜線,例如 C:\project\.env,因此此 hook 會允許對 C:\project\.env 的 Write 或 Edit 呼叫。
Write|Edit matcher 將此 hook 限制於 Write 和 Edit 工具。如果 Claude 使用 Bash 命令寫入 .env,此 hook 不會執行。若要在沙箱執行的情況下阻止 Bash 寫入檔案,請參閱 Python 或 TypeScript 的沙箱設定。

可用的 hooks

SDK 為代理執行的不同階段提供 hooks。某些 hooks 在兩個 SDK 中都可用,而其他則僅限 TypeScript。

設定 hook

要設定 hook,請在 agent 選項的 hooks 欄位中傳遞它(Python 中的 ClaudeAgentOptions,TypeScript 中的 options 物件)。此程式碼片段假設您已經定義了 hook 回調,例如上面範例中 Python 的 protect_env_files 或 TypeScript 的 protectEnvFiles:
hooks 選項是一個字典(Python)或物件(TypeScript),其中:

Matcher

使用 matcher 篩選您的回調何時觸發。matcher 欄位根據 hook 事件類型比對不同的值。例如,工具型 hook 比對工具名稱,而 Notification hook 比對通知類型。 SDK matcher 遵循與設定檔中的 matcher 相同的規則。該部分記錄了精確字串和正規表達式評估路徑、其版本要求,以及每個事件類型的 matcher 值。 盡可能使用 matcher 模式來針對特定工具。帶有 'Bash' 的 matcher 只針對 Bash 命令執行,而省略模式會針對事件的每次出現執行您的回調。

回調函數

輸入

每個 hook 回調接收三個引數:
  • 輸入資料: 一個包含事件詳細資訊的類型物件。每個 hook 類型都有自己的輸入形狀。例如,PreToolUseHookInput 包括 tool_name 和 tool_input,而 NotificationHookInput 包括 message。請參閱 TypeScript 和 Python SDK 參考中的完整類型定義。
    • 所有 hook 輸入共享 session_id、cwd 和 hook_event_name。
    • 當 hook 在 subagent 內觸發時,agent_id 和 agent_type 會被填充。在 TypeScript 中,這些在基本 hook 輸入上,可供所有 hook 類型使用。在 Python 中,它們是 PreToolUse、PostToolUse、PostToolUseFailure 和 PermissionRequest 上的可選欄位,以及 SubagentStart 和 SubagentStop 上的必需欄位。
  • 工具使用 ID(str | None / string | undefined):關聯同一工具呼叫的 PreToolUse 和 PostToolUse 事件。
  • 上下文: 在 TypeScript 中,包含用於取消的 signal 屬性(AbortSignal)。在 Python 中,此引數保留供將來使用。

輸出

您的回調返回一個具有兩類欄位的物件:
  • 頂級欄位在每個事件上被接受:systemMessage 向使用者顯示訊息,continue(Python 中的 continue_)決定此 hook 後 agent 是否繼續執行。某些事件會捨棄它們或將它們傳遞到其他地方。每個事件的部分在 hook 頁面上說明它們的位置。
  • hookSpecificOutput 控制目前操作。內部的欄位取決於 hook 事件類型:
    • 對於 PreToolUse hook,這是您設定 permissionDecision("allow"、"deny"、"ask" 或 "defer")、permissionDecisionReason 和 updatedInput 的地方。如果您返回 "defer",該回合會以一則 stop_reason 為 "tool_deferred" 的結果訊息結束,以便您可以稍後繼續該呼叫。
    • 對於 PostToolUse hook,您可以設定 additionalContext 以將資訊附加到工具結果。要在 Claude 看到之前替換工具的輸出,請設定 updatedToolOutput,這適用於兩個 SDK 中的任何工具。較舊的 updatedMCPToolOutput 欄位僅替換 MCP 工具輸出。
    • 在 TypeScript SDK 中,PostToolUse 回調也可以返回 classifierContext,這是關於工具呼叫結果的簡短說明,用於自動模式權限分類器。因為您的回調在您應用程式自己的程序中執行,分類器可能會將您在說明中轉達的使用者陳述視為使用者意圖。該欄位需要 TypeScript Agent SDK v0.3.236 或更新版本。為自動模式分類器註解結果涵蓋長度上限、僅同步規則,以及不要在說明中放入的內容。
返回 {} 以允許操作而不進行變更。SDK 回調 hook 使用與 Claude Code shell 命令 hook 相同的 JSON 輸出格式,其記錄每個欄位和事件特定選項。對於 SDK 類型定義,請參閱 TypeScript 和 Python SDK 參考。
當多個 PreToolUse hook 返回不同的決策時,deny 優先於 defer,defer 優先於 ask,ask 優先於 allow。

非同步輸出

預設情況下,agent 在您的 hook 返回前等待。如果您的 hook 執行副作用,例如日誌記錄或傳送 webhook,並且不需要影響 agent 的行為,您可以改為返回非同步輸出。這告訴 agent 立即繼續,無需等待 hook 完成。在此程式碼片段中,Python 中的 send_to_logging_service 和 TypeScript 中的 sendToLoggingService 代表您定義的任何日誌記錄函數:
非同步輸出無法阻止、修改或將上下文注入操作,因為 agent 已經繼續。僅將它們用於副作用,例如日誌記錄、指標或通知。

範例

本節中的幾個範例僅顯示回調函數。若要執行其中一個,請在您的選項的 hooks 欄位中的匹配事件下註冊回調,如 設定 hooks 中所示。

修改工具輸入

此範例攔截 Write 工具呼叫並重寫 file_path 引數以預先加上 /sandbox。回調返回帶有修改路徑的 updatedInput 和 permissionDecision: 'allow' 以自動批准重寫的操作:
將 updatedInput 與 permissionDecision: 'allow' 配對以自動批准修改的輸入,或使用 permissionDecision: 'ask' 以將其顯示給使用者。如果您省略 permissionDecision,修改的輸入仍然適用並流經正常的權限評估。使用 'defer' 時,updatedInput 會被忽略。始終返回新物件,而不是改變原始 tool_input。
若要確認重定向,請將前綴設定為您可以寫入的路徑,例如 ./sandbox 或 /tmp/sandbox(macOS 不允許建立根層級的 /sandbox 目錄),然後要求代理寫入檔案:Write 工具在訊息流中的結果會顯示帶有您的沙箱前綴的路徑,而不是 Claude 要求的路徑。

新增上下文並阻止工具

此範例拒絕 file_path 以 /etc 開頭的工具呼叫,並向模型和使用者解釋原因:
  • permissionDecision: 'deny' 停止工具呼叫。
  • permissionDecisionReason 告訴模型原因。
  • systemMessage 向使用者顯示發生了什麼。
若要確認阻止,請在 PreToolUse 下使用 Write|Edit 匹配器註冊回調,並要求代理在 /etc 下建立檔案:Write 工具在訊息流中的結果包含 Writing to /etc is not allowed,且不會建立任何檔案。

自動批准特定工具

預設情況下,agent 可能在使用某些工具前提示權限。此範例透過返回 permissionDecision: 'allow' 自動批准唯讀檔案系統工具(Read、Glob、Grep),讓它們無需使用者確認即可執行(從網路路徑讀取除外),同時讓所有其他工具受到正常權限檢查:

註冊多個 hooks

當事件觸發時,符合的 hook 會並行執行。對於權限決定,以最嚴格的結果為準。任一 hook 的 deny 都會阻止工具呼叫。由於完成順序是不確定的,請編寫每個 hook 以獨立運作,而不是依賴另一個 hook 已先執行。 下面的範例註冊三個獨立檢查,每個都省略 matcher。範例中的 hook 名稱,例如 Python 中的 audit_logger 或 TypeScript 中的 auditLogger,代表您定義的回調:

使用多工具匹配器篩選

使用多工具匹配器在相關工具間共享一個回調。此範例註冊三個具有不同範圍的匹配器,每個 hook 它命名代表您定義的回調:
  • 管道分隔的精確列表(Write|Edit|NotebookEdit)針對 Write、Edit 和 NotebookEdit 工具觸發 file_security_hook。
  • 正規表達式(^mcp__)針對任何名稱以 mcp__ 開頭的 MCP 工具觸發 mcp_audit_hook。
  • 省略的 matcher 觸發 global_logger,不依工具名稱篩選。

追蹤子代理活動

使用 SubagentStop hooks 監控子代理何時完成其工作。請參閱 TypeScript 和 Python SDK 參考中的完整輸入類型。此範例在每次子代理完成時記錄摘要:
若要確認 hook 觸發,請註冊回調並要求代理將小任務委派給子代理,例如列出目前目錄中的檔案:當子代理完成時,回調會列印 [SUBAGENT] Completed: 行,其中包含子代理的 ID 和文字記錄路徑。

從 hooks 發出 HTTP 請求

Hooks 可以執行非同步操作,例如 HTTP 請求。在您的 hook 內捕捉錯誤,而不是讓它們傳播。 此範例在每個工具完成後傳送 webhook,記錄哪個工具執行以及何時執行。hook 捕捉來自失敗 webhook 的錯誤:
若要確認 hook 觸發,請將 webhook URL 指向您可以監視的端點並傳送使用工具的提示:hook 會在每個工具完成後傳送帶有工具名稱和時間戳記的 POST。

將通知轉發到 Slack

使用 Notification hooks 接收來自代理的系統通知並將其轉發到外部服務。在 SDK 工作階段中,Claude Code 為以下通知類型執行此 hook:
  • permission_prompt 一旦權限請求在您的 canUseTool 回調 上等待約六秒。需要 TypeScript Agent SDK v0.3.233 或更新版本,或 Python Agent SDK v0.2.139 或更新版本
  • elicitation_complete 和 elicitation_response 用於使用者提示引導流程
Claude Code 從 SDK 工作階段不執行的互動式 UI 發出其他類型,例如 idle_prompt、auth_success 和 elicitation_dialog。 每個通知都包括帶有人類可讀描述的 message 欄位,以及可選的 title。 此範例將每個通知轉發到 Slack 頻道。它需要 Slack 傳入 webhook URL,您可以通過將應用程式新增到 Slack 工作區並啟用傳入 webhooks 來建立:
當 Notification 事件觸發時,hook 會將通知的 message(前綴為 Agent status:)發佈到您的 webhook 目標的頻道。

修復常見問題

Hook 未觸發

  • 驗證 hook 事件名稱正確且區分大小寫(PreToolUse,而不是 preToolUse)
  • 檢查您的 matcher 模式是否與工具名稱完全匹配
  • 確保 hook 在 options.hooks 中的正確事件類型下
  • 對於支援 matcher 的非工具 hook,如 Notification 和 SubagentStop,matcher 匹配不同的欄位,而 Stop 完全忽略 matcher(請參閱 matcher 模式)
  • 當 agent 達到 max_turns 限制時,hook 可能不會觸發,因為工作階段在 hook 可以執行前結束

Matcher 未按預期篩選

Matcher 只匹配工具名稱,不匹配檔案路徑或其他引數。要按檔案路徑篩選,請在您的 hook 內檢查 tool_input.file_path:

Hook 逾時

Claude Code 以逾時時間執行每個回調,您可以在其 HookMatcher 上使用 timeout 欄位以秒為單位設定。當您未設定時,Claude Code 使用事件的預設值:大多數事件為 600 秒,UserPromptSubmit、PreModelSwitch 和 PostModelSwitch 為 30 秒,MessageDisplay 為 10 秒。Claude Code 在關閉期間執行 SessionEnd 回調,使用較短的 SessionEnd 逾時預算,預設為 1.5 秒。 當回調超過其逾時時間時,Claude Code 取消它並捨棄其輸出,工作階段繼續而不是掛起。接下來發生的情況取決於事件:
  • PreToolUse:Claude Code 阻止工具呼叫。取而代之的是,Claude 收到工具結果,說明 hook 未在逾時前回應,回合繼續。在 v2.1.210 之前,Claude Code 將逾時報告給 Claude 作為使用者拒絕,這使無人值守工作階段停止並等待輸入。
  • PostToolUse 和 PostToolUseFailure:Claude Code 保留工具結果,回合繼續。
  • UserPromptSubmit 和 UserPromptExpansion:Claude Code 以指出 hook 名稱和逾時的訊息阻止提示詞,工作階段繼續。在 v2.1.208 之前,當這些事件上的回調逾時時,Claude Code 以 error_during_execution 結束查詢。
  • Stop 和 SubagentStop:逾時的回調計為不返回任何決定。Agent 或 subagent 停止,如同該回調已允許它,而您其他 hook 在該事件上的決定仍然適用。在 Claude Code v2.1.273 之前,逾時的 Stop 或 SubagentStop 回調計為失敗的 hook 執行,Claude Code 捨棄您其他 hook 在該事件上的決定。
  • SessionStart:逾時的回調計為不返回任何輸出,工作階段繼續,使用您其他 SessionStart hook 的輸出。
  • PreModelSwitch:Claude Code 阻止模型切換。未回答的 hook 尚未核准切換。
  • 其他事件,如 Notification、PreCompact 和 PostModelSwitch:Claude Code 記錄失敗並繼續。
主工作階段中 Stop 或 SessionStart 回調首次逾時時,Claude Code 也會新增 SDKInformationalMessage 到訊息流,說明驅動工作階段的應用程式未回應。稍後的逾時在您的應用程式保持無回應時不會重複該訊息。 如果您在回調待處理時中斷查詢,Claude Code 取消待處理的工具呼叫。在 v2.1.208 之前,如果您在待處理的 PreToolUse 回調期間中斷,工具呼叫仍可能繼續進行。 如果您的回調需要更多時間,請在其 HookMatcher 上設定更高的 timeout。在 TypeScript 中,使用第三個回調引數中的 AbortSignal 以在逾時觸發時優雅地處理取消。

工具意外被阻止

  • 檢查所有 PreToolUse hook 是否返回 permissionDecision: 'deny'
  • 將日誌新增到您的 hook 以查看它們返回的 permissionDecisionReason
  • 驗證 matcher 模式不會太寬泛:空 matcher 匹配所有工具

修改的輸入未應用

  • 確保 updatedInput 在 hookSpecificOutput 內,而不是在頂級:
  • 不要將 updatedInput 與 permissionDecision: 'defer' 配對,這會捨棄修改的輸入。省略 permissionDecision 是可以的:修改的輸入仍通過正常權限評估應用。您也可以返回 'allow' 以自動核准修改的輸入或 'ask' 以向使用者顯示以供核准
  • 在 hookSpecificOutput 中包括 hookEventName 以識別輸出適用於哪個 hook 類型

Python 中不可用工作階段 hook

SessionStart 和 SessionEnd 可以在 TypeScript 中註冊為 SDK 回調 hook,但在 Python SDK 中不可用,因為其 HookEvent 類型省略它們。在 Python 中,它們僅作為shell 命令 hook在設定檔中定義,例如 .claude/settings.json。您的 SDK 應用程式載入哪些設定檔取決於 setting_sources 或 settingSources。如果您設定了該選項,請包括存放 hook 的來源:
要改為執行初始化邏輯作為 Python SDK 回調,請使用 client.receive_response() 的第一條訊息作為您的觸發器。

Subagent 權限提示倍增

生成多個 subagent 時,每個 subagent 可能會分別請求其自身工具呼叫的權限。要避免重複提示,請使用 PreToolUse hook 自動核准特定工具,或設定權限規則,subagent 會從父對話繼承這些規則。

Subagent 的遞迴 hook 迴圈

生成 subagent 的 UserPromptSubmit hook 如果這些 subagent 觸發相同的 hook,可能會建立無限迴圈。要防止這種情況:
  • 使用共享變數或工作階段狀態來追蹤您是否已在 subagent 內
  • 將 hook 範圍限制為僅針對頂級 agent 工作階段執行

systemMessage 未出現在輸出中

systemMessage 欄位向使用者顯示訊息,而不是模型。在 Claude Code v2.1.227 或更新版本上,hook 的 systemMessage 可以在訊息流中呈現為 SDKInformationalMessage。它是否呈現取決於事件。hooks 頁面上每個事件的部分說明輸出如何呈現。要改為將上下文傳遞給模型,請返回 additionalContext。 在 v2.1.227 之前,SDK 僅針對 SessionStart 和 Setup hook 在訊息流中呈現 hook 輸出。對於任何其他事件,輸出僅出現在 includeHookEvents(Python 中的 include_hook_events)新增的生命週期事件中。該選項的條目涵蓋每個 hook 事件產生的生命週期事件。 如果您需要可靠地將 hook 決定呈現給您的應用程式,請分別記錄它們或使用專用輸出頻道。