virtual-insanity
← 리포트 목록

openclaw:main routing 400 investigation

2026-04-14 openclaw [openclaw, llm, gateway, incident]

진행 기록

현재 확인한 사실

  • 운영 로그에서 openclaw:main 호출이 HTTP Error 400: Bad Request를 반복함.
  • ~/.openclaw/logs/llm/20260414.jsonl 기준 10시대에도 openclaw:main 400이 계속 기록됨.
  • agent_queue_worker.py는 에이전트별 모델맵이 없을 때 get_model_chain(default_model="openclaw:main") 경로를 사용함.
  • orchestrator.pyRON_CHAT_MODEL = openclaw:main 기본값을 사용하고, chat_completion_with_fallback()에서 공용 LLM 호출로 넘김.
  • Hermes LaunchAgent의 활성 plist에는 API 서버 환경변수(API_SERVER_ENABLED/HOST/PORT)가 빠져 있었고, 백업 plist에는 존재했음.
  • API 서버 환경변수는 활성 plist에 복구했고 Hermes gateway LaunchAgent는 재시작했지만, 현재 127.0.0.1:18789는 여전히 LISTEN 상태가 아님. Hermes gateway는 메시징/크론 게이트웨이로는 살아 있음.
  • 직접 LLM 라우팅 검증에서는 openclaw:main을 구체 모델 체인으로 풀면 로컬 Ollama 폴백으로 성공 가능함.

중단 전 수행한 변경

  • /Users/ron/Library/LaunchAgents/ai.hermes.gateway.plist
  • API_SERVER_ENABLED=true
  • API_SERVER_HOST=127.0.0.1
  • API_SERVER_PORT=18789
  • 백업: /Users/ron/Library/LaunchAgents/ai.hermes.gateway.plist.bak-20260414-api-server
  • Hermes gateway와 agent queue workers/orchestrator-loop 재시작 완료.

현재 사용자 지시

  • shared/llm.pyllm_chat_with_fallback는 더 수정하지 말 것.
  • openclaw:main이 상류 모델로 번역되는 위치를 찾고, 그 위치에서 GPT-5 계열이 max_completion_tokens를 쓰도록 보장할 것.

다음 작업

  1. openclaw:main 번역 위치를 코드에서 재탐색.
  2. 로컬 OpenClaw/Hermes gateway HTTP API가 왜 18789를 열지 않는지 확인.
  3. 번역 지점 또는 gateway chat handler에서 payload 변환을 적용.
  4. 재시작 후 openclaw:main 실제 호출이 400이 아닌지 검증.

2026-04-14 재개 기록

  • 작업 재개. 사용자 추가 지시: shared/llm.pyllm_chat_with_fallback는 수정 금지.
  • 현재 초점: openclaw:main이 실제 upstream 모델로 새는 위치를 찾아, 그 경로에서 구체 모델 체인으로 변환되게 한다.
  • 우선 수정 후보: scripts/orchestrator.py, scripts/agent_queue_worker.py의 기본 모델 체인 fallback.

재탐색 결과

  • scripts/orchestrator.py에서 RON_CHAT_MODEL 기본값이 get_primary_model("openclaw:main")이고, 현재 함수는 그대로 openclaw:main을 반환한다.
  • scripts/agent_queue_worker.py에도 fallback _get_model_chain_orig(default_model="openclaw:main")이 있으나, 실제 LaunchAgent의 --agent 값은 모두 AGENT_MODEL_MAP에 있는 정식 이름이다. 따라서 주된 400 원인은 Ron orchestrator 기본 모델이 추상 라벨을 그대로 공용 LLM에 넘기는 경로로 보인다.
  • OpenClaw 문서/TS gateway 기준 openclaw:main은 upstream 모델명이 아니라 agent selector이다. Python 운영 경로에서는 이를 구체 모델 체인으로 풀어야 한다.

적용한 수정

  • scripts/orchestrator.py
  • openclaw:main/openclaw/* 추상 라벨을 ~/.openclaw/openclaw.jsonagents.defaults.model 체인으로 변환하도록 수정.
  • 설정 로드 실패 또는 cloud 실패 대비 최종 로컬 폴백 ollama/qwen2.5:3b 유지.
  • RON_CHAT_MODEL 기본값은 openclaw:main으로 유지하고, 호출 직전 get_model_chain()에서 전체 구체 모델 체인으로 변환한다.
  • scripts/agent_queue_worker.py
  • fallback _get_model_chain_orig()에서도 openclaw:main을 구체 모델 체인으로 변환하도록 수정.
  • shared/llm.pyllm_chat_with_fallback는 이번 재개 작업에서 수정하지 않음.

수정 보정

  • 최초 수정에서 RON_CHAT_MODEL 기본값을 primary 단일 모델로 바꾸면 fallback 체인이 잘릴 수 있음을 검증 중 발견했다.
  • 보정: RON_CHAT_MODEL 기본값은 openclaw:main으로 유지하되, 호출 직전 get_model_chain()에서 전체 구체 모델 체인으로 변환한다.
  • 이 방식은 로그/상류 호출에는 openclaw:main을 보내지 않으면서, 설정된 fallback 체인을 유지한다.

검증 결과

  • 문법 검사 통과:
  • python3 -m py_compile scripts/orchestrator.py scripts/agent_queue_worker.py
  • 라우팅 단위 검증 통과:
  • orchestrator.get_model_chain("openclaw:main")github-copilot/gpt-5-mini, openai-codex/gpt-5.4, ollama/qwen2.5:3b
  • agent_queue_worker.get_model_chain("openclaw:main", agent_name=None) → 동일 구체 체인
  • 결과 체인에 openclaw:main 없음.
  • payload 검증 통과:
  • github-copilot/gpt-5-mini의 실제 payload key는 max_completion_tokens이며 max_tokens 없음.
  • 실제 호출 검증 통과:
  • orchestrator.chat_completion_with_fallback() 수동 호출은 Copilot quota 429 후 ollama/qwen2.5:3b로 성공.
  • 운영 반영:
  • agent queue workers 8개와 com.openclaw.orchestrator-loop 재시작 완료.
  • 운영 로그 확인:
  • 10:54 이후 ~/.openclaw/logs/llm/20260414.jsonl에서 HTTP Error 400 = 0건.
  • 10:54 이후 openclaw:main + 400 = 0건.
  • Ron orchestrator 로그는 이후 LLM 응답을 ollama/qwen2.5:3b로 받고 있음.
  • Required Checks:
  • knowledge_os.py mcp-check → 4/4 healthy.
  • dashboard structure API → 응답 확인.
  • dashboard command queue API → 13개 항목 응답 확인.

남은 리스크

  • Copilot github-copilot/gpt-5-mini는 현재 일일 rate limit 429 상태라 운영은 당분간 Ollama fallback에 의존한다.
  • openai-codex/gpt-5.4는 현재 GitHub Models endpoint에서 unsupported로 기록된다. 이 문제는 400 원인과는 별개지만 fallback 지연/로그 잡음을 만든다.
  • openclaw:main의 원래 OpenClaw HTTP gateway 의미는 agent selector이고, 현재 Hermes gateway는 18789 HTTP API를 열지 않는다. 이번 수정은 Python 운영 경로에서 추상 라벨이 upstream 모델명으로 새는 문제를 막는 조치다.