# Hermes 모델 라우팅·토큰 생존성 감사

- 감사 시각: 2026-08-03 11:28 KST
- 범위: 현재 124개 cron, Hermes Agent 전역 모델, 스크립트 내부 provider/router, 사용량 원장, 회로차단기, 로컬 fallback, 최근 7일 실행
- 제외: 비밀값·인증 토큰·개인 포트폴리오 수치/본문
- 작업 성격: 진단 전용. 운영 코드와 모델 설정은 변경하지 않았다.

## 한 줄 결론

보호장치는 이미 많이 구현돼 있지만 **두 개의 서로 다른 LLM 경로에 절반씩 배선돼 있고, 현재 폴백 종단이 끊겨 있다.** Claude 사용한도 뒤에 Sol과 Qwen이 존재하지만, Sol은 개인정보 휴리스틱 과차단과 전역 `xhigh` 때문에 생산 성공률이 낮고 Qwen 서버는 감사 시점에 내려가 있다. 따라서 “사다리가 있다”와 “제품이 살아남는다”가 일치하지 않는다.

## 질문에 대한 직접 답

### 글 작성이 Opus 5인가

아니다. 현재 정확한 기본 모델 문자열은 `claude-opus-4-8`이다.

- Hermes Agent 전역 기본: `claude-opus-4-8` — `config.yaml:1-8`
- 글 작성 라우팅: briefing, digest, 영어/CS/철학 케이스, paper deep-dive, breaking은 `OPUS` — `scripts/model_router.py:21-23`, `:62-74`
- 분류·요약·메모리 추출·속보 Oracle은 대체로 `claude-sonnet-5` — `model_router.py:75-94`
- 45개 agent-prompt cron은 job별 모델이 하나도 없어 전역 Opus 기본을 상속한다.
- 79개 script-only cron 중 LLM 소비 스크립트는 각자 router/provider/direct CLI 경로를 사용한다.

즉 “사용자용 긴 글은 Opus 계열”이라는 정책은 존재하지만, 전부 통일된 것은 아니다. 단순 요약은 Sonnet, 일부 폴백·교차검증은 Sol/Qwen, Oracle은 Claude 고정 경로가 섞여 있다.

### GPT-5.6 Sol로 바꾸는 것이 맞나

**공개정보 기반 고난도 작성의 기본을 Sol로 올리는 방향은 맞다.** 하지만 지금 전역 문자열만 Sol로 바꾸면 장애가 더 커질 가능성이 높다.

1. 현재 Sol 어댑터는 이미 존재하고 실제 생산 호출도 했다.
2. 그러나 최근 7일 Sol 생산 호출 94건 중 성공 14건, 실패 80건이었다.
3. Codex 전역 추론 강도가 `xhigh`이고 어댑터가 이를 override하지 않아 단순 작업까지 `xhigh`를 상속하는 구조로 보인다.
4. 공개 금융 프롬프트도 개인정보 휴리스틱에 걸려 Sol 호출이 막힌다.
5. 생성이 Sol로 성공해도 속보 Oracle은 Claude Sonnet에 고정돼 있어 Claude 한도 때 최종 전달이 중단된다.
6. 개인 포트폴리오 원문은 Sol뿐 아니라 Claude에도 보내면 안 된다. 로컬 처리 또는 비식별·집계 후 공개정보 분석만 외부 모델에 보내야 한다.

OpenAI 공식 가이드는 Sol을 복잡한 전문 작업용 flagship으로 두되, 대량·저비용 작업까지 전부 Sol로 치환하지 말고 역할별로 Sol/Terra/Luna를 나누고 reasoning effort를 의도적으로 설정하라고 안내한다. 현재 Hermes에는 그 역할별 OpenAI 라우팅이 아직 없다.

## 현재 실행 구조

| 층 | 현재 기본 | 현재 fallback | 실제 문제 |
|---|---|---|---|
| Hermes Agent cron 45개 | custom localhost proxy → Claude Opus 4.8 | `fallback_providers: []` | Claude quota 문구가 정상 응답으로 통과할 수 있음 |
| script 내부 provider | Claude subprocess | Claude → Sol → NVIDIA → Qwen | Sol 과차단, NVIDIA 생산 체인 혼입, Qwen 불안정 |
| 일반 Oracle | Claude Opus 4.8 고정 | 없음 | 작성 모델 전환과 무관하게 Claude가 단일 장애점 |
| 속보 Oracle | Claude Sonnet 5 고정 | 없음 | Sol로 본문 생성해도 Claude quota면 미발송 |
| 토큰 보호 | 비필수 22개 진입점 skip | 필수 제품은 통과 | 필수 제품의 다음 provider가 실제로 살아 있지 않음 |

현재 cron은 124개 모두 enabled다. job별 `model` 명시 0개, job별 `provider` 명시 0개다. 따라서 한 작업만 격리해 전환하기 어렵고 전역 설정 변경의 blast radius가 크다.

## 최근 7일 실제 생산 사용량

`state/llm_usage.db`의 `run_kind=prod`만 집계했다. `token_estimate`는 글자수 기반 근사치라 비용 정산값이 아니다.

| Provider/model | 호출 | 성공 | 실패 | 추정 토큰 |
|---|---:|---:|---:|---:|
| Claude Sonnet 5 | 498 | 472 | 26 | 2,293,697 |
| Claude Opus 4.8 | 213 | 189 | 24 | 1,076,296 |
| Claude 기타/별칭 | 28 | 23 | 5 | 128,376 |
| GPT-5.6 Sol | 94 | 14 | 80 | 694,572 |
| Qwen local | 80 | 46 | 34 | 735,121 |

해석:

- Claude subprocess는 739호출로 전체 생산 호출의 80.9%다.
- Sol 실패율은 85.1%, Qwen 실패율은 42.5%다.
- 속보의 Sol 호출은 최근 7일 33건 전부 실패로 기록됐다.
- 최근 24시간 Claude 계열 생산 호출은 전부 실패했다.
- 감사 시점 `token_protect status`는 Claude circuit 때문에 보호 모드 ON이었다.
- 감사 시점 `127.0.0.1:11434`는 connection refused로 로컬 Qwen 최종단도 사용할 수 없었다.

## 발견 사항

### M-01 · CRITICAL — 현재 생존 사다리에 실제 성공 가능한 종단이 없음

- 실패 시나리오: Claude weekly quota → Sol 과차단 → NVIDIA skip → Qwen timeout/서버 부재 → 속보·학습·분석 제품 중단.
- 최근 7일 ladder 사건: Claude circuit skip 88건, Sol `PortfolioDataBlocked` 108건, Qwen timeout 40건.
- 파일: `scripts/llm_provider.py:792-959`, `scripts/gateway-keeper.sh:24-25`
- 판정: “degrade, don't die” 설계가 실제 production 데이터에서는 종단 성공을 보장하지 못한다.

### M-02 · CRITICAL — Agent proxy가 실제 weekly-limit 문구를 놓쳐 거짓 성공을 만든다

- 실패 시나리오: Claude CLI가 `weekly limit` 안내문을 stdout으로 반환 → proxy detector는 quota가 아니라고 판정 → HTTP 200 정상 completion으로 포장 → cron `ok/sent` 거짓녹색.
- 결정론 프로브: 같은 문구에 `llm_fallback._looks_like_quota_error=False`, `llm_provider._is_budget_exhausted=True`.
- 원인: 두 경로의 quota 정규식이 서로 다르다.
- 파일: `scripts/llm_fallback.py:39-59`, `:78-93`; `scripts/llm_provider.py:94-104`, `:353-357`; `scripts/claude-proxy.py:76-183`

### M-03 · HIGH — Sol 개인정보 백스톱이 공개 제품도 과차단한다

- 실패 시나리오: 공개 시장 분석에 `계좌`, `비중`, `수익률` 같은 단어가 개인 맥락과 함께 들어가면 실제 개인 수치가 없어도 전체 프롬프트를 차단한다.
- 증거: 최근 7일 Codex→다음 단 `PortfolioDataBlocked` 108건; 속보 Sol 33/33 실패.
- 파일: `scripts/llm_provider.py:55-61`, `:126-227`, `:456-464`, `:934-943`
- 판정: 개인정보 fail-closed 자체는 맞지만, public packet과 private packet을 호출 전에 구조적으로 분리하지 않아 public Sol 전환도 막는다.

### M-04 · HIGH — Oracle이 Claude에 고정돼 생성 fallback을 무효화한다

- 실패 시나리오: Sol/Qwen이 본문 생성에 성공해도 Claude Oracle이 quota면 제품을 보내지 않는다.
- 속보: `LP.get_provider("subprocess")`로 Sonnet 고정.
- 일반 digest/briefing Oracle: 동일하게 Claude subprocess Opus 고정.
- 파일: `scripts/breaking-news-monitor.py:1959-1973`; `harness/oracle.py:149-161`, `:247-257`

### M-05 · HIGH — Sol 호출이 전역 `xhigh`를 상속한다

- 실패 시나리오: 분류·fallback·장문 작성이 모두 같은 `xhigh`로 돌아 latency와 quota 사용량이 커지고 cron timeout을 유발한다.
- 근거: `~/.codex/config.toml:1-2`는 Sol + `xhigh`; CodexProvider 명령은 모델만 지정하고 effort override가 없다.
- 파일: `scripts/llm_provider.py:441-514`
- 판정: 역할별 `low/medium/high`가 필요하다. 전역 `xhigh`는 자동화 기본값으로 부적절하다.

### M-06 · HIGH — 로컬 Qwen이 최종단인데 현재 서비스가 내려가 있음

- 실패 시나리오: 외부 provider 두 단이 실패한 후에야 600초 로컬 호출을 시도하지만 포트가 닫혀 최종 실패한다.
- 감사 시점: `127.0.0.1:11434` connection refused. LaunchAgent 파일은 있으나 현재 서비스 목록에 없었다.
- 파일: `scripts/llm_fallback.py:35-36`, `:100-138`, `:194-216`; `scripts/llm_provider.py:521-571`

### M-07 · HIGH — 개인정보 정책이 provider별로 뒤집혀 있음

- 실패 시나리오: 개인 보유 구조가 Sol에는 차단되지만 Claude subprocess에는 그대로 전달될 수 있다.
- 현재 정책은 “개인 포트폴리오 수치를 외부 서비스에 보내지 않는다”이므로 Anthropic도 안전 단이 아니다.
- 파일: `scripts/llm_provider.py:55-61`, `:830-834`, `:894-900`
- 필요 계약: private 감지 후 허용 provider는 local뿐. 외부 모델에는 비식별·집계된 public packet만 허용.

### M-08 · MEDIUM — weekly quota를 30분 TTL로만 다룬다

- 실패 시나리오: 실제 reset까지 수십 시간이 남아도 30분마다 Claude를 다시 찔러 quota 실패와 회로 재개방을 반복한다.
- 파일: `scripts/llm_provider.py:685-715`
- 토큰 보호는 Opus 이름만 일 150콜로 세며 같은 구독의 Sonnet 소비와 provider별 reset 시각을 반영하지 않는다.
- 파일: `scripts/token_protect.py:47-101`, `scripts/budget_guard.py:33-53`

### M-09 · MEDIUM — 서로 다른 두 fallback 시스템이 드리프트함

- Agent proxy: Claude→Qwen, 실제 quota 문구 누락, timeout은 Qwen 사용 안 함.
- script provider: Claude→Sol→NVIDIA→Qwen, quota 문구 감지 정상.
- 결과: 같은 장애가 job 종류에 따라 정상·거짓성공·Sol fallback·즉시실패로 다르게 처리된다.
- 파일: `scripts/claude-proxy.py`, `scripts/llm_fallback.py`, `scripts/llm_provider.py`

### M-10 · RESOLVED — NVIDIA 연동 상태와 production 활성화 상태 혼동

- 실패 시나리오: 프로세스 시작 환경만 검사해 전용 보안 파일 fallback을 놓치면 정상 연동을 미연동으로 오판한다.
- NVIDIA provider는 환경변수가 없어도 기존 전용 보안 파일을 직접 읽는다. 과거 실호출 성공 이력을 재확인했고, 공개 production의 최종 외부 fallback은 `HERMES_NVIDIA_LIVE_ALLOWED=1`로 활성화했다. 실카나리에서 DeepSeek V4 Flash가 HTTP 529를 냈지만 GPT-OSS 120B로 자동 전환해 정상 응답을 받았다. 다만 지정 토큰을 정확히 그대로 쓰지는 않아 연결 성공과 형식 준수 품질은 분리 평가한다.
- 실제 gateway env는 `subprocess,codex,nvidia,ollama`다.
- 파일: `scripts/gateway-keeper.sh:24-25`, `scripts/llm_provider.py:823-829`

### M-11 · MEDIUM — cron별 model/provider 격리가 0개다

- 실패 시나리오: 전역 기본을 Sol로 바꾸면 수집·분류·글쓰기·검증·개인 포트폴리오 작업이 동시에 바뀐다.
- 현재 124개 job의 명시 model/provider는 각각 0개다.
- 파일: `cron/jobs.json`; 전역 상속은 `hermes-agent/cron/scheduler.py:1830-1855`, `:1908-1946`

### M-12 · MEDIUM — 단위 테스트는 통과하지만 실제 생존 종단을 검증하지 않는다

- 관련 테스트 76개는 모두 통과했다.
- 그러나 fake provider 성공을 주입하는 단위 테스트라 실제 OAuth/quota 문구, Codex 전역 effort, 공개 금융 프롬프트 과차단, Ollama daemon, Oracle, Telegram까지 잇는 E2E가 없다.
- 필요한 E2E: `Claude quota → Sol public generation → 독립 검증 → Telegram terminal receipt`.

## 세계설계자 제품의 올바른 형태

`X`는 **X 플랫폼, 옛 트위터**를 뜻한다. 내부 운영명 `세계 설계자 X 감시`는 X 계정의 새 게시물을 모으는 수집기다.

사용자에게 보여야 할 것은 링크 큐가 아니라 실행당 최대 한 건의 한국어 분석이다.

```text
🌐 세계설계자 변화 — 마크 앤드리슨

① 무슨 말: 최근 발언의 핵심을 초보자도 이해할 2~3문장
② 왜 중요: 정책·기술·투자 판단에 연결되는 인과
③ 반론: 말뿐인 서사인지 실제 돈·정책 변화인지
④ 볼 것: 다음 확인 트리거 2개

원문: 링크 1~2개
```

- X 관측과 공식 홈페이지 T1 수집은 사용자에게 직접 발송하지 않는다.
- 새 URL 여러 개는 한 인물별로 묶는다.
- 실질적 관점 변화가 없으면 무발송한다.
- 공개정보이므로 이 최종 합성은 Sol `medium`의 적합 후보다.

## 권장 목표 라우팅

사용자가 Claude 토큰을 기본 자동화에서 빼고 싶다는 전제의 권장안이다.

| 역할 | 1차 | 2차 | 추론 강도 | 비고 |
|---|---|---|---|---|
| 공개 속보·세계설계자·다이제스트 최종 작성 | GPT-5.6 Sol | local Qwen | medium, 어려운 회차만 high | 사용자 가치가 높은 글 |
| 짧은 분류·추출·중복제거 | local 또는 Terra/Luna | Sol low | none/low | Sol xhigh 금지 |
| 공개정보 팩트 검증 | 결정론 게이트 + local 독립 모델 | Sol 재검토 | low/medium | 생성과 같은 Sol 단독 Oracle 금지 |
| 코드 감사·자동수리 제안 | Sol | local | high | 실제 수정은 별도 승인 |
| 개인 포트폴리오 원문·수치 결합 | local only | 없음 | 작업별 | 외부 provider 전송 금지 |
| 개인 포트폴리오 관련 공개 뉴스 분석 | 비식별 public packet만 Sol | local | medium | 개인 수치는 로컬에서 최종 join |

Sol을 API로 직접 쓰면 ChatGPT 구독과 별도 과금이다. 현재 `CodexProvider`는 API key가 아니라 Codex CLI 로그인 경로다. 어느 경로를 기본으로 할지 먼저 고정해야 사용한도·비용 계측이 가능하다. 현재 원장은 입력/출력/추론 토큰을 분리하지 않아 API 비용을 정직하게 계산할 수 없다.

## 전환 순서

1. **P0 생존성 복구**: quota detector SSOT 통합, Qwen daemon/정확 모델 health 복구, NVIDIA production 체인 제거.
2. **P0 개인정보 경계**: private/local-only와 redacted-public packet을 구조적으로 분리.
3. **P0 Oracle 분리**: 속보와 digest의 Claude 고정 Oracle 제거; 결정론+local 검증으로 전환.
4. **P0 Sol effort 분리**: 자동화는 `medium` 기본, 분류 `low`, 코드 감사 `high`; 전역 `xhigh` 상속 차단.
5. **P1 세 작업 shadow**: 속보, 세계설계자 최종 요약, 공개 다이제스트를 Claude/Sol 동일 입력으로 비교하되 발송은 한 경로만.
6. **P1 terminal E2E**: Claude quota를 강제로 모사해 Sol 생성부터 Telegram receipt까지 한 번에 통과하는 테스트 추가.
7. **P1 단계적 cutover**: 공개 고난도 글부터 Sol-first. 개인 포트폴리오와 대량 분류는 별도 경로 유지.

## 검증

```text
pytest scripts/test_llm_provider_ladder.py
       scripts/test_llm_provider_retry_p1.py
       scripts/test_llm_provider_fin_backstop.py
       scripts/test_llm_provider_nvidia.py
       scripts/test_token_protect.py
       market_lens/tests/test_llm_provider.py

76 passed in 6.42s
```

단위 테스트 통과와 현재 production 생존 실패가 동시에 참이다. 이번 감사의 핵심은 그 간극이다.

## 2026-08-03 16:49 KST 수리 후 상태

위 발견은 감사 당시 스냅샷이다. 이번 수리로 다음 항목은 해소 또는 축소됐다.

- 공개 script 자동화: `gpt-5.6-sol → Claude subprocess → NVIDIA(최종 외부 fallback) → Ollama(로컬 비상단)`.
- Hermes Agent prompt: Claude primary를 유지하되 rate-limit·5xx·연결 오류 시 `openai-codex/gpt-5.6-sol` fallback.
- private payload: 외부 provider를 첫 호출 전 모두 제거하고 local Ollama만 허용한다.
- effort: 자동 작성 medium, 분류·추출 low, 코드 감사·연구 high로 분리해 전역 xhigh 상속을 차단했다.
- 회로: budget/auth 반복 실패는 30분에서 최대 24시간까지 적응 냉각하며, 뒤 단마다 최소 시간예산을 예약한다.
- NVIDIA: DeepSeek V4 Flash→GPT-OSS 120B 후보 풀과 API 실호출 성공 이력을 확인했다. 운영 live flag를 열었고 현재 gateway에도 상속됐다. DeepSeek 529 시 GPT-OSS 전환 실호출은 성공했으며, 두 후보 모두 5xx면 반복 폭풍 없이 Ollama로 강등한다. Kimi는 opt-in shadow 후보다.
- Claude call-count 경고선은 실제 token/reset SSOT가 아니므로 전역 skip을 유발하지 않는다. 실제 한도 응답 때 Claude circuit을 열고 fallback한다.
- gateway keeper는 PID 검증 단일 인스턴스 잠금을 가져 중복 `--replace` 재시작 루프를 막는다.

검증 결과: routing/NVIDIA/keeper 관련 `87 passed`, Hermes Agent fallback `59 passed`, 전체 scripts `4,062 passed / 0 failed / 2 skipped`. 공개 `gpt-5.6-sol` medium 카나리는 `CANARY_OK`; gateway는 단일 keeper·단일 gateway 유지, NVIDIA live flag 상속, Telegram HTTPS 연결을 확인했다. NVIDIA는 기존 전용 보안 파일을 사용하는 운영 fallback으로 활성화했고 DeepSeek 529→GPT-OSS 전환도 실증했다. 남은 핵심 미완은 Qwen 상시 health, USD 비용 원장, 실제 Telegram terminal receipt E2E다.
