Model Listing

List available provider models through Anvia clients.

Provider clients can list models through the normalized listModels() method.

import { OpenAIClient } from "@anvia/openai";

const client = new OpenAIClient({ apiKey });
const models = await client.listModels();

for (const model of models.data) {
  console.log(model.id, model.contextLength);
}

listModels() returns a ModelList from @anvia/core/model-listing.

type ListedModel = {
  id: string;
  name?: string;
  description?: string;
  type?: string;
  createdAt?: number;
  ownedBy?: string;
  contextLength?: number;
};

type ModelList = {
  data: ListedModel[];
};

Only id is guaranteed. Providers and compatible gateways expose different metadata, so unknown fields remain omitted.

Supported Clients

await new OpenAIClient({ apiKey }).listModels();
await new AnthropicClient({ apiKey }).listModels();
await new GeminiClient({ apiKey }).listModels();
await new MistralClient({ apiKey }).listModels();

Each client fetches live provider data. Anvia does not add hidden model metadata, cache the result, or include beta/private model ids that the provider does not return.

Compatible Gateways

OpenAI-compatible gateways use the same OpenAIClient path.

const client = new OpenAIClient({
  baseUrl: "https://openrouter.ai/api/v1",
  apiKey: process.env.OPENROUTER_API_KEY,
});

const models = await client.listModels();

The request goes to the configured gateway models endpoint, usually GET {baseUrl}/models. If the gateway returns sparse OpenAI-shaped data, Anvia normalizes fields such as id, createdAt, and ownedBy. If the gateway returns richer fields such as name or context_length, Anvia includes those as name and contextLength.

If the gateway does not expose a compatible model-list endpoint, listModels() rejects with ModelListingError.

Manual Model Lists

You do not need listModels() to use a model. If your app already knows the allowed model ids, define a manual ModelList and pass those ids to the provider client.

import type { ModelList } from "@anvia/core/model-listing";
import { OpenAIClient } from "@anvia/openai";

const models: ModelList = {
  data: [
    {
      id: "openai/gpt-5-mini",
      name: "GPT-5 Mini",
      ownedBy: "openai",
      contextLength: 400_000,
    },
    {
      id: "anthropic/claude-sonnet-4.6",
      name: "Claude Sonnet 4.6",
      ownedBy: "anthropic",
      contextLength: 200_000,
    },
  ],
};

const client = new OpenAIClient({
  baseUrl: process.env.OPENAI_COMPATIBLE_BASE_URL,
  apiKey: process.env.OPENAI_COMPATIBLE_API_KEY,
});

const selectedModelId = models.data[0]?.id ?? "openai/gpt-5-mini";
const model = client.completionModel(selectedModelId);

Use this pattern for configuration screens, private deployments, beta models, or gateways that do not expose GET /models.

If you want a manually defined source to match the same shape as provider clients, implement ModelListingClient:

import type { ModelList, ModelListingClient } from "@anvia/core/model-listing";

function staticModelListing(models: ModelList): ModelListingClient {
  return {
    async listModels() {
      return models;
    },
  };
}

You can also merge live provider data with manual entries:

const liveModels = await client.listModels().catch((): ModelList => ({ data: [] }));

const mergedModels: ModelList = {
  data: [
    ...models.data,
    ...liveModels.data.filter(
      (liveModel) => !models.data.some((manualModel) => manualModel.id === liveModel.id),
    ),
  ],
};

Unlisted Models

You can still use a known beta or private model id directly:

const model = client.completionModel("provider/beta-model");

That model will not appear in listModels() unless the provider includes it in the model-list response.

Cookbook

Run the model-listing cookbook example:

pnpm cookbook:providers:10