Back to guides
Setup·September 21, 2026·10 min read

Hermes Agent custom API: providers, transports and first-call checks

Two opposite things are called the Hermes custom API. This is the outbound half — and the transport field you have to write yourself.

Last reviewed on .

A Hermes Agent custom endpoint is configured outbound, as a named entry under providers: in ~/.hermes/config.yaml, where api is the base URL and transport is the wire protocol. That is a different thing from Hermes' own API server, which points the other way. Both are called “the Hermes custom API” in search results, and the official documentation pages for each rank for the same queries — so fix the direction first.

This page is about Hermes Agent, the open-source agent from Nous Research. A check of the GitHub API on September 21, 2026 returned archived: false, disabled: false, an MIT license and a push the same day; the newest published release is Hermes Agent v0.21.3, tagged v2026.9.14 on September 14, 2026, not a prerelease. The surfaces this page takes configuration from are that repository and hermes-agent.nousresearch.com. hermes-agent.org covers the same project from a domain outside nousresearch.com and loads Microsoft Clarity analytics (checked September 21, 2026); it is not one of the project's own surfaces, so do not take configuration from it. This is also not Hermes 3 or Hermes 4, the Nous open-weight model family, and not the JavaScript engine of the same name.

Two opposite things called the Hermes custom API

Outbound: custom model providerInbound: the API server
What it doesPoints Hermes at someone else's model endpointExposes Hermes itself as an OpenAI-compatible endpoint for a frontend such as Open WebUI or LobeChat
Where it is configuredproviders: in ~/.hermes/config.yaml, secrets in ~/.hermes/.envAPI_SERVER_ENABLED and API_SERVER_KEY in the environment
Address involvedYour provider's base URLListens on http://127.0.0.1:8642 by default, over API_SERVER_HOST / API_SERVER_PORT
Who holds the keyHermes holds your provider keyThe caller holds a bearer key you set; it is required on every deployment, including the loopback bind
Blast radiusWhich model answersFull access to the toolset, including terminal commands

Both rows are quoted from Hermes' own pages, read September 21, 2026: the provider reference and the API server page. One naming wrinkle worth checking in your own install: the API server page documents hermes gateway as the command that runs it, while the CLI reference describes hermes gateway as the messaging-service manager with run, start, stop and status subcommands. Run hermes gateway --help rather than guessing. Everything below is the outbound half.

The minimum outbound configuration

Shape taken from Hermes' provider reference, read September 21, 2026
# ~/.hermes/config.yaml
providers:
  kunavo:
    api: https://api.kunavo.com/v1   # aliases accepted: base_url, url
    key_env: KUNAVO_API_KEY          # or inline api_key:, or key_cmd:
    transport: chat_completions      # set it by hand; see the transport section
    models:
      claude-sonnet-5:
        prompt_caching: true

model:
  default: claude-sonnet-5
  provider: custom:kunavo
~/.hermes/.env
KUNAVO_API_KEY=your-key

Field by field, from the provider reference: the config key is providers.<name>, the base URL field is api (with base_url and url accepted as aliases), the credential is key_env, an inline api_key or a key_cmd, and the protocol is transport. The same entry also accepts name, default_model, models, context_length, discover_models, extra_body, extra_headers, session_affinity_header, ssl_ca_cert / ssl_verify, catalog_provider and enabled: false. Select the entry with model.provider: custom:kunavo, or mid-session with /model custom:kunavo:<model-id>.

Two commands are not interchangeable. hermes model, run outside a chat session, is the full provider setup wizard and the only thing that can add a provider or take a key. /model inside a session only switches between what already exists. For enterprise endpoints issuing short-lived tokens, key_cmd names a command that prints a token on stdout — bare, or as JSON with an access_token field — which Hermes runs and caches until shortly before expiry, and which beats a static api_key or key_env on the same entry.

Pick the transport by hand rather than leaving the field blank

The provider reference lists three accepted values for transport on a custom entry. It also says the hermes model Custom Endpoint wizard now prompts for the protocol explicitly and persists the answer to config.yaml, and that URL-based auto-detection “still happens as a fallback when the field is left blank”. The one detection rule the docs spell out is an /anthropic path mapping to anthropic_messages, which a Kunavo base URL does not match; the rest of the heuristic is not enumerated on any page read here, which is the reason to write the field rather than infer what it would do. Kunavo serves /v1/chat/completions, /v1/messages and /v1/responses, so each transport has a matching route on paper.

transportBase URL to write in apiRoute it should reachConfidence
chat_completionshttps://api.kunavo.com/v1/v1/chat/completions, Hermes appends the pathDocumented on both sides. The value must be written by hand
anthropic_messagesTry https://api.kunavo.com or https://api.kunavo.com/v1/v1/messagesUnverified. See the note below before you commit to one
codex_responseshttps://api.kunavo.com/v1/v1/responsesRoute exists. Hermes renames five of its own tools to hermes_<name> on Perplexity and OpenCode-style Responses endpoints; whether that rewrite applies to an arbitrary Responses endpoint is not stated

The Anthropic row deserves the caveat rather than a confident answer. Hermes' Azure Foundry guide states that /v1 is stripped from the base URL because the Anthropic SDK appends /v1/messages to every request — but that sentence sits under an Azure heading, and the provider reference's own example (api: https://proxy.example.com/anthropic) never says what suffix Hermes appends for a generic proxy. So both candidates above are plausible and one of them may produce a double-/v1 404. Check the request path your first call actually records; the base-URL doc covers the origin-versus-/v1 trap behind most 404s on this wire. Authentication is the lesser worry: Kunavo's Messages route accepts both Authorization: Bearer and x-api-key, so whichever header the Anthropic SDK sends for a generic proxy should be accepted — but Hermes does not document that choice, so “should” is the honest word.

One open question this page will not answer either way. Hermes documents a silent upgrade of GPT-5.x-family model names to codex_responses even when config.yaml still says chat_completions — but that sentence appears under provider: azure-foundry while being phrased as a model-name detection. Whether a GPT slug on provider: custom triggers the same move is not documented. If you pick a GPT-class model, record which route the first call went to.

What a custom endpoint does not get for free, per transport

None of these are plan gates. Hermes Agent is “free and open source under the MIT license” per the project's own homepage FAQ, and the providers: dict is documented as ordinary configuration rather than a tier feature. They are capability gates, and they differ by wire.

Capabilitychat_completionsanthropic_messagescodex_responses
Prompt cachingOpt in per model: providers.<name>.models.<id>.prompt_caching: true. Hermes matches the declaration to the exact route and runtime model id “without rewriting the alias or inferring support from its provider name, host, or model family”, and the marker layout follows the transport — the OpenAI-compatible envelope on the chat wire, the native inner-block layout on anthropic_messagesNo marker layout is documented for this transport
extra_headersApplies. The doc says extra_headers reaches OpenAI-compatible routes and anthropic_messages routes alike — main client, /model switches, rebuilds and auxiliary clients — and names bedrock_converse as the one mode that does not use itNot named either way; treat as untested
Reasoning effortSent as a top-level reasoning_effort field. It “reaches a custom endpoint unchanged on both the chat_completions and the codex_responses transport — up to max”, with only the Hermes-internal ultra clamped to max; the Anthropic wire is not stated. The nested reasoning object is reserved for endpoints known to accept it. An endpoint that rejects the level answers HTTP 400 rather than being silently downgraded
Output capNone automatic. “Custom OpenAI-compatible endpoints receive no automatic catalog-sized output cap. Their server defaults apply.”The quoted sentence covers OpenAI-compatible endpoints; the doc does not extend it to these wires. Either way Hermes no longer reads model.max_tokens, HERMES_MAX_TOKENS or model_overrides.*.*.max_output_tokens, so there is no Hermes-side knob to raise a cap
Context windowResolved through a nine-step chain — config override, per-model entry, cache, the endpoint's /models, Anthropic's, OpenRouter, Nous Portal, models.dev — ending at a 128K default. Set context_length when detection lands wrong

Two escape hatches for a gateway specifically. catalog_provider accepts a Hermes provider id or a models.dev id and makes the entry's models inherit that catalogue's metadata — lookups only, requests still go to your api URL with your key. And discover_models: false skips the /models probe entirely and uses only the models you listed on the entry, which is the fix when discovery is noisy or slow. Whether Kunavo's /v1/models response satisfies Hermes' probe has not been tested here; if it does not, context detection falls through to that 128K default. The cost reasoning behind these settings — auxiliary slots, delegation workers and cache continuity — is on Hermes Agent pricing rather than repeated here.

A verification ladder to run before you move real work

These are steps for you to run with the observation to expect, not results Kunavo obtained. No Hermes run against Kunavo has been performed, there is no Kunavo setup guide for Hermes, and nothing on this page should be read as a tested integration. Keep your working route available throughout.

  1. Add the provider, then diagnose. hermes model adds it; hermes doctor is documented as diagnosing config and dependency issues, and the CLI reference records two custom-endpoint config checks it runs — a custom_providers key that is not a YAML list, and a legacy list entry with no matching providers: entry. Both are warn-only and --fix does not rewrite them.
  2. Confirm the key is loaded before spending anything. hermes dump prints a copy-pasteable setup summary — version, provider, model and whether an API key is present. Expect your model id and a present key. hermes prompt-size runs offline and reports a byte breakdown of the system prompt and tool schemas, which is the fixed part every turn carries before any conversation content.
  3. One non-streaming text turn. Expect a reply, and expect the request to have gone to the path you intended. A custom endpoint that “works” but returns garbage is a row in Hermes' quickstart troubleshooting table, which names a wrong base URL, a wrong model name or an endpoint that is not actually OpenAI-compatible, and tells you to verify the endpoint in a separate client first.
  4. One streaming turn. Expect incremental output rather than one block at the end. Whether a given endpoint's stream framing satisfies Hermes' progress parsing is not something this page tested.
  5. One tool round. Expect the tool to execute. If the call is printed as text instead, that is the serving side's tool-calling support, not the transport.
  6. Read the meter. /usage is the in-session token, cost and context panel. Reconcile it against the charge your provider account actually recorded — an agent's own arithmetic over reported tokens is an estimate, not a ledger. See the usage doc.
Symptom on the first callMost likely causeWhere to look
404 immediatelyBase-URL suffix — a doubled /v1 on the Anthropic wire, or a missing one elsewhereThe recorded request path, then base URL
401 or 403The key never loaded: wrong key_env name, or the value is in the wrong filehermes dump reports key presence
400 on every turntransport does not match the route the endpoint servesSet transport explicitly rather than leaving detection to choose
400 naming an unknown fieldA reasoning_effort level the endpoint rejects. Hermes does not silently downgrade itLower the effort and retry
Tool calls printed as textTool calling is not enabled on the serving sideHermes names per-server fixes, e.g. --jinja on llama.cpp, --enable-auto-tool-choice --tool-call-parser hermes on vLLM
Context truncated sooner than expectedDetection fell through to the 128K fallbackSet context_length on the entry
Replies fine, bill higher than expectedNo prompt_caching declaration, so every turn re-reads at full input ratePrompt caching and the caching doc

What the ladder costs, and what a mid-session switch costs

Assume the six steps above send 26,000 input tokens and receive 1,150 output tokens in total — a fixed system prompt and tool schema on each of three calls, plus a tool result re-sent once. That assumption is for illustration; hermes prompt-size reports your own fixed prompt as a byte breakdown, which is closer to the truth than a number this page can guess. Rates are live Kunavo catalog prices per million tokens.

ModelInput / output per 1MCatalog estimate for the whole ladder
Claude Sonnet 5$2.00 / $10.00$0.064
Claude Haiku 4.5$0.40 / $2.00$0.013

This is illustrative token arithmetic at catalog rates, not a measured Hermes task and not a bill ceiling. It excludes cache writes, external tools and tax. The point of the number is its smallness: verifying a route costs far less than discovering a misconfiguration after a week of scheduled work.

The second number is the one the /model command hides. Prompt caches are keyed to the model serving the request, so any mid-conversation model change makes the next message re-read the whole conversation at full input price instead of the cached rate, which Hermes describes as roughly 75 to 90 percent cheaper. On a 120,000-token conversation with Claude Sonnet 5, the difference between $2.00 per million and the $0.20 cache-read rate is about $0.216 for that one turn — trivial once, and not trivial as a habit. Kunavo's catalog amount is a billing floor rather than a cap: when the upstream reports its charge, the bill is the greater of catalog cost and upstream cost times the applicable markup. The minimum is a $10 prepaid top-up with no subscription. See billing.

Backing the configuration out again

Hermes documents an undo path, which is the reason a trial is low risk. enabled: false on the entry hides it without deleting it. Point-in-time copies of config.yaml are written to backups/config/config.yaml.<reason>.<timestamp> before hermes setup or hermes migrate rewrite it and whenever it parses, with identical repeats skipped and only the newest five per reason kept; if the file later fails to parse, Hermes serves the newest good copy instead of built-in defaults. The configuration reference also annotates model.base_url as “cleared on provider switch”, so switching back to a built-in provider is documented as dropping the stale base URL rather than leaving it in the file — check the written value afterwards rather than assuming it.

Three traps come from older tutorials. The legacy top-level custom_providers: list still works and hermes update auto-migrates it into the providers: dict, where legacy model becomes default_model and legacy api_mode becomes transport. LLM_MODEL in .env has been removed outright — config.yaml is the single source of truth. And OPENAI_BASE_URL is documented two ways by two current official pages: the provider reference says it is honored only for the openai-api provider, while the environment-variables reference lists it as the base URL for a custom endpoint. That disagreement is unresolved, so configure the endpoint in config.yaml and do not rely on that environment variable as the route.

If you are choosing a provider rather than wiring one, OpenAI-compatible API covers what the compatible surface does and does not include, and Hermes vs OpenClaw compares the two agents. When you are ready to test this route with a funded key, create a Kunavo account.

FAQ

What is a Hermes Agent custom endpoint?

A custom endpoint is an outbound model provider: a named entry under `providers:` in ~/.hermes/config.yaml that points Hermes Agent at an OpenAI-, Anthropic- or Responses-compatible URL of your own. The entry takes `api` for the base URL, one of `key_env` / `api_key` / `key_cmd` for the credential, and `transport` for the wire protocol. You select it with `model.provider: custom:<name>`, or mid-session with `/model custom:<name>:<model-id>`. Read from Hermes' provider documentation on September 21, 2026.

Is the Hermes custom API the same as the Hermes API server?

No, they point in opposite directions. The API server is inbound: it exposes Hermes Agent itself as an OpenAI-compatible HTTP endpoint on 127.0.0.1:8642 so a frontend such as Open WebUI or LobeChat can drive it, and its documentation warns that it gives full access to the toolset including terminal commands, with API_SERVER_KEY required even on the loopback bind. A custom provider is outbound: it decides which model API Hermes calls. Configuring one has no effect on the other.

How do I add a custom provider in Hermes Agent?

Run `hermes model` from your terminal, outside any chat session — Hermes documents it as the full provider setup wizard, the only place that adds providers, runs OAuth flows and takes API keys. The `/model` command typed inside a session can only switch between providers and models already set up; it cannot add one. You can also write the `providers:` block into ~/.hermes/config.yaml directly and put the key in ~/.hermes/.env.

Which transport should I set for an OpenAI-compatible gateway?

`chat_completions`. Hermes' provider reference lists the three accepted values as chat_completions, anthropic_messages and codex_responses, and the setup wizard now asks for the protocol explicitly rather than relying on URL auto-detection, which is documented as a fallback. Note one inconsistency in the official docs: the prompt-caching example on the configuring-models page writes `transport: openai_chat` instead. chat_completions is the form used across the provider reference and the developer guide, so prefer it, but openai_chat may be an accepted alias rather than an error.

Why does my Hermes custom endpoint fail on tool calls?

Start by separating the wire from the model. A 400 on every tool turn usually means the transport does not match the route the endpoint serves, so set `transport` by hand instead of leaving the field blank. Tool calls that arrive as plain text rather than executing are the server's tool-calling support, not Hermes': its provider reference names per-server fixes such as --jinja for llama.cpp and --enable-auto-tool-choice --tool-call-parser hermes for vLLM. Replies that arrive but are garbage match the quickstart's troubleshooting row for a wrong base URL, a wrong model name, or an endpoint that is not actually OpenAI-compatible, whose fix is to verify the endpoint in a separate client first.

Does using a custom endpoint in Hermes Agent cost extra?

Not from Hermes itself. Its homepage FAQ says Hermes Agent is free and open source under the MIT license, and that model providers and optional hosted services have their own pricing — so the cost sits on your provider's side. On Kunavo there is no subscription and the minimum is a $10 prepaid top-up, which is the cash needed to fund a key rather than a task fee. What a custom endpoint does forfeit by default is prompt caching, which must be declared per model — that is the largest cost lever in a long session.

Hermes Agent documentation — the provider reference, the API server page, the model-configuration page, the configuration page, the CLI reference, the slash-command reference, the quickstart and the project homepage — read September 21, 2026. Repository state and the latest release were checked against the GitHub API the same day. Kunavo's three API routes were confirmed in its own source. Every dollar figure is illustrative token arithmetic over live catalog rates, not a measured task cost. Hermes configuration is reported from source documents; no Hermes run against Kunavo has been performed.