Repository Harness, 파트 2: 30번의 실행 결과, 더 저렴해지지는 않았지만 더 예측 가능해졌다.
요약
코딩 에이전트의 컨텍스트 효율성을 높이기 위한 Repository Harness 벤치마크의 두 번째 실험 결과를 다룹니다. 저장소 지식을 모듈화하고 라우팅 규칙을 정교화하여, 토큰 비용 절감보다는 에이전트 동작의 예측 가능성을 높이는 데 성공했습니다.
핵심 포인트
- Repository Harness는 저장소 지식을 작은 진입점과 라우팅된 컨텍스트로 분리함
- 단순한 라벨링 대신 디렉토리 범위와 컨텍스트 예산 등 엄격한 라우팅 규칙 도입
- 실험 결과, 토큰 사용량의 극적인 감소보다 에이전트 동작의 예측 가능성 향상이 핵심 성과임
- 모듈화된 저장소 지식 전달을 통해 불필요한 컨텍스트 로딩 문제 해결 시도
이 글은 Coding Agents Evolved. Our Repositories Didn’t.의 후속편입니다.
저의 첫 번째 Repository Harness 벤치마크는 불편한 결과를 낳았습니다.
Harness는 단일 파일 형태인 AGENTS.md보다 작업을 더 빠르게 완료했지만, 더 많은 새로운 입력 토큰 (input tokens)을 사용했습니다.
이는 아이디어가 틀렸다는 의미일 수도 있었습니다.
또는 저의 첫 번째 점진적 공개 (progressive disclosure) 구현이 충분히 엄격하지 않았다는 의미일 수도 있었습니다.
그래서 저는 라우팅 모델 (routing model)을 변경하고, 벤치마크 베이스라인 (baseline)을 다시 구축한 뒤 실험을 다시 수행했습니다.
이번에는 30번의 측정된 실행 (measured executions)을 수행했습니다.
결과는 토큰 사용량의 극적인 감소가 아니었습니다.
그보다 더 유용한 것이었습니다:
Repository Harness는 에이전트 (agent)의 동작을 실질적으로 훨씬 더 예측 가능하게 만들었습니다.
아이디어
대부분의 저장소 (repositories)는 다음과 같은 것들의 혼합을 통해 지식을 노출합니다:
- README 파일;
- 아키텍처 문서 (architecture documents);
- 기여 가이드 (contribution guides);
- 스크립트 (scripts);
- 암묵적 지식 (tribal knowledge);
- 점점 더 커지는 하나의
AGENTS.md.
단일 파일 형태의 지침 파일도 작동은 하지만, 대부분의 내용이 무관한 경우에도 모든 작업이 저장소 핸드북 전체를 전달받게 됩니다.
Repository Harness는 해당 모델을 작은 진입점 (entry point)과 라우팅된 컨텍스트 (routed context)로 대체합니다:
AGENTS.md
↓
.harness/
...
루트 파일은 Harness를 사용하는 방법을 설명합니다.
매니페스트 (manifest)는 작업을 분류하고 해당 작업에 필요한 저장소 가이드를 선택합니다.
원래의 가설은 다음과 같았습니다:
선택적 컨텍스트 라우팅 (Selective context routing)은 불필요한 컨텍스트를 줄이면서 구현 품질을 유지해야 한다.
첫 번째 벤치마크는 이를 증명하지 못했습니다.
버전 2에서 변경된 점
첫 번째 Harness는 다음과 같이 광범위한 로딩 규칙을 사용했습니다:
load_when:
- implementation
- feature
...
이러한 라벨들은 너무 일반적이었습니다.
거의 모든 코딩 작업은 구현 (implementation)입니다. 많은 작업은 기능 (feature)입니다. 완료된 모든 작업에는 검증 (validation)이 필요합니다.
따라서 에이전트는 대부분의 문서를 로드할 만한 합리적인 동기를 갖게 되었습니다.
저는 저장소 지식 (repository knowledge)을 모듈화했습니다.
엄격한 라우팅 (routing)을 생성하지는 않았습니다.
두 번째 버전에서는 다음 항목들이 추가되었습니다:
- 저장소 정의 관심사 (repository-defined concerns)
- 디렉토리 범위 (directory scopes)
- 필수 및 선택적 컨텍스트 (required and optional context)
- 에스컬레이션 규칙 (escalation rules)
- 컨텍스트 예산 (context budgets)
- 경로별 검증 (route-specific validation)
해당 라우팅이 어떻게 동작하는지 설명하기 전에, 실험에 사용된 저장소를 이해하는 것이 도움이 됩니다.
벤치마크 프로젝트
벤치마크에는 Godot와 C#으로 구축된 실제 게임 프로젝트를 사용했습니다.
과제는 카메라 컨트롤과 관련된 게임플레이 입력 (gameplay-input) 변경이었습니다.
에이전트는 다음을 수행해야 했습니다:
- 게임패드 줌 (zoom) 기능을 트리거 (triggers)에서 수직 오른쪽 스틱 축으로 이동
- 수평 오른쪽 스틱 회전 유지
- 마우스 휠 줌 유지
- 수평 마우스 이동 회전 추가
- 관련 프롬프트 (prompts) 및 테스트 업데이트
- 게임플레이 및 메뉴가 망가지는 것을 방지
이 저장소는 다음과 같은 다양한 종류의 지식을 포함하고 있었기에 실험에 유용했습니다:
Godot 및 게임플레이 컨벤션 (conventions)
일반적인 엔지니어링 규칙 (engineering rules)
에셋 규칙 (asset rules)
...
카메라 입력 과제는 Godot 전용 가이드가 필요할 것입니다.
에셋 가이드는 필요하지 않을 것입니다.
구현이 아키텍처 경계 (architectural boundary)를 넘는 경우에만 더 넓은 범위의 엔지니어링 가이드가 필요할 것입니다.
이러한 점이 해당 과제를 선택적 라우팅 (selective routing)의 실질적인 테스트로 만들었습니다.
두 가지 변형
저는 동일한 저장소의 격리된 두 가지 버전을 만들었습니다.
모놀리식 (Monolithic) 변형
AGENTS.md
모든 저장소 가이드가 하나의 간결한 루트 문서에 존재했습니다.
Harness 변형
AGENTS.md
.harness/
루트 파일이 진입점 (entry point) 역할을 했습니다.
Harness는 다음을 포함했습니다:
.harness/
├── harness.yaml
├── GODOT.md
...
이 카메라 입력 과제의 경우, 예상된 경로는 다음과 같습니다:
AGENTS.md
+ .harness/harness.yaml
+ .harness/GODOT.md
측정된 15번의 모든 Harness 실행 동안, 에이전트는 관련 없는 엔지니어링이나 에셋 문서를 로드하지 않고 매니페스트 (manifest)와 Godot 전용 가이드를 검사했습니다.
이를 통해 라우팅 메커니즘 자체가 작동하고 있음을 확인했습니다.
남은 질문은 이것이 전체 실행 과정을 개선했는지 여부였습니다.
벤치마크 설계 (Benchmark design)
두 변체(variants) 모두 다음의 동일한 요소를 사용했습니다:
- 코딩 에이전트 (coding agent)
- 모델 (model)
- 소스 코드 베이스라인 (source-code baseline)
- 구현 프롬프트 (implementation prompt)
- 테스트 스위트 (test suite)
- 수락 기준 (acceptance criteria)
저는 다음과 같이 실행했습니다:
변체당 3회의 웜업 (warm-ups)
변체당 15회의 측정 실행 (measured runs)
총 30회의 측정 실행
실행 순서는 변체 간에 교차되었습니다.
프롬프트는 모든 실행에서 동일했습니다.
각 저장소(repository)는 깨끗하고 고정된 커밋(frozen commit) 상태에서 시작되었습니다.
모든 측정된 실행은 벤치마크 수락 기준을 충족했습니다.
AGENTS: 15/15 수락
HARNESS: 15/15 수락
Harness는 신뢰성을 저하시키지 않았습니다.
평균 결과는 거의 대등했습니다
| 지표 (Metric) | AGENTS | Harness | Harness 차이 |
|---|---|---|---|
| 지속 시간 (Duration) | 188.36 s | 185.61 s | -1.46% |
| ... |
Harness가 약간 더 빨랐습니다.
Harness는 캐시되지 않은 입력 토큰 (uncached input tokens)을 약간 적게 사용했고 출력량도 더 적었습니다.
또한 총 입력 토큰 (total input tokens)은 더 많이 사용했고 실패한 명령 (failed commands)도 더 많이 실행했습니다.
이러한 평균값의 차이 중 어느 것도 Harness가 확실히 더 빠르거나 저렴하다고 강력하게 주장할 수 있을 만큼 크지는 않았습니다.
솔직한 결론은 다음과 같습니다:
평균 효율성은 거의 대등했습니다.
그것이 가장 중요한 결과는 아니었습니다.
라우팅된 컨텍스트 (routed context)는 아주 약간만 더 작았습니다
간결한 단일 구조의 AGENTS.md는 약 14 KB였습니다.
Harness 경로는 다음과 같은 양을 로드했습니다:
작은 AGENTS.md ~0.8 KB
harness.yaml ~3.3 KB
GODOT.md ~7.3 KB
...
Harness는 관련 없는 문서들을 성공적으로 피했지만, 직접적인 감소량은 불과 몇 킬로바이트(KB)에 불과했습니다.
이는 소스 파일, 검색 결과, 명령 출력, 테스트, 디프(diffs), 그리고 반복되는 도구 컨텍스트 (tool context)를 포함하는 완전한 에이전트 실행과 비교하면 매우 작은 수치입니다.
실험 결과 실행당 평균 약 62,000개의 캐시되지 않은 입력 토큰이 사용되었습니다.
몇 킬로바이트의 지침을 절약하는 것이 전체 규모를 변화시키기는 어려워 보였습니다.
이로 인해 주요 질문이 바뀌었습니다.
Harness가 주로 초기 프롬프트의 크기를 최적화하는 것은 아닐 수도 있습니다.
그것은 에이전트가 나머지 작업을 얼마나 일관되게 수행하는지를 최적화할 수도 있습니다.
가장 강력한 결과는 낮은 분산 (lower variance) 이었습니다
| 지표 (Metric) | AGENTS 표준 편차 (standard deviation) | Harness 표준 편차 (standard deviation) | 감소율 (Reduction) |
|---|---|---|---|
| 소요 시간 (Duration) | 46.67 s | 25.10 s | 46.2% |
| ... |
이 샘플에서 Harness는 다음과 같은 결과를 생성했습니다:
- 소요 시간 (duration) 변동성 46% 감소;
- 총 입력 (total input) 변동성 55% 감소;
- 캐시되지 않은 입력 (uncached input) 변동성 49% 감소;
- 출력 (output) 변동성 46% 감소;
- 명령 횟수 (command count) 변동성 66% 감소.
저는 이 프로젝트를 시작할 때 분산 (variance)을 주요 가설로 삼지는 않았습니다.
하지만 예측 가능성 (predictability)은 평균 (mean)의 미세한 개선보다 더 중요할 수 있습니다.
낮은 분산은 다음과 같은 사항을 개선합니다:
- 비용 예측 (cost forecasting);
- CI 용량 계획 (CI capacity planning);
- 타임아웃 설정 (timeout configuration);
- 속도 제한 관리 (rate-limit management);
- 이상 탐지 (anomaly detection);
- 사용자 기대치 (user expectations).
Harness가 모든 실행을 극적으로 더 저렴하게 만든 것은 아닙니다.
그것은 실행 경로를 더 반복 가능하게 (repeatable) 만들었습니다.
선택적 라우팅 (selective routing)이 변화시키는 것으로 보이는 것
단일 구조의 지침 파일 (monolithic instruction file)은 에이전트에게 모든 저장소 규칙을 한꺼번에 제공합니다.
에이전트는 작업을 수행하는 도중에 어떤 규칙이 중요한지 결정해야 합니다.
라우팅된 Harness는 이 선택을 명시적으로 만듭니다:
작업 분류 (task classification)
↓
저장소 경로 (repository route)
...
이는 단순히 마크다운 (Markdown) 파일을 정리하는 것 이상의 역할을 합니다.
그것은 에이전트의 결정 공간 (decision space)을 제한합니다.
이것은 비록 이 벤치마크가 인과 관계를 증명할 수는 없지만, 낮은 분산에 대한 그럴듯한 설명을 제공합니다.
데이터에 의해 뒷받침되는 가장 강력한 결론은 다음과 같습니다:
저장소 정의 라우팅 (Repository-defined routing)은 구현 성공률을 유지하면서 코딩 에이전트의 동작을 더 일관되게 만들었다.
Harness가 승리했는가?
제가 처음에 상상했던 단순한 방식으로는 아닙니다.
이 실험은 Harness가 항상 더 적은 토큰을 사용하거나 확실히 더 빠르다는 것을 증명하지는 않습니다.
다만 다음을 보여줍니다:
- 선택적 라우팅 (selective routing)이 작동했습니다.
- 관련 없는 문서들이 로드되지 않았습니다.
- 구현 신뢰성 (implementation reliability)이 유지되었습니다.
- 평균 효율성은 단일 구조 (monolithic) 버전과 유사하게 유지되었습니다.
- 실행 변동성 (execution variability)이 실질적으로 낮아졌습니다.
따라서 결과는 다음과 같습니다:
Harness가 더 저렴하다.
이 아니라:
Harness가 더 예측 가능하다.
그것이 더 가치 있는 엔지니어링 속성일 수 있습니다.
다음 실험은 풀스택 (full-stack)이어야 합니다
현재의 벤치마크는 하나의 Godot 리포지토리 내부의 한 가지 작업을 테스트했습니다.
다음 단계는 라우팅 모델이 기술적 도메인이 명확히 다른 리포지토리로 일반화될 수 있는지 테스트해야 합니다.
백엔드 및 프론트엔드 프로젝트는 모든 작업에 대해 로드될 필요가 없는 지식을 포함하고 있기 때문에 더 강력한 테스트가 됩니다:
backend
database
API contracts
...
다음 벤치마크에는 다음이 포함되어야 합니다:
- 백엔드 전용 작업;
- 프론트엔드 전용 작업;
- 크로스 스택 (cross-stack) 작업.
유용한 Harness는 격리된 작업에 대해서는 좁게 유지되어야 하며, 작업이 경계를 넘을 때만 확장되어야 합니다.
실용적인 설정은 TypeScript 모노레포 (monorepo)가 될 것입니다:
apps/
├── api/
└── web/
...
검증은 완전히 자동화될 수 있습니다:
lint
type-check
unit tests
...
다음 벤치마크는 토큰과 소요 시간뿐만 아니라 다음 항목들도 측정해야 합니다:
- 로드된 문서;
- 불필요하게 로드된 문서;
- 라우트 에스컬레이션 (route escalations);
- 변경된 파일 범위 (changed-file scope);
- p95 소요 시간;
- 분산 (variance).
파트 3의 핵심 질문은 다음과 같습니다:
리포지토리 정의 라우팅 (repository-defined routing)이 백엔드 전용 및 프론트엔드 전용 작업에 대해서는 좁게 유지되다가, 크로스 스택 작업에 대해서는 올바르게 확장될 수 있는가?
메모리가 나중에 도입되어야 하는 이유
지속성 메모리 (Persistent memory)는 유망합니다.
Harness는 궁극적으로 아키텍처 결정, 반복되는 실패, 컨벤션 (conventions), 검증 경로, 그리고 알려진 문제들을 학습할 수 있습니다.
하지만 지금 메모리를 추가하는 것은 두 가지 서로 다른 가설을 섞는 일이 될 것입니다:
- 정적 라우팅 (static routing)이 일반화될 수 있는가?
- 축적된 경험이 미래의 작업을 개선하는가?
메모리(Memory) 또한 이후의 실행이 이전 실행에 의존하게 만들며, 이는 통제된 비교를 복잡하게 만듭니다.
더 깔끔한 시퀀스는 다음과 같습니다:
파트 2
선택적 라우팅 (Selective routing) 및 예측 가능성
...
만약 파트 3에서 Harness가 일반화된다면, 메모리는 다음 논리적 계층이 될 것입니다.
이 프로젝트는 실패가 아니다
원래의 약속은 토큰(token) 감소였습니다.
두 번째 벤치마크는 평균 토큰 사용량에서 크거나 통계적으로 결론적인 감소를 만들어내지 못했습니다.
대신, 다른 이점을 드러냈습니다:
저장소 정의 컨텍스트 라우팅 (Repository-defined context routing)은 구현 성공률을 낮추지 않으면서도 코딩 에이전트 (coding-agent)의 동작을 더 예측 가능하게 만들 수 있다.
신뢰할 수 있는 에이전트 워크플로우 (agent workflows)에는 정확한 최종 코드 그 이상이 필요합니다.
그들에게는 제한된 동작 (bounded behavior)이 필요합니다:
- 제한된 컨텍스트 (bounded context)
- 제한된 검증 (bounded validation)
- 제한된 도구 사용 (bounded tool use)
- 설명 가능한 에스컬레이션 (explainable escalation)
- 반복 가능한 실행 경로 (repeatable execution paths)
이것이 바로 Repository Harness가 되어가고 있는 모습입니다.
첫 번째 기사는 아이디어를 제안했습니다.
첫 번째 벤치마크는 라우팅 결함을 노출했습니다.
두 번째 벤치마크는 더 엄격한 라우팅이 효과가 있으며 에이전트를 더 일관되게 만든다는 것을 보여주었습니다.
파트 3에서는 그 결과가 Godot을 넘어 일반화될 수 있는지 테스트할 것입니다.
질문은 이제 더 이상 다음과 같지 않습니다:
Harness가 토큰을 줄일 수 있는가?
이제 질문은 다음과 같습니다:
저장소가 모든 코딩 에이전트를 위해 예측 가능하고, 감사 가능하며, 점진적으로 공개되는 운영 환경을 정의할 수 있는가?
프로젝트는 다음에서 확인할 수 있습니다:
Repository Harness Specification
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기