1. はじめに

前編では Custom Agent と Agent Skills によるペルソナ・能力の定義を紹介しました。本記事を作成した背景は、instructions や Custom Agent だけでは「AI の行動の前後に確実にコードを実行する」という品質ゲートを保証できないことです。本記事の目的は、Agent Hooks(Preview)を使い、エージェントのライフサイクルにコマンド実行を差し込む方法を解説することです。

instructions や Custom Agent は「AI に何をさせるか」を指示する仕組みです。一方 Hooks は「AI の行動の前後にコードを実行する」仕組みです。フォーマッターの自動実行や危険コマンドのブロックなど、指示だけでは保証できない品質ゲートを組み込めます。

2. 概要: Hooks で何ができるか

Agent Hooks のライフサイクルイベント

Hooks は以下の 8 イベントで発火します(VS Code: Agent hooks 公式ドキュメントより)[^vscode-hooks]。

イベントタイミング代表的な用途
SessionStartセッション開始時環境情報の注入
UserPromptSubmitプロンプト送信時監査ログの記録
PreToolUseツール実行前危険操作のブロック
PostToolUseツール実行後フォーマッター・リンター
PreCompactコンテキスト圧縮前重要情報の退避
SubagentStartサブエージェント起動リソース初期化
SubagentStopサブエージェント終了結果の集約
Stopセッション終了時レポート生成

3. セットアップ

3.1 ステップ 1: 基本の Hook を作る

.github/hooks/format.json を作成します。

json
{
  "hooks": {
    "PostToolUse": [
      {
        "type": "command",
        "command": "./scripts/format-changed-files.sh",
        "timeout": 30
      }
    ]
  }
}

保存するだけで VS Code が自動検出します。Hook は標準入力(stdin)で tool_nametool_input を含む JSON を受け取るので、スクリプト側で編集されたファイルだけを取り出してフォーマットします。

bash
#!/bin/bash
# scripts/format-changed-files.sh
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')

if [ "$TOOL_NAME" = "editFiles" ] || [ "$TOOL_NAME" = "createFile" ]; then
  FILES=$(echo "$INPUT" | jq -r '.tool_input.files[]? // .tool_input.path // empty')
  for FILE in $FILES; do
    [ -f "$FILE" ] && npx prettier --write "$FILE" 2>/dev/null
  done
fi
echo '{"continue":true}'

ファイル単位に絞らずワークスペース全体をフォーマットするだけでよい場合は、command"npx prettier --write ." を指定するだけでも動作します。timeout を省略した場合のデフォルトは 30 秒です[^vscode-hooks-reference]。

3.2 ステップ 2: 危険コマンドをブロックする

.github/hooks/security.json を作成します。

json
{
  "hooks": {
    "PreToolUse": [
      {
        "type": "command",
        "command": "./scripts/block-dangerous-commands.sh"
      }
    ]
  }
}

スクリプトの例です。

bash
#!/bin/bash
# scripts/block-dangerous-commands.sh
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')

if [ "$TOOL_NAME" = "runTerminalCommand" ]; then
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
  if echo "$COMMAND" | grep -qE '(rm -rf|DROP TABLE|FORMAT)'; then
    echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"危険なコマンドがブロックされました"}}'
    exit 0
  fi
fi
echo '{"continue":true}'

stdout に JSON を返し、permissionDecision: "deny" でツール実行をブロックします。exit 2 でもブロックできますが、その場合は stderr がモデルにフィードバックされます[^vscode-hooks-reference]。

3.3 ステップ 3: /create-hook で AI 生成する

Chat で /create-hook ファイル編集後に ESLint を実行 と入力すると、AI がイベントとコマンドを選んで JSON を生成します。同じ生成フローはコマンドパレットの Chat: Generate Hook や、Chat: Open Customizations で開く Agent Customizations エディタの Hooks タブからも呼び出せます[^vscode-hooks]。

4. Agent-scoped Hooks(Preview)

Custom Agent の frontmatter に hooks を記述すると、そのエージェントが有効な場合のみ発火する Hook を定義できます。利用には chat.useCustomAgentHookstrue に設定します[^vscode-hooks]。

markdown
---
name: strict-formatter
description: 編集後に自動フォーマットするエージェント
hooks:
  PostToolUse:
    - type: command
      command: "./scripts/format-changed-files.sh"
---

コードを編集した後、自動的にフォーマットされます。

ワークスペース全体の Hook とは独立して管理できるため、エージェントの役割に応じた自動化を構成できます。

5. Hook の入出力

Hook は stdin で JSON を受け取り、stdout で JSON を返します(VS Code: Agent hooks 公式ドキュメントより)[^vscode-hooks]。

フィールド説明
continuebooleanfalse でセッション全体を停止
stopReasonstring停止理由(ユーザーに表示)
systemMessagestring警告メッセージ(チャットに表示)

PreToolUse では hookSpecificOutput を使うとツール単位で細かく制御できます。permissionDecision"allow" / "deny" / "ask" を指定し、同一ツールに対して複数の Hook が実行された場合は deny > ask > allow の順で最も厳しい判定が適用されます。PostToolUseStop では代わりに decision: "block"reason を返し、後続処理やセッション終了自体をブロックします[^vscode-hooks-reference]。

終了コードでも制御できます。exit 0 は成功(stdout を JSON として解析)、exit 2 はブロック(stderr をモデルにフィードバック)、それ以外は警告です[^vscode-hooks-reference]。

6. 注意点・制限事項

  • Hooks は Preview 機能です。設定形式や動作は将来変更される可能性があります[^vscode-hooks]

  • Hook スクリプトは VS Code と同じ権限で実行されます。信頼できないリポジトリの Hook は必ず内容を確認してください[^vscode-security]

  • エージェントが Hook スクリプト自体を編集できる場合、意図しないコード実行のリスクがあります。chat.tools.edits.autoApprove で Hook スクリプトの編集を手動承認にすることを推奨します[^vscode-security]

  • Stop Hook でセッションをブロックすると、エージェントの実行が継続するぶん GitHub AI クレジットを追加で消費します。stop_hook_active フィールドで無限ループを防いでください[^vscode-hooks-reference][^github-ai-credits]

    bash
    # Stop Hook 内で、既に Stop Hook 経由の継続かどうかを判定する例
    STOP_ACTIVE=$(echo "$INPUT" | jq -r '.stop_hook_active // false')
    if [ "$STOP_ACTIVE" = "true" ]; then
      echo '{"continue":true}' # 既に継続中なら再ブロックしない
      exit 0
    fi
    
  • 組織がポリシーで Hooks を無効化している場合があります。管理者に確認してください[^vscode-hooks]

7. まとめ

Agent Hooks を使うと、Custom Instructions や Custom Agent だけでは保証できない「確実な自動実行」をエージェントのワークフローに組み込めます。まずは PostToolUse + Prettier のような軽量パターンから始め、慣れたら PreToolUse でのセキュリティゲートに進めると導入しやすいです。

8. 参考情報

[^vscode-hooks]: Agent hooks in Visual Studio Code (Preview) — Visual Studio Code Docs(確認日: 2026-08-22)

[^vscode-hooks-reference]: Hooks reference — Visual Studio Code Docs(確認日: 2026-08-22)

[^vscode-security]: AI security in VS Code — Visual Studio Code Docs(確認日: 2026-08-22)

[^github-ai-credits]: GitHub Copilot is moving to usage-based billing — GitHub Blog(確認日: 2026-08-22)


この記事の執筆にあたり、AI の支援を受けています。