Summary
With adapter: anthropic (and similarly other adapters that rely on OpenAI-style model discovery), OpenCodex runs model discovery via:
GET <baseUrl>/v1/models?limit=1000
Some upstreams authorize the API key for inference, but not for the models list endpoint. A concrete case is Volcengine Ark Agent Plan / Coding Plan:
- inference endpoints such as
/v1/messages work
GET /v1/models returns 401 AuthenticationError
When discovery fails and no customModels entry exists, the entire provider silently disappears from the Models tab / Claude model discovery. There is no UI path to manually specify a model id, even though the provider is usable after a manual custom-model registration.
Environment
- opencodex:
2.7.33
- macOS, Apple Silicon
- Upstream: Volcengine Ark Agent Plan / Coding Plan
- Example model:
glm-5-2 / glm-5-2-260617
- Example base URLs:
- Agent Plan Anthropic path:
https://ark.cn-beijing.volces.com/api/plan
- Coding Plan Anthropic path:
https://ark.cn-beijing.volces.com/api/coding
- Provider config shape:
adapter: anthropic, key auth
Current behaviour
- Provider key is valid for inference:
POST <baseUrl>/v1/messages → 200, model responds correctly
- Same key fails model discovery:
GET <baseUrl>/v1/models?limit=1000 → 401 AuthenticationError
- service.log shows something like:
Provider model discovery for "<name>" failed with HTTP 401 [urlClass=provider-models, fallback=configured].
- If no custom model has been registered yet, the provider vanishes from:
- OpenCodex Models tab
- Claude model discovery
- There is no dashboard / model-list UI affordance to manually enter a known model id as a fallback when discovery fails.
Expected behaviour
When model discovery fails (especially with 401 / permission-limited plan keys), OpenCodex should not hide a still-usable provider.
Specifically:
- Keep the provider visible even if
/v1/models fails.
- Support manual model specification at the model-interface / provider layer (config and preferably dashboard UI), e.g.:
- default model
- custom model ids / catalog entries
- configured fallback models used when discovery fails
- Surface discovery failure clearly (
401, discovery failed badge / log-backed reason), instead of silent disappearance.
- Once a model is manually specified, expose it to Codex / Claude as a normal selectable model.
Workaround found
Manually register the known model via:
After that, the provider reappears and inference works immediately.
This proves:
- discovery failure ≠ inference failure
- Agent Plan can be used successfully once the model id is specified manually
- the missing piece is a first-class manual model entry path when discovery is unavailable
Minimal redacted reproduction
# 1) Inference works
curl -sS -X POST 'https://ark.cn-beijing.volces.com/api/plan/v1/messages' \
-H 'x-api-key: <REDACTED>' \
-H 'anthropic-version: 2023-06-01' \
-H 'content-type: application/json' \
-d '{
"model": "glm-5-2",
"max_tokens": 32,
"messages": [{"role":"user","content":"Reply exactly: OK"}]
}'
# → HTTP 200
# 2) Model list fails with the same key
curl -sS 'https://ark.cn-beijing.volces.com/api/plan/v1/models?limit=1000' \
-H 'x-api-key: <REDACTED>'
# → HTTP 401 AuthenticationError
# 3) OpenCodex result without customModels:
# provider disappears from Models tab / discovery UI
# 4) After manual custom model registration:
# provider reappears and inference through OpenCodex works
Why this matters for Agent Plan
Volcengine Agent Plan is a practical multi-model coding/plan product. In practice:
- plan keys may be allowed to call chat/messages endpoints
- plan keys may not be allowed to list models
- the usable model ids are still known to the user (e.g.
glm-5-2)
So OpenCodex currently creates a false “provider broken” state for a working Agent Plan route. Manual model specification should be a supported primary path, not only a hidden recovery API.
Suggested implementation notes
Possible backward-compatible approaches:
- Treat configured
defaultModel / customModels as durable catalog entries independent of discovery success.
- Add an explicit provider/model field such as
manualModels or strengthen existing custom-model support so discovery failure never removes configured models.
- In dashboard / model interface:
- show provider even when discovery fails
- allow adding model ids manually
- badge the provider with
discovery failed (401) or similar
- Keep discovery as best-effort enrichment, not a hard gate for provider visibility.
Additional context
Checks
Summary
With
adapter: anthropic(and similarly other adapters that rely on OpenAI-style model discovery), OpenCodex runs model discovery via:Some upstreams authorize the API key for inference, but not for the models list endpoint. A concrete case is Volcengine Ark Agent Plan / Coding Plan:
/v1/messagesworkGET /v1/modelsreturns401 AuthenticationErrorWhen discovery fails and no
customModelsentry exists, the entire provider silently disappears from the Models tab / Claude model discovery. There is no UI path to manually specify a model id, even though the provider is usable after a manual custom-model registration.Environment
2.7.33glm-5-2/glm-5-2-260617https://ark.cn-beijing.volces.com/api/planhttps://ark.cn-beijing.volces.com/api/codingadapter: anthropic, key authCurrent behaviour
POST <baseUrl>/v1/messages→200, model responds correctlyGET <baseUrl>/v1/models?limit=1000→401 AuthenticationErrorProvider model discovery for "<name>" failed with HTTP 401 [urlClass=provider-models, fallback=configured].Expected behaviour
When model discovery fails (especially with
401/ permission-limited plan keys), OpenCodex should not hide a still-usable provider.Specifically:
/v1/modelsfails.401, discovery failed badge / log-backed reason), instead of silent disappearance.Workaround found
Manually register the known model via:
After that, the provider reappears and inference works immediately.
This proves:
Minimal redacted reproduction
Why this matters for Agent Plan
Volcengine Agent Plan is a practical multi-model coding/plan product. In practice:
glm-5-2)So OpenCodex currently creates a false “provider broken” state for a working Agent Plan route. Manual model specification should be a supported primary path, not only a hidden recovery API.
Suggested implementation notes
Possible backward-compatible approaches:
defaultModel/customModelsas durable catalog entries independent of discovery success.manualModelsor strengthen existing custom-model support so discovery failure never removes configured models.discovery failed (401)or similarAdditional context
dev: [Bug]: anthropic adapter returns empty content (adapter_eof / 0 tokens) for streaming requests against upstreams that emit reasoning blocks (Kimi k3) #312Checks
/v1/modelsreturns 401, and manually specifying the model restores usability.