Hermes 시스템 구조 전수조사 (인수인계)
Hermes 시스템 구조
1. 전체 구조도 (ASCII)
~/hermes-repo/ # GitHub source of truth
cron/jobs.json # 크론 정의 (72개)
workspace/scripts/pipeline/ # 파이프라인 소스 (250개+)
workspace/scripts/shared/ # 공용 유틸 (telegram.py 등)
workspace/configs/ # 설정 파일
hermes-agent/ # 게이트웨이 코어
skills/ # 스킬 정의
scripts/deploy_to_runtime.sh # 배포 도구
│
│ ./scripts/deploy_to_runtime.sh
│ (rsync, 상태 디렉터리 제외)
▼
~/.hermes/ # 크론 실행 런타임
cron/jobs.json # 실행 중인 크론 (repo와 거의 동일, next_run_at만 차이)
workspace/scripts/pipeline/ # 배포된 파이프라인 (374개, .bak 포함)
hermes-agent/ # 실행 중인 게이트웨이
config.yaml # 런타임 설정
gateway.pid / gateway_state.json
data/, logs/, sessions/, memory/, cache/ # 런타임 상태 (배포 시 보존)
│
▼
hermes gateway (launchd: ai.hermes.gateway, PID 55997)
└── cron_ticker (jobs.json 자동 리로드)
├── 데이터 수집 잡 (16개)
├── 채권 잡 (13개)
├── 볼트 운영 잡 (11개)
├── 분석 잡 (8개)
├── 시장 데이터 잡 (5개)
├── 원유/에너지 잡 (5개)
├── 펀더멘털 잡 (3개)
├── 시스템 운영 잡 (2개)
└── 기타 (9개) — 총 72개
2. 레포 ↔ 런타임 관계
| 항목 | 값 |
|---|---|
| 레포 경로 | ~/hermes-repo/ |
| 런타임 경로 | ~/.hermes/ |
| 배포 명령 | ./scripts/deploy_to_runtime.sh (또는 --dry-run) |
| 동기화 대상 | workspace/scripts, workspace/configs, cron, hermes-agent, skills |
| 보존 대상 | memory/, logs/, sessions/, reports/, cache/, state/, .env, *.db |
| 현재 차이 | next_run_at 타임스탬프만 다름 — 실질적으로 동일 |
| launchd 서비스 | ai.hermes.gateway (활성), com.openclaw.hermes-tailer |
| 게이트웨이 기본 모델 | gpt-5.4 via codex-proxy (localhost:18642) |
배포 절차: hermes-repo에서 수정 → commit → ./scripts/deploy_to_runtime.sh 실행 → launchd 게이트웨이가 변경 감지 후 자동 적용 (cron은 jobs.json 자동 리로드).
3. 크론 카탈로그 요약
| 카테고리 | 활성 | 비활성 | 대표 잡 |
|---|---|---|---|
| 데이터 수집 | 16 | 0 | blog_monitor, twitter_collector, channel_collector, gmail_newsletter |
| 채권/크레딧 | 13 | 0 | bond_daily_report, bond_market_close, bond_morning_quiz |
| 볼트 운영 | 9 | 2 | vault120-sync, note-atomizer, vault-architect, vault-flow-health |
| 분석/인텔리전스 | 7 | 1 | sector_news_scorer, discovery_enricher, signal_synthesizer, hypothesis_lifecycle |
| 시장 데이터 | 5 | 0 | price_history, market_indicator_tracker, fnguide_snapshot |
| 원유/에너지 | 5 | 0 | oil_supply_monitor(3회/일), tanker_tracker, refining_tracker |
| 펀더멘털 | 1 | 2 | dart_edgar_disclosure, (dart/edgar raw financials 비활성) |
| 시스템 운영 | 2 | 0 | ops_syncer(10분), cron_watchdog |
| 기타 | 7 | 2 | daeju_trigger(3회), awesome_scout, urea_price_tracker 등 |
| 합계 | 65 | 7 |
3.1 주요 잡 디테일 (20개)
bond-daily-report-real-notify
- 스케줄:
0 9 * * 2-6(화~토 09:00 KST) - 역할: 황대진 채권 메일 파싱 → 3페이지 트레이더 브리핑 생성 → DM 전송
- 스크립트:
bond_daily_report.py
bond-morning-poll-real-gmail-collector
- 스케줄:
3,33 7-9 * * 1-5(평일 07~09시 30분 간격) - 역할: Gmail에서 채권 메일 폴링 수집 →
119-크레딧메일/저장 - 스크립트:
bond_report_parser.py연동
bond-market-close-briefing
- 스케줄:
40 15 * * 1-5(평일 15:40 KST) - 역할:
bond-briefing/latest.json읽어 장마감 커브·스프레드 요약 DM (신선도 가드 포함) - 스크립트:
bond_market_close.py
bond-morning-quiz
- 스케줄:
30 7 * * 1-5(평일 07:30) - 역할: 어제자 bond-briefing 기반 4지선다 퀴즈 1개 → DM 전송
- 스크립트:
bond_morning_quiz.py
bond-morning-quiz-retry
- 스케줄:
0 14 * * 1-5(평일 14:00, 미확인 답변 재발송) - 스크립트:
bond_morning_quiz.py
bond-evening-concept
- 스케줄:
0 21 * * *(매일 21:00) - 역할: concept_progress 큐에서 pending 개념 1개 → DM
- 스크립트:
bond_evening_concept.py
bond-evening-report-notify
- 스케줄:
37 22 * * 1-5(평일 22:37) - 역할: 저녁 채권 보고 DM
- 연동:
bond-evening-poll-1900/2030/2200-gmail-collector3단계 폴링 후 취합
bond-weekly-review / bond-weekly-score
- 스케줄: 금 19:00 / 월 09:00
- 역할: 주간 채권 복습 + 퀴즈 성적 집계
글로벌 석유 공급망 모니터 (3회)
- 스케줄:
0 6,14,21 * * *(일 3회) - 역할: 이충재(한투증권) 세미나 기반 임계값으로 글로벌 석유 공급망 체크리스트 실시간 추적
- 스크립트:
oil_supply_monitor.py
tanker-tracker / refining-tracker
- 스케줄: 매일 06:35 / 06:40
- 역할: VLCC/클린탱커 해운 프록시 주가 + 정유 가동률 수집, 이상치 감지
- 스크립트:
tanker_tracker.py,refining_tracker.py
batchM-intelligence-blog-monitor
- 스케줄: 360분 간격 (6시간마다)
- 역할: 네이버 블로그 RSS 다중 수집 → 인사이트 추출 → 텔레그램
- 스크립트:
blog_monitor.py
twitter-collector
- 스케줄:
20 6 * * *(매일 06:20) - 역할: twikit으로 팔로잉 계정 트윗 수집 → 인게이지먼트 스코어링 → LLM 분석 → 리포트
- 출력:
~/knowledge-agent/100-inbox/112 twitter-reports/
channel-collector (118 텔레그램)
- 스케줄:
17 3,9,15,21 * * *(일 4회) - 역할: 루팡·인포마켓·승도리 채널 수집 → 볼트 노트
- 스크립트:
channel_collector.py
analyst-channel-collector
- 스케줄:
45 7,13 * * 1-5(평일 2회) - 역할: 증권사 애널리스트 텔레그램 채널 →
116 croned_data/섹터/마크다운 - 스크립트:
analyst_channel_collector.py
macro-series-collector
- 스케줄:
50 6 * * 1-5(평일 06:50) - 역할: FRED 46개 시리즈 수집 (크레딧 스프레드, 금융조건지수, 금리, 인플레이션, 고용 등)
- 출력:
memory/macro-timeseries/{SERIES_ID}.json
fed-liquidity-aggregator
- 스케줄:
0 7 * * *(매일 07:00) - 역할: 연준 순유동성 = WALCL - RRPONTSYD - WTREGEN 계산·국면 판단
- 스크립트:
fed_liquidity_aggregator.py
gmail-newsletter-collector
- 스케줄:
47 6 * * *(매일 06:47 KST) - 역할: 구독 뉴스레터 Gmail 수집 → LLM 요약 →
121 뉴스레터/저장 - 스크립트:
gmail_newsletter_collector.py
vault120-sync
- 스케줄:
*/30 * * * *(30분마다) - 역할:
~/knowledge/120 지식사랑방/→~/knowledge-agent/100-inbox/단방향 싱크
note-atomizer (phase-200)
- 스케줄:
37 2,14 * * *(하루 2회) - 역할: 100-inbox 노트 → 200-atomic 분해·구조화
ops-syncer
- 스케줄:
*/10 * * * *(10분마다) - 역할: 게이트웨이 운영 상태 동기화
4. 파이프라인 스크립트 그룹
총 250개 (레포 기준), 374개 (런타임, .bak 포함)
4.1 채권/크레딧 교육
| 파일 | 용도 |
|---|---|
bond_daily_report.py |
황대진 채권 메일 → 3페이지 브리핑 생성 + DM |
bond_market_close.py |
장마감 커브·스프레드 요약 DM |
bond_morning_quiz.py |
아침 퀴즈 4지선다 생성 + 발송 |
bond_evening_concept.py |
채권 개념어 큐에서 1개씩 저녁 발송 |
bond_report_parser.py |
Gmail 메일 HTML → 구조화 JSON (정규식, LLM 없음) |
bond_weekly_review.py |
주간 채권 복습 리포트 |
bond_weekly_score.py |
퀴즈 성적 집계 DM |
bond_monthly_exam.py |
월말 종합 시험 |
4.2 원유/에너지
| 파일 | 용도 |
|---|---|
oil_supply_monitor.py |
글로벌 석유 공급망 체크리스트 (임계값 기반) |
mideast_oil_collector.py |
popular_posts DB에서 중동 지정학/에너지 메시지 수집 |
tanker_tracker.py |
VLCC/클린탱커 해운 프록시 주가 + 이상치 감지 |
refining_tracker.py |
정유 가동률 + EIA 데이터 수집 |
urea_price_tracker.py |
요소 가격 주간 추적 |
copper_market_collector.py |
구리 선물 커브 + 상하이 재고 수집 |
4.3 데이터 수집 (외부 소스)
| 파일 | 용도 |
|---|---|
blog_monitor.py |
네이버 블로그 RSS 다중 수집 → 인사이트 추출 |
twitter_collector.py |
X/Twitter 팔로잉 계정 수집 → 인게이지먼트 스코어링 |
channel_collector.py |
텔레그램 투자 인사이트 채널 수집 (공개+비공개) |
nepcon_collector.py |
네이버 프리미엄 콘텐츠(네프콘) 산업 뉴스 |
ingest_telegram_realtime.py |
텔레그램 채널 실시간 수집 → 볼트 저장 |
gmail_newsletter_collector.py |
Gmail 뉴스레터 수집 → LLM 요약 → 볼트 |
analyst_channel_collector.py |
증권사 애널리스트 텔레그램 채널 수집 |
4.4 거시/시장 데이터
| 파일 | 용도 |
|---|---|
macro_series_collector.py |
FRED 46개 시리즈 수집 |
fed_liquidity_aggregator.py |
연준 순유동성 계산·국면 판단 |
macro_collector.py |
매크로 수집 + 정량 계산 → context JSON |
price_history_collector.py |
yfinance 주요 자산 OHLCV + 기술지표 |
market_indicator_tracker.py |
핵심 시장 지표 수집 + 이상치 감지 |
strategy_flow_collector.py |
한국 시장 투자자별 순매수·프로그램 매매·신용잔고 |
fnguide_snapshot.py |
FnGuide 컨센서스 (반도체6사+석화6사) |
4.5 분석/인텔리전스
| 파일 | 용도 |
|---|---|
sector_news_scorer.py |
섹터별 뉴스 LLM 중요도 채점 |
discovery_enricher.py |
score 7+ 발견 아이템 → 볼트 적용 힌트 생성 |
signal_synthesizer.py |
4축 시그널(매크로/섹터/기업/기술) 합성 |
daily_intelligence_report.py |
7+ 파이프라인 출력 취합 → 통합 데일리 리포트 |
vault_analyst_feedback.py |
분석 에이전트 결과 → 볼트 환류 |
analyst_evolution_tracker.py |
분석 방법론 피드백 추적 |
morning_briefing.py |
모닝/이브닝 브리핑 생성 (한국장·미국장) |
4.6 시스템 운영
| 파일 | 용도 |
|---|---|
cron_watchdog.py |
크론 잡 지연·실패 감지 |
cron_stall_detector.py |
크론 정지 감지 |
auto_healer.py |
자동 복구 |
data_freshness_watcher.py |
데이터 신선도 감시 |
5. 볼트 구조
5.1 ~/knowledge/ (해리 고유 볼트, AI 쓰기 제한)
~/knowledge/
000 선언/ — 시스템 선언·스키마 (편집 절대 금지)
100 수신함/ — 해리 직접 수집물
120 지식사랑방/ — 커뮤니티 공유 (vault120-sync가 agent로 복사)
200 아토믹/ — 원자 노트
300 지식망/ — 해리 활용 지식망
400 판단/ — 해리 투자 판단 (420~442 하위)
500 시그널/ — 시그널
600 데이터/ — 데이터
700 실험실/ — 실험 공간
800 운영/ — 운영 메모
900 프롬프트/ — 프롬프트 저장
규칙: AI 에이전트 읽기만 가능. 해리 지정 분석 결과만 직접 저장 허용 (staging 불필요).
5.2 ~/knowledge-agent/ (AI 작업 공간, 자유 읽기/쓰기)
~/knowledge-agent/
100-inbox/ — 에이전트 수집 결과
110 blog-insights/
112 twitter-reports/
113 popular-posts/
114 filtered-ideas/
117 macro-series/
118 텔레그램/
119-크레딧메일/ — 황대진 채권 메일 파싱 결과
120 지식사랑방/ — vault120-sync 복사본
121 뉴스레터/
122 price-history/
123 fed-liquidity/
124 dart-edgar/
125 sector-news/
126 hypotheses/
200-atomic/ — 원자 노트 (note-atomizer 출력)
300-connected/ — 연결된 노트망
400-reports/ — 에이전트 작성 리포트 (본 문서 포함)
500-signals/ — 4축 시그널 합성 결과
600-data/ — 수집 데이터
700-lab/ — 실험 공간
_staging/ — 해리 검토 후 ~/knowledge/ 승격 대기
cowork/ — Claude Code ↔ Hermes 공유 공간
공유 프로토콜:
- Claude Code → Hermes: 400-reports/에 저장 → Hermes가 agent-vault MCP로 읽음
- Hermes → Claude Code: 100-inbox/에 저장 → Claude Code가 agent-vault MCP로 읽음
- 파일명 규칙: YYMMDD_{source}_{topic}.md
- frontmatter 필수: title, date, source(claude-code/hermes/pipeline), tags
6. 텔레그램 봇 역할
| 봇 | chat_id | 용도 |
|---|---|---|
| @openclaw_harybot | 492860021 (해리 DM) | Claude Code ↔ 해리 직접 대화 |
| @RONforMAC_Bot | 492860021 (해리 DM) | Hermes 시스템 알림 (CRITICAL/INFO) |
| @ronclawBot | 해리 DM | Codex 직접 소통 |
알림 등급 정책 (shared/telegram.py의 등급 게이트):
| 등급 | 목적지 | 조건 |
|---|---|---|
| CRITICAL | 해리 DM | 위기·승인 요청만. 5줄 이내 |
| INFO | 알림센터(ops_multiagent.db) | 정보·보고·루틴. DM 금지 |
| LOG | 로그만 | 디버그·내부 (전송 없음) |
규칙: @RONforMAC_Bot 채널 설정 절대 변경 금지. send_dm(text) 호출 시 level 미지정이면 INFO→알림센터.
7. 인수인계 체크리스트
- [ ] GitHub 레포 접근:
~/hermes-repo/.git/(remote 확인 필요) - [ ]
.env재구성:~/hermes-repo/.env.example참조 - [ ] 배포 도구 실행 환경:
bash ~/hermes-repo/scripts/deploy_to_runtime.sh - [ ] launchd 서비스 등록:
ai.hermes.gateway.plist(현재 활성) - [ ] codex-proxy 가동:
localhost:18642(gateway 기본 모델 라우팅) - [ ] Gmail API OAuth 토큰:
~/.hermes/credentials/확인 - [ ] 텔레그램 봇 토큰 3종:
~/.hermes/bot_tokens.json참조 - [ ] Telethon API 인증:
~/.hermes/auth.json(채널 수집용) - [ ] FRED API 키:
~/.hermes/fred_api_key확인 - [ ] DART API 키:
~/.hermes/dart_api_key확인 - [ ] 볼트 경로 마운트:
~/knowledge/,~/knowledge-agent/접근 확인 - [ ] sector-group.json:
~/.hermes/sector-group.json(섹터 라우팅 설정)
N1. .env.example 전문 (변수명 + 설명)
실측 기준: ~/.hermes/.env에서 변수명만 추출 (값 노출 없음).
# ── Hermes 게이트웨이 ──────────────────────────────────────────
HERMES_GATEWAY_PORT= # 게이트웨이 HTTP 포트 (기본 18789). config.yaml과 일치 필요.
HERMES_GATEWAY_TOKEN= # 게이트웨이 API 인증 토큰. 외부 호출 시 Bearer 헤더에 사용.
HERMES_INFERENCE_PROVIDER= # LLM 공급자 선택 (openai / anthropic / codex-proxy 등). 16개 스크립트 참조.
HERMES_CODEX_BASE_URL= # codex-proxy 엔드포인트 (기본 http://localhost:18642/v1). 5개 스크립트 참조.
# ── API 서버 (MCP / 외부 노출) ────────────────────────────────
API_SERVER_ENABLED= # API 서버 활성화 여부 (true/false). 13개 스크립트 참조.
API_SERVER_HOST= # API 서버 바인드 주소 (예: 0.0.0.0). 10개 스크립트 참조.
API_SERVER_PORT= # API 서버 포트. 11개 스크립트 참조.
API_SERVER_KEY= # API 서버 접근 키. 26개 스크립트 참조.
# ── Telegram ─────────────────────────────────────────────────
TELEGRAM_BOT_TOKEN= # 기본 DM 봇 @RONforMAC_Bot 토큰. 91개 스크립트 참조 (핵심).
TELEGRAM_ALLOWED_USERS= # 봇 명령 허용 user_id 목록 (쉼표 구분). 31개 스크립트 참조.
TELEGRAM_BLOCKED_CHATS= # 수신 차단 chat_id 목록. 2개 스크립트 참조.
TELEGRAM_REQUIRE_MENTION= # 그룹 채팅에서 봇 언급 필요 여부 (true/false). 6개 스크립트 참조.
# ── Anthropic / OpenAI ────────────────────────────────────────
# (Hermes는 codex-proxy 경유가 기본. 직접 호출 시 아래 키 사용)
# 해당 변수가 .env에 없으면 HERMES_INFERENCE_PROVIDER 설정 확인.
# ── DART (공시) ──────────────────────────────────────────────
DART_API_KEY= # open.dart.fss.or.kr 공시 API 키. 24개 스크립트 참조.
# ── Minimax (이미지/음성 생성) ────────────────────────────────
MINIMAX_API_KEY= # Minimax 멀티모달 API 키. 43개 스크립트 참조.
# ── Browser / Browserbase ────────────────────────────────────
BROWSERBASE_ADVANCED_STEALTH= # Browserbase 고급 스텔스 모드 (true/false). 6개 스크립트 참조.
BROWSERBASE_PROXIES= # Browserbase 프록시 설정. 4개 스크립트 참조.
BROWSER_SESSION_TIMEOUT= # 브라우저 세션 타임아웃 (초). 1개 스크립트 참조.
BROWSER_INACTIVITY_TIMEOUT= # 브라우저 비활동 타임아웃 (초). 5개 스크립트 참조.
# ── Terminal / 실행 환경 ─────────────────────────────────────
TERMINAL_TIMEOUT= # 명령 실행 타임아웃 (초). 21개 스크립트 참조.
TERMINAL_LIFETIME_SECONDS= # 터미널 세션 최대 수명. 9개 스크립트 참조.
TERMINAL_MODAL_IMAGE= # 터미널 Docker 이미지 이름. 9개 스크립트 참조.
# ── Obsidian / 볼트 ──────────────────────────────────────────
OBSIDIAN_VAULT_PATH= # Obsidian 볼트 절대 경로. 6개 스크립트 참조.
# 보통 ~/knowledge 또는 ~/knowledge-agent
# ── 디버그 플래그 ────────────────────────────────────────────
IMAGE_TOOLS_DEBUG= # 이미지 도구 상세 로그 (true/false). 5개 스크립트 참조.
MOA_TOOLS_DEBUG= # MoA(Mixture of Agents) 도구 디버그. 4개 스크립트 참조.
VISION_TOOLS_DEBUG= # 비전 도구 디버그. 4개 스크립트 참조.
WEB_TOOLS_DEBUG= # 웹 도구 디버그. 8개 스크립트 참조.
비고: Gmail OAuth, FRED, KIS, Telethon 인증은 별도 credential 파일로 관리
(~/.hermes/credentials/, ~/.hermes/auth.json, ~/.hermes/fred_api_key 등).
.env에 직접 포함하지 않음.
N2. 크론 72개 전체 목록
~/hermes-repo/cron/jobs.json 실측 기준 (2026-04-22). enabled=false는 비활성.
| id (앞 12자) | name | schedule | enabled |
|---|---|---|---|
| 41c2736f0527 | vault-analyst-feedback | 50 7 * * * | true |
| ocPH-SPY-pri | price-history SPY refresh | 0 7,12,18 * * 1-5 | true |
| ocAK-AK000-b | bond-daily-report-real-notify | 0 9 * * 2-6 | true |
| ocAO-AO003-b | bond-morning-poll-real-gmail-collector | 3,33 7-9 * * 1-5 | true |
| macro-series | macro-series-collector FRED macro timeseries collector | 50 6 * * 1-5 | true |
| fed-liquidit | fed-liquidity-aggregator Fed liquidity aggregator | 0 7 * * * | true |
| ocM-M019-blo | batchM-intelligence-blog-monitor | (interval 360m) | true |
| ocAQ-AQ004-g | gmail-newsletter-collector | 47 6 * * * | true |
| ocRESTORE-in | intelligence-cluster Hermes data chain | 0 1 * * * | true |
| ocRESTORE-se | sector-news-scorer Hermes S-code scoring | 30 2,8,14,20 * * * | true |
| ocRESTORE-di | discovery-enricher Hermes vault hints | 35 1 * * * | true |
| ocRESTORE-ke | keyword-tuner Hermes query evolution | 30 4 * * 1,4 | true |
| ocRESTORE-hy | hypothesis-lifecycle Hermes state maintenance | 45 3 * * * | true |
| ocRESTORE-an | analyst-channel-collector Hermes market inputs | 45 7,13 * * 1-5 | true |
| ocRESTORE-an | analyst-quality-tracker Hermes PM QA | 10 8 * * * | true |
| ocRESTORE-no | notion-analyst-sync Hermes research log sync | 20 8 * * 1-5 | true |
| ocJ-J000-nep | nepcon-collector | 37 1,7,13,19 * * * | true |
| fundamental- | fundamental DART financial statement collector | 0 6 * * * | false |
| fundamental- | fundamental EDGAR overseas financial statement collector | 10 6 * * * | false |
| fundamental- | fundamental Twitter collector | 20 6 * * * | false |
| ocFUND-dart- | DART/EDGAR disclosure collector for fundamental analyst | 20 6 * * 1-5 | false |
| ocTC-twitter | twitter-collector X/Twitter following collector | 20 6 * * * | true |
| ocFUND-dart- | fundamental DART disclosure collector | 0 6 * * * | true |
| ocFUND-edgar | fundamental EDGAR disclosure collector | 10 6 * * * | true |
| oc118-channe | channel-collector 118 텔레그램 수집 | 17 3,9,15,21 * * * | true |
| ocRESTORE-po | popular-posts-collect restored cron | 20 7,13 * * 1-5 | true |
| ocRESTORE-va | vault-macro-bridge restored cron | 50 6 * * 1-5 | true |
| ocRESTORE-va | vault-fundamental-bridge restored cron | 0 7 * * 1-5 | true |
| ocRESTORE-va | vault-technical-bridge restored cron | 10 7 * * * | true |
| ocRESTORE-pr | price-history-universe Hermes full price refresh | 0 7,13,18 * * 1-5 | true |
| ocRESTORE-an | analyst-evolution-tracker methodology feedback | 15 8 * * * | true |
| ocRESTORE-no | note-atomizer phase-200 | 37 2,14 * * * | true |
| ocRESTORE-in | inbox-health-auditor 100-inbox health audit | 30 0 * * * | true |
| ocRESTORE-kn | knowledge-promoter | 15 4 * * * | false |
| ocRESTORE-kn | knowledge-connector | 40 2 * * * | false |
| ocRESTORE-pr | promotion candidates reporter | 0 5 * * * | true |
| ocRESTORE-pr | promotion auto mover | 30 5 * * * | false |
| ocRESTORE-va | vault120-sync Harry vault to agent inbox sync | */30 * * * * | true |
| oc-goal-alig | goal-alignment 일일 평가 | 43 12 * * * | true |
| oc-vault-arc | vault-architect 구조 최적화 | 27 4 * * * | true |
| oc-vault-flo | vault-flow-health 볼트 건강도 | 13 5 * * * | true |
| kr-research- | kr-research-collector 한국 리서치 수집 | 15 4 * * * | true |
| ocRESTORE-mo | moat-scorer 기업별 Moat 정량 스코어 | 17 3 * * * | true |
| ocRESTORE-si | signal-synthesizer 4축 시그널 합성 | 27 3 * * * | true |
| ocRESTORE-se | sector-research 섹터 6단계 분석 집계 | 37 3 * * * | true |
| ocCRIT-oil-s | 글로벌 석유 공급망 모니터 | 0 6 * * * | true |
| ocRESTORE-oi | 석유 공급망 모니터 (오후 14시) | 0 14 * * * | true |
| ocCRIT-oil-s | 석유 공급망 모니터 (저녁 21시) | 0 21 * * * | true |
| fd0119a08cc4 | bond-morning-quiz | 30 7 * * 1-5 | true |
| bc3a02bc769c | bond-morning-quiz-retry | 0 14 * * 1-5 | true |
| 0a258438a36e | bond-evening-concept | 0 21 * * * | true |
| 35dac8a246ff | bond-weekly-review | 0 19 * * 5 | true |
| 1659adf98d3b | bond-weekly-score | 0 9 * * 1 | true |
| 2c2062c4ec67 | bond-monthly-exam | 0 10 28-31 * 6 | true |
| ocAO-AO100-b | bond-evening-poll-1900-gmail-collector | 3 19 * * 1-5 | true |
| ocAO-AO101-b | bond-evening-poll-2030-gmail-collector | 33 20 * * 1-5 | true |
| ocAO-AO102-b | bond-evening-poll-2200-gmail-collector | 7 22 * * 1-5 | true |
| ocAK-AK100-b | bond-evening-report-notify | 37 22 * * 1-5 | true |
| oc119-trilli | Trillion_labs 텔레그램 수집 | 0 6,14,21 * * * | true |
| aasf-scout-1 | awesome-agent-frameworks-scout | 7 9 * * 1 | true |
| daeju-trigge | daeju-trigger-0930 078600 대주전자재료 트리거 | 30 9 * * 1-5 | true |
| daeju-trigge | daeju-trigger-1100 078600 대주전자재료 트리거 | 0 11 * * 1-5 | true |
| daeju-trigge | daeju-trigger-1500 078600 대주전자재료 트리거 | 0 15 * * 1-5 | true |
| 1d04396f15ec | bond-market-close-briefing | 40 15 * * 1-5 | true |
| ops-syncer | ops-syncer | */10 * * * * | true |
| ocRESTORE-ma | market-indicator-tracker | 5 7,9,11,13,15,17 * * 1-5 | true |
| ocRESTORE-st | strategy-flow-collector | 0 16 * * 1-5 | true |
| ocRESTORE-ta | tanker-tracker | 35 6 * * * | true |
| ocRESTORE-re | refining-tracker | 40 6 * * * | true |
| ocRESTORE-fn | fnguide-snapshot | 0 17 * * 1-5 | true |
| ocRESTORE-co | copper-market-collector | 30 7 * * 5 | true |
| ocRESTORE-ur | urea-price-tracker | 0 9 * * 1 | true |
합계: 72개 (활성 65, 비활성 7)
N3. jobs.json 스키마
~/hermes-repo/cron/jobs.json 최상위 구조:
{
"jobs": [ ... ],
"updated_at": "ISO-8601"
}
잡 객체 필드
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
id |
string | 필수 | 12자 고유 식별자 (uuid hash 또는 custom prefix) |
name |
string | 필수 | 사람이 읽는 잡 이름 (중복 방지 기준) |
command |
string | 필수 | 실행 명령 전체 경로 (/usr/bin/python3 /path/script.py) |
schedule |
object | 필수 | {"kind": "cron", "expr": "40 15 * * 1-5", "display": "..."} |
enabled |
bool | 필수 | false면 크론 틱커가 건너뜀 |
type / job_type / kind |
string | 필수 | "shell" (현재 단일 타입) |
cwd |
string | 선택 | 실행 디렉터리 (기본 ~/.hermes/workspace) |
timeout_seconds |
int | 선택 | 잡 최대 실행 시간 (기본 300) |
silent |
bool | 선택 | true면 stdout 억제 |
description |
string | 선택 | 잡 설명 |
state |
string | 자동 | "scheduled" / "running" / "failed" |
last_run_at |
ISO-8601 | 자동 | 마지막 실행 시각 |
next_run_at |
ISO-8601 | 자동 | 다음 실행 예정 시각 |
last_status |
string | 자동 | "ok" / "error" |
last_error |
string|null | 자동 | 마지막 에러 메시지 |
repeat.completed |
int | 자동 | 누적 완료 횟수 |
migration |
object | 선택 | 잡 마이그레이션 이력 메타 |
새 잡 추가 방법 (파이프라인 스크립트 내부)
# workspace/scripts/shared/cron_store.py의 add_or_update_job 사용
# 중복 방지: 같은 name이 있으면 schedule/payload만 갱신하고 "updated" 반환
from shared.cron_store import add_or_update_job
new_job = {
"id": "my-job-id-12", # 12자 고유 ID
"name": "my-new-job", # 중복 방지 기준 필드
"command": "/usr/bin/python3 /Users/ron/.hermes/workspace/scripts/pipeline/my_script.py",
"schedule": {
"kind": "cron",
"expr": "0 9 * * *", # cron 표현식 (KST 기준)
"display": "0 9 * * *"
},
"enabled": True,
"type": "shell",
"job_type": "shell",
"kind": "shell",
"timeout_seconds": 300,
"silent": False
}
action, job_id = add_or_update_job(new_job)
# action: "added" / "updated" / "skipped"
주의: add_or_update_job은 name 기준으로 중복 감지. 같은 이름이 이미 있으면 새로 만들지 않고 schedule/payload만 갱신. 직접 jobs.json을 편집하면 크론 틱커 리로드 타이밍에 따라 충돌 가능 — 항상 add_or_update_job을 사용할 것.
N4. 파이프라인 의존성 체인
체인 1: 채권 브리핑 (황대진 메일 → 장마감 DM)
Gmail 수신함 (황대진 메일 07:00~09:00 도착)
↓ [bond-morning-poll-real-gmail-collector: 3,33분 07~09시]
bond_report_parser.py → HTML 파싱 → 구조화 JSON
↓
~/.hermes/workspace/memory/bond-briefing/latest.json
↓ [bond-daily-report-real-notify: 09:00 화~토]
bond_daily_report.py → LLM 3페이지 브리핑 → DM 전송
↓
~/.hermes/workspace/memory/bond-briefing/latest.json (date 필드 갱신)
↓ [bond-market-close-briefing: 15:40 평일]
bond_market_close.py → 신선도 가드(date 오늘인지 확인) → 커브·스프레드 요약 DM
신선도 가드: latest.json의 date 필드가 오늘이 아니면 "stale data" 경고 DM 발송 후 종료. (2026-04-20 사고 교훈 반영)
체인 2: 블로그 → 인텔리전스 리포트
네이버 블로그 RSS (6시간마다)
↓ [batchM-intelligence-blog-monitor: interval 360m]
blog_monitor.py → 인사이트 추출 → 섹터 채널 텔레그램 발송
↓
~/knowledge-agent/100-inbox/110 blog-insights/YYYY-MM-DD/{파일}.md
↓ [intelligence-cluster: 01:00]
daily_intelligence_report.py → blog_count 집계 + LLM 취합
↓
~/.hermes/workspace/memory/blog-insights/ (MEMORY 경로 미러)
→ 통합 데일리 인텔리전스 리포트 DM
체인 3: 트위터 → 인텔리전스
X/Twitter 팔로잉 계정 (매일 06:20)
↓ [twitter-collector-X/Twitter: 20 6 * * *]
twitter_collector.py → twikit 수집 → 인게이지먼트 스코어링 → LLM 분석
↓
~/knowledge-agent/100-inbox/112 twitter-reports/YYYY-MM-DD/{파일}.md
+ ~/.hermes/workspace/memory/twitter-reports/ (MEMORY 미러)
↓ [intelligence-cluster: 01:00]
daily_intelligence_report.py → social_data 집계 → 통합 리포트
체인 4: 볼트 동기화 체인
~/knowledge/120 지식사랑방/ (해리 직접 수집)
↓ [vault120-sync: */30 * * * *]
→ ~/knowledge-agent/100-inbox/120 지식사랑방/ (단방향 복사)
↓ [note-atomizer: 37 2,14 * * *]
→ ~/knowledge-agent/200-atomic/ (원자 노트 분해)
↓ [knowledge-connector: 40 2 * * * — 현재 비활성]
→ ~/knowledge-agent/300-connected/ (연결망 구성)
체인 5: 시그널 합성 체인
macro-series-collector (06:50) → memory/macro-timeseries/
fed-liquidity-aggregator (07:00) → memory/fed-liquidity/
sector-news-scorer (02/08/14/20시) → 125 sector-news/
signal-synthesizer (03:27) ─────────────────────────────┐
← macro bridge (06:50) │
← fundamental bridge (07:00) │
← technical bridge (07:10) │
↓ │
~/knowledge-agent/500-signals/ (4축 시그널 합성 결과) ───┘
↓ [daily_intelligence_report: 01:00]
최종 통합 리포트 + DM
N5. 장애 런북
장애 1: Gateway down
- 증상: 텔레그램 봇 응답 없음,
curl localhost:18789/health불통, 크론 전체 중단 - 진단:
bash launchctl list | grep ai.hermes.gateway # PID 0이면 죽음 cat ~/.hermes/gateway.pid # PID 확인 tail -50 ~/.hermes/logs/gateway.log # 마지막 에러 확인 - 복구:
bash launchctl unload ~/Library/LaunchAgents/ai.hermes.gateway.plist launchctl load -w ~/Library/LaunchAgents/ai.hermes.gateway.plist # 검증 (30초 후) curl -s localhost:18789/health launchctl list | grep ai.hermes.gateway # PID 확인 - 원인 후보: Python 예외 uncaught / 포트 18789 충돌 / 메모리 스파이크 / .env 누락 변수
- 로그:
tail -100 ~/.hermes/logs/gateway.log
장애 2: 크론이 stale 데이터 반복 발송
- 증상: bond_market_close 등이 어제 데이터로 DM 발송 (4-20 사고 패턴)
- 진단:
bash cat ~/.hermes/workspace/memory/bond-briefing/latest.json | python3 -c \ "import json,sys; d=json.load(sys.stdin); print(d.get('date','없음'))" # date 필드가 오늘이 아니면 upstream 수집 실패 - 복구:
bash # 1. upstream 크론 수동 실행 /usr/bin/python3 ~/.hermes/workspace/scripts/pipeline/bond_report_parser.py /usr/bin/python3 ~/.hermes/workspace/scripts/pipeline/bond_daily_report.py # 2. latest.json date 확인 후 재실행 /usr/bin/python3 ~/.hermes/workspace/scripts/pipeline/bond_market_close.py --dry - 원인 후보: Gmail OAuth 만료 / 메일 미도착 / 파서 에러 / 신선도 가드 미구현 버전
- 로그:
tail -100 ~/.hermes/logs/bond_daily_report.log
장애 3: Telegram 봇 409 Conflict
- 증상: 봇이
409 Conflict: terminated by other getUpdates request에러 반복 - 진단: 같은 토큰으로 두 개 이상의 프로세스가 getUpdates 폴링 중
bash ps aux | grep hermes | grep -v grep # gateway 프로세스가 2개 이상 → 충돌 - 복구:
bash # 1. 모든 hermes 프로세스 종료 pkill -f "hermes-agent" # 2. gateway 재시작 launchctl unload ~/Library/LaunchAgents/ai.hermes.gateway.plist launchctl load -w ~/Library/LaunchAgents/ai.hermes.gateway.plist - 원인 후보: 수동 python 실행 후 종료 안 함 / launchd가 두 번 실행 / 배포 중 중복 기동
- 로그:
grep "409" ~/.hermes/logs/gateway.log | tail -20
장애 4: OAuth 만료 (Gmail / Google Drive 재인증)
- 증상: gmail_newsletter_collector / bond_report_parser 에러.
Token has been expired or revoked로그 - 진단:
bash ls -la ~/.hermes/credentials/ # token.json 확인 python3 -c " import json with open('/Users/ron/.hermes/credentials/token.json') as f: t = json.load(f) print('expiry:', t.get('expiry','없음')) " - 복구:
bash # 1. 기존 토큰 삭제 rm ~/.hermes/credentials/token.json # 2. 수동 인증 실행 (브라우저 열림) cd ~/.hermes/workspace python3 scripts/pipeline/gmail_auth.py # 또는 bond_report_parser.py --auth # 3. token.json 재생성 확인 후 크론 재검증 - 원인 후보: 6개월 미사용 / 보안 정책 변경 / 계정 비밀번호 변경
- 로그:
grep -i "token\|oauth\|credential" ~/.hermes/logs/bond_report_parser.log | tail -20
장애 5: codex-proxy 죽음
- 증상: Hermes 게이트웨이가 LLM 호출 실패.
Connection refused localhost:18642에러 - 진단:
bash curl -s localhost:18642/v1/models | head -5 # 응답 없으면 죽음 ps aux | grep codex-proxy | grep -v grep cat ~/.openclaw/workspace/logs/codex-proxy.log | tail -30 - 복구:
bash # 1. codex-proxy 재시작 (launchd 방식) launchctl list | grep codex-proxy launchctl stop [codex-proxy 서비스명] launchctl start [codex-proxy 서비스명] # 2. 직접 실행 방식 (임시) cd ~/.openclaw python3 workspace/codex-proxy/main.py & # 3. 검증 curl -s localhost:18642/v1/models - 원인 후보: ChatGPT 세션 만료 (재로그인 필요) / 포트 충돌 / Python 예외
- 로그:
~/.openclaw/workspace/logs/codex-proxy.log - 추가: ChatGPT 브라우저 로그인 확인 필요. 로그인 만료면 stealth-browser로 재인증.
N6. 볼트 frontmatter 실제 예시
~/knowledge-agent/100-inbox/119-크레딧메일/260422_황대진_...md 실측:
---
title: "전달: 금일 (4/23 목) 입찰 및 수요예측 안내 (DS증권 황대진)"
date: 2026-04-22
source_platform: gmail
source_channel: 황대진
category: 자금수급
tags:
- 크레딧
- 픽스드인컴
---
400-reports/ 에이전트 리포트 예시 (Claude Code 작성):
---
title: "Hermes 시스템 구조 전수조사 (인수인계)"
date: 2026-04-24
source: claude-code
tags: [hermes, system, handover, cron, pipeline, vault]
---
110 blog-insights/ 블로그 인사이트 예시 (pipeline 작성):
---
title: "..."
date: 2026-04-23
source: blog_monitor
source_channel: ranto28
tags: [bridge/blog_monitor, source/ranto28, status/fleeting]
---
필수 필드: title, date, source (또는 source_platform). tags는 필수에 가까움.
N7. v0.7.0 Phase 2 Rework 이슈 상세
GitHub 레포: Choi-Hyeonwoo/hermes. 실측 기준.
#47 cli.py argparse 재배선 + subcommand 모듈화 / Phase 2 of #10
- Depends on: #10 (Phase 1 barrel split) 머지 후
- 범위: HermesCLI 클래스의 슬래시 커맨드 디스패처를 argparse 기반 subcommand 모듈 (
hermes_cli/commands/*.py)로 재배선. baseline help parity 테스트 포함. deprecation warning 경로(기존 호출자 호환) 추가. - 배경: #10 원본이 barrel split + argparse 재배선 + subcommand 분리까지 포함했으나, PR #40(run_agent.py) 패턴과 일관성을 위해 Phase 1은 barrel split만으로 좁히고 이 이슈가 Phase 2 담당.
- 핵심 파일:
hermes-agent/cli.py(6700+ LOC),hermes-agent/hermes_cli/commands/ - 테스트: 기존 help 출력 캡처 → 재배선 후 동일성 확인 (help parity 스냅샷)
#48 gateway/run.py 추상화 심화 / Phase 2 of #11
- Depends on: #11 (Phase 1 barrel split) 머지 후
- 범위: 라우터/미들웨어/bootstrap 경계 재정의.
gateway/platforms/PlatformAdapter와 일관된 디스패치 경로 통합. - 배경: #11 원본 범위 중 순수 barrel split을 벗어나는 라우팅/미들웨어/플랫폼 디스패치 재설계를 Phase 2로 분리. PR #40 패턴 일관성 유지.
- 핵심 파일:
gateway/run.py,gateway/platforms/
#49 workspace/scripts/server.py 추상화 심화 / Phase 2 of #12
- Depends on: #12 (Phase 1 barrel split) 머지 후
- 범위: HTTP 핸들러 구조 재정리. 상태 저장소/startup-shutdown 경로 재설계.
- 배경: #12 원본 범위 중 핸들러 재구성/상태 저장소 리팩터를 Phase 2로 분리. 순수 이동만 먼저 반영.
- 핵심 파일:
workspace/scripts/server.py
#55 state/ 패키지 SSOT 이관 / Phase 2 of #17
- Depends on: #17 Phase 1 머지 후
- 범위: Phase 1은
hermes_agent.state패키지 facade만 추가. Phase 2에서 실제 SSOT 이관 수행. - SQLite 스키마 버전 관리 (alembic/yoyo/수동)
scripts/migrate_state_to_db.py마이그레이션 스크립트workspace/memory/,workspace/mission-control/직접 읽는 모든*.py를hermes_agent.state경유로 교체- 세션/메모리 round-trip 테스트 (
tests/state/test_roundtrip.py) - 핵심 파일:
hermes-agent/hermes_agent/state/,workspace/memory/,workspace/mission-control/
#58 errors/telemetry 전면 migration / Phase 2 of #15
- Depends on: #15 Phase 1 머지 후
- 범위: 기존
logging.getLogger(...),print('[ERROR]...'), ad-hocsys.stderr.write()전부를 새errors.py+telemetry.py경유로 교체. get_logger()교체 (grep 기반 전수 수정)HermesErrorraise로 교체- 최상위
except핸들러 (gateway, cli, scripts) →HermesError분기 추가 docs/ERROR_CODES.md신설 (최소 20개 코드 문서화)- 핵심 파일:
hermes-agent/전체*.py,docs/ERROR_CODES.md
#60 mypy strict 전면 확장 / Phase 2 of #14
- Depends on: #14 Phase 1 머지 후
- 범위: strict override를 아래 순서로 순차 확대. 각 모듈별 타입 힌트 보완 PR 분리.
hermes_agent/agentic.pyhermes_agent/tools/manager.pyhermes_agent/session.pyhermes_cli/**/*.pygateway/server.py,gateway/router.pyhermes_agent/config/*- 전략:
[tool.mypy.overrides]의 strict 블록에 순차 추가. CI에서mypy --strict통과 확인. 한 PR당 1~2 모듈 원칙. 기존 타입 힌트는 변경 없이 추가만. - 핵심 파일:
pyproject.toml(mypy 설정), 각 모듈*.py