Provider Routing Architecture

How a chat request travels from the UI to your chosen AI provider

Switch UI port 3000 Settings → Provider picks active provider PATCH /api/hermes-proxy Settings → Provider src/routes/settings.tsx PATCH config.yaml via API POST /api/send ~/.hermes/config.yaml model: default: auto provider: manifest providers: manifest: type: openai base_url: ... reads config ~/.hermes/.env ANTHROPIC_API_KEY=sk-... OPENAI_API_KEY=sk-... CUSTOM_API_KEY=... key_env → var lookup key_env lookup Hermes Agent port 8642 • Python runtime Provider Router reads config.yaml + .env selects endpoint + injects key Anthropic api.anthropic.com • Claude models type: anthropic OpenAI api.openai.com • GPT models type: openai OpenRouter openrouter.ai • multi-model routing type: openai Ollama (local) 127.0.0.1:11434 • no key required type: ollama Custom OpenAI-compat endpoint any base_url • key_env: CUSTOM_API_KEY type: openai (manifest) HTTPS API calls streaming response SSE chunks

Switch UI never calls providers directly

  • • All provider calls go through the Hermes Agent on :8642
  • • Settings UI PATCHes config.yaml via /api/hermes-proxy
  • • The UI receives tokens back as SSE, not raw provider JSON
  • • Provider selection persists in ~/.hermes/config.yaml

config.yaml + .env

  • • config.yaml holds provider type, base_url, key_env name
  • • ~/.hermes/.env holds the actual key values
  • • key_env field maps provider → env var name
  • • Custom endpoints use type: openai with provider: manifest

Provider types

  • • anthropic — native Anthropic SDK, streaming supported
  • • openai — any OpenAI-compatible API (also OpenRouter)
  • • ollama — local Ollama server, no key required
  • • manifest — named custom entry, avoids "custom" reserved name