ML 실험 자율 오케스트레이터 - cron · Claude Code 에이전트 설계
아키텍처 - 자율 실험 루프
ML 실험 루프는 초기화 → 학습 → 검증 → 기록 → 다음 실험 결정으로 순환합니다. 각 단계가 끝날 때마다 사람이 결과를 보고 다음 실험을 정해야 해서, 자리를 비우면 실험이 멈추고 재개할 때 맥락을 다시 파악해야 했습니다. 이 반복 엔지니어링 자체를 Claude Code에 위임해, cronjob·Skill·Hook·work_history를 조합한 자율 루프로 엔지니어 개입 없는 연속 실험을 가능하게 한 사내 개인 프로젝트입니다.
핵심 기능
판단 → 실행 → 기록 → 재판단 자율 루프cronjob으로 Claude Code Skill 주기 실행 → 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 - mIoU · mAP50 이벤트를 work_history에 기록
실험 진행·완료·에러를 사람이 로그를 직접 봐야 파악할 수 있었습니다. 서버별로 한 번만 실행하는 install_monitor.sh가 모니터 데몬과 @reboot cron을 설치해, 실험 디렉토리와 컨테이너 상태를 주기적으로 스캔합니다. seg는 log.txt· 체크포인트 파일명에서 mIoU를, YOLO는 results.csv에서mAP50을 읽는데, HBB/OBB로 컬럼 위치가 달라도 헤더명을 동적 탐색해 둘 다 지원합니다.
| type=seg | type=yolo | |
|---|---|---|
| 진행 소스 | log.txt | results.csv |
| 지표 | mIoU | mAP50 (헤더명 동적 탐색) |
| 완료 판정 | "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
턴당 1회 block - 무한루프 없이 기록 누락 방지
작업 기록이 사람 의지에 의존하면 누락되기 쉽습니다. 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 # 다음 턴 다시 강제