본문 바로가기
AI2026년 9월 16일10분 읽기

코딩 에이전트 하네스 설계 — 같은 모델로 결과가 달라지는 이유

YS
김영삼
조회 173
코딩 에이전트 하네스 설계 — 같은 모델로 결과가 달라지는 이유

하네스(harness)는 모델을 감싸서 실제 작업을 수행하게 만드는 바깥 구조다. 어떤 도구를 주는가, 컨텍스트에 무엇을 넣는가, 결과를 어떻게 검증하는가, 실패하면 어떻게 되돌리는가 — 이 모든 것이 하네스다.

같은 모델이라도 하네스에 따라 결과가 크게 달라진다. 그래서 "어느 모델이 더 좋은가"라는 질문은 절반만 유효하다. 나머지 절반은 모델에게 무엇을 보여 주고 무엇을 할 수 있게 하느냐에 달려 있다.

직접 에이전트를 만들어 보면 이 사실이 금방 체감된다. 처음엔 프롬프트를 고치며 시간을 보낸다. 그러다 어느 순간 깨닫는다. 프롬프트를 아무리 다듬어도, 모델이 테스트를 실행할 수 없으면 코드가 도는지 알 방법이 없다는 걸. 그때부터 작업의 무게중심이 프롬프트에서 하네스로 옮겨 간다.

하네스를 구성하는 네 축

결정할 것흔한 실패
도구어떤 동작을 허용할 것인가, 인터페이스를 어떻게 줄 것인가도구가 너무 많거나, 출력이 너무 장황함
컨텍스트무엇을 보여 줄 것인가, 언제 잘라낼 것인가전부 넣어 핵심이 묻힘
검증무엇을 기준으로 완료를 판단하는가모델의 자기 보고에 의존
복구실패했을 때 어떻게 되돌리는가부분 변경이 남아 상태가 꼬임

도구 설계 — 적을수록 좋다

도구를 많이 주면 좋을 것 같지만 반대다. 선택지가 늘수록 잘못된 도구를 고를 확률이 오르고, 설명만으로 컨텍스트를 잡아먹는다. 좋은 도구 세트는 겹치지 않고, 각각이 명확하며, 조합으로 대부분의 작업을 커버한다.

도구 설계 원칙
한 도구는 한 가지 일만 한다 — "파일 조작" 대신 "읽기", "쓰기", "검색"으로 분리
출력을 잘라서 준다 — 10만 줄 파일을 통째로 돌려주면 컨텍스트가 폭발한다
에러 메시지를 행동 가능하게 — "실패했습니다"가 아니라 "파일이 없습니다. 경로를 확인하세요"
되돌릴 수 없는 도구는 별도 승인 경로를 둔다 (삭제, 배포, 외부 전송)
도구 이름과 인자는 자명하게 — 설명 없이도 용도를 알 수 있어야 한다
멱등성을 갖게 설계 — 같은 호출을 두 번 해도 안전하면 재시도가 쉬워진다
// 나쁜 도구: 너무 많은 일을 하고 출력이 무제한
{
  name: "file_operation",
  params: { action: "read|write|delete|move", path: "...", content: "..." }
}

// 나은 도구: 분리되고 출력이 제한됨
{
  name: "read_file",
  params: { path: "string", offset: "number?", limit: "number? (기본 2000줄)" },
  returns: "지정 범위의 내용. 잘렸으면 그 사실과 전체 줄 수를 함께 반환"
}
{
  name: "search_code",
  params: { pattern: "string", glob: "string?", max_results: "number? (기본 50)" },
  returns: "파일:줄번호:매칭줄. 결과가 많으면 상위 N개 + 전체 개수"
}
출력 절단이 핵심 도구 출력이 컨텍스트를 채우면 정작 중요한 정보가 밀려난다. 큰 결과는 요약하거나 페이지네이션하고, "더 보려면 이렇게 호출하라"는 힌트를 함께 준다. 모델이 필요할 때 더 가져가게 하는 편이 처음부터 다 주는 것보다 낫다.

컨텍스트 구성 — 무엇을 넣지 않을 것인가

컨텍스트 창이 커졌다고 다 채우면 안 된다. 긴 입력에서 중간 정보가 흐려지는 현상은 여전하고, 비용과 지연도 비례해 늘어난다. 좋은 하네스는 적극적으로 버린다.

1
작업 정의를 앞에
무엇을 해야 하는지, 완료 기준이 무엇인지 먼저 둔다.
2
프로젝트 규칙을 짧게
빌드·테스트 명령과 금지선. 장황한 아키텍처 설명은 뺀다.
3
관련 코드만 선별
전체 파일보다 관련 함수와 그 호출부. 검색 결과를 그대로 붓지 않는다.
4
이전 시도의 결과를 압축
실패한 접근은 "무엇을 시도했고 왜 실패했는지" 한 줄로 남긴다. 전체 로그를 유지하지 않는다.
5
오래된 도구 출력 제거
같은 파일을 여러 번 읽었다면 최신 것만 남긴다.

검증 루프 — 하네스의 심장

에이전트가 "완료했습니다"라고 말하는 것과 실제로 동작하는 것은 다른 문제다. 검증 루프가 없는 에이전트는 자기 보고에 의존하게 되고, 그건 신뢰할 수 없다.

# 검증 루프의 기본 구조
while not done and attempts < MAX:
    action = model.decide(context)
    result = execute(action)
    context.append(compact(result))

    if action.is_final_claim():
        # 모델의 주장을 기계적으로 검증한다
        checks = run_verification()      # 빌드, 테스트, 린트, 타입체크
        if checks.all_passed():
            done = True
        else:
            # 실패 정보를 구체적으로 되돌려 준다
            context.append(checks.failures)   # 어떤 테스트가 왜 실패했는지
    attempts += 1

여기서 중요한 건 검증이 모델 바깥에 있다는 것이다. 테스트 러너, 타입 체커, 린터는 모델과 무관하게 참·거짓을 판정한다. 이 객관적 신호가 있으면 에이전트는 스스로 고칠 수 있다. 없으면 그럴듯한 코드를 쓰고 끝낸다.

좋은 검증 신호
  • 컴파일·타입 체크 결과
  • 단위·통합 테스트 통과 여부
  • 린터 오류
  • 실제 실행 결과(스크린샷·HTTP 응답)
약한 신호
  • 모델의 자기 평가
  • "코드가 올바릅니다" 같은 서술
  • 다른 모델의 리뷰(유용하지만 결정적이지 않음)

실패 복구와 상태 관리

에이전트는 중간에 실패한다. 이때 작업 디렉터리가 어중간한 상태로 남으면 다음 시도가 더 꼬인다. 복구 전략을 미리 정해 둬야 한다.

  • 체크포인트 — 작업 시작 시점의 상태를 기록한다. 버전 관리 시스템이 이미 있다면 그걸 활용하는 게 가장 간단하다.
  • 부분 커밋 금지 — 검증을 통과하기 전에는 확정하지 않는다.
  • 반복 감지 — 같은 실패를 세 번 반복하면 멈추고 사람에게 넘긴다. 무한 루프는 비용만 태운다.
  • 시간·비용 상한 — 토큰이든 시간이든 상한을 두고, 초과 시 현재까지의 결과와 함께 중단한다.
반복 감지의 실무적 형태 직전 N개 행동의 해시를 비교해 같은 도구·같은 인자 호출이 반복되면 개입한다. 모델은 같은 시도를 반복하면서도 매번 새로운 시도라고 생각하는 경향이 있다.

샌드박스와 권한

에이전트에게 실행 권한을 주는 순간 보안 문제가 생긴다. 특히 코드베이스나 외부 데이터에 포함된 지시문이 모델의 행동에 영향을 줄 수 있다는 점을 전제해야 한다.

권한 설계
작업 디렉터리 밖 접근 차단 — 경로 정규화 후 검사
네트워크 아웃바운드 제한 — 필요한 도메인만 허용
시크릿을 환경에서 제거 — 에이전트가 도는 환경에 클라우드 키를 두지 않는다
되돌릴 수 없는 동작은 승인 게이트 — 배포, 삭제, 외부 전송, 결제
읽어 들인 외부 콘텐츠는 데이터로 취급 — 그 안의 지시문을 명령으로 실행하지 않도록 경계 표시

측정 — 하네스를 개선하려면

하네스 개선은 감으로 하면 안 된다. 대표 작업 세트를 만들어 두고, 변경 전후의 성공률·시도 횟수·비용을 비교해야 한다.

지표의미개선 신호
작업 성공률검증까지 통과한 비율가장 중요한 지표
평균 시도 횟수효율성도구·컨텍스트 개선 시 감소
평균 토큰 사용비용컨텍스트 정리로 감소
사람 개입 비율자율성복구 전략 개선 시 감소
잘못된 도구 선택 빈도도구 설계 품질도구 축소·설명 개선 시 감소

이 측정이 있으면 "모델을 바꿀까, 하네스를 고칠까"라는 질문에도 답할 수 있다. 같은 모델로 하네스만 바꿔서 성공률이 오른다면, 아직 모델을 바꿀 때가 아니다.

자주 묻는 질문

하네스가 정확히 무엇인가요?

모델을 감싸 실제 작업을 수행하게 만드는 바깥 구조 전체를 말합니다. 도구 정의, 컨텍스트 구성, 검증 루프, 실패 복구, 권한 경계가 포함되며, 같은 모델이라도 하네스에 따라 결과가 크게 달라집니다.

도구는 많이 주는 게 좋지 않나요?

아닙니다. 선택지가 늘면 잘못된 도구를 고를 확률이 오르고 설명만으로 컨텍스트를 소모합니다. 겹치지 않고 각각 명확한 소수의 도구를, 조합으로 대부분의 작업을 커버하도록 설계하는 편이 낫습니다.

검증 루프는 왜 중요한가요?

모델의 자기 보고는 신뢰할 수 없기 때문입니다. 테스트·타입 체크·린터처럼 모델 바깥의 객관적 판정 수단이 있어야 에이전트가 실패를 인지하고 스스로 고칠 수 있습니다. 검증이 없으면 그럴듯한 결과에서 멈춥니다.

컨텍스트는 많이 넣을수록 좋은가요?

아닙니다. 긴 입력에서 중요한 정보가 흐려지고 비용과 지연이 함께 늘어납니다. 작업 정의와 완료 기준을 앞에 두고, 관련 코드만 선별하며, 오래된 도구 출력과 실패 로그는 압축하거나 제거하세요.

에이전트가 같은 실수를 반복합니다. 어떻게 하나요?

최근 행동의 도구·인자 조합을 해시로 비교해 반복을 감지하고, 일정 횟수를 넘으면 중단하거나 접근 방식을 바꾸도록 개입하세요. 동시에 시도 횟수와 비용 상한을 두어 무한 루프를 막아야 합니다.

보안은 어떻게 챙기나요?

작업 디렉터리 밖 접근을 차단하고, 네트워크 아웃바운드를 제한하며, 실행 환경에서 시크릿을 제거하세요. 되돌릴 수 없는 동작에는 승인 게이트를 두고, 외부에서 읽어 들인 콘텐츠는 명령이 아니라 데이터로 취급하도록 경계를 명확히 해야 합니다.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록