#112600·hermes-agent

opencode: stale Zen model.base_url survives a switch to an opencode-go model → 401 "Model is not supported" (normalize_opencode_base_url never rewrites the family path)

Author: chenwei2610Created Sep 16, 2026Updated Sep 17, 2026
Labelstype/bugcomp/cliprovider/openaiarea/configP2sweeper:risk-compatibility

Summary

Switching to an opencode-go-only model while config.yaml's model.base_url is pinned to the Zen relay leaves the base URL pointing at Zen. The provider flips to opencode-go, the URL does not, and every request fails:

provider=opencode-go  base_url=https://opencode.ai/zen/v1  model=mimo-v2.5
-> HTTP 401: Model mimo-v2.5 is not supported

mimo-v2.5 / mimo-v2.5-pro are Go-subscription models (GET /zen/go/v1/models lists them; GET /zen/v1/models does not), so the Zen relay is correct to reject them — the bug is that we asked Zen at all.

The desktop app is unaffected because it resolves the base URL from the model catalog per session; the CLI inherits the pinned model.base_url override. Both run the same backend, so the only difference is which URL the client is built with.

Environment

  • Hermes Agent v0.21.3 (2026.9.14), upstream 3c3ab69a, install method: git
  • Windows 11, install dir %LOCALAPPDATA%\hermes
  • Provider: built-in opencode-go; credential present in the pool and valid

Steps to reproduce

  1. Have config.yaml in the state left behind by previously using an OpenCode Zen model:
    model:
      default: mimo-v2.5-free
      provider: opencode
      base_url: https://opencode.ai/zen/v1
    
  2. Switch to a Go-only model: hermes -m mimo-v2.5 --provider opencode-go
  3. Send any message.

Actual: HTTP 401: Model mimo-v2.5 is not supported, with provider=opencode-go base_url=https://opencode.ai/zen/v1. Expected: the client is built against https://opencode.ai/zen/go/v1 and the request succeeds.

Evidence

errors.log, provider already correctly resolved to opencode-go but URL still on Zen:

2026-09-16 12:14:22,781 ERROR agent.chat_completion_helpers: Streaming failed before delivery:
  Error code: 401 - {'type': 'error', 'error': {'type': 'ModelError', 'message': 'Model mimo-v2.5 is not supported'}}
2026-09-16 12:14:22,788 WARNING agent.conversation_loop: API call failed (attempt 1/3)
  error_type=AuthenticationError provider=opencode-go base_url=https://opencode.ai/zen/v1 model=mimo-v2.5
  summary=HTTP 401: Model mimo-v2.5 is not supported

Interestingly the session's persisted model_config had the right URL in gateway_runtime while the client used the wrong one:

{"model": "mimo-v2.5",
 "gateway_runtime": {"provider": "opencode-go", "base_url": "https://opencode.ai/zen/go/v1", "api_mode": "chat_completions"},
 "provider": "opencode-go", "base_url": "https://opencode.ai/zen/v1"}

Per-session billing rows (state.db, session_model_usage) across this install — mimo-v2.5 has never succeeded from the CLI, only from desktop:

source model billing_provider billing_base_url calls
desktop mimo-v2.5 opencode-go https://opencode.ai/zen/go/v1 31
cli mimo-v2.5-free opencode-zen https://opencode.ai/zen/v1 1
tui mimo-v2.5-free opencode-zen https://opencode.ai/zen/v1 1

Root cause

normalize_opencode_base_url() (hermes_cli/models.py, present on current origin/main) is the only healing step applied to a carried-over OpenCode base URL, and it only ever touches the /v1 suffix — never the family path segment (/zen vs /zen/go):

url = str(base_url or "").strip().rstrip("/")
if not url or opencode_provider_family(provider_id) is None:
    return url
if api_mode == "anthropic_messages":
    return re.sub(r"/v1$", "", url)
if url.endswith("/v1"):
    return url          # <-- https://opencode.ai/zen/v1 returns unchanged for an opencode-go provider
...

So ("opencode-go", "chat_completions", "https://opencode.ai/zen/v1") returns the Zen URL untouched. Nothing else downstream reconciles the URL against the resolved provider family.

Suggested fix

When opencode_provider_family(provider_id) resolves and the host is opencode.ai, rewrite the family path segment to match the family (opencode-go -> /zen/go/v1, opencode/opencode-zen/opencode-free -> /zen/v1) instead of only healing the /v1 suffix. Custom OPENCODE_*_BASE_URL proxies on non-opencode.ai hosts should keep the existing passthrough behaviour.

Workaround: pin model.base_url: https://opencode.ai/zen/go/v1 in config.yaml by hand. Verified — after that change the same CLI invocation succeeds and bills against https://opencode.ai/zen/go/v1.

Related

  • #100854 — also opencode-go + wrong outbound URL, but the anthropic_messages route and a 404; different surface.
  • #105947 — opencode-free missing /v1; same function, the suffix case it does handle.
  • #65587 — model override not re-resolving provider transport; adjacent lifecycle issue.

Source: NousResearch/hermes-agent