usage 객체가 포함됩니다. Sunra는 호출한 endpoint의 시맨틱으로 사용량을 보고합니다. Messages 응답은 Anthropic 계약을 따르고, Chat Completions 또는 Responses 응답은 OpenAI 계약을 따릅니다.
이 형태들이 서로 다른 것은 의도된 것입니다. Chat Completions 응답을 읽는 OpenAI SDK는 OpenAI 시맨틱을 가정하고, Messages 응답을 읽는 Anthropic SDK는 Anthropic 시맨틱을 가정합니다. 각 endpoint는 하나의 공통된 형태로 강제되는 대신 자신의 명세가 약속하는 바를 지킵니다.
Messages
/v1/messages에서는 세 가지 입력 버킷이 상호 배타적입니다. 어떤 토큰도 두 번 계산되지 않으므로, 프롬프트 총합은 이들의 합입니다:
integer
신규 입력 토큰만 해당합니다. 두 캐시 버킷은 모두 제외합니다.
integer
이 요청이 캐시에 기록한 토큰.
integer
이 요청에 캐시에서 제공된 토큰.
integer
모델이 생성한 토큰.
integer
세 가지 입력 버킷과
output_tokens의 합. 비스트리밍 응답에 존재합니다.null인 버킷은 0으로 계산됩니다.
실제 예시
동일한 19,000 토큰 프리픽스를claude-opus-4-8에 두 번 전송한 경우입니다. 첫 번째 요청은 캐시를 기록하고, 두 번째 요청은 캐시를 읽습니다.
콜드 요청(캐시 쓰기)
웜 요청(캐시 읽기)
input_tokens는 두 요청 모두에서 8로 유지되는데, 매번 실제로 새로 추가된 입력이 8이기 때문입니다. 19,349 토큰 프리픽스는 생성 버킷에서 읽기 버킷으로 이동합니다. 두 요청 모두 합계는 동일한 19,359 토큰이지만 비용은 같지 않습니다. 캐시 쓰기와 캐시 읽기는 각각 자체 토큰당 요율로 과금되며, 그래서 별도의 버킷으로 보고됩니다.
Chat Completions와 Responses
이 endpoint들은 OpenAI 시맨틱을 변경 없이 그대로 보고합니다. 프롬프트 카운트는 프롬프트 전체이며, 캐시된 토큰은 그 부분집합으로 별도로 보고됩니다./v1/chat/completions
prompt_tokens와 cached_tokens를 더하면 이중 계산이 됩니다. 이 endpoint들에서 신규 입력을 구하려면 빼야 합니다:
/v1/responses의 input_tokens와 input_tokens_details.cached_tokens에도 적용됩니다.
sunra_usage_semantics 마커
Sunra가 정규화한 응답에는 usage 안에 마커가 포함됩니다:
usage 객체에 나타나고, 스트리밍 응답에서는 입력 버킷을 전달하는 이벤트인 message_start에 나타납니다. 이 값으로 존재할 때 이 페이지의 보장이 성립합니다. 세 가지 입력 버킷은 상호 배타적이며, total_tokens는 — 존재하는 경우 — 이들의 합에 output_tokens를 더한 값입니다.
마커의 부재 또한 하나의 약속입니다. Sunra는 자신이 측정한 응답 형태만 정규화합니다. 그 외의 것은 업스트림 제공자로부터 손대지 않은 채 전달되며 마커가 붙지 않습니다. 마커가 없는 응답은 그 버킷을 Sunra가 보증하지 않는 응답입니다.
응답이 어떤 규약을 따르는지 숫자를 들여다보며 추측하지 말고, 마커를 검증하세요. 형태를 짐작하는 방식(shape sniffing)이야말로 이 필드가 대체하려는 대상입니다. “버킷의 합이 프롬프트 카운트보다 크므로 버킷은 배타적일 것이다” 같은 휴리스틱은 둘 이상의 규약에서 성립하며, 언젠가는 응답을 잘못 읽게 됩니다.
/v1/messages 응답뿐입니다. Chat Completions와 Responses는 OpenAI 명세를 따르며 마커가 붙지 않습니다.
이 값에는 버전이 있습니다. 이 필드들의 의미에 대한 파괴적 변경은 새로운 값으로 배포되므로, anthropic.exclusive.v1에 대한 동등성 검사가 조용히 다른 계약을 읽기 시작하는 일은 없습니다.
Streaming
스트리밍 Messages 요청에서는 사용량이 두 개의 이벤트에 걸쳐 도착합니다.message_start는 입력 측과 마커를 전달합니다. 마지막 message_delta는 output_tokens만 전달합니다. 마커 검증은 message_start에서 수행하고, 그런 다음 두 이벤트를 통상적인 방식으로 병합 — 나중 이벤트의 usage를 앞선 이벤트 위에 적용 — 하면 위에 문서화된 값이 나옵니다.
total_tokens는 스트리밍 응답에서 생략됩니다. 어떤 단일 이벤트도 입력 측과 출력 측을 모두 알지 못하므로, 스트림 도중에 계산한 총합은 잘못된 값이 됩니다. 스트림이 완료된 후 직접 버킷을 합산하세요.
이전 동작에서의 마이그레이션
Sunra는 이전에/v1/messages에서 업스트림 usage 객체를 그대로 전달했습니다. 일부 제공자 앞단의 변환 계층은 캐시 생성 토큰을 input_tokens 안으로 접어 넣기 때문에, Anthropic 계약을 따라 세 버킷을 합산한 호출자는 캐시 생성 토큰을 두 번 계산했습니다.
- 세 버킷을 합산한다면, Anthropic 계약이 설명하는 그대로이며, 이제 올바릅니다. 여러분 쪽에서 변경할 것은 없습니다.
- 이전 동작을 보정하고 있었다면 —
input_tokens에서cache_creation_input_tokens를 직접 빼거나, 접어 넣는 동작을 역으로 계산하고 있었다면 — 중단하세요. 그 보정은 이제 이미 제외된 토큰을 빼는 것이 되어 입력을 과소 계상하게 됩니다. total_tokens를 읽는다면, 이 값은 계속해서 전체 카운트를 보고합니다. 신규 입력, 두 캐시 버킷, 그리고 출력입니다.