
AI 에이전트의 비용 절감, 가장 위험한 것은 "모델을 낮추는 것"이었다 — 낮출 수 없는 역할에 대하여
요약
AI 에이전트 운용 비용을 절감하기 위해 모델을 혼합 사용하는 전략과 그 과정에서 발생하는 위험성을 다룹니다. 단순히 모델 성능을 낮추는 대신, 입력 데이터를 최적화하여 검증(Critic) 역할을 유지하면서도 비용을 줄이는 설계 방식을 제안합니다.
핵심 포인트
- 역할에 따라 상위 모델과 저렴한 모델을 구분하는 것은 기본 상식임
- 검증(Critic) 역할을 저렴한 모델로 대체할 경우 버그를 놓칠 위험이 큼
- 모델을 낮추는 대신 입력(Input) 데이터의 양을 줄이는 설계가 효과적임
- 검증 게이트를 단계별로 나누어 모델별 역할을 최적화해야 함
TL;DR
- X(구 Twitter)에서 "Fable 5는 비싸니까, 팀을 구성해 모델을 구분해서 사용하면 절약할 수 있다"라는 이야기가 돌았다. 내가 계속 해왔던 방식이었기에, 실제로 운용하며 알게 된 "그 뒷이야기"를 쓴다.
- "무거운 역할은 좋은 모델, 가벼운 작업은 저렴한 모델"은 맞다. 다만, 저렴한 모델로 낮출 수 없는 역할이 있다. 나의 경우 검증 역할(Critic)이었는데, 이 부분을 저렴하게 설정했더니 평범하게 버그를 놓쳐버렸다.
- 그래서 발상을 전환했다. 모델을 낮추는 것이 아니라, 전달하는 입력(Input) 자체를 줄이는 것이다. 검증 게이트를 3단계로 나누어, 저렴한 모델에게 테스트 출력을 처리하게 하고, 높은 모델에게는 코드만 읽게 한다.
- 잘 되지 않았던 안도 적는다. "git diff만 전달하기"는 신규 개발에서는 의미가 없었고, "작성자보다 한 단계 높은 모델로 리뷰하기"도 방법이 좋지 않았다.
- 마지막으로, 이 절약 설계 자체를 Fable 5 스스로에게 리뷰하게 한 이야기를 한다. 나의 초안은 그 Fable에 의해 허무하게 기각되었다.
토대가 되는 멀티 에이전트(Multi-agent) 기반 자체는 지난번에 썼으므로, 그것은 전제로 두고 넘어가겠다.
리포지토리: https://github.com/KoyanagiAyuha/team-framework
발단은 X의 포스트
계기는 이것.
Use Fable 5 as orchestrator and Opus + Codex to execute (to save fable usage):
Fable 5 (max reasoning) = orchestrator
Opus = deep reasoning subagent
Sonnet = mechanical work subagent
Codex = peer Sr. engineer, different perspective
— @diegocabezas01
이 뒤에 구체적인 절차(Fable을 메인으로 설정하고, opus와 sonnet 서브 에이전트를 만들고, Codex를 별도의 관점으로 추가하는...)가 이어지지만, 하고 싶은 말은 "역할에 따라 모델을 구분하여 Fable의 소비를 억제한다"는 한 점이다.
Claude Code에도 /model opusplan
(계획은 Opus, 실행은 Sonnet)이 처음부터 들어가 있을 정도로, "머리를 쓰는 곳은 상위 모델, 손만 움직이는 곳은 저렴한 모델"은 이제 당연한 상식이 되었다.
정리 기사에서는 "이것으로 4~9할 저렴해진다" 같은 숫자도 보인다.
그래서 나도 이전부터 멀티 에이전트 기반으로 같은 일을 하고 있었다.
"아, 이거 내 이야기네"라고 생각했다.
다만, 실제로 매일 돌리다 보면 이 정석만으로는 부족한 상황에 부딪힌다.
오늘은 그 이야기를 하겠다.
애초에 Fable이 비싸다
요금은 다음과 같다 (2026년 7월 기준, 입력/출력의 $ / 100만 토큰).
| 에일리어스 | 실체 | 입력 / 출력 |
|---|---|---|
sonnet | Claude Sonnet 5 | $3 / $15 [1] |
opus | Claude Opus 4.8 | $5 / $25 |
fable | Claude Fable 5 | $10 / $50 |
Fable은 사고(Reasoning)가 항상 켜져 있어, 리뷰나 디버깅, 계획 수립 등은 믿음직스럽다.
다만 출력 단가가 Opus의 2배다.
아무 생각 없이 모든 역할을 이것으로 돌리면 당연히 엄청난 속도로 돈이 녹아내린다.
참고로 나는 $100 구독형을 사용 중인데, 리뷰를 전부 Fable로 돌리던 시절에는 30분 만에 상한에 도달했다.
종량제라면 금액 문제, 구독형이라면 횟수 제한 문제다.
어느 쪽이든 "좋은 모델을 막무가내로 다 쓰는 것"은 지속할 수 없다.
그래서 현재 구성에서는 Fable을 사용하는 것을 무거운 판단이 필요한 부분(Planner의 분해와 Critic 게이트)으로만 한정하고 있다.
모든 역할이 아니라, 가장 머리를 써야 하는 곳에만.
이 전제를 바탕으로 다음을 읽어주길 바란다.
정석대로, 역할에 따라 모델을 나눈다
우리 팀은 역할을 인지 기능으로 정의하고 있으므로, 솔직하게 모델을 대입하면 다음과 같다.
| 역할 | 하는 일 | 모델 | 이유 |
|---|---|---|---|
| Orchestrator | 전체 총괄 (메인 세션) | 사람이 /model로 선택 | 가교 역할에 집중 |
| Planner | 무거운 분해 및 계획 | fable | 계획은 무거운 분해가 필요할 때만 수행. 사전에 재작업을 방지 |
| Worker | 스코프 내 구현 | sonnet | 대부분의 태스크는 Sonnet으로 충분. 복잡한 것만 opus |
| Critic | 결과물 검증 | fable | 판단 부하가 가장 큰 관문 |
Worker를 Sonnet 기본값으로 설정하는 것만으로도, 구현량에 비례하던 비용이 대폭 낮아졌다.
여기까지는 기사에서 읽은 내용과 같았으나, 문제는 그다음이었다.
Critic을 저렴한 모델로 낮췄더니, 놓쳐버렸다
처음에는 Critic도 Opus로 낮추려 했다.
가장 많이 호출되는 역할이고, 이곳을 저렴하게 만들 수 있다면 효과가 클 것이라고 생각했기 때문이다.
Opus의 Critic이 그냥 지나쳐버린 버그를, 완전히 동일한 코드를 Fable에게 리뷰하게 했더니 찾아냈다.
$n=1$인 사례이므로 맹신할 수는 없다.
하지만 방향성 측면에서는 납득이 간다.
깊이 있는 모델의 리뷰가 강력한 지점은, 코드를 읽으면서 "뭔가 걸린다"라고 깨닫는 순간이지, 사전에 체크리스트를 나열하는 단계가 아니다.
기존 코드와의 조화라든가, 암묵적으로 지켜지고 있는 전제가 무너지고 있다든가 하는, "말해주지 않으면 깨닫지 못하는" 것들 말이다.
즉, Critic을 저렴하게 만들면, 가장 잡아내길 바라는 버그부터 놓치게 된다.
이곳은 낮출 수 없다.
그렇게 되면 "무겁다는 건 알지만 Fable 상태로 유지하고 싶은 역할"이 남는다.
그리고 Fable 상태로 돌렸더니, 이번에는 토큰이 폭발했다.
무엇이 폭발했는가, 그리고 빗나간 두 가지 안
검증 게이트(Verification Gate)는 당초 이렇게 작동하고 있었다.
변경 파일을 전부 읽고(Read), 테스트나 컴파일러 등의 출력을 통째로 삼켜서 판정한다.
이것이 Fable의 컨텍스트(Context)를 직격했다.
줄이는 방법을 두 가지 시도해 보았으나, 둘 다 실패했다.
"git diff만 전달하기"는 신규 개발에서는 통하지 않는다
첫 번째 유력한 후보는 이것이었다.
전문이 아니라 git diff만 전달하면 가벼워질 것이라 생각했다.
기존의 큰 파일을 몇 줄 수정하는 정도라면, 차이분(diff)은 전문보다 훨씬 작을 것이다.
하지만 내 업무는 거의 신규 개발이었고, 새로 만든 파일은 git diff를 해도 모든 행이 +로 나온다.
즉, 차이분이 곧 전문이며, 아무것도 줄어들지 않는다.
신규 코드는 애초에 전부 읽지 않으면 리뷰할 수 없으므로, 읽어야 하는 양에 하한선이 존재한다.
diff 작전은 기존 코드 수정에는 효과적이지만, 내 케이스에는 효과가 없었다.
"작성자보다 한 단계 높은 모델로 리뷰"도 논리가 맞지 않는다
다음에 생각한 것은 Sonnet이 쓰면 Opus가, Opus가 쓰면 Fable이 리뷰하는 식으로 작성자보다 한 단계 높은 모델에게 리뷰를 맡기는 안이었다.
깔끔해 보였다.
하지만 방금 전의 버그 건을 떠올리면 논리가 무너진다.
그것은 "완성된 코드를 Opus와 Fable에게 읽혀서 비교한" 이야기였으며, 누가 썼는지는 관계없이 리뷰어 단독의 실력 차이였다.
따라서 "작성자의 난이도에 따라 리뷰어를 결정하는 것"은 축이 어긋나 있다.
게다가 작성자는 대부분 Sonnet이므로, 한 단계 위인 Opus 리뷰가 다수가 된다.
Opus는 버그를 놓친 실적이 있는데, 그것을 주력으로 삼게 되는 셈이다.
그래서 작성자 기준은 포기했다.
향후 리뷰 모델을 배분하더라도, 기준은 작성자가 아니라 "로직의 밀도 $ imes$ 고장 났을 때의 피해"가 될 것이다.
파서(Parser)나 인증, 정합성 같은 급소는 상위 모델, 설정이나 보일러플레이트(Boilerplate)는 저렴한 모델.
이 부분은 이번에는 도입하지 않았지만, 머릿속 한구석에 담아두고 있다.
결국, 모델이 아니라 입력(Input) 쪽을 나누었다
막다른 길에서, 애초에 무엇이 무거운 것인지 다시 생각했다.
폭발하고 있었던 것이 정말 코드인가? 아무래도 아닌 것 같다.
빌드가 실패하면 컴파일러의 연쇄 에러나 스택 트레이스(Stack Trace)가 끝없이 나와서, 코드의 몇 배나 되는 분량이 된다.
그리고 이 출력을 읽는 데 Fable의 지능은 필요 없다.
솔직히 말하자면, 이 "출력이 코드의 몇 배"라는 수치는 설계 상담에서 들은 견적이지, 나의 실측치는 아니다.
사실 폭발한 1개 세션의 내역(읽은 양 vs 테스트 출력의 양)을 계산하여 주된 원인을 확인해야 하는데, 그 부분은 아직 숙제로 남아 있다.
따라서 이 3단계 구조도 "효과가 있을 것"이라는 설계 단계이며, 얼마나 줄었는지에 대한 수치는 이제부터 측정할 단계다.
판단이 필요 없는 무거운 입력(Raw Log)은 저렴한 모델에게 요약하게 하고, 판단이 필요한 코드만을 Fable에게 읽게 한다.
이를 위해 게이트를 3단계로 나누었다.
Stage1 Worker (Sonnet / 복잡한 것만 Opus)
구현함
Stage2 수집역 (Sonnet ・ 판단은 하지 않음) ← 절약의 핵심
...
코드를 읽는 공정만큼은 Fable에게 남겨둔다.
이 부분을 떼어내면 처음의 "놓치는 (見逃す)" 문제가 다시 발생하므로, 깎아낼 수 없다.
깎아내는 것은 생 로그 (Raw Log) 쪽이다.
로그를 압축하는 것은 판단이 필요 없는 단순 작업이므로, Sonnet으로도 충분하다.
한 가지 주의하고 있는 점은, exit code는 생 값 그대로 통과시키는 것이다.
수치는 요약으로 속일 수 없으므로, Sonnet이 "대략 성공"과 같이 뭉뚱그려 버리는 사고를 방지할 수 있다.
또한 입도 (Granularity)에 따른 배압 (Backpressure)도 도입했다.
1개 태스크의 신규·변경 행이 기준치인 600행을 초과하면, Fable을 호출하기 전에 "이것은 너무 크니까 분할해"라고 앞단에서 돌려보낸다.
읽는 양은 아무리 노력해도 입도(Granularity)를 조절하는 방법밖에 없으므로, 거대한 덩어리는 계획 단계로 되돌린다.
일반화하면 다음과 같다
이번 과정을 통해 정리할 수 있었던 것은 대략 다음과 같다.
모델을 낮추기 전에 "낮추면 무엇을 잃게 되는가"를 확인한다.
Worker는 낮춰도 괜찮았지만, Critic은 낮추면 놓치게 되었다.
역할에 따라 답이 다르다는 것을 실감했다.
낮출 수 없는 역할에는 다른 방식의 절약법이 있다.
테스트 실행이나 로그 정렬처럼 판단이 필요 없는 부분을 저렴한 모델로 분리하고, 높은 모델에는 판단에 필요한 것만 전달한다.
생 빌드 로그를 최상위 모델에 직접 흘려보내지 않는 것은 꽤 효과적일 것이다.
로그는 코드보다 긴 경우가 많기 때문이다.
그럼에도 남는 "코드 그 자체"의 양은, 태스크를 작게 나누는 수밖에 없다.
이 부분은 자세히 쓰여 있지 않지만, 모델을 할당하는 것보다 "무엇을 전달할 것인가"를 다듬는 것이 실제로는 더 효과가 있다는 체감이 든다.
결론: 이 절약 설계를 Fable 스스로에게 리뷰하게 했다
가장 쓰고 싶었던 부분은 여기다.
이 일련의 설계를 당사자인 Fable에게 리뷰하게 했다.
먼저 설계 상담.
처음에 가져간 안은 "Fable이 검증 플랜을 만들고, 저렴한 모델이 실제로 검증하며, Fable이 마지막에 판정한다"라는 또 다른 3단계 안이었다.
이 안은 기각되었다.
기각된 이유를 요약하면 다음과 같다.
Opus가 수집한 "증거"에는 Opus가 놓친 버그의 흔적이 애초에 찍혀 있지 않다. 따라서 마지막에 Fable이 그 증거를 보더라도, 결함이 찍히지 않은 자료를 보고 "합격"을 내릴 뿐이다. 지키고 싶었던 Fable의 강점을 구조 자체에서 죽이고 있는 것이다.
이때 Fable이 대신 제안한 것이 "diff만 전달하는 2단계", 즉 이 글의 막다른 길 ①이었다.
그런데 며칠 뒤 "나는 신규 개발이 중심이다"라고 전하며 다시 상담하자, Fable은 자신의 그 안을 철회했다.
신규 파일은 diff가 거의 전체 내용이므로 절약이 되지 않는다는 이유였다.
전제가 바뀌면 최상위 모델이라도 이전의 말을 철회한다.
Fable에게 물으면 정답이 나오는 것은 아니다.
두 번째 대화에서 겨우 "코드를 읽는 공정은 Fable에게 남기고, 깎아내는 것은 생 로그"로 결론이 났다.
구현이 끝난 후에는, 똑같은 Fable에게 검증 게이트 역할로서 적대적으로 리뷰하게 했다.
판정은 REQUEST_CHANGES.
문서에서 약속한 동작이 일부 구현되지 않았다는 등의 놓친 부분을 4건 지적받았고, 전부 수정했다.
모두 예외적인 상황에서만 발생하는 것들이라, 평범하게 작동시키는 것만으로는 절대 찾아낼 수 없었을 내용들이다.
마지막으로 실제 파이프라인을 딱 한 번 실행하여, Worker(격리) → 수집역 → Critic의 전달이 통과하는 것을 확인했다.
결국 한 일은, Fable을 요충지에만 배치하는 것이었다.
그 한 줄에 도달하기 위해 꽤나 멀리 돌아왔다.
요약
- "모델을 계층화하여 저렴하게"는 옳다. Worker를 저렴한 모델로 만드는 것만으로도 효과가 있다.
- 다만 낮추면 망가지는 역할이 있다. 나의 경우 Critic이다. 그 부분은 모델이 아니라 입력을 계층화하여, 저렴한 모델에게 생 로그를 압축하게 하고, 높은 모델에게는 코드와 최소한의 증거만 전달한다.
- "어떤 모델을 적용할 것인가"의 한 단계 아래에는 "무엇을 얼마나 전달할 것인가"가 있다.
- 이 3단계화는 아직 설계를 통과한 단계일 뿐이며, 얼마나 절약되었는지는 측정하지 않았다. 수치가 나오면 추가하겠다.
- 그리고 그 절약 설계를 최상위 모델 스스로에게 리뷰하게 했더니, 예외 케이스의 허점까지 드러났다. 높은 모델은 사용처를 좁히면 충분히 제값을 한다.
리포지토리: https://github.com/KoyanagiAyuha/team-framework
Sonnet 5는 도입 가격 $2/$10가 2026-08-31까지입니다. 최신 정보는 공식 사이트에서 확인하세요. ↩︎
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기