Hermes Agent Setup Guide: Fixing Startup Errors and Switching Between Multiple LLM Providers

What This Guide Covers

If you’re running Hermes Agent with Chinese LLM providers like Kimi, GLM, or ZAI and hitting a wall of errors on startup, this guide is for you. What follows is a complete, real-world debugging walkthrough — from an ImportError on launch to HTTP 404 on the fallback model — with every fix explained and every command tested.

By the end, you’ll understand how Hermes manages provider protocols, how to configure multiple models with automatic failover, and a few security defaults you should change before going to production.


Table of Contents


What Is Hermes Agent?

Hermes Agent is a multi-platform AI gateway that connects large language models to messaging platforms and cron-based automation. In a single configuration file, you can wire a model like GLM or Kimi into Feishu, Slack, Discord, or Telegram — and schedule recurring AI tasks through a built-in job scheduler.

For developers outside the OpenAI ecosystem, the appeal is straightforward: Hermes natively supports Chinese providers like Kimi (Moonshot), GLM (ZAI), and DeepSeek without requiring any proxy or workaround. But that multi-protocol compatibility introduces some non-obvious traps, especially around how provider adapters are selected and what packages they depend on.


Error 1: Missing anthropic Package

The error surfaces in two places simultaneously: the Feishu session agent and the cron scheduler. Both fail with the same message:

ImportError: The 'anthropic' package is required for the Anthropic provider.
Install it with: pip install 'anthropic>=0.39.0'

The immediate reaction for most people is confusion — “I’m using Kimi, not Anthropic. Why does this package matter?” That’s exactly the right question, and chasing it down leads to the real fix.

Fix

On Ubuntu or Debian systems, the standard pip install will be blocked by the system Python environment manager:

error: externally-managed-environment

Add --break-system-packages to override it:

pip install 'anthropic>=0.39.0' --break-system-packages

Verify the installation:

python3 -c "import anthropic; print(anthropic.__version__)"

Any version 0.39.0 or higher confirms you’re good.


Why Kimi Requires the anthropic SDK

This isn’t a misconfiguration. It’s an intentional architectural decision in Hermes.

Kimi’s api.kimi.com/coding endpoint implements the Anthropic Messages API protocol. Hermes uses the anthropic SDK as its transport layer to call that endpoint — it simply swaps in Kimi’s base URL instead of Anthropic’s. The comment in Hermes source code makes this explicit:

# Third-party providers (MiniMax, Kimi, GLM, LiteLLM proxies) that accept the
# Anthropic protocol must never trip OAuth code paths — doing so injects
# Claude-Code identity headers and system prompts that cause 401/403 on their endpoints.

The Kimi plugin documentation inside Hermes is equally clear:

# sk-kimi-* keys → api.kimi.com/coding  (Anthropic Messages API)
# legacy keys    → api.moonshot.ai/v1   (OpenAI Chat Completions)

The key format you’re using determines which endpoint and which protocol Hermes selects:

API Key Format Endpoint Protocol Requires anthropic package
Starts with sk-kimi- api.kimi.com/coding Anthropic Messages API Yes
Legacy format api.moonshot.ai/v1 OpenAI Chat Completions No

Installing the anthropic package in this context is purely a transport layer dependency. Your Kimi API key, account, and billing are entirely unaffected. You are not creating or using an Anthropic account.

A note on protocol reuse: This pattern — one provider implementing another provider’s API spec — is increasingly common in the LLM infrastructure space. It lowers the integration cost for new entrants and lets existing tooling work without modification. The practical consequence for developers is that the package name and the actual service name don’t always match. When you see an unexpected import error, trace the call stack before assuming the obvious.


How One config.yaml Field Broke Everything

A single incorrect base_url entry caused the entire adapter selection logic to go wrong. The original configuration looked like this:

model:
  default: kimi-for-coding
  provider: kimi-coding
  base_url: https://api.kimi.com/coding

That base_url points to the Anthropic-protocol endpoint. Hermes detected it and set api_mode to anthropic_messages, which in turn invoked anthropic_adapter to build the client — triggering the ImportError.

The Kimi plugin’s default base_url is https://api.moonshot.ai/v1, the OpenAI-compatible path. Had the user not overridden it, Hermes would have defaulted to chat_completions mode and the anthropic package wouldn’t have been needed at all.

How Hermes Determines api_mode

Hermes evaluates the provider and base URL in sequence to assign the correct API mode:

provider == "anthropic"
  → api_mode = anthropic_messages

base_url ends with "/anthropic"
  → api_mode = anthropic_messages

base_url contains "bedrock-runtime"
  → api_mode = bedrock_converse

everything else
  → api_mode = chat_completions (OpenAI-compatible)

A manually overridden base_url in config.yaml takes precedence over the plugin’s default — and that override can silently shift the entire mode selection.

A Structural Problem in the Same Config File

There’s a second issue worth flagging: the feishu connection block was incorrectly nested inside model_catalog:

model_catalog:
  enabled: true
  providers: {}
  feishu:              # incorrect — feishu is nested under model_catalog
    reconnect_interval: 5
    heartbeat_interval: 15
    max_reconnect_attempts: 10

The feishu block should be a top-level key:

model_catalog:
  enabled: true
  providers: {}

feishu:
  reconnect_interval: 5
  heartbeat_interval: 15
  max_reconnect_attempts: 10

Incorrect indentation here could cause Feishu connection parameters to be silently ignored.


Error 2: ZAI Balance Depleted and Kimi 404

Once the anthropic package issue was resolved, a second layer of errors appeared.

ZAI (GLM-5.1): Quota Exhausted

HTTP 429: Insufficient balance or no resource package. Please recharge.
{'code': '1113', 'message': 'Insufficient balance or no resource package. Please recharge.'}

The fix here is straightforward: recharge your account at z.ai. What’s worth noting is the failure sequence — the first attempt returned error code 1305 (service overloaded), and only after a 3-second retry did code 1113 (insufficient balance) appear. Hermes retries up to the api_max_retries limit before triggering failover to the fallback model.

Kimi (fallback): HTTP 404

HTTP 404: The requested resource was not found
{'message': 'The requested resource was not found', 'type': 'resource_not_found_error'}

The fallback configuration was:

fallback_model:
  provider: kimi-coding
  model: kimi-for-coding

kimi-for-coding is an internal alias used within Hermes for provider routing. It is not a model identifier that the Kimi API itself recognizes. The API returns 404 because no model by that name exists on the endpoint.

The fix is to use an actual model name accepted by the Kimi API:

fallback_model:
  provider: kimi-coding
  model: kimi-k2-turbo-preview

To list all model names available under your configured providers:

hermes models          # models available with your current API keys
hermes models --all    # all models including unconfigured providers

Real-World Scenario: Silent Failover Between ZAI and Kimi

With the corrected configuration below, Hermes handles provider failure automatically:

model:
  default: glm-5.1
  provider: zai
  base_url: https://api.z.ai/api/paas/v4

fallback_model:
  provider: kimi-coding
  model: kimi-k2-turbo-preview

agent:
  api_max_retries: 2
  api_retry_delay: 5

If GLM-5.1 fails twice within 5-second intervals, Hermes silently switches to Kimi K2. Users on Feishu or other connected platforms experience no interruption.


Security Gap: API Keys Leaking into Logs

Every Hermes startup prints this warning — and most people scroll past it:

⚠ Secret redaction is DISABLED (HERMES_REDACT_SECRETS=false).
API keys and tokens may appear verbatim in chat output, session JSONs, and logs.

With redaction disabled, API keys can appear in:

  • Session JSON files stored in ~/.hermes/sessions/
  • Terminal output
  • Chat history on connected messaging platforms (Feishu, Slack, etc.)

Fix it with one command:

sed -i 's/redact_secrets: false/redact_secrets: true/' ~/.hermes/config.yaml

Verify the change:

grep redact_secrets ~/.hermes/config.yaml
# expected output:   redact_secrets: true

Restart Hermes to apply.

Also worth noting: the FEISHU_HOME_CHANNEL value (a channel ID) is written directly at the bottom of config.yaml. Channel IDs and similar identifiers are better managed through environment variables or a separate .env file that you exclude from version control.

Lesson learned the hard way: Disabling secret redaction during development is reasonable — it simplifies debugging. The mistake is treating “disabled for debugging” as a permanent state. If your Hermes instance is connected to a shared Feishu group, session logs are effectively shared with everyone in that group. Flip redact_secrets to true on first setup, and only disable it temporarily when you specifically need to inspect a raw API response.


Configuring Multiple Models and Switching at Runtime

Hermes supports multiple providers in a single deployment and allows on-the-fly model switching without restarting.

credentials.yaml: Centralized Key Management

All provider API keys go into a single credentials file:

zai:
  api_key: sk-xxx

kimi-coding:
  api_key: sk-kimi-xxx

deepseek:
  api_key: sk-xxx

openai:
  api_key: sk-xxx

config.yaml: Primary and Fallback Model

model:
  default: glm-5.1
  provider: zai
  base_url: https://api.z.ai/api/paas/v4

fallback_model:
  provider: kimi-coding
  model: kimi-k2-turbo-preview

Switching Models at Runtime

Inside any Hermes session, type:

/model kimi-k2-turbo-preview
/model glm-5.1
/model deepseek-chat

To disambiguate models with the same name across providers, prefix with the provider name:

/model kimi-coding/kimi-k2-turbo-preview
/model zai/glm-5.1

No restart required. The switch takes effect immediately.

Managing Multiple Keys for the Same Provider

If you have multiple API keys for the same provider — for example, multiple ZAI accounts to pool quota — configure a credential pool strategy:

credential_pool_strategies:
  zai: fill_first   # exhaust the first key before moving to the next

fill_first prioritizes the first available key and only moves on when it’s exhausted or rate-limited. This is useful for maximizing quota usage under a single provider before triggering cross-provider failover.


Checklist and Quick Reference

Initial Setup

  • [ ] Install the anthropic package if using a sk-kimi-* key: pip install 'anthropic>=0.39.0' --break-system-packages
  • [ ] Add all provider API keys to credentials.yaml
  • [ ] Match base_url in config.yaml to your key format — sk-kimi-* keys use api.kimi.com/coding; legacy keys use api.moonshot.ai/v1
  • [ ] Set fallback_model.model to a real API model identifier, not an internal alias
  • [ ] Enable secret redaction: set security.redact_secrets: true
  • [ ] Confirm feishu is a top-level key in config.yaml, not nested under model_catalog

Ongoing Operations

  • [ ] Monitor ZAI and Kimi balances — HTTP 429 with code 1113 means the account is out of funds
  • [ ] Review ~/.hermes/sessions/ periodically; configure sessions.auto_prune to prevent unbounded disk usage
  • [ ] Use /model to test different models interactively without modifying configuration files

One-Page Summary

Problem Root Cause Fix
ImportError: anthropic sk-kimi-* keys use Anthropic Messages protocol; SDK required as transport layer pip install 'anthropic>=0.39.0' --break-system-packages
ZAI HTTP 429 code 1113 Account balance depleted Recharge at z.ai
Kimi HTTP 404 model field set to internal alias, not a real API model name Change to kimi-k2-turbo-preview or equivalent
API keys visible in logs security.redact_secrets: false Set to true, restart Hermes
Feishu connection params ignored feishu block nested incorrectly under model_catalog Move feishu to top-level in config.yaml
Switch models without restarting Use /model <model-name> in any active session

FAQ

Why does Kimi require the anthropic package if I’m not using Anthropic?
Kimi’s sk-kimi-* API keys use the Anthropic Messages API protocol on their api.kimi.com/coding endpoint. Hermes uses the anthropic SDK purely as an HTTP transport layer to speak that protocol. Your Kimi account and billing are completely separate from Anthropic.

Will installing the anthropic package create an Anthropic account or charge me anything?
No. The anthropic package is a client library. It has no account creation flow, no telemetry, and no billing. Charges come from whichever API key is used — in this case, your Kimi key.

Why does pip say my environment is externally managed?
Ubuntu and Debian protect the system Python installation from direct pip modifications. Adding --break-system-packages bypasses this guard. Since Hermes itself was installed the same way, the flag is safe to use here.

What’s the difference between kimi-for-coding and kimi-k2-turbo-preview?
kimi-for-coding is an internal routing alias that Hermes uses to identify the provider profile. It is not a model name that the Kimi API recognizes, which is why the API returns 404. kimi-k2-turbo-preview is the actual model identifier the API expects.

Does fallback switching happen automatically?
Yes. When the primary model exhausts its retry attempts (configured via api_max_retries), Hermes automatically routes the request to the model defined in fallback_model. No manual intervention is needed.

What exactly gets exposed when redact_secrets is disabled?
API keys, bearer tokens, and similar secrets can appear verbatim in terminal output, session JSON files under ~/.hermes/sessions/, and chat history on connected platforms like Feishu or Slack.

Can I switch models mid-conversation without losing context?
Yes. The /model command switches the model for subsequent requests in the same session. Conversation history already in context is preserved.

How do I manage multiple API keys for the same provider?
List them in credentials.yaml under the same provider key, and configure a credential_pool_strategies entry. The fill_first strategy uses keys sequentially, exhausting one before moving to the next.