Skip to main content

후크 구성

GitHub Copilot 명령 줄 인터페이스 (CLI)와 Copilot 코딩 에이전트와 함께 사용할 후크 구성 방법에 대한 정보를 찾습니다.

이 문서의 내용

이 참조 문서에서는 입력 및 출력 형식, 스크립트 모범 사례 및 로깅, 보안 적용 및 외부 통합에 대한 고급 패턴을 포함하여 예제와 함께 사용 가능한 후크 형식에 대해 설명합니다. 후크를 만드는 방법에 대한 일반적인 내용은 GitHub Copilot 에이전트와 훅 사용을 참조하세요.

후크 형식

세션 시작 후크

새 에이전트 세션이 시작되거나 기존 세션을 다시 시작할 때 실행됩니다.

          **입력 JSON:**
JSON
{
  "timestamp": 1704614400000,
  "cwd": "/path/to/project",
  "source": "new",
  "initialPrompt": "Create a new feature"
}
          **필드:**

* timestamp: Unix 타임스탬프(밀리초) * cwd: 현재 작업 디렉터리 * source "new" : (새 세션), "resume" (다시 시작된 세션) 또는"startup" * initialPrompt: 사용자의 초기 프롬프트(제공된 경우)

          **출력:** 무시됨(반환 값이 처리되지 않음)

          **후크 예:**
JSON
{
  "type": "command",
  "bash": "./scripts/session-start.sh",
  "powershell": "./scripts/session-start.ps1",
  "cwd": "scripts",
  "timeoutSec": 30
}
          **예제 스크립트(Bash):**
Shell
#!/bin/bash
INPUT=$(cat)
SOURCE=$(echo "$INPUT" | jq -r '.source')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')

echo "Session started from $SOURCE at $TIMESTAMP" >> session.log

세션 끝 후크

에이전트 세션이 완료되거나 종료될 때 실행됩니다.

          **입력 JSON:**
JSON
{
  "timestamp": 1704618000000,
  "cwd": "/path/to/project",
  "reason": "complete"
}
          **필드:**

* timestamp: Unix 타임스탬프 밀리초 단위 * cwd: 현재 작업 디렉터리 * reason: 중 "complete"하나, "error", "abort", "timeout"또는 "user_exit"

          **출력:** 무시

          **스크립트 예**
Shell
#!/bin/bash
INPUT=$(cat)
REASON=$(echo "$INPUT" | jq -r '.reason')

echo "Session ended: $REASON" >> session.log
# Cleanup temporary files
rm -rf /tmp/session-*

사용자 프롬프트 제출 후크

사용자가 에이전트에 프롬프트를 제출할 때 실행됩니다.

          **입력 JSON:**
JSON
{
  "timestamp": 1704614500000,
  "cwd": "/path/to/project",
  "prompt": "Fix the authentication bug"
}
          **필드:**

* timestamp: 밀리초 단위의 Unix 타임스탬프 * cwd: 현재 작업 디렉터리 * prompt: 사용자가 제출한 정확한 텍스트

          **출력:** 무시됨(고객 후크에서 현재 지원되지 않는 프롬프트 수정)

          **스크립트 예**
Shell
#!/bin/bash
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')

# Log to a structured file
echo "$(date -d @$((TIMESTAMP/1000))): $PROMPT" >> prompts.log

사전 도구 사용 후크

에이전트가 모든 도구(예: bash, edit``view)를 사용하기 전에 실행됩니다. 도구 실행을 승인하거나 거부할 수 있는 가장 강력한 후크입니다.

          **입력 JSON:**
JSON
{
  "timestamp": 1704614600000,
  "cwd": "/path/to/project",
  "toolName": "bash",
  "toolArgs": "{\"command\":\"rm -rf dist\",\"description\":\"Clean build directory\"}"
}
          **필드:**

* timestamp: Unix 타임스탬프, 밀리초 단위 * cwd: 현재 작업 디렉터리 * toolName: 호출되는 도구의 이름(예: "bash", "edit", "view", "create") * toolArgs: 도구의 인수를 포함하는 JSON 문자열

          **출력 JSON(선택 사항):**
JSON
{
  "permissionDecision": "deny",
  "permissionDecisionReason": "Destructive operations require approval"
}
          **출력 필드:**

* permissionDecision: "allow", "deny", 또는 "ask" (현재는 "deny"만 처리됨) * permissionDecisionReason: 결정에 대한 사람이 읽을 수 있는 설명

          **위험한 명령을 차단하는 후크 예제:**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
TOOL_ARGS=$(echo "$INPUT" | jq -r '.toolArgs')

# Log the tool use
echo "$(date): Tool=$TOOL_NAME Args=$TOOL_ARGS" >> tool-usage.log

# Check for dangerous patterns
if echo "$TOOL_ARGS" | grep -qE "rm -rf /|format|DROP TABLE"; then
  echo '{"permissionDecision":"deny","permissionDecisionReason":"Dangerous command detected"}'
  exit 0
fi

# Allow by default (or omit output to allow)
echo '{"permissionDecision":"allow"}'
          **파일 권한을 적용하는 후크 예제:**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

# Only allow editing specific directories
if [ "$TOOL_NAME" = "edit" ]; then
  PATH_ARG=$(echo "$INPUT" | jq -r '.toolArgs' | jq -r '.path')
  
  if [[ ! "$PATH_ARG" =~ ^(src/|test/) ]]; then
    echo '{"permissionDecision":"deny","permissionDecisionReason":"Can only edit files in src/ or test/ directories"}'
    exit 0
  fi
fi

# Allow all other tools

사후 도구 사용 후크

도구가 실행을 완료한 후 실행됩니다(성공 여부 또는 실패 여부).

          **입력 JSON 예제:**
JSON
{
  "timestamp": 1704614700000,
  "cwd": "/path/to/project",
  "toolName": "bash",
  "toolArgs": "{\"command\":\"npm test\"}",
  "toolResult": {
    "resultType": "success",
    "textResultForLlm": "All tests passed (15/15)"
  }
}
          **필드:**

* timestamp: Unix 타임스탬프(밀리초) * cwd: 현재 작업 디렉터리 * toolName: 실행된 도구의 이름 * toolArgs: 도구의 인수를 포함하는 JSON 문자열 * toolResult: 다음을 포함하는 결과 개체: * resultType: , "success"``"failure"또는"denied" * textResultForLlm: 에이전트에 표시되는 결과 텍스트

          **출력:** 무시됨(결과 수정은 현재 지원되지 않음)

          **CSV 파일에 도구 실행 통계를 기록하는 예제 스크립트:**

이 스크립트는 도구 실행 통계를 CSV 파일에 기록하고 도구가 실패하면 이메일 경고를 보냅니다.

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
RESULT_TYPE=$(echo "$INPUT" | jq -r '.toolResult.resultType')

# Track statistics
echo "$(date),${TOOL_NAME},${RESULT_TYPE}" >> tool-stats.csv

# Alert on failures
if [ "$RESULT_TYPE" = "failure" ]; then
  RESULT_TEXT=$(echo "$INPUT" | jq -r '.toolResult.textResultForLlm')
  echo "FAILURE: $TOOL_NAME - $RESULT_TEXT" | mail -s "Agent Tool Failed" admin@example.com
fi

오류 발생 후크

에이전트를 실행하는 동안 오류가 발생할 때 실행됩니다.

          **입력 JSON 예제:**
JSON
{
  "timestamp": 1704614800000,
  "cwd": "/path/to/project",
  "error": {
    "message": "Network timeout",
    "name": "TimeoutError",
    "stack": "TimeoutError: Network timeout\n    at ..."
  }
}
          **필드:**

* timestamp: Unix 타임스탬프(밀리초) * cwd: 현재 작업 디렉터리 * error: 다음을 포함하는 오류 개체입니다. * message: 오류 메시지 * name: 오류 유형/이름 * stack: 스택 추적(사용 가능한 경우)

          **출력:** 무시됨(오류 처리 수정은 현재 지원되지 않음)

          **로그 파일에 오류 세부 정보를 추출하는 예제 스크립트:**
Shell
#!/bin/bash
INPUT=$(cat)
ERROR_MSG=$(echo "$INPUT" | jq -r '.error.message')
ERROR_NAME=$(echo "$INPUT" | jq -r '.error.name')

echo "$(date): [$ERROR_NAME] $ERROR_MSG" >> errors.log

스크립트 모범 사례

읽기 입력

이 예제 스크립트는 표준 입력(stdin)에서 JSON 입력을 변수에 읽은 다음, jq를 사용하여 timestampcwd 필드를 추출합니다.

          **Bash:**
Shell
#!/bin/bash
# Read JSON from stdin
INPUT=$(cat)

# Parse with jq
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
CWD=$(echo "$INPUT" | jq -r '.cwd')
          **PowerShell:**
PowerShell
# Read JSON from stdin
$input = [Console]::In.ReadToEnd() | ConvertFrom-Json

# Access properties
$timestamp = $input.timestamp
$cwd = $input.cwd

JSON 출력

이 예제 스크립트는 후크 스크립트에서 유효한 JSON을 출력하는 방법을 보여 줍니다. Bash에서는 jq -c를 사용하여 압축된 단일 행 출력을 생성하거나 PowerShell에서는 ConvertTo-Json -Compress을/를 사용합니다.

          **Bash:**
Shell
#!/bin/bash
# Use jq to compact the JSON output to a single line
echo '{"permissionDecision":"deny","permissionDecisionReason":"Security policy violation"}' | jq -c

# Or construct with variables
REASON="Too dangerous"
jq -n --arg reason "$REASON" '{permissionDecision: "deny", permissionDecisionReason: $reason}'
          **PowerShell:**
PowerShell
# Use ConvertTo-Json to compact the JSON output to a single line
$output = @{
    permissionDecision = "deny"
    permissionDecisionReason = "Security policy violation"
}
$output | ConvertTo-Json -Compress

오류 처리

이 스크립트 예제에서는 후크 스크립트에서 오류를 처리하는 방법을 보여 줍니다.

          **Bash:**
Shell
#!/bin/bash
set -e  # Exit on error

INPUT=$(cat)
# ... process input ...

# Exit with 0 for success
exit 0
          **PowerShell:**
PowerShell
$ErrorActionPreference = "Stop"

try {
    $input = [Console]::In.ReadToEnd() | ConvertFrom-Json
    # ... process input ...
    exit 0
} catch {
    Write-Error $_.Exception.Message
    exit 1
}

타임아웃 처리

후크의 기본 시간 제한은 30초입니다. 긴 작업을 위해 timeoutSec을(를) 증가시킵니다.

JSON
{
  "type": "command",
  "bash": "./scripts/slow-validation.sh",
  "timeoutSec": 120
}

고급 패턴

동일한 유형의 여러 후크

동일한 이벤트에 대해 여러 후크를 정의할 수 있습니다. 순서대로 실행됩니다.

JSON
{
  "version": 1,
  "hooks": {
    "preToolUse": [
      {
        "type": "command",
        "bash": "./scripts/security-check.sh",
        "comment": "Security validation - runs first"
      },
      {
        "type": "command", 
        "bash": "./scripts/audit-log.sh",
        "comment": "Audit logging - runs second"
      },
      {
        "type": "command",
        "bash": "./scripts/metrics.sh",
        "comment": "Metrics collection - runs third"
      }
    ]
  }
}

스크립트의 조건부 논리

          **예: 특정 도구만 차단**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

# Only validate bash commands
if [ "$TOOL_NAME" != "bash" ]; then
  exit 0  # Allow all non-bash tools
fi

# Check bash command for dangerous patterns
COMMAND=$(echo "$INPUT" | jq -r '.toolArgs' | jq -r '.command')
if echo "$COMMAND" | grep -qE "rm -rf|sudo|mkfs"; then
  echo '{"permissionDecision":"deny","permissionDecisionReason":"Dangerous system command"}'
fi

구조적 로깅

          **예: JSON 줄 형식**
Shell
#!/bin/bash
INPUT=$(cat)
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
RESULT_TYPE=$(echo "$INPUT" | jq -r '.toolResult.resultType')

# Output structured log entry
jq -n \
  --arg ts "$TIMESTAMP" \
  --arg tool "$TOOL_NAME" \
  --arg result "$RESULT_TYPE" \
  '{timestamp: $ts, tool: $tool, result: $result}' >> logs/audit.jsonl

외부 시스템과 통합

          **예: Slack에 경고 보내기**
Shell
#!/bin/bash
INPUT=$(cat)
ERROR_MSG=$(echo "$INPUT" | jq -r '.error.message')

WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

curl -X POST "$WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\"Agent Error: $ERROR_MSG\"}"

사용 사례 예

준수 감사 내역

로그 스크립트를 활용하여 규정 준수 요구 사항에 대한 모든 에이전트 작업을 기록합니다.

JSON
{
  "version": 1,
  "hooks": {
    "sessionStart": [{"type": "command", "bash": "./audit/log-session-start.sh"}],
    "userPromptSubmitted": [{"type": "command", "bash": "./audit/log-prompt.sh"}],
    "preToolUse": [{"type": "command", "bash": "./audit/log-tool-use.sh"}],
    "postToolUse": [{"type": "command", "bash": "./audit/log-tool-result.sh"}],
    "sessionEnd": [{"type": "command", "bash": "./audit/log-session-end.sh"}]
  }
}

비용 추적

비용 할당에 대한 도구 사용 현황 추적:

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
USER=${USER:-unknown}

echo "$TIMESTAMP,$USER,$TOOL_NAME" >> /var/log/copilot/usage.csv

코드 품질 적용

코드 표준을 위반하는 커밋 방지:

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

if [ "$TOOL_NAME" = "edit" ] || [ "$TOOL_NAME" = "create" ]; then
  # Run linter before allowing edits
  npm run lint-staged
  if [ $? -ne 0 ]; then
    echo '{"permissionDecision":"deny","permissionDecisionReason":"Code does not pass linting"}'
  fi
fi

알림 시스템

중요한 이벤트에 대한 알림 보내기:

Shell
#!/bin/bash
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt')

# Notify on production-related prompts
if echo "$PROMPT" | grep -iq "production"; then
  echo "ALERT: Production-related prompt: $PROMPT" | mail -s "Agent Alert" team@example.com
fi