Bug Description
is_local_endpoint() in agent/model_metadata.py only matches IP addresses, localhost, and _LOCAL_HOSTS. When running Hermes behind a local LLM proxy (e.g. LiteLLM, Ollama) accessed via Docker/Podman DNS name (like hermes-litellm or ollama), the function returns False.
This causes the stale stream timeout (180s default) to NOT be auto-disabled (the fix from #6368), leading to the infinite retry loop described in #7069 — the local model is still prefilling but the agent kills the connection and reconnects.
Root Cause
The check at line ~4951 in run_agent.py:
if _stream_stale_timeout_base == 180.0 and self.base_url and is_local_endpoint(self.base_url):
_stream_stale_timeout = float("inf")
...never triggers because is_local_endpoint("http://hermes-litellm:4000/v1") returns False — it's not an IP, not in _LOCAL_HOSTS, and the hostname can't be parsed as an IP address.
Proposed Fix
Three additions to is_local_endpoint():
-
Unqualified hostnames (no dots) → always local. A hostname like ollama, litellm, or hermes-litellm is always a local network name (Docker DNS, mDNS, /etc/hosts). This covers the most common case with zero configuration.
-
DNS resolution fallback — resolve the hostname to an IP with socket.gethostbyname(), then check if it's private. This catches qualified local hostnames like ollama.local or litellm.internal.
-
Configurable model.local_endpoints — a list of hostnames in config.yaml to explicitly mark as local. Useful for edge cases where DNS resolution isn't available or the hostname is unusual.
Related
Bug Description
is_local_endpoint()inagent/model_metadata.pyonly matches IP addresses,localhost, and_LOCAL_HOSTS. When running Hermes behind a local LLM proxy (e.g. LiteLLM, Ollama) accessed via Docker/Podman DNS name (likehermes-litellmorollama), the function returnsFalse.This causes the stale stream timeout (180s default) to NOT be auto-disabled (the fix from #6368), leading to the infinite retry loop described in #7069 — the local model is still prefilling but the agent kills the connection and reconnects.
Root Cause
The check at line ~4951 in
run_agent.py:...never triggers because
is_local_endpoint("http://hermes-litellm:4000/v1")returnsFalse— it's not an IP, not in_LOCAL_HOSTS, and the hostname can't be parsed as an IP address.Proposed Fix
Three additions to
is_local_endpoint():Unqualified hostnames (no dots) → always local. A hostname like
ollama,litellm, orhermes-litellmis always a local network name (Docker DNS, mDNS, /etc/hosts). This covers the most common case with zero configuration.DNS resolution fallback — resolve the hostname to an IP with
socket.gethostbyname(), then check if it's private. This catches qualified local hostnames likeollama.localorlitellm.internal.Configurable
model.local_endpoints— a list of hostnames in config.yaml to explicitly mark as local. Useful for edge cases where DNS resolution isn't available or the hostname is unusual.Related