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

# Find a cheaper recipe

> Each month Brussle tests smaller versions of a judgment's context recipe against your outcomes, free, and suggests the one that costs least per answer with no loss your outcomes can see.

The [context recipe](/guides/context-recipes) decides what each answer costs. Once a judgment has enough outcomes, Brussle tests smaller versions of its recipe against them each month at no charge, and suggests the one that costs least per answer with no loss your outcomes can see. Brussle also lists what the recipe can leave out without harm, even when that saves nothing. You decide whether to switch.

The smaller recipes are the second group of the [alternatives table](/calibration/alternatives#read-the-table-and-its-quote), and `recipe-suggestion` shows them too.

## How tuning works

* **When it runs.** A tuning run follows the fit once a version's correction rests on 100 outcomes, with 20 of each kind. After that it runs at most every 30 days, and again after the engine changes.
* **What saves money.** A smaller recipe saves money only where it moves answers into a smaller [size class](/pricing#judgments), since fewer tokens in the same size class cost the same.
* **What it tries.** Each test recipe makes one change to yours: it leaves out one field or one relation, or halves one `last_n`, one `window`, one field's `max_chars` or one relation's `last_n`. Tuning halves a relation's `last_n` only when the relation shows its documents' fields and has no `aggregate` and no `match` on answers or outcomes.
* **How it tests.** The test recipes use the contexts already stored with your labelled answers, sent to the same engine on the same terms, and Brussle compares them with the current recipe on the same outcomes. Brussle skips contexts that sent an image you [erased](/guides/images#erase-an-image).
* **When nothing is cheaper,** the run still tests the recipes and lists those that did no worse in `no_worse`, so even for a recipe already at the smallest size class you see what it can leave out.
* **Cost.** Tuning is never billed. It uses only part of your organization's monthly allowance for free replays, so a refit after the engine changes by itself always has the rest. The [alternatives run](/calibration/alternatives#confirm-a-run), which scores engines and named alternatives, is billed as judging, and the allowance does not stop it.

## Read the suggestion

`GET /namespaces/{ns}/judgments/{name}/recipe-suggestion` (`ns.judgments.recipeSuggestion(name)` in TypeScript, `recipe_suggestion(name)` in Python) returns the last run's result for the active version.

* **`status`**: `ready` when there is a suggestion, `none` when the last run found none, `running`, or `not_run`.

* **`reason`** and **`message`** say why there is no suggestion.

  | `reason` | Means |
  | - | - |
  | `awaiting_run` | The correction is fitted, and the next calibration run starts tuning. |
  | `too_few_outcomes` | No correction yet, or too few labelled answers could be tested. |
  | `no_recipe` | The version sends the whole `state`, so give it a recipe first. |
  | `no_smaller_recipe` | The recipe has nothing to make smaller (a single field, for example). |
  | `nothing_to_save` | Every labelled answer is already a standard judgment, the smallest size class. See `no_worse`. |
  | `no_cheaper_recipe` | No smaller recipe moves enough answers to a smaller size class to be clearly cheaper per answer. See `no_worse`. |
  | `accuracy_would_drop` | Each recipe that was cheap enough did worse on your outcomes, beyond noise. |
  | `cost_cap` | The run stopped at its part of the monthly allowance, and runs again next month. |
  | `superseded` | The engine changed during the run. It runs again once the new engine version has a correction. |
  | `composite`, `inherited` | Composites are not tuned. A template's tenants read the template's suggestion. |

* **`suggestion`**, when `status` is `ready`:
  * `recipe`: the whole new recipe. `removed`: what changed, such as "the field state.internal\_notes".
  * `definition`: the exact body to post as a new version, which is your active version with only `context` changed. It gives no `thresholds`, so your current thresholds stay when you activate it.
  * `cost_per_answer_before` and `cost_per_answer_after`: the mean number of judgments per labelled answer with each recipe, each counted by its size class times the engine's [weight](/pricing#judgments). `unit_reduction` is the part saved. On Jev, `unit_reduction` is 0.75 when answers that were all large (4.0) all become standard (1.0). It is 0.5625 when only three quarters of them do (1.75). On gpt-6-luna the counts are 2.5 times larger, and `unit_reduction` is the same.
  * `held_out`: log loss and accuracy with both recipes, each scored on outcomes that the correction did not see. `interval` is the 95% interval of the change in log loss, where above 0 is worse. A recipe qualifies only when neither log loss nor accuracy is worse beyond noise, and the suggestion is the qualified recipe with the largest `unit_reduction`. Brussle measures each recipe on the labelled answers it could be tested on, so you can compare two recipes' reductions, but not always their cost per answer.
  * `labels`: the labelled answers both recipes were scored on. `engine_version`: the epoch both were judged in.

* **`headline`**: one sentence, such as "A context recipe 75% cheaper per answer, moving answers to a smaller size class, with accuracy unchanged within noise on 312 labelled answers."

* **`no_worse`**: once a run has ended, the other test recipes whose held-out log loss was no worse than yours beyond noise, cheaper or not, with the same fields as `suggestion` but no `engine_version` or `computed_at`. Most save nothing on the bill, but each tells you something the recipe can leave out without a loss your outcomes can see. Accuracy is shown, but it is not part of this test.

* **`computed_at`** and **`next_run_after`**: when the last run ended, and the earliest time the daily calibration run tries again.

## Apply a suggestion

The recipe decides what you send to the engine and which changes make Brussle judge again, so Brussle applies nothing for you and the choice stays yours. Create the version and activate it through its shadow report, as for [any change to a question](/guides/change-a-judgment#change-a-question-safely-with-a-shadow-report).

```python theme={"theme":{"light":"css-variables","dark":"css-variables"}}
found = ns.judgments.recipe_suggestion("material_change")
suggestion = found["suggestion"]
if found["status"] == "ready" and suggestion and suggestion["definition"]:  # definition is null below Team
    created = ns.judgments.create(**suggestion["definition"])
    if "version" in created:
        job = ns.judgments.activate("material_change", version=created["version"])
        # Read job["report"]. Confirm with db.jobs.confirm(job["id"]) once the report looks right.
```

## Run tuning now

`POST /namespaces/{ns}/judgments/{name}/recipe-tuning` (`tuneRecipe`, `tune_recipe`) runs this month's tuning without waiting for the daily calibration run. It returns the result as it is now, which reads `running` until the run ends. Brussle keeps one run for each version, engine epoch and calendar month, so a second request returns the same run. A version that cannot be tuned yet returns `invalid_request` with the reason.

## In the dashboard

The judgment's **Alternatives** tab shows the current recipe and the last tuning run, with its status and reason. When a suggestion is ready, the tab shows what the suggestion changes, the cost per answer before and after, the held-out log loss and accuracy with the interval, and the labels they rest on. After a run it also lists the recipes that were no worse, with what each leaves out and its scores.

**Create version** posts the suggestion's `definition` as a new, inactive version and starts its shadow report on the **Overview**, where you confirm or cancel it. **Run now** starts this month's run.

## Plans

Recipe tuning is on Team and Scale. On Developer, `recipe-suggestion` shows the headline and the numbers but withholds `recipe`, `removed` and `definition` (in `suggestion` and in `no_worse`), with `plan_required` beside them, and `recipe-tuning` returns `plan_required`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.