<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Task-Management on ICE-ICE-BEAR-BLOG</title><link>https://ice-ice-bear.github.io/ko/tags/task-management/</link><description>Recent content in Task-Management on ICE-ICE-BEAR-BLOG</description><generator>Hugo -- gohugo.io</generator><language>ko</language><lastBuildDate>Mon, 06 Apr 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://ice-ice-bear.github.io/ko/tags/task-management/index.xml" rel="self" type="application/rss+xml"/><item><title>Claude Code 하네스 해부학 #3 — 42개 도구의 설계 철학, BashTool부터 AgentTool까지</title><link>https://ice-ice-bear.github.io/ko/posts/2026-04-06-harness-anatomy-3/</link><pubDate>Mon, 06 Apr 2026 00:00:00 +0900</pubDate><guid>https://ice-ice-bear.github.io/ko/posts/2026-04-06-harness-anatomy-3/</guid><description>&lt;img src="https://ice-ice-bear.github.io/" alt="Featured image of post Claude Code 하네스 해부학 #3 — 42개 도구의 설계 철학, BashTool부터 AgentTool까지" /&gt;&lt;h2 id="개요"&gt;개요
&lt;/h2&gt;&lt;p&gt;Claude Code에는 42개의 도구가 존재한다. 이 포스트에서는 &lt;code&gt;Tool.ts&lt;/code&gt;의 30+ 멤버 인터페이스가 구현하는 &amp;ldquo;도구가 자신을 알고 있다&amp;rdquo; 패턴을 해부하고, 42개 도구를 8개 패밀리로 분류한다. 그 중 가장 복잡한 BashTool(12,411줄)의 6계층 보안 체인, AgentTool(6,782줄)의 4가지 스폰 모드, FileEditTool의 문자열 매칭 전략, MCPTool의 빈 껍데기 프록시 패턴, Task 상태 머신을 심층 분석한다.&lt;/p&gt;
&lt;h2 id="1-tool-인터페이스--도구가-자신을-알고-있다"&gt;1. Tool 인터페이스 &amp;ndash; &amp;ldquo;도구가 자신을 알고 있다&amp;rdquo;
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Tool.ts&lt;/code&gt;(792줄)는 도구 시스템의 계약서다. 모든 도구가 구현하는 &lt;code&gt;Tool&lt;/code&gt; 타입(Tool.ts:362-695)은 &lt;strong&gt;30개 이상의 멤버&lt;/strong&gt;로 구성되며 네 영역으로 나뉜다:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;영역&lt;/th&gt;
 &lt;th&gt;핵심 멤버&lt;/th&gt;
 &lt;th&gt;역할&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;실행 계약&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;call()&lt;/code&gt;, &lt;code&gt;inputSchema&lt;/code&gt;, &lt;code&gt;validateInput()&lt;/code&gt;, &lt;code&gt;checkPermissions()&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;도구의 핵심 로직&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;메타데이터&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;name&lt;/code&gt;, &lt;code&gt;aliases&lt;/code&gt;, &lt;code&gt;searchHint&lt;/code&gt;, &lt;code&gt;shouldDefer&lt;/code&gt;, &lt;code&gt;maxResultSizeChars&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;검색과 표시&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;동시성/안전성&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;isConcurrencySafe()&lt;/code&gt;, &lt;code&gt;isReadOnly()&lt;/code&gt;, &lt;code&gt;isDestructive()&lt;/code&gt;, &lt;code&gt;interruptBehavior()&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;오케스트레이션 결정&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UI 렌더링&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;renderToolUseMessage()&lt;/code&gt; 등 10개+&lt;/td&gt;
 &lt;td&gt;터미널 표시&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;왜 이렇게 많은 멤버가 한 인터페이스에?&lt;/strong&gt; 오케스트레이터(&lt;code&gt;toolExecution.ts&lt;/code&gt;)가 도구를 호출할 때 외부 매핑 테이블 없이 도구 객체 자체에서 모든 메타데이터를 읽을 수 있다. 새 도구 추가가 &lt;strong&gt;한 디렉토리 안에서 완결&lt;/strong&gt;되는 플러그인 아키텍처의 근간이다.&lt;/p&gt;
&lt;h3 id="toolusecontext--42개-필드의-실행-환경"&gt;ToolUseContext &amp;ndash; 42개 필드의 실행 환경
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;ToolUseContext&lt;/code&gt;(Tool.ts:158-300)는 도구 실행 시 주입되는 환경 컨텍스트다. 142줄에 걸쳐 42개 필드가 정의되어 있다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;abortController&lt;/code&gt;: 3-tier 동시성 모델의 취소 전파&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getAppState()&lt;/code&gt;/&lt;code&gt;setAppState()&lt;/code&gt;: 전역 상태 접근 (권한, todo, 팀)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readFileState&lt;/code&gt;: LRU 캐시 기반 변경 감지&lt;/li&gt;
&lt;li&gt;&lt;code&gt;contentReplacementState&lt;/code&gt;: 대용량 결과를 디스크에 저장하고 요약만 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;도구는 격리된 함수가 아니라 하네스의 전체 상태에 접근해야 한다. FileReadTool은 캐시로 변경 여부를 판단하고, AgentTool은 서브에이전트 상태를 등록하며, BashTool은 형제 프로세스를 중단한다.&lt;/p&gt;
&lt;h3 id="buildtool의-fail-closed-기본값"&gt;buildTool()의 fail-closed 기본값
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;buildTool()&lt;/code&gt;(Tool.ts:783)은 &lt;code&gt;ToolDef&lt;/code&gt;를 받아 기본값을 채운 완전한 &lt;code&gt;Tool&lt;/code&gt;을 반환한다. 기본값은 &lt;strong&gt;fail-closed&lt;/strong&gt; 원칙(Tool.ts:757-768):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;isConcurrencySafe&lt;/code&gt; -&amp;gt; &lt;code&gt;false&lt;/code&gt; (안전하지 않다고 가정)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isReadOnly&lt;/code&gt; -&amp;gt; &lt;code&gt;false&lt;/code&gt; (쓰기한다고 가정)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;새 도구를 만들 때 동시성/읽기전용을 명시적으로 선언하지 않으면 가장 보수적인 경로(순차 실행, 쓰기 권한 요구)를 탄다. &lt;strong&gt;실수로 안전하지 않은 도구를 병렬 실행하는 버그를 구조적으로 방지&lt;/strong&gt;한다.&lt;/p&gt;
&lt;h2 id="2-42개-도구의-8개-패밀리"&gt;2. 42개 도구의 8개 패밀리
&lt;/h2&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart LR
 subgraph safe["isConcurrencySafe: true (10개)"]
 direction TB
 R1["FileReadTool"]
 R2["GlobTool / GrepTool"]
 R3["WebFetchTool / WebSearchTool"]
 R4["ToolSearchTool / SleepTool"]
 R5["TaskGetTool / TaskListTool"]
 R6["LSPTool"]
 end

 subgraph unsafe["isConcurrencySafe: false (32개)"]
 direction TB
 W1["BashTool 12,411줄"]
 W2["FileEditTool / FileWriteTool"]
 W3["AgentTool 6,782줄"]
 W4["MCPTool / SkillTool"]
 W5["Task 5개 / Todo"]
 W6["Config / PlanMode / Worktree"]
 end

 subgraph orch["오케스트레이터"]
 O["partitionToolCalls()&amp;lt;br/&amp;gt;toolOrchestration.ts"]
 end

 O --&gt;|"병렬 배치"| safe
 O --&gt;|"순차 실행"| unsafe

 style safe fill:#e8f5e9
 style unsafe fill:#ffebee&lt;/pre&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;패밀리&lt;/th&gt;
 &lt;th&gt;도구 수&lt;/th&gt;
 &lt;th&gt;대표 도구&lt;/th&gt;
 &lt;th&gt;핵심 특징&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;파일시스템&lt;/td&gt;
 &lt;td&gt;5&lt;/td&gt;
 &lt;td&gt;FileReadTool (1,602줄)&lt;/td&gt;
 &lt;td&gt;PDF/이미지/노트북 지원, 토큰 제한&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;실행&lt;/td&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;td&gt;BashTool (12,411줄)&lt;/td&gt;
 &lt;td&gt;6계층 보안, 명령 의미론&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;에이전트/팀&lt;/td&gt;
 &lt;td&gt;4&lt;/td&gt;
 &lt;td&gt;AgentTool (6,782줄)&lt;/td&gt;
 &lt;td&gt;4가지 스폰, 재귀적 하네스&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;태스크 관리&lt;/td&gt;
 &lt;td&gt;7&lt;/td&gt;
 &lt;td&gt;TaskUpdateTool (484줄)&lt;/td&gt;
 &lt;td&gt;상태 머신, 검증 넛지&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;MCP/LSP&lt;/td&gt;
 &lt;td&gt;5&lt;/td&gt;
 &lt;td&gt;MCPTool (1,086줄)&lt;/td&gt;
 &lt;td&gt;빈 껍데기 프록시&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;웹/외부&lt;/td&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;WebFetchTool (1,131줄)&lt;/td&gt;
 &lt;td&gt;병렬 안전&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;상태/설정&lt;/td&gt;
 &lt;td&gt;5&lt;/td&gt;
 &lt;td&gt;ConfigTool (809줄)&lt;/td&gt;
 &lt;td&gt;세션 상태 변경&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;인프라/유틸&lt;/td&gt;
 &lt;td&gt;11&lt;/td&gt;
 &lt;td&gt;SkillTool (1,477줄)&lt;/td&gt;
 &lt;td&gt;커맨드-도구 브리지&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;42개 중 10개(24%)만 병렬 실행 가능하지만, 이 10개가 가장 빈번하게 호출되는 도구(Read, Glob, Grep, Web)이므로 실제 체감 병렬성은 비율보다 높다.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="3-bashtool--6계층-보안-체인"&gt;3. BashTool &amp;ndash; 6계층 보안 체인
&lt;/h2&gt;&lt;p&gt;BashTool은 단순한 셸 실행기가 아니다. &lt;strong&gt;임의 코드 실행&lt;/strong&gt;이라는 본질적 위험 때문에 12,411줄의 절반 이상이 보안 레이어다.&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB
 A["모델: Bash 호출"] --&gt; B{"validateInput"}
 B --&gt;|"sleep 패턴 차단"| B1["에러 반환"]
 B --&gt;|"통과"| C{"6계층 보안 체인"}

 subgraph chain["보안 체인"]
 C1["1. bashSecurity.ts&amp;lt;br/&amp;gt;2,592줄 -- 명령 구조 분석"]
 C2["2. bashPermissions.ts&amp;lt;br/&amp;gt;2,621줄 -- 규칙 매칭"]
 C3["3. readOnlyValidation.ts&amp;lt;br/&amp;gt;1,990줄 -- 읽기전용 판단"]
 C4["4. pathValidation.ts&amp;lt;br/&amp;gt;1,303줄 -- 경로 기반 보안"]
 C5["5. sedValidation.ts&amp;lt;br/&amp;gt;684줄 -- sed 전용 보안"]
 C6["6. shouldUseSandbox.ts&amp;lt;br/&amp;gt;153줄 -- 샌드박스 결정"]
 C1 --&gt; C2 --&gt; C3 --&gt; C4 --&gt; C5 --&gt; C6
 end

 C --&gt; chain
 chain --&gt; D{"allow / ask / deny"}
 D --&gt;|"allow"| E["runShellCommand()"]
 D --&gt;|"ask"| F["사용자 승인 요청"]
 D --&gt;|"deny"| G["거부"]
 E --&gt; H["결과 처리&amp;lt;br/&amp;gt;interpretCommandResult()&amp;lt;br/&amp;gt;trackGitOperations()"]

 style chain fill:#fff3e0&lt;/pre&gt;&lt;p&gt;각 레이어가 다른 위협을 담당한다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;bashSecurity.ts&lt;/strong&gt; (2,592줄): 명령 치환(&lt;code&gt;$()&lt;/code&gt;, &lt;code&gt;`&lt;/code&gt;), Zsh 모듈 기반 공격 차단. 핵심: &lt;strong&gt;unquoted 컨텍스트의 메타문자만 위험으로 분류&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;bashPermissions.ts&lt;/strong&gt; (2,621줄): 규칙 기반 allow/deny/ask. &lt;code&gt;stripAllLeadingEnvVars()&lt;/code&gt; + &lt;code&gt;stripSafeWrappers()&lt;/code&gt;로 래퍼 제거 후 실제 명령 추출&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;readOnlyValidation.ts&lt;/strong&gt; (1,990줄): 읽기전용이면 &lt;code&gt;isConcurrencySafe: true&lt;/code&gt; &amp;ndash; 병렬 실행 허용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pathValidation.ts&lt;/strong&gt; (1,303줄): 명령별 경로 추출 규칙으로 경로 안전성 판단&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sedValidation.ts&lt;/strong&gt; (684줄): sed의 &lt;code&gt;w&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt; 플래그는 파일 쓰기/임의 실행 가능 &amp;ndash; 별도 차단&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;shouldUseSandbox.ts&lt;/strong&gt; (153줄): 최종 격리 결정&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;명령 의미론&lt;/strong&gt; (&lt;code&gt;commandSemantics.ts&lt;/code&gt;): &lt;code&gt;grep&lt;/code&gt;과 &lt;code&gt;diff&lt;/code&gt;는 exit code 1이 에러가 아닌 정상 결과다. &lt;code&gt;COMMAND_SEMANTICS&lt;/code&gt; Map으로 명령별 해석 규칙을 정의한다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rust 포팅 시사점&lt;/strong&gt;: 이 6계층을 통째로 재현하거나, 아예 sandbox-only로 단순화해야 한다. 중간 단계 생략은 보안 구멍을 만든다.&lt;/p&gt;
&lt;h2 id="4-agenttool--4가지-스폰-모드"&gt;4. AgentTool &amp;ndash; 4가지 스폰 모드
&lt;/h2&gt;&lt;p&gt;AgentTool은 &amp;ldquo;도구&amp;quot;라기보다 &lt;strong&gt;에이전트 오케스트레이터&lt;/strong&gt;다. 핵심: &lt;code&gt;runAgent()&lt;/code&gt;는 하네스의 &lt;code&gt;query()&lt;/code&gt; 루프를 재귀 호출한다. 자식 에이전트는 부모와 동일한 도구/API/보안 체크를 받는다.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;모드&lt;/th&gt;
 &lt;th&gt;트리거&lt;/th&gt;
 &lt;th&gt;컨텍스트 공유&lt;/th&gt;
 &lt;th&gt;백그라운드&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;동기&lt;/td&gt;
 &lt;td&gt;기본&lt;/td&gt;
 &lt;td&gt;없음 (프롬프트만)&lt;/td&gt;
 &lt;td&gt;X&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;비동기&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;run_in_background: true&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;없음&lt;/td&gt;
 &lt;td&gt;O&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;포크&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;subagent_type&lt;/code&gt; 생략&lt;/td&gt;
 &lt;td&gt;부모 전체 컨텍스트&lt;/td&gt;
 &lt;td&gt;O&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;원격&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;isolation: &amp;quot;remote&amp;quot;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;없음&lt;/td&gt;
 &lt;td&gt;O&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="포크-서브에이전트--byte-identical-프리픽스"&gt;포크 서브에이전트 &amp;ndash; byte-identical 프리픽스
&lt;/h3&gt;&lt;p&gt;포크는 부모의 &lt;strong&gt;전체 대화 컨텍스트를 상속&lt;/strong&gt;한다. 프롬프트 캐시 공유를 위해 모든 포크 자식이 byte-identical API 요청 프리픽스를 생성하도록 설계한다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;도구 사용 결과를 플레이스홀더로 대체&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FORK_BOILERPLATE_TAG&lt;/code&gt;로 재귀 포크 방지&lt;/li&gt;
&lt;li&gt;모델 동일 유지 (&lt;code&gt;model: 'inherit'&lt;/code&gt;) &amp;ndash; 다른 모델은 캐시 불일치&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="메모리-시스템-agentmemoryts"&gt;메모리 시스템 (agentMemory.ts)
&lt;/h3&gt;&lt;p&gt;에이전트별 지속 메모리를 3가지 스코프로 관리:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;user&lt;/strong&gt;: &lt;code&gt;~/.claude/agent-memory/&amp;lt;type&amp;gt;/&lt;/code&gt; &amp;ndash; 사용자 전역&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;project&lt;/strong&gt;: &lt;code&gt;.claude/agent-memory/&amp;lt;type&amp;gt;/&lt;/code&gt; &amp;ndash; 프로젝트 공유 (VCS)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;local&lt;/strong&gt;: &lt;code&gt;.claude/agent-memory-local/&amp;lt;type&amp;gt;/&lt;/code&gt; &amp;ndash; 로컬 전용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="5-fileedittool--부분-대체-패턴"&gt;5. FileEditTool &amp;ndash; 부분 대체 패턴
&lt;/h2&gt;&lt;p&gt;FileEditTool(1,812줄)은 전체 파일 쓰기가 아닌 &lt;strong&gt;&lt;code&gt;old_string&lt;/code&gt; -&amp;gt; &lt;code&gt;new_string&lt;/code&gt; 패치&lt;/strong&gt;를 수행한다. 모델이 전체 파일을 출력할 필요가 없어 토큰을 절약하고, diff 기반 리뷰를 가능하게 한다.&lt;/p&gt;
&lt;p&gt;매칭 전략:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;정확한 문자열 매칭&lt;/strong&gt;: &lt;code&gt;fileContent.includes(searchString)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;따옴표 정규화&lt;/strong&gt;: curly quote -&amp;gt; straight quote 변환 후 재시도, &lt;code&gt;preserveQuoteStyle()&lt;/code&gt;로 원본 스타일 보존&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;고유성 검증&lt;/strong&gt;: &lt;code&gt;old_string&lt;/code&gt;이 파일에서 유일하지 않으면 실패 (또는 &lt;code&gt;replace_all&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;동시성 보호&lt;/strong&gt;: &lt;code&gt;readFileState&lt;/code&gt; Map에 파일별 마지막 읽기 타임스탬프를 저장. 편집 시 디스크 수정 시간과 비교하여 외부 변경을 감지한다. 이것이 &amp;ldquo;Read 후 Edit&amp;rdquo; 규칙이 프롬프트에서 강제되는 이유다.&lt;/p&gt;
&lt;h2 id="6-mcptool--빈-껍데기-프록시"&gt;6. MCPTool &amp;ndash; 빈 껍데기 프록시
&lt;/h2&gt;&lt;p&gt;MCPTool(1,086줄)은 &lt;strong&gt;하나의 도구 정의가 수백 개의 외부 도구를 대표&lt;/strong&gt;한다. 빌드 시점에는 빈 껍데기이고, 런타임에 &lt;code&gt;mcpClient.ts&lt;/code&gt;가 서버별로 복제 + 오버라이드한다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// MCPTool.ts:27-51 -- 핵심 메서드가 &amp;#34;Overridden in mcpClient.ts&amp;#34; 주석
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;mcp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 런타임에 &amp;#39;mcp__serverName__toolName&amp;#39;으로 교체
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;call() {&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// 런타임에 실제 MCP 호출로 교체
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;UI 축소 분류(&lt;code&gt;classifyForCollapse.ts&lt;/code&gt;, 604줄)는 139개 SEARCH_TOOLS, 280개+ READ_TOOLS 이름으로 MCP 도구의 읽기/검색 여부를 판단한다. 알 수 없는 도구는 축소하지 않는다(보수적).&lt;/p&gt;
&lt;h2 id="7-task-상태-머신--에이전트-ipc"&gt;7. Task 상태 머신 &amp;ndash; 에이전트 IPC
&lt;/h2&gt;&lt;p&gt;TaskUpdateTool(406줄)의 상태 흐름: &lt;code&gt;pending -&amp;gt; in_progress -&amp;gt; completed&lt;/code&gt; 또는 &lt;code&gt;deleted&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;핵심 행동:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;소유자 자동 설정&lt;/strong&gt;: &lt;code&gt;in_progress&lt;/code&gt; 변경 시 현재 에이전트 이름 자동 할당&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;검증 넛지&lt;/strong&gt;: 3개+ 태스크 완료 후 검증 단계가 없으면 verification agent 스폰 권고&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;메시지 라우팅&lt;/strong&gt; (SendMessageTool 917줄): 이름, &lt;code&gt;*&lt;/code&gt; 브로드캐스트, &lt;code&gt;uds:path&lt;/code&gt; Unix 도메인 소켓, &lt;code&gt;bridge:session&lt;/code&gt; 원격 피어, 에이전트 ID 재개&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Task/SendMessage는 단순한 유틸리티가 아니라 멀티에이전트 시스템의 &lt;strong&gt;프로세스 간 통신(IPC)&lt;/strong&gt; 기초다.&lt;/p&gt;
&lt;h2 id="ts-vs-rust-비교"&gt;TS vs Rust 비교
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;측면&lt;/th&gt;
 &lt;th&gt;TS (42개 도구)&lt;/th&gt;
 &lt;th&gt;Rust (10개 도구)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;도구 정의&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;Tool&lt;/code&gt; 인터페이스 + &lt;code&gt;buildTool()&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ToolSpec&lt;/code&gt; 구조체 + &lt;code&gt;mvp_tool_specs()&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;입력 스키마&lt;/td&gt;
 &lt;td&gt;Zod v4 + &lt;code&gt;lazySchema()&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;serde_json::json!()&lt;/code&gt; JSON Schema 직접&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;동시성 선언&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;isConcurrencySafe(parsedInput)&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;없음 &amp;ndash; 순차 실행&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;권한 검사&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;checkPermissions()&lt;/code&gt; -&amp;gt; &lt;code&gt;PermissionResult&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;PermissionMode&lt;/code&gt; enum&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;UI 렌더링&lt;/td&gt;
 &lt;td&gt;10+ render 메서드 (React/Ink)&lt;/td&gt;
 &lt;td&gt;없음&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;MCP 통합&lt;/td&gt;
 &lt;td&gt;MCPTool + &lt;code&gt;inputJSONSchema&lt;/code&gt; 이중 경로&lt;/td&gt;
 &lt;td&gt;없음&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;크기 비교&lt;/td&gt;
 &lt;td&gt;~48,000줄 (도구 코드만)&lt;/td&gt;
 &lt;td&gt;~1,300줄 (lib.rs 단일)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;핵심 격차&lt;/strong&gt;: Rust 포트는 실행 계약(&lt;code&gt;call&lt;/code&gt; 등가물)만 구현하고, 동시성 선언, 권한 파이프라인, UI 렌더링, 지연 로딩 최적화는 모두 없다.&lt;/p&gt;
&lt;h2 id="인사이트"&gt;인사이트
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;보안은 단일 체크포인트가 아니라 체인이다&lt;/strong&gt; &amp;ndash; BashTool의 6계층은 각 레이어가 다른 위협을 담당한다. bashSecurity는 명령 구조, bashPermissions는 규칙 매칭, pathValidation은 경로 안전성. 이 체인의 어느 한 곳이라도 빠지면 공격 표면이 열린다. fail-closed 원칙과 결합하여 &amp;ldquo;모르면 차단&amp;quot;이라는 보수적 전략이 전체 시스템을 관통한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;에이전트는 재귀적 하네스 인스턴스다&lt;/strong&gt; &amp;ndash; AgentTool의 &lt;code&gt;runAgent()&lt;/code&gt;가 하네스의 &lt;code&gt;query()&lt;/code&gt; 루프를 재귀 호출한다는 것은, &amp;ldquo;에이전트&amp;quot;가 별개의 시스템이 아니라 **같은 하네스의 다른 구성(configuration)**이라는 아키텍처 결정이다. 도구 풀만 교체하고 동일한 보안/훅/오케스트레이션을 재사용한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;42개 도구 중 10개만 concurrency-safe이지만 체감 병렬성은 높다&lt;/strong&gt; &amp;ndash; 전체의 24%에 불과한 10개 도구(Read, Glob, Grep, Web, LSP)가 가장 빈번하게 호출된다. 이 비대칭이 3-tier 동시성 모델의 실용적 가치를 보여준다. &lt;code&gt;buildTool()&lt;/code&gt;의 fail-closed 기본값(&lt;code&gt;isConcurrencySafe: false&lt;/code&gt;)이 안전 경계를 형성하여, 새 도구 개발자가 동시성을 잘못 선언하는 실수를 구조적으로 방지한다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;다음 포스트: &lt;a class="link" href="https://ice-ice-bear.github.io/posts/2026-04-06-harness-anatomy-4/" &gt;#4 &amp;ndash; 런타임 훅 26+이벤트와 CLAUDE.md 6단계 디스커버리&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>