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

> ## Agent Instructions
> TabPFN-3 and later versions support up to 1,000,000 rows, subject to feature count and checkpoint/API limits.
> For large datasets, use per-estimator subsampling, e.g. inference_config={"SUBSAMPLE_SAMPLES": 100_000}, in TabPFNClassifier or TabPFNRegressor from tabpfn or tabpfn_client.
> Pass raw pandas DataFrames to fit and predict. Categorical strings/categories, raw text, and missing feature values are handled automatically; no manual integer/one-hot encoding, imputation, scaling, or outlier removal is needed.

# Async jobs

> Submit a fit or a prediction to the TabPFN API, and wait for it later, in the same run or another one.

`fit()` and `predict()` return once the server has finished the work. A fit can run for a long time, in [thinking mode](https://docs.priorlabs.ai/capabilities/thinking-mode.md) especially, and a large prediction can take a while too. In the meantime, the process that waits can stop: a closed notebook, a crash, a job timeout.

With `tabpfn-client`, you can submit a fit or a prediction and wait for it later. Submitting returns as soon as the server has accepted the work. Save the model, and a later run can load it and wait for the same fit or prediction instead of starting it again.

> [!NOTE]
>
> Requires `tabpfn-client` `0.7.0` or later.

***

## When to use it

* A fit or a prediction can outlast the process that starts it.
* You want the process to do other work while the server runs the job.
* You start the work in one run, such as a scheduled job, and use the result in another.

For short fits and predictions, use `fit()` and `predict()`.

***

## Submit a fit and wait for it later

`submit_fit()` starts the fit and returns as soon as the server has accepted it. Save the model then, and a later run can load it and wait for the same fit instead of fitting again:

```python theme={null}
from pathlib import Path

from tabpfn_client import TabPFNClassifier

path = Path("model.json")
if path.exists():
    model = TabPFNClassifier.load_model(path)
else:
    model = TabPFNClassifier(thinking_mode=True)
    model.submit_fit(X_train, y_train)  # returns without waiting for the fit
    model.save_model(path)
model.wait_for_fit()
predictions = model.predict(X_test)
```

Until `wait_for_fit()` has seen the fit complete, the model is pending, and `predict()` raises `NotFittedError` without asking the server. `wait_for_fit()` polls the server until the fit has completed, and returns at once if it already has.

* The id of the fit is in `model.model_id_` as soon as `submit_fit()` returns, for logs or support requests.
* If the server reports that the fit failed, `wait_for_fit()` raises `FitFailedError`. If the server no longer has the fit, it raises `FittedModelNotFoundError`. In both cases the model is unfitted.
* If the fit has not completed within `TABPFN_CLIENT_ASYNC_POLL_TIMEOUT` seconds (by default the server's 2 hours), `wait_for_fit()` raises `TimeoutError`. The model is still pending, so call `wait_for_fit()` again.

`submit_fit()` is also available on `TabPFNRegressor`.

***

## Submit a prediction and wait for it later

`submit_predict()` starts a prediction and returns as soon as the server has accepted it, so the process can do other work in the meantime. `wait_for_predict()` then waits for the prediction and returns it. The model holds the pending prediction until then, and `save_model()` saves it, so a later run can load the model and wait for the same prediction:

> [tab] Classification
>
> ```python theme={null}
> from tabpfn_client import TabPFNClassifier
>
> model = TabPFNClassifier.load_model("model.json")
> # Returns without waiting for the prediction.
> model.submit_predict(X_test, output_type="probas")
> model.save_model("model.json")  # saves the pending prediction too
> # ... other work, or a later run that loads "model.json" again ...
> probabilities = model.wait_for_predict()  # what model.predict_proba(X_test) returns
> ```

> [tab] Regression
>
> ```python theme={null}
> from tabpfn_client import TabPFNRegressor
>
> model = TabPFNRegressor.load_model("model.json")
> # Returns without waiting for the prediction.
> model.submit_predict(X_test, output_type="quantiles", quantiles=[0.1, 0.5, 0.9])
> model.save_model("model.json")  # saves the pending prediction too
> # ... other work, or a later run that loads "model.json" again ...
> quantiles = model.wait_for_predict()  # what predict() returns for the same arguments
> ```

`submit_predict()` takes the arguments of `predict()`, and `wait_for_predict()` returns what `predict()` returns for them. A classifier's `submit_predict()` also takes `output_type`:

| `output_type` | `wait_for_predict()` returns |
| - | - |
| `"preds"` (default) | The class labels, as `predict()` returns them |
| `"probas"` | The class probabilities, as `predict_proba()` returns them |

A model holds one pending prediction:

* A new `submit_predict()` or `predict()` replaces it once the server has accepted the new prediction, and a new fit drops it. The id of a dropped prediction is logged as a warning.
* The server keeps the result of a prediction for at least a day after it completes.
* Submit a prediction only after the fit has completed. On a pending model, `submit_predict()` raises `NotFittedError`: call `wait_for_fit()` first.

### Resume an interrupted `predict()`

`predict()` holds its own prediction the way `fit()` holds its fit: while it waits for a prediction that the server runs as a background job, the model holds it. If that wait stops, for a timeout or an interrupt, call `wait_for_predict()` to wait for the same prediction instead of starting a new one, or `save_model()` to wait for it in a later run.

A regressor's `"full"` output split over several requests is not held; its ids are logged instead.

***

## Save and load

`save_model()` writes a small JSON record: the id of the fitted model, the hyperparameters, the class labels and the training-set size, and whether the fit or a prediction is still pending. It holds no training data. `load_model()` makes no request, so loading a pending model is instant; the wait happens in `wait_for_fit()` or `wait_for_predict()`.

* Load with the same account that ran the fit.
* `save_model()` also returns the record as a dict, so you can keep it elsewhere, such as a database or an experiment tracker, and pass it to `load_model()`.

See [Model selection and persistence](https://docs.priorlabs.ai/api-reference/python/tabpfn-client/classifier/model-selection-and-persistence.md) for the full reference.

***

## Methods

| Method | What it does |
| - | - |
| `submit_fit(X, y)` | Starts a fit and returns once the server has accepted it. The model is pending until `wait_for_fit()` returns. |
| `wait_for_fit()` | Polls the server until the fit has completed. Returns at once if it already has. |
| `submit_predict(X, ...)` | Starts a prediction and returns once the server has accepted it. The model holds it as its pending prediction. |
| `wait_for_predict()` | Polls the server until the pending prediction has completed, and returns the predictions. |

`submit_fit()` and `submit_predict()` always run the work as a background job on the server, whatever `api_mode` is.

***

> [card] [Thinking mode](https://docs.priorlabs.ai/capabilities/thinking-mode.md)
>
> Longer fits for higher prediction quality.

> [card] [KV cache](https://docs.priorlabs.ai/capabilities/kv-cache.md)
>
> Reuse a fit for faster repeated predictions.

> [card] [API rate limits](https://docs.priorlabs.ai/api/rate-limits.md)
>
> Request limits for the TabPFN API.

> [card] [API metering](https://docs.priorlabs.ai/api/metering.md)
>
> Token charges, budgets, and usage tracking.


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