ZAI and Kimi provider endpoint routing fixes

NousResearch/hermes-agent · cluster 966 · agent

Data as of

12 open items. Fix merged in #9907. Check it covers your case.

The short answer

4open issues
8open PRs
31items grouped
Known?
Yes. 31 related items grouped here, 8 issues already closed.
Fix event
A fix was merged to main in PR #9907. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this partially resolved, deciding PR #9907. That is separate from the fix event.
Still open
4 issues and 8 PRs.

These issues and PRs address incorrect endpoint selection, ignored base URL configuration, and wrong billing paths for the ZAI/GLM and Kimi/Kimi-Coding providers across authentication, credential pools, and vision auxiliary clients. A recurring theme is hardcoded or incorrectly ordered endpoint probing causing users to be charged against metered quotas instead of subscription/coding-plan quotas.

Open issues4

  • Issue#5908kimi-coding credential pool base_url not re-resolved from key prefix on load
  • Issue#18302[Bug]: ZAI/GLM provider base_url causes 429/404 errors — config ignored by 5 code paths
  • Issue#42536[bug] Z.AI/GLM provider endpoint probe order causes Coding Plan users to be charged against wallet balance instead of subscription quota
  • Issue#55112[Bug]: hardcoded zai vision base_urls (paas/v4) bypass the coding-plan endpoint → silent metered billing

Open PRs8

  • PR#13993fix(providers): add moonshotai provider, disambiguate from kimi-for-coding
  • PR#18694fix(auth): re-resolve Kimi pool base URLs
  • PR#37816Respect configured ZAI base URL
  • PR#42547fix(zai): probe Coding Plan endpoints before generic to prevent silent wallet drain
  • PR#55116fix(auxiliary): prepend zai coding-plan vision endpoint before metered paas/v4 (fixes #55112)
  • PR#55156fix(auxiliary): try zai coding-plan vision endpoint before metered fallbacks (#55112)
  • PR#83537fix(auth): re-resolve stale kimi pool base_url on load (#5908)
  • PR#114111fix(auth): route Kimi Code credentials by key

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #9907 feat(zai): add GLM-5V-Turbo support for coding plan

    merged to main

    files: agent/auxiliary_client.py, hermes_cli/auth.py, hermes_cli/models.py

    Show the diff
    • agent/auxiliary_client.py
      @@ -112,6 +112,7 @@ def _normalize_aux_provider(provider: Optional[str]) -> str:
       # "exotic provider" branch checks this before falling back to the main model.
       _PROVIDER_VISION_MODELS: Dict[str, str] = {
           "xiaomi": "mimo-v2-omni",
      +    "zai": "glm-5v-turbo",
       }
       
       # OpenRouter app attribution headers
    • hermes_cli/auth.py
      @@ -383,13 +383,16 @@ def _resolve_api_key_provider_secret(
       # Z.AI has separate billing for general vs coding plans, and global vs China
       # endpoints.  A key that works on one may return "Insufficient balance" on
       # another.  We probe at setup time and store the working endpoint.
      +# Each entry lists candidate models to try in order — newer coding plan accounts
      +# may only have access to recent models (glm-5.1, glm-5v-turbo) while older
      +# ones still use glm-4.7.
       
       ZAI_ENDPOINTS = [
      -    # (id, base_url, default_model, label)
      -    ("global",        "https://api.z.ai/api/paas/v4",        "glm-5",   "Global"),
      -    ("cn",            "https://open.bigmodel.cn/api/paas/v4", "glm-5",   "China"),
      -    ("coding-global", "https://api.z.ai/api/coding/paas/v4",  "glm-4.7", "Global (Coding Plan)"),
      -    ("coding-cn",     "https://open.bigmodel.cn/api/coding/paas/v4", "glm-4.7", "China (Coding Plan)"),
      +    # (id, base_url, probe_models, label)
      +    ("global",        "https://api.z.ai/api/paas/v4",        ["glm-5"],   "Global"),
      +    ("cn",            "https://open.bigmodel.cn/api/paas/v4", ["glm-5"],   "China"),
      +    ("coding-global", "https://api.z.ai/api/coding/paas/v4",  ["glm-5.1", "glm-5v-turbo", "glm-4.7"], "Global (Coding Plan)"),
      +    ("coding-cn",     "https://open.bigmodel.cn/api/coding/paas/v4", ["glm-5.1", "glm-5v-turbo", "glm-4.7"], "China (Coding Plan)"),
       ]
       
       
      @@ -397,35 +400,37 @@ def detect_zai_endpoint(api_key: str, timeout: float = 8.0) -> Optional[Dict[str
           """Probe z.ai endpoints to find one that accepts this API key.
       
           Returns {"id": ..., "base_url": ..., "model": ..., "label": ...} for the
      -    first working endpoint, or None if all fail.
      +    first working endpoint, or None if all fail.  For endpoints with multiple
      +    candidate models, tries each in order and returns the first that succeeds.
           """
      -    for ep_id, base_url, model, label in ZAI_ENDPOINTS:
      -        try:
      -            resp = httpx.post(
      -                f"{base_url}/chat/completions",
      -                headers={
      -                    "Authorization": f"Bearer {api_key}",
      -                    "Content-Type": "application/json",
      -                },
      -                json={
      -                    "model": model,
      -                    "stream": False,
      -                    "max_tokens": 1,
      -                    "messages": [{"role": "user", "content": "ping"}],
      -                },
      -                timeout=timeout,
      -            )
      -            if resp.status_code == 200:
      -                logger.debug("Z.AI endpoint probe: %s (%s) OK", ep_id, base_url)
      -                return {
      -                    "id": ep_id,
      -                    "base_url": base_url,
      -                    "model": model,
      -                    "label": label,
      -                }
      -            logger.debug("Z.AI endpoint probe: %s returned %s", ep_id, resp.status_code)
      -        except Exception as exc:
      -            logger.debug("Z.AI endpoint probe: %s failed: %s", ep_id, exc)
      +    for ep_id, base_url, probe_models, label in ZAI_ENDPOINTS:
      +        for model in probe_models:
      +            try:
      +                resp = httpx.post(
      +                    f"{base_url}/chat/completions",
      +                    headers={
      +                        "Authorization": f"Bearer {api_key}",
      +                        "Content-Type": "application/json",
      +                    },
      +                    json={
      +                        "model": model,
      +                        "stream": False,
      +                        "max_tokens": 1,
      +                        "messages": [{"role": "user", "content": "ping"}],
      +                    },
      +                    timeout=timeout,
      +                )
      +                if resp.status_code == 200:
      +                    logger.debug("Z.AI endpoint probe: %s (%s) model=%s OK", ep_id, base_url, model)
      +                    return {
      +                        "id": ep_id,
      +                        "base_url": base_url,
      +                        "model": model,
      +                        "label": label,
      +                    }
      +                logger.debug("Z.AI endpoint probe: %s model=%s returned %s", ep_id, model, resp.status_code)
      +            except Exception as exc:
      +                logger.debug("Z.AI endpoint probe: %s model=%s failed: %s", ep_id, model, exc)
           return None
       
       
    • hermes_cli/models.py
      @@ -44,6 +44,7 @@
           ("minimax/minimax-m2.7",            ""),
           ("minimax/minimax-m2.5",            ""),
           ("z-ai/glm-5.1",                    ""),
      +    ("z-ai/glm-5v-turbo",               ""),
           ("z-ai/glm-5-turbo",                ""),
           ("moonshotai/kimi-k2.5",            ""),
           ("x-ai/grok-4.20",                  ""),
      @@ -89,6 +90,7 @@ def _codex_curated_models() -> list[str]:
               "minimax/minimax-m2.7",
               "minimax/minimax-m2.5",
               "z-ai/glm-5.1",
      +        "z-ai/glm-5v-turbo",
               "z-ai/glm-5-turbo",
               "moonshotai/kimi-k2.5",
               "x-ai/grok-4.20-beta",
      @@ -134,6 +136,7 @@ def _codex_curated_models() -> list[str]:
           "zai": [
               "glm-5.1",
               "glm-5",
      +        "glm-5v-turbo",
               "glm-5-turbo",
               "glm-4.7",
               "glm-4.5",

10 PRs closed without merging

From the close comments: superseded by another PR 4 · done elsewhere 2 · merged via another change 1 · other 3

  • #967 feat(providers): add Kimi Coding endpoint with auto-detection · merged via another change
  • #5566 fix(credential_pool): use _resolve_kimi_base_url when seeding kimi-coding pool · other → #5669
  • #5669 fix(auth): kimi-coding pool base_url seeding + PKCE endpoint fallback · other
  • #13954 fix(setup): clarify Moonshot/Kimi provider labels and accept MOONSHOT_API_KEY (#13935) · other
  • #42678 fix(auth): reorder Z.AI endpoint probe to try coding plan first (#42536) · superseded by another PR → #42547, #42536
Show 5 more
  • #43629 fix(provider): use api.kimi.com/coding endpoint for kimi-coding provider · done elsewhere → #43617
  • #43813 fix(provider): update kimi-coding endpoint and User-Agent (#43617) · superseded by another PR → #43629, #43617
  • #48509 fix(auxiliary_client): resolve API keys for inferred custom endpoints · done elsewhere → a8841e2
  • #58088 fix(zai): honor configured base url · superseded by another PR → 23d3eda
  • #61575 fix(agent): route Z.AI manual-pool entries through _resolve_zai_base_url · superseded by another PR
Closed issues · 8
  • Closed#966[Feature]: Add Kimi Coding as a direct inference provider
  • Closed#5561kimi-coding credential pool seeds wrong base_url for sk-kimi- keys, causing 401 on first request
  • Closed#9888[Feature]: Glm-5v-turbo for GLM Coding Plan
  • Closed#13935[Bug/UX]: kimi-coding provider misleading — points to kimi.com/coding not platform.moonshot.ai
  • Closed#43617[Bug]: kimi-coding provider uses wrong endpoint + User-Agent for sk-kimi-* keys, breaking all API calls including vision
  • Closed#58071[Bug] zai provider ignores config.yaml base_url and always probes endpoints in hardcoded order — standard endpoint always wins over coding endpoint
  • Closed#61563zai manual-pool credentials always routed to metered /api/paas/v4 instead of /api/coding/paas/v4 (hermes auth add cannot override base_url)
  • Closed#68239hermes auth add stamps registry-default base_url for kimi-coding — sk-kimi- keys paired with api.moonshot.ai/v1, instant 401
How this cluster was grouped
  • Link evidence (partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
  • Members outside that structural core may belong to a different underlying problem.
  • Pairwise link density 0.05: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
agent
Merged PRs
#9907
Closed issues
8
Attempts
10 PRs closed without merging
Fix link checked
14 Apr 2026. This confirmation is old and may be out of date (a revert or reopen would not have invalidated it here); re-verify.

For your agent

The same facts, typed.