요약
이 글은 같은 모델을 써도 에이전트 성능이 갈리는 이유가 모델이 아닌 하네스(모델을 둘러싼 환경 전체)에 있다는 관점에서, 프롬프트·컨텍스트·하네스 엔지니어링의 층위 차이를 구분하고 하네스를 구성하는 핵심 요소들을 다룹니다. 지시 문서(AGENTS.md)와 자동 검사 장치의 결합, 에이전트 바깥의 결정론적 검증, 컴팩션·하위 에이전트·진행파일을 통한 컨텍스트 관리 기법을 설명하며, 작게 시작해 실수할 때마다 한 겹씩 보강해 나가는 5단계 실천 가이드를 함께 제시하는 글입니다.
서론
“같은 모델인데 결과가 다르다.” 요즘 에이전트를 만들어본 사람이라면 한 번쯤 겪는 일입니다. 동일한 LLM을 썼는데도 불구하고 어떤 시스템에서는 작업을 척척 끝내고, 어떤 시스템에서는 같은 자리를 맴돌다 엉뚱한 곳으로 빠집니다. 이 차이를 만든 것은 에이전트 모델이 아니라, 그 모델을 감싸고 있는 하네스(harness)가 취약하고 안전하지 않으며 예측 불가능하기 때문입니다.
하네스라는 용어는 AI 에이전트에서 모델 자체를 제외한 모든 것을 의미하는 약어로 등장했습니다. 즉, 에이전트 = 모델 + 하네스입니다. 조금 더 풀어 보면 도구 실행, 메모리, 컨텍스트 관리, 상태 유지처럼 LLM을 둘러싼 모든 장치를 하네스라고 부를 수 있습니다.
이번 글에서는 하네스가 정확히 무엇이고 어떤 요소로 이루어지는지, 좋은 하네스를 가르는 설계 원칙은 무엇인지, 그리고 실제 사례에서 그것이 어떻게 성능 차이로 드러나는지를 살펴볼 예정입니다.
하네스란 무엇인가
때로는 프롬프트 엔지니어링, 컨텍스트 엔지니어링, 하네스 엔지니어링이 종종 같은 의미처럼 혼용됩니다. 하지만 이 셋은 사실 서로 다른 단계의 작업입니다. 세 층은 서로를 감싸는 동심원에 가깝습니다. 안쪽 층을 아무리 정교하게 다듬어도, 그것을 둘러싼 바깥 층이 부실하면 전체가 무너집니다.

프롬프트 엔지니어링 : 무엇을 말할까
가장 안쪽 층입니다. 모델에게 건네는 지시 그 자체, 즉 단어 선택과 예시, 사고를 유도하는 방식의 문제입니다. 단발성 질의응답이나 짧은 작업에서는 이 층이 품질의 거의 전부를 좌우합니다. 하지만 작업이 길어지고 도구를 쓰기 시작하면, “어떻게 말하느냐”만으로 해결되지 않는 문제들이 빠르게 등장합니다.
컨텍스트 엔지니어링 : 모델이 무엇을 보게 할까
한 단계 바깥 층입니다. 어느 순간 모델의 컨텍스트 창에 무엇이 들어가 있고 무엇이 빠져 있는가를 다룹니다. 핵심은 많이 넣을수록 좋은 것이 아니라는 점입니다. AI 애플리케이션을 위한 검색 · retrieval 용 오픈소스 벡터 데이터베이스를 만드는 회사인 Chroma의 2025년 연구 결과, 18개 최신 AI 모델을 대상으로 실험했더니 입력 길이가 늘어날수록 성능이 점점 불안정해졌다고 합니다. 관련 없는 정보가 1개만 추가되어도 성능이 크게 하락하고, 4개 추가 시 급락한다는 것을 발견했습니다. 컨텍스트는 채우는 것이 아니라 관리하는 자원입니다.
하네스 엔지니어링 : 모델이 어떤 환경에서 행동할까
가장 바깥 층입니다. 모델이 어떤 루프 안에서 돌고, 어떤 도구를 손에 쥐며, 행동의 결과를 어떻게 관찰하고, 실패했을 때 어떻게 회복하며, 언제 작업을 끝내는가와 같이 모델이 행동하는 무대 전체를 설계하는 일입니다.이 차이가 극명하게 드러나는 곳은 장기 실행 작업입니다. 모델은 본래 한 번의 호출이 끝나면 그전의 일을 스스로 기억하지 못합니다. 그래서 세션이 바뀌거나 컨텍스트가 가득 찰 때 “지금까지 무엇을 했고 다음에 무엇을 해야 하는지”를 다시 넘겨주는 구조를 누군가는 설계해야 하죠. 그 인수인계 구조까지 포함한 환경 전체가 하네스입니다.
하네스를 구성하는 요소

1. 지시 문서
AI 에이전트는 세션이 끝나면 모든 것을 잊습니다. 같은 프로젝트에 대해 어제 알려준 컨벤션을 오늘 또 알려줘야 한다는 뜻입니다. 이 문제를 해결하는 가장 단순하고 강력한 방법은 레포지토리 루트에 AGENTS.md라는 마크다운 파일을 두고 에이전트가 매 세션 시작 시 자동으로 읽게 하는 것입니다. 사람을 위한 문서가 README.md라면, AGENTS.md는 에이전트를 위한 README인 셈입니다. (Claude Code는 AGENTS.md가 아니라 CLAUDE.md를 사용합니다.)
표준에서 권장하는 기본 구성은 프로젝트 개요, 빌드·테스트 명령, 코드 스타일 가이드, 테스트 지침, 보안 고려사항입니다. 여기에 더해, 이전 에이전트 세션에서 발견한 안티 패턴(반복해서 저지르는 실수) 목록을 함께 두면 좋습니다.
지시 문서의 핵심 원칙은 처음부터 완벽한 문서를 쓰는 것이 아닙니다. HashiCorp 공동창업자이자 Terraform · Ghostty 제작자인 Mitchell Hashimoto는 다음과 같이 말했습니다. “에이전트가 실수할 때마다, 그 특정 실수를 다시는 못 하게 만드는 무언가를 만들어라.” 첫 문서는 짧게 시작하여, 에이전트가 실수할 때마다 한 줄씩 추가해 나가는 것입니다.
다만 규칙을 끝없이 덧붙이다 보면 파일이 서로 충돌하는 규칙이 뒤섞여 오히려 에이전트 성능을 해치게 됩니다. 그래서 자세한 내용은 별도 문서로 빼고, 지시 문서에는 진짜 필요한 것만 남겨야 합니다.
2. 자동 규칙 검사 도구와 구조 테스트
지시 문서에 규칙을 적어두는 것이 그 규칙이 반드시 지켜진다는 뜻은 아닙니다. 에이전트는 규칙을 읽을 수 있지만, 긴 작업 중 맥락을 놓치거나 잘못 판단하면 얼마든지 어길 수 있습니다. 그렇다면 규칙이 실제로 지켜지는지 어떻게 확인하고, 위반을 어떻게 사전에 막을까요?
Hashimoto는 표준 위반 시 PR을 차단하는 자동 검사 장치를 연결하라고 권했습니다. 지시 문서를 작성하는 것은 에이전트가 잘 지켜주리라 기대하는 방식이고, 검사 장치를 연결하는 것은 지키지 않으면 통과 자체를 허용하지 않는 방식이라는 것이죠.
자동 검사 장치에는 대표적으로 다음이 있습니다.
- Linter : 코드가 정해진 스타일·구조·명명 규칙을 따르는지 자동으로 검사하고, 어기면 에러를 냅니다.
- Pre-commit Hooks : 커밋하려는 시점에 린터·포매터·검사 항목이 자동 실행되고, 통과하지 못하면 커밋이 거부됩니다.
- Custom 검증 스크립트 : 의존성 방향, 파일 크기, 보안 규정 등 해당 프로젝트에만 적용되는 규칙을 검사하도록 직접 작성한 점검 항목입니다.
- Test suite : 변경된 코드가 실제로 의도대로 동작하는지 자동으로 검증합니다
규칙을 문서에만 적어두면 에이전트가 어겨도 걸러지지 않고, 자동 검사만 있으면 에이전트는 왜 막혔는지 모른 채 같은 실수를 반복합니다. 작업이 차단되는 동시에 무엇이 잘못됐는지 알려주는 오류 메시지가 함께 돌아올 때, 에이전트는 그 피드백을 읽고 스스로 수정할 수 있습니다. AGENTS.md와 자동 검사 장치가 짝을 이룰 때 비로소 에이전트가 스스로 학습하며 개선되는 환경이 완성됩니다.
3. 자동화 파이프라인과 자동화 테스트
LangChain이 2026년 2월 실험에서 확인한 가장 흔한 에이전트 실패 패턴이 있습니다. 에이전트가 결과물을 만든 뒤, 스스로 검토하고 “괜찮다”라고 판단한 다음 거기서 멈추는 것입니다.
그래서 자동화 테스트의 핵심은 에이전트가 자기 결과물을 스스로 검증하게 두지 않고, 에이전트 바깥의 기준으로 검증하도록 하는 것입니다. 사람으로 치면, 보고서를 쓴 사람에게 그 보고서를 검토시키는 대신 제3자에게 맡기는 것과 같습니다. 왜 스스로 검증하면 안 될까요?
- 같은 컨텍스트의 한계 : 검토를 맡은 AI는 직전에 자기가 생성한 내용을 그대로 기억하고 있습니다. 그래서 작성할 때 빠뜨린 부분은 검토할 때도 똑같이 눈에 들어오지 않습니다.
- 같은 편향의 반복 : 초안을 쓸 때 깔고 간 전제가 검토 시점에도 그대로 유지됩니다. 애초에 방향을 잘못 잡았더라도, 검토 단계에서 이 방향이 맞다고 판단해 버립니다. 잘못된 출발점 자체를 의심하지 못하는 것입니다.
- 자기 보호 경향 : LLM은 자기가 만든 결과물을 방어하려는 성향이 있습니다. 검토를 시키면 문제를 찾아내기보다, 그럴듯한 이유를 붙여 이대로 괜찮다고 정당화하는 쪽으로 기웁니다.
그래서 필요한 것이 외부의 결정론적 검증입니다. ‘결정론적’이라는 건 같은 입력에는 늘 같은 결과를 내고, 그때그때의 판단이나 분위기에 흔들리지 않는다는 뜻입니다. 누군가의 의견이 아니라 정해진 기준에 따라 통과/실패가 명확히 갈리는 검사를 말합니다. 외부 검증을 실제로 붙이는 방법은 생성과 검토의 컨텍스트를 얼마나 분리하느냐에 따라 세 단계로 나뉩니다. 단계가 올라갈수록 앞서 본 자가 검증의 함정에서 더 멀어집니다.
- 단일 루프 : 같은 모델·같은 세션을 쓰되, 초안 생성이 끝나면 검토용 시스템 프롬프트로 역할을 전환합니다. 핵심은 검토 프롬프트를 명시적 기준으로 주는 것입니다. 예를 들어 “지금부터 검토자 역할을 맡는다. 다음 5개 기준 각각에 대해 pass/fail과 근거를 JSON으로 출력하라”처럼 강제합니다. 다만 같은 컨텍스트 윈도우(직전 생성 이력)를 공유하므로 같은 컨텍스트의 한계와 같은 편향의 반복은 완전히 깨지 못합니다. 가장 가볍지만 효과도 제한적입니다.
- 이중 루프 : 생성 호출과 검토 호출을 완전히 분리합니다. 검토 호출에는 생성 당시의 대화 이력을 넘기지 않고, 결과물과 명세(기준)만 새 컨텍스트에 넣습니다(LLM-as-judge 패턴). 같은 모델이라도 새 세션·새 컨텍스트로 열면 자기 보호 경향이 약해지고, 아예 다른 모델로 교차 검토하면 같은 편향의 반복까지 줄어듭니다.
- 자동화 루프 : 생성 → 검토 → 분기 → 수정·재생성의 흐름을 사람 개입 없이 코드로 연결합니다. 오케스트레이션 프레임워크(예: LangGraph), CI 파이프라인, 평가 하네스로 엮으면, 어떤 단계를 어떤 순서로 실행할지 직접 정해 둘 수 있고, 같은 설정으로 다시 돌리면 같은 결과가 나와 원인 추적과 전후 비교가 쉬워집니다. 이때 검토 단계는 LLM 판정에만 맡기지 않고 결정론적 검사(테스트 실행, 스키마·타입 검증, lint, 명세 충족 여부)도 반드시 통과해야만 다음 단계로 넘어가게 막아둡니다.
LLM-as-judge 패턴
LLM-as-judge는 한 LLM이 만든 결과물을 별도의 LLM에게 정해진 기준에 따라 채점·판정하게 하는 패턴입니다. 사람이 일일이 평가하기 어려운 출력의 품질·정확성·기준 충족 여부를 자동으로, 대규모로 검사할 때 씁니다.
핵심은 평가자에게 생성 당시의 맥락을 넘기지 않고 결과물과 명세만 새 컨텍스트로 줘서, 생성자의 편향과 자기 보호 경향을 차단하는 것입니다. “잘 됐나?”가 아니라 “이 기준 각각을 통과했는가”를 pass/fail과 근거로 출력하게 해야 신뢰도가 올라갑니다. 다만 LLM 판정 자체도 편향·일관성 한계가 있어, 결정론적 검사(테스트, 스키마 검증 등)와 함께 쓰는 것이 안전합니다.
4. 컨텍스트 관리
컨텍스트 윈도우는 모델이 한 번에 펼쳐 놓고 추론할 수 있는 정보의 총량입니다. 유한하고, 빠르게 오염되며, 다 채우면 품질이 떨어지는 작업 공간입니다. 그래서 좋은 에이전트는 컨텍스트를 더 크게 키우는 데서 나오는 게 아니라 더 깨끗하게 관리하는 데서 나옵니다. 컨텍스트는 결국 토큰이고, 토큰은 비용이자 응답 지연(latency)이기 때문에, 이 관리 방식은 곧바로 품질·속도·비용·안정성으로 이어집니다.
AI 애플리케이션을 위한 검색·retrieval용 오픈소스 벡터 데이터베이스를 만드는 회사인 Chroma의 2025년 연구 결과, 18개 최신 AI 모델을 대상으로 실험했더니 입력 길이가 늘어날수록 성능이 점점 불안정해졌다고 합니다. 방해 정보가 많을수록 컨텍스트 부패가 가속된다는 사실도 확인 되었습니다. Chroma의 연구에선 관련 없는 정보가 1개만 추가되어도 성능이 크게 하락하고, 4개 추가 시 급락한다는 것을 발견 했습니다. 앞서 말씀드렸듯이, Chroma의 연구는 18개 최신 모델 모두에서 입력이 길어질수록 단순한 작업에서조차 신뢰도가 떨어진다는 것을 보여주었습니다.
Anthropic 엔지니어링 팀이 장기 실행 에이전트를 연구하며 발견한 또 하나의 현상, 컨텍스트 불안(Context Anxiety)은 모델이 컨텍스트 윈도우 한계에 가까워졌다고 느끼면, 작업이 끝나지 않았는데도 서둘러 마무리하려는 경향을 보입니다.
컴팩션 (대화 요약·축소)
하나의 긴 대화로 모든 것을 처리하려는 것이 컨텍스트 부패의 가장 큰 원인입니다. 컴팩션은 지금까지의 대화 중 핵심 결과를 자동으로 요약·압축하고, 그 요약본을 새 컨텍스트의 시작점으로 삼는 방식입니다. Claude Code에는 /compact 명령으로 수동 실행하거나 윈도우 한계가 임박하면 자동으로 작동하는 컴팩션이 내장돼 있습니다.
언제 컴팩션을 실행할지에 대한 기준이 있습니다. 작업의 성격이 바뀌는 지점이 자연스러운 분할선입니다. 같은 종류의 작업은 하나의 컨텍스트 안에서 이어가고, 다른 종류의 작업이 시작할 때 새 컨텍스트를 엽니다.
하위 에이전트
메인 에이전트가 무거운 탐색·분석 작업을 별도 컨텍스트를 가진 다른 에이전트에게 위임하고, 압축된 결과만 돌려받는 방식입니다.
예를 들어 “이 코드 베이스에서 인증 관련 함수를 모두 찾아줘” 같은 작업을 메인 에이전트가 직접 처리하면, 수십 개 파일 내용이 메인 컨텍스트에 쌓여 오염시킵니다. 이걸 하위 에이전트에게 맡기면, 그쪽이 자기만의 독립된 창에서 다 뒤지고 “관련 함수 5개와 위치 목록” 같은 정제된 결과만 반환합니다. 탐색 과정에서 쌓인 불필요한 내용은 그쪽 창에 남고, 메인 컨텍스트는 깨끗하게 유지됩니다. 이는 일종의 함수 호출 + 반환값(return value) 구조입니다. 함수 안에서 무슨 일이 있었든 호출자에게 남는 것은 반환된 값 뿐인 것과 같습니다.
진행파일 (progress file)
Anthropic 엔지니어링 팀은 장기 실행 에이전트의 핵심 문제를 이렇게 정의했습니다. “각 새 세션은 이전 맥락 없이 시작된다. 교대 근무하는 엔지니어가 이전 교대에서 무슨 일이 있었는지 모르는 것과 같다.” 팀은 이를 “교대 인수인계 문제”라고 이름 붙였습니다. 해결책으로 도입한 것이 진행파일(progress file)입니다. 진행 상황을 모델의 기억(컨텍스트)에 담아두는 대신, 컨텍스트 밖 파일에 적어두고 필요할 때 다시 읽는 방식입니다. PROGRESS.md, TODO, git 커밋 같은 산출물에 무엇을 했고 다음에 무엇을 할지를 기록해 두면, 컨텍스트를 일종의 장기 기억처럼 쓸 수 있습니다. 처음 만나는 교대 팀원에게 인수인계 노트를 건네는 것과 같습니다.
이 방식이 중요한 이유는, 컨텍스트는 비워지거나 리셋돼도 파일은 남기 때문입니다. 컴팩션이 일어나든 하위 에이전트로 작업이 넘어가든, 진행 파일이 있으면 기억은 끊겨도 작업은 끊기지 않습니다.
컨텍스트 엔지니어링
위의 기법들을 아우르는 더 큰 개념이 컨텍스트 엔지니어링입니다. 매 세션이 끝날 때, 이번 세션에서 발견한 새로운 패턴이나 실수를 지시 파일에 추가하는 것입니다. 진행 파일이 이번 프로젝트의 현재 상태를 담는다면, 지시 파일 갱신은 이 AI와 일하면서 알게 된 영구적 규칙을 쌓는 것입니다. 핵심은 모델에게 주는 정보 중에서 답에 도움이 되는 내용의 비율을 최대한 높이고 도움이 안 되는 내용은 줄이는 것입니다.
개발자를 위한 실천 가이드
하네스는 한 번에 완성되는 설계가 아닙니다. 작은 토대를 하나 깔고, 측정하고, 실패에서 배운 것들을 다시 토대에 새기는 일을 반복하며 단단해집니다.
1단계. 가장 작게 시작한다
첫걸음은 AGENTS.md 한 장입니다. 완벽한 문서일 필요 없이, 역할·형식·금지 정도만 적은 짧은 초안으로 시작합니다.
# 역할
[프로젝트 맥락, 기술 스택, 에이전트가 맡는 작업 범위와 경계]
예: "CMake로 빌드 하는 C++11 라이브러리의 코딩 에이전트. 기능 추가·버그 수정 담당, 빌드 설정(CMakeLists.txt)·CI는 변경 금지."
# 형식
[코드 스타일, 디렉터리 구조, 커밋·PR 규칙, 완료 기준]
예: "스타일은 .clang-format을 따르고(헤더 .hpp / 소스 .cpp), 변경마다 테스트를 추가해 `-std=c++11 -Wall -Wextra` 빌드·clang-tidy·ctest를 통과시킨 뒤 마친다."
# 금지
[절대 하지 말아야 할 변경이나 패턴]
예: "수동 new/delete·C 스타일 캐스트·헤더 내 using namespace std 금지(RAII와 스마트 포인터 사용)"
# 참고
[AI가 참조해야 할 자료나 기준]
예: "코딩 컨벤션은 docs/STYLE.md, 모범 구조는 src/core/를 기준으로 삼는다."
# 주의
[반복되는 실수와 방지 규칙]
처음에는 비워 둔다. 실수가 생길 때마다 한 줄씩 추가한다.
지시가 많아질수록 준수 품질은 떨어지므로, 늘어난 규칙은 주기적으로 별도 문서로 빼고 핵심만 앞에 남깁니다.
2단계. 검증을 모델 바깥에 붙인다
거창한 CI가 아니라, 이미 쓰고 있는 린터나 테스트 하나를 통과하지 못하면 작업이 막히도록 거는 것으로 충분합니다. 규칙 위반 시 차단과 동시에 무엇이 왜 막혔는지 알려주는 오류 메시지가 에이전트에게 돌아와야 스스로 고칩니다.
3단계. 길어지는 작업은 컨텍스트를 관리한다
작업이 여러 세션에 걸치기 시작하면 컨텍스트 관리가 본론이 됩니다. 작업의 성격이 바뀌는 지점을 자연스러운 분할선으로 삼아, 같은 종류의 작업은 한 컨텍스트에서 이어가고 다른 작업이 시작될 때 요약 후 새 컨텍스트를 열도록 합니다 (컴팩션). 진행 상황은 모델의 기억이 아니라 PROGRESS.md · TODO · git 커밋처럼 컨텍스트 바깥에 적어둬, 세션이 바뀌어도 작업이 끊기지 않게 인수인계합니다.
4단계. 무엇을 측정할지 정한다
측정하지 않는 것은 개선할 수 없습니다. 하네스의 효과는 같은 모델을 고정한 채 하네스만 바꿔 비교할 때 가장 선명하게 드러납니다. 하네스를 손보기 전, 먼저 기준선을 잡아야 어떤 변경이 실제로 효과가 있는지 판단할 수 있습니다. 추적하기 좋은 지표는 작업 완료율, 작업당 단계 수, 토큰 사용량과 비용, 응답 지연, 같은 실수를 스스로 바로잡을 비율 등입니다.
5단계. 반복해서 개선한다
개선의 엔진은 Hashimoto의 원칙 그대로입니다. 에이전트가 실수할 때마다, 그 실수를 다시 못하게 만드는 무언가를 만든다. 매 세션이 끝날 때, 이번에 발견한 새 패턴이나 반복된 실수를 지시 파일에 한 줄씩 반영합니다. 진행 파일이 이번 프로젝트의 현재 상태를 담는다면, 지시 파일 갱신은 이 에이전트와 일하며 알게 된 영구적 규칙을 쌓는 것입니다. 이 과정이 돌기 시작하면 하네스는 쓸수록 똑똑해집니다.
마무리
저희는 이제 “같은 모델인데 결과가 다른” 이유를 알게 되었습니다. 답은 모델이 아니라 하네스, 즉 모델을 둘러싼 환경 전체의 설계에 있습니다. 모델의 성능이 빠르게 평준화되는 지금, 무게중심은 점점 하네스 쪽으로 옮겨가고 있습니다.
좋은 하네스는 환경을 읽기 쉽게 만들고, 검증을 모델 바깥의 결정론적 기준에 맡기며, 컨텍스트를 깨끗하게 관리합니다. 그리고 한 번에 완성되지 않습니다. 짧은 지시 문서 한 장에서 시작해, 실수할 때마다 한 겹씩 단단해집니다. 오늘 만든 그 한 장이, 내일의 에이전트가 일하는 무대가 됩니다.
출처
- Harness engineering vs prompt engineering vs context engineering
- Effective context engineering for AI agents
- ChromaDB: Context Rot: Evaluating LLM Performance Degradation with Increasing Input Tokens – ZenML LLMOps Database
- Harness design for long-running application development
- 3. 하네스 구성요소
- Better Model vs. Better Harness — Which One Actually Moves Your Agent’s Benchmark Score?