Configuring Custom AI Providers in Hermes

How do you safely configure a custom AI Provider in Hermes? Based on a source-code review and community practice, this article lays out the complete configuration path and common pitfalls.

This article is compiled from community practice and a review of the underlying source code. Its goal is to objectively present the safe configuration path for custom AI Providers in Hermes, and to flag the differences and supplementary notes between user experience and what the code actually does.

The Configuration Flow as Practiced by Users

The steps below come from Herald’s hands-on experience and describe his distilled “safely add a third-party custom AI Provider” end-to-end flow.

Step 1: Prepare the Provider’s Basic Info

Before you start, confirm the following:

  • base url: the API endpoint address
  • api key: the access key
  • model name: the model name

Step 2: Add the Custom Provider Interactively

Enter the interactive wizard via the hermes model command:

  • Fill in the base url and model name
  • Leave the api key blank (this field is optional)
  • Fill in context size if you know it; leave it blank if you don’t

Step 3: Edit the Provider Name in the Config File

After the interactive add, the provider is named after the base url by default. You can manually edit ~/.hermes/config.yaml to change the name to something more readable. For example:

Step 4: Add the API Key via the Credential Pool

Run the following command to add a key for the custom provider:

Under the hood, this command writes the key into a separate credential pool store rather than into config.yaml. This avoids the risk of plaintext keys leaking from the config file.

Step 5: Restart the Gateway

Once the configuration and key are in place, restart the gateway for the changes to take effect.

Corrections & Additions from the Source Code

The following analysis is based on direct reading of Hermes’s underlying code, validating and supplementing the flow above.

1. Flexibility in Resolving the custom_providers Name

At the code level, model.provider supports two forms:

  • custom:kimi-plan: a slug with the custom: prefix that directly locates the matching entry in custom_providers
  • custom: the legacy form, which relies on base_url to match against custom_providers

The provider: custom:kimi-plan form in the user example is exactly what the underlying code expects. Resolution is case-insensitive and spaces are automatically replaced with -, so there’s a fair amount of tolerance in naming.

2. The Full Chain of Automatic Context-Size Detection

The user noted “leave it blank and let the program auto-detect” — the underlying code does fully support this, but the detection logic has a clear priority:

  1. A handwritten models.<model>.context_length in custom_providers
  2. The local cache ~/.hermes/context_length_cache.yaml
  3. models.dev / OpenRouter metadata cache (when the base_url belongs to a known provider, e.g. api.kimi.com)
  4. Direct probing of the /models endpoint (especially effective for local / ollama / vLLM / LM Studio)
  5. Descending context probing (starting from 128K and stepping down until the API stops returning context-overflow errors)
  6. Final fallback to 128K

So leaving it blank for auto-detection usually works for standard OpenAI-compatible endpoints; if the endpoint’s /models response isn’t in a standard format or omits context_length, it may fall back to the 128K default.

3. How hermes auth add Stores Keys

The underlying code path is agent/credential_pool.py and hermes_cli/auth_commands.py:

  • _normalize_provider("kimi-plan") detects a match against custom_providers names and normalizes it to custom:kimi-plan
  • A PooledCredential entry is generated and written to the credential pool’s persistent store
  • At runtime, _try_resolve_from_custom_pool() in runtime_provider.py reads the key from the pool first

This means:

  • The API key never lands in config.yaml
  • The mechanism natively supports multi-key rotation (fill_first, round_robin, random, and other strategies)

4. On the Scope of “Restart the Gateway”

You need to distinguish between run modes:

  • CLI mode: after editing config or adding auth, the next call picks it up — no restart needed
  • Gateway mode (running as a background service receiving Telegram / Discord / Slack messages): model.provider and model.default are loaded and cached at startup, so restarting the gateway is required for changes to be noticed

Flow Comparison Summary

User description Verified in code Notes
Interactive add via hermes model, no api key Correct _model_flow_custom supports this
Manually edit the custom_providers name Correct name is customizable; slug is custom:<name>
hermes auth add <provider> --api-key Correct Writes to the credential pool, bypassing config.yaml
Blank context_length auto-detection Partially correct Works for standard endpoints; non-standard endpoints may fall back to 128K
Restart gateway to apply Mostly correct CLI needs no restart; gateway does

Additional Advice

If you’ve already stored your key in the credential pool via hermes auth add, it’s worth checking whether config.yaml still contains an api_key field accidentally written during the interactive session, and cleaning it up so no plaintext key remains in the config file.

Notes on Configuring Custom Providers for Auxiliary Tasks

Hermes’s auxiliary system (which handles side tasks like image understanding, context compression, and web-page summarization) does not read API keys the same way the main conversation model does.

Key difference: when an auxiliary task uses a named custom provider, if that provider doesn’t explicitly set key_env, the underlying code does not fall back to OPENAI_API_KEY or OPENROUTER_API_KEY — it instead sends Bearer no-key-required, which makes the provider return 401 Unauthorized. Worse, some API gateways (e.g. SiliconFlow) may already have counted the input tokens and generated billing at the gateway ingress layer before the auth layer rejects the request.

So as long as your custom provider requires API-key authentication, you must explicitly set key_env in custom_providers, for example:

Then reference that provider name directly in auxiliary:

Multi-Model Configuration Advice

Don’t create multiple entries for the same endpoint in custom_providers. When Hermes resolves a named custom provider it only matches the first entry whose name matches in the list; later entries with the same name are ignored.

If you need to configure context lengths for multiple models of the same provider, use the models sub-dictionary:

The model field (sibling of models) isn’t required. If omitted, Hermes falls back to the main model configured in model.default, or ultimately to gpt-4o-mini.