# Switch to a cheaper model safely

URL: https://bridge.wekoya.tech/docs/workloads
Updated: 2026-11-08

> A cheaper model can often do your job as well as the one you use now, but your instructions were written for the old one. Bridge tests the cheaper model on…

A cheaper model can often do your job as well as the one you use now, but your instructions were written for the old one. Bridge tests the cheaper model on your own examples, rewrites the instructions until it matches your current results, and tells you plainly whether to switch. In the console this is AI tasks; the API calls them workloads.

#### 1. Say what a good answer is, and add examples
Describe the answer's shape and which fields must be right. Then add real messages your app gets. You don't have to supply the right answers: Bridge can take them from your current model. About 30% of examples are kept for a final check the optimiser never sees.

```
curl https://wekoya-api.wekoya.tech/v1/workloads \
  -H "Authorization: Bearer $WEKOYA_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "name": "WhatsApp orders",
    "monthly_volume": 200000,
    "contract": {
      "output": "json",
      "schema": { "type": "object", "required": ["phone", "items"], "properties": {
        "phone": { "type": "string" },
        "items": { "type": "array", "items": { "type": "object", "properties": {
          "sku": { "type": "string" }, "quantity": { "type": "integer" } } } } } },
      "fields": [
        { "path": "phone", "match": "exact", "critical": true },
        { "path": "items[*].sku", "match": "set", "critical": true }
      ]
    }
  }'

# Then your examples, one per line. "expected" (the right answer) is optional.
curl https://wekoya-api.wekoya.tech/v1/workloads/$TASK/cases \
  -H "Authorization: Bearer $WEKOYA_API_KEY" -H "Content-Type: application/x-ndjson" \
  --data-binary @examples.jsonl
```

```
{"id": "order-1", "slice": "pidgin", "messages": [{"role": "user", "content": "Abeg send 2 carton indomie. 08031234567, I dey Yaba"}]}
{"id": "order-2", "messages": [{"role": "user", "content": "..."}], "expected": {"phone": "+2348031234567", "items": [{"sku": "IND-CTN", "quantity": 2}]}}
```

#### 2. Find a cheaper model
Bridge tries the cheaper model with your instructions as they are, with worked examples, with similar past examples, and with your current model's habits written down (such as "zone is always 'the mainland'"). Then a strong model reads its mistakes and rewrites the instructions. A rewrite is kept only if it does better without breaking what already worked.

```
# Your current setup
curl https://wekoya-api.wekoya.tech/v1/workloads/$TASK/configs \
  -H "Authorization: Bearer $WEKOYA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "label": "Current", "spec": { "model": "gemini-3.8-flash", "instructions": "You process WhatsApp orders..." } }'

# Find a cheaper model (POST .../runs/estimate first tells you the likely cost)
curl https://wekoya-api.wekoya.tech/v1/workloads/$TASK/runs \
  -H "Authorization: Bearer $WEKOYA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "kind": "adapt", "source": { "config_id": "'$SETUP'" },
        "target_models": ["gemini-2.5-flash-lite"], "budget": 2000 }'
```
The result says `switch`, `switch_with_fallback` (your current model answers when the cheaper one's answer is unusable), `keep_current`, or `need_more_cases` with how many more examples would settle it. It shows the cost per answer and per month, and every answer that failed and why. Mark answers right or wrong: your verdicts replace the grader's and teach it your standard.

#### 3. Go live under a name
Your app calls `cfg:<name>` like any model. Bridge checks each answer and fixes broken JSON. If an answer is still unusable, your current model (the backup) answers instead. You can try a new version on a share of traffic and undo with one click, without changing your code.

```
curl https://wekoya-api.wekoya.tech/v1/workloads/$TASK/deployments \
  -H "Authorization: Bearer $WEKOYA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "name": "orders", "config_id": "'$CHEAPER_SETUP'" }'

# Your app uses the name like any model. Tools and streaming work as usual.
reply = client.chat.completions.create(
    model="cfg:orders",
    messages=[{"role": "user", "content": whatsapp_message}],
)
```

- Tools work as on any model. The answer streams word by word when nothing needs checking. Otherwise the checked answer arrives in one piece.
- Automatic checks (optional, with a monthly limit). When a cheaper model appears, Bridge tests it on your task by itself and can try a passing one on a small share of live traffic. If a trial does worse, Bridge stops it within minutes. Making it the main version is always your call.
- Learn from live traffic (optional). When the backup rescues an answer, Bridge keeps that request and answer as an example, so the cheaper model learns from real misses. This stores those requests; otherwise Bridge stores only counts, never content.
- Runs are ordinary requests on your balance, within a spending limit you set. Changing what a live name serves needs an admin.
Why not train a small model on the big one's answers? That needs dedicated capacity per customer, costs far more than the saving for most workloads, and has to be retrained whenever the task changes. Learning from similar examples and live traffic gets most of the benefit with no training.
