agent-sdk/hooks.md +17 −17
24 </Step>24 </Step>
25 25
26 <Step title="SDK が登録されたフックを収集する">26 <Step title="SDK が登録されたフックを収集する">
2727 SDK は、そのイベントタイプに登録されたフックをチェックします。これには、`options.hooks` に渡すコールバックフックと、対応する [`settingSources`](/ja/agent-sdk/typescript#setting-source) または [`setting_sources`](/ja/agent-sdk/python#setting-source) エントリが有効になっているときの設定ファイルからのシェルコマンドフックが含まれます。これはデフォルトの `query()` オプションで有効になっています。 SDK は、そのイベントタイプに登録されたフックをチェックします。これには、`options.hooks` に渡すコールバックフックと、対応する [`settingSources`](/ja/agent-sdk/typescript#settingsource) または [`setting_sources`](/ja/agent-sdk/python#settingsource) エントリが有効になっているときの設定ファイルからのシェルコマンドフックが含まれます。これはデフォルトの `query()` オプションで有効になっています。
28 </Step>28 </Step>
29 29
30 <Step title="マッチャーがどのフックを実行するかをフィルタリングする">30 <Step title="マッチャーがどのフックを実行するかをフィルタリングする">
225 225
226すべてのフックコールバックは 3 つの引数を受け取ります。226すべてのフックコールバックは 3 つの引数を受け取ります。
227 227
228228* **入力データ:** イベント詳細を含む型付きオブジェクト。各フック型には独自の入力形状があります(たとえば、`PreToolUseHookInput` には `tool_name` と `tool_input` が含まれ、`NotificationHookInput` には `message` が含まれます)。[TypeScript](/ja/agent-sdk/typescript#hook-input) および [Python](/ja/agent-sdk/python#hook-input) SDK リファレンスで完全な型定義を参照してください。* **入力データ:** イベント詳細を含む型付きオブジェクト。各フック型には独自の入力形状があります(たとえば、`PreToolUseHookInput` には `tool_name` と `tool_input` が含まれ、`NotificationHookInput` には `message` が含まれます)。[TypeScript](/ja/agent-sdk/typescript#hookinput) および [Python](/ja/agent-sdk/python#hookinput) SDK リファレンスで完全な型定義を参照してください。
229 * すべてのフック入力は `session_id`、`cwd`、および `hook_event_name` を共有します。229 * すべてのフック入力は `session_id`、`cwd`、および `hook_event_name` を共有します。
230 * `agent_id` と `agent_type` は、フックがサブエージェント内で発火するときに入力されます。TypeScript では、これらはベースフック入力にあり、すべてのフック型で利用可能です。Python では、`PreToolUse`、`PostToolUse`、および `PostToolUseFailure` のみにあります。230 * `agent_id` と `agent_type` は、フックがサブエージェント内で発火するときに入力されます。TypeScript では、これらはベースフック入力にあり、すべてのフック型で利用可能です。Python では、`PreToolUse`、`PostToolUse`、および `PostToolUseFailure` のみにあります。
231* **ツール使用 ID**(`str | None` / `string | undefined`):同じツール呼び出しの `PreToolUse` と `PostToolUse` イベントを相関させます。231* **ツール使用 ID**(`str | None` / `string | undefined`):同じツール呼び出しの `PreToolUse` と `PostToolUse` イベントを相関させます。
236コールバックは 2 つのカテゴリのフィールドを持つオブジェクトを返します。236コールバックは 2 つのカテゴリのフィールドを持つオブジェクトを返します。
237 237
238* **トップレベルフィールド**は会話を制御します。`systemMessage` はモデルに表示される会話にメッセージを注入し、`continue`(Python では `continue_`)はこのフック後にエージェントが実行を続けるかどうかを決定します。238* **トップレベルフィールド**は会話を制御します。`systemMessage` はモデルに表示される会話にメッセージを注入し、`continue`(Python では `continue_`)はこのフック後にエージェントが実行を続けるかどうかを決定します。
239239* **`hookSpecificOutput`** は現在の操作を制御します。内部のフィールドはフックイベントタイプに依存します。`PreToolUse` フックの場合、ここで `permissionDecision`(`"allow"`、`"deny"`、または `"ask"`)、`permissionDecisionReason`、および `updatedInput` を設定します。TypeScript SDK では、`permissionDecision` は `"defer"` も受け入れて、クエリを終了し[後で再開](/ja/hooks#defer-a-tool-call-for-later)します。この値は Python SDK では利用できません。`PostToolUse` フックの場合、`additionalContext` を設定してツール結果に情報を追加できます。または `updatedToolOutput` を設定して、Claude がそれを見る前にツールの出力全体を置き換えることができます。* **`hookSpecificOutput`** は現在の操作を制御します。内部のフィールドはフックイベントタイプに依存します。`PreToolUse` フックの場合、ここで `permissionDecision`(`"allow"`、`"deny"`、`"ask"`、または `"defer"`)、`permissionDecisionReason`、および `updatedInput` を設定します。`"defer"` を返すとクエリが終了し、[後で再開](/ja/hooks#defer-a-tool-call-for-later)できます。`PostToolUse` フックの場合、`additionalContext` を設定してツール結果に情報を追加できます。または `updatedToolOutput` を設定して、Claude がそれを見る前にツールの出力全体を置き換えることができます。
240 240
241241変更なしで操作を許可するには `{}` を返します。SDK コールバックフックは、[Claude Code シェルコマンドフック](/ja/hooks#json-output)と同じ JSON 出力形式を使用します。これはすべてのフィールドとイベント固有のオプションを文書化しています。SDK 型定義については、[TypeScript](/ja/agent-sdk/typescript#sync-hook-json-output) および [Python](/ja/agent-sdk/python#sync-hook-json-output) SDK リファレンスを参照してください。変更なしで操作を許可するには `{}` を返します。SDK コールバックフックは、[Claude Code シェルコマンドフック](/ja/hooks#json-output)と同じ JSON 出力形式を使用します。これはすべてのフィールドとイベント固有のオプションを文書化しています。SDK 型定義については、[TypeScript](/ja/agent-sdk/typescript#synchookjsonoutput) および [Python](/ja/agent-sdk/python#synchookjsonoutput) SDK リファレンスを参照してください。
242 242
243<Note>243<Note>
244 複数のフックまたはパーミッションルールが適用される場合、**deny** は **defer** より優先され、**defer** は **ask** より優先され、**ask** は **allow** より優先されます。いずれかのフックが `deny` を返す場合、他のフックに関係なく操作はブロックされます。244 複数のフックまたはパーミッションルールが適用される場合、**deny** は **defer** より優先され、**defer** は **ask** より優先され、**ask** は **allow** より優先されます。いずれかのフックが `deny` を返す場合、他のフックに関係なく操作はブロックされます。
326</CodeGroup>326</CodeGroup>
327 327
328<Note>328<Note>
329329 `updatedInput` を使用する場合、`permissionDecision: 'allow'` も含める必要があります。元の `tool_input` を変更するのではなく、常に新しいオブジェクトを返します。 `updatedInput` を使用する場合、`permissionDecision: 'allow'` を含めて変更された入力を自動承認するか、`permissionDecision: 'ask'` を含めてユーザーに表示する必要があります。`'defer'` の場合、`updatedInput` は無視されます。常に元の `tool_input` を変更するのではなく、新しいオブジェクトを返します。
330</Note>330</Note>
331 331
332### コンテキストを追加してツールをブロックする332### コンテキストを追加してツールをブロックする
489 489
490### サブエージェントアクティビティを追跡する490### サブエージェントアクティビティを追跡する
491 491
492492`SubagentStop` フックを使用して、サブエージェントが作業を完了するときを監視します。[TypeScript](/ja/agent-sdk/typescript#hook-input) および [Python](/ja/agent-sdk/python#hook-input) SDK リファレンスで完全な入力型を参照してください。この例は、サブエージェントが完了するたびに概要をログします。`SubagentStop` フックを使用して、サブエージェントが作業を完了するときを監視します。[TypeScript](/ja/agent-sdk/typescript#hookinput) および [Python](/ja/agent-sdk/python#hookinput) SDK リファレンスで完全な入力型を参照してください。この例は、サブエージェントが完了するたびに概要をログします。
493 493
494<CodeGroup>494<CodeGroup>
495 ```python Python theme={null}495 ```python Python theme={null}
621 621
622### 通知を Slack に転送する622### 通知を Slack に転送する
623 623
624624`Notification` フックを使用して、エージェントからのシステム通知を受け取り、外部サービスに転送します。通知は特定のイベントタイプに対して発火します。`permission_prompt`(Claude がパーミッションを必要とする)、`idle_prompt`(Claude が入力を待機している)、`auth_success`(認証が完了した)、および `elicitation_dialog`(Claude がユーザーにプロンプトを表示している)です。各通知には、人間が読める説明を含む `message` フィールドと、オプションで `title` が含まれます。`Notification` フックを使用して、エージェントからのシステム通知を受け取り、外部サービスに転送します。通知は特定のイベントタイプに対して発火します。`permission_prompt`(Claude がパーミッションを必要とする)、`idle_prompt`(Claude が入力を待機している)、`auth_success`(認証が完了した)、`elicitation_dialog`(Claude がユーザーにプロンプトを表示している)、`elicitation_response`(ユーザーが質問に答えた)、および `elicitation_complete`(質問が閉じられた)です。各通知には、人間が読める説明を含む `message` フィールドと、オプションで `title` が含まれます。
625 625
626この例は、すべての通知を Slack チャネルに転送します。[Slack 受信ウェブフック URL](https://api.slack.com/messaging/webhooks) が必要です。これは、Slack ワークスペースにアプリを追加し、受信ウェブフックを有効にすることで作成します。626この例は、すべての通知を Slack チャネルに転送します。[Slack 受信ウェブフック URL](https://api.slack.com/messaging/webhooks) が必要です。これは、Slack ワークスペースにアプリを追加し、受信ウェブフックを有効にすることで作成します。
627 627
727* マッチャーパターンがツール名と正確にマッチしていることを確認します727* マッチャーパターンがツール名と正確にマッチしていることを確認します
728* フックが `options.hooks` の正しいイベントタイプの下にあることを確認します728* フックが `options.hooks` の正しいイベントタイプの下にあることを確認します
729* `Stop` や `SubagentStop` などの非ツールフックの場合、マッチャーは異なるフィールドに対してマッチングされます([マッチャーパターン](/ja/hooks#matcher-patterns)を参照)729* `Stop` や `SubagentStop` などの非ツールフックの場合、マッチャーは異なるフィールドに対してマッチングされます([マッチャーパターン](/ja/hooks#matcher-patterns)を参照)
730730* エージェントが [`max_turns`](/ja/agent-sdk/python#claude-agent-options) 制限に達するとセッションが終了する前にフックが実行される可能性があるため、フックが発火しない場合があります* エージェントが [`max_turns`](/ja/agent-sdk/python#claudeagentoptions) 制限に達するとセッションが終了する前にフックが実行される可能性があるため、フックが発火しない場合があります
731 731
732### マッチャーが期待どおりにフィルタリングしない732### マッチャーが期待どおりにフィルタリングしない
733 733
734734マッチャーは**ツール名**のみをマッチングし、ファイルパスやその他の引数はマッチングしません。ファイルパスでフィルタリングするには、フック内で `tool_input.file_path` をチェックします。マッチャーは**ツール名**のみをマッチングし、ファイルパスやその他の引数はマッチングしません。ファイルパスでフィルタリングするには、フック内で `tool_input.file_path` をチェックします:
735 735
736```typescript theme={null}736```typescript theme={null}
737const myHook: HookCallback = async (input, toolUseID, { signal }) => {737const myHook: HookCallback = async (input, toolUseID, { signal }) => {
738 const preInput = input as PreToolUseHookInput;738 const preInput = input as PreToolUseHookInput;
739 const toolInput = preInput.tool_input as Record<string, unknown>;739 const toolInput = preInput.tool_input as Record<string, unknown>;
740 const filePath = toolInput?.file_path as string;740 const filePath = toolInput?.file_path as string;
741741 if (!filePath?.endsWith(".md")) return {}; // マークダウンファイル以外をスキップする if (!filePath?.endsWith(".md")) return {}; // マークダウンファイル以外をスキップ
742742 // マークダウンファイルを処理する... // マークダウンファイルを処理...
743 return {};743 return {};
744};744};
745```745```
751 751
752### ツールが予期せずブロックされた752### ツールが予期せずブロックされた
753 753
754754* `PreToolUse` フックすべてで `permissionDecision: 'deny'` を返していないかチェックします* すべての `PreToolUse` フックで `permissionDecision: 'deny'` を返していないかチェックします
755* フックにログを追加して、返している `permissionDecisionReason` を確認します755* フックにログを追加して、返している `permissionDecisionReason` を確認します
756* マッチャーパターンが広すぎないことを確認します(空のマッチャーはすべてのツールにマッチングします)756* マッチャーパターンが広すぎないことを確認します(空のマッチャーはすべてのツールにマッチングします)
757 757
758### 変更された入力が適用されない758### 変更された入力が適用されない
759 759
760760* `updatedInput` が `hookSpecificOutput` の内部にあり、トップレベルにないことを確認します。* `updatedInput` が `hookSpecificOutput` の内部にあり、トップレベルにないことを確認します:
761 761
762 ```typescript theme={null}762 ```typescript theme={null}
763 return {763 return {
769 };769 };
770 ```770 ```
771 771
772772* 入力変更を有効にするには、`permissionDecision: 'allow'` も返す必要があります* 入力変更を有効にするには、`permissionDecision: 'allow'` または `'ask'` も返す必要があります
773 773
774* `hookSpecificOutput` に `hookEventName` を含めて、出力がどのフック型用かを識別します774* `hookSpecificOutput` に `hookEventName` を含めて、出力がどのフック型用かを識別します
775 775
776### Python でセッションフックが利用できない776### Python でセッションフックが利用できない
777 777
778778`SessionStart` と `SessionEnd` は TypeScript で SDK コールバックフックとして登録できますが、Python SDK では利用できません(`HookEvent` は除外されています)。Python では、設定ファイルで定義された[シェルコマンドフック](/ja/hooks#hook-events)としてのみ利用可能です(たとえば、`.claude/settings.json`)。SDK アプリケーションからシェルコマンドフックをロードするには、[`setting_sources`](/ja/agent-sdk/python#setting-source) または [`settingSources`](/ja/agent-sdk/typescript#setting-source) で適切な設定ソースを含めます。`SessionStart` と `SessionEnd` は TypeScript で SDK コールバックフックとして登録できますが、Python SDK では利用できません(`HookEvent` は除外されています)。Python では、設定ファイルで定義された[シェルコマンドフック](/ja/hooks#hook-events)としてのみ利用可能です(たとえば、`.claude/settings.json`)。SDK アプリケーションからシェルコマンドフックをロードするには、[`setting_sources`](/ja/agent-sdk/python#settingsource) または [`settingSources`](/ja/agent-sdk/typescript#settingsource) で適切な設定ソースを含めます:
779 779
780<CodeGroup>780<CodeGroup>
781 ```python Python theme={null}781 ```python Python theme={null}
782 options = ClaudeAgentOptions(782 options = ClaudeAgentOptions(
783783 setting_sources=["project"], # フックを含む .claude/settings.json をロードする setting_sources=["project"], # フックを含む .claude/settings.json をロード
784 )784 )
785 ```785 ```
786 786
787 ```typescript TypeScript theme={null}787 ```typescript TypeScript theme={null}
788 const options = {788 const options = {
789789 settingSources: ["project"] // フックを含む .claude/settings.json をロードする settingSources: ["project"] // フックを含む .claude/settings.json をロード
790 };790 };
791 ```791 ```
792</CodeGroup>792</CodeGroup>