Skip to main content

Hermes

AI agent gateway with an OpenAI-compatible API and a live dashboard.

ToolUse for
Hermes dashboardSessions, skills, and agent configuration
Open WebUIDay-to-day conversations
opencodeCoding assistant — connect via Hermes gateway as the OpenAI API endpoint

Configure opencode to point at the Hermes gateway (https://hermes-agent.<domain>/v1) with HERMES_API_KEY as the API key so all three surfaces share the same models and skills.

Services

ContainerPurposePort
hermes-agentGateway API + dashboard48642 (API), 49119 (dashboard)

Architecture

hermes-agent is the long-running gateway. It exposes an OpenAI-compatible HTTP API on :8642 and a dashboard on :9119. Open WebUI connects to it over the internal exist network.

The ./data directory is bind-mounted into the container for agent config, sessions, skills, and memory.

Profiles

With GATEWAY_MULTIPLEX_PROFILES=1 the gateway serves more than one agent from the same container. The default profile answers at /v1; every other profile lives at /p/<name>/v1 with its own HERMES_HOME under /opt/data/profiles/<name>/, and therefore its own toolsets, MCP servers and skills.

That separation is what makes routing affordable. A profile's system prompt carries a schema for every tool it owns — roughly 2.4 KB each — so the default profile's 21 tools cost about 17,000 tokens on every single call. A router that only has to pick a department needs no tools at all, so it runs at about 650 tokens: a 64x reduction on a decision made for every incoming message.

Each profile needs its own API_SERVER_KEY — one profile's key will not authenticate against another, and an unknown profile name returns 404. ai/hermes/entrypoint.sh creates one profile per directory in ai/hermes/profiles/ on every boot, reading each department's declared description, toolsets and MCP servers out of its profile.yml. It is idempotent, so a restart only fills in what is missing.

See Routing to Departments for how a message reaches the right one.

Model configuration

The model: block in config.yaml is kept in step with .env.shared — change EXIST_MODEL_CHAT or the chat endpoint and the next ./existential.sh moves hermes with the rest of the stack. That only applies while the block still points at a local model server (provider: custom and a :11434 endpoint). Point it at Anthropic, OpenRouter or anything else and it becomes yours: every line is left alone from then on, except context_length, which is a fact about how the model was built rather than a preference.

Authentication

HERMES_API_KEY in ai/hermes/.env.exist is the shared secret for the gateway. It is the gateway's API_SERVER_KEY; Open WebUI sends it as OPENAI_API_KEY.

Upgrading

The hermes-agent-src volume caches the agent Python source. After pulling a new image, remove it before restarting:

docker compose down
docker volume rm hermes_hermes-agent-src
docker compose pull && docker compose up -d

Debugging

docker compose logs hermes-agent