Skip to content

bug: bare 'custom' provider falls through to OpenRouter — no base_url resolution #14676

@thadreber-web

Description

@thadreber-web

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

  1. Run a local server on localhost:8082 (llama.cpp, LM Studio, etc.)
  2. In a Hermes session, use /model to switch to the Custom provider
  3. Select a model from the local server
  4. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High — major feature broken, no workaroundarea/configConfig system, migrations, profilescomp/agentCore agent loop, run_agent.py, prompt buildertype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions