하네스 연구 · 2026-07-30

에이전트별 자동 검사는
이미 있었다

"사용자·프로젝트 단위 자동 검사 파이프라인은 있는데 에이전트 단위는 없다"는 통념은 절반만 맞다. Claude Code 플랫폼은 이미 세 가지로 지원하고 있었고, 없는 것은 하네스가 그걸 쓰지 않은 것뿐이다 — 89개 에이전트 중 채택 0개. 이 페이지는 그 원인분석과 실측, 그리고 만들어 본 파이프라인을 정리한다.

없는 건 기능이 아니라 채택이었다

먼저 용어 하나. 훅(hook)은 "특정 순간이 오면 자동으로 실행되는 작은 검사 스크립트"다. 예를 들어 파일을 저장할 때마다 문법을 검사하거나, 서버에 코드를 올리기 직전 테스트가 통과했는지 막아서는 관문이 훅이다. Claude Code에서 이 훅은 지금까지 "사용자 전체" 또는 "프로젝트 하나" 단위로만 거는 줄 알려져 있었다. 그런데 "에이전트 하나하나마다 다른 훅을 건다"는 건 못 한다는 통념이 있었다. 실측해 보니 플랫폼은 이미 세 가지 방법으로 이걸 지원하고 있었다. 진짜 문제는 우리 하네스가 89개 에이전트 중 단 하나도 그 기능을 쓰지 않았다는 것이었다.

0 / 89에이전트 채택률
3플랫폼 지원 방식
8격리 실측 실험
13Codex 적대 리뷰
플랫폼(Claude Code v2.1.219)이 이미 지원하는 3가지 — 전부 실측 확인 frontmatter 훅 에이전트 정의 파일(.md) 맨 위 설정칸에 훅을 직접 적음 그 에이전트가 도는 동안만 유효 ✓ 발화 확인 (debug 로그) 사용자 스코프는 신뢰승인 불필요 agent_type 식별자 훅에 들어오는 입력(stdin)에 "지금 어느 에이전트냐"가 담김 메인 대화엔 없고 서브에이전트만 ✓ 에이전트 3건 / 메인 0건 실측 = 분배기의 판단 근거가 됨 SubagentStart 필터 서브에이전트가 시작/종료할 때 에이전트 이름으로 훅을 매칭 matcher: "hookprobe" 정확 발화 ✓ 4/4 매칭, 오발화 0건 이벤트: Start · Stop · TaskDone… 플랫폼은 준비돼 있었다 — 하네스 채택만 0 / 89 user·project·plugin 에이전트 전부에서 훅 사용 0건
세 가지 지원 방식을 8개 격리 실험으로 하나씩 발화시켜 확인했다. 초록 체크(✓)는 실제 로그·덤프 파일로 증거를 남긴 항목이다.
왜 아무도 안 썼나 — 두 층의 이야기

원인은 두 겹이다. 하나는 기능이 늦게 생긴 플랫폼의 역사, 다른 하나는 그 기능을 지나친 우리 하네스의 사각지대다. 진짜 원인은 오른쪽이다.

플랫폼 — 역사적 이유

늦게 생긴 기능

"원래 훅은 설정 파일만 소유했다"

  • 초기 설계: 훅은 사용자·프로젝트 설정 파일에만 존재. 에이전트 정의 파일은 훅을 가질 수 없었다
  • 훅에 들어오는 입력에 "어느 에이전트냐" 정보가 아예 없어, 분배로 우회하는 것조차 불가능했다
  • 에이전트 파일은 저장소로 유통되는 문서라, 거기에 실행 명령을 붙이면 악성 저장소의 공격 통로가 된다
  • 그래서 나중에 기능이 추가될 때도 프로젝트 에이전트엔 "신뢰 승인" 관문이 함께 붙었다 (실측 재현)
하네스 — 진짜 원인

보이지 않던 사각지대

"기능이 생긴 걸 관측할 표면이 없었다"

  • 파이프라인이 기능 등장 전에 굳어졌고, 다시 검토할 계기(트리거)가 없었다
  • 참조하던 문서 스냅샷이 낡아서, frontmatter 훅·agent_type 입력이 문서에 아예 없었다
  • 텔레메트리(관측 로그)가 agent_type을 기록하지 않아, "훅이 에이전트 안에서 돈다"는 사실이 측정에 안 잡혔다 — 갭이 갭으로 안 보였다
  • 도구 화이트리스트·종료 훅·문장 지시로 우회해 와서, 부재가 마찰로 드러나지 않았다
같은 명령이 위치에 따라 갈린다

방안의 심장은 분배기(dispatcher)다. 설정 파일에 훅 하나만 걸어두고, 그 훅이 입력의 agent_type을 읽어 "지금 어느 에이전트냐"에 따라 알맞은 검사로 넘긴다. 89개 에이전트 파일을 하나도 안 건드리고 중앙에서 에이전트별 정책을 관리할 수 있다. 아래는 실제로 돌려 본 결과다 — 똑같은 date 명령이 메인 대화에선 통과하고, 특정 에이전트 안에서는 막힌다.

agent_type 분배기 — 하나의 훅, 위치별 상이 판정 메인 대화가 실행: date 입력에 agent_type 없음 hookprobe 에이전트가 실행: date 입력에 agent_type = hookprobe 분배기 (설정 훅 1개) 입력의 agent_type을 읽어 알맞은 검사로 넘김 · 89개 에이전트 파일 무수정 에이전트 없음 hookprobe 규칙 적용 통과 · exit 0 메인엔 이 게이트가 없으므로 그대로 실행 차단 · exit 2 이 에이전트 안에선 echo만 허용 → date 거부 실측 e2e: MAIN_DATE=통과 · AGENT_ECHO=통과 · AGENT_DATE=차단
실제 Claude 세션으로 돌린 결과다. 훅은 단 하나인데, 입력에 담긴 에이전트 이름을 보고 같은 명령을 다르게 판정한다 — 이것이 에이전트 스코프 훅의 핵심이다.
3층으로 짓는다 — 관측부터

권장 순서는 C → B → A다. 관측을 먼저 깔아야 다음 두 층의 효과가 수치로 측정되고, 분배기가 중앙 규약을 세운 뒤 개별 훅은 꼭 필요한 고위험 에이전트에만 붙이는 것이 유지비가 가장 낮다.

Tier C · 먼저

관측

텔레메트리(관측 로그)에 agent_type·agent_id 두 필드를 추가한다. 이게 없으면 아래 두 층을 깔아도 "훅이 에이전트 안에서 돈다"는 사실이 측정에 안 잡힌다. 몇 줄짜리 변경.

2
추가 필드
최소
변경량
Tier B · 중심

분배기

설정 훅 하나가 agent_type을 읽어 에이전트별 검사로 넘긴다. 89개 에이전트 파일을 안 건드리고 중앙에서 정책을 관리한다. "특정 에이전트 안에서만 위험 명령 차단" 같은 강제 게이트를 실증 완료.

1
중앙 훅
0
에이전트 수정
Tier A · 선별

개별 훅

에이전트 정의 파일에 훅을 직접 붙인다. 사용자 스코프 에이전트는 신뢰 승인 배관 없이 바로 동작한다(실측). 인프라를 되돌릴 수 없게 만지는 devops, 검증 담당 user-proxy 같은 고위험 에이전트에만 선별 적용.

고위험
선별 적용
즉시
user 스코프
지원 방식 플랫폼 상태 하네스 채택 실측 증거
frontmatter 훅 지원됨 — 에이전트 수명 동안 유효 0 / 89 debug 로그 Registered 1 frontmatter hook(s)
agent_type 입력 지원됨 — 서브에이전트 훅에만 존재 미사용 에이전트 3건 vs 메인 0건 (덤프)
SubagentStart 필터 지원됨 — 에이전트 이름으로 매칭 미사용 matcher 4/4 발화, 오발화 0
신뢰 승인 관문 프로젝트 에이전트만 필요 · 사용자 스코프는 불필요 즉시 채택 가능 "not trusted" 에러 재현
"헛소리라고 가정하라" — 13라운드

방안을 실제 코드로 만든 뒤, 다른 모델(Codex)에게 "이건 헛소리다"라고 가정하고 결함을 찾게 했다. 라운드마다 진짜 결함이 나왔다. 아래 타임라인에서 위쪽 붉은 마커는 심각(CRITICAL) 결함, 아래 회색은 높음(HIGH) 결함이다. 핵심 로직의 심각 결함은 6라운드에서 사라졌고, 이후는 곁가지(로그 유틸리티)의 하드닝이 이어지다 13라운드에서 전부 통과(CLEAN)로 수렴했다.

Codex 적대 리뷰 R1 → R13 수렴 CRITICAL HIGH R1 eval 우회 R2 개행 우회 R3 R4 R5 R6 TOCTOU·토큰화 R7 R9 R10 R11 디렉토리 R12 R13 CLEAN 핵심 로직 — 심각 결함 (R6에서 종료) 곁가지 로그 유틸 하드닝 → 수렴 각 수정마다 우회 벡터를 단위 테스트로 전수 방어 확인 · 공백 경로 e2e 재검증
라운드가 반복되며 같은 계열(문자열 필터의 무한 우회, 로그의 적대적 파일시스템 공격)이 나오면, 6번째 패치 대신 설계·주장을 낮추는 것이 옳다 — 완전 방어가 불가능한 부분은 OS 격리에 위임하고 그 한계를 문서로 남겼다.
핵심 통찰

"헛소리라고 가정하라"는 적대 검증이 실제로 결함을 잡았다. 그중 하나는 내가 놓칠 뻔한 진짜 버그였다 — 로그 유틸을 파이썬으로 바꾸며 입력 통로가 막혀 데이터가 하나도 안 써졌는데, "실제로 기록됐는지" 검증하는 습관 덕에 잡았다. 결론은 단순하다: 에이전트 스코프 훅은 이미 있었고, 없던 건 채택뿐이다. 관측(C) → 분배기(B) → 개별 훅(A) 순으로 3층을 세우면 89개 에이전트를 안 건드리고도 에이전트별 강제 게이트를 얻는다.