한컴인스페이스

ML 실험 자율 오케스트레이터 - cron · Claude Code 에이전트 설계

2026.05 ~ 2026.06
설계 및 개발
Claude CodePythonShell ScriptSlack APIcron

아키텍처 - 자율 실험 루프

Claude Code Skill
cronjob (@reboot · */5) - 주기 실행
↓ work_history 읽고 다음 실험 판단
학습 실행
Hook + sh - 학습 프로세스 자동 실행
모니터 데몬 / cron
install_monitor.sh - seg mIoU · YOLO mAP50 감지
↓ best_update · finished · error · stopped
기록
work_history/*.md 자동 기록
↺ 다음 판단 인풋으로 재투입 - 무인 연속 실험
Stop 훅 기록 강제 · Slack WebHook 실시간 알림

ML 실험 루프는 초기화 → 학습 → 검증 → 기록 → 다음 실험 결정으로 순환합니다. 각 단계가 끝날 때마다 사람이 결과를 보고 다음 실험을 정해야 해서, 자리를 비우면 실험이 멈추고 재개할 때 맥락을 다시 파악해야 했습니다. 이 반복 엔지니어링 자체를 Claude Code에 위임해, cronjob·Skill·Hook·work_history를 조합한 자율 루프로 엔지니어 개입 없는 연속 실험을 가능하게 한 사내 개인 프로젝트입니다.

핵심 기능

판단 → 실행 → 기록 → 재판단 자율 루프

cronjob으로 Claude Code Skill 주기 실행 → work_history 재투입

자율 루프

핵심은 work_history를 상태 저장소이자 다음 판단의 입력으로 함께 쓴다는 점입니다. cronjob이 Claude Code Skill을 주기적으로 깨우면, Skill은 work_history의 지난 실험 기록을 읽어 다음 실험을 판단하고, Hook + sh로 학습 프로세스를 자동 실행합니다. 학습이 끝나면 결과가 다시 work_history에 기록되고, 그 기록이 다음 cron 틱의 판단 인풋으로 재투입됩니다.

그 결과 AI를 단순 코드 보조가 아니라 반복 엔지니어링 자체를 위임하는 에이전트로 운영하게 됐고, 엔지니어가 자리를 비워도 실험이 스스로 다음 사이클로 넘어갑니다.

seg · YOLO 학습 자동 감지 모니터

install_monitor.sh - mIoU · mAP50 이벤트를 work_history에 기록

모니터링

실험 진행·완료·에러를 사람이 로그를 직접 봐야 파악할 수 있었습니다. 서버별로 한 번만 실행하는 install_monitor.sh가 모니터 데몬과 @reboot cron을 설치해, 실험 디렉토리와 컨테이너 상태를 주기적으로 스캔합니다. seg는 log.txt· 체크포인트 파일명에서 mIoU를, YOLO는 results.csv에서mAP50을 읽는데, HBB/OBB로 컬럼 위치가 달라도 헤더명을 동적 탐색해 둘 다 지원합니다.

type=segtype=yolo
진행 소스log.txtresults.csv
지표mIoUmAP50 (헤더명 동적 탐색)
완료 판정"Training finished" 로그마지막 epoch ≥ args.yaml epochs
컨테이너 의존필요 (training_XX)불필요 (csv만으로 판정)

best_update · finished · error(CUDA OOM 등) · stopped 이벤트를 감지해 일별 YYYY-MM-DD_auto_monitor.md에 자동 기록합니다. 예를 들어 한 세그멘테이션 학습은 mIoU 0.39 → 0.70까지 오르는 88 epoch 전 과정이 사람 개입 없이 기록됐습니다. 실험별 상태 파일로 이벤트 중복 기록을 막아, cron 매 틱이 멱등이 되도록 했습니다.

Stop 훅으로 작업 기록 강제

턴당 1회 block - 무한루프 없이 기록 누락 방지

Hook

작업 기록이 사람 의지에 의존하면 누락되기 쉽습니다. Claude Code Stop 훅으로 매 턴이 끝날 때 "작업했으면 work_history에 기록하라"는 리마인드를 강제 주입했습니다. 권한 규칙이 있는 settings.local.json을 직접 건드리면 auto-mode classifier가 권한 확대로 거부하므로, 훅만 담은 별도 settings.json에 분리해 넣었습니다.

훅이 매번 block하면 무한루프에 빠지므로, 세션별 sentinel 파일(/tmp/claude-...-$session_id)로턴당 1회만 block하고 두 번째 stop은 통과시켰습니다.

# 파이프 테스트 결과
1차 stop = block   # "기록하라" 리마인드 주입
2차 stop = allow   # 통과 (무한루프 방지)
3차 stop = block   # 다음 턴 다시 강제