# Setup Parameters

> Setup parameters configure an app's initialization steps. Modifying these parameters triggers a full restart (re-running setup()).

**URL:** https://inference.sh/docs/apps/setup-parameters
**Last updated:** 2026-10-05

---

Setup parameters configure an app's initialization steps. Modifying these parameters triggers a full restart (re-running `setup()`).

Unlike **input parameters** which change per request, setup parameters control expensive, static resources:

*   Model weights
*   Hardware precision (fp16/fp32)
*   Database connections
*   System prompts or behavior flags

Setup parameters replaced app variants. An app that used to ship a `fast` and a `quality` variant, or several quantizations of one model, now exposes that choice as a setup parameter.

## Defining Setup Parameters

Define an `AppSetup` class in `inference.py`. This schema validates configuration on startup.

```python
from inferencesh import BaseApp, BaseAppInput
from pydantic import Field

class AppSetup(BaseAppInput):
    model_id: str = Field(default="gpt2", description="HuggingFace model ID")
    precision: str = Field(default="fp16", description="Model precision")
    enable_cache: bool = Field(default=True, description="Enable KV cache")

class App(BaseApp):
    async def setup(self, config: AppSetup):
        # Access parameters via config object
        self.model = load_model(
            config.model_id, 
            precision=config.precision
        )
```

## Usage

Provide setup parameters when starting an app. If parameters match an existing running instance for that app, the request executes immediately. If they differ, the instance re-initializes.

### CLI

```bash
belt app run user/app-name --input input.json --setup setup.json
```

### Python SDK

```python
client.run({
    "app": "my-app",
    "setup": {
        "model_id": "meta-llama/Llama-2-7b",
        "precision": "fp16"
    },
    "input": {
        "prompt": "Hello world"
    }
})
```

### REST API

```bash
curl -X POST https://api.inference.sh/apps/run \
  -H "Authorization: Bearer inf_your_key" \
  -H "Content-Type: application/json" \
  -d '{"app": "user/app-name", "setup": {"model_id": "meta-llama/Llama-2-7b"}, "input": {"prompt": "Hello world"}}'
```

### Web app

The app's page shows its setup fields with the inputs, an enum as a dropdown. A run uses the values set there.

### Agents

An app used as an agent tool takes a `setup` block next to its `function`. Every call the agent makes through that tool uses it.

## One app, several models

Give the app one setup field that names the model, with the allowed values as an enum. A run without `setup` gets the default.

```python
from typing import Literal
from inferencesh import BaseApp, BaseAppSetup
from pydantic import Field

MODELS = {
    "small": "org/model-small",
    "base": "org/model-base",
}

class AppSetup(BaseAppSetup):
    model: Literal["small", "base"] = Field(default="base", description="Model size to load")

class App(BaseApp):
    async def setup(self, config: AppSetup):
        self.model = load_model(MODELS[config.model])
```

## How setup values run

*   Each distinct set of setup values runs as its own instance of the app on a worker. Two requests with different values do not share a loaded model.
*   The scheduler prefers a worker that is already running the app with the same setup values. A value no worker has loaded starts cold.
*   Fields the request leaves out take their defaults from `AppSetup`.

## What setup does not change

*   **Resources.** An app has one `resources` block in `inf.yml`, and every setup value runs under it. Size it for the largest configuration. See [Configuration](/docs/extend/configuration#resources).
*   **Price.** Pricing expressions read the task's input and usage, not its setup.

Models that need different amounts of memory, or different prices, are separate apps.
