Tool calling 이 어떤 모델의 built-in feature 가 되기 한참 전에, 사람들은 이미 LLM 을 방에서 꺼내려고 발버둥치고 있었어. 옛날 workaround 를 알아두는 게 가치 있는 이유는 두 가지: (a) 옛날 코드에 아직 살아있고, (b) 오늘날의 깔끔한 API 가 왜 그렇게 안도감 주는지를 설명해주거든.
첫 번째 family 는 prompt-and-parse 였어: 모델한테 구조화된 문자열 — JSON, XML, 특별한 <action> 태그 — 를 토해내라고 하고, 그 출력에 regex 를 돌려서 'function 호출하고 싶다' 를 detect 해. 신뢰성 스토리는 비참했어. 모델은 중간에 format 을 까먹고, JSON 을 수다스러운 서론으로 감싸고, 따옴표 스타일 바꾸고, 필드를 hallucinate 했어. 모든 팀이 자기들만의 retry-and-repair loop 를 짰고, 모든 팀의 loop 가 코너 케이스를 흘렸어.
두 번째 family 는 ReAct 식 scaffolding 이었어: 모델한테 Thought / Action / Observation 라인을 번갈아 출력하라고 하고, stream 에서 Action 만 뽑아 실행하고, Observation 을 다시 집어넣어. ReAct 는 진짜 지적 도약이었어 — 추론과 행동이 sequential 하지 않고 interleaved 라는 걸 가르쳐줬거든 — 근데 engineering substrate 로는 종이처럼 얇았어. 모델은 여전히 모든 step 을 완벽하게 format 해야 했고, parser 는 시(詩) 에 대해 방어적이어야 했어.
세 번째 family 는 본격 agent framework: LangChain agents, AutoGPT, BabyAGI. Prompt-and-parse loop 를 OOP 기계장치로 감싸고, planner · memory · self-critique 를 얹었어. 동작할 땐 동작했어. 안 동작할 땐 화려하고 디버깅 불가능한 방식으로 실패했어 — 모든 layer 가 여전히 똑같이 부서지기 쉬운 '모델아 제발 format 좀 해줘' 토대 위에 쌓고 있었거든.
이 모든 것 안에 숨어있는 교훈이 — 우리가 곧 공부할 모든 protocol 의 교훈이야: contract 는 prose 아래에 살아야 해. Tool 호출이 영어 답변의 일부로 모델이 타이핑해주는 거인 한, 너는 모델의 기분에 도박하는 거야. Breakthrough 는 tool 호출을 API 자체의 first-class output 으로 만든 거야 — 모델이 적는 텍스트가 아니라, inference engine 이 토해내는 구조화된 필드.