Was this page helpful?
이 기능은 Zero Data Retention (ZDR)의 적용 대상입니다. 조직에 ZDR 계약이 체결되어 있는 경우, 이 기능을 통해 전송된 데이터는 API 응답이 반환된 후 저장되지 않습니다.
서버 측 "compaction"(컴팩션)은 장기 실행 대화 및 에이전트 워크플로에서 컨텍스트를 관리하기 위한 권장 전략입니다. 최소한의 통합 작업으로 컨텍스트 관리를 자동으로 처리합니다.
컴팩션은 "context window"(컨텍스트 윈도우) 한계에 근접할 때 오래된 컨텍스트를 자동으로 요약하여 장기 실행 대화 및 작업의 유효 컨텍스트 길이를 확장합니다. 이는 단순히 토큰 상한선 아래로 유지하는 것만이 아닙니다. 대화가 길어질수록 모델은 전체 기록에 걸쳐 집중력을 유지하기 어려워집니다. 컴팩션은 오래된 콘텐츠를 간결한 요약으로 대체하여 활성 컨텍스트를 집중적이고 성능 좋게 유지합니다.
긴 컨텍스트가 성능 저하를 일으키는 이유와 컴팩션이 어떻게 도움이 되는지 자세히 알아보려면 Effective context engineering을 참조하세요.
이는 다음과 같은 경우에 이상적입니다:
컴팩션은 베타 상태입니다. 이 기능을 사용하려면 API 요청에 베타 헤더 compact-2026-01-12를 포함하세요.
컴팩션은 다음 모델에서 지원됩니다:
claude-fable-5)claude-mythos-5)컴팩션이 활성화되면 Claude는 대화가 구성된 토큰 임계값에 근접할 때 자동으로 대화를 요약합니다. API는 다음을 수행합니다:
compaction 블록을 생성합니다.후속 요청에서는 응답을 메시지에 추가하세요. API는 compaction 블록 이전의 모든 메시지 블록을 자동으로 제거하고 요약부터 대화를 계속합니다.
Messages API 요청의 context_management.edits에 compact_20260112 전략을 추가하여 컴팩션을 활성화하세요.
| 매개변수 | 타입 | 기본값 | 설명 |
|---|---|---|---|
type | string | 필수 | "compact_20260112"여야 합니다 |
trigger | object | 150,000 토큰 | 컴팩션을 트리거할 시점입니다. 최소 50,000 토큰이어야 합니다. |
pause_after_compaction | boolean | false | 컴팩션 요약 생성 후 일시 중지할지 여부 |
instructions | string | null | 사용자 지정 요약 프롬프트입니다. 제공되면 기본 프롬프트를 완전히 대체합니다. |
trigger 매개변수를 사용하여 컴팩션이 트리거되는 시점을 구성하세요:
기본적으로 컴팩션은 다음 요약 프롬프트를 사용합니다:
You have written a partial transcript for the initial task above. Please write a summary of the transcript. The purpose of this summary is to provide continuity so you can continue to make progress towards solving the task in a future context, where the raw history above may not be accessible and will be replaced with this summary. Write down anything that would be helpful, including the state, next steps, learnings etc. You must wrap your summary in a <summary></summary> block.instructions 매개변수를 통해 사용자 지정 지침을 제공하여 이 프롬프트를 완전히 대체할 수 있습니다. 사용자 지정 지침은 기본값을 보완하지 않고 완전히 대체합니다:
pause_after_compaction을 사용하여 컴팩션 요약 생성 후 API를 일시 중지하세요. 이를 통해 API가 응답을 계속하기 전에 추가 콘텐츠 블록(예: 최근 메시지 또는 특정 지침 중심 메시지 보존)을 추가할 수 있습니다.
활성화되면 API는 컴팩션 블록을 생성한 후 compaction 중지 사유와 함께 메시지를 반환합니다:
모델이 많은 도구 사용 반복이 포함된 긴 작업을 수행할 때 총 토큰 소비량이 크게 증가할 수 있습니다. pause_after_compaction을 컴팩션 카운터와 결합하여 누적 사용량을 추정하고 예산에 도달하면 작업을 정상적으로 마무리할 수 있습니다:
client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
TRIGGER_THRESHOLD = 100_000
TOTAL_TOKEN_BUDGET = 3_000_000
n_compactions = 0
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": TRIGGER_THRESHOLD},
"pause_after_compaction": True,
}
]
},
)
if response.stop_reason == "compaction":
n_compactions += 1
messages.append({"role": "assistant", "content": response.content})
# 소비된 총 토큰을 추정하고, 예산을 초과하면 마무리를 유도합니다
if n_compactions * TRIGGER_THRESHOLD >= TOTAL_TOKEN_BUDGET:
messages.append(
{
"role": "user",
"content": "Please wrap up your current work and summarize the final state.",
}
)컴팩션이 트리거되면 API는 어시스턴트 응답의 시작 부분에 compaction 블록을 반환합니다.
장기 실행 대화는 여러 번의 컴팩션을 발생시킬 수 있습니다. 마지막 컴팩션 블록은 프롬프트의 최종 상태를 반영하며, 그 이전의 콘텐츠를 생성된 요약으로 대체합니다.
{
"content": [
{
"type": "compaction",
"content": "Summary of the conversation: The user requested help building a web scraper..."
},
{
"type": "text",
"text": "Based on our conversation so far..."
}
]
}단축된 프롬프트로 대화를 계속하려면 후속 요청에서 compaction 블록을 API에 다시 전달해야 합니다. 가장 간단한 방법은 전체 응답 콘텐츠를 메시지에 추가하는 것입니다:
API가 compaction 블록을 받으면 그 이전의 모든 콘텐츠 블록은 무시됩니다. 다음 중 하나를 선택할 수 있습니다:
컴팩션이 활성화된 상태에서 응답을 스트리밍할 때 컴팩션이 시작되면 content_block_start 이벤트를 받게 됩니다. 컴팩션 블록은 텍스트 블록과 다르게 스트리밍됩니다. content_block_start 이벤트를 받은 후, 전체 요약 콘텐츠가 포함된 단일 content_block_delta(중간 스트리밍 없음)를 받고, 그다음 content_block_stop 이벤트를 받게 됩니다.
컴팩션은 프롬프트 캐싱과 잘 작동합니다. 컴팩션 블록에 cache_control 중단점을 추가하여 요약된 콘텐츠를 캐시할 수 있습니다. 원본 컴팩션된 콘텐츠는 무시됩니다.
{
"role": "assistant",
"content": [
{
"type": "compaction",
"content": "[summary text]",
"cache_control": { "type": "ephemeral" }
},
{
"type": "text",
"text": "Based on our conversation..."
}
]
}컴팩션이 발생하면 요약은 캐시에 기록되어야 하는 새 콘텐츠가 됩니다. 추가 캐시 중단점이 없으면 캐시된 시스템 프롬프트도 무효화되어 컴팩션 요약과 함께 다시 캐시되어야 합니다.
캐시 적중률을 극대화하려면 시스템 프롬프트 끝에 cache_control 중단점을 추가하세요. 이렇게 하면 시스템 프롬프트가 대화와 별도로 캐시되므로 컴팩션이 발생할 때:
이 접근 방식은 긴 시스템 프롬프트에 특히 유용합니다. 대화 전반에 걸쳐 여러 컴팩션 이벤트가 발생하더라도 시스템 프롬프트가 캐시된 상태로 유지되기 때문입니다.
컴팩션은 추가 샘플링 단계가 필요하며, 이는 속도 제한 및 청구에 반영됩니다. API는 응답에 상세한 사용량 정보를 반환합니다:
{
"usage": {
"input_tokens": 23000,
"output_tokens": 1000,
"iterations": [
{
"type": "compaction",
"input_tokens": 180000,
"output_tokens": 3500
},
{
"type": "message",
"input_tokens": 23000,
"output_tokens": 1000
}
]
}
}iterations 배열은 각 샘플링 반복의 사용량을 보여줍니다. 컴팩션이 발생하면 compaction 반복 다음에 메인 message 반복이 표시됩니다. 이 예제에서는 컴팩션이 아닌 반복이 하나뿐이므로 최상위 input_tokens 및 output_tokens가 message 반복과 정확히 일치합니다. 최종 반복의 토큰 수는 컴팩션 후의 유효 컨텍스트 크기를 반영합니다.
최상위 input_tokens 및 output_tokens는 컴팩션 반복 사용량을 포함하지 않습니다. 이들은 모든 비컴팩션 반복의 합계를 반영합니다. 요청에 대해 소비되고 청구된 총 토큰을 계산하려면 usage.iterations 배열의 모든 항목을 합산하세요.
이전에 비용 추적 또는 감사를 위해 usage.input_tokens 및 usage.output_tokens에 의존했다면, 컴팩션이 활성화된 경우 usage.iterations 전체를 집계하도록 추적 로직을 업데이트해야 합니다. iterations 배열은 요청 중에 새 컴팩션이 트리거될 때만 채워집니다. 이전 compaction 블록을 다시 적용하는 경우 추가 컴팩션 비용이 발생하지 않으며, 이 경우 최상위 사용량 필드는 정확하게 유지됩니다.
서버 도구(예: 웹 검색)를 사용할 때 컴팩션 트리거는 각 샘플링 반복의 시작 시점에 확인됩니다. 트리거 임계값과 생성된 출력량에 따라 단일 요청 내에서 컴팩션이 여러 번 발생할 수 있습니다.
토큰 계산 엔드포인트(/v1/messages/count_tokens)는 프롬프트의 기존 compaction 블록을 적용하지만 새 컴팩션을 트리거하지는 않습니다. 이전 컴팩션 후의 유효 토큰 수를 확인하는 데 사용하세요:
다음은 컴팩션을 사용한 장기 실행 대화의 전체 예제입니다:
다음은 pause_after_compaction을 사용하여 이전 대화 교환과 현재 사용자 메시지(총 세 개의 메시지)를 요약하는 대신 그대로 보존하는 예제입니다:
요약에 동일한 모델 사용: 요청에 지정된 모델이 요약에 사용됩니다. 요약에 다른(예: 더 저렴한) 모델을 사용하는 옵션은 없습니다.
도구가 정의된 경우 컴팩션이 실패할 수 있음: 요청에 tools가 포함된 경우, 모델이 내부 요약 단계에서 요약을 작성하는 대신 도구를 호출하는 경우가 간혹 있습니다. 이 경우 응답에는 content: null인 compaction 블록이 포함됩니다. 이를 방지하려면 instructions를 모델에게 도구를 호출하지 말라고 명시적으로 지시하는 프롬프트로 설정하세요. 예를 들면 다음과 같습니다:
Summarize the transcript inside <summary></summary> tags. Include relevant information in the summary for continuing the task in the next context window. Do not call any tools while writing this summary; respond with text only.client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Help me build a website"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
# 대화를 계속하려면 응답(압축 블록 포함)을 추가하세요
messages.append({"role": "assistant", "content": response.content})client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 150000},
}
]
},
)client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"instructions": "Focus on preserving code snippets, variable names, and technical decisions.",
}
]
},
)client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [{"type": "compact_20260112", "pause_after_compaction": True}]
},
)
# 압축이 일시 중지를 트리거했는지 확인
if response.stop_reason == "compaction":
# 응답에 압축 블록만 포함됨
messages.append({"role": "assistant", "content": response.content})
# 요청 계속 진행
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
# 압축 블록이 포함된 응답을 받은 후
messages.append({"role": "assistant", "content": response.content})
# 대화를 계속합니다
messages.append({"role": "user", "content": "Now add error handling"})
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
with client.beta.messages.stream(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
) as stream:
for event in stream:
if event.type == "content_block_start":
if event.content_block.type == "compaction":
print("Compaction started...")
elif event.content_block.type == "text":
print("Text response started...")
elif event.type == "content_block_delta":
if event.delta.type == "compaction_delta":
print(f"Compaction complete: {len(event.delta.content or '')} chars")
elif event.delta.type == "text_delta":
print(event.delta.text, end="", flush=True)
# 최종 누적 메시지 가져오기
message = stream.get_final_message()
messages.append({"role": "assistant", "content": message.content})client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
system=[
{
"type": "text",
"text": "You are a helpful coding assistant...",
"cache_control": {
"type": "ephemeral"
}, # Cache the system prompt separately
}
],
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Hello, Claude"}]
count_response = client.beta.messages.count_tokens(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
print(f"Current tokens: {count_response.input_tokens}")
print(f"Original tokens: {count_response.context_management.original_input_tokens}")client = anthropic.Anthropic()
messages: list[dict] = []
def chat(user_message: str) -> str:
messages.append({"role": "user", "content": user_message})
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 100000},
}
]
},
)
# 응답 추가 (압축 블록은 자동으로 포함됨)
messages.append({"role": "assistant", "content": response.content})
# 텍스트 콘텐츠 반환
return next(block.text for block in response.content if block.type == "text")
# 긴 대화 실행
print(chat("Help me build a Python web scraper"))
print(chat("Add support for JavaScript-rendered pages"))
print(chat("Now add rate limiting and error handling"))
# ... 필요한 만큼 계속from typing import Any
client = anthropic.Anthropic()
messages: list[dict[str, Any]] = []
def chat(user_message: str) -> str:
messages.append({"role": "user", "content": user_message})
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 100000},
"pause_after_compaction": True,
}
]
},
)
# 압축이 발생하고 일시 중지되었는지 확인
if response.stop_reason == "compaction":
# 응답에서 압축 블록 가져오기
compaction_block = response.content[0]
# 이전 대화 + 현재 사용자 메시지(3개 메시지)를
# 압축 블록 뒤에 포함하여 보존
preserved_messages = messages[-3:] if len(messages) >= 3 else messages
# 새 메시지 목록 구성: 압축 + 보존된 메시지
new_assistant_content = [compaction_block]
messages_after_compaction = [
{"role": "assistant", "content": new_assistant_content}
] + preserved_messages
# 압축된 컨텍스트 + 보존된 메시지로 요청 계속
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-8",
max_tokens=4096,
messages=messages_after_compaction,
context_management={"edits": [{"type": "compact_20260112"}]},
)
# 압축을 반영하도록 메시지 목록 업데이트
messages.clear()
messages.extend(messages_after_compaction)
# 최종 응답 추가
messages.append({"role": "assistant", "content": response.content})
# 텍스트 콘텐츠 반환
return next(block.text for block in response.content if block.type == "text")
# 긴 대화 실행
print(chat("Help me build a Python web scraper"))
print(chat("Add support for JavaScript-rendered pages"))
print(chat("Now add rate limiting and error handling"))
# ... 필요한 만큼 계속