hermes - ✅(Solved) Fix [Bug] normalize_model_name rewrites custom provider model IDs, breaking models with dots (e.g. z-ai/glm-5.1 via zenmux) [1 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

The root cause is _anthropic_preserve_dots(), which only returns True for a hardcoded allowlist of built-in providers (alibaba, minimax, opencode-go, opencode-zen, zai, bedrock) or specific URL substrings. A custom provider like zenmux is not in that list, so its model name gets mangled even though the user explicitly configured the exact ID the upstream expects.

Fix Action

Fix / Workaround

  • #7475 — Same underlying problem with glm-4.7 via the built-in zai provider (fixed by adding zai to the _anthropic_preserve_dots allowlist). The fix there was provider-specific; the general problem for custom providers remains.

PR fix notes

PR #13068: fix(agent): preserve dots in custom provider model IDs (#13061)

Description (problem / solution / changelog)

Summary

  • Fixes #13061 — normalize_model_name() rewrote dots to hyphens for custom providers, breaking upstreams whose model IDs legitimately contain dots (e.g. zenmux's z-ai/glm-5.1z-ai/glm-5-1 → HTTP 404).
  • _anthropic_preserve_dots() now returns True whenever the provider is custom or custom:<name>. The user has already configured the exact model ID the upstream expects, and Hermes cannot second-guess an arbitrary third-party API.
  • Implements Option A from the issue (preferred).

Test plan

  • New TestCustomProviderPreserveDots in tests/agent/test_minimax_provider.py covers bare custom, named custom:zenmux, and unknown URLs.
  • Updated test_non_bedrock_aws_url_does_not_preserve_dots to use an empty provider so it continues to test URL-heuristic scoping in isolation.
  • uv run python -m pytest tests/agent/test_anthropic_adapter.py tests/agent/test_bedrock_integration.py tests/agent/test_minimax_provider.py tests/test_ctx_halving_fix.py — 232 passed.

🤖 Generated with Claude Code

Changed files

  • run_agent.py (modified, +8/-1)
  • tests/agent/test_bedrock_integration.py (modified, +8/-2)
  • tests/agent/test_minimax_provider.py (modified, +34/-0)

Code Example

custom_providers:
     - name: zenmux
       base_url: https://zenmux.ai/api/anthropic
       api_key: ""
       api_mode: anthropic_messages
       key_env: ZENMUX_API_KEY
   model:
     default: z-ai/glm-5.1
     provider: zenmux

---

HTTP 404: Requested model is not valid
RAW_BUFFERClick to expand / collapse

Bug Description

When using a custom provider with an Anthropic-compatible endpoint, Hermes still applies normalize_model_name(), which blindly converts dots to dashes in the model identifier. This breaks providers whose model IDs legitimately contain dots.

For example, with a custom provider configured for zenmux (https://zenmux.ai/api/anthropic) and model z-ai/glm-5.1:

  • User-configured model ID: z-ai/glm-5.1
  • After normalize_model_name(): z-ai/glm-5-1
  • zenmux API response: HTTP 404 — Requested model is not valid

The root cause is _anthropic_preserve_dots(), which only returns True for a hardcoded allowlist of built-in providers (alibaba, minimax, opencode-go, opencode-zen, zai, bedrock) or specific URL substrings. A custom provider like zenmux is not in that list, so its model name gets mangled even though the user explicitly configured the exact ID the upstream expects.

Steps to Reproduce

  1. Add a custom provider in ~/.hermes/config.yaml:
    custom_providers:
      - name: zenmux
        base_url: https://zenmux.ai/api/anthropic
        api_key: ""
        api_mode: anthropic_messages
        key_env: ZENMUX_API_KEY
    model:
      default: z-ai/glm-5.1
      provider: zenmux
  2. Start a chat (hermes).
  3. Observe fallback to another provider with:
    HTTP 404: Requested model is not valid
  4. Verify via direct SDK call that z-ai/glm-5.1 works, but z-ai/glm-5-1 returns the same 404.

Expected Behavior

For custom providers, Hermes should respect the user-configured model ID exactly as written. The user has already told Hermes what string the upstream expects; Hermes should not second-guess it with normalize_model_name().

Actual Behavior

normalize_model_name() converts z-ai/glm-5.1z-ai/glm-5-1, causing a 404 from the upstream.

Related Issues

  • #7475 — Same underlying problem with glm-4.7 via the built-in zai provider (fixed by adding zai to the _anthropic_preserve_dots allowlist). The fix there was provider-specific; the general problem for custom providers remains.

Proposed Fix

Option A (preferred): Skip normalize_model_name() entirely when the provider is a custom provider, or at least default preserve_dots=True for custom providers and let the user opt into normalization if needed.

Option B: Extend _anthropic_preserve_dots() to detect custom providers and inspect the configured model name. If the original model string contains dots, preserve them.

Affected Component

CLI / Agent (agent/anthropic_adapter.py, run_agent.py)

Hermes Version

v0.8.0+

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

extent analysis

TL;DR

To fix the issue, modify the agent/anthropic_adapter.py file to skip normalize_model_name() for custom providers or extend _anthropic_preserve_dots() to handle custom providers.

Guidance

  • Identify the agent/anthropic_adapter.py file and locate the normalize_model_name() function to understand its current implementation.
  • Consider implementing Option A by adding a conditional check to skip normalize_model_name() when the provider is custom, or defaulting preserve_dots=True for custom providers.
  • Alternatively, explore Option B by modifying _anthropic_preserve_dots() to detect custom providers and preserve dots in the model name if present.
  • Verify the fix by testing with a custom provider and a model ID containing dots, ensuring that the correct ID is sent to the upstream API.

Example

# Example of skipping normalize_model_name() for custom providers
if provider_type == 'custom':
    # Skip normalization for custom providers
    model_id = user_configured_model_id
else:
    model_id = normalize_model_name(user_configured_model_id)

Notes

The proposed fix requires modifying the Hermes codebase, specifically the agent/anthropic_adapter.py file. The choice between Option A and Option B depends on the desired behavior for custom providers.

Recommendation

Apply workaround by modifying the agent/anthropic_adapter.py file to skip normalize_model_name() for custom providers, as this approach is more straightforward and respects the user-configured model ID.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix [Bug] normalize_model_name rewrites custom provider model IDs, breaking models with dots (e.g. z-ai/glm-5.1 via zenmux) [1 pull requests]