Hermes Agent
Nous Research's self-improving terminal agent, pointed at Melious through a provider profile
Hermes Agent is Nous Research's terminal agent, and the unusual part is what it does between sessions: it writes skills from what it learned doing a task, edits them the next time they don't quite fit, keeps a memory file about you, and searches its own past conversations. It also doesn't stay in the terminal — one gateway process fronts Telegram, Discord, Slack, and WhatsApp against the same agent. Providers are declared as profiles rather than hardcoded, so adding a backend is two files and no patch to the codebase. There's a pleasing symmetry in pointing it at us: Melious serves Nous' own Hermes 4 weights, so you can run their agent on their models on European infrastructure.
Setup
Install Hermes
The installer creates a virtualenv, puts hermes on your PATH, and clones the project into ~/.hermes/hermes-agent (a Linux root install puts the code under /usr/local/lib instead — the config path below is the same either way). Python 3.11–3.13.
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bashiex (irm https://hermes-agent.nousresearch.com/install.ps1)Windows is supported natively — no WSL needed.
Add Melious as a provider
Hermes discovers provider profiles from ~/.hermes/plugins/model-providers/<name>/, so a directory is all it takes. Create ~/.hermes/plugins/model-providers/melious/__init__.py:
from providers import register_provider
from providers.base import ProviderProfile
register_provider(ProviderProfile(
name="melious",
display_name="Melious",
env_vars=("MELIOUS_API_KEY", "MELIOUS_BASE_URL"),
base_url="https://api.melious.ai/v1",
auth_type="api_key",
default_aux_model="gpt-oss-20b",
fallback_models=(
"hermes-4-405b",
"glm-5.1",
),
)) The env var order matters: the API key comes first, and a name ending in _BASE_URL is treated as the base-URL override rather than a credential.
Adding the profile wires up everything downstream — credential resolution, the --provider flag, the hermes model picker, the hermes doctor health check, the hermes setup wizard, and the model catalog fetched from /v1/models. No other file needs editing.
This is the supported mechanism, not a workaround — Hermes documents user plugins as a first-class path and reads them on every start. Worth knowing for later: a plugin in ~/.hermes/ overrides a bundled one of the same name, not the other way round. So if melious ever ships built into Hermes, delete this directory — leave it in place and your file keeps winning, and you'd be running this short profile instead of the richer built-in one.
Add your key and pick a model
echo "MELIOUS_API_KEY=sk-mel-<YOUR_API_KEY>" >> ~/.hermes/.env
hermes doctorhermes doctor lists Melious under API Connectivity with a /v1/models probe — a green check there means the profile loaded and the key works.
hermes chat -q "Say hello" --provider melious --model hermes-4-405bOr set it permanently in ~/.hermes/config.yaml:
model:
provider: "melious"
default: "hermes-4-405b"hermes model walks you through provider and model selection interactively, and /model switches between already-configured providers inside a session.
Picking a model
Hermes runs long tool-call chains and edits files across many turns, so the thing that matters is whether a model holds a plan together — not raw benchmark scores. Filter GET /v1/models?include_meta=true on _meta.capabilities.function_calling and sort by _meta.context_length, or browse melious.ai/hub/models.
hermes-4-405b is Nous' own model and the obvious place to start — a 128K window and tool calling. For longer sessions, glm-5.2, deepseek-v4-pro, kimi-k3, and minimax-m3 each carry a 1M-token window. glm-5.1 is a good middle default at 203K.
One thing to know about the model list: our /v1/models response covers every surface we run — embeddings, image generation, transcription, guardrails — not only chat. A generic OpenAI-compatible client will show you all of it, so bge-m3 and flux-2-dev can turn up in a model picker where they make no sense. Filter on _meta.type == "chat" if you're building the list yourself.
Append a flavor suffix to bias provider selection — hermes-4-405b:speed, :price, or :eco. See Routing.
Auxiliary models
Hermes runs side tasks on a second, cheaper model: context compression when a session approaches its window, session-search summaries, web-extract summaries, memory flushes, and image description. That's what default_aux_model in the profile selects.
gpt-oss-20b is the pick here — our cheapest tool-calling chat model, at €0.03/€0.13 per 1M tokens. hermes-4-405b also works if you'd rather keep side tasks on Nous' own model. Set auxiliary.*.provider: "auto" in config.yaml to route side tasks to your main model instead.
The Hermes 4 family is text-only, so image description won't work on it. Point the vision task at a multimodal model — qwen3.5-9b is the cheapest one we run that also does tool calling:
auxiliary:
vision:
provider: "melious"
model: "qwen3.5-9b"Messaging gateway
The gateway resolves its provider through the same path the CLI does, so there's no Melious-specific wiring for it — the profile and key you already set are what it uses:
hermes gateway startYou still need the platform's own credentials. With none set, the gateway starts and logs No messaging platforms enabled, which is the expected state until you add a bot token (TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN, …) and an allowlist. Gateway sessions never prompt for secrets in-band, so put MELIOUS_API_KEY in ~/.hermes/.env before starting it rather than expecting a prompt.
Note that gateway start also installs a background service so the gateway survives a reboot — on Windows a Scheduled Task, or a Startup-folder login item when it can't get admin approval. hermes gateway stop halts the running process but leaves that service registered; use hermes gateway uninstall to remove it.
What's different
- Providers are plugins, not patches. Most tools in this section need a config block in a file they own. Hermes reads a directory, which means your Melious profile survives
hermes updateuntouched. - The reasoning toggle doesn't reach us. Hermes has a
/reasoningpanel, but for a plain OpenAI-compatible provider it sends nothing on the wire — so the panel has no effect on Melious models. Our hybrid models reason by default and return their trace inmessage.reasoning_content; you'll see the tokens billed underusage.reasoning_tokenseither way.reasoning_effortis accepted on most of our models but rejected by a few, which is why nothing sends it blindly. - Two tool-result image shapes. Hermes can attach an image directly to a tool result on models that accept it, and falls back to a text summary on models that don't. Ours split on this —
qwen3.5-9btakes it,mistral-small-3.2-24b-instructreturns a 400 for the same payload in a tool message while accepting it in a user message. Hermes notices the rejection and switches to summaries for that model for the rest of the session. - Extra response fields ride along.
environment_impactandbilling_costcome back on every Chat Completions response. Hermes ignores them; your usage dashboard aggregates them. - No Melious CLI support.
melious tools installcovers Claude Code, OpenCode, Mistral Vibe, and Pi. Hermes you wire by hand — the profile above is the integration. - No explicit cache control. Nothing marks a prefix as cacheable. Transparent prefix caching still happens and bills at the cheaper cache-read rate, reported as
usage.cached_tokens. See Models.
When it breaks
Unknown provider 'melious'— the profile didn't load. Check the path (~/.hermes/plugins/model-providers/melious/__init__.py, and$HERMES_HOMEif you've moved it) and that the file callsregister_providerat module level rather than inside a function.- Melious missing from
hermes doctor— the profile loaded butauth_typeisn't"api_key", orenv_varsis empty. Both are needed for the connectivity probe to be generated. - Embedding and image models in the model picker — expected from a generic client. Our
/v1/modelscovers every surface; filter on_meta.type == "chat". 404 Model not found— the model ID doesn't exist here. Hermes' own defaults are OpenRouter-style slugs, so an unsetmodelfails on the first turn.GET /v1/modelsfor the real list.400on a model that worked a moment ago — you're likely sending a parameter it rejects rather than hitting a real fault.reasoning_effortis the usual culprit;llama-3.3-70b-instructrefuses it.- Side tasks failing while chat works — the auxiliary model is wrong or retired. Image description against a Hermes 4 model fails this way, because that family is text-only.
- Context truncation warnings on your context file — Hermes' own
AGENTS.mdis larger than the default per-file cap. Raisecontext_file_max_charsor pick a model with a bigger window. 429mid-session — per-plan token caps, and an agent session carries a lot of context per turn. Rate limits covers which plan lifts which limit.
Errors and retry patterns: Errors.