Problem
When a user selects the Custom provider (for llama.cpp, LM Studio, Ollama, vLLM, etc.) via hermes setup or the /model picker, the runtime resolves to OpenRouter instead of the local server. No request ever reaches the local model — it silently hits OpenRouter with the local model name (e.g. Carnice-9b-Q4_K_M.gguf), which of course fails.
Root Cause
In runtime_provider.py, _get_named_custom_provider() (line 289) explicitly returns None for bare "custom":
def _get_named_custom_provider(requested_provider: str) -> Optional[Dict[str, Any]]:
requested_norm = _normalize_custom_provider_name(requested_provider or "")
if not requested_norm or requested_norm == "custom":
return None # <-- bare 'custom' always returns None
This causes _resolve_named_custom_runtime() to return None, and the resolution chain falls all the way through to _resolve_openrouter_runtime().
The _get_custom_base_url() function in models.py reads model.base_url from config.yaml, but that's the default model's URL (e.g. Z.AI or OpenRouter), not a local server. There is no CUSTOM_BASE_URL env var check in the runtime provider resolution path — it only exists in models.py for the model list display.
Named custom providers (e.g. custom:local) with entries under providers: in config.yaml work correctly because they match in _get_named_custom_provider().
Steps to Reproduce
- Run a local server on localhost:8082 (llama.cpp, LM Studio, etc.)
- In a Hermes session, use
/model to switch to the Custom provider
- Select a model from the local server
- Send a message — it routes to OpenRouter instead of localhost
Expected Behavior
Bare custom provider should resolve to a local endpoint. Options:
- Check
CUSTOM_BASE_URL env var during runtime provider resolution (not just for model listing)
- Or:
hermes setup should create a named entry under providers: in config.yaml when the user configures a custom endpoint (e.g. providers.local.base_url)
- Or: fall back to
model.base_url only when it looks like a local URL (localhost/127.0.0.1)
Workaround
Manually add named entries to ~/.hermes/config.yaml:
providers:
local:
base_url: http://localhost:8082/v1
api_key: no-key-required
default_model: your-model.gguf
Then use custom:local when hotswapping in-session.
Environment
- Hermes Agent v0.10.0 (2026.4.16)
- Python 3.11.14
- Local backend: llama.cpp server on localhost:8082
Problem
When a user selects the Custom provider (for llama.cpp, LM Studio, Ollama, vLLM, etc.) via
hermes setupor the/modelpicker, the runtime resolves to OpenRouter instead of the local server. No request ever reaches the local model — it silently hits OpenRouter with the local model name (e.g.Carnice-9b-Q4_K_M.gguf), which of course fails.Root Cause
In
runtime_provider.py,_get_named_custom_provider()(line 289) explicitly returnsNonefor bare"custom":This causes
_resolve_named_custom_runtime()to returnNone, and the resolution chain falls all the way through to_resolve_openrouter_runtime().The
_get_custom_base_url()function inmodels.pyreadsmodel.base_urlfrom config.yaml, but that's the default model's URL (e.g. Z.AI or OpenRouter), not a local server. There is noCUSTOM_BASE_URLenv var check in the runtime provider resolution path — it only exists inmodels.pyfor the model list display.Named custom providers (e.g.
custom:local) with entries underproviders:in config.yaml work correctly because they match in_get_named_custom_provider().Steps to Reproduce
/modelto switch to the Custom providerExpected Behavior
Bare
customprovider should resolve to a local endpoint. Options:CUSTOM_BASE_URLenv var during runtime provider resolution (not just for model listing)hermes setupshould create a named entry underproviders:in config.yaml when the user configures a custom endpoint (e.g.providers.local.base_url)model.base_urlonly when it looks like a local URL (localhost/127.0.0.1)Workaround
Manually add named entries to
~/.hermes/config.yaml:Then use
custom:localwhen hotswapping in-session.Environment