Models & Algorithms•SOTAAZ Lab••EN

Harness²: 정답 없이 하네스를 고치는 루프, 숫자와 한계

Harness²(arXiv:2610.14224)는 모델을 둘러싼 하네스를 편집 가능한 여덟 부분으로 나누고, 정답 없이 그 하네스를 반복해서 고칩니다. GLM-5와 OpenCode 조합의 WorkBuddy-Bench 평균이 한 번의 개선 단계로 11.5점 올랐고, 실험은 OpenCode와 Codex 두 에이전트 도구 위에서 했습니다. 선택 단계가 더 약한 후보를 고른 사례도 논문 스스로 밝힙니다. 공개 데모는 로컬에서 돌려 봤습니다.

Harness²: 정답 없이 하네스를 고치는 루프, 숫자와 한계

Harness²: 정답 없이 하네스를 고치는 루프, 숫자와 한계

먼저 구글의 Harness² 공개 저장소를 서버에서 돌려 봤습니다. 장부 과제 두 개를 k=2로 돌렸고, 실행 28회와 에디터·컴포저·선택기·리플렉터 세션 호출 32회가 나왔습니다. 파라미터는 아래 표를 참고해주세요.

용어뜻사용한 값비고
k편집 범위마다 만드는 후보의 수. 병렬 모드는 합성 후보도 k개, 순차 모드는 이어 가는 단계가 k개입니다21이면 후보가 하나뿐이라 선택 단계를 건너뜁니다. 올리면 실행과 호출이 늘고 선택기가 일을 합니다. 얼마나 느는지는 이번에 재지 않았습니다
실행하네스를 붙여 과제를 처음부터 끝까지 한 번 돌린 횟수28회후보와 합성이 늘면 같이 늡니다
세션 호출에디터(편집 제안), 컴포저(합성), 선택기, 리플렉터(라이브러리 항목 작성) 세션이 불린 횟수32회이것도 k에 따라 증가
병렬·순차같은 베이스에서 후보를 한꺼번에 만드는 방식과, 앞 단계 결과 위에 이어 쌓는 방식둘 다둘 다 돌려도 베이스 실행(k회)은 한 번만 돌리고 두 방식이 같이 씁니다

데모의 베이스 하네스에는 양수 금액만 더하도록 시연용으로 심어 둔 버그가 있습니다. 첫 과제가 Total: 105.25를 찍었는데 부호를 모두 더한 값은 Total: 85.15입니다.

저자들의 주장은 모델이 아니라 모델을 둘러싼 하네스(프롬프트, 규칙, 메모리, 도구, 스킬)를 최적화 대상으로 보자는 것입니다. Propose–Probe–Compose 한 번으로 GLM-5와 OpenCode 조합의 WorkBuddy-Bench 점수가 64.2에서 75.7로 올라갔고, JobBench에서는 Gemini 3.5 Flash 조합이 4.5점 올랐습니다. 이 두 값은 후보를 하나만 만드는 k=1 설정이라 최종 선택 단계를 건너뛴 결과입니다. 선택기는 k가 2 이상일 때만 작동합니다.

다만 숫자보다 눈여겨볼 곳은 루프가 다음 하네스를 고르는 방식입니다. 이 루프는 정답을 한 번도 보지 못한 채 다음 하네스를 고릅니다. 예산을 늘려 k를 2 이상으로 올리면 이 선택 단계가 붙고, 논문이 정리한 실패 사례에는 그 단계에서 더 약한 후보를 고른 사례가 그대로 들어 있습니다. 이 글은 논문을 읽고 공개 데모를 돌려 본 기록이고, 그 선택 단계가 정확히 무엇을 보고 고르는지는 다음 글에서 코드로 따라가 봅니다.

하네스, 그리고 편집 가능한 여덟 부분

저장소의 README는 하네스를 이렇게 정의합니다. "A harness is the system around a model that enables it to act as an agent: prompts, tools, memory, skills, orchestration, and more." 논문은 모델은 그대로 두고 그 주변 장치를 고쳐 나가는 일을 하네싱(harnessing)이라고 부릅니다. OpenCode에서 편집할 수 있는 여덟 부분(시스템 프롬프트, 가드레일, 메모리, 도구 지침, 서브에이전트, 스킬, 스크립트, 플러그인)과 하네스 엔지니어링이라는 말의 출처는 이 연재 1부에서 다뤘습니다. 이 글에서 알아 둘 것은 하나입니다. OpenCode에서는 항상 켜져 있는 텍스트 네 가지(시스템 프롬프트·가드레일·메모리·도구 지침)를 합쳐 24,000자로 제한합니다. 상한은 글자 수로 재고, 이유는 소스에 "여기 있는 토큰 하나하나가 에이전트 자신의 출력 예산과 경쟁한다"고 적혀 있습니다.

하네스를 고치는 두 개의 루프

첫 번째 루프는 지금 풀고 있는 과제 하나에 맞춰 하네스를 다듬습니다. 하네스 에디터가 편집을 제안하고, 같은 과제에서 후보들을 실제로 실행하고, 고치기 전 하네스로 돌린 결과와 무엇이 달라졌는지 비교해서 새 하네스를 만듭니다. 논문은 이 비교를 행동 대비(behavioral contrast)라고 부릅니다. 이 루프 어디에도 정답은 입력받지 않습니다. 논문이 풀려는 문제가 바로 이 지점입니다. 실제 업무 과제는 미리 본 적 없는 것이 대부분이고 채점표도 없어서, 고친 것이 맞는지 알려 줄 장치가 없습니다. 그래서 에디터는 두 번 돌린 결과가 어떻게 달라졌는지만 보고 판단해야 합니다.

두 번째 루프는 과제와 과제 사이에서 천천히 돕니다. 과제 하나가 끝나면 채택된 하네스와, 그것이 왜 채택됐는지에 대한 과정과 교훈이 영역별 라이브러리에 들어갑니다. 같은 영역의 다음 과제는 시작하기 전에 그 라이브러리를 읽고 출발합니다.

라이브러리가 실제로 쓰이는지 논문은 두 가지 숫자로 보여 줍니다. 첫째는 겹침입니다. 하네스에서 수정된 파일마다, 라이브러리 항목에 이미 있던 줄이 얼마나 들어 있는지 셉니다. 어느 정도라도 겹치는 파일은 LAB과 WorkBuddy-office에서 22%, JobBench에서 47%였습니다. 라이브러리의 내용이 새 하네스에 흘러 들어갔다는 뜻입니다. 둘째는 복사 정도입니다. 줄의 절반 이상을 라이브러리 항목에서 그대로 가져온 파일은 2%에서 10%뿐이었습니다. 저자들은 이것을 통째로 복사하기보다 가져다가 과제에 맞게 고쳐 쓰는 경우가 더 많다는 신호로 읽습니다. 수정된 파일의 나머지(LAB과 WorkBuddy-office는 78%, JobBench는 53%)는 라이브러리 항목과 겹치는 줄이 없었습니다. 편집이 어느 부분에 몰렸는지도 따로 셌는데, 편집의 절반가량이 스킬과 스크립트였습니다.

Harness²에는 두 루프가 있어서, 첫 루프는 한 과제에 대해 하네스를 좋게 만들고, 두 번째 루프는 다음 과제에서 하네스를 고치는 수고를 덜어 줍니다.

논문이 보고한 숫자

논문의 Table 1과 Table 2는 베이스 하네스 대비 개선 한 단계를 세 번 실행한 평균으로 보고합니다.

벤치마크, 모델, 에이전트 도구베이스 하네스Harness² (k=1, 한 단계)변화
WorkBuddy-Bench 평균, GLM-5 + OpenCode64.2 (1.4)75.7 (2.2)+11.5
JobBench, Gemini 3.5 Flash + OpenCode31.5 (1.1)36.0 (2.3)+4.5
LAB 부분 통과율, GLM-5 + OpenCode59.6 (2.7)71.4 (2.9)+11.8%p

괄호는 세 번 실행 시의 표준편차입니다. 평균 +11.5는 두 표준편차(1.4와 2.2)보다 훨씬 크지만, 영역별 베이스 표준편차는 WorkBuddy-code 5.2, web 6.9까지 벌어집니다. 고치는 횟수(예산)를 늘리면 이득이 더 붙습니다. 같은 GLM-5 조합에서 k=1은 WorkBuddy-code를 58.4에서 77.1로, web을 59.2에서 69.1로 올리고, k=5는 여기에 code 4.8점, web 5.3점(세 영역 평균 3.9점)을 더합니다.

헤드라인보다 중요한 비교 숫자가 두 개 있습니다. 먼저 비교 대상부터 정리합니다. 논문은 Harness²를 다른 방법들과 같은 조건에서 겨룹니다. 같은 고정 모델, 같은 시작 하네스, 같은 과제 순서, 같은 채점자를 씁니다. 여기서 비교 대상은 세 가지입니다. ReasoningBank는 하네스를 한 번도 고치지 않고, 비슷한 과거 과제에서 뽑아 둔 경험 메모를 과제 프롬프트 앞에 붙여 줍니다. Harness Scaling은 과제마다 하네스를 고쳐 쓰는 수정 루프를 돌리지만 라이브러리가 없습니다. Meta-Harness는 시험에 들어가기 전에 별도의 훈련 과제로 하네스를 미리 최적화해 두고, 시험 때는 그대로 씁니다.

첫 번째 숫자는 이 비교 대상이 모두 도움이 되는 것은 아니라는 점입니다. ReasoningBank는 GLM-5와 Codex 조합의 코딩 과제에서 베이스 하네스(56.8)보다 6.6점 낮은 50.2로 끝났습니다. 두 번째 숫자는 Meta-Harness에 붙은 표시입니다. WorkBuddy-Bench에서 Gemini 3.5 Flash와 OpenCode로 비교한 그림에서는 이 방법이 가장 강한 기준선입니다. 그런데 Meta-Harness는 시험 전에 훈련 과제를 따로 받아 최적화한 방법이라 표에 표시가 붙어 있습니다. Harness²는 훈련 과제 없이 시험 과제를 차례로 풀면서 배웁니다. 출발선이 달라서, 둘을 같은 자리에서 겨룬 것으로 읽으면 안 됩니다. 반대 방향의 숫자도 있습니다. LAB 부분 통과율에서는 ReasoningBank가 GLM-5와 OpenCode 조합에서 71.3(1.3)으로, Harness²의 71.4(2.9)와 사실상 같습니다. 위 표의 +11.8%p는 그 조합의 베이스 59.6과 비교한 값이어서, 무엇과 비교하느냐에 따라 이득의 크기가 달라집니다.

표의 점수를 읽을 때 알아 둘 점이 두 가지 있습니다. 하나는 흔들림입니다. 세 번 실행하면서 매번 과제 순서를 섞었다고 논문이 적고, 모델이 답을 만들 때의 무작위성은 고정하지 않았다고 저장소의 실험 문서(docs/EXPERIMENTS.md)가 적습니다. 같은 설정으로 다시 돌려도 점수가 조금씩 달라지고, 괄호 안 표준편차가 그 흔들림입니다. 다른 하나는 채점입니다. 각 칸의 점수에는 LLM이 판정한 부분이 들어 있어서 채점도 완전히 고정된 잣대가 아닙니다. 논문의 Appendix F는 반복 개선에 드는 비용이 한계라고 적으면서, 비용을 더 쓸수록 얼마나 좋아지는지는 한정된 예산 범위에서만 살펴봤다고 말합니다.

Ablation: 하네스의 어느 부분이 핵심 역할을 하나

논문은 이미 개선된 하네스에서 부품 묶음을 빼고, 개선사항을 다시 돌리지 않은 채 다시 채점합니다(Appendix E.1, WorkBuddy-Bench, Gemini 3.5 Flash + OpenCode, k=5).

구성평균
전체 하네스80.8
스킬 제거75.5
스크립트 제거77.1
프롬프트 묶음 제거79.3
베이스 하네스72.4

제거했을 때 손해가 가장 큰 건 스킬이고, 그다음이 스크립트, 프롬프트 텍스트가 가장 작습니다. 그런데도 묶음을 하나씩 빼 본 어느 구성도 베이스 하네스보다는 높습니다. Harness²의 기여가 어느 하나에 집중된 것이 아니라는 뜻입니다. 저자들은 이 어블레이션이 "여러 부품 묶음의 기여를 뒷받침하지만, 더하기 효과를 입증하지는 않는다"고 적습니다.

공개 데모를 돌려 봤습니다

저장소에는 모델 자격 증명이 필요 없는 로컬 데모가 들어 있습니다. 작동 방식을 보고 싶어 이 서버에서 돌려 봤습니다.

데모의 베이스 하네스에는 시연용으로 심어 둔 버그가 있습니다. scripts/summarize.py가 양수인 금액만 더합니다. 그래서 첫 과제(100.25, −20.10, 5.00)는 모두 더하면 Total: 85.15 가 되어야 하지만 베이스 하네스에서 측정하면 Total: 105.25가 나옵니다. 에디터의 편집은 if amount > 0 조건 한 조각을 지운 것이고, 라이브러리 항목에는 이를 "dropped the positive-only filter from the amount sum"으로 적었습니다. 고친 하네스로 다시 실행하면 베이스 실행의 Total: 105.25 대신 Total: 85.15가 나오고, 선택 단계는 장부와 맞는 쪽을 남깁니다. 두 번째 과제도 같습니다. 금액이 (35.50, −10.25, −5.00)이고, 결과가 Total: 35.50에서 Total: 20.25로 바뀝니다.

이 실행이 보여 주는 건 비용의 형태입니다. 두 과제, 두 가지 반복 방식(병렬·순차), k=2로 파이프라인은 실행 28회와 에디터·컴포저·선택기·리플렉터 세션 호출 32회를 만들었습니다. 과제 하나당 8회(병렬 모드: 베이스 기준 2회, 불변 후보 2회, 영역 후보 2회, 합성 2회), 6회(순차 모드, 베이스 기준 실행은 재사용)입니다. 병렬 8회와 순차 6회를 합친 14회가 과제마다 들어가므로 과제 둘이면 28회입니다. 논문도 에이전트 스텝 수(#Steps)와, 개선에 쓴 토큰까지 합친 총 계산량(Figure 6)을 따로 보고합니다. 이 작은 실행은 그 계산량이 어떤 모양으로 쌓이는지를 보여 줍니다.

라이브러리 항목이 저희가 가장 궁금했던 산출물입니다. 작은 마크다운 파일 하나입니다(아래는 발췌이고 서식을 정리했습니다). 채택된 하네스와 왜 그걸 골랐는지, 각 편집이 무엇을 했는지, 그리고 옮겨 쓸 수 있는 교훈이 단서·교훈·근거·확신도로 적힌 형태입니다.

- adopted: `agg1`  (run `demo-oc-agg2/ledger-1/agg1`)
- components: 1 scripts; 62 always-on chars
...
- cue: When a ledger includes credits and debits
- lesson: Include both signs when summing in scripts/summarize.py.
- evidence: The scripts/summarize.py row -- removing the positive-only filter changed
  the probe total to include the credits omitted by the base trajectory.
- confidence: high for this observed arithmetic contrast

이 숫자들 옆에 반드시 붙여야 할 단서가 하나 있습니다. 공개 데모에서 에디터와 선택 단계는 모델이 아니라 스크립트로 되어 있습니다. 이 실행은 루프가 어떻게 돌아가고 무엇을 남기는지 보여 줄 뿐, 실제 모델이 에디터를 맡아도 그만큼 좋은 편집을 찾는지는 알려 주지 않습니다. 선택 단계도 마찬가지입니다. 데모의 선택 스크립트는 장부 합계를 직접 계산해서 맞는 후보를 선택하므로, 정답 없이 고르는 단계는 이 데모로 볼 수 없습니다.

루프가 잘못 선택하는 지점

논문의 Appendix E.6은 점수가 오히려 떨어진 사례 아홉 개를 세 종류로 나눕니다. 첫째가 이 글에서 가장 중요한 종류입니다. 선택 단계가 더 약한 후보를 고를 수 있습니다. 사후 평가 기준으로 WorkBuddy-code에서는 95점짜리가 아니라 55점짜리 산출물이 채택됐습니다. LAB에서는 다루는 범위가 좁아진 산출물이 채택되어 점수가 54에서 26으로 떨어졌습니다. 둘째는 잘못된 전제가 후보 전체로 전파되는 경우로 2점에서 11점까지 깎입니다. 셋째는 실행마다 결과가 흔들리거나 판정이 빠져서, 점수 변화가 무엇 때문인지 가리기 어려운 경우입니다.

한계 부분은 왜 이런 일이 생기는지 분명히 적습니다. 정답을 알려 주는 쪽이 없으니 개선은 "행동 대비와 모델 판단", 즉 두 실행의 차이와 모델의 판단에만 기댑니다. 그런데 이 신호는 "실행 변동성과 공유된 모델 편향에 민감"하고 "정확성을 보장하지 않습니다". 재사용 쪽 숫자에도 같은 주의가 붙습니다. 자기 항목을 라이브러리에서 빼고 다시 돌린 점수는 WorkBuddy-Bench에서 79.4(원래 실행은 77.5), JobBench에서 37.7(원래 실행은 36.0)이었습니다(앞의 표와 다른 설정입니다. 77.5는 Gemini 3.5 Flash와 OpenCode 조합의 k=1 값입니다). 이 비교는 과제를 차례로 푼 원래의 k=1 실행이 기준이고, 다시 돌린 실행은 뒤 과제의 항목도 쓸 수 있으며 저자들은 반복 실행의 효과도 섞였을 수 있다고 적습니다. 그래서 항목을 빼서 점수가 올랐다는 인과로 읽을 수 없고, 저자들도 이것은 과제를 차례로 풀며 얻는 이득을 잰 값이 아니라, 실행이 끝난 뒤 라이브러리를 다시 써 본 분석이라고 밝힙니다.

모델 간 이전도 실제로 되지만 고르지 않습니다. Gemini 3.5 Flash에 맞춰 다듬은 하네스를 GLM-5에 그대로 쓰면 WorkBuddy-code가 58.5에서 75.8로 오릅니다(모델 간 이전 실험의 베이스 값이라 앞의 표 58.4와 따로 적힌 수치입니다). 같은 하네스가 Gemini 3.7 Flash의 code 부분집합에는 0.3점, Claude Opus 4.8에는 2.6점을 붙입니다. 같은 문단에서 저자들은 세 모델 모두 code와 office 양쪽에서 좋아졌다고 적고, office에서는 Gemini 3.7 Flash가 6.4점, Opus 4.8이 1.1점 올랐습니다.

다음 글에서 볼 것

Harness²에서 진지하게 볼 부분은 정답 없이 후보를 고르는 선택 단계입니다. 논문은 이 단계의 실패를 사례로 싣지만 적중률은 싣지 않았습니다(본문에서 oracle, regret, selection accuracy를 검색하면 0건). 이 글의 데모는 선택기를 스크립트로 대신했기 때문에 그 단계를 볼 수 없었습니다. 4부에서는 공개 코드에서 선택기가 무엇을 입력으로 받고 무엇을 근거로 후보를 고르는지 읽어 봅니다.

Harness²는 하네스를 최적화 대상으로 만들고, 예산을 늘려 후보를 둘 이상 만들면 정답 없이 골라야 하는 한 단계가 붙습니다. 논문 스스로도 그 단계가 95점짜리 대신 55점짜리를 고른 사례를 밝혔습니다.

방법 노트

  • 논문: Harness²: Recursive Agent Harnessing for an Open World, arXiv:2610.14224(2026년 10월 9일 제출), Ruiyao Xu 외(Google Cloud AI Research 주도, Northwestern University 포함). 인용한 숫자는 Table 1과 2, Appendix E.1에서 E.3, E.6, F에서 가져왔고 arXiv HTML과 대조했습니다.
  • 코드: google-research/harness2, Apache 2.0, 커밋 1cfe254, 패키지 버전 0.1.0. README는 이 프로젝트가 구글의 공식 지원 제품이 아니라고 밝힙니다.
  • 데모 실행: uv venv --python 3.12 .venv, uv pip install -e '.[render]', harness2-demo --output runs/demo --k 2. Linux, Python 3.12, 2026년 10월 20일. 모델 자격 증명을 쓰지 않았고 모델 호출도 없었습니다.

참고문헌

더 많은 콘텐츠를 받아보세요

SNS에서 새로운 글과 튜토리얼 소식을 가장 먼저 받아보세요

이메일로 받아보기