v0.109: Fable 5 거부가 HTTP 200으로 도착

SDK v0.108–0.109: Fable 5 200 내 거부, Managed Agents 크론, vault 자격 증명, 0.109.1 enum 수정.

v0.109: Fable 5 거부가 HTTP 200으로 도착
Share

2026년 6월 9일, 공식 Anthropic Python SDK는 8시간 안에 세 번 릴리스됐고, 6일 뒤 정리 릴리스가 이어졌다. 핵심은 새로운 실패 형태다. Claude Fable 5는 요청을 거절하면서도 HTTP 200을 반환할 수 있다.

v0.108–0.109 묶음에는 무엇이 들어 있나?

v0.108–0.109 묶음은 anthropic Python SDK의 네 단계 릴리스 흐름으로, 새 모델 식별자 두 개, 성공 응답처럼 보이는 거절 응답 형태, Managed Agents용 타입 인터페이스를 도입한다. 하루 동안 세 릴리스가 배포됐다. v0.108.0은 16:37, v0.109.0은 20:04, v0.109.1은 23:55에 나왔고, 6월 15일에는 v0.109.2 정리 릴리스가 뒤따랐다 . 이는 Stainless식 코드 생성 배포 리듬이다. API 스펙 변경이 분기별 대형 묶음이 아니라, 작고 잦은 버전으로 나온다.

빠른 답변: v0.108–0.109 묶음은 claude-fable-5claude-mythos-5, 서버 측 및 클라이언트 측 거절 fallback, Managed Agents 타입 인터페이스, 그리고 frontier_llm 거절 카테고리를 추가한다. 이 네 릴리스는 2026년 6월 9일부터 15일까지 배포됐다 .

실질적인 변경은 v0.108.0에 들어가고, 0.109.x 라인이 이를 다듬는다. 저장소 CHANGELOG와 GitHub Releases 기준으로 각 릴리스에 포함된 내용은 다음과 같다 :

릴리스배포 시점추가된 내용
v0.108.06월 9일 16:37claude-fable-5claude-mythos-5, 거절 시 서버 측 fallback(베타), 클라이언트 측 BetaRefusalFallbackMiddleware
v0.109.06월 9일 20:04Managed Agents 타입 인터페이스(cron 스케줄링, vault 환경 자격 증명), managed-agents-2026-04-01 베타 헤더 자동 주입
v0.109.16월 9일 23:55거절 카테고리 enum에 frontier_llm 추가. 출시 당시 빠져 있던 값
v0.109.26월 15일타입 스텁에서 폐기된 모델 식별자 제거

이들을 관통하는 주제는 거절 처리다. v0.108.0은 거절 시 fallback을 도입하고, v0.109.1은 누락된 거절 카테고리를 보완하며, v0.109.2는 타입 클라이언트에서 deprecated 모델을 정리한다 . Fable 5나 Mythos 5를 호출한다면 아래 섹션에서 무엇이 어떻게 달라지는지 줄 단위로 나눠 볼 수 있다. 두 모델도 Managed Agents도 쓰지 않는다면, 실제 영향은 대체로 0.109.2의 타입 스텁 정리에 그친다.

Fable 5의 거절은 예외가 아니라 200이다

문제를 줄 단위로 보면 이렇다. claude-fable-5는 API 오류를 발생시키는 대신, 본문에 stop_reason: "refusal"을 담은 HTTP 200을 반환할 수 있다 . 200을 성공으로 간주하고 content.text를 읽는 핸들러는 이 거절을 조용히 버리게 된다. 예외도 발생하지 않고, 상태 코드가 retry 로직을 건드리지도 않는다. 요청은 사용할 수 있는 내용을 만들지 못했지만, 코드는 이를 알아차리지 못한다.

정작 필요한 세부 정보는 stop_details에 있다. 여기에는 category와 사람이 읽을 수 있는 explanation이 들어간다. 출시 당시 문서화된 카테고리는 cyber, bio, frontier_llm, reasoning_extraction이었다 . 실제 마이그레이션에서 해야 할 일은 간단하다. content.text에 접근하기 전에 반드시 stop_reason으로 분기해야 한다.

"거절 응답은 HTTP 200과 refusalstop_reason으로 반환되며, stop_details 객체에는 카테고리와 설명이 포함된다." — Anthropic 거절 및 fallback 문서 (source: platform.claude.com).

이는 Fable에 한정된 동작이지, 모든 모델에 공통으로 적용되는 것은 아니다. claude-mythos-5는 Project Glasswing을 통해 접근이 제한되며, 100만 토큰 컨텍스트 창과 입력 100만 토큰당 10달러, 출력 100만 토큰당 50달러 가격을 갖는다 . 이 모델에는 Fable 5의 안전 분류기가 없다. 따라서 200 안의 거절은 모델 선택으로 opt in하는 Fable 5 동작이지, 모든 Anthropic 모델에 걸친 일괄 변경이 아니다.

출시 당시에는 enum 공백 하나가 상황을 더 나쁘게 만들었다. frontier_llm 카테고리는 v0.109.1에서 추가되기 전까지 SDK의 타입 enum에 빠져 있었다 . 카테고리 값을 검증하거나 그 값으로 분기하던 타입 클라이언트는, 경쟁 모델 개발을 도울 수 있는 요청을 표시하는 바로 그 거절을 업그레이드 전까지 잘못 처리할 수 있었다.

fallback을 연결하면, 응답은 실제로 무엇이 실행됐는지도 알려준다:

  • Fallback content blocks는 한 모델이 멈추고 다른 모델이 이어받은 지점을 표시한다 .
  • usage.iterationsmessagefallback_message 타입 항목을 보면 어떤 모델이 어떤 토큰을 생성했는지 추적하고, 그에 맞춰 과금도 계산할 수 있다.
  • 최상위 model은 실제로 답변한 모델을 나타낸다. 요청한 모델이 아니다. 따라서 응답 모델이 요청 파라미터와 같다고 가정하면 안 된다.

Fable 5 통합에서 기억해야 할 점은 이렇다. 200은 전달 영수증이지, 콘텐츠 보장이 아니다. 먼저 stop_reason을 확인하고, stop_details.category를 읽어 분류한 뒤, usage.iterations와 최상위 model 필드로 실제 실행된 내용을 재구성해야 한다 .

자동 재시도가 작동하는 곳과 작동하지 않는 곳

자동 거부 재시도는 정확히 두 환경에서만 작동합니다. 서버 측 폴백은 Fable 5 분류기의 거부를 한 번의 API 호출 안에서 재시도하고 단일 메시지를 반환하지만, 베타 전용입니다. 즉 server-side-fallback-2026-06-01 헤더로 활성화해야 하며 Claude API 직접 호출과 AWS의 Claude Platform에서만 사용할 수 있습니다 . 그 밖의 모든 환경에서는 재시도가 플랫폼이 아니라 여러분 코드의 책임입니다.

이 구분이 중요한 이유는 클라우드 리셀러가 명시적으로 제외되어 있기 때문입니다. Message Batches, Amazon Bedrock, Vertex AI, Microsoft Foundry는 서버 측 폴백을 지원하지 않습니다. 이런 플랫폼에서는 대신 SDK의 클라이언트 측 미들웨어를 직접 연결해야 합니다 . 이 인터셉터가 BetaRefusalFallbackMiddleware이며, BetaFallbackState와 함께 사용됩니다. 거부된 요청을 잡아 폴백 대상에 다시 보내고 fallback-credit-2026-06-01 헤더를 자동으로 붙입니다 .

미들웨어 지원 범위는 언어 SDK마다 고르지 않습니다.

환경 / SDK재시도 경로
Claude API 직접 호출, AWS의 Claude Platform서버 측 폴백(한 번의 API 호출)
Python, TypeScript, Go, Java, C#BetaRefusalFallbackMiddleware(클라이언트 측)
Ruby, PHP, 원시 HTTP없음 — 직접 재시도 구현 필요
Message Batches없음 — 거부된 항목을 모아 수동으로 다시 제출

따라서 Ruby와 PHP 팀, 그리고 원시 HTTP 엔드포인트를 호출하는 경우에는 미리 만들어진 헬퍼가 없으므로 재시도와 헤더 재설정 루프를 직접 구현해야 합니다 . 배치 사용자는 더 까다롭습니다. 자동 경로가 전혀 없기 때문에 결과 집합에서 거부된 항목을 모아 새 요청으로 다시 제출해야 합니다 .

전용 크레딧 헤더가 존재하는 이유는 비용 때문입니다. 프롬프트 캐시는 모델별로 적용되므로, 거부된 요청을 다른 모델에서 재시도하면 원래라면 전체 캐시 쓰기 비용을 다시 내야 합니다. 거부 응답에는 이 재과금을 상쇄하기 위한 fallback_credit_token과, 프리필 요청용 fallback_has_prefill_claim 플래그가 포함될 수 있습니다 . 이 크레딧 덕분에 모델을 바꿔 재시도해도 입력 비용이 조용히 두 배로 불어나지 않습니다.

모든 경로에 적용되는 제약도 하나 있습니다. 출시 시점 기준으로 Fable 5 거부에 허용된 유일한 폴백 대상은 Claude Opus 4.8(claude-opus-4-8)입니다 . 임의의 더 저렴한 모델을 고를 수는 없습니다. 넘겨받는 대상은 Opus 4.8이거나, 아무것도 없습니다. 실무적으로는 Fable 5가 거절하는 트래픽 비율만큼 Opus 등급 가격을 예산에 반영하고, 어떤 환경에서 실행 중인지 계측한 뒤에야 재시도가 무료로 일어난다고 가정해야 한다는 뜻입니다.

판단 흐름은 짧습니다. Anthropic 직접 호출이나 AWS라면 베타 헤더를 보내 플랫폼이 재시도하게 두면 됩니다. Bedrock, Vertex, Foundry에서 지원 SDK를 쓴다면 미들웨어를 설치합니다. Ruby, PHP, 원시 HTTP, Batches라면 재시도를 직접 작성하고 명시적으로 다시 제출해야 합니다 .

예약 실행과 볼트에 저장되는 시크릿

이번 배치의 나머지 절반은 바로 다음 릴리스에 들어갔습니다. v0.109.0은 Anthropic의 Managed Agents를 위한 타입 지정 인터페이스를 추가합니다. 이는 장기 실행 및 비동기 작업을 위한 베타 단계의 사전 구축형 실행 틀로, agents, environments, sessions, events라는 네 가지 객체를 중심으로 모델링되어 있습니다 . 모든 요청에는 managed-agents-2026-04-01 베타 헤더가 붙으며, SDK가 이를 자동으로 주입하므로 호출마다 직접 설정할 필요가 없습니다 .

핵심 기능은 자율 스케줄링입니다. 예약된 배포를 설정하면 에이전트가 POSIX 크론 표현식과 IANA 타임존 조합에 따라 스스로 세션을 열 수 있습니다. 최소 단위는 분까지이며, 분보다 더 작은 단위의 트리거는 없습니다 .

타입 지정 인터페이스는 프로덕션 크론 작업에 필요한 제어 기능을 노출합니다:

  • upcoming_runs_at — 계산된 다음 실행 시각으로, 스케줄이 의도한 대로 해석되는지 확인할 수 있습니다.
  • 스케줄 외 수동 일회성 실행과 함께 일시 중지, 재개, 보관 제어 기능 .
  • 각 호출에 대한 실행 기록, 그리고 정각 분 경계에 부하가 몰리지 않도록 최대 10초의 지터.
  • 조직당 예약 배포 1,000개라는 하드 제한 — 에이전트별 감각이 아니라 이 상한을 기준으로 팬아웃을 설계해야 합니다 .

자격 증명은 별도 모델로 다뤄집니다. 환경 변수 시크릿은 볼트에 저장되며, 카테고리는 mcp_oauth, static_bearer, environment_variable 세 가지입니다 . 환경 변수 자격 증명은 secret_name으로 키가 지정되고, 샌드박스 안에는 불투명한 플레이스홀더로 저장됩니다. 실제 값은 요청이 샌드박스를 떠나는 지점인 이그레스에서만 대체되므로, 에이전트 자체는 원본 시크릿을 읽지 못합니다.

이 설계는 가장 obvious한 유출 경로를 막습니다. 프롬프트 인젝션을 당한 에이전트가 자격 증명을 이름으로 참조할 수는 있어도 그 내용을 빼낼 수는 없습니다. 다만 이 단계에서 이를 기반으로 구축하기 전에 알아둘 트레이드오프가 있습니다:

  • 아직 자체 호스팅 샌드박스는 지원하지 않습니다 — 볼트 자격 증명은 Anthropic이 관리하는 환경을 전제로 합니다.
  • 자격 증명 키는 생성 후 변경할 수 없습니다. 이름을 바꾸려면 삭제하고 다시 만들어야 합니다.
  • 중복 키는 409를 반환하므로 생성 작업은 멱등적이지 않습니다 — 충돌을 명시적으로 처리해야 합니다.
  • 볼트당 최대 20개의 자격 증명 .

Messages API만 호출하는 개발자에게는 이 변화가 영향을 주지 않습니다. 하지만 에이전트를 크론에 연결하고 시크릿을 환경 변수에 직접 넣고 있었다면, v0.109.0은 예약 배포와 볼트라는 타입 지정 기본 요소를 제공하며 이제 SDK가 대신 검증해 줍니다.

타입 핸들러에서 조용히 오작동하던 enum 누락

v0.109.0은 refusal 인터페이스를 배포하면서 타입 enum에 frontier_llm 값을 빠뜨렸습니다. 그래서 해당 카테고리의 Fable 5 refusal이 발생하면 다음 패치가 나오기 전까지 엄격한 타입 핸들러가 깨질 수 있었습니다 . 모든 경우를 다루는 match/switch 문은 빠져나가고, Pydantic Literal 검증기는 인식하지 못한 문자열에 예외를 냈을 것입니다. 수정은 몇 시간 뒤 v0.109.1에 들어갔고, 변경 내용은 단순히 “frontier_llm refusal category”를 추가한 것이었습니다 .

이 공백이 중요했던 이유는 refusal 처리 경로가 이미 실제로 동작 중이었기 때문입니다. 클라이언트는 HTTP 200과 함께 stop_reason: "refusal" 및 코드가 존재조차 몰랐던 카테고리가 들어 있는 stop_details를 받을 수 있었습니다. 0.109.0 스텁을 기준으로 작성된 검증 로직은 정상 응답을 잘못된 응답으로 취급했을 것입니다.

frontier_llm은 실제로 무엇을 포괄할까요? Anthropic은 이를 상업 조건상 경쟁 AI 모델 개발을 도울 수 있는 요청으로 설명하며, 정상적인 머신러닝 작업도 이를 트리거할 수 있다고 명시합니다 . 따라서 이는 적대적 프롬프트에만 해당하는 예외 상황이 아닙니다. Fable 5로 일반적인 ML 실험을 실행하는 개발자도 마주칠 수 있으므로, 누락된 enum 값은 이론적 문제가 아니라 프로덕션 위험입니다.

전체 refusal 카테고리는 네 가지이며, 타입 클라이언트가 안전하려면 모든 exhaustive match에 네 값이 모두 들어가야 합니다:

  • cyber
  • bio
  • frontier_llm
  • reasoning_extraction

이 값들은 refusal의 stop_details에 반환되는 문서화된 카테고리입니다 . 핸들러가 카테고리에 따라 분기하거나, 다운스트림 서비스가 이 값을 타입 스키마로 직렬화한다면, 이 중 하나라도 빠지는 순간 0.109.0이 가졌던 동일한 fall-through 문제가 다시 생깁니다.

실무적 결론은 이렇습니다. Fable 5 refusal 로직을 프로덕션에 배포하기 전에는 최소 v0.109.1 이상으로 고정하세요. 카테고리 타입 핸들러를 쓰면서 아직 0.109.0에 머물러 있는 개발자는 먼저 업그레이드해야 합니다 — 두 릴리스는 2026년 6월 9일 같은 날 나왔으므로, 더 이른 버전에 머물 이유가 없습니다 . 즉시 업그레이드할 수 없다면, 검증기에서 refusal 카테고리를 닫힌 Literal이 아니라 열린 문자열 집합으로 취급하고, 알 수 없는 값에는 예외를 내지 말고 로그를 남기세요.

0.109.2 이후: 타입 스텁에서 사라진 것들

거절 처리 로직이 탄탄해졌다면, 이 릴리스 흐름의 마지막 버전은 가장 이해하기 쉽습니다. 2026년 6월 15일에 공개된 0.109.2는 SDK 타입 정의에서 폐기된 모델 식별자를 제거하는 정리 전용 릴리스입니다 . 동작 변경도, API 표면 변경도 없습니다 — 클라이언트는 0.109.1 때와 같은 엔드포인트와 통신합니다.

"remove retired models from API and SDKs" — anthropics/anthropic-sdk-python CHANGELOG (source: GitHub Releases)

실제 영향은 런타임이 아니라 타입 검사 시점에 나타납니다. 코드가 SDK의 타입 지정 모델 enum을 통해 제거된 식별자를 참조한다면, 업그레이드할 때 타입 또는 린트 오류가 보일 수 있습니다 . 원시 문자열 리터럴은 영향을 받지 않습니다 — 하드코딩된 모델 이름은 그대로 전달되어 서버 측에서 해석되므로, 실패 양상은 깨진 요청이 아니라 더 엄격해진 로컬 툴체인입니다.

그래서 업그레이드 순서는 단순합니다. Fable 5 또는 Mythos 5로 이동하는 팀이라면 다음 흐름이 깔끔합니다.

  • 먼저 0.109.2로 업그레이드합니다. 타입 지정 모델 목록에서 폐기된 식별자 관련 잡음을 없애고, 오래된 참조를 한 번에 드러낼 수 있습니다.
  • 거절 처리 로직을 점검합니다. 문서화된 네 가지 카테고리인 cyber, bio, frontier_llm, reasoning_extraction이 모두 있어야 합니다. Fable 5에서는 stop_reason: "refusal"이 포함된 200 응답이 정상 성공 경로이기 때문입니다 .
  • 그다음 필요한 재시도 경로를 켭니다 — Claude API에서는 서버 측 fallback을, 서버 측 fallback을 사용할 수 없는 Bedrock, Vertex, Foundry에서는 클라이언트 측 미들웨어를 사용합니다 .

핵심은 이렇습니다. 0.109.2는 6월 9일 묶음 전체의 안전한 도착점입니다. 동작은 건드리지 않고 죽은 모델 이름만 제거하므로, 이 버전으로 업그레이드한 뒤 카테고리 enum이 완전한지 확인하고, 거절을 성공 응답으로 처리할 수 있게 된 다음에만 fallback을 켜면 됩니다. SDK의 자동 코드 생성 주기를 보면 이런 작은 릴리스는 앞으로도 계속 나올 것입니다 — 버전을 고정하고 changelog를 읽어야 합니다. 이제 타입 스텁은 이를 설명하는 본문 문서보다 더 빠르게 움직입니다.

마지막 업데이트: 2026-06-18.

자주 묻는 질문

stop_reason: refusal이란 무엇이며 API 오류와 어떻게 다른가요?

거절은 구조적으로 성공한 응답입니다. 전송 계층은 HTTP 200을 반환하지만, 모델은 답변을 거부하고 stop_reason: "refusal"을 설정하며, stop_details에는 categoryexplanation이 담깁니다 . 4xx나 5xx와 달리 SDK는 예외를 발생시키지 않습니다 — 콘텐츠 블록을 소비하기 전에 코드에서 stop_reason을 검사해야 합니다. 그렇지 않으면 답변이 아니라 거절 문구가 들어 있는 본문을 읽게 됩니다.

Bedrock, Vertex, Foundry 사용자는 거절 시 자체 재시도를 구현해야 하나요?

예. 서버 측 fallback은 Claude API와 AWS의 Claude Platform에서만 베타로 제공됩니다. Message Batches, Amazon Bedrock, Vertex AI, Microsoft Foundry에서는 사용할 수 없습니다 . 해당 플랫폼에서는 Python, TypeScript, Go, Java, C#용으로 문서화된 SDK의 BetaRefusalFallbackMiddleware를 사용해야 합니다. Ruby와 PHP에는 미들웨어가 없으므로 직접 재시도 로직이 필요하고, batch 사용자는 거절된 항목을 모아 수동으로 다시 제출해야 합니다.

Fable 5의 네 가지 거절 카테고리는 무엇인가요?

문서화된 카테고리는 cyber, bio, frontier_llm, reasoning_extraction입니다 . frontier_llm 카테고리 — 경쟁 모델 개발을 도울 수 있는 요청과 일부 무해한 ML 작업을 포함합니다 — 는 v0.109.1 전까지 타입 지정 SDK enum에 없었습니다 . 카테고리 타입 기반 핸들러가 있는 0.109.0 코드라면 실제 트래픽을 처리하기 전에 업그레이드해야 합니다.

frontier_llm이 enum에 없을 때 타입 지정 코드에서는 정확히 무엇이 깨졌나요?

stop_details.category를 닫힌 값 집합으로 제한한 코드 — exhaustive match/switch 문이나 Pydantic Literal 및 enum validator — 는 v0.109.1 전까지 frontier_llm을 처리할 경로가 없었습니다 . 그런 방식으로 분류된 거절은 파싱 시 validation error를 일으키거나 기본 분기로 조용히 빠져, 실제 Fable 5 거절을 올바르게 라우팅하지 못하고 잘못 처리했을 것입니다.

Mythos 5는 일반적으로 사용할 수 있나요? 그리고 거절 시 HTTP 200을 반환하나요?

둘 다 아닙니다. Claude Mythos 5(claude-mythos-5)는 Project Glasswing을 통해 접근이 제한되어 있으며 Fable 5의 안전 분류기를 갖고 있지 않습니다. 따라서 stop_reason: "refusal"을 반환하지 않습니다 — 그 동작은 Fable 5에만 해당합니다 . 두 모델 모두 100만 토큰 컨텍스트 창을 공유하며, 가격은 입력 100만 토큰당 10달러, 출력 100만 토큰당 50달러입니다 .