Claude Code가 서브에이전트(subagent) 프롬프트 캐시에서 조용히 약 14%를 과다 청구하고 있으며, 이는 설정 변경이 아닌
요약
Claude Code 사용 시 서브에이전트의 프롬프트 캐시 효율 저하로 인해 비용이 약 14% 과다 청구되는 구조적 문제를 분석합니다. 프롬프트 구조와 캐시 만료 정책이 캐시 재사용을 방해하여 발생하는 비용 상승 원인을 다룹니다.
핵심 포인트
- 서브에이전트 실행 시 동일 컨텍스트가 캐시 쓰기 요금으로 청구되어 비용 상승
- 동적 요소(날짜, 경로 등)가 프롬프트 앞부분에 위치하여 캐시 무효화 유발
- 서브에이전트의 짧은 캐시 유지 시간(5분)으로 인한 부모 컨텍스트 만료 문제
- 단순한 TTL 연장보다는 프롬프트 구조 재배치와 콘텐츠별 캐시 분리가 핵심 해결책
저는 Claude Code에서 많은 중첩된 서브에이전트 (subagents)를 실행하며, 새로운 에이전트가 구동되거나 중첩된 에이전트가 반환될 때마다 프롬프트 캐시 (prompt cache)를 얼마나 손실하는지 궁금해졌습니다. Claude Code는 모든 API 호출의 캐시 사용량을 로컬에 기록하므로, 저는 약 2주간의 제 트랜스크립트(transcripts) — 약 95개 세션, 약 1,800개의 서브에이전트, 68억 개의 입력 토큰(input tokens) — 를 파싱했습니다.
주장에 대해 정확히 말씀드리자면, 이것은 "더 많은 토큰이 처리된다"는 뜻이 아닙니다. 서브에이전트가 캐싱되는 방식 때문에 동일한 컨텍스트 (context)가 읽기 요금 (read rates) 대신 캐시 쓰기 요금 (cache-write rates)으로 청구되어, 결과적으로 지불해야 할 것보다 더 많은 비용이 발생한다는 의미입니다. 제 데이터에 따르면:
- 서브에이전트 프롬프트 비용이 약 14% 너무 높음
- 전체 지출의 약 8% 차이 (메인 세션 + 출력은 영향을 받지 않으므로 수치가 더 낮음)
이것은 하나의 버그가 아니라 몇 가지 별개의 문제입니다:
-
모든 서브에이전트는 시작 시 약 30k 토큰의 정적 컨텍스트 (static context)를 다시 전송합니다. 그리고 프롬프트 자체의 구조가 재사용을 방해하는 큰 원인입니다. 콜드 스타트 (Cold start)는 약 37k 토큰이며, 실제 작업은 약 950개(약 3%)뿐입니다. 나머지 약 97%는 동일한 유형의 서브에이전트 간에 거의 동일한 보일러플레이트 (boilerplate, 시스템 프롬프트, 도구 정의, 프로젝트 규칙 등)입니다. 재사용을 막는 두 가지 요인은 다음과 같습니다: (a) 해당 공유 접두사 (shared prefix)는 5분 동안만 캐싱되므로, 마지막 형제 에이전트 실행 후 5분이 지나서 실행되는 리뷰어는 이미 만료된 캐시를 발견하게 됩니다. (b) 호출당 발생하는 동적 요소들 (날짜, cwd, git 브랜치, 주입된 리마인더 등)이 프롬프트 앞부분에 배치되어 있습니다. 프롬프트 캐시 (prompt cache)는 변경되지 않은 접두사만을 재사용할 수 있으므로, 첫 번째 변경 사항이 발생하면 그 이후의 모든 내용이 무효화됩니다. 변동성이 큰 콘텐츠가 정적 블록 앞에 위치함에 따라, 동일한 블록을 캐시로 공유할 수 없게 됩니다. 이 두 가지 모두 구조적인 문제이며 Anthropic이 해결해야 합니다: 더 오래 지속되는 접두사 캐시 (prefix cache)가 (a)를 해결하고, 프롬프트 순서 재배치가 (b)를 해결할 수 있습니다.
-
부모의 캐시가 자식의 응답을 기다리는 동안 만료됩니다. 서브에이전트는 5분의 캐시를 할당받는 반면, 메인 루프는 1시간을 할당받습니다. 읽기 (Reading) 작업은 타이머를 갱신하므로 활성 상태인 에이전트는 괜찮지만, 부모가 자식을 생성하고 5분 이상 차단 (block) 상태로 대기하면 부모의 캐시는 조용히 만료되며, 자식이 돌아왔을 때 전체 컨텍스트를 다시 쓰게 (re-writes) 됩니다.
제 데이터에 따르면, 그중 96%는 실제 캐시 소멸 (cache deaths)이었으며, 5분 선을 넘어서는 시점에 집중되어 있었습니다.
더 기가 막힌 점은, 명백한 해결책처럼 보이는 "서브에이전트 (subagents)에게 그냥 1시간 캐시를 부여하라"는 방식이 오히려 상황을 8.6% 더 악화시킨다는 것입니다. 캐시 재사용 (cache reuse)의 98%는 약 34초 이내에 발생하므로, 보유 기간 (retention)을 길게 잡는 것은 대부분 모든 항목에 대해 더 높은 쓰기 비용 (write price)을 지불하게 만들 뿐입니다. "변동성 (volatility)에 따라 캐시를 분할한다"는 단순한 접근 방식 또한 큰 차이가 없었습니다 (+1.3%).
핵심은 TTL (Time To Live) 값이 아니라, 어떤 콘텐츠에 어떤 TTL을 적용하느냐입니다. Anthropic의 현재 GA 프롬프트 캐싱 (prompt-caching) API를 통해 실행 가능한 두 가지 정밀한 변경 사항은 다음과 같습니다 (하나의 요청에 1시간과 5분 임계값 (breakpoints)을 혼합하는 것은 이미 지원됩니다):
- 자식 에이전트가 파견되기 직전의 쓰기 작업에 1시간 TTL 적용 (부모가 대기 시간 동안 유지되도록 함): −6%
- 동일한 유형의 정적 접두사 (static prefix)에 1시간 TTL 적용 + 동적 콘텐츠를 그 뒤로 이동 (공유되도록 하며, 다시 전송되지 않게 함): −7.6%, 그리고 콜드 스타트 (cold start) 비용이 약 88% 저렴해짐
- 계속 변하는 대화의 끝부분 (conversation tail)에는 기본 5분 TTL 유지 (몇 초 내에 다시 읽히므로, 여기에 1시간을 적용하는 것은 순전한 낭비임)
두 개의 차트가 있습니다. "어떤 해결책이 실제로 도움이 되는가"를 보여주는 차트가 제가 가장 좋아하는 것인데, 대부분의 직관적인 아이디어들이 0의 잘못된 방향(비용 증가)에 머물러 있습니다:
https://preview.redd.it/vcaam81pobbh1.png?width=1920&format=png&auto=webp&s=c9100fb4b333cd9c7c54df762948a0bc6eb8f199
https://preview.redd.it/fxl38w8qobbh1.png?width=1960&format=png&auto=webp&s=2c60b2c73ddb14ff121b93fe0863212700e64a05
직접 확인해 보세요: 저는 로컬의 ~/.claude/projects 트랜스크립트 (transcripts)를 읽어 두 가지 수치(절감 가능한 전체 비용 및 서브에이전트 효율성)를 출력하는 약 150줄 규모의 표준 라이브러리 전용 (stdlib-only) 스크립트를 작성했습니다. 로컬에서 실행되며 아무것도 전송하지 않습니다. 전체 보고서 + 과금 계산법 + 스크립트: https://github.com/anthropics/claude-code/issues/74318
주의 사항: 이는 서브에이전트를 많이 사용하는 워크플로우를 가진 한 개인의 사례입니다. 서브에이전트로 작업을 분산 (fan out)하지 않는다면 큰 차이를 느끼지 못할 것입니다. "서브에이전트가 5분 캐시를 사용 중이다"라는 부분은 직접 측정된 것이며, 절감액은 Anthropic의 과금이 아닌 사용 로그를 바탕으로 모델링된 것입니다. 서브에이전트에 의존하는 다른 분들도 동일한 양상을 보이는지 궁금합니다.
submitted by /u/farono
[link] [comments]
AI 자동 생성 콘텐츠
본 콘텐츠는 r/ClaudeAI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기