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? -
Error 1: Missing anthropic Package -
Why Kimi Requires the anthropic SDK -
How One config.yaml Field Broke Everything -
Error 2: ZAI Balance Depleted and Kimi 404 -
Security Gap: API Keys Leaking into Logs -
Configuring Multiple Models and Switching at Runtime -
Checklist and Quick Reference -
One-Page Summary -
FAQ
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_secretstotrueon 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_urlinconfig.yamlto your key format —sk-kimi-*keys useapi.kimi.com/coding; legacy keys useapi.moonshot.ai/v1 -
[ ] Set fallback_model.modelto a real API model identifier, not an internal alias -
[ ] Enable secret redaction: set security.redact_secrets: true -
[ ] Confirm feishuis a top-level key inconfig.yaml, not nested undermodel_catalog
Ongoing Operations
-
[ ] Monitor ZAI and Kimi balances — HTTP 429 with code 1113means the account is out of funds -
[ ] Review ~/.hermes/sessions/periodically; configuresessions.auto_pruneto prevent unbounded disk usage -
[ ] Use /modelto 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.

