Claude Code 서브에이전트 중첩 depth, 직접 측정해봤다 (2026년 7월)
Claude Code의 서브에이전트(Agent 툴)는 작업을 병렬로 쪼개는 데 쓴다. 그런데 서브에이전트가 또 서브에이전트를 띄우는 중첩(nesting)은 이야기가 다르다. 최근 버전에서 이 제한이 두 번 바뀌었는데, 검색해보면 설명이 서로 안 맞는다.
그래서 공식 changelog로 사실관계를 정리하고, 내 컴퓨터에 설치된 버전에서 실제로 실행해서 측정했다. 결과적으로 남의 글에서 본 숫자를 옮기는 것보다 훨씬 쓸모 있는 걸 알게 됐다 — 특히 마지막 사례가 그렇다.
1. 왜 설명이 서로 안 맞는가: 두 개의 다른 숫자
검색으로 찾은 글들은 “depth 5”, “이전 값은 1”, “기본 3” 같은 숫자를 섞어 쓴다. 공식 changelog를 직접 읽어보니 서로 다른 두 가지를 섞은 것이었다.
| 버전 | changelog 원문 요지 | 무엇에 대한 값인가 |
|---|---|---|
| 2.1.181 | 포그라운드 서브에이전트가 무한 중첩되던 문제 수정 — 백그라운드와 동일한 5단계 depth 제한을 따르게 함 | 하드 상한 |
| 2.1.212 | 세션당 서브에이전트 생성 총량 상한 추가 (CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION) | 개수 상한(깊이 아님) |
| 2.1.217 | 서브에이전트가 기본적으로 중첩 생성을 하지 않도록 변경. 더 깊게 하려면 CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH 설정 | 기본값 |
| 2.1.219 | 서브에이전트가 기본 depth 3까지(이전 1) 중첩 생성 가능. stream-json에 depth-2 이상 서브에이전트도 표시되도록 추가 | 기본값 |
정리하면 5는 하드 상한(2.1.181)이고, 1과 3은 기본값(2.1.217 → 2.1.219)이다. 성격이 다른 두 숫자를 같은 층위에 놓고 비교하면 당연히 모순처럼 보인다.
두 번째로 눈에 띈 건 2.1.219의 stream-json 항목이다. “depth-2 이상 서브에이전트가 이제 표시된다”는 건, 그 전까지는 깊은 곳의 에이전트가 로그에 안 보였다는 뜻이다. 이 사실은 뒤에서 실제로 발목을 잡는다.
2. 환경변수는 실존하지만 문서에는 없다
changelog에 나온 환경변수 두 개가 정말 동작하는 것인지, 설치된 바이너리에서 직접 확인했다.
# 설치된 버전 확인
$ claude --version
2.1.218 (Claude Code)
# 실행 파일 실제 경로 (심볼릭 링크를 따라감)
$ readlink -f ~/.local/bin/claude
/Users/me/.local/share/claude/versions/2.1.218
# 바이너리 안에 환경변수 이름이 존재하는지
$ strings -a ~/.local/share/claude/versions/2.1.218 \
| grep -c CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH
두 변수 모두 문자열로 존재했다. 나아가 상한에 걸렸을 때 도구가 실제로 출력하는 안내 문구까지 그대로 들어 있었다.
Complete this task directly using your tools instead of spawning another agent. If the user explicitly requested deeper nesting, ask them to raise
CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH.
그런데 공식 설정 문서 페이지에는 이 두 변수가 없다(확인 시점 2026-07-27). changelog와 바이너리에만 있다. 문서화되지 않은 설정이라는 뜻이고, 예고 없이 바뀔 수 있다고 보는 게 맞다. 실제로 두 버전 사이에 기본값이 이미 두 번 바뀌었다.
strings로 확인되는 건 이름이 존재한다는 것까지다. 기본값이 몇인지는 문자열만으로는 알 수 없다. 그래서 다음 단계로 실제 실행 측정이 필요했다.
3. 실제로 어디서 막히는지 측정
내 버전(2.1.218)에서 중첩이 몇 단계까지 되는지 직접 실행해서 확인했다. 먼저 환경변수 오버라이드가 없다는 것을 확인해야 측정이 의미가 있다.
# 설정 파일과 환경변수에 관련 설정이 없는지 먼저 확인
$ grep -c SUBAGENT ~/.claude/settings.json .env
0
$ env | grep -i SUBAGENT
(설정 없음)
그다음 헤드리스 모드(-p)로 체인을 만들었다. 각 에이전트에게 “너도 서브에이전트를 하나 띄우고, 막히면 그 메시지를 그대로 보고해라”를 넘기는 방식이다.
$ claude -p '체인 지시문...' --allowed-tools "Agent" --max-turns 12 --model haiku
측정 결과는 이렇다.
메인 세션 (depth 0)
└─ 에이전트 depth 1 Agent 호출 성공 ✅
└─ 에이전트 depth 2 Agent 호출 성공 ✅
└─ 에이전트 depth 3 Agent 툴이 툴셋에 아예 없음 ❌
depth 3까지 생성되고, depth 3 에이전트는 더 띄우지 못했다.
여기서 예상과 달랐던 지점이 두 개 있다.
(1) 막히는 방식이 에러가 아니다. depth 3 에이전트는 “제한에 걸렸다”는 에러를 받지 않았다. 그냥 Agent 툴이 사용 가능한 목록에 없었다. 그래서 이 에이전트는 툴을 검색해보다가 못 찾고, “Agent 툴을 찾을 수 없다”는 자기만의 설명을 지어냈다. 상한이 조용히 적용되기 때문에, 로그만 보면 “제한 때문”인지 “모델이 헤맨 것”인지 구분이 안 된다.
(2) changelog 설명과 어긋난다. 2.1.217은 “기본적으로 중첩하지 않음”이라고 했는데, 2.1.218에서 오버라이드 없이 depth 3까지 됐다. 왜 그런지는 확정할 수 없다 — 217과 219 사이에 조정이 있었을 수도 있고, 에이전트 타입이나 실행 방식에 따라 다를 수도 있다. [확인 필요] 다만 확실한 건, changelog 문장을 내 환경의 동작으로 그대로 믿으면 안 됐다는 것이다.
4. 가장 중요한 발견: 모델의 자기보고가 틀렸다
측정에서 제일 값진 건 depth 숫자가 아니었다.
최상위 실행이 최종 보고한 내용은 이랬다.
Deepest N reached: 4
- N=1 → spawned N=2 ✅
- N=2 → spawned N=3 ✅
- N=3 → spawned N=4 ✅
- N=4 → blocked
깔끔하고 그럴듯하다. 그런데 사실이 아니었다.
서브에이전트는 각각 자기 트랜스크립트 파일을 남긴다. 그 파일을 세어보면 실제로 몇 개가 떴는지 알 수 있다.
# 세션별 서브에이전트 트랜스크립트 개수
$ ls ~/.claude/projects/<프로젝트>/<세션ID>/subagents/agent-*.jsonl | wc -l
3
3개다. 보고서가 말한 4단계는 존재하지 않았다. 게다가 각 에이전트가 스스로 붙인 번호(N=3, N=4)도 서로 어긋나 있었다 — 지시문을 전달하는 과정에서 라벨이 밀린 것이다. 즉 모델이 말하는 depth 숫자는 근거로 쓸 수 없었다.
실제 구조는 트랜스크립트에서 Agent 툴 호출 횟수를 세는 방식으로만 확인됐다.
agent-ab7a06... Agent 호출 1회 → 자식 있음
agent-aa9158... Agent 호출 1회 → 자식 있음
agent-a65fb1... Agent 호출 0회 → 말단 (ToolSearch만 시도하다 실패)
호출 1회짜리 둘 + 말단 하나 = 3단계. 이게 실측이다.
여기엔 함정이 하나 더 있다. 트랜스크립트 파일은 subagents/ 아래에 계층 구조 없이 평평하게 저장된다. 디렉터리 모양만 봐서는 누가 누구의 자식인지 알 수 없고, 파일 내용의 툴 호출을 봐야 한다.
앞에서 언급한 2.1.219의 “stream-json에 depth-2 이상이 이제 표시됨” 항목이 여기서 연결된다. 깊은 곳의 에이전트는 원래 표준 로그에 안 보였고, 그래서 상위 보고를 검증할 방법이 기본으로는 없었던 것이다.
이건 이전 글에서 겪은 것과 정확히 같은 종류의 문제다 — Claude Code로 사이드 프로젝트 자동화하기에서 “수정 완료” 보고를 받고도 실제 배포 결과는 여전히 깨져 있었던 사례. “했다”는 보고와 “실제로 됐다”는 사실 사이에는 항상 검증 단계가 필요하다. 에이전트를 중첩하면 그 검증해야 할 층이 늘어난다.
5. 본인 버전에서 확인하는 방법
기본값이 버전마다 바뀌므로, 숫자를 외우는 것보다 확인 절차를 갖고 있는 게 낫다.
# 1. 내 버전
claude --version
# 2. 오버라이드가 걸려 있는지 (이걸 안 보면 측정이 무의미)
grep -c SUBAGENT ~/.claude/settings.json ~/.claude/settings.local.json .env 2>/dev/null
env | grep -i SUBAGENT
# 3. 작업 후 실제로 몇 개가 떴는지
ls ~/.claude/projects/*/<세션ID>/subagents/agent-*.jsonl | wc -l
3번이 핵심이다. 에이전트가 몇 개 떴는지는 보고를 믿지 말고 파일을 세면 된다.
정리
| 항목 | 확인된 사실 | 근거 |
|---|---|---|
| 하드 상한 5 vs 기본값 1·3 | 서로 다른 층위의 숫자. 섞어 비교하면 모순처럼 보임 | 공식 changelog 2.1.181 / 2.1.217 / 2.1.219 |
| 환경변수 2개 | 실존하나 공식 설정 문서에는 없음 | 바이너리 문자열 + 문서 페이지 확인(2026-07-27) |
| 내 버전(2.1.218) 실측 | 오버라이드 없이 depth 3까지, depth 3은 생성 불가 | 헤드리스 실행 + 트랜스크립트 3개 |
| 막히는 방식 | 에러가 아니라 Agent 툴이 툴셋에서 조용히 사라짐 → 모델이 이유를 지어냄 | 말단 에이전트 트랜스크립트 |
| 모델 자기보고 | ”4단계 도달” 보고했으나 실제 3개. depth 라벨도 어긋남 | 트랜스크립트 개수 대조 |
실무적으로 얻은 결론은 단순하다. 중첩 depth를 늘리는 것보다, 한 단계에서 병렬로 여러 개를 띄우는 게 관측하기 쉽다. 깊게 쌓으면 비용과 시간이 늘어나는 것보다 “안에서 무슨 일이 있었는지 확인할 수 없다”는 쪽이 더 큰 비용이다. 그리고 확인이 필요할 때는 보고서를 읽는 게 아니라 트랜스크립트를 세면 된다.
이 글의 측정값은 2.1.218 기준이다. 2.1.219 이후는 직접 측정하지 않았으므로, 위 depth 3이 219의 새 기본값과 같은 것이라고 단정하지 않는다. 버전이 다르면 5번의 절차로 각자 확인하는 편이 정확하다.
자주 묻는 질문
서브에이전트 중첩 depth 기본값은 몇인가요?
버전에 따라 다릅니다. 공식 changelog 기준으로 2.1.217에서 '기본적으로 중첩 안 함'으로 바뀌었고, 2.1.219에서 '기본 depth 3(이전 1)'으로 다시 열렸습니다. 특정 숫자를 외우기보다 본인 버전에서 직접 확인하는 편이 정확합니다 — 본문에 확인 방법을 적었습니다.
CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH는 공식 문서에 있나요?
확인 시점(2026-07-27) 기준 공식 설정 문서 페이지에는 이 환경변수가 문서화돼 있지 않았습니다. changelog와 실제 바이너리 문자열에서만 확인됐습니다. 문서화되지 않은 설정은 예고 없이 바뀔 수 있다고 보는 편이 안전합니다.
중첩을 깊게 하면 뭐가 문제인가요?
같은 작업이 여러 단계를 거치며 컨텍스트가 반복 전달되므로 비용과 시간이 늘어납니다. 더 실질적인 문제는 관측 가능성입니다 — 깊은 곳의 에이전트가 무엇을 했는지 상위 보고만으로는 알 수 없고, 본문 사례처럼 그 보고가 사실과 다를 수 있습니다.