# Model catalog

> How an LMSP service lists its local models, the model object and its capability flags, the model lifecycle states, stable model ids and catalog revisions.

Source: https://madeforagent.com/lmsp/1.0/models/
Language: en
Specification: LMSP 1.0 (draft)
Updated: 2026-11-08

## 5.1 List models {#list}

```http
GET /lmsp/v1/models?capability=chat&ready_only=false
Authorization: Bearer <token>
```

| Query parameter | Meaning |
| --- | --- |
| `capability` | Return only models that have the named capability, for example `chat`, `embeddings` or `tools`. |
| `ready_only` | When `true`, return only models whose `status` is `ready`. Defaults to `false`. |

```json
{
  "object": "list",
  "catalog_revision": "42",
  "data": [
    {
      "id": "qwen3:14b-q4_k_m",
      "object": "model",
      "display_name": "Qwen3 14B Q4_K_M",
      "owned_by": "local",
      "family": "qwen3",
      "revision": "sha256:8f27c1a4e9b05d36f2a7c8e1b4d90a63c5e2f7b8a1d4c9e60b3f5a7d2c8e1b04",
      "status": "ready",
      "capabilities": {
        "chat": true,
        "completion": true,
        "embeddings": false,
        "tools": true,
        "vision": false,
        "structured_output": true,
        "streaming": true
      },
      "input_modalities": ["text"],
      "output_modalities": ["text"],
      "context_window": 32768,
      "max_output_tokens": 8192,
      "runtime": {
        "backend": "llama.cpp",
        "device": "metal",
        "load_on_demand": true
      }
    }
  ]
}
```

To spare clients from fetching the full catalog again and again, a service **SHOULD** return an `ETag` header, a `catalog_revision` field, or both:

- `catalog_revision` is an opaque string that changes whenever the catalog changes.
- A service that sends `ETag` **SHOULD** answer a matching `If-None-Match` with `304 Not Modified`.

## 5.2 Model object {#object}

| Field | Meaning |
| --- | --- |
| `id` | Stable model identifier, used in every request that names a model. |
| `object` | Always `"model"`. |
| `display_name` | Human-readable name. The user can change it. |
| `aliases` | Optional list of alternative names. They are informational only. |
| `owned_by` | Where the model comes from. `local` for models installed on this device. |
| `family` | Model family, such as `qwen3`. |
| `revision` | Digest of the model content, such as `sha256:8f27...`. |
| `status` | Lifecycle state ([section 5.3](https://madeforagent.com/lmsp/1.0/models.md#lifecycle)). |
| `capabilities` | Boolean flags: `chat`, `completion`, `embeddings`, `tools`, `vision`, `structured_output` and `streaming`. |
| `input_modalities`, `output_modalities` | The kinds of content the model reads and writes. `text` is the only modality defined in 1.0. |
| `context_window` | Maximum number of tokens of context. |
| `max_output_tokens` | Maximum number of tokens in one response. |
| `runtime` | `backend` (for example `llama.cpp`), `device` (for example `metal`) and `load_on_demand`. |
| `error` | Present when `status` is `error`. A problem object ([section 9.3](https://madeforagent.com/lmsp/1.0/common-rules.md#errors)). |

A model `id` **MUST** be stable. The display name and aliases can be changed by the user, so they **MUST NOT** be used as the primary key.

## 5.3 Model lifecycle {#lifecycle}

```text
installed --> loading --> ready --> unloading --> installed
                 |
                 +-----> error
```

| Status | Meaning |
| --- | --- |
| `installed` | The model exists but is not loaded. |
| `loading` | Memory is being allocated or the runtime is initializing. |
| `ready` | The model can process requests immediately. |
| `unloading` | Resources are being released. |
| `error` | Loading failed. The model object **SHOULD** carry a structured error. |

A new load request moves a model in the `error` state back to `loading`.

When a request names a model that is `installed` and its `runtime.load_on_demand` is `true`, the service loads it as part of the request. If the model cannot be used right away and is not loaded on demand, the service answers `409` with `model_not_ready`. If loading fails, the error is `model_load_failed`.

## 5.4 Model operations {#operations}

`GET /lmsp/v1/models/{model_id}` returns one model object. An unknown id gives `404` with `model_not_found`.

Two optional endpoints control loading explicitly. They are available when the `model_management` capability is `true`, and they require the `models:manage` scope ([section 10.3](https://madeforagent.com/lmsp/1.0/security.md#scopes)):

| Endpoint | Behavior |
| --- | --- |
| `POST /lmsp/v1/models/{model_id}/load` | Preloads the model. Returns the model object with `202 Accepted` when loading has started, or `200` when it is already `ready`. |
| `POST /lmsp/v1/models/{model_id}/unload` | Unloads the model. Returns the model object. Repeating the request is harmless. |

Both accept an `Idempotency-Key` ([section 9.2](https://madeforagent.com/lmsp/1.0/common-rules.md#idempotency)).
