에이전트 상태보고 '재시도대기·요청과다' 반복노출 정책 검토
[권고]
1순위: LLM_CONCURRENCY_MAX(현재 4)를 상한 재산정 — 세마포어 도입 후에도 시간당 429가 259건 발생 중
근거: agent_queue_worker.py 682-686행 R9 패치가 파일 기반 세마포어(LLM_CONCURRENCY_MAX=4)로 프로세스 간 동시 LLM 호출을 4개로 제한했음에도, 최근 1시간 로그 실측(grep -c 429)에서 codex 50건·cowork 82건·analyst-technical 56건·analyst-macro 36건·analyst-fundamental 35건, 합계 259건의 "HTTP Error 429: Too Many Requests / Too many concurrent runs (max 10)"가 계속 발생 중이다. 세마포어가 로컬 슬롯 수는 제한하지만 게이트웨이 계정 전역 상한(10)과 정합이 맞지 않거나, burst 디스패치 시 슬롯 획득~해제 사이 지연으로 순간적으로 여러 워커가 동시에 상한을 넘는 것으로 판단된다. LLM_CONCURRENCY_MAX를 2~3으로 하향하거나, 프로세스별(codex/cowork/analyst-*) 예약 쿼터를 나눠 게이트웨이 상한 10 대비 여유를 3배 이상 확보해야 한다. 기대효과: 429 재발 빈도 50% 이상 감소.
2순위: "재시도대기·요청과다" 문구를 실제 재시도 여부와 일치시킨다 — 현재 즉시실패인데 "대기중"으로 표시되는 불일치
근거: agent_queue_worker.py 4777행 LAST_TASK_DONE[agent] = f"#{cid} " + title[:14] + " (재시도대기·요청과다)"는 _is_llm_infra_failure_note()가 True일 때(429/timeout/model_cooldown_active) 무조건 붙는 라벨이다. 그런데 실제 로그(codex/cowork 공통)를 보면 [model-cooldown] codex 백오프 중 예산 소진(remaining=4.9s) — 모든 모델 쿨다운 유지, 강제 재시도 없이 즉시 실패 반환처럼 예산 소진 시 재시도를 하지 않고 그 자리에서 실패로 끝난다. 그런데도 표시 문구는 "재시도대기"라서 관찰자(오케스트레이터/해리)가 "곧 자동으로 재시도되어 해결될 것"으로 오인할 위험이 있다. 실제 동작 분기(재시도 진행 중 vs 재시도 소진·즉시실패 vs 모델 쿨다운 대기)에 따라 문구를 3종으로 분리해야 한다. 기대효과: 5개 에이전트 상태창이 실제 원인을 구분해 표시 → 관찰자가 "정상적으로 재시도 중"과 "재시도 자체가 끝난 실패"를 혼동하지 않음.
[현황]
- guardian의 큐 진단 결과(#36316, 2026-08-18 06:04~06:06 실행) 인용: "결론: 429 백오프 여부는 큐 수치(queued=5, claimed=6, done=7)만으로 판단 불가 — 실제 로그/에러코드 미확인." (#36347) 및 "[리스크] 실패 원인은 데이터소스가 아니라 LLM 오케스트레이션 레이어 429(동시 실행 한도 10건 근접)였음. yfinance 소스 자체는 정상이라 교체 불필요." (#36316) — guardian은 큐 수치만으로 원인을 단정하지 않고, 로그 원문(
HTTP Error 429: Too Many Requests,Too many concurrent runs (max 10))을 근거로 "실제 요청과다"로 판정했다. 즉 이번 사례는 템플릿 버그가 아니라 실제 API 동시성 상한 초과로 원인이 이미 특정돼 있다. - 코드상 근본 원인도 이미 R9 패치 주석(671-681행)에 문서화되어 있다: "7개 에이전트 워커 프로세스가 각자 독립 LaunchAgent로 떠서 orchestrator burst 디스패치 시 동시에 같은 anthropic/claude-sonnet-5 게이트웨이를 호출 — 계정 전역 동시성 상한(max 10)에 부딪힘."
- 최근 12시간
bus_commands집계: failed 14건, done 7건, cancelled 2건, claimed 2건. failed 14건 중 5건이 429/timeout/cooldown 텍스트를 포함(result_note LIKE '%429%' OR '%timeout%' OR '%cooldown%'). - 최근 1시간 429 텍스트 발생 건수(로그 grep 실측): codex 50 / cowork 82 / analyst-fundamental 35 / analyst-macro 36 / analyst-technical 56 (합계 259).
- 현재 LLM 동시성 슬롯 디렉토리(
~/.hermes/run/llm_concurrency/) 실물 확인: 활성 슬롯 파일 2개(22591_a26f6da5.slot,26360_ae39f48d.slot) — 설정 상한 4개 중 2개만 점유, 즉 세마포어 자체는 정상 작동 중이며 "슬롯 부족"이 아니라 "게이트웨이 전역 상한과 로컬 상한의 정합 부족"이 원인 후보로 좁혀진다. - 429 전용 쿨다운(R10 패치,
MODEL_429_STREAK_THRESHOLD=3,MODEL_429_COOLDOWN_SEC=300초)과 model_cooldown_active 즉시실패 분류(R12 패치)는 이미 구현되어 있으나, 시간당 259건이라는 실측치는 현재 파라미터가 여전히 부족함을 보여준다. - guardian 자신도 같은 429에 두 번(#36278, #36279, 2026-08-18 01:49~02:00) 잡아먹혀 검증 태스크 자체가 실패한 이력이 있다 — 진단 주체가 진단 대상 장애에 종속되는 구조.
[리스크]
- 단일 장애점:
LAST_TASK_DONE[agent] = ...라벨 생성 로직이agent_queue_worker.py4777행 한 곳에 집중돼 있고, 이 문자열이 5개 에이전트 대시보드 current_task 필드와 orchestrator의 Ron LLM 프롬프트 컨텍스트에 동시에 흘러들어간다(R8 패치 주석, 1201-1216행: title[:20] 절단으로 orchestrator가 실패를 다른 의미로 오독해 존재하지 않는 장애를 진단하라는 태스크(#36309, #36312)를 반복 생성한 전례 있음). 문구를 바꾸면 orchestrator 프롬프트 파싱 로직도 함께 검토해야 한다 — 표시만 고치고 소비처를 안 보면 R8과 같은 2차 오독이 재발할 수 있다. - 세마포어 하향의 트레이드오프:
LLM_CONCURRENCY_MAX를 낮추면 429는 줄지만 claimed 상태 적체(큐잼)가 늘어날 수 있다. 12시간 claimed 2건 수준은 아직 여유가 있으나, 하향 폭이 크면(예: 4→1) 처리량이 급감해 다른 큐잼 감지 로직(대기 5건·30분 초과)이 새로 트리거될 위험이 있다. - 진단 주체의 자기잠식: guardian 스스로도 같은 429에 실패한 이력이 있어(#36278/#36279), 이번 정책 개선 이후 재검증을 guardian에게 다시 맡길 경우 검증 태스크 자체가 같은 장애로 실패할 가능성이 남아있다 — 검증 시점을 429 빈도가 낮은 시간대로 분리하거나 검증 태스크를 저우선순위 큐에서 재시도하도록 배치해야 한다.
- 재시도 정책 불일치가 이미 1건 실측됨:
MODEL_429_COOLDOWN_SEC(5분)과MODEL_TIMEOUT_COOLDOWN_SEC(10분)이 별도 트랙으로 관리되는데, 예산 소진 시(remaining=4.9s) 두 트랙 모두 "강제 재시도 없이 즉시 실패"로 수렴한다 — 이 즉시실패 분기가 코드 여러 지점(1384-1402행, 로그 기준)에 흩어져 있어 향후 파라미터 변경 시 한 곳만 고치고 다른 곳을 누락할 위험이 있다.
[검증방법]
- KPI: 정책 변경 후 1시간 동안
grep -c 429 /Users/ron/.hermes/logs/agent-queue-{codex,cowork,fundamental,macro,technical}.log합계가 현재 259건 대비 50% 이상(130건 이하) 감소. - 명령:
sqlite3 ~/.hermes/data/ops_multiagent.db "SELECT status, count(*) FROM bus_commands WHERE updated_at >= datetime('now','-1 hour') GROUP BY status;"— failed 비율이 현재(12시간 14/25=56%) 대비 개선되는지 확인. - 기대값: LLM 동시성 슬롯 디렉토리(
~/.hermes/run/llm_concurrency/) 파일 수가 설정 상한을 초과하지 않고, claimed 상태가 30분 이상 5건을 넘지 않음(guardian 큐잼 기준 재사용). - 문구 수정 검증: 5개 에이전트 current_task 필드를
/api/bus/agents로 재조회해 "재시도대기"와 "즉시실패"가 서로 다른 문구로 구분 출력되는지 확인. - 롤백 조건:
LLM_CONCURRENCY_MAX하향 후 30분 관찰에서 claimed 적체가 5건을 초과하거나 done 처리량이 하향 전 대비 30% 이상 감소하면 원래 값(4)으로 즉시 복원한다.