하네스 엔지니어링 — LLM 에이전트의 구조적 행동 제어
LLM 에이전트에게 "위임하라"고 지시해도 새 세션에서는 직접 처리하는 문제가 반복됩니다. 피드백 메모리를 쌓아도 해결되지 않았습니다. 스킬 파일 자체에 금지 패턴, 위임 게이트, 검증 체크포인트를 설계하여 구조가 올바른 경로를 강제하는 방법론을 정리했습니다.
TL;DR LLM 에이전트에게 “A에 위임하라”고 지시해도, 새 세션에서는 빈번하게 직접 처리하는 문제가 발생합니다. 피드백 메모리를 쌓아도 해결되지 않았습니다. 하네스 엔지니어링은 이 문제에 대한 구조적 해법입니다. 스킬 파일 자체에 금지 패턴, 위임 게이트, 검증 체크포인트를 설계하여 LLM이 지시를 “기억”하지 못해도 올바른 경로로만 진행하도록 제약합니다.
문제: 피드백 메모리의 한계
Claude Code에서 멀티레포 오케스트레이션 스킬(org-flow)을 운영하고 있습니다. 이 스킬은 이슈 라이프사이클 관리를 devex:flow라는 하위 스킬에 위임하도록 설계되어 있습니다.
org-flow (오케스트레이션)
└─ devex:flow (이슈 라이프사이클)
├─ Dooray 상태 변경
├─ 태그/CC 보정
├─ 본문 업데이트
├─ 브랜치 생성
└─ 데일리로그 연동
문제는 org-flow가 devex:flow에 위임하지 않고 직접 Dooray API를 호출하는 현상이 반복된다는 것입니다. 스킬 파일에 “위임하라”고 명시되어 있음에도 새 세션에서 이를 무시했습니다.
시도한 해결책과 결과
| 시도 | 결과 |
|---|---|
| 스킬 파일에 “위임” 텍스트 명시 | 무시됨 — LLM이 더 빠른 경로(직접 API 호출)를 선택 |
| 피드백 메모리 추가 | 일시적 효과 — 새 세션에서 메모리를 참조하지 않거나 우선순위가 밀림 |
| 역할 분담 테이블 추가 | 읽히지만 구속력 없음 — “참고 정보”로 취급됨 |
공통적인 실패 원인: 텍스트 지시는 LLM에게 “권고”로 작용하지, “제약”으로 작용하지 않습니다.
메모리 교정의 근본적 한계
피드백 메모리가 효과적인 세션에서도, 이 접근에는 근본적인 한계가 있습니다.
플러그인을 도구로 인식하고 있습니다. 도구는 설치하면 모든 영역에서 온전히 동작해야 합니다. 그래서 유저 스코프에 글로벌 설치하여 작업하고 있습니다. 하지만 피드백 메모리는 도구 바깥에 있는 외부 상태입니다.
- 노트북을 교체하면 메모리는 유실됩니다
- 팀원에게 스킬을 공유해도 교정은 전달되지 않습니다
- 다른 프로젝트 디렉토리에서는 같은 메모리가 존재하지 않을 수 있습니다
도구의 올바른 동작이 도구 외부의 상태에 의존한다면, 그것은 온전한 도구가 아닙니다. 메모리를 더 쌓는 것이 아니라, 행동 제약을 도구 안에 넣어야 합니다.
원인 분석: 왜 텍스트 지시가 실패하는가
LLM 에이전트가 스킬 파일의 지시를 무시하는 구조적 원인을 분석하면 세 가지로 정리됩니다.
1. 최단 경로 편향
LLM은 목표(이슈 상태를 “진행 중”으로 변경)를 인식하면, 가장 직접적인 경로를 선택하는 경향이 있습니다. “devex:flow에 위임”은 간접 경로이고, “Dooray API를 직접 호출”은 직접 경로입니다. 스킬 파일이 간접 경로를 지시하더라도, LLM은 직접 경로의 유혹에 빠집니다.
2. 사이드이펙트 비가시성
위임의 가치는 사이드이펙트(데일리로그 연동, 태그 보정 등)에 있습니다. 하지만 이 사이드이펙트는 주 목표(“상태 변경”)와 분리되어 있어, LLM이 직접 경로를 선택할 때 누락 가능성을 인식하지 못합니다.
3. 세션 간 컨텍스트 단절
피드백 메모리는 “참조 가능한 정보”일 뿐, 실행 시점에 강제로 로딩되지 않습니다. 새 세션에서 스킬이 트리거되면 스킬 파일만 로딩되고, 관련 메모리가 자동으로 주입되지 않습니다.
해법: 하네스 엔지니어링
하네스 엔지니어링(Harness Engineering) 은 LLM 에이전트의 행동을 구조적으로 제약하는 스킬 설계 방법론입니다.
하네스(harness): 말이나 동물에 채우는 마구. 방향을 유도하되 자유도를 제한합니다. 소프트웨어의 테스트 하네스(test harness)처럼, 실행 경로를 사전에 규정하고 이탈을 감지합니다.
핵심 원칙은 “기억에 의존하지 않고, 구조가 강제한다” 입니다.
도구의 관점에서 보면 자연스러운 결론입니다. 도구가 올바르게 동작하기 위한 제약은 도구 안에 있어야 합니다. 외부 메모리에 의존하면 환경이 바뀔 때 깨집니다. 하네스는 스킬 파일 자체에 내장되므로, 스킬을 설치하면 행동 제약도 함께 설치됩니다.
패턴 1: 금지 패턴 선언 (Forbidden Pattern)
스킬 파일 상단에 “하지 말아야 할 것”을 테이블로 명시합니다. 단순히 “위임하라”가 아니라, 금지 행위 + 이유 + 올바른 방법을 삼중으로 기술합니다.
Before (텍스트 지시):
## 규칙
- 이슈 생성/시작/완료는 `devex:flow`에 위임 — 중복 구현 금지
After (금지 패턴 선언):
## 금지 패턴 (HARD CONSTRAINTS)
| 금지 행위 | 이유 | 올바른 방법 |
|----------|------|------------|
| Dooray 상태 변경 API 직접 호출 | devex:flow의 데일리로그/태그/CC 후속 처리 누락 | devex:flow issue start 위임 |
| Dooray 태스크 본문 PUT 직접 호출 | devex:flow의 시작일시 기록, 필드 보존 로직 누락 | devex:flow에서 처리 |
| 데일리로그 직접 수정 | devex:flow의 장기→일일 이동 로직과 충돌 | devex:flow가 처리 |
차이점:
- “규칙” → “금지 패턴” — 용어 자체가 제약을 암시합니다
- 이유를 명시하여 LLM이 금지의 근거를 이해하므로 우회 경로도 차단됩니다
- 올바른 방법을 병기하여 대안이 불명확할 때 직접 경로로 회귀하는 것을 방지합니다
패턴 2: 위임 게이트 (Delegation Gate)
위임 단계를 (GATE) 태그로 표시하고, 위임의 구체적 실행 방법과 기대 산출물을 명시합니다.
Before:
### Step 2: 이슈 처리
- 기존 이슈: 티켓 번호로 `devex:flow` issue start 위임
After:
### Step 2: devex:flow 위임 — 이슈 처리 (GATE)
> **이 단계는 devex:flow 스킬에 위임한다. org-flow가 직접 처리하지 않는다.**
주 레포 디렉토리로 이동한 후, devex:flow의 issue 가이드를 읽고 워크플로우를 실행한다.
devex:flow가 수행하는 작업 (org-flow는 관여하지 않음):
1. Dooray 태스크 상태 변경
2. 태그/CC gap fill
3. 본문에 시작 일시 추가
4. 주 레포 브랜치 생성
5. 데일리로그 일일 계획에 이슈 추가
차이점:
(GATE)태그로 이 단계가 통과 조건이 있는 관문임을 명시합니다- 위임 대상의 작업 목록을 나열하여 “직접 하면 이것들이 누락된다”는 것을 자명하게 합니다
- “org-flow가 직접 처리하지 않는다” — 이중 부정이 아닌 직접적 금지입니다
패턴 3: 검증 체크포인트 (Verification Checkpoint)
위임 게이트 직후에 검증 항목을 배치합니다. 검증 실패 시 다음 단계 진입을 차단합니다.
#### 위임 결과 검증 (CHECKPOINT)
devex:flow 완료 후, 아래 항목을 모두 확인한다.
**하나라도 실패 시 Step 3으로 진행하지 않는다.**
- [ ] 주 레포에 feature/{ticket} 브랜치 존재
- [ ] Dooray 태스크 상태 = "In progress"
- [ ] 데일리로그 일일 계획에 해당 이슈 항목 존재
이 패턴이 효과적인 이유는 세 가지입니다.
- LLM이 직접 API를 호출했다면 데일리로그 항목이 없으므로 체크포인트에서 실패합니다
- 실패 시 “다음 단계로 진행하지 않는다”는 명시적 중단 조건이 있습니다
- 검증 항목이 위임 대상의 산출물과 1:1 매핑됩니다
패턴 4: 역할 경계 테이블 강화
역할 분담 테이블에 “직접 수행 여부” 컬럼을 추가하여, 각 행위가 위임인지 직접인지를 명시합니다.
| 책임 | 담당 | org-flow 직접 수행 여부 |
|------|------|----------------------|
| 이슈 시작 | devex:flow issue start | **금지** — 위임만 |
| 스코핑 | org-flow | 직접 |
| 관련 레포 브랜치 생성 | org-flow | 직접 |
“금지”라는 단어가 각 행에 반복되면서, LLM이 테이블을 스캔할 때 직접 수행 가능한 작업과 위임 전용 작업을 즉시 구분할 수 있습니다.
설계 원칙 정리
하네스 엔지니어링의 네 가지 설계 원칙입니다.
| 원칙 | 설명 | 대응 패턴 |
|---|---|---|
| 명시적 금지 | “하라”보다 “하지 마라”가 더 강한 제약 | 금지 패턴 선언 |
| 이유 동반 | 금지의 근거를 알아야 우회도 차단됨 | 금지 패턴의 “이유” 컬럼 |
| 게이트 전환 | 단계를 “설명”이 아닌 “관문”으로 설계 | 위임 게이트 |
| 산출물 검증 | 과정이 아닌 결과로 올바름을 판정 | 검증 체크포인트 |
하네스 vs 메모리 vs 훅
LLM 에이전트의 행동을 제어하는 세 가지 메커니즘을 비교합니다.
| 차원 | 피드백 메모리 | 하네스 엔지니어링 | 시스템 훅 |
|---|---|---|---|
| 제어 강도 | 약함 (참조 가능) | 중간 (구조적 유도) | 강함 (실행 차단) |
| 소속 | 도구 외부 (환경 상태) | 도구 내부 (스킬 파일) | 도구 외부 (시스템 설정) |
| 이식성 | 환경 교체 시 유실 | 도구와 함께 이동 | 설정 동기화 필요 |
| 유지보수 | 메모리 파일 관리 | 스킬 파일 수정 | 훅 스크립트 개발 |
| 적합한 상황 | 선호/스타일 전달 | 위임 체계, 실행 순서 | 보안, 데이터 보호 |
| 우회 가능성 | 높음 | 낮음 | 없음 |
핵심적인 차이는 소속입니다. 하네스는 도구 안에 있으므로 도구와 생명주기를 같이합니다. 메모리는 도구 바깥에 있으므로 환경이 바뀌면 깨집니다. 도구가 온전히 동작하기 위한 제약이라면, 도구 안에 있어야 합니다.
실무에서는 세 가지를 조합하고 있습니다.
- 선호/스타일 → 피드백 메모리
- 위임 체계/실행 순서 → 하네스 엔지니어링
- 보안/데이터 보호 → 시스템 훅
적용 결과
구조 변경 비교
org-flow 스킬을 하네스 패턴으로 리팩터링한 결과입니다.
| 항목 | Before | After |
|---|---|---|
| 금지 패턴 | 없음 | 4개 행위 + 이유 + 대안 명시 |
| 위임 게이트 | “위임” 한 줄 | (GATE) 태그 + 작업 목록 + 금지 재확인 |
| 검증 체크포인트 | 없음 | 3개 항목 검증 후 다음 단계 진입 |
| 역할 경계 | 2컬럼 (책임, 담당) | 3컬럼 (책임, 담당, 직접 수행 여부) |
| 스킬 파일 규칙 섹션 | 하단 6줄 | 상단 금지 패턴 테이블로 승격 |
핵심 변화는 규칙의 위치입니다. 기존에는 스킬 파일 하단의 “규칙” 섹션에 있어 LLM이 실행 단계를 먼저 읽고 규칙은 나중에 참조했습니다. 리팩터링 후에는 금지 패턴이 스킬 파일 상단에 위치하여, 실행 단계보다 먼저 읽힙니다.
실전 검증
하네스 패턴 적용 후 실제 이슈 시작 시 devex:flow 위임이 정상 동작하는지 추적한 결과입니다.
| 회차 | 세션 | devex:flow 위임 | 비고 |
|---|---|---|---|
| 0 (적용 전) | 최초 세션 | 실패 (직접 API 호출) | 하네스 적용 계기 |
| 1 | 적용 후 첫 세션 | 성공 | 금지 패턴+게이트+체크포인트 모두 동작 |
| 2 | 동일 세션 finish | 성공 | org-flow finish에서 github 스킬로 위임 |
회고: 오버 엔지니어링의 경계
하네스 엔지니어링을 정리한 뒤, 운영 중인 플러그인 전체에 적용할 수 있는지 점검했습니다. 결과는 의외였습니다.
실제로 하네스가 필요한 플러그인은 devex 하나뿐이었습니다. toolkit의 스킬들은 단일 책임으로 설계되어 있어 위임 체계 자체가 없습니다. ssh-tools는 서브 에이전트가 독립적으로 동작하므로 금지 패턴이 불필요합니다. 하네스가 해결하는 문제 — “LLM이 위임하지 않고 직접 처리한다” —는 위임 구조가 있는 스킬에서만 발생합니다.
방법론을 만들면 모든 곳에 적용하고 싶은 유혹이 있습니다. 하지만 문제가 없는 곳에 해법을 넣으면 그것이 오버 엔지니어링입니다. 금지 패턴 테이블과 게이트와 체크포인트는 구조적 비용입니다. 스킬 파일이 복잡해지면 LLM이 읽는 데 더 많은 토큰을 소비하고, 유지보수할 표면도 넓어집니다.
하네스 엔지니어링은 “모든 스킬에 적용하는 표준”이 아니라, 위임 실패가 반복될 때 꺼내는 도구입니다. 필요한 곳에만 쓸 때 가치가 있습니다.
마무리
하네스 엔지니어링은 LLM 에이전트의 “기억력”에 기대지 않고, 스킬 파일의 구조 자체가 올바른 실행 경로를 강제하는 설계 방법론입니다.
플러그인은 도구입니다. 설치하면 온전히 동작해야 합니다. 행동 교정이 도구 바깥(메모리)에 있으면, 환경이 바뀔 때마다 같은 교정을 반복해야 합니다. 하네스 엔지니어링은 이 교정을 도구 안에 넣어서 해결했습니다.
이 방법론이 필요한 신호입니다.
- 같은 피드백을 여러 세션에 걸쳐 반복하고 있다
- 피드백 메모리를 추가해도 다음 세션에서 동일한 실수가 재발한다
- 위임 체계가 있는데 LLM이 직접 처리하는 경로를 선택한다
- 스킬을 다른 환경이나 다른 사람에게 공유했을 때 동일한 문제가 발생한다
이럴 때 메모리를 더 쌓는 대신, 스킬 파일 자체를 하네스로 리팩터링하는 것이 근본적인 해결입니다.
이 글은 Claude와 함께 작업했습니다.