Claude Code의 Plan mode는 프롬프트 엔지니어링일 뿐, 강제적인 제약이 아니다
요약
Claude Code의 Plan mode는 실제 시스템 제약이 아닌 프롬프트 기반의 권고 사항일 뿐임을 소스 코드 분석을 통해 밝힙니다. 다른 모드와 달리 Plan mode는 런타임 체크나 거부 목록을 사용하지 않는다는 점을 지적합니다.
핵심 포인트
- Plan mode는 시스템 리마인더를 통한 프롬프트 엔지니어링 방식임
- 실제 도구 실행 경로에는 Plan mode를 위한 강제적 제약이 없음
- 다른 모드(default, auto 등)는 실제 런타임 권한 체크를 수행함
- 에이전트 설계 시 권고와 강제 집행의 차이를 인지해야 함
문제점 (Problem)
Claude Code는 6가지 권한 모드 (permission modes)를 제공합니다. Plan mode는 그중 하나입니다. 이 모드가 활성화되면, 마치 실제 가드레일 (guardrail)처럼 보이는 시스템 리마인더 (system reminder)가 주입됩니다:
Plan mode가 활성화되었습니다. 사용자가 아직 실행을 원하지 않는다고 표시했습니다.
-- 당신은 어떠한 수정도 해서는 안 되며, 읽기 전용이 아닌 도구(설정 변경 또는 커밋 포함)를 실행하거나, 그 외 시스템에 어떠한 변경도 가해서는 안 됩니다.
문장만 본다면 모델이 진정으로 제약받고 있다고 믿기 쉽습니다. 하지만 소스 코드를 읽어보면 그렇지 않습니다. 이 리마인더는 이름 그대로 컨텍스트 (context) 내에 존재하는 하나의 문자열일 뿐입니다. 도구 실행 경로 (tool execution path) 어디에도 도구 수준의 거부 목록 (deny list), 디스패치 단계의 권한 확인 (dispatch-stage permission check), 또는 모드 인지형 허용 목록 (mode-aware allow-list)이 존재하지 않습니다.
소스 코드상에 존재하는 격차 (Where the gap is, in source)
Claude Code 패키지에서 발견된 세 가지 증거입니다:
- **시스템 리마인더는
messages.ts:3227에 `
Plan이 Claude Code에서 유일한 프롬프트 전용 구조물은 아니지만, 대부분의 유사한 기능들이 실제 런타임 체크 (runtime checks)를 수반한다는 점에서 Plan은 눈에 띄게 다릅니다:
| 모드 | 메커니즘 | 실제 강제성 여부? |
|---|---|---|
default | 익숙하지 않은 작업에 대해 권한 승인 프롬프트(permission prompt)를 띄움 | 예 |
| ... |
표준 빌드에서의 Shift+Tab 사이클은 default → acceptEdits → plan → bypass → default로, 4단계 루프를 형성합니다. dontAsk가 존재하지만, 이는 플래그(flag)나 설정을 통해서만 도달할 수 있습니다.
흥미로운 클러스터는 bypassPermissions와 auto입니다. 두 기능 모두 실제적인 피해를 줄 수 있으므로, Plan 모드는 절대 호출하지 않는 정적 위험 탐지 (static danger detection) 계층과 함께 배포됩니다:
permissionSetup.ts:94-147의isDangerousBashPermission()— 와일드카드나 인터프리터(interpreter)를 사용하는 Bash 규칙을 플래그(flag) 처리합니다.permissionSetup.ts:157-233의isDangerousPowerShellPermission()—iex,Start-Process등을 플래그(flag) 처리합니다.L295-342의findDangerousClassifierPermissions()— auto 모드로 진입하기 전 모든 허용 규칙을 스캔합니다.L510-553의stripDangerousPermissionsForAutoMode()— auto 모드인 동안 위험한 규칙들을strippedDangerousRules로 이동시킵니다.L561-579의restoreDangerousPermissions()— auto 모드를 벗어날 때 이를 복구합니다.
강제 실행 인프라(enforcement infrastructure)는 이미 존재합니다. 단지 Plan 모드가 그 중 어떤 것도 사용하지 않을 뿐입니다.
교훈 (Lessons learned)
-
권고(Advisory) vs. 강제 집행(Hard enforcement). 에이전트 기반 코딩 제품에서 "모델에게 X를 하지 말라고 말하는 것"과 "모델이 X를 할 수 없는 것"은 근본적으로 다른 두 가지 속성입니다. 전자는 희망 사항이며, 후자는 도구 계층(tool-layer)의 로직을 필요로 합니다. Plan 모드는 전자에 해당합니다.
-
프롬프트 우회(Prompt bypass)에는 악의가 필요하지 않습니다. 정교한 인젝션(injection)이 필요하지 않습니다. 긴 대화와 컨텍스트 드리프트(context drift)는 모델의 유효한 주의력(attention) 범위 밖으로 시스템 리마인더(system reminders)를 자연스럽게 밀어냅니다. 충분한 토큰, 충분한 도구 결과, 충분한 문답이 이어지면 리마인더는 효과적으로 사라질 때까지 희석됩니다.
-
진정한 해결책의 모습.
Edit,Write,Bash를Tool.isReadOnly()를 참조하고 부작용(side effects)이 발생하기 _전_에 Plan 모드에서의 호출을 거부하는 모드 인식 디스패처(mode-aware dispatcher)로 감싸야 합니다. 허용 목록(allow-list)은 산문(prose)이 아니라 데이터여야 합니다. 모델은 스스로에게 "이 쓰기 작업은 괜찮아"라고 설득할 수 있지만,return문을 말로 설득해서 통과할 수는 없습니다. -
표준 보안 패턴. 이것은 숙련되지 않은 보안 시스템이 아닌 모든 시스템이 사용하는 정책(policy)과 권고(advisory)의 분리입니다. 심층 방어(Defense in depth) 원칙에 따르면, 정책은 설득될 수 있는 계층보다 더 낮은 계층에 존재해야 합니다.
Claude Agent SDK에 미치는 영향
Agent SDK는 permission_mode를 노출합니다. coreSchemas.ts:339에 있는 열거형(enum)에는 'dontAsk'가 포함되어 있어, 다운스트림 개발자들이 실제 강제 집행을 선택할 수 있습니다. 하지만 그들은 또한 자신만의 Plan 모드 형태의 가드(guard)를 작성할 수도 있습니다: "강력한 시스템 프롬프트를 설정하고 희망하기"와 같은 방식 말입니다.
두 번째 경로를 선택하는 사람은 누구나 동일한 종류의 버그를 배포하게 됩니다. Agent-SDK 문서와 에이전트 설계 검토(design reviews) 시, 어떤 보장이 런타임(runtime)에서 오는지, 그리고 어떤 보장이 모델이 준수하도록 요청받은 문자열(string)에서 오는지 명시적으로 밝히는 것이 가치가 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기