Skip to main content
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

1

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.
2

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:
POST /{ownerName}/{alias}
Authorization: Key $MODELRUNNER_KEY
Content-Type: application/json

{ "subject": "a fox in a trench coat", "mood": "noir", "base_model": "fal/flux-dev" }
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.
3

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.
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.

Bridging schema differences

Two models rarely name their inputs identically. Say you extend the cinematic-portrait wrapper 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:
{
  "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.
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.

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.
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.