하네스 엔지니어링 적용편 — AI 에이전트 성능보다 더 중요한 건 바깥 구조였다

지난 글에서는 하네스 엔지니어링이라는 말을 조금 추상적으로 다뤘다. 모델 바깥에 제약을 두고, 도구 실행을 통제하고, 상태를 넘겨주는 구조가 중요하다는 이야기였다. 그런데 그런 설명만으로는 좀 안 와닿는다. 나도 그랬다. “그래서 실제로는 뭘 어떻게 묶었다는 건데?”라는 질문이 계속 남았다.

 

Anthropic이 공개한 에이전트 설계와 OpenAI Codex 팀의 실험 기록을 같이 보면 그 질문에 답이 생긴다. 둘이 접근 방식은 조금 다르지만, 읽다 보면 결국 같은 결론으로 수렴한다. 좋은 결과를 내는 건 모델의 ‘지능’ 자체가 아니라, 모델이 실수하지 않도록 둘러싸는 바깥 구조라는 점이다.

 

이걸 이해하는 가장 쉬운 출발점은 거창한 다이어그램이 아니라 그냥 하나의 루프다.

 

에이전트는 결국 while(true)다

 

복잡한 AI 에이전트를 머릿속에서 너무 거대하게 상상하면 오히려 핵심을 놓친다. 실제 동작은 생각보다 단순하다. 에이전트의 중심에는 거의 항상 반복 루프가 있다. 컨텍스트를 준비하고, 모델을 호출하고, 도구를 실행하고, 계속할지 판단한다. 이 네 단계가 계속 돈다.

 

중요한 건 이 반복이 단순 호출이 아니라는 점이다. 한 번 돌 때마다 모델은 생각하고, 뭔가를 시도하고, 결과를 보고, 다시 판단한다. 익숙한 표현으로 바꾸면 사고 → 행동 → 관찰 사이클이다. 사람도 비슷하게 일한다. 문서를 보고, 터미널을 치고, 에러를 보고, 다시 수정한다. 에이전트도 크게 다르지 않다.

 

그런데 여기서 많은 설명이 지나치게 모델 중심으로 흘러간다. 마치 모델이 도구를 직접 다루고, 스스로 질서를 유지하고, 알아서 올바른 경로로 가는 것처럼 묘사된다. 실제로는 반대다. 모델은 의도를 낼 뿐이고, 실행은 바깥에서 막고, 거르고, 승인하고, 다시 주입한다. 그러니까 도구 사용의 주체는 모델처럼 보이지만, 책임을 지는 쪽은 하네스다.

 

이 차이가 꽤 크다.

 

모델이 “이제 파일을 읽자”, “테스트를 돌리자”, “배포 API를 호출하자” 같은 출력을 내면, 하네스는 그걸 그냥 믿고 흘려보내지 않는다. 출력에서 도구 호출을 감지하고, 텍스트 생성을 멈추고, 입력 형식을 검증하고, 권한 정책을 확인하고, 필요하면 사용자 승인으로 넘긴다. 그리고 실제 실행 결과를 다시 모델 컨텍스트에 넣는다. 이 구조가 없으면 에이전트는 똑똑한 척하는 자동완성기에 가깝고, 이 구조가 있으면 비로소 작업 단위를 가진 시스템이 된다.

 

그러니까 에이전트 성능을 올린다고 할 때 진짜 질문은 “어떤 모델을 쓰느냐”보다 “도구 호출을 누가, 어떤 순서로, 어디까지 통제하느냐”에 가깝다.

 

여기까지는 그럴듯하다. 문제는 이 루프가 생각보다 빨리 무너진다는 데 있다.

 

길어지는 순간 모델은 갑자기 이상해진다

 

짧은 작업은 이 구조만으로도 꽤 잘 된다. 파일 하나 수정하고, 테스트 돌리고, 결과 확인하는 정도는 충분히 감당한다. 그런데 작업이 길어지면 분위기가 달라진다. 컨텍스트가 쌓이고, 중간 상태가 늘어나고, 처음에 세웠던 계획과 지금 보는 화면 사이의 거리가 멀어진다. 이때부터 모델은 실수를 다른 방식으로 하기 시작한다.

 

처음에는 디테일을 놓친다. 그다음에는 이미 한 작업을 또 하거나, 끝나지 않은 일을 끝난 것처럼 말한다. 더 가면 조급해진다. 토큰 한계에 가까워질수록 갑자기 “이제 거의 끝났다” 같은 분위기를 내면서 어설프게 마무리하려 든다. Anthropic이 말한 “컨텍스트 불안”이 바로 이런 상태다. 모델이 정말 불안을 느끼는 건 아니지만, 행동 패턴은 꽤 비슷하다. 여유 있게 검토하던 흐름이 깨지고, 빨리 정리하려는 방향으로 기울어진다.

 

이 지점이 흥미롭다. 우리는 보통 긴 컨텍스트를 지원하는 모델이면 장기 작업도 자연스럽게 잘할 거라고 기대한다. 그런데 실제 운영에서는 반대로, 오래 들고 가는 것 자체가 품질 저하를 만들기도 한다. 메모리를 많이 준다고 집중력이 좋아지는 게 아닌 셈이다.

 

Anthropic이 여기서 선택한 해법은 요약도, 보존도, 압축도 아니었다. 그냥 리셋이다.

 

깨끗하게 버리고, 파일로 이어 붙인다

 

Anthropic의 Ralph Loop 패턴을 보면 발상이 꽤 과격하다. 작업이 길어져 컨텍스트가 지저분해지면, 그걸 예쁘게 줄이려고 애쓰지 않는다. 통째로 버리고 새 세션으로 넘어간다. 처음 보면 너무 무식한 방법처럼 보인다. “아니, 여기까지 쌓은 문맥을 다 버린다고?” 싶다.

 

그런데 전제가 있다. 상태가 모델 머리 안이 아니라 파일 시스템 바깥에 있어야 한다.

 

세션 사이를 연결하는 건 긴 대화 내역이 아니라 구조화된 인수인계 파일이다. 사람이 읽는 진행 로그, 모델이 다루기 쉬운 기능 목록, 그리고 git 이력 같은 것들이 다리 역할을 한다. 한 세션이 끝날 때는 진행 상황을 남기고 커밋한다. 다음 세션은 깨끗한 컨텍스트에서 시작하지만, 이 파일들을 읽으면서 바로 현재 위치를 복원한다.

 

이 방식이 왜 괜찮으냐면, 장기 작업에서 진짜 중요한 건 “모든 대화를 기억하는 것”이 아니라 “지금 무엇을 해야 하는지 잃지 않는 것”이기 때문이다. 오히려 이전의 장황한 문맥을 계속 들고 가는 쪽이 집중을 흐린다. 파일 하나에 완료한 것, 깨진 것, 다음 할 일을 남겨두면 그게 훨씬 강한 앵커가 된다.

 

여기서 나는 좀 인간적인 루틴이 보였다. 개발자도 비슷하다. 어제 하루 종일 붙잡고 있던 브랜치를 오늘 다시 열면, 머릿속에서 모든 사고 과정을 그대로 재생하지 않는다. TODO, 커밋 로그, 메모, 테스트 상태를 보고 다시 탑승한다. Anthropic은 이걸 그냥 하네스로 만든 거다.

 

사소해 보이는데 꽤 인상적인 부분도 있다. 예를 들어 세션 시작 루틴에 pwd가 들어간다. 올바른 작업 디렉토리인지 확인하는 그 한 줄 말이다. 너무 뻔해서 웃길 정도인데, 이런 걸 빼먹으면 비용 큰 실수가 난다. 잘못된 저장소에서 수정하거나, 엉뚱한 서버를 띄우는 식이다. 결국 실무 하네스라는 건 거대한 지능 시스템이 아니라, 사람이 자주 망하는 지점을 기계적으로 막는 장치에 가깝다.

 

Markdown보다 JSON이 더 낫다는 얘기가 괜히 나온 게 아니다

 

Anthropic이 기능 백로그를 Markdown 대신 JSON으로 관리한 이유도 그런 맥락에서 읽힌다. 이건 취향 문제가 아니다. 모델은 생각보다 자유 서술 형식을 너무 자유롭게 다룬다. Markdown 문서는 보기 좋지만, 항목을 슬쩍 지우거나, 순서를 흐리거나, 의미를 바꾸는 식의 사고가 자주 난다. 반면 JSON은 구조가 깨지면 바로 티가 난다. 항목이 빠졌는지, passes가 true인지 false인지, 배열이 살아 있는지 확인하기가 훨씬 쉽다.

 

이 차이가 별거 아닌 것 같아도 장기 루프에서는 엄청 크다. 사람이 문서를 볼 때는 문맥으로 읽어버리지만, 모델은 형식을 핑계로 의미를 흐릴 때가 있다. 그래서 Anthropic이 “테스트를 삭제하거나 수정하지 마라” 같은 강한 지시를 별도로 둔 것도 이해가 간다. 기능 검증 목록 자체가 흔들리면, 그다음부터는 작업을 얼마나 했는지 평가할 기준이 사라진다.

 

결국 여기서 배운 건 한 가지다. 모델이 잘 읽는 형식과 사람이 예쁘다고 느끼는 형식은 다를 수 있다. 이걸 구분하지 않으면 설계가 자꾸 감성 쪽으로 흐른다.

 

Planner, Generator, Evaluator로 쪼갠 이유

 

Anthropic의 3-에이전트 구조는 이름만 보면 좀 교과서 같다. Planner가 계획 세우고, Generator가 구현하고, Evaluator가 검증한다. 얼핏 보면 “역할 분리 좋죠” 수준의 당연한 얘기처럼 보인다. 그런데 실제 포인트는 역할명이 아니라 경계다.

 

특히 Evaluator가 흥미롭다. 이 에이전트는 코드를 리뷰하는 데 머물지 않는다. 실제 브라우저를 열고, 페이지를 탐색하고, 사용자처럼 행동하면서 결과를 확인한다. Playwright MCP를 쓴다는 대목이 중요한 이유가 여기 있다. 코드가 예뻐 보이는지보다, 실제로 스크롤이 되는지, 빈 화면이 뜨는지, 버튼이 반응하는지를 본다.

 

이 차이는 생각보다 거칠고 현실적이다. 개발 현장에서 망가지는 대부분은 코드의 문장미가 아니라 동작의 어긋남이기 때문이다. 함수 이름이 깔끔해도 버튼이 두 번 눌리면 끝이다. Anthropic은 이걸 너무 잘 알고 있었던 것 같다. 그래서 평가를 코드 수준의 논리 확인이 아니라, 사용자 행위 기반 검증으로 내려버렸다.

 

그리고 그 위에 “계약”이라는 층을 하나 더 얹는다. 이게 꽤 영리하다. “잘 구현했는가?” 같은 질문은 너무 흐리다. 대신 스프린트마다 Generator와 Evaluator가 합의한 조건을 만든다. 위로 올리면 20개가 더 로드되는지, 타임스탬프가 상대 시간으로 보이는지, 새 메시지가 스크롤 점프 없이 아래에 붙는지 같은 식이다. 이렇게 되면 평가는 주관을 덜 타게 된다. 좋다 나쁘다가 아니라, 충족했냐 못 했냐의 문제로 바뀐다.

 

내가 이 부분을 좋게 본 이유는, 결국 에이전트 품질도 명세 품질에 종속된다는 걸 아주 노골적으로 드러내기 때문이다. AI가 애매한 요구를 알아서 잘 해석해줄 거라는 기대는 아직 비싸고 불안정하다. 차라리 합의 가능한 행동 기준으로 잘게 잘라두는 게 낫다.

 

모델이 좋아지면 하네스는 오히려 줄어든다

 

이 대목은 개인적으로 꽤 중요했다. 많은 팀이 하네스를 만들기 시작하면, 시간이 갈수록 규칙과 훅과 에이전트 수를 계속 늘리는 방향으로 간다. 잘 안 되면 하나 더 붙이고, 또 안 되면 체크 하나 더 붙인다. 그렇게 복잡도가 쌓인다.

 

그런데 Anthropic이 보여준 방향은 반대다. 초기 모델에서는 스프린트 분해와 다중 검증 구조가 필수였지만, 모델이 개선되면서 일부 구조를 걷어낼 수 있었다. 평가 단계를 단일 패스로 줄이고, 분해 구조를 없애도 성능이 유지됐다. 이건 꽤 중요한 태도다. 하네스를 성전처럼 모시지 않는다는 뜻이기 때문이다.

 

좋은 하네스는 영구 불변의 설계가 아니다. 특정 모델의 약점을 메우기 위해 잠깐 존재하는 외골격에 가깝다. 모델이 달라지면 외골격도 달라져야 한다. 그런데 현실에서는 반대로 간다. 예전에 필요했던 룰이 계속 남고, 아무도 왜 있는지 모르는 훅이 저장소에 눌러앉는다. 그러다 어느 순간부터는 모델보다 하네스가 더 피곤해진다.

 

그래서 “하네스를 설계한다”보다 “하네스를 계속 없앤다”는 감각도 필요하다. 이건 실제 운영을 해본 팀만 갖게 되는 태도 같다.

 

Brain, Hands, Session으로 분리한 건 성능보다 안전 때문이다

 

2026년 4월에 공개된 Managed Agents 구조는 한 걸음 더 나간다. 여기서는 아예 시스템을 셋으로 찢는다. Brain은 판단한다. Hands는 실행한다. Session은 기억한다. 이걸 읽으면서 든 첫 느낌은 “이제야 운영 시스템처럼 보인다”였다.

 

기존 모놀리식 에이전트는 편하긴 하다. 모델, 도구, 실행 환경, 상태가 한 컨테이너 안에 다 있으면 구현은 빠르다. 그런데 운영은 곧장 힘들어진다. 스케일링이 어려워지고, 장애가 나면 한 덩어리로 무너지고, 보안 표면도 넓어진다. 특히 자격 증명이 들어 있는 환경과 모델이 같은 공간에 있으면 프롬프트 인젝션 한 방으로 민감한 값이 새어 나갈 수 있다. 이건 이론적인 걱정이 아니라 구조적인 문제다.

 

Brain과 Hands를 나누면 상황이 달라진다. 실행 환경은 필요할 때만 잠깐 뜨고, 상태도 없고, 장기 자격 증명에 접근하지 못한다. 세션 기억은 append-only 로그로 밖에 남는다. 그러면 컨테이너를 계속 들고 있을 필요도 없고, 장애가 나도 새 인스턴스가 마지막 이벤트부터 다시 이어받을 수 있다.

 

이 구조가 좋은 이유는 “머리가 똑똑해서”가 아니라 “죽어도 다시 일어나기 쉬워서”다. 실무 시스템은 결국 그게 중요하다. 한 번에 천재처럼 푸는 것보다, 중간에 넘어져도 복구 가능한 쪽이 더 오래 간다.

 

OpenAI Codex 팀 사례가 더 와닿는 이유

 

Anthropic 쪽 자료가 설계와 원칙을 잘 보여준다면, OpenAI Codex 팀 이야기는 훨씬 거칠고 실전적이다. 5개월 동안 사람이 코드를 직접 타이핑하지 않고 개발했다는 설정부터 이미 무리수처럼 들린다. 그런데 결과 숫자를 보면 그냥 장난은 아니었다. 3명으로 약 100만 줄, 1500개 PR, 체감 속도 10배. 수치만 놓고 보면 거의 과장처럼 읽힌다.

 

근데 더 중요한 건 초반에 잘 안 됐다는 얘기다. 환경 설정이 부족했고, 도구 연결도 미완성이었고, 에러 복구도 약했다. 그러니까 처음부터 모델이 미친 듯이 잘한 게 아니었다. 오히려 하네스를 손볼수록 생산성이 나중에 폭발했다.

 

이건 꽤 냉정한 메시지다. 많은 팀이 에이전트를 붙여보고 “별로인데?” 하고 접는 이유가 모델 성능 탓이라고 생각한다. 실제로는 작업 환경이 너무 허술한 경우가 많다. 저장소 구조가 엉망이고, 테스트가 약하고, 지침은 거대한 문서 한 장으로 뭉쳐 있고, 실패했을 때 돌아오는 피드백은 막연하다. 이런 상태에서는 사람도 느리다. 하물며 모델은 더 심하게 망가진다.

 

Codex 팀이 “1000페이지 매뉴얼 대신 지도를 줘라”라고 한 이유도 여기 있다. 하나의 AGENTS.md 파일에 모든 규칙을 몰아넣으면, 결국 아무 것도 전달되지 않는다. 모든 게 중요하다고 써 있으면 실제로는 아무 것도 중요하지 않은 상태가 된다. 그래서 문서를 디렉토리 구조로 흩어놓고, 필요한 맥락만 찾아가게 만드는 방식이 더 낫다. 이것도 결국 컨텍스트를 아껴 쓰는 설계다.

 

프롬프트보다 더 강한 건 기계적 강제였다

 

OpenAI 팀 사례에서 가장 마음에 남는 건 “Mechanical Enforcement”라는 표현이다. 프롬프트로 아무리 “이렇게 코딩하세요”라고 타이르더라도, 결국 위반을 진짜로 막아주는 건 린터와 테스트와 구조 검증이다.

 

이건 정말 실무적이다. 에이전트에게 아키텍처 원칙을 백 번 설명하는 것보다, 금지된 의존성 방향이 나오면 빌드를 깨버리는 쪽이 낫다. 더 좋았던 건, 실패 메시지 안에 수정 방향까지 넣는 방식이다. 그러면 에이전트는 추상적인 질책이 아니라 바로 적용 가능한 피드백을 받는다. “틀렸음”이 아니라 “이 방향으로 고치면 통과함”이 되는 셈이다.

 

여기서 하네스와 프롬프트 엔지니어링의 차이가 분명해진다. 프롬프트 엔지니어링은 설득이고, 하네스는 구조다. 설득은 잘될 때도 있지만 흔들린다. 구조는 귀찮아도 더 버틴다.

 

그리고 코드 가비지 컬렉션 얘기도 재밌다. 에이전트가 코드를 빠르게 쏟아내면 안 좋은 패턴도 같이 증식한다. 이걸 사람이 일일이 청소하면 결국 사람 병목이 생긴다. 그래서 아예 백그라운드 청소 에이전트를 둬서 오래된 패턴, 문서와 어긋난 코드, 기술 부채를 계속 정리하게 했다. 이 발상은 좀 무섭기도 하고, 동시에 너무 현실적이기도 하다. 생산성만 밀어붙이면 저장소는 반드시 더러워진다. 그러면 언젠가 그 이자를 누가 갚아야 한다.

 

개발자는 이제 직접 고치는 사람보다 구조를 조정하는 사람에 가까워진다

 

이쯤 되면 개발자 역할이 달라지는 건 자연스럽다. 예전에는 AI가 만든 결과물을 사람이 직접 고치는 쪽, 즉 Human in the Loop가 중심이었다면, 지금은 Human on the Loop 쪽으로 이동하고 있다는 말이 왜 나오는지 이해가 된다.

 

중요한 건 코드 한 줄을 대신 치는 게 아니다. 왜 이런 결과가 나왔는지 보고, 다음에는 같은 실수가 안 나오게 구조를 조정하는 일이다. 테스트가 약했는지, 컨텍스트 분리가 부족했는지, 승인 정책이 느슨했는지, 피드백 문구가 모호했는지를 보는 쪽이다.

 

이건 개발자가 더 위로 올라간다는 뜻이라기보다, 책임의 성격이 바뀐다는 뜻에 가깝다. 직접 구현하는 손의 비중은 줄고, 시스템을 튜닝하는 감각의 비중이 커진다. 솔직히 말하면, 이건 재밌기도 하지만 꽤 피곤한 역할이다. 결과가 구리면 AI 탓을 할 수가 없기 때문이다. 결국 “왜 이런 출력을 허용했지?”라는 질문이 내 쪽으로 돌아온다.

 

하네스가 만능이라는 말은 아니다

 

여기까지 읽으면 “결국 하네스만 잘 짜면 되는 거네”라고 받아들일 수도 있다. 그런데 그건 또 아니다. 아직 프로덕션 코딩에서 AI 에이전트 적용 비율이 높지 않다는 통계도 있고, 실제 사고 사례도 적지 않다. 운영 환경 삭제, 대규모 주문 손실, 검증되지 않은 생성 코드로 인한 장애 같은 이야기는 과장용 에피소드가 아니라 현실 체크에 가깝다.

 

그리고 또 하나, 하네스 자체가 과잉 설계되는 문제도 있다. 에이전트 수십 개, 스킬 수백 개, 규칙 수십 개, 훅 수십 개로 불어난 설정은 웅장해 보이지만 실제로는 관리 비용이 엄청나다. 표면적이 넓어질수록 컨텍스트는 더 빨리 닳고, 디버깅은 더 어려워지고, 어느 순간부터는 모델보다 설정 파일이 더 복잡해진다. Anthropic이 하네스를 “거대한 아키텍처 설계”보다 “미세 조정”의 관점에서 보라고 한 이유가 바로 여기 있을 거다.

 

나도 이 부분은 꽤 공감했다. 이런 시스템은 자꾸 크게 만들고 싶어진다. 뭔가 체계적으로 보이기 때문이다. 그런데 실제로 오래 가는 건 오히려 작은 규칙 몇 개, 명확한 로그, 강한 테스트, 복구 쉬운 상태 관리 같은 것들이다. 화려한 멀티 에이전트보다 이런 기본기가 더 오래 버틴다.

 

결국 남는 건 하나다. 내 프로젝트에서는 어디까지 할 것인가

 

Anthropic과 OpenAI 사례를 같이 보면 방향은 분명하다. AI 에이전트 품질은 모델 성능만으로 설명되지 않는다. 루프를 어떻게 끊을지, 상태를 어디에 둘지, 검증을 어떤 식으로 강제할지, 실패했을 때 어떻게 다시 이어붙일지가 결과를 더 크게 바꾼다.

 

그렇다고 이 구조를 통째로 복사해서 내 프로젝트에 붙인다고 바로 좋아지지는 않는다. 대부분 팀은 Brain, Hands, Session 아키텍처부터 들어갈 필요가 없다. 오히려 그 전에 더 싸고 효과 큰 일들이 있다. 작업 로그를 파일로 남기기, 기능 체크리스트를 구조화하기, 테스트 실패 메시지를 더 구체적으로 바꾸기, 긴 작업을 세션 단위로 끊기, 위험한 도구 호출에 승인 절차 넣기. 이런 것들이 먼저다.

 

하네스 엔지니어링을 멋진 개념처럼 다루면 자꾸 멀어진다. 그런데 실무에서는 의외로 소박한 데서 시작한다. 작업 전에 경로를 확인하고, 로그를 읽고, 테스트를 돌리고, 한 번에 하나만 끝내고, 끝나면 상태를 남기는 것. 그런 사소한 절차를 모델이 매번 지키게 만드는 것. 결국 그게 에이전트를 “똑똑한 데모”에서 “쓸 만한 작업 시스템”으로 바꾸는 지점이다.

 

다음으로 넘어가야 할 질문은 어렵지 않다.

 

내 프로젝트에서 지금 당장 넣을 수 있는 가장 작은 하네스는 뭐냐는 것.

 

그 질문부터 시작하는 편이, 거대한 멀티 에이전트 아키텍처 그림을 붙잡는 것보다 훨씬 현실적이다.