100줄의 Lisp로 구현하는 AI 에이전트
현대의 복잡한 AI 에이전트 프레임워크를 벗어던지면, 에이전트의 본질은 단순히 LLM 모델을 호출하고 도구를 실행하는 '재귀 함수'에 불과합니다. 개발자는 오랜 역사를 가진 Lisp 언어의 동질성(Homoiconicity, 코드가 곧 데이터)을 활용하여 단 100줄의 코드로 복잡한 프레임크 없이 완벽하게 작동하는 에이전트를 구현할 수 있음을 증명합니다. 이는 에이전트 개발의 실질적인 진입 장벽이 얼마나 낮은지를 보여주는 중요한 통찰입니다.
2000년경, 저는 구엘프 대학교(University of Guelph)에서 AI 강의를 수강했습니다. 제가 많은 것을 배웠다고는 생각하지 않습니다. 기억하는 한, 우리는 신경망(Neural Networks)에 대해 다루지 않았습니다. 제 학기 말 프로젝트는 아마도 AI 탈을 쓴 길 찾기 알고리즘이었을 겁니다. 트랜스포머(Transformers)에 대한 논의는 당연히 없었습니다. CUDA도, PyTorch도 없었습니다. 그런 것들은 존재하지도 않았으니까요. 하지만 제가 기억하는 것은 어두운 구엘프 대학교 CIS 실에서 Lisp로 코딩을 정말 많이 했다는 것입니다. 저는 평생 이름도 기억할 수 없는 당시 교수님께서 그것을 "AI를 위한 언어"라고 불렀고, 당시에는 그것이 상식이었을 수도 있습니다 - 확실치 않습니다. 하지만 저는 실제로 Lisp 코드를 작성하는 것을 즐겼습니다. 저에게 이 우아한 재귀 함수들을 구축하는 것은 일종의 예술이었습니다. 저는 그런 느낌을 주는 다른 컴퓨터 언어를 알지 못합니다 (아마 매우 우스꽝스럽겠지만, 초우아한 재귀로 XML 변환을 만드는 것을 정말 좋아했던 극소수의 사람 중 한 명인 제가 좋아했던 XML 스타일시트는 예외입니다).
교수님에 따르면, Lisp는 구체적으로 기호 AI(Symbolic AI)의 언어였습니다: 전문가 시스템, 정리 증명기, 기호와 규칙을 조작하는 프로그램들 말입니다. 하지만 결국 통계적 방법이 승리했고, 딥러닝이 그 승자를 묻어버렸으며, 저는 Lisp가 궁극적으로 기호 AI와 함께 잊혀졌다고 생각합니다. 적어도 폴 그레이엄(Paul Graham)이 자신의 첫 전자상거래 플랫폼을 작성하는 것에 대한 에세이 중 하나에서 사용했다고 언급한 것을 기억하는 것 외에는, 저는 그것을 정기적으로 사용하는 사람을 거의 (아예) 모릅니다.
이제 저희는 제가 그 AI 과정을 수강하고 배웠다고 기억하는 단 한 가지, Lisp를 떠난 지 25년 이상이 지났습니다. 그리고 그동안 저는 한 달 넘게 AI 에이전트 플랫폼을 구축하는 데 매몰되어 있었고, 오늘 아침 제 뇌간 밑바닥을 잡아당기는 작은 생각이 떠올랐습니다. "Lisp가 실제로 에이전트 루프에 유용한 언어가 될 수 있을까?" 그리고 저는 제가 해야 할 일에서 주의를 돌려 그저 확인해 보기 위해 Claude와 함께 작업하기 시작했습니다...
에이전트는 재귀 함수입니다
Claude Code, OpenClaw 또는 다른 AI 에이전트 도구들의 힘에 속지 마세요. 프레임워크를 걷어내면 에이전트 루프는 믿을 수 없을 정도로 단순합니다.
메시지 목록이 있습니다. 이를 모델로 보냅니다. 모델은 단어로 대답하거나 도구 사용을 요청합니다. 요청하면 도구를 실행하고, 결과를 추가한 다음, 다시 반복합니다. 일부 에이전트는 이를 상태(state)를 가진 while 루프로 구현할 수 있습니다. 하지만 아마도 기저 상태(Base case)를 가진 재귀로 구현하는 것이 실제로 더 나을 것입니다.
저는 Lisp 구문에 전혀 깊이 들어가지 않을 것입니다. 만약 여러분이 Lisp로 코딩해 본 적이 없다면 이것은 꽤 이상하게 보일 것이지만, 여기 Lisp로 작성된 에이전트 루프가 있습니다:
(defun agent-loop (messages) ( let* ((message (ref (call-model messages) "choices" 0 "message" )) (tool-calls ( gethash "tool_calls" message))) ( if (and tool-calls ( plusp ( length tool-calls))) (agent-loop ( append messages ( list message) ( map 'list #' execute tool-calls))) ( append messages ( list message)))))
농담이 아니라 전체 에이전트는 고작 8줄의 Common Lisp입니다.
기저 상태: 모델이 답변하고 기록을 반환합니다. 재귀 상태: 도구를 원하고, 실행하고, 강화된 메시지 목록으로 재귀합니다. 프레임워크도 없습니다. 상태 머신도 없습니다. 에이전트의 상태는 재귀를 통해 접힌(Fold) 인자일 뿐입니다.
저는 Claude의 도움을 받아 OpenRouter와 연동되는 약 100줄의 완전한 Common Lisp AI 에이전트를 만들었습니다. SBCL, 두 개의 라이브러리 (HTTP용 dexador, JSON용 shasht), 그리고 그 외에는 아무것도 없습니다.
유일한 도구는 eval입니다
에이전트를 구축할 때 일반적으로 도구를 죄다 덧붙이는 것으로 시작합니다 - Agent Foundry에는 웹 검색 및 크롤링, 테이블 및 파일 도구, 파이썬 실행 도구 등이 있습니다. 사실, 대부분의 에이전트에서 대부분을 차지하는 것은 도구 카탈로그입니다.
Lisp는 이런 부분에서 속일 수 있는 방법을 제공합니다. Lisp는 언어 광들이 동질성(Homoiconic)이라고 부르는 것입니다 - 이는 단순한 아이디어를 나타내는 화려한 단어입니다. Lisp 프로그램은 Lisp 자체의 데이터 구조(리스트)로 작성되기 때문에 코드가 곧 데이터이고 데이터가 곧 코드입니다. 프로그램은 객체를 조립하는 동일한 방식으로 또 다른 프로그램을 구축할 수 있습니다.