에이전트 하니스 엔지니어링
TMT코딩 에이전트는 “모델 + 그 주변에 당신이 쌓아 올린 모든 것”입니다. 하니스 엔지니어링은 이를 하나의 진짜 산출물로 취급하고, 에이전트가 한 번 미끄러질 때마다 이를 더 조여 나가는 접근입니다.
대략 이런 개념입니다: 에이전트가 실수를 할 때마다, 같은 실수를 다시는 하지 않도록 에이전트를 설계하는 데 시간을 들이는 겁니다.
지난 2년 동안 우리는 모델을 두고 논쟁을 벌여왔습니다. 어떤 모델이 더 똑똑한지, 어떤 모델이 더 깔끔한 React 코드를 쓰는지, 어떤 모델이 환각을 덜 하는지. 이런 대화도 어느 정도는 의미 있지만, 사실 시스템의 나머지 절반은 잘 다루지 못합니다. 모델은 실행 중인 에이전트에 들어가는 요소 중 하나일 뿐입니다. 나머지는 바로 하니스(harness) 입니다. 프롬프트, 도구, 컨텍스트 정책, 훅, 샌드박스, 서브에이전트, 피드백 루프, 복구 경로처럼, 모델이 실제로 무언가를 끝까지 완수할 수 있도록 그 주변에 둘러싼 모든 것 말이죠.
괜찮은 모델에 훌륭한 하니스를 붙인 쪽이, 훌륭한 모델에 엉망인 하니스를 붙인 것보다 낫습니다. 저는 이걸 제 작업 속에서 계속 지켜봐 왔습니다. 그리고 점점 흥미로운 엔지니어링은 모델을 고르는 데 있는 게 아니라, 그 주변에 쌓는 것을 설계하는 데 있다는 쪽으로 기울고 있습니다.
이제 이 분야에는 이름까지 생겼습니다. Viv Trivedy 가 하니스 엔지니어링 이라는 용어를 만들었고, 그의 글 “Anatomy of an Agent Harness”는 하니스가 실제로 무엇인지, 그리고 각 구성 요소가 왜 존재하는지 가장 깔끔하게 풀어낸 글입니다. Dex Horthy는 이 패턴이 등장하는 과정을 추적해 왔습니다. HumanLayer는 대부분의 에이전트 실패를, 모델 가중치가 아니라 설정(configuration) 차원에서의 “스킬 이슈(skill issue)”로 설명합니다. Anthropic 엔지니어링 팀은 장시간 실행되는 작업을 위한 하니스 설계 방법을 가장 잘 정리한 공개 자료를 내놓았습니다. 그리고 Birgitta Böckeler는 사용자 관점에서 이게 어떻게 보이는지를 잘 정리해 두었죠.
이 글은 그 실타래들을 한데 모아보려는 제 시도입니다.
하니스는, 정말로, 무엇인가?
Viv 의 한 줄 정의가 이 개념 대부분을 설명해 줍니다.
Agent = Model + Harness. If you’re not the model, you’re the harness.
하니스는 모델 자체를 제외한, 코드·설정·실행 로직 전부를 포함합니다. 날 것의(raw) 모델은 에이전트가 아닙니다. 하니스가 상태(state), 도구 실행, 피드백 루프, 강제 가능한 제약 조건을 부여할 때 비로소 에이전트가 됩니다.
에이전트 하니스의 해부도는 이렇습니다. 모델이 가운데에 있고, 그 주변을 컨텍스트 주입, 제어 흐름, 액션, 영속성, 관찰 레이어가 둘러싸고 있습니다.
구체적으로, 하니스에는 다음이 포함됩니다.
- 시스템 프롬프트,
CLAUDE.md,AGENTS.md, 스킬 파일, 서브에이전트 프롬프트 - 도구, 스킬, MCP 서버 및 그 설명들
- 번들된 인프라 (파일시스템, 샌드박스, 브라우저)
- 오케스트레이션 로직 (서브에이전트 스폰, 핸드오프, 모델 라우팅)
- 결정적 실행을 위한 훅과 미들웨어(컴팩션, 컨티뉴에이션, 린트 체크)
- 관측 가능성(observability) (로그, 트레이스, 비용·지연 시간 측정)
Simon Willison은 이 루프 부분을 본질까지 줄입니다. 에이전트는 “도구를 루프 속에서 실행해 목표를 달성하는 시스템” 이라는 것입니다. 스킬은 도구와 루프를 어떻게 설계하느냐에 달려 있습니다.
표면적이 꽤 넓어 보인다면, 실제로 그렇습니다. 그리고 이건 모델 제공사가 아니라 당신 이 책임져야 하는 표면적입니다. Claude Code, Cursor, Codex, Aider, Cline 같은 것들은 모두 하니스입니다. 아래 깔린 모델은 종종 같을지라도, 당신이 경험하는 행동은 대부분 하니스가 하는 일에 의해 좌우됩니다.
coding agent = AI model(s) + harnessViv 가 정리하고 HumanLayer 가 이어받은 이 등식이 바로 실제 작업이 이뤄지는 지점입니다. 등식의 왼쪽(모델)을 두고 벌어지는 논쟁은 시끄럽지만, 실제 레버리지는 오른쪽(하니스)에 더 많이 있습니다.
“스킬 이슈”라는 재프레이밍
제가 엔지니어들이 반복해서 빠지는 패턴을 하나 봐왔습니다. 에이전트가 멍청한 짓을 하면, 엔지니어는 모델을 탓하고, 그 탓은 “다음 버전을 기다리자”는 쪽으로 정리됩니다.
하니스 엔지니어링 마인드셋은 이 기본값을 거부합니다. 실패는 대개 읽을 수 있는 신호입니다. 에이전트가 어떤 컨벤션을 몰랐다면, AGENTS.md 에 그 컨벤션을 추가합니다. 에이전트가 파괴적인 명령을 실행했다면, 그걸 막는 훅을 추가합니다. 에이전트가 40단계짜리 작업에서 길을 잃었다면, 플래너와 실행자(executor)로 역할을 쪼갭니다. 에이전트가 깨진 코드를 계속 “완료”라고 주장한다면, 타입체크 결과를 압력 신호(back-pressure)로 루프에 연결합니다.
HumanLayer 는 이렇게 말합니다. “이건 모델 문제가 아니다. 설정 문제다.” 이 말을 진지하게 받아들이면, 거기서부터가 바로 하니스 엔지니어링입니다.
Viv 의 글과 HumanLayer 글에서 모두 등장하는 흥미로운 데이터 포인트가 하나 있습니다. Terminal Bench 2.0 에서 Claude Opus 4.6 은 Claude Code 안에서 실행될 때보다, 커스텀 하니스 안에서 실행될 때 점수가 훨씬 낮게 나옵니다. Viv 의 팀은 코딩 에이전트를, 모델은 그대로 둔 채 하니스만 바꿔서, 순위 Top 30 에서 Top 5 로 끌어올렸습니다. 모델은 자신이 훈련될 때 같이 쓰이던 하니스에 사후 학습(post-training)으로 맞물리게 됩니다. 그 모델을 다른 하니스로 옮기되, 당신 코드베이스에 맞는 더 나은 도구, 더 타이트한 프롬프트, 더 날카로운 백프레셔를 갖춘 하니스로 옮기면, 기존 하니스가 바닥에 흘리던 능력을 끌어올릴 수 있습니다.
이건 “그냥 GPT-6 나올 때까지 기다리자”는 내러티브의 정반대입니다. 오늘날 모델이 할 수 있는 일과 당신이 실제로 보게 되는 일 사이에는, 상당 부분 하니스 갭이 존재합니다.
래칫(ratchet): 모든 실수는 규칙이 된다
하니스 엔지니어링에서 가장 중요한 습관은 에이전트의 실수를 영구적인 신호로 취급하는 것입니다. 한 번 웃고 넘길 에피소드도 아니고, “운 나쁜 실행”이라며 다시 돌려보는 것도 아닙니다. 신호입니다.
에이전트가 주석 처리된 테스트를 포함한 PR을 올렸고, 제가 실수로 그것을 머지했다면, 그건 입력입니다. 다음 버전의 AGENTS.md에는 “테스트를 주석 처리하지 말 것; 필요하면 삭제하거나 고칠 것”이라는 문장이 들어갑니다. 다음 버전의 pre-commit 훅은 diff 안에서 .skip( 이나 xit( 을 grep 합니다. 다음 버전의 리뷰어 서브에이전트는 주석 처리된 테스트를 반드시 막아야 할 항목으로 표시합니다.
제약은 실제로 실패를 목격했을 때에만 추가합니다. 역으로, 충분히 유능한 모델이 그 제약이 필요 없을 정도가 되었을 때에만 제거합니다. 좋은 AGENTS.md 안의 모든 줄은, 구체적으로 어떤 일이 잘못되었는지에 대한 흔적으로 추적 가능해야 합니다.
그래서 하니스 엔지니어링은 프레임워크라기보다 하나의 규율(discipline)에 가깝습니다. 당신 코드베이스에 맞는 하니스는, 그 코드베이스에서 실제로 겪은 실패의 히스토리에 의해 모양이 잡히기 때문입니다. 이건 다운로드해서 쓸 수 있는 게 아닙니다.
행동에서부터 거꾸로 설계하기
제가 실제로 하니스를 설계할 때 가장 유용하게 쓰는 Viv 의 프레이밍은, 원하는 행동에서 출발해 그 행동을 가능하게 해 줄 하니스 조각을 도출하는 방식입니다. 그의 패턴은 이렇습니다. 우리가 원하거나(혹은 고치고 싶은) 행동 → 모델이 그 행동을 달성하도록 돕는 하니스 설계.
각 하니스 기능은, 모델이 혼자서는 제공하지 못하는 특정 행동에서 파생됩니다. 실제 데이터를 다루는 작업은 파일시스템과 git으로 매핑됩니다. 코드를 작성·실행하는 일은 bash와 코드 실행으로 매핑됩니다. 안전한 실행과 기본값은 샌드박스 환경과 도구로 매핑됩니다. 새로운 지식을 기억하는 일은 메모리 파일, 웹 검색, MCP 로 매핑됩니다. 긴 컨텍스트에서의 성능은 컴팩션, 도구 오프로딩, 스킬로 매핑됩니다. 장기적인 작업은 Ralph 루프, 플래닝, 검증으로 매핑됩니다.
이렇게 거꾸로 도출하는 게 좋은 이유는, 각 하니스 컴포넌트마다 수행해야 할 구체적인 일이 생기기 때문입니다. 어떤 컴포넌트가 존재하는 이유가 “어떤 행동을 제공하기 위해서인지” 설명하지 못한다면, 그 컴포넌트는 아마 거기 있으면 안 됩니다.
이제부터는 Viv 가 짚어 나간 순서를 대략 따라가면서, 제가 직접 써 보며 “훔쳐 쓸 만하다”고 느낀 패턴을 같이 정리해 보겠습니다.
파일시스템과 Git: 내구성 있는 상태
파일시스템은 가장 기본적인 프리미티브지만, 지루하다는 이유로 과소평가되는 경우가 많습니다. 모델은 컨텍스트에 들어온 것만 직접 조작할 수 있습니다. 파일시스템 없이라면, 사용자는 내용을 복붙해 채팅창에 넣는 수밖에 없고, 이건 제대로 된 워크플로우라고 부르기 어렵습니다.
파일시스템이 생기면, 에이전트는 워크스페이스를 가지게 됩니다. 데이터, 코드, 문서를 읽어 들이고, 중간 결과를 컨텍스트 대신 디스크에 내려놓으며, 여러 에이전트와 사람이 공유 파일을 통해 협력할 수 있는 공간이 생깁니다. 여기에 Git 을 얹으면 버저닝이 공짜로 따라와, 에이전트는 진행 상황을 추적하고, 오류를 롤백하고, 실험용 브랜치를 따로 딸 수 있습니다.
다른 하니스 프리미티브 대부분은 결국 파일시스템을 향해 뭔가를 읽고 쓰게 됩니다.
Bash와 코드 실행: 범용 도구
오늘날의 메인 에이전트 루프는 ReAct 루프입니다. 모델이 추론하고, 도구 호출을 통해 액션을 취하고, 결과를 관찰한 뒤, 이를 반복합니다. 하지만 하니스는 자신이 실행 로직을 알고 있는 도구만 실행할 수 있습니다. 모든 가능 액션마다 도구를 일일이 먼저 만들어 줄 수도 있고, 아니면 에이전트에게 bash 를 주고, 필요한 도구를 그때그때 만들게 할 수도 있습니다.
Willison 의 관점은 이렇습니다. 에이전트는 이미 셸 명령에 꽤 능숙하며, 대부분의 작업은 잘 고른 몇 개의 CLI 호출로 수렴합니다. 하니스는 여전히 특정 목적에 맞춘 도구를 함께 제공하지만, bash 와 코드 실행은 자율적인 문제 해결을 위한 기본 전략이 되었습니다. 특정 주방 도구 하나를 가르쳐 주는 것과, 주방 전체를 통째로 건네주는 것의 차이에 가깝습니다.
샌드박스와 기본 도구 세트
bash 가 쓸모 있으려면, 우선 안전하게 실행할 수 있어야 합니다. 에이전트가 생성한 코드를 당신 노트북에서 바로 실행하는 건 위험하고, 단일 로컬 환경은 여러 개의 에이전트를 병렬로 돌리기에도 적합하지 않습니다.
샌드박스는 에이전트에게 격리된 실행 환경을 제공합니다. 로컬에서 실행하는 대신, 하니스는 샌드박스에 연결해 코드를 실행하고, 파일을 살피고, 의존성을 설치하며, 작업을 검증합니다. 실행 가능한 명령을 화이트리스트로 제한하고, 네트워크를 차단해 둘 수 있고, 태스크마다 환경을 새로 띄웠다가 끝나면 버릴 수 있습니다.
좋은 샌드박스는 좋은 기본값을 함께 제공합니다. 주요 언어 런타임과 패키지, Git·테스트 CLI, 웹 상호작용을 위한 헤드리스 브라우저 같은 것들입니다. 브라우저, 로그, 스크린샷, 테스트 러너는 에이전트가 자신의 작업을 관찰하고, 자기 검증 루프를 닫을 수 있게 해 줍니다.
모델은 자신의 실행 환경을 구성하지 않습니다. 에이전트를 어디서 돌릴지, 무엇을 쓸 수 있게 할지, 결과를 어떻게 검증할지는 전부 하니스 차원의 의사결정입니다.
메모리와 검색: 지속적인 학습
모델은 가중치와 현재 컨텍스트 외의 추가 지식을 갖고 있지 않습니다. 가중치를 편집하지 못하는 이상, 새로운 지식을 더하는 유일한 방법은 컨텍스트 주입뿐입니다.
여기서도 기본 프리미티브는 파일시스템입니다. 하니스는 AGENTS.md 같은 메모리 파일 표준을 지원하고, 이 파일은 시작할 때마다 컨텍스트에 주입됩니다. 에이전트가 이 파일을 수정하면, 하니스는 파일을 다시 로드하고, 한 세션에서 축적된 지식이 다음 세션에도 이어집니다. 거칠지만 효과적인 형태의 지속적 학습입니다.
훈련 시점에 존재하지 않았던 지식(새 버전의 라이브러리, 최신 문서, 오늘의 데이터)을 위해서는, 웹 검색과 Context7 같은 MCP 도구가 커트오프를 보완합니다. 이런 것들은 사용자의 손에만 맡겨 두기보다는, 하니스 차원에서 기본 프리미티브로 통합해 두는 편이 좋습니다.
컨텍스트 부패(context rot)와의 싸움
컨텍스트 부패란, 컨텍스트 창이 가득 차갈수록 모델의 추론과 작업 완수 능력이 점점 떨어지는 현상을 말합니다. 컨텍스트는 희소 자원이고, 하니스란 결국 좋은 컨텍스트 엔지니어링을 위한 전달 메커니즘입니다.
여기서 반복해서 등장하는 기술이 세 가지 있습니다.
컴팩션(compaction). 윈도우가 가득 차기 직전에, 뭔가를 포기해야 합니다. 프로덕션 하니스에서 API 에러를 그대로 두는 건 선택지가 아닙니다. 대신 하니스는 오래된 컨텍스트를 지능적으로 요약해 내보내고, 그 자리에 새 정보를 넣어 에이전트가 계속 작업할 수 있게 합니다.
도구 호출 결과 오프로딩(tool-call offloading). 2,000줄짜리 로그처럼, 거대한 도구 출력은 실질적인 신호는 얼마 없으면서 컨텍스트를 잡아먹습니다. 하니스는 머리와 꼬리 일부만 남기고, 전체 출력은 파일시스템으로 내려, 필요할 때 에이전트가 직접 읽도록 합니다.
점진적 공개가 가능한 스킬(skills with progressive disclosure). 시작부터 모든 도구와 MCP 를 컨텍스트에 다 올려 두면, 에이전트가 아무 행동도 하기 전에 성능이 떨어집니다. 스킬을 사용하면 하니스는, 그 태스크에 실제로 필요할 때만 해당 스킬의 지침과 도구를 드러낼 수 있습니다.
Anthropic 의 하니스 글은, 정말 긴 작업을 위한 또 다른 기법을 제시합니다. 바로 전체 컨텍스트 리셋입니다. 하니스가 세션을 완전히 종료하고, 컴팩트한 핸드오프 파일을 기반으로 새 세션을 구성하는 방식입니다. 그들은 컴팩션만으로는 긴 작업에 충분하지 않았다 고 명시합니다. 때때로는, 요약된 브리프를 들고 완전히 새로 시작해야 합니다. 이건 우리가 보통 “메모리”라고 생각하는 것보다, 새 엔지니어를 온보딩하는 방식에 훨씬 더 가깝습니다.
장기 실행: Ralph 루프, 플래닝, 검증
자율적인 장기 실행 작업은 일종의 성배 같은 목표지만, 제대로 구현하기 제일 어렵습니다. 오늘날의 모델은 일찍 멈추고, 복잡한 문제를 잘게 나누지 못하고, 여러 컨텍스트 윈도우에 걸친 작업을 이어가며 일관성을 잃습니다. 하니스는 이런 문제를 피해 가도록 설계되어야 합니다.
저는 self-improving agents와 2026 트렌드 글에서 Ralph 루프 같은 자율 코딩 루프에 대해 이미 쓴 적이 있지만, 이 프레이밍에서 다시 정리해 볼 만합니다. 훅이 모델의 종료 시도를 가로채고, 원래 프롬프트를 새 컨텍스트 윈도우에 다시 주입해, 에이전트가 목표를 달성할 때까지 계속하게 만드는 방식입니다. 각 반복은 깨끗한 컨텍스트에서 시작하되, 파일시스템을 통해 이전 상태를 읽어옵니다. 단일 세션 에이전트를 여러 세션에 걸친 에이전트로 바꾸는 놀라울 만큼 단순한 트릭이며, “그냥 더 똑똑한 모델을 쓰면 되지”라는 발상만으로는 떠올리기 힘든 종류의 프리미티브입니다.
플래닝(planning) 은 모델이 목표를 일련의 단계로 쪼개, 보통 디스크의 플랜 파일에 적어 두는 과정입니다. 하니스는 플랜 파일을 어떻게 사용할지에 대한 프롬프트와 리마인더로 이를 지원합니다. 각 단계를 수행한 뒤, 에이전트는 자기 검증(self-verification)을 통해 작업을 점검합니다. 훅이 미리 정의된 테스트 스위트를 실행하고, 실패하면 에러 텍스트를 모델에게 돌려보내거나, 모델이 자신이 낸 결과를 명시적인 기준에 따라 스스로 리뷰하게 하는 식입니다.
플래너 / 제너레이터 / 이밸류에이터 분리. Anthropic 의 장기 실행 하니스 작업은, 생성과 평가를 분리된 에이전트에 맡겼을 때 자기 평가(self-evaluation)보다 더 좋은 성능이 나온다고 명시합니다. 에이전트가 자기 작업을 채점하면 일관되게 후하게 점수를 준다는 겁니다. 프로즈 버전의 GAN 과도 비슷합니다. 여기서 파생된 관련 패턴이 바로 스프린트 컨트랙트(sprint contract) 입니다. 제너레이터와 이밸류에이터가 코드를 쓰기 전에 “완료”의 의미를 협상해 두는 방식입니다. 제 경험상, 작업을 시작하기 전에 “done” 조건을 글로 적는 습관이, 제가 지금까지 바꿔 본 어떤 프롬프트보다 스코프 드리프트를 더 많이 잡아줬습니다.
훅: 규칙을 실제로 강제하는 레이어
훅은 “나는 에이전트에게 X 를 하라고 지시했다”와 “시스템이 X 를 실제로 강제한다” 사이에 놓인 구성요소입니다.
훅은 특정 라이프사이클 지점에 실행되는 스크립트입니다. 도구 호출 전, 파일 수정 후, 커밋 전에, 세션 시작 시 같은 타이밍이죠. 에이전트가 자주 잊어버리지만, 결코 잊어선 안 되는 것들을 넣기에 딱 좋은 자리입니다. 매번 수정 후 타입체크와 린트, 테스트를 돌리고, 실패하면 결과를 표면 위로 올립니다. 파괴적인 bash 명령(rm -rf, git push --force, DROP TABLE)을 차단합니다. PR 을 열거나 main 에 푸시하기 전에 승인을 요구합니다. 파일을 쓸 때마다 자동 포맷팅을 적용해, 에이전트가 공백 같은 것에 토큰을 낭비하지 않도록 합니다.
HumanLayer 가 강조하고, 저도 전적으로 동의하게 된 원칙이 하나 있습니다. 성공은 조용하고, 실패는 시끄러워야 한다 는 것입니다. 타입체크가 통과하면, 에이전트는 아무것도 듣지 못합니다. 실패하면 에러 텍스트가 루프에 주입되어, 에이전트가 스스로 수정합니다. 이렇게 하면 피드백 루프는 일반적인 경우에는 거의 공짜에 가깝고, 문제가 생겼을 때는 바로 액션으로 이어질 수 있을 만큼 구체적인 신호를 줍니다.
AGENTS.md와 도구 선택
리포지토리 루트에 있는 평평한 마크다운 룰북은, 여전히 레버리지가 가장 큰 설정 포인트입니다. 매 턴 시스템 프롬프트에 들어가기 때문입니다. 패키지 매니저, 테스트 프레임워크, 포맷팅 규칙, “/legacy 디렉터리는 절대 건드리지 말 것”, “항상 우리 로거를 사용할 것” 같은 관례들이 여기에 들어갑니다. 여기서 제가 몸으로 배운 교훈 두 가지가 있습니다.
짧게 유지하라. HumanLayer 는 그들의 AGENTS.md 를 60줄 이내로 유지합니다. 한 줄 한 줄이 주목 경쟁을 벌이기 때문에, 규칙이 늘어날수록 각 규칙의 영향은 줄어듭니다. 파일럿용 체크리스트이지, 스타일 가이드가 아닙니다.
각 줄은 “벌어서” 얻어라. 규칙은 구체적인 과거 실패나, 바꿀 수 없는 외부 제약에서 나와야 합니다. 그렇지 않으면 잡음에 불과합니다. 브레인스토밍이 아니라 래칫입니다.
도구에도 똑같은 규율이 필요합니다. 도구 이름, 설명, 스키마는 매 요청마다 프롬프트에 찍힙니다. 겹치는 도구 50개보다, 초점을 잘 맞춘 도구 10개가 더 낫습니다. 모델이 “메뉴판”을 머릿속에 담을 수 있기 때문입니다. HumanLayer 는 여기서 보안 측면의 진짜 걱정거리도 짚습니다. 도구 설명은 프롬프트에 들어가기 때문에, 설치하는 MCP 서버는 모두 모델이 읽게 되는 “신뢰된 텍스트”가 됩니다. 허술하거나 악의적인 MCP 는, 당신이 아무것도 치기 전에 에이전트를 프롬프트 인젝션으로 오염시킬 수 있습니다.
프로덕션에서 이것이 어떻게 보이는지
성숙한 하니스의 그림을 가장 잘 보여 주는 공개 자료는, Fareed Khan 이 (추정해) 정리한 Claude Code 아키텍처입니다. 이 다이어그램은 잠시 멈춰서 곱씹어 볼 가치가 있습니다.
Claude Code 아키텍처는 레이어별로 이렇게 주석을 달 수 있습니다. 사용자 인터페이스, 세션 매니저, 권한 게이트가 있는 입력 레이어;
스킬 레지스트리, 컨텍스트 컴프레서, 태스크 그래프, 메모리 스토어로 구성된 지식 레이어;
MCP 런타임과 외부 서버로 이뤄진 통합 레이어;
도구 디스패치, 스트리밍 런타임, 프롬프트 캐시가 있는 실행 레이어;
검증된 태스크 결과를 반환하는 출력 레이어;
이벤트 버스와 백그라운드 실행기가 있는 관측 레이어;
그리고 서브에이전트 스폰, 팀메이트 메일박스, FSM 프로토콜, 자율 보드, 워크트리 아이솔레이터를 포함하는 멀티에이전트 레이어입니다.
마스터 에이전트 루프는 다이어그램 가운데에 자리 잡고, 모든 레이어에서 화살표가 중앙으로 흘러 들어옵니다.
앞서 이야기한 개념 대부분이 이 다이어그램 어딘가에서 이름 붙은 컴포넌트로 등장합니다. 컨텍스트 주입은 지식 레이어에 해당합니다. 루프 상태는 메모리 스토어와 워크트리 아이솔레이터에 저장됩니다. 파괴적 액션을 막는 훅은 권한 게이트 뒤에 위치합니다. 서브에이전트 간 컨텍스트 파이어월은 멀티에이전트 레이어 전체입니다. 도구 디스패치 레지스트리는 MCP 서버와 bash 가 둘 다 꽂히는 자리입니다. Khan 의 주장은 Viv 의 주장과 같습니다. 다만 실제 제품에 투영해 보여 줄 뿐이죠. Claude Code 의 진화 궤적은, 아래 깔린 모델만큼이나 하니스에 의해 결정됩니다.
하니스는 작아지지 않고, 자리를 옮긴다
Anthropic 글에서 가장 인상적인 관찰 중 하나는, 모델이 좋아져도 의미 있는 하니스 조합의 공간은 줄어들지 않는다는 점입니다. 대신 그 공간이 “이동”합니다.
단순한 이야기는 이렇습니다. 더 좋은 모델이 등장하면, 하니스는 필요 없어질 거라는 겁니다. 모델이 플래닝을 잘하면, 플래너는 필요 없습니다. 모델이 장기 일관성이 좋다면, 컨텍스트 리셋도 필요 없습니다. 실제로 Opus 4.6 은 “컨텍스트 불안(context anxiety)”이라는 실패 모드 대부분을 없애 버렸습니다. Sonnet 4.5는 자신이 생각하는 컨텍스트 한계에 가까워지면 조기에 작업을 마무리하는 경향이 있었는데, 이걸 막기 위해 6개월 전만 해도 제가 쓰던 여러 “불안 완화용 스캐폴딩”들은 이제 쓸모없는 코드가 되었다는 뜻입니다.
하지만 모델이 좋아지면서 “천장”도 함께 올라갔습니다. 예전에는 아예 손대지 못하던 작업들이 이제는 가능한 구간으로 들어왔고, 그 작업들은 또 다른 종류의 실패 모드를 갖고 있습니다. 불안을 달래기 위한 스캐폴딩은 사라지지만, 그 자리에 며칠에 걸친 메모리 정책, 세 명의 전문 에이전트를 조율하는 하니스, 생성된 UI 의 디자인 퀄리티를 평가하기 위한 이밸류에이터 같은 것들이 필요해집니다. 전제가 바뀌면, 그 전제를 코드로 담아내는 스캐폴딩도 함께 바뀌는 셈입니다.
Anthropic 은 이걸 이렇게 정리합니다. “하니스의 모든 컴포넌트는, 모델이 혼자서는 할 수 없는 일에 대한 하나의 가정을 인코딩한다.” 모델이 어떤 일을 더 잘하게 되면, 그 컴포넌트는 더 이상 아무것도 떠받치지 못하게 되고, 제거해야 합니다. 반대로 모델이 새로운 일을 할 수 있게 되면, 그 새 천장에 닿기 위해 또 다른 스캐폴딩이 필요해집니다.
모델–하니스 트레이닝 루프
Viv 가 명시적으로 이름 붙인 또 하나의 흐름은, 하니스 설계와 모델 트레이닝 사이의 피드백 루프입니다.
모델–하니스 트레이닝 루프의 모습은 이렇습니다. 하니스에서 유용한 프리미티브가 발견되면, 그것이 제품 차원에서 표준화되고, 다음 세대 모델을 훈련할 때 이 프리미티브가 포함됩니다. 그러면 새 모델은 이 프리미티브를 더 잘 사용하게 됩니다. 그리고 이 사이클이 반복됩니다.
오늘날의 에이전트 제품은 하니스를 루프에 넣은 상태로 사후 학습(post-training)됩니다. 모델은 하니스 디자이너들이 “잘했으면 좋겠다”고 생각한 행동들, 예를 들어 파일시스템 조작, bash 사용, 플래닝, 서브에이전트 디스패치 같은 것들에 대해 특히 더 잘하게 됩니다. 그래서 Opus 4.6 이 Claude Code 안에 있을 때와, 다른 누군가의 하니스 안에 있을 때 느낌이 달라지고, 도구의 내부 로직을 조금만 바꿔도 이상한 회귀(regression)가 튀어나오곤 합니다. 진짜 일반적인 모델이라면 apply_patch 를 쓰든 str_replace 를 쓰든 상관하지 않아야겠지만, 공동훈련(co-training)은 필연적으로 오버피팅을 만들어냅니다.
여기서의 실질적인 함의는 두 가지입니다. 하니스는 한 번 세팅하고 끝나는 설정 파일이 아니라, 살아 있는 시스템이라는 점. 그리고 “최고의” 하니스는 꼭 모델이 훈련될 때 쓰였던 그 하니스일 필요는 없다는 점입니다. 당신의 태스크를 위해 설계된 하니스가 진짜 최적입니다. Viv 의 Terminal Bench 점수를 Top 30 에서 Top 5 로 끌어올린 사례는, 제가 본 것 중 이 점을 가장 잘 보여 주는 증거입니다.
서비스로서의 하니스(Harness-as-a-Service)
Viv 가 제안한 또 하나의 프레이밍이 HaaS, 바로 Harness-as-a-Service 입니다. 관찰 포인트는, 우리가 LLM API 위에(완성된 텍스트를 돌려주는 API) 구축하던 시대에서, 하니스 API 위에(런타임을 제공하는 API) 구축하는 시대로 옮겨가고 있다는 것입니다. Claude Agent SDK, Codex SDK, OpenAI Agents SDK 모두 같은 방향을 가리킵니다. 루프, 도구, 컨텍스트 관리, 훅, 샌드박스 프리미티브를 한 번에 제공하고, 거기에 당신이 커스터마이즈를 얹어가는 방식입니다.
이 변화가 중요한 이유는 기본 경로(default path)가 달라지기 때문입니다. 예전 기본 경로는 “직접 루프를 만들고, 도구 호출을 연결하고, 대화 상태를 관리하고, 승인 플로우를 설계하는 것”이었습니다. 이제 기본 경로는 “하니스 프레임워크를 하나 고르고, 네 가지 축(시스템 프롬프트, 도구, 컨텍스트, 서브에이전트)에 맞춰 설정한 다음, 나머지 노력은 도메인 특화 프롬프트와 도구 설계에 집중하는 것”입니다.
그래서 “스킬 이슈”가 감당 가능한 문제가 됩니다. 매번 문제가 생길 때마다 에이전트를 처음부터 다시 만드는 게 아니라, 이미 잘 구성된 설정 표면(configuration surface)을 조금씩 조정하는 일이 되기 때문입니다.
Viv 의 문장 가운데, 초기 버전을 서둘러 만들라는 조언은 이 맥락을 가장 잘 요약합니다. “좋은 에이전트 빌딩은 반복(iteration)의 연속이다. v0.1 이 없으면 반복도 없다.”
이 흐름이 향하는 곳
상위권 코딩 에이전트들(Claude Code, Cursor, Codex, Aider, Cline)을 나란히 놓고 보면, 이들은 서로의 기반 모델보다 서로의 하니스 구조를 더 많이 닮아 있습니다. 모델은 서로 다르지만, 하니스 패턴은 수렴해 가고 있습니다. 제 생각에 이건 우연이 아닙니다. 제너레이티브 모델을 “실제로 뭔가를 배송(ship)할 수 있는 것”으로 바꿔 주는, 하니스의 하중을 버티는(load-bearing) 부품들을 산업 전체가 천천히 찾아가는 과정입니다.
Viv 가 제시한 오픈 문제 목록 가운데, 제가 특히 흥미롭게 보는 것들은 다음과 같습니다. 하나의 공유 코드베이스 위에서 여러 에이전트를 병렬로 오케스트레이션하는 일. 자신의 트레이스를 분석해 하니스 레벨의 실패 모드를 스스로 찾고 고치는 에이전트. 태스크가 시작되기 전에 모든 도구와 컨텍스트를 미리 정해 두는 대신, 태스크마다 “딱 맞는” 도구와 컨텍스트를 즉석에서 조합해 내는 하니스.
특히 마지막 지점은, 하니스가 더 이상 정적인 설정 파일이 아니라, 컴파일러에 가까운 무언가로 변해 가는 순간처럼 느껴집니다.