🎁 신규 무료 가입, 10회 호출 제공. 최대 $1, 카드 불필요.
에이전트를 위한 Claude Fable 5: 툴 호출 거부, GLM 5.2 대비 비용

에이전트를 위한 Claude Fable 5: 툴 호출 거부, GLM 5.2 대비 비용

목차
  1. tool call을 실행하기 전에 stop_reason부터 확인하라
  2. 다섯 가지 에이전트 형태의 비용
  3. 에이전트 청구서를 낮게 유지하기
  4. 문서가 짚어 주지 않는 두 가지 비용 함정
  5. request surface 에서 바뀐 것
  6. 결론
  7. FAQ

우리 평가에서 Claude Fable 5 는 코딩 에이전트 44 턴 중 11 턴에서 툴 호출 도중 작업을 거부했다. config 기본값을 고치는 것처럼 지극히 평범한 작업에서도 그랬다. 거부는 툴 인자를 생성하던 중간에 stop_reason: "refusal" 로 날아온다. 잘려버린 인자도 유효한 JSON 으로 파싱되기 때문에, stop reason 을 확인하지 않고 툴 호출을 실행하는 에이전트 루프는 반쯤 만들다 만 파일을 아무 문제 없다는 듯 디스크에 써버린다. Fable 5 를 에이전트에 투입할 때 가장 먼저 손봐야 할 것은 가격표가 아니라 바로 이 동작이다.

TL;DR

  • Claude Fable 5 는 평범한 에이전트 작업( config 기본값 수정, 회의실 예약)에서 툴 호출 도중 stop_reason: "refusal" 을 반환했다. 잘린 write_file 인자도 파싱이 되므로, stop reason 을 확인하지 않는 루프는 반쯤 작성된 파일을 실행해버린다.
  • Fable 5 의 thinking 은 적응형이고 끄는 스위치가 없다. enableddisabled 둘 다 거부되며, 제어는 output_config.effort 로 한다.
  • Fable 5 의 비용 프리미엄은 작업 형태에 따라 다르다. 4 턴짜리 코딩 작업은 $0.045 로 glm-5.2 의 $0.003 대비 15배였지만, warm 배치 작업에서는 sonnet-5 의 5배에 그쳤다.
  • Fable 5 는 30일 데이터 보존을 요구한다.

아래 내용은 모두 2026-07-05 에 Synthorai 게이트웨이를 통해 작은 시나리오 하네스로 측정했다. 다섯 가지 에이전트 워크로드 형태(툴을 쓰는 코딩 루프, RAG 질의응답, 툴 위주의 오케스트레이션, 배치 분류, 15 턴 대화)를 claude-fable-5, claude-opus-4-8, claude-sonnet-5, glm-5.2 에 대해 돌렸고, 편차가 중요한 작업은 태스크당 3회씩 실행했다. 태스크는 일부러 사소하게 잡았다. 통과율은 능력 벤치마크가 아니라 정상 동작 여부를 거르는 관문일 뿐이다. 비용은 게이트웨이가 청구한 usage.cost 값이다.

tool call을 실행하기 전에 stop_reason부터 확인하라

문서가 경고해 주지 않는 실패 유형이고, 상태를 망가뜨린다. 에이전트가 app.py를 읽고 수정 코드를 작성하기로 결정한 뒤 write_file 호출을 내보내기 시작한다. 그런데 파일 내용을 절반쯤 쓰던 도중에 스트림이 멈춘다.

{
  "stop_reason": "refusal",
  "content": [{
    "type": "tool_use",
    "name": "write_file",
    "input": {
      "path": "app.py",
      "content": "DEFAULTS = {\n    \"timeout_s\": 30,\n    "
    }
  }]
}

input 객체는 완전하고 파싱 가능한 JSON이다. “도중에 멈췄다”는 신호는 어디에도 없다. 루프의 규약이 “tool call을 받았으면 실행한다”라면, 방금 app.py를 38자짜리 파편으로 덮어쓴 것이다. 딕셔너리 중간에서 끝나 버려 더 이상 Python으로 파싱되지 않고, 다음 턴도 refusal이라 루프는 워크스페이스가 망가진 채로 끝난다.

데이터에서 확실히 말할 수 있는 것이 세 가지 있다.

  • 평범한 작업에서 발동한다. refusal을 유발한 작업은 config 조회의 KeyError 수정, slugify 함수 구현, 회의실 예약, 청구서 초안 생성이었다. 이중 용도도 아니고 민감한 것도 없다.
  • 무작위가 아니라 재현된다. 어떤 코딩 작업은 streaming과 non-streaming을 가리지 않고 세 번의 실행 모두에서 refusal이 발생했다. 반면 다른 작업들은 한 번도 발생하지 않았다. 조건 전반에 걸쳐 사소한 코딩 에피소드의 통과율은 Fable 5에서 58~75%였고, claude-opus-4-8、claude-sonnet-5、glm-5.2는 100%였다. 그리고 모든 실패는 잘못된 코드가 아니라 refusal로 귀결됐다.
  • refusal이 대화에 한 번 들어오면 그 에피소드는 끝이다. 이후 턴은 빈 출력과 함께 stop_reason: "refusal"을 반환했다. 같은 컨텍스트 안에서 재시도해도 복구되지 않았다.

트리거는 작업 내용이 아니고, 데이터가 이 점을 분명히 보여준다. 매번 거부된 작업은 config 딕셔너리의 9줄짜리 KeyError 수정이었다. credential도 없고 exploit도 없다. 반면 배치 시나리오에서는 암호화폐 채굴, 유출된 Stripe 키, 피싱 페이지에 관한 지원 티켓을 단 한 건의 refusal도 없이 분류했고, RAG 시나리오에서는 AES-256-GCM 시크릿과 침해 대응 절차로 가득한 문서를 대상으로 답변했는데 역시 깨끗했다. 모든 refusal은 멀티턴이면서 tool을 실행하는 두 시나리오에서 발생했다. 단발성인 세 시나리오는 더 무거운 내용을 다루면서도 한 번도 거부하지 않았다. 패턴은 단어가 아니라 에이전트 루프의 형태에 있다. 즉 입력을 아무리 정제해도 막을 수 없다.

수정은 tool 실행 단계 앞에 한 줄이면 된다.

if response.stop_reason == "refusal":
    # do NOT execute tool calls from this turn: arguments may be truncated
    raise AgentInterrupted("model refused; restart episode or escalate")

동작 방식은 Anthropic이 문서화해 두었다. 출력이 나오기 전에 발동한 refusal은 빈 content 배열을 반환하고 과금되지 않는다. 스트림 도중에 발생한 refusal은 이미 스트리밍된 출력에 과금되며, 지침은 그 부분 출력을 버리라는 것이다. 응답에는 카테고리(cyberbio 같은 값, 또는 null)를 담은 stop_details 객체도 실려 있어서 분류기 차단인지 일반적인 거부인지 구분할 수 있다. 문서가 명시하지 않은 것은 위에서 겪은 tool use와의 상호작용이다. refusal이 인자 생성 도중에 발생할 수 있고, 그 부분 인자는 완전한 인자와 구별되지 않는다.

공식 복구 경로도 있다. Claude API에서는 베타 fallbacks 파라미터(betas: ["server-side-fallback-2026-06-01"]fallbacks: [{"model": "claude-opus-4-8"}])가 거부된 요청을 같은 호출 안에서 fallback 모델로 다시 실행하며, 거부가 출력 전에 발동한 경우 그 거부 자체는 과금되지 않는다. Amazon Bedrock、Vertex AI、Microsoft Foundry에서는 사용할 수 없고, 대신 SDK가 클라이언트 측 fallback 미들웨어를 제공한다. 어느 경로를 쓰든 위의 가드가 먼저다. stop reason이 refusal인 턴의 tool call은 절대 실행하지 마라.

다섯 가지 에이전트 형태의 비용

같은 프롬프트를 같은 날에 돌렸을 때, 완료된 단위(작업, 쿼리, 항목, 대화) 하나당 비용의 중앙값이다.

시나리오fable-5opus-4-8sonnet-5glm-5.2
코딩 루프 (작업당, 중앙값 4턴)$0.045$0.012$0.0059$0.0031
RAG 응답 (쿼리당)$0.024$0.0075$0.0036$0.0031
도구 오케스트레이션 (작업당)$0.048$0.011$0.0045$0.0027
배치 분류 (항목당, warm)$0.0024$0.0012$0.00046$0.00057
15턴 대화 (전체)$0.94$0.34$0.26$0.083

이 표에서 개별 숫자보다 중요한 건 두 가지 관점이다.

  • 가장 싼 모델은 형태에 따라 바뀐다. 루프와 긴 대화에서는 glm-5.2 가 이기지만, 배치 분류에서는 claude-sonnet-5 가 glm-5.2 보다도 싸다. scaffold 프롬프트가 warm 상태가 되면 cache-read 비율이 97% 에 달해서 도입 가격의 이점이 그대로 살아나기 때문이다.
  • Fable 5 의 프리미엄도 형태에 따라 다르다. 코딩 루프에서는 glm-5.2 의 15배, 대화에서는 11배지만, 캐싱이 프롬프트 대부분을 흡수하는 warm 배치 항목에서는 sonnet-5 의 5배에 그친다.

나머지 비용 이야기는 이 숫자들을 통제하는 방법, 그리고 그 숫자를 조용히 다시 밀어 올리는 두 가지에 관한 것이다.

에이전트 청구서를 낮게 유지하기

캐싱이 가장 큰 지렛대이고, Fable 5 에서도 그 계약은 그대로다. 에이전트 데이터를 보면 그 가치가 드러난다. cache_control 마커를 제거하면 같은 코딩 작업의 비용이 2.0배, warm 배치 항목은 6.8배로 뛰었다. opus-4-8 에서 같은 실험을 하면 3.8배와 6.9배가 나온다. 루프에서 sliding-marker 패턴은 최적화가 아니라, 감당 가능한 청구서냐 아니냐를 가르는 요소다.

프롬프트 순서가 두 번째 지렛대인데, 우리가 돌린 모든 모델에서 통했다. 쿼리별 컨텍스트 뒤가 아니라 앞에 안정적인 규칙을 두면 네 모델 모두에서 RAG 쿼리가 26~37% 저렴해졌다. Claude 계열에서는 순서를 잘못 두면 모든 호출마다 1.25배의 cache-write 프리미엄까지 추가로 물게 된다. 원리는 LangChain 캐싱 글에 있고, 여기 숫자들은 그 원리가 Fable 5 에도 그대로 적용된다는 것을 확인해 줄 뿐이다.

Fable 5 는 자체적인 지렛대도 두 개 더한다. 첫 번째는 캐시 적용 하한선이 2,048 토큰으로 내려간 것으로, Opus 4.8 의 4,096 의 절반이다. 이건 사소한 정보처럼 들리지만, 에이전트의 절감이 어디서 나오는지 떠올리면 얘기가 달라진다. 반복되는 scaffold(시스템 프롬프트, 도구 정의, sliding 대화 prefix)가 캐시되는 대상이고, 하한선을 넘겨야만 캐시된다. 턴별 prefix 가 2,048 에서 4,096 토큰 사이였던 도구 중심 에이전트는 Opus 4.8 에서는 캐싱이 전혀 안 됐지만, Fable 5 에서는 캐싱이 시작된다. 이후 모든 턴에서 정가 prefix 가 대략 정가의 10% 수준인 cache read 로 바뀐다. 반대 방향으로도 작동한다. 기존 4,096 하한선을 넘기려고 패딩을 넣어둔 prefix 는 이제 쓸데없는 무게를 지고 있을 수 있다. 짐작하지 말고 실제 응답에서 cache_read_input_tokens 를 읽어라. Fable 5 에서는 할인이 더 일찍 시작되기 때문이다.

두 번째는 task budget(베타, 헤더 task-budgets-2026-03-13)으로, 이 비교가 계속 드러내는 바로 그 문제를 다룬다. Fable 5 루프는 청구서를 빠르게 불리는데 max_tokens 는 도움이 안 된다. 이건 모델이 볼 수 없는 응답당 하드 캡이라, 모델은 무한한 공간이 있는 것처럼 계획을 세우다가 생각 도중에 잘려버린다. task budget 은 다르다. 루프에 토큰 상한(최소 20,000)을 주면 모델은 이를 남은 카운트다운처럼 보면서 스스로 페이스를 조절하고, 잘리는 대신 깔끔하게 마무리한다. 매 요청마다 다시 보내는 전체 히스토리가 아니라, 모델이 생성한 것과 그 턴에서 읽은 도구 결과를 센다. 코딩 루프 턴 비용이 glm-5.2 의 15배인 모델에서, 모델이 스스로 맞춰가는 예산은 붙일 수 있는 가장 싼 가드레일이다.

문서가 짚어 주지 않는 두 가지 비용 함정

주요 설정을 잡고 나서도, 문서에 경고가 없는 방향으로 요금에 영향을 준 작은 요소가 두 가지 더 있었다.

“low” effort 가 더 싸지 않았다. Fable 5 의 thinking 깊이는 output_config.effort 로 조절하는데, low 가 비용이 적을 것이라 생각하기 쉽다. 실제로는 그렇지 않았다. effort: "low" 로 코딩 루프를 돌리면 태스크당 $0.0478 이 나왔고, 기본값에서는 $0.0451 이었다. output token 도 더 적기는커녕 더 많았다. GLM 5.2 에서도 같은 양상이었고, 여기서도 effort 이름이 token 수를 따라가지 않는다. 두 모델 계열 모두 “low” 가 “적음”을 뜻한다고 가정하지 말고, 자기 워크로드에서 이 값을 직접 측정하라. 숫자를 예측하기 어려운 이유 하나는, adaptive thinking 이 차지하는 output token 비율이 코딩 루프에서 2%, RAG 답변에서 30%, 배치 분류에서 52% 로 흔들렸다는 점이다. 같은 모델, 같은 날 기준이다. output token 예산은 모델별이 아니라 워크로드 형태별로 잡아야 한다.

reasoning_content 를 절대 다시 넣지 마라. OpenAI 호환 모델에서 reasoning 필드는 대화 이력이 아니다. DeepSeek API 는 이 필드를 제거하도록 요구한다. GLM 5.2 에서는 다시 넣어도 되지만 과금된다. 이걸 메시지 이력에 다시 넣었더니 GLM 루프 비용이 약 28% 부풀었고, 제거하고 나서야 정상으로 돌아왔다. Anthropic 자체 thinking 블록은 다르다. 같은 모델에서는 그대로 다시 넣어야 하지만, Fable 5 thinking 블록이 다른 모델로 라우팅되면(예: Opus 로 fallback 될 때) prompt 에서 자동으로 제거되고 과금도 되지 않으므로, 따로 제거할 것이 없다.

request surface 에서 바뀐 것

Fable 5 는 request surface 대부분을 Opus 4.7/4.8, Sonnet 5 와 공유한다. 문서 기준으로 사라진 항목은 다음과 같다.

  • thinking: {type: "enabled", budget_tokens: N} 는 400 을 반환한다. token 예산을 지정하는 extended thinking 은 Claude 3.7 Sonnet 부터 4.5 계열까지 쓰이던 방식으로, 4.7+ 라인 전체에서 adaptive thinking 으로 대체되며 퇴출됐다.
  • thinking: {type: "disabled"} 는 400 을 반환한다. 이건 Fable 5 에만 해당한다. Opus 4.7/4.8 과 Sonnet 5 는 여전히 thinking 을 끌 수 있지만 Fable 5 는 못 끈다.
  • temperature, top_p, top_k 는 기본값이 아닌 값이면 거부된다.
  • Assistant 메시지 prefill(마지막 턴에 assistant 를 붙이는 것)은 400 을 반환한다.

포팅한 request 에서 가장 자주 걸리는 것은 temperature/top_p/top_k 와 prefill 제거 두 가지다. thinking 과 retention 변경은 위 내용과 retention 관련 글에서 다룬다.

결론

에이전트에서 Fable 5 는 예산 문제이기 이전에 엔지니어링 문제다. tool call 을 실행하기 전에 stop_reason: "refusal" 을 처리하지 않으면, config 수정처럼 지루한 태스크에서도 잘린 쓰기가 상태를 망가뜨린다. 그리고 비용은 직접 다듬는 대상으로 봐야 한다. 캐싱이 가장 큰 지렛대이고, 적용 하한선이 이제 2,048 token 이니 prefix 를 다시 확인하라. 태스크 예산을 두면 이번 비교에서 가장 높은 턴당 비용까지 루프가 치솟는 것을 막을 수 있고, effort: "low" 는 이름이 암시하는 만큼 할인이 아니다. 예산은 워크로드 형태별로도 잡아라. 같은 모델이 코딩 루프에서는 glm-5.2 의 15배, warm 배치 작업에서는 sonnet-5 의 5배 비용이 나온다. 쓰라 마라의 문제가 아니라, 기본값이 중립적이지 않다는 이야기다. 요금도 실패 방식도 모두 에이전트를 어떻게 구성했느냐에 달려 있다.

FAQ

Fable 5 는 tool call 을 자주 거부하나요? 특정 작업에 몰려 있었습니다。 config 수정 작업 하나는 실행할 때마다 거부했고,다른 작업들은 한 번도 거부하지 않았으며,동일한 작업은 streaming 과 non-streaming 호출 양쪽에서 똑같이 재현됐습니다。 재시도로 넘길 수 있는 드문 오류가 아니라는 뜻입니다。 실제 워크로드에서의 비율은 다를 수 있지만,엔지니어링 관점의 답은 어느 쪽이든 같습니다。 tool call 을 실행하기 전에 stop_reason 을 확인하세요。

Fable 5 의 thinking 을 끌 수 있나요? 없습니다。 thinking.type.disabledenabled 둘 다 거부됩니다。 thinking 은 기본적으로 adaptive 이고 제어할 수 있는 건 output_config.effort 뿐입니다。 우리 루프에서는 low effort 로도 비용이 줄지 않았습니다。

Fable 5 가 저렴한 선택이 되는 경우도 있나요? 이번 세트에서는 없습니다。 프리미엄이 가장 작은 경우는 warm cache 비중이 높은 배치 작업으로,sonnet-5 대비 약 5배 수준입니다。 warm cache 가 prompt 대부분을 흡수하는 경우죠。 루프 작업과 긴 대화에서는 우리가 돌린 모델 중 가장 비쌌습니다。


검증: 모든 수치는 2026-07-05 에 https://synthorai.io/ 를 대상으로 측정했습니다(Claude 계열은 Anthropic-native /v1/messages,glm-5.2 는 /v1/chat/completions)。 다섯 가지 시나리오 형태에 걸쳐 505 개 episode 와 1,022 개 call,편차가 중요한 작업은 작업당 세 번 실행했습니다。 비용은 gateway 가 보고한 usage.cost 이며 중앙값을 표시했습니다。 작업은 일부러 단순하게 만들었으므로 통과율은 역량 벤치마크가 아니라 sanity 체크입니다。 측정하지 않은 역량 주장은 공개하지 않습니다。 거부 동작은 streaming 과 non-streaming 모드 양쪽에서 재현됐습니다。 수치는 prompt,리전,부하에 따라 달라집니다。

← 블로그로 돌아가기