agent-sdk/hooks.md +71 −71
15* **追蹤會話生命週期**以管理狀態、清理資源或傳送通知15* **追蹤會話生命週期**以管理狀態、清理資源或傳送通知
16 16
17<h2 id="how-hooks-work">17<h2 id="how-hooks-work">
1818 Hooks 如何工作 Hook 如何運作
19</h2>19</h2>
20 20
21<Steps>21<Steps>
22 <Step title="事件觸發">22 <Step title="事件觸發">
2323 代理執行期間發生某事,SDK 觸發事件:工具即將被呼叫(`PreToolUse`)、工具返回結果(`PostToolUse`)、子代理啟動或停止、代理空閒或執行完成。請參閱[完整事件列表](#available-hooks)。 agent 執行期間發生某事,SDK 觸發事件:工具即將被呼叫(`PreToolUse`)、工具返回結果(`PostToolUse`)、subagent 啟動或停止、agent 閒置或執行完成。請參閱[完整事件列表](#available-hooks)。
24 </Step>24 </Step>
25 25
2626 <Step title="SDK 收集已註冊的 hooks"> <Step title="SDK 收集已註冊的 hook">
2727 SDK 檢查為該事件類型註冊的 hooks。這包括您在 `options.hooks` 中傳遞的回調 hooks 和來自設定檔案的 shell 命令 hooks,當相應的 [`settingSources`](/docs/zh-TW/agent-sdk/typescript#settingsource) 或 [`setting_sources`](/docs/zh-TW/agent-sdk/python#settingsource) 項目啟用時(預設 `query()` 選項就是這樣)。 SDK 檢查為該事件類型註冊的 hook。這包括您在 `options.hooks` 中傳遞的回呼 hook,以及當相應的 [`settingSources`](/docs/zh-TW/agent-sdk/typescript#settingsource) 或 [`setting_sources`](/docs/zh-TW/agent-sdk/python#settingsource) 項目啟用時(預設 `query()` 選項即為啟用)來自設定檔的 shell 命令 hook。
28 </Step>28 </Step>
29 29
3030 <Step title="匹配器篩選哪些 hooks 執行"> <Step title="matcher 篩選哪些 hook 執行">
3131 如果 hook 有 [`matcher`](#matchers) 模式(例如 `"Write|Edit"`),SDK 會針對事件的目標(例如工具名稱)測試它。沒有匹配器的 hooks 會針對該類型的每個事件執行。 如果 hook 有 [`matcher`](#matchers) 模式(例如 `"Write|Edit"`),SDK 會針對事件的目標(例如工具名稱)測試它。沒有 matcher 的 hook 會針對該類型的每個事件執行。
32 </Step>32 </Step>
33 33
3434 <Step title="回調函數執行"> <Step title="回呼函式執行">
3535 每個匹配的 hook 的[回調函數](#callback-functions)接收有關正在發生的事情的輸入:工具名稱、其參數、會話 ID 和其他事件特定的詳細資訊。 每個相符 hook 的[回呼函式](#callback-functions)會接收有關正在發生之事的輸入:工具名稱、其引數、工作階段 ID 以及其他事件特定的詳細資訊。
36 </Step>36 </Step>
37 37
3838 <Step title="您的回調返回決定"> <Step title="您的回呼返回決定">
3939 執行任何操作(記錄、API 呼叫、驗證)後,您的回調返回[輸出物件](#outputs),告訴代理該做什麼:允許操作、阻止它、修改輸入或將上下文注入對話。 執行任何操作(日誌、API 呼叫、驗證)後,您的回呼會返回[輸出物件](#outputs),告訴 agent 該做什麼:允許操作、阻止它、修改輸入或將上下文注入對話。
40 </Step>40 </Step>
41</Steps>41</Steps>
42 42
4343以下範例將這些步驟組合在一起。它註冊一個 `PreToolUse` hook(步驟 1),帶有 `"Write|Edit"` 匹配器(步驟 3),因此回調只針對檔案寫入工具觸發。觸發時,回調接收工具的輸入(步驟 4),檢查檔案路徑是否針對 `.env` 檔案,並返回 `permissionDecision: "deny"` 以阻止操作(步驟 5):以下範例將這些步驟組合在一起。它註冊一個 `PreToolUse` hook(步驟 1),帶有 `"Write|Edit"` matcher(步驟 3),因此回呼只針對檔案寫入工具觸發。觸發時,回呼接收工具的輸入(步驟 4),檢查檔案路徑是否指向 `.env` 檔案,並返回 `permissionDecision: "deny"` 以阻止操作(步驟 5):
44 44
45<CodeGroup>45<CodeGroup>
46 ```python Python theme={null}46 ```python Python theme={null}
54 )54 )
55 55
56 56
5757 # 定義一個接收工具呼叫詳細資訊的 hook 回調 # 定義一個接收工具呼叫詳細資訊的 hook 回呼
58 async def protect_env_files(input_data, tool_use_id, context):58 async def protect_env_files(input_data, tool_use_id, context):
5959 # 從工具的輸入參數中提取檔案路徑 # 從工具的輸入引數中提取檔案路徑
60 file_path = input_data["tool_input"].get("file_path", "")60 file_path = input_data["tool_input"].get("file_path", "")
61 file_name = file_path.split("/")[-1]61 file_name = file_path.split("/")[-1]
62 62
6363 # 如果針對 .env 檔案,阻止操作 # 如果指向 .env 檔案,阻止操作
64 if file_name == ".env":64 if file_name == ".env":
65 return {65 return {
66 "hookSpecificOutput": {66 "hookSpecificOutput": {
78 options = ClaudeAgentOptions(78 options = ClaudeAgentOptions(
79 hooks={79 hooks={
80 # 為 PreToolUse 事件註冊 hook80 # 為 PreToolUse 事件註冊 hook
8181 # 匹配器篩選為僅 Write 和 Edit 工具呼叫 # matcher 篩選為僅 Write 和 Edit 工具呼叫
82 "PreToolUse": [HookMatcher(matcher="Write|Edit", hooks=[protect_env_files])]82 "PreToolUse": [HookMatcher(matcher="Write|Edit", hooks=[protect_env_files])]
83 }83 }
84 )84 )
97 ```typescript TypeScript theme={null}97 ```typescript TypeScript theme={null}
98 import { query, HookCallback, PreToolUseHookInput } from "@anthropic-ai/claude-agent-sdk";98 import { query, HookCallback, PreToolUseHookInput } from "@anthropic-ai/claude-agent-sdk";
99 99
100100 // 使用 HookCallback 類型定義 hook 回調 // 使用 HookCallback 類型定義 hook 回呼
101 const protectEnvFiles: HookCallback = async (input, toolUseID, { signal }) => {101 const protectEnvFiles: HookCallback = async (input, toolUseID, { signal }) => {
102 // 將輸入轉換為特定 hook 類型以確保類型安全102 // 將輸入轉換為特定 hook 類型以確保類型安全
103 const preInput = input as PreToolUseHookInput;103 const preInput = input as PreToolUseHookInput;
107 const filePath = toolInput?.file_path as string;107 const filePath = toolInput?.file_path as string;
108 const fileName = filePath?.split("/").pop();108 const fileName = filePath?.split("/").pop();
109 109
110110 // 如果針對 .env 檔案,阻止操作 // 如果指向 .env 檔案,阻止操作
111 if (fileName === ".env") {111 if (fileName === ".env") {
112 return {112 return {
113 hookSpecificOutput: {113 hookSpecificOutput: {
127 options: {127 options: {
128 hooks: {128 hooks: {
129 // 為 PreToolUse 事件註冊 hook129 // 為 PreToolUse 事件註冊 hook
130130 // 匹配器篩選為僅 Write 和 Edit 工具呼叫 // matcher 篩選為僅 Write 和 Edit 工具呼叫
131 PreToolUse: [{ matcher: "Write|Edit", hooks: [protectEnvFiles] }]131 PreToolUse: [{ matcher: "Write|Edit", hooks: [protectEnvFiles] }]
132 }132 }
133 }133 }
140 ```140 ```
141</CodeGroup>141</CodeGroup>
142 142
143143當您執行任一指令碼時,Claude 嘗試建立 `.env` 檔案,hook 拒絕工具呼叫,Claude 的最終回應說明它無法建立 `.env` 檔案。當您執行任一指令碼時,Claude 會嘗試建立 `.env` 檔案,而 hook 會拒絕該工具呼叫。
144 144
145<h2 id="available-hooks">145<h2 id="available-hooks">
146 可用的 hooks146 可用的 hooks
179| `ConfigChange` | 否 | 是 | 設定檔案變更 | 動態重新載入設定 |179| `ConfigChange` | 否 | 是 | 設定檔案變更 | 動態重新載入設定 |
180| `InstructionsLoaded` | 否 | 是 | `CLAUDE.md` 或規則檔案載入到上下文中 | 審計哪些指令檔案載入 |180| `InstructionsLoaded` | 否 | 是 | `CLAUDE.md` 或規則檔案載入到上下文中 | 審計哪些指令檔案載入 |
181| `WorktreeCreate` | 否 | 是 | Git worktree 已建立 | 追蹤隔離的工作區 |181| `WorktreeCreate` | 否 | 是 | Git worktree 已建立 | 追蹤隔離的工作區 |
182182| `WorktreeRemove` | 否 | 是 | Git worktree 已移除 | 清理工作區資源 || `WorktreeRemove` | 否 | 是 | 正在移除由 `WorktreeCreate` hook 建立的 worktree | 清理工作區資源 |
183| `CwdChanged` | 否 | 是 | 會話期間工作目錄變更 | 按目錄重新載入環境變數 |183| `CwdChanged` | 否 | 是 | 會話期間工作目錄變更 | 按目錄重新載入環境變數 |
184| `FileChanged` | 否 | 是 | 監視的檔案被修改、建立或刪除 | 當專案檔案變更時重新載入設定 |184| `FileChanged` | 否 | 是 | 監視的檔案被修改、建立或刪除 | 當專案檔案變更時重新載入設定 |
185| `DirectoryAdded` | 否 | 是 | 會話期間新增工作目錄 | 為中途新增的儲存庫安裝相依性 |185| `DirectoryAdded` | 否 | 是 | 會話期間新增工作目錄 | 為中途新增的儲存庫安裝相依性 |
186 186
187<h2 id="configure-hooks">187<h2 id="configure-hooks">
188188 配置 hooks 設定 hook
189</h2>189</h2>
190 190
191191要配置 hook,請在代理選項的 `hooks` 欄位中傳遞它(Python 中的 `ClaudeAgentOptions`,TypeScript 中的 `options` 物件)。此程式碼片段假設您已經定義了 hook 回調,例如上面範例中 Python 的 `protect_env_files` 或 TypeScript 的 `protectEnvFiles`:要設定 hook,請在 agent 選項的 `hooks` 欄位中傳遞它(Python 中的 `ClaudeAgentOptions`,TypeScript 中的 `options` 物件)。此程式碼片段假設您已經定義了 hook 回調,例如上面範例中 Python 的 `protect_env_files` 或 TypeScript 的 `protectEnvFiles`:
192 192
193<CodeGroup>193<CodeGroup>
194 ```python Python theme={null}194 ```python Python theme={null}
219`hooks` 選項是一個字典(Python)或物件(TypeScript),其中:219`hooks` 選項是一個字典(Python)或物件(TypeScript),其中:
220 220
221* **鍵**:[hook 事件名稱](#available-hooks),例如 `'PreToolUse'`、`'PostToolUse'` 和 `'Stop'`221* **鍵**:[hook 事件名稱](#available-hooks),例如 `'PreToolUse'`、`'PostToolUse'` 和 `'Stop'`
222222* **值**:[匹配器](#matchers)的陣列,每個都包含可選的篩選模式和您的[回調函數](#callback-functions)* **值**:[matcher](#matchers) 的陣列,每個都包含可選的篩選模式和您的[回調函數](#callback-functions)
223 223
224<h3 id="matchers">224<h3 id="matchers">
225225 匹配器 Matcher
226</h3>226</h3>
227 227
228228使用匹配器篩選您的回調何時觸發。`matcher` 欄位根據 hook 事件類型匹配不同的值。例如,工具型 hooks 匹配工具名稱,而 `Notification` hooks 匹配通知類型。使用 matcher 篩選您的回調何時觸發。`matcher` 欄位根據 hook 事件類型比對不同的值。例如,工具型 hook 比對工具名稱,而 `Notification` hook 比對通知類型。
229 229
230230SDK 匹配器遵循與[設定檔案中的匹配器](/docs/zh-TW/hooks#matcher-patterns)相同的規則。該部分記錄了精確字串和正規表達式評估路徑、其版本要求,以及每個事件類型的匹配器值。SDK matcher 遵循與[設定檔中的 matcher](/docs/zh-TW/hooks#matcher-patterns) 相同的規則。該部分記錄了精確字串和正規表達式評估路徑、其版本要求,以及每個事件類型的 matcher 值。
231 231
232| 選項 | 類型 | 預設值 | 描述 |232| 選項 | 類型 | 預設值 | 描述 |
233| - | - | - | - |233| - | - | - | - |
234234| `matcher` | `string` | `undefined` | 針對事件的篩選欄位匹配的模式,遵循[設定檔案中匹配器的規則](/docs/zh-TW/hooks#matcher-patterns)。對於工具 hooks,這是工具名稱。內建工具包括 `Bash`、`Read`、`Write`、`Edit`、`Glob`、`Grep`、`WebFetch`、`Agent` 等(請參閱[工具輸入類型](/docs/zh-TW/agent-sdk/typescript#tool-input-types)以取得完整列表)。MCP 工具使用模式 `mcp__<server>__<action>`,其中 `<server>` 是您在 `mcpServers` 配置中使用的鍵。 || `matcher` | `string` | `undefined` | 針對事件的篩選欄位比對的模式,遵循[設定檔中 matcher 的規則](/docs/zh-TW/hooks#matcher-patterns)。對於工具 hook,這是工具名稱。內建工具包括 `Bash`、`Read`、`Write`、`Edit`、`Glob`、`Grep`、`WebFetch`、`Agent` 等(請參閱[工具輸入類型](/docs/zh-TW/agent-sdk/typescript#tool-input-types)以取得完整列表)。MCP 工具使用模式 `mcp__<server>__<action>`,其中 `<server>` 是您在 `mcpServers` 設定中使用的鍵。 |
235235| `hooks` | `HookCallback[]` | - | 必需。當模式匹配時執行的回調函數陣列 || `hooks` | `HookCallback[]` | - | 必需。當模式比對成功時執行的回調函數陣列 |
236236| `timeout` | `number` | `undefined` | 超時時間(秒)。省略時,Claude Code 會應用[事件的預設超時](#hook-timeout)。您的 SDK 回調遵循 `command` hook 預設值 || `timeout` | `number` | `undefined` | 逾時時間(秒)。省略時,Claude Code 會套用[事件的預設逾時](#hook-timeout)。您的 SDK 回調遵循 `command` hook 預設值 |
237 237
238238盡可能使用 `matcher` 模式來針對特定工具。帶有 `'Bash'` 的匹配器只針對 Bash 命令執行,而省略模式會針對事件的每次出現執行您的回調。故意省略它以記錄您的會話進行的每個工具呼叫。盡可能使用 `matcher` 模式來針對特定工具。帶有 `'Bash'` 的 matcher 只針對 Bash 命令執行,而省略模式會針對事件的每次出現執行您的回調。故意省略它以記錄您的工作階段進行的每個工具呼叫。
239 239
240<h3 id="callback-functions">240<h3 id="callback-functions">
241 回調函數241 回調函數
245 輸入245 輸入
246</h4>246</h4>
247 247
248248每個 hook 回調接收三個參數:每個 hook 回調接收三個引數:
249 249
250* **輸入資料:** 一個包含事件詳細資訊的類型物件。每個 hook 類型都有自己的輸入形狀。例如,`PreToolUseHookInput` 包括 `tool_name` 和 `tool_input`,而 `NotificationHookInput` 包括 `message`。請參閱 [TypeScript](/docs/zh-TW/agent-sdk/typescript#hookinput) 和 [Python](/docs/zh-TW/agent-sdk/python#hookinput) SDK 參考中的完整類型定義。250* **輸入資料:** 一個包含事件詳細資訊的類型物件。每個 hook 類型都有自己的輸入形狀。例如,`PreToolUseHookInput` 包括 `tool_name` 和 `tool_input`,而 `NotificationHookInput` 包括 `message`。請參閱 [TypeScript](/docs/zh-TW/agent-sdk/typescript#hookinput) 和 [Python](/docs/zh-TW/agent-sdk/python#hookinput) SDK 參考中的完整類型定義。
251 * 所有 hook 輸入共享 `session_id`、`cwd` 和 `hook_event_name`。251 * 所有 hook 輸入共享 `session_id`、`cwd` 和 `hook_event_name`。
252252 * 當 hook 在子代理內觸發時,`agent_id` 和 `agent_type` 會被填充。在 TypeScript 中,這些在基本 hook 輸入上,可供所有 hook 類型使用。在 Python 中,它們是 `PreToolUse`、`PostToolUse`、`PostToolUseFailure` 和 `PermissionRequest` 上的可選欄位,以及 `SubagentStart` 和 `SubagentStop` 上的必需欄位。 * 當 hook 在 subagent 內觸發時,`agent_id` 和 `agent_type` 會被填充。在 TypeScript 中,這些在基本 hook 輸入上,可供所有 hook 類型使用。在 Python 中,它們是 `PreToolUse`、`PostToolUse`、`PostToolUseFailure` 和 `PermissionRequest` 上的可選欄位,以及 `SubagentStart` 和 `SubagentStop` 上的必需欄位。
253* **工具使用 ID**(`str | None` / `string | undefined`):關聯同一工具呼叫的 `PreToolUse` 和 `PostToolUse` 事件。253* **工具使用 ID**(`str | None` / `string | undefined`):關聯同一工具呼叫的 `PreToolUse` 和 `PostToolUse` 事件。
254254* **上下文:** 在 TypeScript 中,包含用於取消的 `signal` 屬性(`AbortSignal`)。在 Python 中,此參數保留供將來使用。* **上下文:** 在 TypeScript 中,包含用於取消的 `signal` 屬性(`AbortSignal`)。在 Python 中,此引數保留供將來使用。
255 255
256<h4 id="outputs">256<h4 id="outputs">
257 輸出257 輸出
259 259
260您的回調返回一個具有兩類欄位的物件:260您的回調返回一個具有兩類欄位的物件:
261 261
262262* **頂級欄位**在每個事件上被接受:`systemMessage` 向使用者顯示訊息,`continue`(Python 中的 `continue_`)決定此 hook 後代理是否繼續執行。某些事件會捨棄它們或將它們傳遞到其他地方。每個[事件的部分](/docs/zh-TW/hooks#hook-events)在 hooks 頁面上說明它們的位置。* **頂級欄位**在每個事件上被接受:`systemMessage` 向使用者顯示訊息,`continue`(Python 中的 `continue_`)決定此 hook 後 agent 是否繼續執行。某些事件會捨棄它們或將它們傳遞到其他地方。每個[事件的部分](/docs/zh-TW/hooks#hook-events)在 hook 頁面上說明它們的位置。
263* **`hookSpecificOutput`** 控制目前操作。內部的欄位取決於 hook 事件類型:263* **`hookSpecificOutput`** 控制目前操作。內部的欄位取決於 hook 事件類型:
264 * 對於 `PreToolUse` hook,這是您設定 `permissionDecision`(`"allow"`、`"deny"`、`"ask"` 或 `"defer"`)、`permissionDecisionReason` 和 `updatedInput` 的地方。如果您返回 `"defer"`,該回合會以一則 `stop_reason` 為 `"tool_deferred"` 的結果訊息結束,以便您可以[稍後繼續該呼叫](/docs/zh-TW/hooks#defer-a-tool-call-for-later)。264 * 對於 `PreToolUse` hook,這是您設定 `permissionDecision`(`"allow"`、`"deny"`、`"ask"` 或 `"defer"`)、`permissionDecisionReason` 和 `updatedInput` 的地方。如果您返回 `"defer"`,該回合會以一則 `stop_reason` 為 `"tool_deferred"` 的結果訊息結束,以便您可以[稍後繼續該呼叫](/docs/zh-TW/hooks#defer-a-tool-call-for-later)。
265265 * 對於 `PostToolUse` hook,您可以設定 `additionalContext` 以將資訊附加到工具結果。要在 Claude 看到之前替換工具的輸出,請設定 `updatedToolOutput`,這適用於兩個 SDK 中的任何工具。較舊的 `updatedMCPToolOutput` 欄位僅替換 MCP 工具輸出,已被棄用。 * 對於 `PostToolUse` hook,您可以設定 `additionalContext` 以將資訊附加到工具結果。要在 Claude 看到之前替換工具的輸出,請設定 `updatedToolOutput`,這適用於兩個 SDK 中的任何工具。較舊的 `updatedMCPToolOutput` 欄位僅替換 MCP 工具輸出。
266 * 在 TypeScript SDK 中,`PostToolUse` 回調也可以返回 `classifierContext`,這是關於工具呼叫結果的簡短說明,用於[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)權限分類器。因為您的回調在您應用程式自己的程序中執行,分類器可能會將您在說明中轉達的使用者陳述視為使用者意圖。該欄位需要 TypeScript Agent SDK v0.3.236 或更新版本。[為自動模式分類器註解結果](/docs/zh-TW/hooks#annotate-a-result-for-the-auto-mode-classifier)涵蓋長度上限、僅同步規則,以及不要在說明中放入的內容。266 * 在 TypeScript SDK 中,`PostToolUse` 回調也可以返回 `classifierContext`,這是關於工具呼叫結果的簡短說明,用於[自動模式](/docs/zh-TW/permission-modes#eliminate-prompts-with-auto-mode)權限分類器。因為您的回調在您應用程式自己的程序中執行,分類器可能會將您在說明中轉達的使用者陳述視為使用者意圖。該欄位需要 TypeScript Agent SDK v0.3.236 或更新版本。[為自動模式分類器註解結果](/docs/zh-TW/hooks#annotate-a-result-for-the-auto-mode-classifier)涵蓋長度上限、僅同步規則,以及不要在說明中放入的內容。
267 267
268268返回 `{}` 以允許操作而不進行變更。SDK 回調 hooks 使用與 [Claude Code shell 命令 hooks](/docs/zh-TW/hooks#json-output) 相同的 JSON 輸出格式,其記錄每個欄位和事件特定選項。對於 SDK 類型定義,請參閱 [TypeScript](/docs/zh-TW/agent-sdk/typescript#synchookjsonoutput) 和 [Python](/docs/zh-TW/agent-sdk/python#synchookjsonoutput) SDK 參考。返回 `{}` 以允許操作而不進行變更。SDK 回調 hook 使用與 [Claude Code shell 命令 hook](/docs/zh-TW/hooks#json-output) 相同的 JSON 輸出格式,其記錄每個欄位和事件特定選項。對於 SDK 類型定義,請參閱 [TypeScript](/docs/zh-TW/agent-sdk/typescript#synchookjsonoutput) 和 [Python](/docs/zh-TW/agent-sdk/python#synchookjsonoutput) SDK 參考。
269 269
270<Note>270<Note>
271271 當多個 hooks 或權限規則適用時,`deny` 優先於 `defer`,`defer` 優先於 `ask`,`ask` 優先於 `allow`。如果任何 hook 返回 `deny`,操作將被阻止,無論其他 hooks 如何。 當多個 hook 或權限規則適用時,`deny` 優先於 `defer`,`defer` 優先於 `ask`,`ask` 優先於 `allow`。如果任何 hook 返回 `deny`,操作將被阻止,無論其他 hook 如何。
272</Note>272</Note>
273 273
274<h4 id="asynchronous-output">274<h4 id="asynchronous-output">
275 非同步輸出275 非同步輸出
276</h4>276</h4>
277 277
278278預設情況下,代理在您的 hook 返回前等待。如果您的 hook 執行副作用,例如記錄或傳送 webhook,並且不需要影響代理的行為,您可以改為返回非同步輸出。這告訴代理立即繼續,無需等待 hook 完成。在此程式碼片段中,Python 中的 `send_to_logging_service` 和 TypeScript 中的 `sendToLoggingService` 代表您定義的任何記錄函數:預設情況下,agent 在您的 hook 返回前等待。如果您的 hook 執行副作用,例如日誌記錄或傳送 webhook,並且不需要影響 agent 的行為,您可以改為返回非同步輸出。這告訴 agent 立即繼續,無需等待 hook 完成。在此程式碼片段中,Python 中的 `send_to_logging_service` 和 TypeScript 中的 `sendToLoggingService` 代表您定義的任何日誌記錄函數:
279 279
280<CodeGroup>280<CodeGroup>
281 ```python Python theme={null}281 ```python Python theme={null}
296 296
297| 欄位 | 類型 | 描述 |297| 欄位 | 類型 | 描述 |
298| - | - | - |298| - | - | - |
299299| `async` | `true` | 表示非同步模式。代理無需等待即可繼續。在 Python 中,使用 `async_` 以避免保留關鍵字。 || `async` | `true` | 表示非同步模式。agent 無需等待即可繼續。在 Python 中,使用 `async_` 以避免保留關鍵字。 |
300300| `asyncTimeout` | `number` | 背景操作的可選超時時間(毫秒) || `asyncTimeout` | `number` | 背景操作的可選逾時時間(毫秒) |
301 301
302<Note>302<Note>
303303 非同步輸出無法阻止、修改或將上下文注入操作,因為代理已經繼續。僅將它們用於副作用,例如記錄、指標或通知。 非同步輸出無法阻止、修改或將上下文注入操作,因為 agent 已經繼續。僅將它們用於副作用,例如日誌記錄、指標或通知。
304</Note>304</Note>
305 305
306<h2 id="examples">306<h2 id="examples">
802</h3>802</h3>
803 803
804* 驗證 hook 事件名稱正確且區分大小寫(`PreToolUse`,而不是 `preToolUse`)804* 驗證 hook 事件名稱正確且區分大小寫(`PreToolUse`,而不是 `preToolUse`)
805805* 檢查您的匹配器模式是否與工具名稱完全匹配* 檢查您的 matcher 模式是否與工具名稱完全匹配
806* 確保 hook 在 `options.hooks` 中的正確事件類型下806* 確保 hook 在 `options.hooks` 中的正確事件類型下
807807* 對於支援匹配器的非工具 hooks,如 `Notification` 和 `SubagentStop`,匹配器匹配不同的欄位,而 `Stop` 完全忽略匹配器(請參閱[匹配器模式](/docs/zh-TW/hooks#matcher-patterns))* 對於支援 matcher 的非工具 hook,如 `Notification` 和 `SubagentStop`,matcher 匹配不同的欄位,而 `Stop` 完全忽略 matcher(請參閱 [matcher 模式](/docs/zh-TW/hooks#matcher-patterns))
808808* 當代理達到 [`max_turns`](/docs/zh-TW/agent-sdk/python#claudeagentoptions) 限制時,hooks 可能不會觸發,因為會話在 hooks 可以執行前結束* 當 agent 達到 [`max_turns`](/docs/zh-TW/agent-sdk/python#claudeagentoptions) 限制時,hook 可能不會觸發,因為工作階段在 hook 可以執行前結束
809 809
810<h3 id="matcher-not-filtering-as-expected">810<h3 id="matcher-not-filtering-as-expected">
811811 匹配器未按預期篩選 Matcher 未按預期篩選
812</h3>812</h3>
813 813
814814匹配器只匹配工具名稱,不匹配檔案路徑或其他參數。要按檔案路徑篩選,請在您的 hook 內檢查 `tool_input.file_path`:Matcher 只匹配工具名稱,不匹配檔案路徑或其他引數。要按檔案路徑篩選,請在您的 hook 內檢查 `tool_input.file_path`:
815 815
816```typescript theme={null}816```typescript theme={null}
817const myHook: HookCallback = async (input, toolUseID, { signal }) => {817const myHook: HookCallback = async (input, toolUseID, { signal }) => {
825```825```
826 826
827<h3 id="hook-timeout">827<h3 id="hook-timeout">
828828 Hook 超時 Hook 逾時
829</h3>829</h3>
830 830
831831Claude Code 以超時時間執行每個回調,您可以在其 `HookMatcher` 上使用 `timeout` 欄位以秒為單位設定。當您未設定時,Claude Code 使用事件的預設值:大多數事件為 600 秒,`UserPromptSubmit`、`PreModelSwitch` 和 `PostModelSwitch` 為 30 秒,`MessageDisplay` 為 10 秒。Claude Code 在關閉期間執行 `SessionEnd` 回調,使用較短的 [SessionEnd 超時預算](/docs/zh-TW/hooks#sessionend-input),預設為 1.5 秒。Claude Code 以逾時時間執行每個回調,您可以在其 `HookMatcher` 上使用 `timeout` 欄位以秒為單位設定。當您未設定時,Claude Code 使用事件的預設值:大多數事件為 600 秒,`UserPromptSubmit`、`PreModelSwitch` 和 `PostModelSwitch` 為 30 秒,`MessageDisplay` 為 10 秒。Claude Code 在關閉期間執行 `SessionEnd` 回調,使用較短的 [SessionEnd 逾時預算](/docs/zh-TW/hooks#sessionend-input),預設為 1.5 秒。
832 832
833833當回調超過其超時時間時,Claude Code 取消它並捨棄其輸出,會話繼續而不是掛起。接下來發生的情況取決於事件:當回調超過其逾時時間時,Claude Code 取消它並捨棄其輸出,工作階段繼續而不是掛起。接下來發生的情況取決於事件:
834 834
835835* `PreToolUse`:Claude Code 不執行工具呼叫,Claude 收到工具結果,說明 hook 未在超時前回應,轉換繼續。如果另一個 `PreToolUse` hook 返回明確拒絕,Claude 改為收到該拒絕而不是超時錯誤。在 v2.1.210 之前,Claude Code 將超時報告給 Claude 作為使用者拒絕,這使無人值守會話停止並等待輸入。* `PreToolUse`:Claude Code 不執行工具呼叫,Claude 收到工具結果,說明 hook 未在逾時前回應,回合繼續。如果另一個 `PreToolUse` hook 返回明確拒絕,Claude 改為收到該拒絕而不是逾時錯誤。在 v2.1.210 之前,Claude Code 將逾時報告給 Claude 作為使用者拒絕,這使無人值守工作階段停止並等待輸入。
836836* `PostToolUse` 和 `PostToolUseFailure`:Claude Code 保留工具結果,轉換繼續。* `PostToolUse` 和 `PostToolUseFailure`:Claude Code 保留工具結果,回合繼續。
837837* `UserPromptSubmit` 和 [`UserPromptExpansion`](/docs/zh-TW/hooks#userpromptexpansion):Claude Code 以命名 hook 和超時的訊息阻止提示,會話繼續。因為這些事件上的回調可以充當政策閘門,Claude Code 永遠不會讓超時的提示通過未篩選。在 v2.1.208 之前,當這些事件上的回調超時時,Claude Code 以 `error_during_execution` 結束查詢。* `UserPromptSubmit` 和 [`UserPromptExpansion`](/docs/zh-TW/hooks#userpromptexpansion):Claude Code 以指出 hook 名稱和逾時的訊息阻止提示詞,工作階段繼續。因為這些事件上的回調可以充當政策閘門,Claude Code 永遠不會讓逾時的提示詞未經篩選就通過。在 v2.1.208 之前,當這些事件上的回調逾時時,Claude Code 以 `error_during_execution` 結束查詢。
838838* `Stop` 和 `SubagentStop`:超時的回調計為不返回任何決定。代理或子代理停止,如同該回調已允許它,而您其他 hooks 在事件上的決定仍然適用。在 Claude Code v2.1.273 之前,超時的 `Stop` 或 `SubagentStop` 回調計為失敗的 hook 執行,Claude Code 捨棄您其他 hooks 在事件上的決定。* `Stop` 和 `SubagentStop`:逾時的回調計為不返回任何決定。Agent 或 subagent 停止,如同該回調已允許它,而您其他 hook 在該事件上的決定仍然適用。在 Claude Code v2.1.273 之前,逾時的 `Stop` 或 `SubagentStop` 回調計為失敗的 hook 執行,Claude Code 捨棄您其他 hook 在該事件上的決定。
839839* `SessionStart`:超時的回調計為不返回任何輸出,會話繼續,使用您其他 `SessionStart` hooks 的輸出。* `SessionStart`:逾時的回調計為不返回任何輸出,工作階段繼續,使用您其他 `SessionStart` hook 的輸出。
840840* `PreModelSwitch`:Claude Code 阻止模型切換。未回答的 hook 尚未批准切換。* `PreModelSwitch`:Claude Code 阻止模型切換。未回答的 hook 尚未核准切換。
841* 其他事件,如 `Notification`、`PreCompact` 和 `PostModelSwitch`:Claude Code 記錄失敗並繼續。841* 其他事件,如 `Notification`、`PreCompact` 和 `PostModelSwitch`:Claude Code 記錄失敗並繼續。
842 842
843843主會話中 `Stop` 或 `SessionStart` 回調首次超時時,Claude Code 也會新增 [`SDKInformationalMessage`](/docs/zh-TW/agent-sdk/typescript#sdkinformationalmessage) 到訊息流,說明驅動會話的應用程式未回應。稍後的超時在您的應用程式保持無回應時不會重複該訊息。主工作階段中 `Stop` 或 `SessionStart` 回調首次逾時時,Claude Code 也會新增 [`SDKInformationalMessage`](/docs/zh-TW/agent-sdk/typescript#sdkinformationalmessage) 到訊息流,說明驅動工作階段的應用程式未回應。稍後的逾時在您的應用程式保持無回應時不會重複該訊息。
844 844
845如果您在回調待處理時中斷查詢,Claude Code 取消待處理的工具呼叫。在 v2.1.208 之前,如果您在待處理的 `PreToolUse` 回調期間中斷,工具呼叫仍可能繼續進行。845如果您在回調待處理時中斷查詢,Claude Code 取消待處理的工具呼叫。在 v2.1.208 之前,如果您在待處理的 `PreToolUse` 回調期間中斷,工具呼叫仍可能繼續進行。
846 846
847847如果您的回調需要更多時間,請在其 `HookMatcher` 上設定更高的 `timeout`。在 TypeScript 中,使用第三個回調參數中的 `AbortSignal` 以在超時觸發時優雅地處理取消。如果您的回調需要更多時間,請在其 `HookMatcher` 上設定更高的 `timeout`。在 TypeScript 中,使用第三個回調引數中的 `AbortSignal` 以在逾時觸發時優雅地處理取消。
848 848
849<h3 id="tool-blocked-unexpectedly">849<h3 id="tool-blocked-unexpectedly">
850 工具意外被阻止850 工具意外被阻止
851</h3>851</h3>
852 852
853853* 檢查所有 `PreToolUse` hooks 是否返回 `permissionDecision: 'deny'`* 檢查所有 `PreToolUse` hook 是否返回 `permissionDecision: 'deny'`
854854* 將記錄新增到您的 hooks 以查看它們返回的 `permissionDecisionReason`* 將日誌新增到您的 hook 以查看它們返回的 `permissionDecisionReason`
855855* 驗證匹配器模式不會太寬泛:空匹配器匹配所有工具* 驗證 matcher 模式不會太寬泛:空 matcher 匹配所有工具
856 856
857<h3 id="modified-input-not-applied">857<h3 id="modified-input-not-applied">
858 修改的輸入未應用858 修改的輸入未應用
870 };870 };
871 ```871 ```
872 872
873873* 不要將 `updatedInput` 與 `permissionDecision: 'defer'` 配對,這會捨棄修改的輸入。省略 `permissionDecision` 是可以的:修改的輸入仍通過正常權限評估應用。您也可以返回 `'allow'` 以自動批准修改的輸入或 `'ask'` 以向使用者顯示以供批准* 不要將 `updatedInput` 與 `permissionDecision: 'defer'` 配對,這會捨棄修改的輸入。省略 `permissionDecision` 是可以的:修改的輸入仍通過正常權限評估應用。您也可以返回 `'allow'` 以自動核准修改的輸入或 `'ask'` 以向使用者顯示以供核准
874 874
875* 在 `hookSpecificOutput` 中包括 `hookEventName` 以識別輸出適用於哪個 hook 類型875* 在 `hookSpecificOutput` 中包括 `hookEventName` 以識別輸出適用於哪個 hook 類型
876 876
877<h3 id="session-hooks-not-available-in-python">877<h3 id="session-hooks-not-available-in-python">
878878 Python 中不可用會話 hooks Python 中不可用工作階段 hook
879</h3>879</h3>
880 880
881881`SessionStart` 和 `SessionEnd` 可以在 TypeScript 中註冊為 SDK 回調 hooks,但在 Python SDK 中不可用,因為其 `HookEvent` 類型省略它們。在 Python 中,它們僅作為[shell 命令 hooks](/docs/zh-TW/hooks#hook-events)在設定檔案中定義,例如 `.claude/settings.json`。要從您的 SDK 應用程式載入 shell 命令 hooks,請使用 [`setting_sources`](/docs/zh-TW/agent-sdk/python#settingsource) 或 [`settingSources`](/docs/zh-TW/agent-sdk/typescript#settingsource) 包括適當的設定來源:`SessionStart` 和 `SessionEnd` 可以在 TypeScript 中註冊為 SDK 回調 hook,但在 Python SDK 中不可用,因為其 `HookEvent` 類型省略它們。在 Python 中,它們僅作為[shell 命令 hook](/docs/zh-TW/hooks#hook-events)在設定檔中定義,例如 `.claude/settings.json`。您的 SDK 應用程式載入哪些設定檔取決於 [`setting_sources`](/docs/zh-TW/agent-sdk/python#settingsource) 或 [`settingSources`](/docs/zh-TW/agent-sdk/typescript#settingsource)。如果您設定了該選項,請包括存放 hook 的來源:
882 882
883<CodeGroup>883<CodeGroup>
884 ```python Python theme={null}884 ```python Python theme={null}
897要改為執行初始化邏輯作為 Python SDK 回調,請使用 `client.receive_response()` 的第一條訊息作為您的觸發器。897要改為執行初始化邏輯作為 Python SDK 回調,請使用 `client.receive_response()` 的第一條訊息作為您的觸發器。
898 898
899<h3 id="subagent-permission-prompts-multiplying">899<h3 id="subagent-permission-prompts-multiplying">
900900 子代理權限提示倍增 Subagent 權限提示倍增
901</h3>901</h3>
902 902
903903生成多個子代理時,每個子代理可能會分別請求其自身工具呼叫的權限。要避免重複提示,請使用 `PreToolUse` hooks 自動批准特定工具,或配置權限規則,子代理[從父對話繼承](/docs/zh-TW/sub-agents#permission-modes)。生成多個 subagent 時,每個 subagent 可能會分別請求其自身工具呼叫的權限。要避免重複提示,請使用 `PreToolUse` hook 自動核准特定工具,或設定權限規則,subagent 會[從父對話繼承](/docs/zh-TW/sub-agents#permission-modes)這些規則。
904 904
905<h3 id="recursive-hook-loops-with-subagents">905<h3 id="recursive-hook-loops-with-subagents">
906906 子代理的遞迴 hook 迴圈 Subagent 的遞迴 hook 迴圈
907</h3>907</h3>
908 908
909909生成子代理的 `UserPromptSubmit` hook 如果這些子代理觸發相同的 hook,可能會建立無限迴圈。要防止這種情況:生成 subagent 的 `UserPromptSubmit` hook 如果這些 subagent 觸發相同的 hook,可能會建立無限迴圈。要防止這種情況:
910 910
911911* 使用共享變數或會話狀態來追蹤您是否已在子代理內* 使用共享變數或工作階段狀態來追蹤您是否已在 subagent 內
912912* 將 hooks 範圍限制為僅針對頂級代理會話執行* 將 hook 範圍限制為僅針對頂級 agent 工作階段執行
913 913
914<h3 id="systemmessage-not-appearing-in-output">914<h3 id="systemmessage-not-appearing-in-output">
915 systemMessage 未出現在輸出中915 systemMessage 未出現在輸出中
916</h3>916</h3>
917 917
918918`systemMessage` 欄位向使用者顯示訊息,而不是模型。在 Claude Code v2.1.227 或更新版本上,hook 的 `systemMessage` 可以在訊息流中呈現為 [`SDKInformationalMessage`](/docs/zh-TW/agent-sdk/typescript#sdkinformationalmessage)。它是否呈現取決於事件。每個[事件的部分](/docs/zh-TW/hooks#hook-events)在 hooks 頁面上說明輸出如何呈現。要改為將上下文傳遞給模型,請返回 [`additionalContext`](/docs/zh-TW/hooks#add-context-for-claude)。`systemMessage` 欄位向使用者顯示訊息,而不是模型。在 Claude Code v2.1.227 或更新版本上,hook 的 `systemMessage` 可以在訊息流中呈現為 [`SDKInformationalMessage`](/docs/zh-TW/agent-sdk/typescript#sdkinformationalmessage)。它是否呈現取決於事件。hooks 頁面上每個[事件的部分](/docs/zh-TW/hooks#hook-events)說明輸出如何呈現。要改為將上下文傳遞給模型,請返回 [`additionalContext`](/docs/zh-TW/hooks#add-context-for-claude)。
919 919
920920在 v2.1.227 之前,SDK 僅針對 `SessionStart` 和 `Setup` hooks 在訊息流中呈現 hook 輸出。對於任何其他事件,輸出僅出現在 [`includeHookEvents`](/docs/zh-TW/agent-sdk/typescript#options)(Python 中的 `include_hook_events`)新增的生命週期事件中。該選項的條目涵蓋每個 hook 事件產生的生命週期事件。在 v2.1.227 之前,SDK 僅針對 `SessionStart` 和 `Setup` hook 在訊息流中呈現 hook 輸出。對於任何其他事件,輸出僅出現在 [`includeHookEvents`](/docs/zh-TW/agent-sdk/typescript#options)(Python 中的 `include_hook_events`)新增的生命週期事件中。該選項的條目涵蓋每個 hook 事件產生的生命週期事件。
921 921
922如果您需要可靠地將 hook 決定呈現給您的應用程式,請分別記錄它們或使用專用輸出頻道。922如果您需要可靠地將 hook 決定呈現給您的應用程式,請分別記錄它們或使用專用輸出頻道。
923 923