Summary
When using the opencode-go provider with the Hermes Agent CLI, any model whose name contains a dot as a version separator (e.g. minimax-m2.7, glm-4.5, kimi-k2.5) is silently mangled before the API request is made — dots are replaced with hyphens. This causes the OpenCode Go endpoint to return HTTP 401:
error type: ModelError
message: Model minimax-m2-7 not supported
The root cause is not the OpenCode Go API itself. Manual curl requests with the correct model name (minimax-m2.7) succeed. The bug lives entirely inside Hermes and affects two separate code paths.
Affected Models (non-exhaustive)
| Model |
Mangled to |
Result |
minimax-m2.7 |
minimax-m2-7 |
401 from OpenCode Go |
minimax-m2.5 |
minimax-m2-5 |
401 from OpenCode Go |
glm-4.5 |
glm-4-5 |
401 from OpenCode Go |
kimi-k2.5 |
kimi-k2-5 |
401 from OpenCode Go |
mimo-v2-omni |
mimo-v2-omni |
Works (no dot, coincidence) |
glm-5 |
glm-5 |
Works (no dot, coincidence) |
Models without a . version separator appeared to work not because the logic was correct, but because the mangled output happens to match the input.
Root Cause — Two Separate Bugs
Bug 1: hermes/cli/model_normalize.py — opencode-go incorrectly in DOT_TO_HYPHEN_PROVIDERS
opencode-go was included in DOT_TO_HYPHEN_PROVIDERS (alongside anthropic), causing normalize_model_for_provider() to call dots_to_hyphens() on all model names for this provider. The Anthropic API uses hyphens (e.g. claude-sonnet-4-6), but OpenCode Go uses its own identifiers with dots (e.g. minimax-m2.7).
Fix:
DOT_TO_HYPHEN_PROVIDERS: frozenset[str] = frozenset({
"anthropic",
"opencode-zen",
- "opencode-go",
})
Bug 2: run_agent.py — anthropic_preserve_dots() missing opencode-go
When the API mode is anthropic_messages (which MiniMax models on the Go endpoint use), Hermes builds the request via anthropic_adapter.build_anthropic_kwargs(). That function calls normalize_model_name(model, preserve_dots=...). The preserve_dots argument is set by anthropic_preserve_dots(), which only checked for Alibaba DashScope — never for OpenCode Go. So even after Bug 1 is fixed, the API-layer call still converts minimax-m2.7 → minimax-m2-7.
Fix:
def anthropic_preserve_dots(self) -> bool:
- """True when using AlibabaDashScope anthropic-compatible endpoint —
- model names keep dots, e.g. qwen3.5-plus."""
- if getattr(self, "provider", "") or "").lower() == "alibaba":
+ """True when using an anthropic-compatible endpoint that preserves dots in model names.
+ AlibabaDashScope keeps dots (e.g. qwen3.5-plus).
+ OpenCode Go keeps dots (e.g. minimax-m2.7). Without this, dots become hyphens → 401."""
+ if getattr(self, "provider", "") or "").lower() in {"alibaba", "opencode-go"}:
return True
base = (getattr(self, "base_url", "") or "").lower()
- return "dashscope" in base or "aliyuncs" in base
+ return "dashscope" in base or "aliyuncs" in base or "opencode.ai/zen/go" in base
Evidence
Request dump from a failing session (.hermes/sessions/request_dump.json):
{
"method": "POST",
"url": "https://opencode.ai/zen/go/chat/completions",
"body": { "model": "minimax-m2-7" } // dots already became hyphens here
}
Working curl with correct model name:
curl https://opencode.ai/zen/go/v1/messages \
-H "x-api-key: sk-..." \
-H "Content-Type: application/json" \
-d '{"model": "minimax-m2.7", "max_tokens": 50, "messages": [{"role": "user", "content": "Say hello briefly"}]}'
# Returns a valid response
config.yaml is always correct — Hermes stores the name properly. The mangling happens after config is loaded, during the API request build step:
model_default: minimax-m2.7 # correct
provider: opencode-go
base_url: https://opencode.ai/zen/go/v1
Summary
When using the
opencode-goprovider with the Hermes Agent CLI, any model whose name contains a dot as a version separator (e.g.minimax-m2.7,glm-4.5,kimi-k2.5) is silently mangled before the API request is made — dots are replaced with hyphens. This causes the OpenCode Go endpoint to return HTTP 401:The root cause is not the OpenCode Go API itself. Manual
curlrequests with the correct model name (minimax-m2.7) succeed. The bug lives entirely inside Hermes and affects two separate code paths.Affected Models (non-exhaustive)
minimax-m2.7minimax-m2-7minimax-m2.5minimax-m2-5glm-4.5glm-4-5kimi-k2.5kimi-k2-5mimo-v2-omnimimo-v2-omniglm-5glm-5Models without a
.version separator appeared to work not because the logic was correct, but because the mangled output happens to match the input.Root Cause — Two Separate Bugs
Bug 1:
hermes/cli/model_normalize.py—opencode-goincorrectly inDOT_TO_HYPHEN_PROVIDERSopencode-gowas included inDOT_TO_HYPHEN_PROVIDERS(alongsideanthropic), causingnormalize_model_for_provider()to calldots_to_hyphens()on all model names for this provider. The Anthropic API uses hyphens (e.g.claude-sonnet-4-6), but OpenCode Go uses its own identifiers with dots (e.g.minimax-m2.7).Fix:
DOT_TO_HYPHEN_PROVIDERS: frozenset[str] = frozenset({ "anthropic", "opencode-zen", - "opencode-go", })Bug 2:
run_agent.py—anthropic_preserve_dots()missingopencode-goWhen the API mode is
anthropic_messages(which MiniMax models on the Go endpoint use), Hermes builds the request viaanthropic_adapter.build_anthropic_kwargs(). That function callsnormalize_model_name(model, preserve_dots=...). Thepreserve_dotsargument is set byanthropic_preserve_dots(), which only checked for Alibaba DashScope — never for OpenCode Go. So even after Bug 1 is fixed, the API-layer call still convertsminimax-m2.7→minimax-m2-7.Fix:
Evidence
Request dump from a failing session (
.hermes/sessions/request_dump.json):{ "method": "POST", "url": "https://opencode.ai/zen/go/chat/completions", "body": { "model": "minimax-m2-7" } // dots already became hyphens here }Working curl with correct model name:
config.yamlis always correct — Hermes stores the name properly. The mangling happens after config is loaded, during the API request build step: