> ## Documentation Index
> Fetch the complete documentation index at: https://vetta.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Models

> The model catalogue an agent can run on — read live from the inference network, never a fixed list.

<Info>There is **no fixed list of models**. The catalogue is read from the inference network and cached briefly, so a model published this morning is runnable this morning. Search it here; pass what you find as `model` on an [agent](/docs/api/agents) or a [session](/docs/api/sessions), or as `model` to the [model proxy](/docs/api/proxy).</Info>

## The model object

<ResponseField name="object" type="string">Always `model`.</ResponseField>
<ResponseField name="id" type="string">The model's id. This is what `model` takes on an agent, a session and the proxy.</ResponseField>
<ResponseField name="context_window" type="integer">Maximum context length in tokens, as the provider that will serve it publishes it.</ResponseField>
<ResponseField name="max_output_tokens" type="integer">The longest reply this model may produce. It is also the output half of the [pre-flight quote](/docs/concepts/budgets), so a model with a large allowance reserves more against your balance for the same prompt.</ResponseField>
<ResponseField name="supported_windows" type="string[]">Which [completion windows](/docs/concepts/completion-window) this model can run in. `immediate` is always present; `priority` and `loose` appear only for pool-hosted models.</ResponseField>
<ResponseField name="efforts" type="string[]">Effort levels the model accepts, from what it publishes. Empty when it accepts none.</ResponseField>

**No price is published here**, the same line [`GET /v1/media/models`](/docs/api/media) draws. What a call costs depends on the window it runs in and on which of the five token tiers its usage lands in; a single figure on this reply would be a guess. See [the model router](/docs/concepts/model-router#what-a-model-call-costs) for how a call is metered, and [Pricing](/docs/platform/pricing).

## List the catalogue

`GET /v1/models` — any valid key; no scope.

<ParamField query="window" type="string">`immediate`, `priority` or `loose`. Narrows the list to models that window can actually serve — the same derivation the router refuses on, so a model listed for a window is never refused for it.</ParamField>
<ParamField query="search" type="string">Free text, matched against a model's id and name. Omit it to list them all.</ParamField>
<ParamField query="limit" type="number">Page size, 1–100. Defaults to 20.</ParamField>
<ParamField query="after" type="string">The `next_cursor` of the previous page. Opaque — it is not a row id.</ParamField>

The catalogue runs to several hundred entries, so **this reply is paged** ([Pagination](/docs/api/pagination)). Nothing should assume one call returns the whole catalogue.

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -fsSL "https://api.vetta.sh/v1/models?search=glm&limit=2" \
    -H "authorization: Bearer sk_live_..."
  ```

  ```typescript TypeScript theme={"system"}
  const page = await vetta.models.list({ search: "glm", limit: 2 });
  ```

  ```bash CLI theme={"system"}
  vetta models list --search glm --limit 2
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={"system"}
  {
    "object": "list",
    "data": [
      {
        "object": "model",
        "id": "zai-org/GLM-5.2-FP8",
        "context_window": 1048576,
        "max_output_tokens": 32768,
        "supported_windows": ["immediate", "priority", "loose"],
        "efforts": ["high"]
      }
    ],
    "has_more": true,
    "next_cursor": "2"
  }
  ```
</ResponseExample>

Ordering is cheapest published input rate first, then by id, so a page boundary is stable within one read.

## Retrieve one model

`GET /v1/models/{id}` — any valid key; no scope.

<Warning>A model id contains a `/`, so it must be **percent-encoded** in the path: `anthropic/claude-sonnet-5` becomes `anthropic%2Fclaude-sonnet-5`.</Warning>

Use this when you already hold an id — the model an agent is set to, say — and want to know what it can do before you spend on it. It answers on the ids this route *lists*; a model the catalogue republishes under a different spelling is resolved for billing but is not itself an id you can retrieve.

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -fsSL "https://api.vetta.sh/v1/models/anthropic%2Fclaude-sonnet-5" \
    -H "authorization: Bearer sk_live_..."
  ```

  ```typescript TypeScript theme={"system"}
  const model = await vetta.models.retrieve("anthropic/claude-sonnet-5");
  console.log(model.supported_windows); // ["immediate"]
  ```

  ```bash CLI theme={"system"}
  vetta models get anthropic/claude-sonnet-5
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={"system"}
  {
    "object": "model",
    "id": "anthropic/claude-sonnet-5",
    "context_window": 1000000,
    "max_output_tokens": 32768,
    "supported_windows": ["immediate"],
    "efforts": ["low", "medium", "high"]
  }
  ```
</ResponseExample>

## Choose a model for a conversation

`POST /v1/models/auto_select` — scope `proxy:write` (or `sessions:write`). [`Idempotency-Key`](/docs/api/overview#idempotency) accepted.

An **optional add-on** — the capability page is [Model auto-selection](/docs/concepts/model-selection). You name two to sixteen catalogue ids, each with one line on what it is for, and hand over the conversation so far; the reply is **one of those ids**, which you then pass unchanged as `model` to the [model proxy](/docs/api/proxy), an [agent](/docs/api/agents) or a [session](/docs/api/sessions). It selects; it does not call the model it selected, and nothing about routing, the catalogue or `vetta/auto` changes whether or not you use it.

<ParamField body="options" type="object" required>
  Catalogue id → description, **2 to 16 entries**. Every key must be an id [the catalogue](#list-the-catalogue) lists, spelled exactly — an unknown id, an alias or `vetta/auto` is `validation_failed` with `param: "options.<id>"`. A description is trimmed and must be 1 to 500 characters after trimming.
</ParamField>

<ParamField body="messages" type="object[]" required>
  The conversation, **1 to 32 turns** of `{ "role": "user" | "assistant", "content": string }`, each `content` at least one character. The `content` lengths must **sum to 32000 characters or fewer**; over that the request is `validation_failed` with `param: "messages"`. Nothing is trimmed, windowed or truncated for you — send less if you want less considered.
</ParamField>

<ParamField body="default" type="string">
  One of the `options` keys, else `validation_failed` with `param: "default"`. Returned in place of the pick when `min_confidence` is set and not met.
</ParamField>

<ParamField body="min_confidence" type="number">
  A number above `0` and at most `1`. Requires `default` — a threshold with nothing to fall back to is `validation_failed` with `param: "min_confidence"`.
</ParamField>

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -fsSL "https://api.vetta.sh/v1/models/auto_select" \
    -H "authorization: Bearer sk_live_..." \
    -H "content-type: application/json" \
    -d '{
      "options": {
        "anthropic/claude-sonnet-4.5": "Routine coding, edits and tool use",
        "openai/gpt-5.6-sol": "Hard multi-step reasoning or architecture",
        "google/gemini-3-flash": "Short factual answers where speed matters"
      },
      "messages": [{ "role": "user", "content": "What year did the Berlin Wall fall?" }],
      "default": "anthropic/claude-sonnet-4.5",
      "min_confidence": 0.5
    }'
  ```

  ```typescript TypeScript theme={"system"}
  const pick = await vetta.models.autoSelect({
    options: {
      "anthropic/claude-sonnet-4.5": "Routine coding, edits and tool use",
      "openai/gpt-5.6-sol": "Hard multi-step reasoning or architecture",
      "google/gemini-3-flash": "Short factual answers where speed matters",
    },
    messages,
    default: "anthropic/claude-sonnet-4.5",
    min_confidence: 0.5,
  });
  // pick.model is a catalogue id — pass it as `model` on the next call.
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={"system"}
  {
    "object": "model_selection",
    "model": "google/gemini-3-flash",
    "confidence": 0.81,
    "probabilities": {
      "anthropic/claude-sonnet-4.5": 0.12,
      "openai/gpt-5.6-sol": 0.07,
      "google/gemini-3-flash": 0.81
    },
    "defaulted": false,
    "spent_micro_usd": 11,
    "usage": { "input_tokens": 210 }
  }
  ```
</ResponseExample>

<ResponseField name="object" type="string">Always `model_selection`.</ResponseField>
<ResponseField name="model" type="string">One of the `options` keys — the id to pass on.</ResponseField>
<ResponseField name="confidence" type="number | null">The selector's probability for its own choice; `null` when it reported no distribution.</ResponseField>
<ResponseField name="probabilities" type="object | null">The full distribution over the `options` keys, or `null`.</ResponseField>
<ResponseField name="defaulted" type="boolean">`true` only when `default` was returned in place of the selector's pick.</ResponseField>
<ResponseField name="spent_micro_usd" type="integer">What this call debited, in micro-USD.</ResponseField>
<ResponseField name="usage.input_tokens" type="integer">The input tokens the selection consumed — the reported count, or the pre-flight estimate the debit was priced from when none was reported.</ResponseField>

**The selection rule.** One choice is asked over `options`, about the conversation, with a fixed question: which option should answer the latest user message, given each option's description.

* Without `min_confidence`, `model` is the selector's choice and `defaulted` is `false`.
* With `min_confidence`, if `confidence` is `null` **or** below the threshold, `model` is `default` and `defaulted` is `true`; `confidence` and `probabilities` still report what the selector said. `default` does nothing without `min_confidence`.
* An answer that is not one of the `options` keys is `internal_error` (500), never a silent default.

**It fails closed.** `default` is a confidence policy, not an outage policy. A deploy with no selector configured answers `feature_not_configured` (501); a selector that cannot be reached answers `rate_limited` (429) or `internal_error` (500), exactly as the model proxy does for an upstream failure. None of those costs anything. A caller who wants "use my default when selection is unavailable" catches the error and does so in their own code.

**What it costs.** An organization-level call like the proxy: no reservation, no session hold, no session or agent id on the entry. The conversation is estimated before the call and the organization's balance must cover the quote, else `insufficient_credits` (402) before any spend. Afterwards **one debit, one `input` line item** — the selector reads and emits nothing billable — booked under this request's id and readable on [`GET /v1/credits/ledger`](/docs/api/credits#ledger). `spent_micro_usd` on the reply is what the ledger actually took. A refused or failed call is not debited.

## Vetta Auto

`vetta/auto` is in the catalogue like any other id, and it picks the model per request. It serves `immediate` only. Because it publishes no rate card of its own, it is quoted against a price ceiling that is enforced upstream — a call that no model can serve within your budget is refused before it runs, never served at a higher price. See [the model router](/docs/concepts/model-router#vetta-auto).

## Errors

| Status  | Code                     | When                                                                                                                                                                                                                                                                                                                                                                                                       |
| ------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **400** | `validation_failed`      | `window` is not one of `immediate\|priority\|loose`. On `auto_select`: an unknown key (`param: "options.<id>"`), fewer than 2 or more than 16 options, more than 32 turns or more than 32000 characters of content (`param: "messages"`), a `default` that is not an option (`param: "default"`), a `min_confidence` with no `default` (`param: "min_confidence"`), or a body key the route does not take. |
| **402** | `insufficient_credits`   | `auto_select`: the balance is below the pre-flight quote. Nothing was spent.                                                                                                                                                                                                                                                                                                                               |
| **404** | `not_found`              | No model with that id — including an id this deploy cannot serve.                                                                                                                                                                                                                                                                                                                                          |
| **429** | `rate_limited`           | `auto_select`: the selector is busy. Retry shortly; nothing was spent.                                                                                                                                                                                                                                                                                                                                     |
| **500** | `internal_error`         | `auto_select`: the selector could not complete the request, or answered something that is not one of your options. Nothing was spent.                                                                                                                                                                                                                                                                      |
| **501** | `feature_not_configured` | This deploy has no inference network configured — an empty list would say "the network publishes no models", which is a different fact. On `auto_select`: this deploy has no selector configured.                                                                                                                                                                                                          |

A transient failure to reach the network answers **500** rather than a stale or empty catalogue. The failed read is not cached, so an immediate retry is the right response to one.

<Card title="Next: the model router" icon="route" href="/docs/concepts/model-router">
  How a call is routed, what the completion window changes, and how tokens are metered.
</Card>
