OpenClaw·Hermes 마이그레이션 (13/13) — Cutover 당일: 전환 6단계 절차와 설정 트랩

에이전트 스택 전체를 교체할 때 필요한 단계, 검증 체크포인트, 그리고 설정 결합에서 발생하는 대표적 트랩 2종.


핵심 요약

  • 에이전트 Cutover는 6단계로 나뉜다: 기존 스택 종료 → 신규 스택 부팅 검증 → config 설정 → cron 등록 → Gateway/메신저 연결 → 24h 검증.
  • 재현성 있게 걸리는 설정 트랩 2종: sandbox 환경에서의 $HOME 오염, smart_model_routing과 기본 모델 간 불일치.
  • 롤백은 "LaunchAgent + cron 복구" 한 줄로 유지해두는 것이 안전 설계의 최소 단위다.

Phase 1 — 기존 스택 종료

에이전트 교체에서 포트/토큰/프로세스 충돌을 피하려면 기존 스택을 완전히 정지한 뒤 다음 단계로 진입해야 한다. cron·LaunchAgent·메신저 봇 연결이 각각 독립된 경로로 재기동될 수 있으므로 세 지점을 모두 차단한다.

crontab -r   # OpenClaw 전체 cron 제거

launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.openclaw.gateway.plist

완전 정지를 확인하지 않고 Phase 2로 넘어가면 신규 스택 부팅 시 포트 충돌로 heartbeat가 경쟁한다. 이 경우 로그상 원인 분리가 어려워지므로 "프로세스 잔류 0" 확인이 게이트다.


Phase 2 — 신규 스택 부팅 검증

인증 토큰은 기존 CLI 계열에서 그대로 승계 가능한 경우가 많다. Codex CLI 토큰, OAuth refresh_token, 메신저 봇 토큰 세 축을 재배치한다.

cp ~/.codex/auth.json ~/.hermes/auth.json

cat ~/.hermes/config.yaml | grep provider

부팅 후 hermes doctor 같은 자체 진단 커맨드로 3개 축(아이덴티티 파일, 사용자 파일, Auth)을 확인한다.

SOUL.md     ✓
USER.md     ✓
Auth        ✓

세 항목 모두 통과해야 Phase 3로 진입한다. 하나라도 실패하면 해당 파일/토큰 교정 후 재검증. 부팅 단계의 미검증 오류는 뒤 단계에서 훨씬 비싸게 드러난다.


Phase 3 — config.yaml 설정

config 설계에서는 세 가지가 동시에 잡혀야 한다: 스킬 로드 경로, 비활성 플랫폼/스킬 목록, 라우팅 규칙.

skills:
  disabled: 45
  external_dirs:
    - ~/Hermes/.claude/skills

platform_disabled:
  discord: 14

routing:
  smart_model_routing: true
  default_model: gpt-4o-mini   # 이후 문제가 된 설정

provider: openai-codex

external_dirs는 스킬 파일이 기본 경로 밖에 있을 때 로드 경로를 추가한다. 누락 시 Tier 2 스킬이 로드되지 않는다.

smart_model_routing: truegpt-4o-mini 조합은 뒤에 설명하는 트랩 2번과 직접 연결된다. 라우팅이 켜져 있는 상태에서 기본 모델이 특정 모드의 지원 모델 집합과 어긋나면 런타임에 unsupported model error가 발생한다.


Phase 4 — Cron 등록

상시 실행 에이전트의 "숨쉬기"는 cron으로 분해해 관리한다. 정각 충돌을 피하기 위해 heartbeat는 7분/37분 오프셋을 준다.

잡 이름 스케줄 설명
heartbeat-tick 7,37 * * * * 30분 간격 heartbeat
daily-brief 40 22 * * * 22:40 일일 브리핑
research-scan 0 9 * * * 09:00 리서치 스캔
reflect 0 3 * * * 03:00 반성 루프
monthly-memory 0 9 1 * * 매월 1일 09:00 메모리 정리
crontab -e
crontab -l  # 등록 확인

정각(0분/30분)은 시스템 다른 잡과 충돌 가능성이 있어 heartbeat 류는 7/37 같은 홀수 오프셋이 안전하다.


Phase 5 — Gateway + 메신저 연결

hermes gateway install
launchctl load ~/Library/LaunchAgents/com.hermes.gateway.plist

launchctl list | grep hermes

Discord 연결 시 확인 포인트: - 봇 계정(Mir#4703) 연결 - 슬래시 커맨드 50개 동기화 - Cron ticker 60초 간격 시작

Discord 슬래시 커맨드 동기화는 API 특성상 최대 1시간까지 지연될 수 있다. 동기화 직후 테스트하면 커맨드가 안 보일 수 있으므로 5~10분 대기 후 확인이 기본이다.


Phase 6 — 24시간 검증

Cutover 성공/실패 판정은 24시간 관측 구간으로 정의한다. 모든 주기 잡이 최소 1회 이상 실행되고, 오류 발생 시 자동 복구 여부까지 본다.

관측 구간의 대표 이벤트:

구간 이벤트
T+0 Cutover 시작 / 검증 카운트다운 개시
T+20m 첫 heartbeat-tick 실행 (정상)
T+4h대 daily-brief 실행 (정상)
T+9h대 reflect 실행 (정상)
T+15h대 research-scan 실행 + dawn heartbeat 오류 발생

dawn heartbeat 오류 로그:

unsupported model error: 1회
mode info recognition failure: 1회
→ 자동 복구 완료

오류 원인은 Phase 3 config의 라우팅 설정과 맞물린다. 아래 트랩 2번에서 분리 분석한다.


설정 트랩 1: Sandbox $HOME 오염

증상: 신규 스택이 ~/.hermes/ 대신 예상치 못한 경로로 데이터를 쓴다.

원인: Claude Code sandbox 환경은 $HOME을 실제 사용자 홈(/Users/username)이 아닌 sandbox 격리 경로로 설정한다. 로더 스크립트가 $HOME을 그대로 참조하면 설치 경로가 어긋난다.

수정:

HERMES_HOME="$HOME/.hermes"

REAL_HOME=$(eval echo ~$USER)
HERMES_HOME="$REAL_HOME/.hermes"

eval echo ~$USER는 사용자 레코드에서 홈 경로를 직접 조회하므로 sandbox의 $HOME 재정의 영향을 받지 않는다.

추가 권고: 최초 설치는 사용자 터미널에서 직접 수행한다. sandbox 내부에서 설치하면 심링크 대상이 sandbox 경로로 고정되어 재기동 시 깨진다.


설정 트랩 2: Smart Model Routing과 기본 모델 불일치

증상: 24h 검증 중 dawn heartbeat에서 unsupported model error가 1회 발생하고 자동 복구.

원인: smart_model_routing: true 상태에서 기본 모델이 gpt-4o-mini로 설정되어 있다. 특정 모드(예: heartbeat의 특정 사고 단계)에서 라우터가 해당 모드에 허용되지 않는 모델을 선택하면 런타임에서 모델 로드가 거부된다.

수정:

routing:
  smart_model_routing: false   # 라우팅 비활성화
  default_model: gpt-5.4       # 고정 모델로 전환

원리: 라우팅 테이블의 모드별 허용 모델 집합과 default_model이 교집합을 갖지 않으면 폴백 경로가 실패한다. 해법은 두 가지다.

  1. 라우팅을 유지하되 default_model을 모든 모드에서 허용되는 모델로 고정
  2. 라우팅을 끄고 단일 모델로 통일

운영 초기에는 2번이 안전하다. 실패 지점이 줄어들고, 비용/성능 프로파일이 안정되면 1번으로 확장한다.


롤백 경로

Cutover 실패 또는 심각한 오류 시 이전 스택으로 회귀한다.

launchctl load ~/Library/LaunchAgents/com.openclaw.gateway.plist && crontab ~/openclaw_cron_backup.txt

핵심 설계: 롤백은 "LaunchAgent 로드 + cron 복구" 한 줄로 정의 가능해야 한다. 여러 명령이 필요하면 롤백 자체가 실패할 여지가 커진다. 24h 검증이 통과하기 전까지 cron 백업 파일을 보관한다.


최종 상태 체크리스트

항목 결과
이전 스택 프로세스 잔류 0
이전 스택 토큰 잔류 0
보조 토큰 잔류 0
heartbeat-tick 정상
daily-brief 정상
reflect 정상
research-scan 정상 (오류 1회 → 자동 복구)
Discord 슬래시 커맨드 50개 동기화 완료

적용 가능 범위와 열린 질문

이 6단계 구조는 OpenClaw → Hermes에 한정되지 않는다. "상시 실행 에이전트 스택"이 cron + LaunchAgent + 메신저 봇 + 라우팅 레이어로 구성된다면 동일한 뼈대로 옮겨 쓸 수 있다. 구체적으로는 다음 조합에 그대로 대응한다.

  • Claude Code 기반 로컬 에이전트 ↔ 다른 로컬 에이전트 하네스
  • ChatGPT Plus OAuth + Codex CLI 토큰 기반 스택 간 이식
  • 단일 메신저 봇(Discord/Slack)을 공유하는 두 백엔드 사이 전환

열린 질문 두 가지:

  1. smart_model_routing을 다시 켤 가치가 있는가? 모드별 비용/성능 프로파일이 유의미하게 갈릴 때만 가치가 있다. 모든 모드에서 단일 모델이 "충분히 좋다"면 라우팅은 복잡도만 늘린다.
  2. 24h 검증 구간은 충분한가? 월 1회 잡(monthly-memory)은 24h에 포함되지 않는다. 저빈도 잡을 별도 관측 구간으로 떼어내 2단계 검증으로 확장하는 쪽이 안전하다.

시리즈 전체 안내: 시리즈 목차

댓글

이 블로그의 인기 게시물

"LLM 핵심 학습 (1/6) — 기본: 토큰화·임베딩·어텐션·위치 인코딩"

"LLM 핵심 학습 (2/6) — 파인튜닝: LoRA·QLoRA·증류·Adapter"

"ML 기초 학습 (1/9) — 머신러닝과 sklearn: 학습의 좌표계"