Support model providers in the app-server model/list API

Open 💬 1 comment Opened Aug 18, 2026 by marmeladema

What variant of Codex are you using?

app-server API through my Giskard web frontend

What feature would you like to see?

Problem

The app-server model/list API currently lists models only for the configured
default provider. Unlike thread/start, clients cannot select a model provider.

This makes it difficult for clients to present models for another configured
provider before starting a thread.

Proposed behavior

Add an optional modelProvider parameter to model/list:

{
  "modelProvider": "amazon-bedrock",
  "limit": 100,
  "cursor": null,
  "includeHidden": false
}

When omitted, model/list should continue using the configured default provider.

The response should also identify the provider associated with the returned
catalog. Two possible shapes are:

  1. Add modelProvider to every model, allowing future mixed-provider responses.
  2. Add modelProvider to ModelListResponse, establishing that one response

always contains models from exactly one provider.

The response-level field may be preferable because the request resolves exactly
one provider and avoids repeating identical metadata:

{
  "modelProvider": "amazon-bedrock",
  "data": [
    {
      "id": "openai.gpt-5.6-sol",
      "model": "openai.gpt-5.6-sol"
    }
  ],
  "nextCursor": null
}

Listing models from all providers could be considered separately. That design
would need explicit rules for ordering, pagination, per-provider defaults,
latency, and partial failures.

Implementation considerations

  • Unknown provider IDs should return an invalid-request error.
  • Provider resolution should use the latest effective configuration.
  • Pagination cursors should remain scoped to the selected provider.
  • Provider-specific model managers should be reused in memory.
  • Alternate providers should not share the current file-backed model cache,

because that cache is not partitioned by provider.

Reference implementation

I explored an implementation on my fork:

https://github.com/marmeladema/codex/tree/model-list-provider-support

The reference implementation uses the per-model modelProvider shape. It also
includes generated API schemas, documentation, and integration coverage for
explicit provider selection, default-provider fallback, and unknown providers.

I understand that external pull requests are not accepted; the fork is provided
only as technical exploration and a concrete reference for the design.

Additional information

_No response_

View original on GitHub ↗

1 Comment

marmeladema · 8 days ago

Three things worth folding in.

1. It's a correctness bug, not just listing. Turn metadata resolves from the
single ThreadManagerState.models_manager:

  • core/src/thread_manager.rs:1858 — Session::spawn is handed

Arc::clone(&self.models_manager), even though the config in that same
struct literal already carries the thread's resolved model_provider.

  • core/src/session/mod.rs:645 and core/src/session/turn_context.rs:338 both

call get_model_info on it.

So a thread started with a non-default modelProvider looks its model up in the
root provider's catalog, misses, and degrades silently:
Model metadata for <slug> not found. Defaulting to fallback metadata —
conservative context window, generic effort ladder. Resolving that manager from
the registry this issue already proposes, keyed on the session's provider, fixes
it. Same registry, one more caller.

2. A shared remote_models is a collision, not just a limitation. In
apply_remote_models, should_use_remote_models_only is true whenever the auth
mode has a ChatGPT account and the fetched list has a visible model — and it
replaces remote_models outright rather than merging. With one shared list the
last provider to refresh wins and the other provider's models disappear.
Per-provider managers make that impossible rather than merely unlikely.

3. The cache point is already acknowledged in-tree —
models-manager/src/manager.rs:

// TODO(celia-oai): Include provider identity in cache eligibility so switching
// providers does not reuse a fresh models_cache.json entry from another provider.