Skip to content

[Bug]: Per-model api override not resolved in auth path #80487

@huveewomg

Description

@huveewomg

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

When a model within a custom provider overrides api (e.g., api: "anthropic-messages" on a model under a provider with api: "openai-completions"), two things break:

  1. Auth resolution: resolveProviderHookRefs only reads providerConfig.api, so the overridden API's plugin hooks are never discovered.
  2. Transport selection: resolveConfiguredFallbackModel and the discovered-model path in resolveModelAsync resolve transport using only provider-level api/baseUrl, ignoring the per-model override — the model routes through the wrong adapter.

Steps to reproduce

  1. Configure a custom provider with api: "openai-completions" and add a model with api: "anthropic-messages" override:
{
  models: {
    providers: {
      "my-router": {
        baseUrl: "http://localhost:8080/v1",
        api: "openai-completions",
        models: [
          { id: "my-router/gpt-model", name: "GPT Model", contextWindow: 400000, input: ["text"] },
          { id: "my-router/claude", name: "Claude", api: "anthropic-messages", baseUrl: "http://localhost:8080", contextWindow: 200000, input: ["text", "image"] }
        ]
      }
    }
  }
}
  1. Set primary model to my-router/claude
  2. Send a chat message
  3. Observe router logs — the request hits /v1/chat/completions (provider-level adapter) instead of /v1/messages (per-model override)

Expected behavior

Model resolves auth via the overridden API's plugin hooks and routes through the correct transport adapter (POST /v1/messages for anthropic-messages).

Actual behavior

  • Auth resolution fails to discover the correct plugin hooks (uses provider-level api instead of model-level)
  • Transport routes through the provider-level adapter (POST /v1/chat/completions) instead of the per-model override (POST /v1/messages)

Fix status

PR #80488 fixes both auth resolution and transport selection for transport-aware APIs (openai-completions, anthropic-messages, google-generative-ai, etc.).

Verified at runtime: Provider-level api: "openai-completions" with per-model api: "anthropic-messages" correctly routes to POST /v1/messages after the fix.

Known remaining limitation (out of scope for this issue): Per-model api: "ollama" under a non-ollama provider still fails with "No API provider registered for api: ollama". This is because ollama is not a transport-aware API — it has no case in createSupportedTransportStreamFn and lives entirely in the plugin layer. Making ollama transport-aware would be a separate feature request.

OpenClaw version

2026.5.6

Operating system

Ubuntu 24.04

Install method

docker

Model

Custom provider model with per-model api: "anthropic-messages" override

Provider / routing chain

openclaw → custom local router → Anthropic API / OpenAI API

Additional provider/model setup details

The use case is a local LLM router that proxies multiple backends behind a single provider entry. Some models use openai-completions transport (GPT), others need anthropic-messages (Claude). The per-model api override is accepted by the config schema but was ignored by both auth and transport resolution.

Logs, screenshots, and evidence

Before fix (all models routed through provider-level adapter):

POST /v1/chat/completions HTTP/1.1" 200 OK    <- anthropic model incorrectly using openai adapter

After fix (per-model override respected):

POST /v1/chat/completions HTTP/1.1" 200 OK    <- GPT model (inherited provider-level api)
POST /v1/messages HTTP/1.1" 200 OK            <- Anthropic model (per-model override working)

Impact and severity

  • Affected: Users running local routers/proxies that handle multiple backends behind a single provider
  • Severity: Medium — blocks per-model api overrides for transport-aware APIs. Workaround exists (split into separate providers per API type)
  • Frequency: Always, 100% reproducible when per-model api differs from provider-level api
  • Consequence: Users must create separate provider entries for each transport type, fragmenting the model list and complicating configuration

Additional information

The original report used api: "ollama" as the example, which revealed a deeper limitation: ollama is plugin-based, not transport-aware. The auth fix in PR #80488 resolves hook refs correctly for ollama, but the transport layer has no ollama case in createSupportedTransportStreamFn. This is a separate feature request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingbug:behaviorIncorrect behavior without a crash

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions