GEODE는 Anthropic, OpenAI(+ChatGPT 구독), OpenRouter, GLM 네 프로바이더 경로를 명시적으로 라우팅합니다. 이 페이지는 모델이 어떻게 결정되고, 호출이 어느 어댑터로 가며, 실패했을 때 무엇이 일어나는지 정리합니다.
구성 요소
| 구성 | 코드 |
|---|---|
| 프로바이더 유틸리티 | core/llm/providers/anthropic.py, codex.py, glm.py, openrouter.py. quota·identity·request shaping을 어댑터에 제공 |
| 비동기 호출 어댑터 | core/llm/adapters/. SDK client와 acomplete() 호출 표면 소유 |
| 프로바이더 composition | core/llm/registry.py. 모델 identity, credential route, transport/API shape를 분리해 선언 |
| 어댑터 레지스트리 | core/llm/adapters/registry.py의 bootstrap_builtins(). 내장 factory와 운영자 정책이 승인한 geode.llm_adapters 진입점을 불변 generation snapshot으로 검색 |
| 라우팅 매니페스트 | core/config/routing.toml (+ ~/.geode/routing.toml 사용자 오버라이드). 모델 id prefix로 프로바이더 결정 |
서브프로세스 워커는 부모의 wiring 컨테이너를 거치지 않으므로 bootstrap_builtins()를 명시적으로 호출해야 합니다. 빈 레지스트리는 AdapterNotFoundError로 끝납니다. 각 AgenticLoop 세션은 생성 시 현재 generation을 캡처하므로, reload는 새 세션에만 보이고 실행 중 세션의 라우팅은 바뀌지 않습니다.
OpenRouter 경계
OpenRouter는 openrouter provider identity와 Chat Completions transport를 조합합니다. GEODE model id는 openrouter/<publisher>/<model>이며 어댑터가 외부 namespace 하나만 제거합니다. direct Anthropic/OpenAI와 equivalence group을 만들지 않으므로 자격이나 비용 경계가 조용히 바뀌지 않습니다. 응답이 제공한 실제 charge와 최종 serving route는 공통 usage/event 경로로 들어가고, 없을 때만 기존 정적 가격 추정을 사용합니다.
컴팩션 등 텍스트 요약도 같은 OpenRouter 어댑터를 사용해 캐시 마커, 세션 식별과 사용량을 보존합니다. 알려진 OpenAI reasoning 모델은 선택한 effort를 relay 요청에 전달하며, 다른 모델의 effort 지원을 추정하지 않습니다. 응답 스키마를 요청하면 JSON Schema 형식과 require_parameters: true를 함께 전달합니다. 명시적으로 이 옵션을 false로 지정한 호출은 거절합니다. 실제 스키마 지원과 강제 수준은 상위 endpoint에 달려 있고, 로컬 응답 검증도 유지됩니다.
알려진 OpenAI reasoning 경로는 기본 temperature를 전송하지 않고, 지원하지 않는 사용자 지정 값을 호출 전에 거절합니다. 이 relay에서는effort=none도 sampling 지원을 의미하지 않습니다. 선택한 effort와 공급자 제한은 그대로 유지합니다.
선택한 effort 보존
모델 선택 화면에서 확인한 effort는 요청의 값과 같아야 합니다. 프로바이더별 필드명은 달라도 값을 임의로 낮추거나 높이지 않습니다. 선택한 모델이 저장된 값을 지원하지 않으면 설정 변경이나 호출 전에 거절하므로, /model에서 지원하는 값을 직접 선택해야 합니다. 역할 탭을 이동하거나 Space로 선택을 추가한 뒤 Enter로 확정해도 primary effort를 보존합니다. 선택 화면에는 지원되는 값만 표시하며, 저장된 값이 맞지 않으면 방향키로 유효한 값을 고르기 전까지 Enter·Space 확정을 막습니다. 취소하면 기존 설정은 유지됩니다. Reflection 모델은 primary effort를 상속하므로, 함께 고른 모델과 effort의 호환성도 저장 전에 검사합니다.
지원되는 OpenAI·Claude·GLM 텍스트 보조 요청에도 명시한 effort를 전달합니다. OpenRouter의 알려진 OpenAI 경로도 같은 값을 전달합니다. effort 제어가 없는 모델은 선택 화면에 조절 기능을 표시하지 않으며, 서로 다른 모델의 같은 effort가 같은 계산량을 뜻하지는 않습니다.
모델 해석 우선순위
강한 쪽이 이깁니다.
CLI 인자
> env (os.environ + .env)
> 프로젝트 .geode/config.toml
> 글로벌 ~/.geode/config.toml
> routing.toml 기본값어느 레이어가 이기는지는 geode config explain model이 레이어별 후보와 함께 보여줍니다. 실효 모델 확인은 항상 geode about입니다. config.toml만 보고 판단하면 상위 env 레이어에 가려진 값을 놓칩니다.
폴백 체인은 비어서 출하됩니다
[model.fallbacks]는 기본값이 전부 빈 목록입니다. primary 모델이 실패하면 GEODE는 다른 모델로 몰래 갈아타지 않습니다. 쿼터 소진이면 BillingError를, 일시 오류면 마지막 예외를 그대로 올리고, 다음 모델은 사용자가 /model로 직접 고릅니다. 자동 폴백을 원하면 ~/.geode/routing.toml의 체인을 채워 옵트인합니다. 체인 실행기는 core/llm/router/calls/_failover.py의 call_with_failover입니다.
조용한 cross-provider 자동 전환은 의도적으로 삭제된 기능입니다. 관측 불가능한 폴백은 어느 모델이 답했는지에 대한 신뢰를 무너뜨립니다.
재시도와 fast-fail
분류와 지연은 core/llm/fallback.py의 RetryPolicy, classify_retry_error, retry_delay_for가 공유합니다. 메인 루프는 동일 모델 안에서, 보조 호출은 run_with_retry_policy로 명시된 모델 체인 안에서만 실행합니다. SDK 재시도는 0입니다. 상태를 가진 CircuitBreaker 클래스는 없습니다.
| 판정 | 대상 | 효과 |
|---|---|---|
is_billing_fatal | 결제, 쿼터 소진 | 재시도 없이 즉시 실패 |
is_request_fatal | 400류 요청 오류 | 같은 요청을 다시 보내봤자 같은 결과이므로 즉시 실패 |
classify_retry_error | 연결, timeout, 408/409/429/5xx | 설정된 총 시도 횟수 안에서 jitter backoff |
| stream/effect guard | 이미 보인 출력, 불확실한 부작용 | 동일 호출을 재실행하지 않고 중단 또는 reconcile |
모델별 동작 차이
모델 패밀리별 능력 앵커는 core/llm/model_capabilities.py에 있습니다. 한 가지가 운영에서 특히 중요합니다. Fable 5는 안전 거절을 HTTP 200의 stop_reason: "refusal"로 보내며, Anthropic 프로바이더의 normalize_anthropic이 stop_details를 보존하고 루프가 model_refusal 종료로 매핑합니다. 자세한 동작은 안쪽 agentic 루프의 종료 경로 절을 참고합니다.
실패 모드
| 증상 | 원인 | 해법 |
|---|---|---|
| 모델을 바꿨는데 효과가 없음 | 상위 레이어(env)가 가리는 중 | geode config explain model로 이기는 레이어를 찾고 geode about으로 실효값을 확인합니다 |
| primary 실패 시 다른 모델로 안 넘어감 | 폴백 체인이 기본값(빈 목록) | 의도된 동작입니다. /model로 전환하거나 ~/.geode/routing.toml에서 옵트인합니다 |
서브프로세스에서 AdapterNotFoundError | bootstrap_builtins() 미호출 | 워커 진입점에서 명시적으로 호출합니다 |
| 400 오류가 재시도 없이 바로 실패 | is_request_fatal fast-fail | 의도된 동작입니다. 요청 자체(스키마, 크기)를 고칩니다 |
다음
- 프로바이더 설정 가이드. 자격과 경로 선택.
- 도구 호출. ToolSpec, 선택 모드, 실행과 결과 replay.
- 구조화 출력. JSON Schema 배선과 검증 경계.
- 인증. OAuth, API 키, credential 경로.
- 어댑터 추가 가이드. 새 모델, 새 레인 붙이기.