훅(Hooks)

훅(Hooks)

훅을 사용하면 에이전트 실행 중 주요 지점에서 셸 명령을 자동으로 실행할 수 있어요. 정책을 강제하고, 컨텍스트를 주입하고, 도구 입력을 검증하고, 권한을 자동 승인하거나 외부 시스템과 통합하는 데 사용하세요. 훅은 에이전트가 하고 있는 일을 관찰하거나, 입력을 수정하거나, 작업을 완전히 차단할 수 있어요.

출처: Hooks

본문

훅 이벤트

각 훅은 에이전트 수명 주기의 특정 지점에서 발생하는 이벤트에 연결돼요.

이벤트 발생 시점 차단 가능
PreToolUse 도구가 실행되기 전 예
PostToolUse 도구 실행이 끝난 후 아니요
PermissionRequest 권한 대화상자가 표시되려 할 때 예(자동 허용 또는 자동 거부)
SessionStart 새 채팅 세션이 만들어질 때 아니요
UserPromptSubmit 사용자가 프롬프트를 제출할 때 예
Stop 에이전트의 턴이 끝날 때 아니요(단, 강제 계속 가능)
Notification 알림이 전송될 때 아니요
PreCompact 대화 요약/압축 전 아니요
SessionEnd 세션 종료 시(지우기, 로그아웃, 종료) 아니요
SubagentStop 하위 에이전트의 턴이 끝날 때 아니요
Setup 에이전트가 초기 환경 설정을 수행할 때 예

훅 관리

Agent Settings를 열고 사이드바에서 Hooks를 선택하세요. 패널은 모든 이벤트 유형을 확장 가능한 섹션으로 나열하며, 구성된 훅 수(활성/전체)를 보여주는 배지가 있어요.

새 훅을 추가하려면:

  • 훅을 연결할 이벤트 옆의 + 버튼을 클릭.
  • 저장 위치(Storage Location) 선택: - User — 전역으로 ~/.snowflake/cortex/settings.json에 저장. - Workspace — <workspace>/.snowflake/cortex/settings.json에 저장.
  • Form 보기로 구성하거나 JSON으로 전환해 원시 편집.
  • 필드 설정: - Tool Matcher — 도구 이벤트의 경우 어떤 도구가 훅을 트리거하는지 필터링하는 정규식 패턴. 모든 도구에는 * 사용. - Command — 실행할 셸 명령(예: ./my-hook-script.sh). - Timeout — 타임아웃까지 기다릴 초(기본값 60). - Status Message — 훅이 실행되는 동안 스피너로 표시되는 사용자 정의 메시지.
  • Save 클릭.

구성 파일

훅은 설정 파일의 hooks 키에 저장돼요.

범위 경로
User(전역) ~/.snowflake/cortex/settings.json
Workspace <workspace>/.snowflake/cortex/settings.json 또는 <workspace>/.cortex/settings.json

CoCo Desktop은 settings.json 훅과 함께 전용 전역 훅 파일 ~/.snowflake/cortex/hooks.json(동일한 { "hooks": { ... } } 스키마 사용)도 로드하며, 변경 시 다시 로드해요. 이 파일은 CoCo CLI와 공유되며 Desktop 훅 UI에는 표시되지 않아서, UI에서 훅을 편집해도 덮어쓰지 않아요. 그 훅은 설정 파일의 훅 위에 겹쳐지는 것이 아니라 추가돼요.

예제 구성:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "./validate-tool-call.sh",
            "timeout": 60,
            "enabled": true,
            "statusMessage": "Validating..."
          }
        ]
      }
    ],
    "SessionStart": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Session started'",
            "timeout": 10
          }
        ]
      }
    ]
  }
}

훅 필드

필드 유형 설명
type string "command" — 셸 명령 실행.
command string 실행할 셸 명령.
timeout number 타임아웃까지 기다릴 초(기본값: 60).
enabled boolean 훅이 활성인지(기본값: true).
statusMessage string 훅이 실행되는 동안 스피너로 표시되는 메시지.

도구 매처

도구 기반 이벤트(PreToolUse, PostToolUse, PermissionRequest)의 matcher 필드는 도구 이름에 대해 검사하는 정규식 패턴이에요. 모든 도구를 매치하려면 "*"를 사용하거나 비워 두세요. 같은 이벤트에 다른 훅이 있는 여러 매처를 구성할 수 있어요.

도구 이름은 대소문자를 구분해요. 기본 제공 도구 이름은 소문자라서 bash 매처는 일치하지만 Bash는 일치하지 않아요. 존재하지 않는 도구를 지정한 매처는 절대 발생하지 않으며 오류도 보고되지 않아요.

실행 컨텍스트

훅이 발생하면 전체 실행 컨텍스트가 JSON으로 명령의 stdin에 파이프돼요. 현재 세션과 트리거 이벤트에 대한 정보를 포함해요.

필드 사용 가능 시점 설명
session_id 모든 이벤트 고유 세션 식별자
cwd 모든 이벤트 현재 작업 디렉터리
hook_event_name 모든 이벤트 트리거되는 이벤트
tool_name 도구 이벤트 호출되는 도구 이름
tool_input 도구 이벤트 입력 매개변수(JSON 객체)
tool_response PostToolUse 도구의 응답 텍스트
prompt UserPromptSubmit 사용자가 제출한 프롬프트 텍스트

훅 출력

훅 명령은 stdout(JSON) 과 exit code를 통해 다시 통신해요.

Exit 코드

Exit 코드 의미
0 성공 — 정상 진행
2 차단 — 작업 방지. stderr 콘텐츠가 차단 이유가 됨.
기타 0이 아닌 값 오류 — 기록되지만 차단하지 않음

JSON 출력(stdout)

더 많은 제어를 위해 훅이 stdout에 JSON을 출력할 수 있어요.

{
  "decision": "approve",
  "reason": "All checks passed",
  "additionalContext": "Extra context injected into the conversation",
  "hookSpecificOutput": {
    "permissionDecision": "allow",
    "updatedInput": { "command": "modified-command" }
  }
}
필드 설명
decision "approve" 또는 "block" — 진행할지 차단할지.
reason 설명(차단되면 에이전트에 표시됨).
additionalContext 에이전트의 컨텍스트로 대화에 주입되는 텍스트.
hookSpecificOutput.permissionDecision PermissionRequest의 경우: "allow", "deny" 또는 "ask".
hookSpecificOutput.updatedInput PreToolUse의 경우: 수정된 도구 입력 매개변수.

stdout이 유효한 JSON이 아니면 additionalContext 텍스트로 처리돼요.

작업 차단

PreToolUse, PermissionRequest, UserPromptSubmit 훅은 작업을 차단할 수 있어요. 훅이 차단하면:

  • 도구 호출(또는 프롬프트 제출)이 방지됨.
  • 차단 이유가 에이전트에 표시되어 접근 방식을 조정할 수 있음.
  • 에이전트가 "[Hook] Tool execution blocked: " 같은 메시지를 봄.

훅에서 차단하려면 다음 중 하나를 사용해요.

  • 코드 2로 종료하고 이유를 stderr에 작성.
  • "decision": "block"과 "reason" 필드가 있는 JSON 출력.

예시

프로덕션 파일에 대한 쓰기 차단

#!/bin/bash
# block-prod-writes.sh — PreToolUse hook for edit/write tools
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

if [[ "$FILE" == */production/* ]]; then
  echo "Cannot modify files in the production directory" >&2
  exit 2
fi

읽기 전용 도구 자동 승인

#!/bin/bash
# auto-approve-reads.sh — PermissionRequest hook
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')

case "$TOOL" in
  read|grep|glob)
    echo '{"hookSpecificOutput":{"permissionDecision":"allow"}}'
    ;;
  *)
    echo '{"hookSpecificOutput":{"permissionDecision":"ask"}}'
    ;;
esac

세션 시작 시 프로젝트 컨텍스트 주입

#!/bin/bash
# session-context.sh — SessionStart hook
echo "This project uses Python 3.12, pytest for testing, and ruff for linting."

구성 우선 순위

여러 소스의 훅이 병합돼요. Workspace 훅이 user 훅보다 먼저 발생해요. 플러그인과 프로필도 훅을 기여할 수 있어요(UI에서 읽기 전용으로 표시됨).

더 알아보기