52개 빌트인 도구의 공통 인터페이스, 10단계 실행 파이프라인, 안전=병렬/위험=순차 동시성 모델, 5단계 권한 파이프라인, 888KB 23단계 bash 보안
Claude Code에서 “이 파일을 수정해줘”라고 말하면, 응답이 나오기까지 수십 밀리초 안에 도구 선택, 입력 검증, 권한 확인, AST 보안 검사, 실행, 결과 가공이 순서대로 일어납니다. 단순한 함수 호출이 아닙니다. 52개 도구가 공통 인터페이스를 통해 10단계 파이프라인을 거치고, 23단계 보안 검사를 통과하는 시스템입니다.
이 글에서는 Claude Code 소스(512,000줄 TypeScript) 분석을 기반으로, 에이전트의 Tool System이 실제로 어떻게 작동하는지 분해합니다.
도구가 호출되면 무슨 일이 벌어지는가
LLM이 도구를 호출하면 단순히 함수가 실행되는 것이 아닙니다. Claude Code에서 하나의 도구 호출이 완료되기까지 거치는 과정을 요약하면 다음과 같습니다.
- 도구 이름 조회 (52개 중 매칭)
- 중단 여부 확인 (사용자가 Ctrl+C를 눌렀는가)
- 입력 스키마 검증 (Zod)
- PreToolUse 훅 실행
- 권한 확인 (5단계 파이프라인)
- 도구 실행 (실제 작업)
- 결과를 ToolResult로 매핑
- 결과 크기 검사 (초과 시 디스크 저장)
- PostToolUse 훅 실행
- 텔레메트리 전송
이 10단계 중 실제 작업은 6번 하나뿐이고, 나머지 9단계는 모두 안전과 일관성을 위한 인프라입니다. 이것이 프로덕션 에이전트 시스템의 현실입니다.
52개 도구 카탈로그
Claude Code의 전체 도구는 8개 카테고리로 분류됩니다. 괄호 안 gated 표시는 Feature Flag로 제어되어 기본 비활성 상태인 도구입니다.
| 카테고리 | 도구 수 | 도구 목록 |
|---|---|---|
| File Operations | 6 | FileRead, FileEdit, FileWrite, Glob, Grep, NotebookEdit |
| Execution | 3 | Bash, PowerShell, REPL |
| Search and Fetch | 4 | WebBrowser (gated), WebFetch, WebSearch, ToolSearch |
| Agents and Tasks | 11 | Agent, SendMessage, TaskCreate/Get/List/Update/Stop/Output, TeamCreate, TeamDelete, ListPeers (gated) |
| Planning | 5 | EnterPlanMode, ExitPlanMode, EnterWorktree, ExitWorktree, VerifyPlanExecution (gated) |
| MCP | 4 | mcp, ListMcpResources, ReadMcpResource, McpAuth |
| System | 11 | AskUserQuestion, TodoWrite, Skill, Config, RemoteTrigger (gated), CronCreate/Delete/List (gated), Snip (gated), Workflow (gated), TerminalCapture (gated) |
| Experimental | 8 | Sleep, SendUserMessage, StructuredOutput (gated), LSP (gated), SendUserFile (gated), PushNotification (gated), Monitor (gated), SubscribePR (gated) |
총 52개. 이 중 상시 활성 41개, Feature-gated 11개입니다. 단순한 리스트로 보면 “도구가 많다” 정도지만, 핵심은 이 52개가 동일한 인터페이스를 공유한다는 점입니다.
공통 인터페이스: 모든 도구의 계약
52개 도구가 하나의 파이프라인으로 통합될 수 있는 이유는 공통 인터페이스 때문입니다.
| 속성/메서드 | 역할 |
|---|---|
name | 도구 식별자 (LLM이 호출 시 사용) |
inputSchema (Zod) | 파라미터 스키마 검증 — LLM hallucination 방어 |
call() | 실제 실행 로직 |
description() | LLM에 제공되는 도구 설명 |
checkPermissions() | 권한 확인 로직 |
validateInput() | 스키마 외 추가 입력 검증 |
isConcurrencySafe() | 병렬 실행 가능 여부 반환 |
isReadOnly() | 읽기 전용 여부 — 권한 모드에서 활용 |
maxResultSizeChars | 결과 크기 상한 — 초과 시 디스크 저장 후 참조만 반환 |
render*() | 터미널 UI 렌더링 (입력/결과 각각) |
isConcurrencySafe()는 단순한 boolean이 아닙니다. FileRead는 항상 true를 반환하지만, FileEdit는 같은 파일을 동시에 수정하는 경우에만 false를 반환합니다. 이 세밀한 구분이 동시성 모델의 기반이 됩니다.
maxResultSizeChars도 중요합니다. LLM 컨텍스트 윈도우는 유한하므로, 도구 결과가 너무 크면 디스크에 저장하고 참조 경로만 반환합니다. 컨텍스트 오염 방지 전략입니다.
도구 조립 파이프라인
52개 도구가 최종적으로 LLM에 전달되기까지 5단계 필터링을 거칩니다.
flowchart LR
A["getAllBaseTools()\n44+ 내장 도구"] --> B["Feature Gate\n필터"]
B --> C["Deny Rules\n필터"]
C --> D["Mode 필터\nplan/auto/default"]
D --> E["Alphabetical\nSort"]
E --> F["assembleToolPool()\n+ MCP 도구 병합"]
알파벳 정렬이 왜 중요한가? Claude Code는 Anthropic API의 프롬프트 캐싱을 활용합니다. 도구 정의는 시스템 프롬프트의 일부로 전송되는데, 도구 순서가 바뀌면 캐시 키가 달라져서 캐시 히트율이 급락합니다. 도구가 추가/제거될 때마다 순서가 흔들리지 않도록 알파벳 정렬을 강제한 것입니다.
Deny Rules 필터는 .claude/settings.json에서 사용자가 특정 도구를 차단할 수 있게 합니다. Mode 필터는 Plan 모드에서 쓰기 도구를 제외하는 등 실행 맥락에 따라 도구셋을 조정합니다.
10단계 실행 파이프라인 상세
각 단계를 좀 더 깊이 들여다봅니다.
1단계: 이름 조회. assembleToolPool()의 결과에서 도구 이름을 매칭합니다. 없으면 즉시 에러를 반환하고 LLM에 “이 도구는 존재하지 않는다”고 알립니다.
2단계: 중단 확인. 사용자가 Ctrl+C를 누르면 AbortSignal이 전파됩니다. 실행 전에 이를 확인하여 불필요한 도구 실행을 방지합니다.
3단계: 입력 검증. Zod 스키마로 LLM이 생성한 파라미터를 검증합니다. LLM은 확률적으로 잘못된 타입이나 누락된 필드를 생성할 수 있으므로, 스키마 검증은 필수입니다.
4단계: PreToolUse 훅. 도구 실행 전에 외부 스크립트를 실행할 수 있는 확장 포인트입니다. 기업 환경에서 커스텀 보안 검사를 추가하는 데 사용됩니다.
5단계: 권한 확인. 5단계 Permission Pipeline (후술)을 거칩니다. 여기서 차단되면 도구는 실행되지 않습니다.
6단계: 실행. call() 메서드가 호출되어 실제 작업이 수행됩니다.
7단계: 결과 매핑. 도구의 원시 결과를 ToolResult 표준 형식으로 변환합니다. 텍스트, 이미지, 에러 등 다양한 타입을 일관된 구조로 통합합니다.
8단계: 크기 검사. maxResultSizeChars를 초과하면 결과를 디스크에 저장하고, LLM에는 “결과가 크므로 파일 참조를 확인하라”는 메시지만 전달합니다.
9단계: PostToolUse 훅. 실행 후 외부 스크립트를 실행하는 확장 포인트입니다. 감사 로깅, 알림 등에 활용됩니다.
10단계: 텔레메트리. 실행 시간, 성공/실패, 도구 이름 등을 수집합니다. 사용 통계와 성능 모니터링의 기반입니다.
동시성 모델: 안전한 것은 병렬, 위험한 것은 순차
LLM이 한 턴에 여러 도구를 호출하면 어떻게 실행될까요? Claude Code의 StreamingToolExecutor가 이를 관리합니다.
flowchart TB
subgraph "Batch 1 -- Parallel"
direction LR
R1["FileRead\n/src/a.ts"]
R2["FileRead\n/src/b.ts"]
R3["Grep\npattern: error"]
end
subgraph "Batch 2 -- Sequential"
E1["FileEdit\n/src/a.ts"]
end
subgraph "Batch 3 -- Parallel"
R4["FileRead\n/src/c.ts"]
R5["Glob\n**/*.test.ts"]
end
R1 & R2 & R3 --> E1
E1 --> R4 & R5
핵심 규칙:
| 구분 | 조건 | 실행 방식 |
|---|---|---|
| 안전 도구 | isConcurrencySafe() = true | 같은 배치에 묶어 병렬 실행 (최대 10개) |
| 위험 도구 | isConcurrencySafe() = false | 새 배치를 시작하여 단독 순차 실행 |
| 실패 처리 | 배치 내 도구 하나가 실패 | 같은 배치의 형제 도구를 abort |
StreamingToolExecutor의 핵심 최적화: API 응답이 스트리밍되는 동안 도구 파라미터가 완성되는 즉시 실행을 시작합니다. LLM이 세 번째 도구의 파라미터를 생성하는 동안 첫 번째 도구는 이미 실행 중일 수 있습니다. 이 오버랩이 체감 응답 시간을 크게 줄입니다.
병렬 배치의 최대 크기가 10인 이유: 파일시스템 부하와 프로세스 수를 제한하기 위한 실용적 상한입니다. 10개를 초과하는 안전 도구 호출은 다음 배치로 넘어갑니다.
5단계 Permission Pipeline
도구 실행 전 권한을 확인하는 파이프라인입니다.
flowchart TB
A["1. Rule Matching\nDeny/Allow 규칙 매칭"] --> B["2. Mode Check\n실행 모드 확인"]
B --> C["3. ReadOnly Check\n읽기 전용 여부"]
C --> D["4. AI Classifier\nAuto 모드 전용"]
D --> E["5. User Prompt\n최종 사용자 확인"]
E --> F["ALLOW / DENY"]
4가지 권한 모드가 이 파이프라인의 동작을 결정합니다.
| 모드 | 읽기 도구 | 쓰기 도구 | 특징 |
|---|---|---|---|
| Default | 자동 허용 | 사용자 확인 | 가장 안전, 기본값 |
| Auto | 자동 허용 | AI 분류기 판단 | 생산성 우선, AI가 안전 여부 판단 |
| Plan | 허용 | 차단 | 읽기 전용, 계획 수립 모드 |
| Bypass | 자동 허용 | 자동 허용 | 모든 확인 생략, CI/CD 전용 |
규칙 우선순위: Local (.claude/settings.local.json) 이 가장 높고, 그 다음이 Project (.claude/settings.json), User (~/.claude/settings.json), CLI Flags, Org Policy 순입니다. 하위 규칙은 상위 규칙을 override할 수 없습니다.
Auto 모드의 AI 분류기는 별도 LLM 호출이 아니라, 도구 이름과 파라미터를 기반으로 한 경량 규칙 엔진입니다. “이 명령어가 파일을 삭제하는가”, “네트워크에 접근하는가” 등을 패턴 매칭으로 판단합니다.
BashTool 보안: 888KB, 23단계 AST 검사
Bash 도구는 에이전트 시스템에서 가장 위험한 도구입니다. 임의의 셸 명령을 실행할 수 있기 때문입니다. Claude Code는 이를 위해 Tree-sitter 기반 AST 파싱이라는 정교한 보안 체계를 구축했습니다.
| 수치 | 값 |
|---|---|
| 보안 코드 크기 | 888KB (18개 파일) |
| 검사 단계 | 23단계 |
| 파서 | Tree-sitter (bash + zsh grammar) |
| 설계 원칙 | Fail-closed (파싱 실패 시 차단) |
23단계 검사의 주요 영역
명령어 치환 (Command Substitution) 검사: $(rm -rf /) 같은 중첩 명령을 AST에서 추출하여 개별적으로 검사합니다. 문자열 안에 숨겨진 명령어 치환도 감지합니다.
변수 확장 (Variable Expansion) 검사: $HOME, ${PATH} 같은 변수 확장을 추적합니다. 공격자가 환경 변수를 통해 악성 경로를 주입하는 것을 방지합니다.
리다이렉션 (Redirection) 검사: >, >>, 2>&1 등 모든 리다이렉션 대상 파일 경로를 검증합니다. 시스템 파일에 대한 쓰기를 차단합니다.
파이프 (Pipe) 검사: | 뒤에 오는 명령어를 개별적으로 검사합니다. cat file | bash 같은 간접 실행 패턴을 감지합니다.
Zsh 전용 검사: =curl (equals expansion), builtin 명령어 우회 시도 등 Zsh 고유 문법의 악용을 차단합니다.
유니코드 공격 방어: Zero-width 문자, Null 바이트, Homoglyph(시각적으로 유사한 다른 문자) 삽입을 감지합니다. rm -rf / 에서 /를 유사한 유니코드 문자로 바꾸는 공격을 차단합니다.
Fail-Closed 설계
가장 중요한 설계 원칙입니다. Tree-sitter가 명령어를 파싱하지 못하면 — 문법 에러든, 알 수 없는 구문이든 — 기본적으로 차단합니다. “이해할 수 없는 것은 실행하지 않는다”는 원칙입니다.
이 방식의 트레이드오프는 명확합니다. 안전하지만 때때로 정당한 명령이 차단될 수 있습니다. 하지만 에이전트 시스템에서 보안은 편의성보다 우선입니다.
Hook System: 실행 흐름에 개입하기
Hook은 도구 실행 파이프라인의 특정 지점에 외부 로직을 삽입하는 메커니즘입니다.
timeline
title Hook Lifecycle
SessionStart : 세션 초기화 시
UserPromptSubmit : 사용자 입력 제출 시
PreToolUse : 도구 실행 직전
PostToolUse : 도구 실행 직후
Stop : 에이전트 응답 완료 시
Hook 응답 타입
| 응답 필드 | 효과 |
|---|---|
continue: false | 전체 파이프라인 중단 |
decision: "block" | 해당 도구 실행만 차단 |
updatedInput | 도구 입력 파라미터 수정 |
additionalContext | LLM에 추가 컨텍스트 주입 |
PreToolUse 훅에서 updatedInput을 사용하면, LLM이 요청한 파라미터를 실행 전에 수정할 수 있습니다. 예를 들어 기업 환경에서 특정 디렉토리 경로를 강제로 변경하거나, 민감한 파라미터를 마스킹하는 데 사용합니다.
additionalContext는 도구 실행 결과와 함께 LLM에 전달됩니다. 도구가 반환하지 않는 부가 정보(예: “이 파일은 최근에 수정되었으므로 주의하라”)를 주입할 수 있습니다.
BashTool 특수 기능
BashTool은 단순한 명령어 실행기가 아닙니다. 두 가지 핵심 기능이 사용 경험을 크게 개선합니다.
15초 타임아웃과 백그라운드 자동 전환: 명령어가 15초 이상 실행되면, 자동으로 백그라운드 태스크로 전환됩니다. LLM은 “명령어가 오래 걸리고 있으니 백그라운드에서 계속 실행하겠다”는 메시지를 받고, 다른 작업을 먼저 진행할 수 있습니다.
2초 간격 진행 보고: 장시간 실행되는 명령의 stdout/stderr를 2초마다 캡처하여 LLM에 진행 상황을 보고합니다. npm install이 패키지를 하나씩 설치하는 과정을 LLM이 실시간으로 추적할 수 있습니다.
이 두 기능은 에이전트의 “기다리는 시간”을 최소화합니다. 전통적인 동기 실행 모델에서는 npm install이 끝날 때까지 에이전트 전체가 멈추지만, Claude Code에서는 다른 도구를 먼저 실행하면서 설치 완료를 비동기로 대기합니다.
AgentTool: 5가지 실행 모드
Agent 도구는 서브 에이전트를 생성하여 작업을 위임합니다. 5가지 모드가 있습니다.
| 모드 | 프로세스 | 상태 격리 | 주요 용도 |
|---|---|---|---|
| Same-process Immediate | 동일 프로세스 | 공유 | 단순 위임, 빠른 응답 |
| Background Async | 동일 프로세스, 비동기 | 공유 | 긴 작업 병렬 처리 |
| Tmux Panel (Teammate) | 별도 tmux 패널 | 부분 격리 | 사용자와 동시 작업 |
| Isolated Git Worktree | 별도 프로세스 | 완전 격리 (별도 git worktree) | 병렬 브랜치 작업 |
| Remote Cloud | 원격 서버 | 완전 격리 | CI/CD 연동, 대규모 작업 |
Isolated Git Worktree 모드가 특히 흥미롭습니다. 동일 저장소의 다른 브랜치에서 독립적으로 작업할 수 있습니다. 메인 브랜치에서 코드 리뷰를 하면서, 서브 에이전트가 feature 브랜치에서 테스트를 실행하는 식입니다. git worktree를 활용하므로 저장소를 복제하지 않아 디스크 공간을 절약합니다.
핵심 수치 정리
| 항목 | 수치 |
|---|---|
| 전체 도구 수 | 52개 (41 활성 + 11 gated) |
| 도구 카테고리 | 8개 |
| 실행 파이프라인 단계 | 10단계 |
| 병렬 배치 최대 크기 | 10개 |
| 권한 파이프라인 단계 | 5단계 |
| 권한 모드 | 4가지 |
| Bash 보안 코드 크기 | 888KB (18개 파일) |
| Bash 보안 검사 단계 | 23단계 |
| Hook 포인트 | 5개 |
| AgentTool 실행 모드 | 5가지 |
| BashTool 타임아웃 | 15초 (이후 백그라운드 전환) |
| 진행 보고 주기 | 2초 |
마무리: 도구 시스템이 에이전트의 품질을 결정한다
52개 도구, 10단계 파이프라인, 23단계 보안이라는 숫자가 말해주는 것은 단순합니다. 에이전트의 실제 능력은 LLM의 추론 능력만으로 결정되지 않습니다. 도구를 얼마나 안전하게, 효율적으로, 확장 가능하게 관리하느냐가 프로덕션 에이전트의 품질을 결정합니다.
Claude Code의 설계에서 세 가지 원칙이 반복적으로 등장합니다.
첫째, 일관성. 52개 도구가 동일한 인터페이스와 파이프라인을 거칩니다. 새 도구를 추가해도 기존 인프라가 그대로 적용됩니다.
둘째, 안전 우선. fail-closed 설계, 23단계 AST 검사, 5단계 권한 파이프라인. 편의성보다 안전을 선택했고, 그 비용을 다른 최적화(스트리밍 오버랩, 백그라운드 전환)로 상쇄합니다.
셋째, 확장 가능성. Hook 시스템, MCP 통합, Feature Flag. 코어를 수정하지 않고 동작을 변경할 수 있는 지점이 곳곳에 설계되어 있습니다.
에이전트 시스템을 설계한다면, LLM 프롬프트보다 Tool System에 먼저 투자하는 것이 올바른 순서입니다.
Sources & Limitations
이 시리즈는 아래 공개 분석 자료를 종합하여 작성했으며, 유출된 소스 코드를 직접 포함하지 않습니다.
| Source | URL | 특징 |
|---|---|---|
| ccunpacked.dev | ccunpacked.dev | 시각적 아키텍처 가이드, 도구/커맨드 카탈로그 |
| Wikidocs 분석서 | wikidocs.net/338204 | 한국어 상세 기술 분석 (실행 흐름, 상태 관리, 렌더링) |
| PyTorch KR | discuss.pytorch.kr | GeekNews 기반 커뮤니티 분석 + HN 의견 종합 |
| Claw Code | github.com/ultraworkers/claw-code | 클린룸 재구현 (Rust/Python), PARITY.md 패리티 갭 분석 |
분석 시점: 2026-04-02. Anthropic은 유출 직후 DMCA로 8,100+ 포크를 차단하고 npm 배포를 중단했으므로, 일부 소스의 접근성이 변경되었을 수 있습니다. 또한 Feature Flag 뒤의 미공개 기능은 출시 전 변경되거나 폐기될 수 있습니다.
관련 글

에이전트 시스템 설계 캔버스 — Claude Code 유출이 증명한 12가지 프로덕션 패턴
Claude Code 소스 유출(512K줄 TS)에서 확인된 에이전트 시스템 설계의 6-Layer 캔버스와 8+4 핵심 패턴. 250K/일 API 낭비를 3줄로 해결한 Circuit Breaker부터, 23단계 bash AST 보안까지.

Claude Code 유출이 보여준 것: AI 에이전트의 해부학
2026년 3월 31일 npm 소스맵 사고로 드러난 Claude Code 내부. 4단계 실행, 7가지 모드, 11단계 Agent Loop의 전체 구조를 분석

매일 버려지는 학습 시그널 — AI 초안과 최종본 사이의 간극
AI 초안을 수정할 때마다 발생하는 implicit feedback(편집 diff)을 캡처하고, 주기적으로 패턴을 분석하여 프롬프트를 자동 진화시키는 Self-Tuning Loop 패턴. 학술 연구(DSPy, TextGrad, POHF)와의 gap 분석 포함.