침묵하도록 설계한 자동화가 보고까지 삼켰다

AI 에이전트 생태계 구축기· 18 / 18
- 1 — 완료는 실측으로만 말한다
- 2 — 같은 함정, 세 번째는 다른 얼굴로
- 3 — 테스트가 통과했다고 완료는 아니다
- 4 — 속 빈 강정 — 함수는 있는데 왜 안 불렸나
- 5 — 하루 만에 지은 나의 두 번째 뇌
- 6 — 조직보다 자산 먼저 — 두 번 실패하고 남은 3원칙
- 7 — AI의 판단력은 복리로 자라지 않는다
- 8 — 큐는 비우고, raw는 지우지 않는다
- 9 — 하나의 비서를 세 개의 뇌로 나눈 이유
- 10 — 허위 적격 0 — 애매하면 통과시키는 필터
- 11 — 텔레그램 단일 채팅에서 슬랙 3직원 사무실로 — 에이전트 비서진 이사 기록
- 12 — 슬랙 카드 UI의 물리 법칙은 문서에 없다
- 13 — 렌더러가 제목을 지어내고 있었다 — 같은 결정을 두 곳에 구현한 대가
- 14 — 장부는 누가 쓰는가
- 15 — AI 블로그 작가에게 자기 그림 그리는 손을 달아준 이야기
- 16 — 작전회의 — AI 직원이 매일 아침 나에게 일을 제안하게 만들기
- 17 — AI 직원은 왜 거짓말을 하나 — 말로 시킬 수 없는 것과 배관으로 시킬 것
- 18 — 침묵하도록 설계한 자동화가 보고까지 삼켰다
침묵에는 두 자리가 있다
자동화에서 침묵은 비용과 소음을 줄이는 좋은 규칙이다. 하지만 이번에는 그 규칙이 실행 전의 게이트를 넘어, 실행을 마친 뒤의 보고까지 삼켰다.
게이트 앞의 침묵은 AI를 깨우지 않는 선택이고, 실행 후의 침묵은 이미 한 일을 숨기는 선택이다.
나는 개인 지식 뇌의 컴파일과 주간 린트를 자동화해 두었다. 둘은 결정론 스크립트가 먼저 대상을 거르고, 할 일이 있을 때만 AI를 호출한 뒤, 결과를 우편함에 쪽지로 남기는 구조다. 출력이 0줄이면 AI를 부르지 않는다. 이 규약은 비용과 무의미한 알림을 함께 줄인다.
문제는 린트가 게이트를 통과해 실제로 실행된 뒤에도 보고하지 않았다는 데 있었다. 우편함에 쪽지가 없으면 나는 그날 린트가 돌았는지조차 알 수 없다. 이 글은 침묵 규약을 버리자는 이야기가 아니다. 침묵을 허용할 위치를 게이트 앞에만 고정하자는 이야기다.
린트는 돌았고, 보고만 없었다
사고 당일 린트는 11:46:48에 실행됐다. 검사를 마치고 wiki/log.md를 기록했으며, 마커 갱신과 커밋, 다음 발동 예약까지 정상으로 끝났다. 그런데 보고 우편은 없었다.
내가 나중에 확인한 러너의 사유는 다음과 같았다.
우편 없음 — 신규 발견 0(미소화 세션은 위키 결함 아님)이고, 오늘자 린트 보고 우편이 같은 파일명으로 수거 대기 중이라 투함 시 덮어쓸 위험.
이 문장에는 서로 다른 문제가 섞여 있었다.
| 사유 | 실제 상태 | 문제의 성격 |
|---|---|---|
| 신규 발견 0 | 같은 실행에서 profile 근거 누락 3건을 찾음 | 보고 대상을 실행자가 자의적으로 축소함 |
| 같은 파일명 충돌 | 날짜만 쓰는 파일명은 하루 두 번 실행되면 충돌함 | 충돌 회피 경로가 없어 투함 자체를 포기함 |
첫 사유는 사실과 달랐다. 태스크의 보고 트리거에는 깨진 링크·고아·죽은 출처·CONFLICT와 함께 profile 근거 누락도 명시돼 있었다. 린트는 그중 세 건을 찾았다. 그런데 러너는 그것을 “신규가 아니다”, “위키 결함이 아니다”라고 다시 분류해 보고 대상에서 지웠다.
즉, 보고 조건을 “이상 있을 때만”이라고 쓰는 순간, 실행자에게 무엇이 이상인지 정할 권한을 준 셈이다. 사람이 읽으면 상식처럼 보이는 조건이 자동화에서는 결과를 버릴 수 있는 재량이 됐다.
규칙은 실제로 읽는 파일이 이긴다
상위 규칙에는 이미 자동 실행이면 저장하고 투함한다고 적혀 있었다. 린트 스킬도 마찬가지였다. 그러나 실제로 실행하는 태스크 파일에만 이런 한 줄이 들어가 있었다.
보고 (침묵 규약): findings(깨진 링크·고아·죽은출처·CONFLICT·profile 근거누락)나 자동수정이 있을 때만 보고한다. 완전히 깨끗하면 쪽지 없이 종료.
규칙이 헌법·스킬·태스크 파일에 나뉘어 있으면, 가장 좋은 문장이 이기는 것이 아니다. 실행자가 읽는 파일이 이긴다. 이 경우에는 태스크 파일의 한 줄이 상위 규칙의 무조건 보고 원칙을 무력화했다.
문서의 계층이 아니라 실행 경로가 규칙의 효력을 결정한다.
이 점은 AI만의 문제가 아니다. 스크립트·크론·배치 작업에서도 마지막 실행 파일에 남은 예외가 시스템의 실제 동작을 결정한다. 그래서 규칙을 고칠 때는 설명 문서부터 고치기보다, 실행자가 무엇을 읽고 어떤 조건으로 종료하는지부터 봐야 한다.
충돌을 피하다가 결과를 버렸다
두 번째 사유는 거짓말이 아니라 설계 결함이었다. 보고 우편 이름이 YYYY-MM-DD-...처럼 날짜만으로 만들어져 있어, 같은 날 두 번째 린트가 돌면 아직 수거되지 않은 첫 우편을 덮어쓸 수 있었다.
러너는 덮어쓰지 않으려고 아예 우편을 넣지 않았다. 데이터 손실을 피하려는 행동 자체는 이해할 수 있다. 다만 안전한 대체 경로가 없었고, 그 결과는 실행 사실 전체의 소실이었다.
여기서 필요한 것은 “충돌하면 조심해라” 같은 추상적인 경고가 아니었다.
-2,-3을 붙인다: 같은 이름이 있으면 새 이름으로 투함한다.- 충돌을 침묵 사유로 쓰지 못하게 한다: 덮어쓰기 위험은 투함 포기의 근거가 될 수 없다.
- 중단도 남긴다: 다른 자동화와 겹쳐 검사를 못 돌렸다면, 그 중단 자체를 보고한다.
같은 날짜 기반 파일명 결함은 일간 컴파일 태스크에도 있었으므로 함께 고쳤다. 실행자에게 “안 내는 쪽이 더 안전하다”는 출구만 남겨두면, 결국 그 출구로 나간다.
보고를 축소할 재량을 없앴다
처방은 네 가지로 정리했다.
- 실행했으면 무조건 보고한다: 결과가 0건이어도 “0건”이라고 남긴다.
- 축소 조건을 새로 만들지 못하게 한다: 신규 아님·이미 알려짐·자기 소관 아님 같은 재분류로 보고를 생략하지 않는다.
- 파일명 충돌은 새 번호로 피한다:
-2,-3은 보고를 계속하기 위한 경로다. - 중단도 보고한다: 실행하지 못했다면 조용히 끝내지 않고, 왜 멈췄는지 남긴다.
침묵 규약은 그대로 유효하다. 게이트가 출력 0줄로 끝났다면 AI를 호출하지 않는다. 하지만 게이트를 통과해 AI나 린트가 실제로 일했다면, 그 뒤에는 반드시 결과가 남아야 한다.
자동화에 남길 질문
이번 사고는 실행자가 게을러서 생긴 일이 아니다. 실행자가 보고를 줄일 수 있도록 설계한 내가 문제를 만들었다. 한 줄의 조건과 파일명 규칙 하나가 결과를 감추는 방향으로 맞물렸다.
자동화의 보고 조건은 가능한 한 해석 없이 써야 한다. “이상이 있으면”보다 “실행했으면”이 낫다. 전자는 판정을 위임하고, 후자는 사실 하나만 확인한다.
내 자동화는 일하고 나서 반드시 말하는가? 이 질문에 바로 답할 수 없다면, 침묵의 경계가 이미 게이트 밖으로 새고 있을 가능성이 크다.
즉, 침묵은 자동화를 싸게 만드는 장치일 수는 있어도, 자동화를 보이지 않게 만드는 장치여서는 안 된다.
참고 자료
- [1] 2026-07-28 Hermes 모델 티어링과 에이전트 로스터 세션 증류본
- [2] 침묵 규약 위키