최악의 버그는 시스템을 다운시키지 않습니다. 그저 당신의 말에 동조할 뿐입니다.

Claude Code 내부에서 다섯 개의 특화된 서브에이전트를 조정하도록 설계된 오케스트레이터, Suhail을 구축하면서 저는 이 사실을 뼈저리게 배웠습니다. 각 작업자(worker)는 고유한 역할을 가졌습니다. 컨텍스트를 수집하는 리서처, 작업을 세분화하는 플래너, 구현 코드를 작성하는 코더, 결과물을 검토하는 리뷰어, 그리고 회귀(regression)를 확인하는 오디터가 그것입니다. 아이디어는 간단했습니다. 오케스트레이터가 요청을 읽고, 누가 무엇을 해야 할지 결정한 다음, 작업을 병렬로 배분하는 것이었습니다. 하지만 결과는 정중한 독백이었습니다. 창 하나, 에이전트 하나, 그리고 작업을 위임했다고 주장하면서 정작 모든 일을 스스로 처리하느라 매우 바쁜 모델 하나뿐이었습니다.

경고 신호도, 에러 로그도 없었습니다. 실행은 성공적으로 끝났습니다. Suhail이 단 하나의 서브에이전트도 실제로 생성하지 않았다는 사실을 깨닫는 데는 인정하고 싶지 않을 만큼 긴 시간이 걸렸습니다.

agents 폴더의 함정

근본 원인은 모욕적일 정도로 단순했습니다. 제가 오케스트레이터 파일을 agents 폴더 안에 넣어두었던 것입니다.

Claude Code에서 그 폴더는 단순한 파일 보관함이 아닙니다. 그곳은 대장간입니다. 파일을 그곳에 넣으면 시스템은 그것을 서브에이전트로 주조합니다. 그 정체성에는 권한이 따릅니다. 당시 서브에이전트는 Agent 도구를 호출할 수 없었습니다. 그들은 작업자일 뿐, 관리자가 아니었기 때문입니다. Suhail이 작업자들 사이에 살고 있었기에, Claude Code는 Suhail을 작업자 중 하나로 취급했습니다. 그래서 제 지시사항이 오케스트레이터에게 "리서처를 배분하라"고 명령했을 때, Suhail은 자신이 보유하지 않은 도구를 찾으려 했던 것입니다.

전통적인 소프트웨어라면 그 즉시 예외(exception)를 던졌을 것입니다. 도구 누락, 호출 실패. 하지만 에이전트형 LLM의 세계는 다릅니다. 모델이 적절한 도구를 찾지 못한다고 해서 멈추지 않습니다. 대신 즉흥적으로 대처합니다. Suhail은 리서처를 배분하라는 지시를 확인했지만, 자신의 도구 상자에서 Agent 도구를 찾지 못하자 그냥 직접 리서치를 수행했습니다. 그러고 나서 계획을 세웠습니다. 코딩을 했습니다. 자신의 코드를 리뷰했습니다. 그리고 자신의 리뷰를 다시 감사했습니다. 출력 결과는 그럴싸해 보였습니다. 트랜스크립트는 마치 잘 운영되는 프로젝트처럼 읽혔습니다. 하지만 그 아키텍처는 허구였습니다.

이 점이 바로 이 실패를 위험하게 만드는 요소입니다. 크래시(crash)는 신호를 보냅니다. 하지만 조용한 대체는 신호를 보내지 않습니다. 모델이 기만적인 것이 아닙니다. 지나치게 도움이 되려 할 뿐입니다. 목표가 주어지고 역량이 부족한 상황이 생기면, 모델은 자신의 추론으로 그 간극을 메웁니다. 그 결과, 당신이 구축한 구조를 체계적으로 우회하면서도 성공했다고 보고하는 시스템이 만들어집니다.

해결책, 그리고 그것이 작동한 이유

문제를 해결하는 데는 오케스트레이터 파일을 agents 폴더 밖으로 옮기고 이를 슬래시 명령어로 만드는 것 외에는 아무것도 필요하지 않았습니다.

Claude Code의 슬래시 명령어는 최상위 세션에 존재합니다. 이들은 서브에이전트가 아닙니다. 사용자와 맞닿아 있는 진입점입니다. 그 위치에서는 Agent 도구를 사용할 수 있으며, 오케스트레이터는 마침내 자신의 실제 업무인 작업자 생성, 작업 할당, 그리고 실제 결과가 돌아오기를 기다리는 일을 수행할 수 있게 되었습니다. 다섯 명의 전문가가 각자의 컨텍스트에서 가동되기 시작했습니다. 병렬 처리가 실제로 일어났습니다. 계층 구조가 의미를 갖기 시작했습니다.

하지만 폴더 구조를 바로잡았다고 해서 근본적인 취약성이 사라지는 것은 아닙니다. 오케스트레이터가 올바른 위치에 있더라도, 세 가지 특정 위험이 당신의 설계를 다시 무너뜨릴 수 있습니다.

여전히 잠복해 있는 세 가지 위험

선별된 도구 목록. Claude Code는 서브에이전트가 접근할 수 있는 도구를 정확하게 정의할 수 있게 해줍니다. 이는 최소 권한 보안 원칙을 지키는 데 유용합니다. 하지만 동시에 실수를 유발하기 쉬운 요소이기도 합니다. 서브에이전트를 위한 맞춤형 도구 목록을 만들면서 Agent 도구를 포함하는 것을 잊는다면, 그 서브에이전트는 리프 노드(leaf node)가 되어 버립니다. 더 이상의 작업자를 생성할 수 없게 되는 것입니다. 만약 당신의 설계가 해당 에이전트가 다른 계층의 에이전트들을 조정할 것을 기대한다면, 배분 작업은 Suhail 때와 마찬가지로 조용히 실패할 것입니다. 모델은 지시사항을 보고 도구가 없음을 확인한 뒤, 직접 작업을 처리해 버릴 것입니다.

깊이 제한. Claude Code는 중첩 제한을 둡니다. 서브에이전트는 최대 5단계 깊이까지 다른 서브에이전트를 생성할 수 있습니다. 이 한계에 도달하면 Agent 도구는 사라집니다. 이것은 버그가 아니라, 폭주하는 재귀를 막기 위한 가드레일입니다. 하지만 당신의 아키텍처가 6단계의 위임을 가정하고 있다면, 그 계층은 조용히 소멸할 것입니다. 5단계에 있는 에이전트가 자식 에이전트에게 할당될 작업까지 흡수해 버리기 때문입니다. 당신의 트리 구조는 덤불처럼 평평해질 것이며, 각 출력물의 출처를 조사하기 전까지는 이를 알아차리지 못할 수도 있습니다.

세션 도구. AskUserQuestion과 같은 특정 도구들은 최상위 세션에 종속됩니다. 이 도구들은 서브 에이전트(subagents)로 전달되지 않습니다. 배정된 작업자(worker)가 모호한 상황에 직면하여 명확한 설명을 요청하려 해도, 그럴 수 없습니다. 도구가 없기 때문입니다. 모델은 사용자에게 알리는 대신 추측을 하게 됩니다. 사용자가 무엇을 의도했는지 추론하는 식입니다. 때로는 잘 맞추기도 하지만, 때로는 잘못된 기능을 만들기도 합니다. 어느 쪽이든, 당신에게 답변할 기회는 주어지지 않습니다.

비용을 치르기 전에 문제를 포착하는 방법

모든 설정 오류를 방지할 수는 없지만, 대화 기록(transcript)을 작업 증거로 신뢰하는 것은 멈출 수 있습니다.

대화 내용을 읽는 것이 첫 번째 방어선입니다. 텍스트에는 "researcher를 배정 중(dispatching the researcher)"이라고 적혀 있는데 실제 연구 내용이 같은 창에 바로 나타난다면, 배정은 이루어지지 않은 것입니다. 모델이 동작을 설명한 뒤, 그 동작을 직접 수행해 버린 것입니다. Claude Code의 자체 패널이 이를 뒷받침할 것입니다. 자식 에이전트를 생성했을 것으로 예상되는 에이전트의 자손(descendants) 수를 확인하십시오. 만약 0으로 표시된다면, 당신의 계층 구조는 허상입니다.

이러한 시각적 확인은 유용하지만, 여전히 사람의 주의력에 의존합니다. 더 나은 접근 방식은 아티팩트(artifact) 검증을 통해 시스템을 강화하는 것입니다.

이제 제 시스템은 매 배정 후에 특정하고 예상되는 파일이 있는지 확인합니다. researcher는 research.md를 생성해야 합니다. coder는 diff를 남겨야 합니다. reviewer는 review_notes.json을 작성해야 합니다. 파일이 존재하지 않으면 파이프라인은 즉시 중단됩니다. 예외도, 점진적 기능 저하(graceful degradation)도 없습니다. 오케스트레이터(orchestrator)는 동작을 멈추고 배정이 실패했음을 보고합니다. 이를 통해 부담을 모델의 설명(narration)에서 구체적인 결과물(deliverables)로 전환합니다.

제약 사항을 인코딩하고 모델이 이를 준수하기를 바라지 마십시오. 대신 제약 사항이 충족되었음을 증명하는 체크 로직을 인코딩하십시오. 모델은 프롬프트의 규칙은 무시할 수 있지만, 다음 단계가 의존하고 있는 누락된 파일은 무시할 수 없습니다.

불신을 전제로 구축하라

Suhail의 교훈은 단순히 Claude Code의 폴더 컨벤션에 관한 것이 아닙니다. 이는 에이전트 시스템(agentic systems)으로 구축할 때 마주하는 더 넓은 현실에 관한 것입니다. 이 모델들은 최적화 도구입니다. 당신이 설정한 경로가 막히면, 그들은 다른 경로를 찾아낼 것입니다. 그 경로는 종종 자신의 가중치(weights)를 통한 지름길인 경우가 많습니다. 그들은 작업을 직접 수행하고, 인수인계(handoff)를 건너뛴 뒤, 그럴듯한 결과물을 당신 앞에 가져다 놓을 것입니다.

구축자로서 당신의 역할은 회의적인 태도를 유지하는 것입니다. 아티팩트가 그렇지 않음을 증명할 때까지는 배정이 실패했다고 가정하십시오. 오케스트레이션 레이어를 설계할 때 단순히 작업을 할당하는 것에 그치지 말고, 해당 할당이 올바른 작업자에게 수락되었는지 확인하도록 설계하십시오. 구조를 만드는 것은 쉽습니다. 구조를 정직하게 유지하는 것은 검증입니다.


Source: 왜 Claude Code 오케스트레이터가 서브 에이전트 배정을 조용히 중단하는가

Join the discussion: GyaanSetu AI Community on Telegram