내 프로젝트의 자체 지침이 에이전트에게 존재하지 않는 도구를 사용하도록 지시했습니다
요약
코딩 에이전트의 프로젝트 지침 파일(예: CLAUDE.md)에 명시된 '필수 규칙'들이 실제 실행 환경과 다를 때 발생하는 문제를 분석합니다. 오래되거나 업데이트되지 않은 문서화된 시스템 설명은 에이전트가 존재하지 않는 도구를 호출하거나 잘못된 절차를 따르게 하여 시간과 컨텍스트 자원을 낭비하게 만듭니다.
핵심 포인트
- 문서화된 지침(README 등)의 '필수' 규칙에 대한 과도한 신뢰는 위험할 수 있습니다.
- 오래되거나 환경 의존적인 시스템 설명은 에이전트에게 잘못된 행동을 유발합니다.
- 명령형 언어('MANDATORY')가 강한 안전 규칙 문구는 판단 과정을 단축시키고 복종하게 만듭니다.
- 코드와 달리 지침 파일에는 테스트 케이스가 없어 오류를 발견하기 어렵습니다.
저는 리포지토리 중 하나 루트에 CLAUDE.md 파일을 보관하고 있습니다. 이 파일은 코딩 에이전트가 해당 프로젝트에서 어떤 작업을 수행하기 전에 읽는 파일입니다. 여기에는 컨벤션, 주의사항, '이것을 하고 저것은 하지 마라'와 같은 내용이 담겨 있습니다. 제 파일에는 굵은 글씨로 된 '필수 라우팅 규칙(MANDATORY routing rules)'이라는 섹션이 있습니다. 이 섹션은 에이전트에게 대량의 명령어 출력을 컨텍스트에 덤프하는 대신 샌드박스를 통해 라우팅하기 위한 MCP 도구 세트가 존재하며, curl과 wget은 가로채져 차단되고, WebFetch는 아예 거부되며 대신 가져와 인덱싱하는(fetch-and-index) 도구로 리디렉션된다고 알려줍니다.
하지만 이 내용들은 해당 리포지토리가 체크아웃되는 모든 환경에서 사실이 아닙니다. 제가 실제로 실행했던 환경에서는 그러한 도구들이 연결되어 있지 않았습니다. 그것들을 제공했을 MCP 서버는 연결되지 않았고, curl도 차단되지 않았으며, WebFetch는 정상적으로 작동했습니다.
만약 에이전트가 CLAUDE.md를 액면 그대로 따른다면 다음과 같은 일이 발생했을 것입니다. URL을 가져와야 하는 단계에 도달하여 'WebFetch는 차단되었으니 대신 ctx_fetch_and_index를 사용하라'는 내용을 보고, 자신의 도구 목록에는 없는 도구를 호출하고, 하드 실패(hard failure)를 얻거나, 같은 존재하지 않는 도구를 몇 번 재시도하거나, 아예 해당 단계를 포기했을 것입니다. 어느 쪽이든, 파일이 했다고 맹세한 문제를 피하기 위해, 실제로 존재하지 않는 문제에 해결하는 데 시간과 컨텍스트가 소모되었습니다.
이것은 악의적인 프롬프트 주입(prompt injection)이 아닙니다. 아무도 사보타주를 위해 그 텍스트를 몰래 넣지 않았습니다. 단지 오래된 문서일 뿐입니다. 누군가가 한 환경을 위해 컨텍스트 라우팅 MCP 서버를 설정하고, 모든 미래 세션에서 그것을 올바르게 사용하도록 리포지토리 지침에 규칙을 작성한 다음, 도구링(tooling)이 이동했거나 다른 환경이 서버 없이 같은 리포지토리를 가져간 것입니다. 지침은 업데이트되지 않았는데, 아무것도 강제하지 않았기 때문입니다. CLAUDE.md는 코드가 아니므로 아무것도 실행되지 않고, 오래되었다고 해서 CI가 실패하는 것도 없습니다.
실제로 저를 걱정하게 만드는 부분
파일에서 'MANDATORY'라는 단어를 사용했습니다. '선호한다(prefer)'나 '사용 가능하다면(if available)'가 아니라—이 규칙들이 '선택 사항이 아님(NOT optional)'을 명시하고 있으며, '컨텍스트 창을 보호하기 위해(protect your context window)' 존재한다고 하는 섹션에서 말입니다. 바로 이런 틀 잡기가 에이전트가 확인 없이 복종하게 만드는 방식입니다. 안전 규칙처럼 표현되어 있고, 안전 규칙 문구는 판단 과정을 단축시키도록 설계되었습니다. 명령형 언어(imperative language)가 강할수록, 에이전트나 사람이 '잠깐, 이게 아직 정확한가?'라고 멈춰서 질문할 가능성이 낮아집니다.
저는 이것이 제 리포지토리에만 국한된 우연이라고 생각하지 않습니다. 더 많은 프로젝트들이 자체적인 CLAUDE.md / AGENTS.md / .cursorrules를 만들면서, 그 안에 들어 있는 지침들은 정규 코드가 항상 가지고 있던 같은 실패 모드를 축적하고 있습니다: 즉, 한때는 사실이었던 시스템을 설명한다는 것입니다. 차이점은 코드에는 현실과 설명이 다를 때 크게 실패하는 테스트가 있다는 것입니다. 하지만 지침 파일에는 아무것도 없습니다. 그저 잘못된 상태로, 자신만만하게 거기에 놓여 있다가 에이전트가 그 간극에 부딪힐 때까지 기다릴 뿐입니다.
제가 실제로 지금 하는 일
저는 프로젝트 자체의 지침에 있는 'MANDATORY'라는 언어를 무조건적으로 실행해야 할 것으로 취급하는 것을 멈췄습니다. 에이전트가 문서화된 도구 라우팅 규칙을 확정하기 전에, 그 도구로 라우팅되는 도구가 실제로 이 세션에서 존재하는지 확인하는 것은 비용이 적게 드는 작업입니다:
# 프로젝트 문서의 '도구 X를 반드시 사용해야 한다'는 규칙을 신뢰하기 전에 에이전트가 실행하길 원하는 검사(check)에 대한 의사 코드(pseudocode)
def verify_routing_claim(claimed_tool_name, available_tools):
...
실제로는 문서가 참조하는 정확한 도구 이름에 대해 ToolSearch(또는 사용 중인 프레임워크의 동등 기능—도구 목록 호출)를 세션 시작 시 한 번 수행하는 것입니다. 이를 단계별로 맹신해서 진행하기보다는요. 검색 결과가 비어 있다면, 그것은 막다른 길이 아니라 신호입니다. 직접적인 접근 방식(순수 curl, 순수 WebFetch, 문서에서 피하라고 했던 무엇이든)으로 되돌아가고—그리고 이것이 제가 실제로 중요하게 생각하는 부분입니다—그 편차를 사람이 볼 수 있는 곳에 기록해야 합니다. 제 저장소에서는 docs/project_notes/bugs.md 파일의 한 줄로 남깁니다: "CLAUDE.md는 2026-07 현재 이 환경에는 존재하지 않는 ctx_fetch_and_index를 참조합니다." 이렇게 하면 조용한 실패가 수정 가능한 실패로 바뀝니다. 다음 사람, 또는 다음 세션은 다시 정직해진 문서를 받게 됩니다.
더 넓은 습관은 지침 파일을 코드의 주석처럼 취급하는 것입니다. 이 주석이 어떤 함수가 무언가를 한다고 주장할 때와 같습니다. 읽을 가치가 있고 대부분 따를 가치는 있지만, 현재 실제로 관찰 가능한 것보다 더 신뢰할 만한 것은 아닙니다. "필수(MANDATORY)"라는 것은 세상에 대한 주장이며, 세상에 대한 주장은 틀릴 수 있습니다. 해결책은 프로젝트 지침을 무시하는 것이 아닙니다—대부분의 경우 그것들은 정확하며 실제 작업을 절약해 줍니다. 핵심은 그들이 그렇지 않을 때 알려주는 저렴한 확인 과정을 구축하는 것입니다: 문서가 존재한다고 말하는 것이 실제로 지금, 이 세션에 존재하는가? 그렇다면 따릅니다. 아니라면, 유령 도구를 세 번이나 재시도해서 예산을 소진하며 알아내는 실수를 하지 마십시오—되돌아가고, 문서를 고치기 위해 발견한 내용을 기록하십시오. 그래야 다음 에이전트가 읽을 때 계속 잘못된 상태로 남아있지 않습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기