NousResearch/hermes-agent · critical · RuntimeError
Failed to initialize OpenAI client: {e}
Error message
Failed to initialize OpenAI client: {e} What it means
A generic wrapper around ANY exception thrown while constructing the OpenAI-compatible client during agent init — the try block spans key inspection, banner printing, and client construction. The real cause is carried in {e}; this RuntimeError only adds the 'during init' context.
Source
Thrown at agent/agent_init.py:1446
if not agent.quiet_mode:
print(f"🤖 AI Agent initialized with model: {agent.model}")
if base_url:
print(f"🔗 Using custom base URL: {base_url}")
# ``api_key`` may be a callable Entra ID bearer
# provider (Azure Foundry). The OpenAI SDK mints a
# fresh JWT per request internally — the banner
# never invokes or inspects the callable.
from agent.azure_identity_adapter import is_token_provider
key_used = client_kwargs.get("api_key", "none")
if is_token_provider(key_used):
print("🔑 Using credentials: Microsoft Entra ID")
elif isinstance(key_used, str) and key_used and key_used != "dummy-key" and len(key_used) > 12:
print(f"🔑 Using API key: {key_used[:8]}...{key_used[-4:]}")
else:
print("⚠️ Warning: API key appears invalid or missing")
except Exception as e:
raise RuntimeError(f"Failed to initialize OpenAI client: {e}")
# Keep a stable identity for the pool entry that supplied this runtime.
# OAuth refreshes can replace the runtime token before a failed request is
# recovered, so the mutable API-key value alone cannot reliably attribute
# the failure to its source entry.
from agent.agent_runtime_helpers import sync_credential_pool_entry_id
sync_credential_pool_entry_id(agent)
# Provider fallback chain — ordered list of backup providers tried
# when the primary is exhausted (rate-limit, overload, connection
# failure). Supports both legacy single-dict ``fallback_model`` and
# new list ``fallback_providers`` format.
if isinstance(fallback_model, list):
agent._fallback_chain = [
f for f in fallback_model
if isinstance(f, dict) and f.get("provider") and f.get("model")
]
elif isinstance(fallback_model, dict) and fallback_model.get("provider") and fallback_model.get("model"):View on GitHub (pinned to c896c09c42)
Solutions
- Read the {e} portion of the message first — it names the actual failure; fix that underlying cause
- Validate model.base_url in config.yaml is a well-formed http(s) URL with a valid port
- Verify the API key resolves to a string or a token-provider callable, not dict/None
- Reinstall the pinned dependency set (uv sync) if the openai SDK surface drifted
Example fix
# config.yaml — before model: base_url: "https://api.example.com:v1" # after model: base_url: "https://api.example.com/v1"
Defensive patterns
Strategy: try-catch
Validate before calling
from urllib.parse import urlparse
def client_config_sane(base_url: str, api_key) -> str | None:
if base_url:
try:
parsed = urlparse(base_url)
if parsed.scheme in {"http", "https"}:
_ = parsed.port # raises on malformed port
except ValueError:
return f"bad base_url: {base_url!r}"
if api_key is not None and not (isinstance(api_key, str) or callable(api_key)):
return f"api_key must be str or callable, got {type(api_key).__name__}"
return None
err = client_config_sane(base_url, api_key)
if err:
fail_fast(err) Try / catch
try:
agent = AIAgent(...)
except RuntimeError as e:
if str(e).startswith("Failed to initialize OpenAI client:"):
underlying = str(e).split(":", 1)[1].strip()
log_and_report(underlying) # the {e} suffix is the real cause
raise Prevention
- Validate base_url shape and api_key type before constructing the agent
- Pin the openai dependency range so SDK surface changes cannot break init
- Never hand-edit config.yaml URLs without paste-checking them into a URL parser first
When it happens
Trigger: Any constructor failure: malformed model.base_url rejected by httpx, wrong api_key type (dict/None where a string or token-provider callable is expected), broken proxy configuration, azure token-provider errors, or an openai SDK version whose surface changed.
Common situations: Custom endpoint URL with a bad port/scheme in config.yaml; OPENAI_BASE_URL typo; openai package upgraded/downgraded out of the pinned range; a model-provider plugin returning an unexpected key type.
Related errors
- Provider '{_explicit}' is set in config.yaml but no API key
- No LLM provider configured. Run `hermes model` to select a p
- Invalid profile name: ${value}
- SSH host is required.
- HERMES_DESKTOP_REMOTE_URL is set but HERMES_DESKTOP_REMOTE_T
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/187b96df52c9d0f2.
Report an issue: GitHub.