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

# Switching base models

> Put one stable interface in front of several models — pick a default, let callers choose at request time, and bridge schema differences with per-model mappings.

A wrapper can sit on top of **more than one base model**. Callers keep using the same endpoint and the same input fields; behind the scenes the wrapper routes to whichever model is selected. This is what makes a wrapper a durable interface rather than a thin alias for one model.

## Why you'd want it

* **Swap providers without breaking callers.** Migrate from one image model to a newer one by changing the wrapper's default — every integration keeps working untouched.
* **Offer tiers.** Back a "fast" and an "HD" model with one wrapper, and let the caller pick.
* **A/B and hedge.** Route between comparable models without publishing two separate products.

## How selection works

<Steps>
  <Step title="Every wrapper has a default">
    `defaultBaseModelId` is the model used when the caller doesn't ask for a specific one. Make it the safest, most representative option — most calls will land here.
  </Step>

  <Step title="Callers can override with `base_model`">
    To target a non-default model, the caller sends a top-level `base_model` field in the request body set to that model's **endpoint** — its `ownerName/alias`, the same identifier you'd use to call the model directly:

    ```bash theme={null}
    POST /{ownerName}/{alias}
    Authorization: Key $MODELRUNNER_KEY
    Content-Type: application/json

    { "subject": "a fox in a trench coat", "mood": "noir", "base_model": "owner/model-name" }
    ```

    `base_model` is **honored only when the wrapper has more than one base model**, and the endpoint must be one of the wrapper's own base models — otherwise the request is rejected. For a single-model wrapper it's ignored.
  </Step>

  <Step title="Per-model mappings adapt the same input">
    Each base model carries its **own** `fieldMappings`. The caller's input is identical regardless of which model runs; the mappings reconcile it to each model's native schema.
  </Step>
</Steps>

<Warning>
  `base_model` is a **platform-level selector** — never declare it in your wrapper's input `schema`. Callers send it alongside your schema fields; the platform reads it directly.
</Warning>

## Bridging schema differences

Two models rarely name their inputs identically. Say you extend the [cinematic-portrait wrapper](/docs/guides/wrappers/authoring) to a second image model that calls its output count `n` instead of `num_outputs`. You don't change the caller's experience — you add a `rename` to that model's mapping:

```json theme={null}
{
  "defaultBaseModelId": "<model-a-uuid>",
  "baseModels": [
    {
      "baseModelId": "<model-a-uuid>",
      "fieldMappings": {
        "staticValues": { "num_outputs": 1, "output_format": "png" },
        "omit": ["mood"]
      }
    },
    {
      "baseModelId": "<model-b-uuid>",
      "fieldMappings": {
        "staticValues": { "n": 1 },
        "renames": { "output_format": "format" },
        "omit": ["mood"]
      }
    }
  ]
}
```

Same `{ subject, mood }` input, two different downstream payloads — resolved per model. The full set of mapping operations (`collectFields`, `staticValues`, `presets`, `renames`, `omit`) and the order they run in is covered in [build a wrapper](/docs/guides/wrappers/authoring#choosing-what-to-expose).

<Note>
  Two identifiers, two contexts: when **authoring** a wrapper you reference each base model by its `baseModelId` (the model's id), as in the payload above. When **calling** the wrapper, the runtime `base_model` override is the model's `ownerName/alias` **endpoint** — the same string you'd use to call that model directly.
</Note>

## Rules for multi-model wrappers

When you select more than one base model, your wrapper schema has to remain valid for **all** of them:

* **Keep the schema compatible with every model.** Don't expose a field only one model understands unless you can safely `omit` or adapt it for the others.
* **Each model needs its own mappings** that produce only keys that model accepts. Create-time validation checks every produced key against each base model's schema.
* **`image_size` must be a shared subset.** If your wrapper exposes an `image_size` enum, every preset you offer must be supported by *all* selected models — the allowed set is the intersection of what each model supports. Don't advertise a size one of your models can't honor.

<Tip>
  Start with a single base model and get the wrapper working end to end. Add a second model only when there's a real reason for callers to choose — or when you're migrating the default. Fewer models means simpler mappings and fewer compatibility constraints.
</Tip>
