# NousResearch/hermes-agent · Z.ai GLM coding-plan vision endpoint and GLM-5V-Turbo support

## Open now

- 1 issue, 2 PRs open on GitHub.
- #55112: \[Bug\]: hardcoded zai vision base_urls (paas/v4) bypass the coding-plan endpoint → silent metered billing
- PR #55116: fix(auxiliary): prepend zai coding-plan vision endpoint before metered paas/v4 (fixes #55112)
- PR #55156: fix(auxiliary): try zai coding-plan vision endpoint before metered fallbacks (#55112)

Members center on Z.ai's coding plan: adding GLM-5V-Turbo support, and a reported issue where hardcoded vision base URLs (paas/v4) may bypass the coding-plan endpoint and lead to metered billing. Two pull requests propose trying the coding-plan vision endpoint before metered fallbacks.

## TL;DR

- 5 member(s): 1 open issue(s), 1 closed issue(s), 2 open PR(s), 1 merged PR(s), 0 PR(s) closed without merging.
- A fix was merged to main in PR #9907. Verify it addresses your case.
- **Recommended:** read PR #9907 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `partially_resolved` · deciding PR(s): `pr-9907`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_PARTIAL`): 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.34`: the share of member 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.

## Open related issues

- #55112: \[Bug\]: hardcoded zai vision base_urls (paas/v4) bypass the coding-plan endpoint → silent metered billing

## Closed / duplicate issues

- #9888: \[Feature\]: Glm-5v-turbo for GLM Coding Plan

## Prior & competing PRs

- **#9907: feat(zai): add GLM-5V-Turbo support for coding plan**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `agent/auxiliary_client.py`, `hermes_cli/auth.py`, `hermes_cli/models.py`
  - fix hunks:
  - `agent/auxiliary_client.py`

    ```diff
    @@ -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`

    ```diff
    @@ -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)"),
     ]
     
     
    ```

    ```diff
    @@ -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`

    ```diff
    @@ -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",                  ""),
    ```

    ```diff
    @@ -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",
    ```

    ```diff
    @@ -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",
    ```
- **#55116: fix(auxiliary): prepend zai coding-plan vision endpoint before metered paas/v4 (fixes #55112)**. open
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `#62467`
  - files: `agent/auxiliary_client.py`
- **#55156: fix(auxiliary): try zai coding-plan vision endpoint before metered fallbacks (#55112)**. open
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#55116`, `#55112`
  - files: `agent/auxiliary_client.py`, `tests/agent/test_vision_zai_coding_plan_55112.py`

## Fix status

- Merged to main in PR #9907 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-04-14`. This confirmation is old and may be out of date (a revert/reopen would not have invalidated it here); re-verify.
- Subsystem: `agent`
