에이전트를 위한 Claude Fable 5: 도구 호출 거부, 비용 대 GLM 5.2 비교
요약
Claude Fable 5를 에이전트에 적용할 때 발생하는 도구 호출(tool-call) 중 거부(refusal) 현상과 그 위험성을 분석합니다. 중단 사유를 확인하지 않을 경우 불완전한 데이터가 생성되어 워크스페이스가 손상될 수 있음을 경고하며, 비용 및 성능 비교 데이터를 제공합니다.
핵심 포인트
- Claude Fable 5는 도구 호출 중 'refusal'로 인해 인자가 잘리는 현상이 발생함
- 에이전트 루프 설계 시 반드시 stop_reason을 확인하여 데이터 손상을 방지해야 함
- Fable 5의 사고(thinking) 제어는 output_config.effort를 통해 수행됨
- GLM 5.2 대비 코딩 작업 비용이 약 15배 높으나 작업 유형에 따라 차이가 있음
우리의 평가에서 Claude Fable 5는 설정 기본값 수정과 같이 평범한 작업임에도 불구하고 44번의 코딩 에이전트(coding-agent) 턴 중 11번에서 도구 호출(tool-call) 도중 거부했습니다. 이 거부는 도구 인자(tool arguments)를 생성하는 도중에 stop_reason: "refusal"로 나타나며, 잘린 인자들은 여전히 유효한 JSON으로 파싱됩니다. 따라서 중단 사유(stop reason)를 확인하지 않고 도구 호출을 실행하는 에이전트 루프(agent loop)는 미완성된 파일을 디스크에 그대로 작성하게 됩니다. Fable 5를 에이전트에 적용할 때 엔지니어링 측에서 가장 먼저 고려해야 할 점은 가격이 아니라 바로 이러한 동작입니다.
요약 (TL;DR)
- Claude Fable 5는 평범한 에이전트 작업(설정 기본값 수정, 회의실 예약 등) 중 도구 호출 도중에
stop_reason: "refusal"을 반환했습니다. 잘린write_file인자가 여전히 파싱되었기 때문에, 중단 사유를 확인하지 않는 루프는 절반만 작성된 파일을 실행하게 됩니다. - Fable 5의 사고(thinking)는 적응형이며 끌 수 있는 스위치가 없습니다:
enabled와disabled모두 거부되며, 제어 방식은output_config.effort입니다. - Fable 5의 비용 프리미엄은 작업 형태에 따라 다릅니다: 4턴 코딩 작업의 경우 $0.045가 소요되어 glm-5.2의 $0.003 대비 15배였으나, 워밍 배치(warm batch) 작업에서는 sonnet-5 대비 5배에 불과했습니다.
- Fable 5는 30일간의 데이터 보유(data retention)가 필요합니다.
아래의 모든 수치는 2026-07-05에 Synthorai 게이트웨이를 통해 소규모 시나리오 하네스(scenario harness)로 측정되었습니다. 다섯 가지 에이전트 워크로드 형태(도구를 사용하는 코딩 루프, RAG 질의응답, 도구 중심 오케스트레이션, 배치 분류, 15턴 대화)를 대상으로 claude-fable-5, claude-opus-4-8, claude-sonnet-5, glm-5.2에 대해 실행하였으며, 변동성이 중요한 점을 고려하여 작업당 3회씩 실행했습니다. 작업들은 의도적으로 사소하게 설정되었습니다. 통과율(pass rates)은 능력 벤치마크가 아닌 정상 작동 여부를 확인하는 검증 단계입니다. 비용은 게이트웨이에서 청구된 usage.cost 기준입니다.
도구 호출 실행 전 stop_reason 확인하기
이것은 문서에서 경고하지 않는 실패 사례이며, 상태(state)를 손상시킵니다. 에이전트가 app.py를 읽고 수정을 결정한 뒤 write_file 호출을 내보내기 시작합니다. 파일 내용이 생성되는 도중에 스트림이 중단됩니다:
{
"stop_reason": "refusal",
"content": [{
...
input 객체는 완전하고 파싱 가능한 JSON입니다. 그 어디에도 "조기에 중단되었다"는 내용은 없습니다. 만약 당신의 루프(loop) 계약이 "도구 호출(tool calls)을 받으면 실행하라"는 것이라면, 당신은 단지 38자짜리 파편(fragment)으로 app.py를 덮어쓴 셈입니다. 이 파편은 딕셔너리 중간에서 끊겨 더 이상 파이썬(Python)으로 파싱되지 않으며, 다음 턴 역시 거부(refusal)로 이어지므로 루프는 워크스페이스가 손상된 채 종료됩니다.
데이터를 통해 말할 수 있는 세 가지 사실은 다음과 같습니다:
- 일상적인 작업에서도 트리거됩니다. 거부를 유발한 작업들은 설정 조회(config lookup) 시의
KeyError수정, 슬러그화(slugify) 함수 구현, 회의실 예약, 그리고 송장 초안 생성과 같은 것들이었습니다. 이중 용도(dual-use)나 민감한 내용은 전혀 없었습니다. - 무작위가 아니라 반복적입니다. 한 코딩 작업은 스트리밍(streaming) 방식과 비스트리밍(non-streaming) 방식 모두에서 세 번의 실행 모두 거부를 유발했습니다. 반면 다른 작업들은 한 번도 거부를 유발하지 않았습니다. 여러 조건에 걸쳐, 사소한 코딩 에피소드의 58-75%가 Fable 5에서 통과된 반면, claude-opus-4-8, claude-sonnet-5, 그리고 glm-5.2는 100% 통과되었습니다. 또한 모든 실패는 잘못된 코드가 아니라 거부(refusal)에서 기인했습니다.
- 대화에 한 번 거부가 포함되면, 해당 에피소드는 종료됩니다. 후속 턴들은 빈 출력과 함께
stop_reason: "refusal"을 반환했습니다. 동일한 컨텍스트 내에서 재시도해도 복구되지 않았습니다.
트리거는 작업 내용이 아니며, 데이터는 이를 명확히 보여줍니다. 매 실행마다 거부된 작업은 설정 딕셔너리 내의 9줄짜리 KeyError 수정이었으며, 자격 증명(credentials)이나 익스플로잇(exploits)은 없었습니다. 반면, 배치(batch) 시나리오에서는 암호화폐 채굴, 유출된 Stripe 키, 피싱 페이지에 관한 지원 티켓을 단 한 번의 거부 없이 분류해냈고, RAG 시나리오에서는 AES-256-GCM 비밀 정보와 침해 대응 절차로 가득 찬 문서들에 대해 답변하면서도 깨끗했습니다. 모든 거부는 멀티 턴(multi-turn) 도구 실행 시나리오 두 곳에서 발생했습니다. 세 가지 싱글 샷(single-shot) 시나리오는 더 무거운 콘텐츠를 포함했음에도 단 한 번도 거부하지 않았습니다. 패턴은 단어가 아니라 에이전트 루프(agent-loop)의 형태이며, 이는 입력값을 정화(sanitizing)한다고 해서 이를 방지할 수 없음을 의미합니다.
해결책은 도구 실행(tool-execution) 단계 직전에 한 줄을 추가하는 것입니다:
if response.stop_reason == "refusal":
# 이번 턴의 도구 호출(tool calls)을 실행하지 마십시오: 인자(arguments)가 잘려 있을 수 있습니다.
raise AgentInterrupted("model refused; restart episode or escalate")
Anthropic은 그 메커니즘을 문서화하고 있습니다: 출력이 반환되기 전에 발생하는 거부(refusal)는 빈 content 배열을 반환하며 비용이 청구되지 않습니다. 스트림 중간에 발생하는 거부(mid-stream refusal)는 이미 스트리밍된 출력에 대해 비용이 청구되며, 가이드는 해당 부분(partial)을 폐기하는 것입니다. 또한 응답에는 카테고리(예: cyber 또는 bio, 혹은 null)를 포함하는 stop_details 객체가 포함되어 있어, 분류기 차단(classifier blocks)과 일반적인 거절을 구분할 수 있습니다. 하지만 문서에서 명시하지 않은 점은 우리가 위에서 겪은 도구 사용(tool use)과의 상호작용입니다: 거부가 인자 생성(argument generation) 도중에 발생할 수 있으며, 이때 부분적인 인자(partial arguments)는 완전한 인자와 구별할 수 없습니다.
공식적인 복구 경로(recovery path)도 존재합니다. Claude API에서는 베타 기능인 fallbacks 파라미터(betas: ["server-side-fallback-2026-06-01"], fallbacks: [{"model": "claude-opus-4-8"}])를 통해, 동일한 호출 내에서 거절된 요청을 폴백 모델(fallback model)로 다시 실행할 수 있습니다. 이때 거절이 출력 전에 발생했다면 해당 거절 자체에 대한 비용은 청구되지 않습니다. 이 기능은 Amazon Bedrock, Vertex AI 또는 Microsoft Foundry에서는 사용할 수 없으며, 해당 플랫폼의 SDK는 클라이언트 측 폴백 미들웨어(client-side fallback middleware)를 제공합니다. 어떤 경로를 적용하든, 위의 가드(guard)가 여전히 최우선입니다: 중단 사유(stop reason)가 거부(refusal)인 턴의 도구 호출은 절대 실행하지 마십시오.
다섯 가지 에이전트 형태의 비용
완료된 단위(태스크, 쿼리, 항목 또는 대화)당 중앙값 비용, 동일한 프롬프트, 동일한 날짜 기준:
| 시나리오 | fable-5 | opus-4-8 | sonnet-5 | glm-5.2 |
|---|---|---|---|---|
| 코딩 루프 (태스크당, 4턴 중앙값) | $0.045 | $0.012 | $0.0059 | $0.0031 |
| ... | ||||
| 해당 표에서 단일 셀의 값보다 더 중요한 두 가지 해석은 다음과 같습니다: |
- 가장 저렴한 모델은 형태(shape)에 따라 달라집니다. glm-5.2는 루프(loops)와 긴 대화(long conversation)에서 승리하지만, claude-sonnet-5는 세트 내에서 가장 저렴한 배치 분류기(batch classifier)입니다. 이는 scaffold 프롬프트가 예열(warm)된 후 도입 가격(introductory price)이 97%의 캐시 읽기(cache-read) 점유율에 기반하기 때문입니다.
- Fable 5의 프리미엄 또한 형태에 따라 달라집니다: 코딩 루프(coding loop)에서는 glm-5.2의 15배, 대화(conversation)에서는 11배이지만, 캐싱이 프롬프트의 대부분을 흡수하는 예열된 배치 항목(warm batch items)에서는 sonnet-5의 5배에 불과합니다.
비용 구조의 나머지 부분은 이러한 수치들을 제어하는 것과, 그 수치들을 다시 조용히 끌어올리는 두 가지 요소에 관한 것입니다.
에이전트 비용 절감하기
캐싱(Caching)은 가장 큰 단일 레버(lever)이며, Fable 5에서 그 계약 조건은 변경되지 않았습니다. 에이전트 데이터는 그 가치를 보여줍니다: cache_control 마커를 제거했을 때, 동일한 코딩 작업의 비용은 2.0배 더 많이 들었고, 예열된 배치 항목은 6.8배 더 많이 들었습니다. opus-4-8의 경우 동일한 제거 실험(ablation) 결과 3.8배 및 6.9배로 나타났습니다. 루프 내에서 슬라이딩 마커(sliding-marker) 패턴은 단순한 최적화가 아니라, 실행 가능한 청구서와 그렇지 않은 것 사이의 차이를 만듭니다.
프롬프트 순서(Prompt order)는 두 번째 레버이며, 우리가 테스트한 모든 모델에서 일관되게 유지되었습니다. 쿼리별 컨텍스트(per-query context) 뒤가 아닌 그 앞에 안정적인 규칙(stable rules)을 배치함으로써, 네 가지 모델 모두에서 RAG 쿼리 비용을 26-37% 절감할 수 있었습니다. Claude 라인의 경우, 순서가 잘못되면 매 호출마다 1.25배의 캐시 쓰기(cache-write) 프리미엄을 추가로 지불해야 합니다. 구체적인 메커니즘은 LangChain 캐싱 포스트에 설명되어 있으며, 여기의 수치들은 이 원리가 Fable 5에도 변함없이 적용됨을 확인해 줄 뿐입니다.
Fable 5는 또한 자체적인 두 가지 레버(levers)를 추가했습니다. 첫 번째는 캐시 적격성 하한선(cache-eligibility floor)이 2,048 토큰으로 낮아졌다는 점이며, 이는 Opus 4.8의 4,096 토큰의 절반 수준입니다. 에이전트의 비용 절감이 어디에서 오는지 기억한다면 이는 단순한 잡학 지식처럼 들리지 않을 것입니다. 즉, 반복되는 스캐폴드(scaffold)(시스템 프롬프트, 도구 정의, 슬라이딩 대화 접두사)가 캐싱되는 대상이며, 이는 오직 하한선을 넘었을 때만 가능합니다. 턴당 접두사(prefix)가 2,048에서 4,096 토큰 사이에 머물렀던 도구 중심(tool-heavy) 에이전트는 Opus 4.8에서 캐싱을 전혀 받지 못했지만, Fable 5에서는 캐싱을 시작하여 전체 가격의 접두사를 이후 모든 턴에서 약 10% 가격의 캐시 읽기(cache read)로 전환합니다. 이는 반대의 경우에도 적용됩니다. 이전의 4,096 하한선을 넘기 위해 채워 넣었던 접두사는 이제 불필요한 무게(dead weight)를 실어 나르고 있을 수 있습니다. 추측하기보다는 실제 응답에서 cache_read_input_tokens를 읽으십시오. Fable 5에서는 할인이 더 일찍 시작되기 때문입니다.
두 번째는 태스크 예산(task budgets) (베타 버전, 헤더 task-budgets-2026-03-13)입니다. 이는 이 비교 분석에서 계속해서 드러나는 바로 그 문제, 즉 Fable 5 루프가 청구 금액을 빠르게 높이며 max_tokens가 도움이 되지 않는 문제를 해결합니다. max_tokens는 모델이 볼 수 없는 응답당 하드 캡(hard cap)이기에, 모델은 무제한의 공간이 있는 것처럼 계획하다가 사고 중간에 끊겨 버립니다. 태스크 예산은 다릅니다. 루프에 토큰 상한선(최소 20,000)을 부여하면 모델은 이를 진행 중인 카운트다운으로 인식하여 스스로 속도를 조절하며, 중간에 잘리는 대신 우아하게 마무리합니다. 이는 매 요청마다 다시 보내는 전체 히스토리가 아니라, 모델이 생성한 것과 해당 턴에서 읽은 도구 결과(tool results)를 계산합니다. 코딩 루프 턴 비용이 glm-5.2의 15배인 모델의 경우, 모델이 스스로 조절하는 예산은 장착할 수 있는 가장 저렴한 가드레일(guardrail)입니다.
문서에서 지적하지 않을 두 가지 비용 놀라움
레버가 설정되었음에도 불구하고, 문서에서 경고하지 않는 방향으로 우리의 청구 금액을 움직인 두 가지 작은 요소들이 여전히 남아 있습니다.
"Low" 노력(effort) 설정이 더 저렴하지는 않았습니다. Fable 5의 사고 깊이(thinking depth)는 output_config.effort에 의해 제어되며, 직관적으로는 low가 비용이 적게 들 것이라고 생각하기 쉽습니다. 하지만 그렇지 않았습니다. effort: "low"를 설정했을 때 우리의 코딩 루프(coding loop) 비용은 작업당 $0.0478로, 기본값인 $0.0451보다 높았으며, 출력 토큰(output tokens) 또한 더 적지 않고 더 많았습니다. effort 이름이 토큰 수를 반영하지 않는 GLM 5.2에서도 동일한 패턴을 확인했습니다. 두 모델 라인 모두에서, "low"가 "적음"을 의미한다고 가정하기 전에 자신의 워크로드(workload)에 대해 직접 조절 장치(knob)를 측정해 보십시오. 수치를 예측하기 어려운 한 가지 이유는 적응형 사고(adaptive thinking)가 차지하는 출력 토큰의 비중이 동일한 모델, 동일한 날에 코딩 루프에서는 2%였으나, RAG 답변에서는 30%, 배치 분류(batch classification)에서는 52%까지 급격히 변동했기 때문입니다. 모델당이 아니라 워크로드 형태에 따라 출력 토큰 예산을 책정하십시오.
reasoning_content를 절대 재전송(replay)하지 마십시오. OpenAI 호환 모델에서 추론(reasoning) 필드는 대화 기록(conversation history)이 아닙니다. DeepSeek의 API는 이를 제거할 것을 요구합니다. GLM 5.2에서는 이를 재전송하는 것이 허용되지만 비용이 청구됩니다. 이를 메시지 기록에 다시 입력했을 때, 우리가 이를 제거하기 전까지 GLM 루프 비용이 약 28% 상승했습니다. Anthropic 자체의 사고 블록(thinking blocks)은 다릅니다. 동일한 모델에서는 이를 변경 없이 재전송해야 하지만, Fable 5의 사고 블록이 다른 모델로 라우팅되는 경우(예: Opus로의 폴백(fallback) 시)에는 프롬프트에서 자동으로 제외되며 비용이 청구되지 않으므로 제거할 것이 없습니다.
요청 인터페이스(request surface)에서 변경된 사항
Fable 5는 요청 인터페이스의 대부분을 Opus 4.7/4.8 및 Sonnet 5와 공유합니다. 문서에 따르면 사라진 기능은 다음과 같습니다:
thinking: {type: "enabled", budget_tokens: N}은 400 에러를 반환합니다. 토큰 예산(token budget)을 사용하는 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-message prefills, 마지막에
assistant턴을 추가하는 것)은 400 에러를 반환합니다.
temperature/top_p/top_k 및 프리필(prefill) 제거는 포팅된 요청에서 가장 자주 문제를 일으키는 두 가지 요소입니다. 사고(thinking) 및 데이터 보존(retention) 변경 사항은 위에서 설명하였으며, retention 포스트에서도 다루었습니다.
핵심 요약 (Bottom line)
에이전트 환경에서 Fable 5를 사용하는 것은 예산 문제이기 이전에 엔지니어링 문제입니다. 도구 호출(tool calls)을 실행하기 전에 stop_reason: "refusal"을 처리하십시오. 그렇지 않으면 설정 수정과 같이 단순한 작업에서도 잘린 쓰기(truncated write)로 인해 상태(state)가 손상될 수 있습니다. 그다음 비용은 직접 조절할 수 있는 요소로 취급하십시오. 캐싱(caching)이 가장 큰 레버리지이며, 자격 기준 하한선(eligibility floor)이 이제 2,048 토큰이므로 접두사(prefix)를 다시 확인하십시오. 작업 예산(task budget)을 설정하면 루프가 이번 비교에서 가장 높은 턴당 비용을 발생시키며 계속 실행되는 것을 방지할 수 있습니다. 또한 effort: "low"는 그 이름이 암시하는 것만큼의 할인을 제공하지 않습니다. 워크로드 형태에 따라 예산을 편성하십시오. 동일한 모델이 코딩 루프에서는 glm-5.2보다 15배 비싸고, 워밍 배치(warm batch) 작업에서는 sonnet-5보다 5배 비쌉니다. 이 내용이 사용하라는 뜻도, 사용하지 말라는 뜻도 아닙니다. 다만 기본 설정은 중립적이지 않으며, 비용과 실패 모드(failure modes) 모두 에이전트가 어떻게 설계되었는지에 따라 달라진다는 것을 의미합니다.
FAQ
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기