압축과 보존된 사고
보존된 사고를 지원하는 모델에서 온디맨드 압축 후 유지된 턴의 사고 블록이 유효하게 유지되는 경우와 이를 확인하는 방법.
"preserved thinking"(보존된 사고)를 지원하는 모델에 사고 블록을 다시 보내고 "compaction"(압축) 블록 이후의 턴을 유지하는 경우가 아니라면 이 페이지를 건너뛰세요. "Kept turns"(유지된 턴)는 블록 뒤에 오는 턴으로, 최근 턴을 유지하는 압축에서처럼 압축 요청에서 제외한 최근 턴이거나, 백그라운드 압축에서처럼 요약이 작성되는 동안 도착한 턴입니다.
보존된 사고를 지원하는 모델은 이전 사고 블록을 그것을 생성한 대화와 대조하여 확인합니다. 요약은 해당 대화의 일부를 대체하지만, API가 요약을 작성한 경우 확인 과정에서 이 교체를 허용하므로 유지된 턴의 사고는 유효한 상태로 남을 수 있습니다.
유지된 사고가 유효하게 유지되기 위한 조건
유지된 턴의 사고 블록은 다음 조건이 모두 충족되는 동안 유효하게 유지됩니다:
- 압축 요청이 보존된 사고를 지원하는 모델에서 실행됩니다. 이 조건은 가장 최근의 압축 요청뿐만 아니라 사고 블록이 생성된 이후의 모든 압축 요청에 적용됩니다. 이 조건을 충족하는 한 가지 방법은 모든 압축 요청을 대화에서 사용하는 모델로 보내는 것입니다.
- 유지된 턴이 요약된 메시지 바로 뒤에 오며, 이를 변경하지 않고 보냅니다. 각 유지된 메시지를 기록에 있는 그대로 정확히 보내세요. 마지막 요약된 메시지와 첫 번째 유지된 메시지 사이에서 메시지를 건너뛰거나 추가하지 마세요. 또한 첫 번째 유지된 메시지는 마지막 요약된 메시지와 다른 역할(role)을 가져야 하며, 대화 중간의
role: "system"메시지일 수 없습니다. 그렇지 않으면 API가 이를 마지막 요약된 메시지에 병합합니다. 첫 번째 유지된 메시지를 올바르게 구성하는 한 가지 방법은 이미 보낸 요청의messages를 정확히 그대로 압축하는 것입니다. 그러면 유지된 턴은 해당 요청에 대한 Claude의 응답으로 시작합니다. system과defer_loading: true로 표시되지 않은tools가 변경되지 않습니다. 이들은 압축 요청에서도 유지된 사고를 생성한 요청에서와 동일하며, 이후 요청에서도 동일하게 유지됩니다. 시스템 프롬프트 또는 도구 변경에서 이를 안전하게 변경하는 방법을 다룹니다.
조건이 충족되지 않더라도 압축 시에는 아무것도 실패하지 않으며, API는 어느 경우든 이후 요청에서 블록을 허용합니다. 실패는 API가 확인을 적용하는 곳에서 유지된 사고를 보내는 첫 번째 이후 요청에서 발생합니다: 기본적으로 400 오류가 발생하거나, 요청에서 thinking.block_binding.prefix_mismatch_behavior를 "drop_block"으로 설정한 경우 사고 블록이 삭제됩니다. Message Batches API에서는 이 필드를 설정하지 않은 항목이 실패하지 않습니다. 확인이 기본적으로 적용되는 경우, API는 대신 블록을 삭제합니다. API가 무효한 블록을 처리하는 방식에서 두 결과를 모두 설명하며, API가 확인을 적용하는 시점에서 어떤 요청이 확인되는지 설명합니다.
이전 사고를 손상시키지 않고 다시 압축하기
다시 압축하면서 턴을 유지할 수 있습니다: 새 블록은 이전 요약과 압축 요청에서 그 뒤에 오는 모든 메시지를 포함하며, 해당 요청에서 제외한 턴은 새 블록의 유지된 턴이 됩니다.
유지된 사고에 대한 조건 중 첫 번째는 사고 블록이 생성된 이후의 모든 압축을 대상으로 하므로, 두 번의 압축을 거쳐 유지하는 턴은 두 압축 모두 보존된 사고를 지원하는 모델에서 실행되어야 합니다.
사고 블록이 생성되기 전의 압축은 해당 블록에 영향을 주지 않습니다. 블록이 자리 잡은 후 생성된 사고는 해당 블록에 바인딩되며, 조건을 충족하는 이후 압축을 거쳐도 유효하게 유지됩니다.
시스템 프롬프트 또는 도구 변경
이후 요청은 압축 요청과 다른 system, 다른 tools 또는 다른 모델을 사용할 수 있으며, API는 여전히 블록을 허용합니다. 이러한 변경은 유지된 턴의 사고를 무효화할 수 있지만, 그 외의 영향은 없습니다.
유지된 사고를 무효화하지 않고 system 또는 tools를 변경하려면, 먼저 전체 대화를 압축하여 유지되는 턴이 없도록 하세요. 그런 다음 다음 요청에서 변경하세요.
system 또는 tools를 건드리지 않고 지시를 추가하거나 사용 가능한 도구를 변경하려면, 접두사를 편집하지 않고 변경하기에 설명된 대로 변경 사항을 messages에 추가하세요.
요약된 턴 내부의 대화 중간 시스템 메시지도 함께 요약되므로, 교체 후에는 해당 메시지에 담긴 텍스트 지시도 더 이상 적용되지 않습니다. 이를 계속 적용하려면, 유지된 턴 뒤에 오는 첫 번째 새 user 턴 바로 다음에 role: "system" 메시지로 다시 명시하세요. 압축 요청에 inline-tools-2026-09-15도 포함된 경우 해당 턴 내부의 도구 변경은 자동으로 이어집니다: 반환된 블록이 tool_changes 필드에 그 최종 효과를 기록하므로, 블록을 수정하지 않고 그대로 다시 보내세요. 블록에 tool_changes 필드가 없으면 해당 도구 변경을 같은 방식으로 다시 명시하세요. 블록과 유지된 턴 사이에 배치된 시스템 메시지는 해당 턴의 사고를 손상시킵니다.
유지된 사고가 유효한지 확인하기
압축 응답은 유지된 사고가 유효한지 알려주지 않습니다. 교체 후 첫 번째 요청이 이를 알려줍니다. 테스트에서 확인하려면:
- 사고를 켠 상태로 짧은 대화를 진행하세요. API가 확인을 실행하는 모델을 사용하고(API가 확인을 적용하는 시점 참조), 모든 단계에서 해당 모델을 사용하세요. 사고 블록을 읽을 수 없는 모델은 오류 없이 블록을 삭제하기 때문입니다.
- 이전 턴을 압축하고, 사고 블록을 포함하는 턴을 하나 이상 유지하세요.
- 블록을 먼저, 그다음 유지된 턴, 그다음 새
user메시지 순서로 배치하고thinking.block_binding.prefix_mismatch_behavior를"error"로 설정하여 다음 요청을 보내세요. - 결과를 확인하세요.
input_transformations배열이 비어 있는 200 응답은 확인에 실패하거나 삭제된 사고 블록이 없음을 의미합니다. 블록이 다른 대화에 바인딩되어 있다는 400 오류는 그러한 블록이 있음을 의미합니다. 메시지는 실패한 첫 번째 블록의 경로로 시작하며, API가 무효한 블록을 처리하는 방식에서 전체 메시지를 보여줍니다.
prefix_mismatch_behavior 필드에는 compact-2026-09-04 베타 헤더와 함께 thinking-binding-controls-2026-08-01 베타 헤더가 필요합니다. 이 필드를 설정하면 확인이 기본적으로 활성화되지 않은 계정에서도 요청이 확인에 참여하게 됩니다.
다음 프로그램은 네 단계를 실행합니다. 유지된 턴에 포함된 사고 블록 수와 input_transformations의 항목 수를 출력하며, 항목이 없으면 유지된 사고가 유효하다는 의미입니다:
from anthropic.types.beta import BetaMessageParam, BetaThinkingConfigParam
client = anthropic.Anthropic()
# Claude Fable 5.1은 다시 전송된 사고 내용을 대화와 대조하여 검사하는 첫 번째 모델입니다.
MODEL = "claude-fable-5-1"
BETAS = ["compact-2026-09-04", "thinking-binding-controls-2026-08-01"]
SYSTEM = "You help plan a recipe app's release. Keep answers short."
# "error"로 설정하면 검사에 실패한 사고 블록으로 인해 요청이 400으로 실패합니다.
THINKING: BetaThinkingConfigParam = {
"type": "adaptive",
"block_binding": {"prefix_mismatch_behavior": "error"},
}
# 1. 사고를 켠 상태로 짧은 대화를 진행합니다.
history: list[BetaMessageParam] = [
{"role": "user", "content": "What are the main entities in the app's data model?"}
]
first = client.beta.messages.create(
model=MODEL,
max_tokens=8192,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history,
)
history += [
{"role": "assistant", "content": first.content},
{
"role": "user",
"content": "Testing starts on Tuesday, March 3, 2026, takes 10 weekdays, and pauses on March 9 and March 16. On which date does it end?",
},
]
second = client.beta.messages.create(
model=MODEL,
max_tokens=8192,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history,
)
history.append({"role": "assistant", "content": second.content})
thinking_blocks = sum(block.type == "thinking" for block in second.content)
print(f"Thinking blocks in the kept turn: {thinking_blocks}")
# 2. 첫 번째 턴을 요약합니다. 두 번째 턴은 요청에 포함하지 않습니다.
summary = client.beta.messages.create(
model=MODEL,
max_tokens=4096,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history[:2],
compaction={"type": "summarize"},
)
if summary.stop_reason != "compaction":
raise SystemExit(f"No summary: {summary.stop_reason}")
# 3. 유지한 턴 앞에 블록을 배치하고 다음 질문을 합니다.
history = [
{"role": "assistant", "content": summary.content},
*history[2:],
{"role": "user", "content": "Which day should the release go out?"},
]
third = client.beta.messages.create(
model=MODEL,
max_tokens=8192,
system=SYSTEM,
betas=BETAS,
thinking=THINKING,
messages=history,
)
# 4. 삭제된 블록 없이 200이 반환되면 유지한 사고가 유효하다는 의미입니다.
print(f"Dropped thinking blocks: {len(third.input_transformations)}")Thinking blocks in the kept turn: 1
Dropped thinking blocks: 0프로덕션에서는 "drop_block"을 사용하면 조건이 충족되지 않을 때도 요청이 계속 성공하며, 삭제된 각 블록이 input_transformations에 reason: "prefix_binding_mismatch"와 함께 보고됩니다. path가 유지된 턴에 해당하는 항목은 해당 턴의 사고가 유효하지 않았음을 의미합니다. API가 무효한 블록을 처리하는 방식에서 무엇이 삭제되는지 설명하고 이에 대한 알림을 설정하는 방법을 안내합니다.
Compatibility
| Supported models |
|
|---|---|
| Supported platforms |
|
Was this page helpful?