패스노트
도메인 1. 에이전틱 아키텍처와 오케스트레이션

1.5Agent SDK와 훅

예상 학습 시간 40

Claude Agent SDK는 Claude Code를 구동하는 에이전트 하네스를 라이브러리로 제공합니다. 이 수업에서는 SDK의 기본 사용법, 권한 모델, 그리고 도구 호출 전후에 결정적 코드를 실행하는 훅(hook) 시스템을 다룹니다.

Agent SDK의 구조와 기본 사용법

Claude Agent SDK(구 Claude Code SDK)는 파일 읽기·편집·명령 실행·검색 같은 도구, 권한 관리, 컨텍스트 관리를 갖춘 에이전트 하네스를 Python과 TypeScript 라이브러리로 제공합니다. Claude Code CLI가 대화형 셸이라면, SDK는 같은 엔진을 프로그램에서 호출하는 인터페이스입니다.

Python의 기본 사용법은 query() 함수입니다.

import anyio
from claude_agent_sdk import query, ClaudeAgentOptions

async def main():
    options = ClaudeAgentOptions(
        system_prompt="당신은 테스트 커버리지를 개선하는 에이전트입니다",
        allowed_tools=["Read", "Grep", "Glob", "Edit", "Bash"],
        permission_mode="acceptEdits",   # 파일 편집은 자동 승인
        cwd="/path/to/repo",
        max_turns=30,
    )
    async for message in query(
        prompt="커버리지가 없는 모듈을 찾아 테스트를 추가해줘",
        options=options,
    ):
        print(message)   # 진행 메시지 스트림

anyio.run(main)

핵심 옵션을 정리하면:

  • allowed_tools — 에이전트에 노출할 도구의 화이트리스트. 역할에 맞게 최소로 제한하는 것이 원칙입니다.
  • permission_mode — 권한 처리 방식. default(민감 작업마다 확인), acceptEdits(편집 자동 승인), bypassPermissions(모두 자동 승인, 샌드박스 환경에서만 권장) 등이 있습니다.
  • max_turns — 반복 상한. 1.1 수업에서 다룬 루프 가드레일이 SDK에는 옵션으로 내장되어 있습니다.
  • mcp_servers — MCP 서버 연결로 외부 도구를 추가합니다.

단발 query() 외에 ClaudeSDKClient(Python) / ClaudeAgent류 클라이언트를 쓰면 같은 세션에서 여러 차례 주고받는 연속 대화가 가능합니다. 시험에서는 "SDK가 제공하는 것"(하네스: 도구·권한·컨텍스트 관리)과 "개발자가 제공하는 것"(목표 프롬프트·커스텀 도구·정책)을 구분하는 문제가 나옵니다.

훅 시스템: 이벤트에 결정적 코드 걸기

**훅(hook)**은 에이전트 수명주기의 특정 이벤트에서 실행되는 사용자 정의 코드입니다. 프롬프트가 "부탁"이라면 훅은 "규칙"입니다. 모델의 판단을 거치지 않고 항상 실행되므로, 1.4에서 다룬 구조적 강제의 핵심 도구입니다.

주요 훅 이벤트:

  • PreToolUse — 도구 실행 직전. 검사 결과에 따라 호출을 차단할 수 있어 가장 자주 쓰입니다.
  • PostToolUse — 도구 실행 직후. 결과 검증, 자동 포맷팅, 로깅에 씁니다.
  • UserPromptSubmit — 사용자 입력 제출 시. 컨텍스트 주입이나 입력 검증에 씁니다.
  • Stop — 에이전트가 턴을 마치려 할 때. 완료 조건 미충족 시 계속하게 만들 수 있습니다.

Claude Code에서는 settings.json에 선언합니다.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 .claude/hooks/block_dangerous.py"
          }
        ]
      }
    ]
  }
}

훅 스크립트는 stdin으로 도구 호출 정보(JSON)를 받고, 종료 코드나 JSON 출력으로 허용/차단을 알립니다. 예를 들어 block_dangerous.py가 명령에 rm -rf나 프로덕션 호스트명이 포함되면 차단 응답을 돌려주는 식입니다. SDK에서는 같은 개념을 hooks 옵션에 콜백 함수로 등록합니다.

훅 설계의 원칙: 결정적으로 판단 가능한 정책만 훅에 넣습니다. "위험해 보이는 명령"처럼 판단이 필요한 것은 권한 시스템과 휴먼 승인에 맡기고, 훅은 "이 경로는 절대 수정 금지", "커밋 전 린트 필수"처럼 기계적으로 검사 가능한 규칙을 맡는 것이 유지보수에 유리합니다.

권한 모델과 안전한 자동화

에이전트를 무인(headless)으로 돌리려면 권한 설계가 필수입니다. Agent SDK와 Claude Code는 여러 층의 권한 제어를 제공하며, 층마다 목적이 다릅니다.

  1. 도구 화이트리스트(allowed_tools) — 애초에 노출할 도구를 제한합니다. 가장 강력하고 단순한 제어입니다.
  2. 권한 규칙(settings.json의 permissions) — 도구별·패턴별 허용/거부. 예: Bash(npm test:*)는 허용, Bash(rm:*)는 거부.
  3. 권한 모드 — 세션 전체의 기본 동작. CI에서는 샌드박스와 결합해 bypassPermissions를 쓰기도 하지만, 격리 없는 환경에서 이 모드를 쓰는 것은 시험에서 항상 오답입니다.
  4. canUseTool 콜백 / PreToolUse 훅 — 호출 단위의 동적 판단.
async def can_use_tool(tool_name: str, tool_input: dict, context) -> dict:
    # 프로덕션 배포는 언제나 사람 승인
    if tool_name == "Bash" and "deploy --prod" in tool_input.get("command", ""):
        return {"behavior": "deny", "message": "프로덕션 배포는 승인 필요"}
    return {"behavior": "allow", "updatedInput": tool_input}

options = ClaudeAgentOptions(can_use_tool=can_use_tool, ...)

안전한 자동화의 표준 조합은 최소 도구 + 명시적 허용 규칙 + 위험 패턴 차단 훅 + 격리된 실행 환경입니다. 어느 한 층이 뚫려도 다른 층이 막는 심층 방어(defense in depth)를 구성합니다.

시험 함정 하나를 짚어두면, "훅과 권한 규칙은 같은 기능"이 아닙니다. 권한 규칙은 선언적 패턴 매칭이고, 훅은 임의 코드를 실행할 수 있는 프로그래밍 지점입니다. 규칙으로 표현 가능한 정책은 규칙으로, 동적 판단이 필요한 정책만 훅으로 구현하는 것이 권장 순서입니다.

시험 함정

  • PreToolUse와 PostToolUse의 역할 혼동 — 호출을 차단할 수 있는 것은 PreToolUse뿐이고, PostToolUse는 실행 후 검증·후처리용입니다.
  • 격리되지 않은 환경에서 bypassPermissions를 권하는 선택지 — 이 모드는 샌드박스 등 격리 환경에서만 정당화됩니다.
  • 훅에 '위험해 보이면 차단' 같은 판단형 정책을 넣는 오답 — 훅은 결정적 규칙, 판단은 권한 시스템·휴먼 승인의 몫입니다.
  • SDK의 query()가 대화 상태를 자동 유지한다는 오답 — 연속 대화에는 클라이언트 세션을 사용해야 합니다.
  • allowed_tools를 넓게 열고 프롬프트로 자제시키는 구성을 정답으로 제시하는 함정 — 최소 권한 원칙에 어긋납니다.

실습 시나리오

실제 시험과 같은 형식의 시나리오 문제입니다.

CI 파이프라인에서 Agent SDK로 코드 수정 에이전트를 무인 실행하려 합니다. 에이전트가 .env 파일을 절대 수정하지 못하게 보장하는 가장 적절한 방법은?

빌드 연습 · 훅으로 보호되는 무인 에이전트 구성

55
  1. 1.SDK 기본 실행

    query()로 간단한 리팩터링 작업을 수행하는 스크립트를 작성합니다.

    기대 결과 · allowed_tools가 Read/Grep/Edit/Bash로 제한된 상태에서 작업이 완료됩니다.

  2. 2.경로 보호 훅 작성

    PreToolUse 훅으로 .env, secrets/ 경로에 대한 쓰기를 차단합니다.

    기대 결과 · 보호 경로 수정 시도가 차단되고 에이전트에게 사유가 전달됩니다.

  3. 3.명령 차단 훅 작성

    Bash 명령에 rm -rf, curl | sh 패턴이 있으면 차단하는 훅을 추가합니다.

    기대 결과 · 위험 명령이 실행되지 않고 로그에 차단 기록이 남습니다.

  4. 4.PostToolUse 포매터 연결

    Edit 후 자동으로 포매터를 실행하는 PostToolUse 훅을 추가합니다.

    기대 결과 · 모든 편집 결과가 포맷 규칙을 일관되게 따릅니다.

  5. 5.차단 시나리오 테스트

    에이전트에게 일부러 보호 경로 수정을 요청해 방어가 작동하는지 확인합니다.

    기대 결과 · 훅 차단 → 에이전트가 대안 제시 또는 중단 보고의 흐름이 관찰됩니다.

출처 및 더 읽기