AI 에이전트로 블로그를 매일 발행하기 — 파이프라인 8단계와 기계가 막는 관문 3곳
매일 아침 8시, 사람이 아무것도 누르지 않아도 블로그 다섯 곳에 글이 한 편씩 올라갑니다. 주제를 정하고 법령 원문을 확인하고 본문을 쓰고 삽화를 그리고 검사를 통과시키고 커밋까지 하는 일을 AI 에이전트가 이어서 합니다. 이 글은 그 파이프라인이 어떻게 여덟 단계로 도는지, 그리고 사람이 지켜보지 않는 동안 규칙이 무너지지 않도록 어디에 기계 관문을 세 곳 세웠는지에 대한 기록입니다.
먼저 밝혀 둘 게 있습니다. 이 사이트(잡동사니 노트)는 세금·법률 블로그와 달리 정확도 게이트가 꺼져 있습니다. 그래서 이 글에는 시행일이나 조문을 강제로 붙이지 않습니다. 대신 note 의 기준은 다른 데 있습니다 — 직접 돌려보지 않은 것을 후기처럼 쓰지 않는다는 것입니다. 그래서 아래 내용의 근거는 전부 이 저장소의 코드와 FLOW.md 에 남은 기록입니다.
하루의 자동 일정. 발행은 08시 한 번, 나머지는 그 뒤를 따라 붙는다.
하루가 어떻게 도는가
시작 신호는 사람이 아니라 스케줄러입니다. Paperclip 이라는 사내 CMP 의 루틴이 매일 08:00(Asia/Seoul)에 발화하고, 이 루틴이 실행 이슈를 만들어 에이전트에 배정하면 그게 곧 러너를 깨우는 신호가 됩니다. 러너는 발행 스크립트(pipeline/daily.sh)를 돌리고 그 안에서 사이트별로 파이프라인이 순서대로 실행됩니다.
발행 대상은 매일 다섯 사이트 전부입니다. 2026년 8월 17일부터 그렇게 바뀌었습니다. 그전에는 money 한 곳만 매일 돌고 나머지가 한 자리를 요일별로 나눠 썼는데, 그러다 보니 정치 사이트 두 곳이 몇 주가 지나도록 글 한 편에 머물렀습니다. 지금은 순서만 남았습니다 — money 가 항상 맨 앞입니다. 뒤쪽이 타임아웃으로 잘리는 날에도 살아남는 쪽이 money 여야 하기 때문입니다. 발행 자체가 끝나면 브리핑과 데드맨 점검, 티스토리 미러링 같은 후속 작업이 뒤를 따릅니다.
여덟 단계 — planner에서 distributor까지
파이프라인은 여덟 단계지만, 에이전트 정의 파일은 일곱 개입니다. .claude/agents/ 에 planner·researcher·writer·illustrator·editor·publisher·distributor 일곱이 들어 있고, 윤문(humanize)은 에이전트가 아니라 도구 단계이기 때문입니다. 그래서 "에이전트가 여덟 개"라고 쓰면 틀립니다. 순서는 이렇습니다.
- planner — 뉴스를 훑어 주제를 확정합니다. 쓸 만한 주제가 없으면 그날은 여기서 정상 종료하고 알림만 보냅니다.
- researcher — 1차 출처로 사실을 확인합니다. 핵심 수치를 확인하지 못하면 발행을 거르고 종료합니다.
- writer — 리서치 메모에 없는 사실은 쓰지 못합니다. 기억에서 세율을 꺼내는 걸 막는 규칙입니다.
- illustrator — 숫자·조건이 들어가는 삽화는 SVG 로 직접 그리고, 정보를 담지 않는 히어로 사진만 생성 이미지를 씁니다.
- humanize — 윤문 전에 수치를 스냅샷으로 잠그고(
fact-lock snapshot), 윤문한 다음 다시 대조합니다(verify). - editor — 판정만 합니다. 본문을 직접 고치지 않고, 같은 항목을 세 번 반려하면 중단합니다.
- publisher — draft 를 해제하고 빌드한 뒤 커밋합니다.
- distributor — 카드뉴스·스레드 같은 파생물을 만듭니다. 여기서 실패해도 원본 글은 살아남습니다.
여덟 단계 흐름. 왼쪽으로 흐르다 확인이 안 되면 아래 거름 분기로 빠진다.
규칙을 프롬프트에 두지 않은 이유
에이전트에게 "1200자를 넘겨라", "h2 를 세 개 이상 써라" 하고 프롬프트로 부탁할 수도 있습니다. 하지만 프롬프트는 지켜지지 않을 때 조용합니다. 그래서 본질적인 규칙은 종료 코드를 뱉는 스크립트에 박아뒀습니다. 관문은 세 종류입니다.
첫째는 fact-lock 입니다. 윤문 도구가 문장을 다듬는 과정에서 숫자 하나가 틀어질 수 있으니, 윤문 전후의 숫자·조문·날짜·링크를 집합으로 대조해 0 또는 1의 종료 코드로 답합니다. 다르면 윤문본을 버립니다. 둘째는 check-content(post:check)로, 구조와 정확도 규칙을 검사합니다. 셋째는 push 이후 CI 가 다시 check-content 와 테스트, 빌드를 돌립니다.
여기서 눈여겨볼 점은 check-content 를 세 번 돌린다는 것입니다. editor 앞에서, push 앞에서, 그리고 CI 에서. FLOW.md 에는 그 이유가 한 줄로 적혀 있습니다 — "같은 명령을 세 번 돌린다. 기준이 두 벌이면 반드시 어긋나기 때문이다." 검사 로직을 각 단계에 새로 짜 넣으면 서로 미세하게 달라지고 그 틈으로 문제가 샙니다. 그래서 판정 기준을 pipeline/check-content.ts 한 곳에 두고 모두 그것만 부릅니다.
이 사이트에서 실제로 걸리는 건 구조 게이트뿐입니다. check-content 코드는 if (!editorial?.disclaimer) return issues; 한 줄로 정확도 검사를 건너뛰는데, note 의 config 에는 disclaimer 키가 없어서 시행일·조문·고지 검사가 켜지지 않습니다. 남는 규칙은 h2 38개, 본문 1200자(공백·코드·이미지 제외), 본문 이미지 36장, h1 금지 같은 뼈대뿐입니다. 오류가 한 건이라도 있으면 명령이 exit 1 로 떨어져 push 가 막힙니다.
관문 세 곳의 위치. 어디서 걸리든 화살표는 앞 단계로 되돌아간다.
원본과 파생물의 실패를 다르게 다룬다
실패는 다 같은 실패가 아닙니다. 이 파이프라인의 핵심 원칙은 하나입니다 — 블로그 발행이 실패하면 나머지는 전부 취소되고, 소셜이 실패해도 블로그는 남는다. 원본 글은 반드시 지키고 그 위에 얹는 파생물은 실패해도 그 채널만 조용히 건너뜁니다.
FLOW.md 의 실패 지점별 표를 옮기면 이렇습니다. 주제가 없거나 사실 확인이 안 되면 정상 종료하고 그날은 글이 없습니다. editor 가 같은 항목을 세 번 반려하면 중단하고 커밋을 남기지 않습니다. post:check 가 실패하면 push 하지 않되 커밋은 남겨 사람이 볼 수 있게 합니다. push 자체가 실패하면 중단하고 알림을 보냅니다. 반면 카드·스레드·티스토리 같은 파생 채널이 실패하면 원본은 그대로 두고 그 채널만 빠집니다.
실패 지점마다 멈추는 범위가 다르다. 아래로 갈수록 원본에서 멀어진다.
무인 실행이 거짓말하지 않게 만든 것들
사람이 안 볼 때 가장 무서운 건 실패가 아니라 성공한 척하는 실패입니다. 그래서 몇 가지 장치를 덧댔습니다.
첫째, 완료 계약입니다. 파이프라인은 출력 마지막 줄에 PIPELINE_RESULT 발행|거름|중단 을 찍어야 하고, pipeline/verdict.ts 가 이 줄을 읽습니다. 이 줄이 없으면 결과를 "미완료"로 떨어뜨립니다. 모르면 정상으로 보는 쪽이 아니라 모르면 이상으로 보는 쪽에 뒀습니다. 계기가 있었습니다 — 2026년 8월 12일, politics-right 를 돌리던 중 researcher 가 사실을 확인하는 도중에 오케스트레이터가 "완료 알림을 기다립니다"로 턴을 끝내 버렸는데, claude 프로세스는 exit 0 으로 끝나 러너가 "주제 없음"으로 잘못 알렸습니다. 종료 코드만 믿으면 이렇게 속습니다.
둘째, 러너 안전장치입니다. 발행 스크립트는 .runner.lock 을 mkdir 로 원자적으로 잡아, 이미 돌고 있으면 물러납니다. 그리고 하루 기동 횟수를 BLOG_MAX_RUNS_PER_DAY(기본 3)로 못 박습니다. 이건 실제 사고에서 나온 값입니다. 2026년 8월 7일, track open 이 러너 자신을 이슈 담당자로 박는 바람에 러너가 자기를 다시 부르는 신호가 됐고 그렇게 자기를 14,221번 다시 불렀습니다. 잠금만으로는 겹치지 않고 하나씩 빠르게 이어지는 재기동을 못 막아서, 원인과 무관하게 횟수 자체를 막았습니다.
여기에 하나 더 있습니다. 스레드 발행을 에이전트에게 프롬프트로 시켰더니 34편 동안 0편이 나갔습니다. 그래서 지금은 스레드를 에이전트가 아니라 러너가 push 뒤에 기계적으로 올립니다. "알아서 잘 해줘"가 통하지 않는 일은 코드로 내려버린 셈입니다.
남은 것과 사람이 하는 일
자동화하지 않은 자리도 분명히 있습니다. 카카오 로그인은 2단계 인증이 걸려 사람이 한 번 해줘야 하고, 스레드 토큰 발급도 마찬가지입니다. 무엇보다 정정 판단은 사람이 합니다. post:stale 이라는 명령이 인용한 법령이 그 뒤에 개정된 글을 찾아 주지만, 그걸 보고 고칠지 말지는 자동으로 결정하지 않습니다. push 와 배포도 기본은 커밋까지이고, 그 너머는 사람이 지시할 때만 진행합니다.
정리하면 이렇습니다. 매일 여덟 단계가 무인으로 돌지만, 규칙은 프롬프트가 아니라 종료 코드에 박혀 있습니다. 관문 세 곳이 같은 기준으로 세 번 판정하고 실패의 무게에 따라 멈추는 범위가 다릅니다. 그리고 무인 실행이 거짓말하지 못하도록 완료 계약과 기동 상한을 걸어 뒀습니다 — 사고가 한 번씩 남긴 값들입니다.