Tool Calling의 쓴 교훈: JSON 호출 대신 코드로 도구를 부르면 어떨까
The Bitter Lesson of Tool Calling
TL;DR Highlight
도구를 JSON 대신 Python 코드로 불렀더니 14개 중 11개 모델이 같거나 더 나았다
Who Should Read
에이전트에서 여러 도구를 연쇄·병렬로 호출하다 턴 수와 호출 누락 문제를 겪는 백엔드 개발자
Core Mechanics
- 코드로 부르면 11/14 모델이 동률 이상
- Programmatic tool calling(PTC)은 도구를 타입 붙은 Python 스텁(stub)으로 노출하고 모델이 스크립트를 짜 호출하는 방식이다.
- BFCL v4 309개 항목 기준으로 JSON 호출 대비 11개 모델이 같거나 더 높았다.
- 세대가 문제였지 회사가 문제는 아니었다
- Claude 5개 모델과 최신 GPT-5.6 계열은 모두 동률 이상이었다.
- GPT-4o, GPT-4.1, GPT-5.4-mini는 줄바꿈이 \n 글자로 나와 문법 오류가 났다.
- 체인이 길수록 코드 방식이 유리했다
- 체인 길이 12 이상에서 JSON 호출보다 절대 18.8% 높았다.
- JSON은 링크마다 추론 턴이 한 번 더 필요해서 생기는 차이다.
- 병렬 호출이 많으면 JSON이 호출을 빠뜨렸다
- Claude Sonnet 5는 JSON 방식에서 N=70~72 근처부터 호출이 누락됐다.
- PTC는 N=100에서도 열거 정확도 100%였다.
- 스키마 128개를 쏟아도 PTC는 버텼다
- 컨텍스트에 엉뚱한 함수 스키마를 섞었을 때 JSON은 평균 2.3% 떨어지고 PTC는 5.5% 올랐다.
- 파일시스템 탐색 방식은 평균 32% 떨어졌다.
Evidence
- GPT-5.6이 가장 크게 올랐다
- GPT-5.6-Sol과 Terra는 자기 JSON 기준 대비 절대 10.6%p 올랐다.
- BFCL v4 309개 항목 기준이다.
- 구세대 GPT는 크게 떨어졌다
- GPT-4o, GPT-4.1, GPT-5.4-mini는 JSON 대비 절대 19.7~26.9%p 낮았다.
- GPT-4o는 81.9에서 55.0으로 내려갔다.
- 체인 실험에서 Sonnet 5가 80.8에서 96.2
- Claude Opus 4.8도 80.8에서 94.2로 올랐다.
- GPT-4.1은 98.1에서 40.4로 무너졌다(n=52).
- 병렬 실험에서 GPT-5가 71.9에서 96.9
- 14개 중 13개 모델이 동률 이상이었고 예외는 GPT-4.1(96.9에서 90.6)이었다.
- N=48에서 토큰은 JSON 5,097 대비 PTC 3,535였다.
How to Apply
- 오늘 프롬프트로 PTC 흉내 내 보기
- 도구 2~3개를 연쇄로 부르는 시나리오 하나를 골라 아래 프롬프트를 붙여넣어라.
- JSON 호출 결과와 정답·턴 수를 비교해라.
- 팬아웃이 큰 작업은 코드 실행으로 바꾸기
- 한 응답에서 도구를 수십 개 병렬 호출하는 작업을 찾아라.
- 스텁을 만들고 모델이 루프나 asyncio.gather로 부르게 한 뒤 서브프로세스로 실행해라.
- 모델별로 멀티라인 코드 생성부터 점검하기
- 쓰는 모델이 구세대라면 생성 코드에 \n 글자가 섞이는지 먼저 테스트해라.
- 문법 오류가 나면 해당 모델은 JSON 호출을 유지해라.
- 토큰 비용을 N별로 재 보기
- 시스템 프롬프트 고정 오버헤드 때문에 호출 수가 적으면 PTC가 더 비싸다.
- 우리 서비스 평균 호출 수로 JSON과 PTC 토큰을 비교해라.
Try It
# Claude나 ChatGPT 대화창에 붙여넣기 (논문 방법의 간이 버전: 실제 실행 없이 스크립트 생성만 확인)
너는 도구를 JSON이 아니라 Python 스크립트로 호출하는 에이전트다.
아래 타입이 붙은 스텁 함수만 import해서 쓸 수 있다.
```python
{{도구 함수 시그니처를 Python 스텁으로 붙여넣기}}
```
규칙:
- 필요한 호출을 하나의 Python 스크립트에 모두 작성한다.
- 서로 독립적인 호출은 루프나 asyncio.gather로 처리한다.
- 결과는 json.dumps로 print한다.
- 줄바꿈은 실제 개행으로 쓰고 \n 글자를 쓰지 않는다.
요청: {{사용자 요청}}
이어서 해 볼 것: 같은 요청을 JSON 함수 호출로도 돌려 호출 수, 정확도, 토큰을 비교해 보세요.Terminology
관련 논문
같은 시뮬레이션, 다른 근거: 도구 출력을 파일로 넘기면 LLM 에이전트 정확도가 어디서 깎이나
긴 툴 출력을 파일로 넘기자 GPT-5.1은 정확도 11.3%p 하락, 정식 출력 지정하니 회복
가짜 뉴스가 진짜 폭락을: LLM 트레이딩 에이전트 대상 정보 주입 공격
가짜 헤드라인 한 줄로 LLM 트레이딩 에이전트 62%를 조종했다(프롬프트 주입은 14%)
Harness Engineering 101: LLM은 뇌, harness는 몸
에이전트는 JSON 배열을 관리하는 루프이고, 16개 챕터로 직접 만들어 본다
Harness²: 에이전트 harness를 스스로 고쳐 쓰는 재귀 최적화 프레임워크
모델은 고정하고 harness를 재귀로 고쳤더니 벤치마크 점수가 최대 11.8%p 올랐다
해고된 Savannah 경찰관, ICE 요원 남편에게 Flock 계정 공유
경찰관이 Flock 계정을 남편(ICE 요원)에게 공유했고, 감사에서 983건 검색이 드러나 해고됐다
tmux와 Claude Code: 세션, send-keys, 그리고 한계선
tmux로 Claude Code 여러 개를 돌리면 편하지만 에이전트 4개쯤에서 한계가 온다
Hybrid Reasoning Agents: 잠재 공간에서 생각하고 텍스트로 행동하는 LLM 에이전트
잠재 공간 추론과 텍스트 도구 호출을 섞었더니 성능 10.4%↑, 토큰 최대 54.7%↓
Original Abstract (Expand)
Tool use transforms LLMs into agents that act beyond their training data, and for code-capable models, programmatic tool calling extends this further by replacing rigid JSON calls with scripts that chain and parallelize naturally. However, a systematic evaluation of tools as code on an established benchmark across current and prior model generations under real-world task conditions has not been conducted. In this work, we empirically compare programmatic tool calling (PTC) to native JSON tool calling across 14 language models on BFCL v4. In the programmatic tool calling paradigm, tools are exposed as typed Python stubs that the model invokes through code, with execution and results handled in a single agent turn. Programmatic tool calling matches or exceeds native JSON tool calling in 11 of 14 models on BFCL v4, with the GPT-5.6 family achieving a 10.6% improvement over the JSON tool calling baseline. Further, it matches or outperforms baseline in 13 of 14 models under parallel fan-out, and holds stable under context rot conditions where baseline degrades 2.3% on average. Our results demonstrate that programmatic tool calling is a viable and robust alternative to JSON tool calling, with performance tracking model capability across release generations.