🔧
Part 2중급⏱ 약 50분 · 3개 섹션
Tool 인터페이스 설계
모든 도구의 청사진

✦이 챕터에서 배울 것
전체 아키텍처에서 현재 위치
⚙️코어 엔진
→🔧도구 시스템
→🛡️보안
→🧠컨텍스트
→🤝멀티 에이전트
→🌐생태계
→⚡인프라
1
Tool 타입 정의 해부
Tool<Input, Output, P> 제네릭의 각 파라미터와 메서드를 분석합니다
제네릭 타입Zod 스키마LazySchemaToolResult|
Tool.tsClaude Code의 모든 도구는 Tool<Input, Output, P> 제네릭 인터페이스를 구현합니다. 이 인터페이스는 792줄의 src/Tool.ts에 정의되어 있으며, 50개 이상의 도구가 동일한 계약을 따릅니다.
핵심 타입 파라미터:
Input— Zod 스키마로 정의된 입력 타입 (strictObject로 알려지지 않은 필드 거부)Output— 도구 실행 결과 타입P extends ToolProgressData— 스트리밍 진행률 타입 (BashProgress, AgentToolProgress 등)
src/Tool.ts:362-450 — Tool 인터페이스 정의
1// src/Tool.ts — 핵심 Tool 인터페이스 (792줄 중 발췌)2 3export type Tool<💡4 Input extends AnyObject = AnyObject,5 Output = unknown,6 P extends ToolProgressData = ToolProgressData,7> = {8 // ─── 식별 ───9 aliases?: string[] // 이름 변경 시 하위 호환 별칭10 searchHint?: string // ToolSearch 키워드 매칭 (3-10 단어)11 12 // ─── 핵심 메서드 ───13 call(💡14 args: z.infer<Input>,15 context: ToolUseContext,16 canUseTool: CanUseToolFn,17 parentMessage: AssistantMessage,18 onProgress?: ToolCallProgress<P>,19 ): Promise<ToolResult<Output>>20 21 description(input, options): Promise<string>22 readonly inputSchema: Input // Zod 스키마23 outputSchema?: z.ZodType<unknown>24 25 // ─── 안전성 메서드 ───26 isConcurrencySafe(input): boolean // 기본: false (fail-closed)27 isEnabled(): boolean // 기본: true💡28 isReadOnly(input): boolean // 기본: false29 isDestructive?(input): boolean // 기본: false30 31 // ─── 인터럽트 동작 ───32 interruptBehavior?(): 'cancel' | 'block' // 기본: 'block'33 34 // ─── 검색/읽기 분류 (UI 최적화) ───35 isSearchOrReadCommand?(input): {36 isSearch: boolean37 isRead: boolean38 isList?: boolean💡39 }💡40 41 // ─── 지연 로딩 ───42 readonly shouldDefer?: boolean // ToolSearch로만 접근43 readonly alwaysLoad?: boolean // 항상 모델에 전달44 45 // ─── 권한 ───46 checkPermissions(input, context): Promise<PermissionResult>47 validateInput?(input, context): Promise<ValidationResult>48 getPath?(input): string49 preparePermissionMatcher?(input): Promise<(pattern: string) => boolean>50 51 // ─── 렌더링 (UI.tsx) ───52 renderToolUseMessage(input, options): ReactNode53 renderToolResultMessage(result, options): ReactNode54 renderToolUseProgressMessage?(progress, options): ReactNode55 getToolUseSummary(input): string56 userFacingName(input): string57}💡 fail-closed 원칙
isConcurrencySafe()의 기본값이 false인 이유: 새 도구를 추가할 때 개발자가 동시성 안전을 깜빡하고 선언하지 않으면, 시스템은 '안전하지 않다'고 가정합니다. 이것이 보안 시스템의 핵심 원칙인 fail-closed입니다. 반대로 fail-open이면 선언을 깜빡한 도구가 병렬 실행되어 레이스 컨디션이 발생할 수 있습니다.
2
buildTool() 팩토리 패턴
안전한 기본값 적용과 타입 추론
팩토리 패턴기본값 설계fail-closed타입 추론|
Tool.tstools.tsbuildTool() 팩토리 함수는 안전한 기본값을 적용하여 도구를 생성합니다. 모든 도구는 이 함수를 통해 만들어집니다.
src/Tool.ts + src/tools/GrepTool/GrepTool.ts
1// src/Tool.ts:750-792 — TOOL_DEFAULTS와 buildTool()2 3const TOOL_DEFAULTS = {4 isEnabled: () => true,💡5 isConcurrencySafe: (_input?: unknown) => false, // ← fail-closed6 isReadOnly: (_input?: unknown) => false, // ← 쓰기 가정7 isDestructive: (_input?: unknown) => false,8 checkPermissions: (input, _ctx?) =>9 Promise.resolve({ behavior: 'allow', updatedInput: input }), // ← 일반 권한에 위임10 toAutoClassifierInput: (_input?: unknown) => '', // ← 분류기 건너뛰기11 userFacingName: (_input?: unknown) => '',12}13 14export function buildTool<D extends AnyToolDef>(def: D): BuiltTool<D> {💡15 return {16 ...TOOL_DEFAULTS, // 1. 안전한 기본값 적용17 userFacingName: () => def.name, // 2. 이름 기본값18 ...def, // 3. 사용자 정의로 오버라이드19 } as BuiltTool<D>20}21 22// ─── 사용 예시: GrepTool ───23export const GrepTool = buildTool({24 name: GREP_TOOL_NAME,25 searchHint: 'search file contents regex ripgrep',26 inputSchema: lazySchema(() => z.strictObject({💡27 pattern: z.string().describe('정규식 패턴'),28 path: z.string().optional(),29 // ...30 })),31 isConcurrencySafe: () => true, // ← 읽기 전용이므로 명시적 선언32 isReadOnly: () => true, // ← 읽기 전용33 async call(input, context) {34 const results = await ripGrep(input.pattern, resolvedPath);35 return { output: results };36 },37})3
도구 등록과 검색
getAllBaseTools(), assembleToolPool(), ToolSearch 메커니즘
도구 레지스트리피처 게이트MCP 도구 병합지연 로딩|
tools.tssrc/tools.ts는 모든 도구의 단일 진실 소스(Single Source of Truth)입니다. getAllBaseTools() 함수가 전체 도구 목록을 반환하며, 피처 게이트와 환경변수에 따라 조건부로 도구를 포함합니다.
src/tools.ts — 도구 등록 시스템
1// src/tools.ts — 도구 등록의 3계층 구조2 3// 1단계: 정적 import (항상 포함)4import { BashTool } from './tools/BashTool/BashTool.js'5import { FileEditTool } from './tools/FileEditTool/FileEditTool.js'6import { FileReadTool } from './tools/FileReadTool/FileReadTool.js'7import { GlobTool } from './tools/GlobTool/GlobTool.js'8import { GrepTool } from './tools/GrepTool/GrepTool.js'9 10// 2단계: 피처 게이트 (빌드 타임 dead code elimination)11const SleepTool = feature('PROACTIVE') || feature('KAIROS')💡12 ? require('./tools/SleepTool/SleepTool.js').SleepTool13 : null14const MonitorTool = feature('MONITOR_TOOL')15 ? require('./tools/MonitorTool/MonitorTool.js').MonitorTool16 : null17 18// 3단계: 환경변수 기반 (런타임)19const REPLTool = process.env.USER_TYPE === 'ant'20 ? require('./tools/REPLTool/REPLTool.js').REPLTool21 : null22 23// ─── 전체 도구 목록 반환 ───24export function getAllBaseTools(): Tools {25 return [💡26 AgentTool, BashTool, FileReadTool, FileEditTool,27 FileWriteTool, GlobTool, GrepTool, WebFetchTool,28 TodoWriteTool, WebSearchTool, AskUserQuestionTool,29 SkillTool, EnterPlanModeTool, ExitPlanModeV2Tool,30 NotebookEditTool, TaskStopTool, BriefTool,31 // 피처 게이트 도구32 ...(SleepTool ? [SleepTool] : []),33 ...(MonitorTool ? [MonitorTool] : []),34 ...(RemoteTriggerTool ? [RemoteTriggerTool] : []),35 // 환경변수 도구36 ...(process.env.USER_TYPE === 'ant' ? [ConfigTool, TungstenTool] : []),37 ...(REPLTool ? [REPLTool] : []),38 // ToolSearch (지연 로딩 활성화 시)39 ...(isToolSearchEnabledOptimistic() ? [ToolSearchTool] : []),💡40 ].filter(Boolean) as Tools41}42 43// ─── MCP 도구 병합 ───44export function assembleToolPool(builtIn, mcpTools): Tools {💡45 // 내장 도구가 MCP 도구보다 우선 (이름 충돌 시)46 return uniqBy([...builtIn, ...mcpTools], t => t.name)47}⚠️ dead code elimination의 중요성
feature('PROACTIVE')가 false이면 SleepTool의 require()는 빌드 결과에 아예 포함되지 않습니다. 이것은 번들 크기를 줄이는 것뿐 아니라, 해당 도구의 의존성 전체가 제거되는 효과가 있습니다. 단순한 if문이 아니라 빌드 타임 최적화입니다.
?
이해도 확인 퀴즈
buildTool()에서 isConcurrencySafe의 기본값이 false인 이유는?
✅ 학습 체크리스트
이해한 항목을 체크하고 학습 진도를 확인하세요
0/5 완료0%
📋 Chapter 4 요약: Tool 인터페이스 설계
이 챕터에서 배운 핵심 개념을 정리합니다
1
Tool 제네릭
Tool<Input, Output, P>로 모든 도구를 타입 안전하게 정의합니다.
2
buildTool 팩토리
TOOL_DEFAULTS + 사용자 정의를 스프레드로 병합하여 안전한 기본값을 보장합니다.
3
fail-closed
명시적 선언 없이는 동시 실행 불가 — 안전 우선 원칙.
4
도구 등록
정적 import + 피처 게이트 + 환경변수로 3단계 조건부 등록.
다음 챕터 미리보기: 다음 챕터에서는 FileEdit, Grep, BashTool 등 실제 도구 구현을 분석합니다.