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

# Tinker

> Sample from Tinker-trained LoRA checkpoints on Sail with SailTokenCompleter

[Tinker](https://thinkingmachines.ai/tinker) is a training API for fine-tuning open-weight models with LoRA. Sail can run the sampling side of your Tinker training loop: `sail.SailTokenCompleter` is a drop-in [tinker-cookbook](https://github.com/thinking-machines-lab/tinker-cookbook) `TokenCompleter` that samples from your Tinker checkpoints on Sail, with no manual adapter upload step.

Token IDs go in and token IDs come out. The completer sends your prompt token IDs to Sail verbatim and returns sampled token IDs with per-token logprobs, so there is no chat-template or re-tokenization drift between training and sampling. Each call creates a background Responses API request for the [completion window](/completion-windows) you choose (`balanced` by default) and polls it to completion, retrying transient failures with exponential backoff.

We also have a [guide](tinker-rl) on how to use `sail.SailTokenCompleter` in a GRPO-style Tinker training loop.

## Install

```bash theme={null}
pip install sail tinker tinker-cookbook
export SAIL_API_KEY=sk_your_key_here
export TINKER_API_KEY=your_tinker_key
```

## Sample on Sail

`SailTokenCompleter` works anywhere tinker-cookbook expects a `TokenCompleter` (i.e. RL rollouts, evals, or direct calls):

```python theme={null}
import sail
from tinker import types

completer = sail.SailTokenCompleter(
    model="moonshotai/Kimi-K2.6",
    max_tokens=256,
    temperature=0.7,
    completion_window="balanced",
)

prompt = types.ModelInput.from_ints(tokens=tokenizer.encode("Question: 2+2?\nAnswer:"))
result = await completer(prompt, stop=["\n"])

result.tokens          # sampled token IDs
result.maybe_logprobs  # per-token logprobs (None when request_logprobs=False)
result.stop_reason
```

### Parameters

| Parameter                | Default      | Description                                                                                                                                                                                                                                                                                 |
| ------------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model`                  | (required)   | Sail model ID. Must support LoRA serving when a LoRA source is set (see [LoRAs](/loras#supported-base-models)).                                                                                                                                                                             |
| `max_tokens`             | (required)   | Maximum sampled tokens per call.                                                                                                                                                                                                                                                            |
| `temperature`            | `1.0`        | Sampling temperature.                                                                                                                                                                                                                                                                       |
| `top_p`                  | `1.0`        | Nucleus sampling threshold.                                                                                                                                                                                                                                                                 |
| `completion_window`      | `"balanced"` | [Completion window](/completion-windows) for each request. K2.6 LoRA requests use `balanced` by default; `flex` is available for background work and `priority` remains accepted for existing clients. LoRA requests cannot use `asap`; the selected window must be supported by the model. |
| `lora`                   | `None`       | Name or ID of a LoRA [uploaded to Sail](/loras).                                                                                                                                                                                                                                            |
| `tinker_lora_signed_url` | `None`       | Signed Tinker checkpoint archive URL. Mutually exclusive with `lora`.                                                                                                                                                                                                                       |
| `adapter_config`         | `None`       | PEFT `adapter_config.json` contents (dict or JSON string). Required with `tinker_lora_signed_url`.                                                                                                                                                                                          |
| `tinker_lora_name`       | `None`       | Optional label for the Tinker checkpoint.                                                                                                                                                                                                                                                   |
| `metadata`               | `None`       | Extra request metadata merged into each request.                                                                                                                                                                                                                                            |
| `timeout`                | `None`       | Per-HTTP-call timeout in seconds.                                                                                                                                                                                                                                                           |
| `request_logprobs`       | `True`       | Request per-token logprobs with each sample.                                                                                                                                                                                                                                                |

The `stop` argument on the call itself accepts a string, a list of strings, or token IDs, matching the tinker-cookbook `TokenCompleter` contract.

## Sample from a Tinker checkpoint

To sample from a LoRA you are training in Tinker, save sampler weights, resolve a signed archive URL, and pass both the URL and the adapter's PEFT config to the completer. Sail downloads the checkpoint archive and loads the adapter for your requests.

```python theme={null}
import sail

# 1. Save sampler weights for the current step
save_future = await training_client.save_weights_for_sampler_async(
    "rl-step-7",
    ttl_seconds=3600,
)
save_result = await save_future
tinker_path = save_result.path  # tinker://<run-id>/sampler_weights/rl-step-7

# 2. Resolve a signed checkpoint archive URL
signed_url = await sail.get_tinker_checkpoint_signed_url_async(
    service_client,
    tinker_path,
    ttl_seconds=3600,  # optional: set/extend the checkpoint TTL
)

# 3. Sample from the checkpoint on Sail
completer = sail.SailTokenCompleter(
    model="moonshotai/Kimi-K2.6",
    max_tokens=256,
    completion_window="balanced",
    tinker_lora_signed_url=signed_url,
    adapter_config=adapter_config,  # contents of the PEFT adapter_config.json
    tinker_lora_name="rl-step-7",
)
```

`adapter_config` is the PEFT adapter config for the LoRA Tinker is training. The same compatibility rules apply as for [uploaded LoRAs](/loras#adapter-requirements): the base model must match `model`, and the rank must be within the base model's limit.

When `ttl_seconds` is passed to `get_tinker_checkpoint_signed_url_async`, the helper sets the Tinker checkpoint's TTL before resolving the URL, so per-step RL sampler checkpoints are cleaned up automatically instead of accumulating in your Tinker account.

### Using an uploaded LoRA instead

If you have already [uploaded a LoRA to Sail](/loras), pass its name or ID as `lora` instead of a signed URL:

```python theme={null}
completer = sail.SailTokenCompleter(
    model="moonshotai/Kimi-K2.6",
    max_tokens=256,
    completion_window="balanced",
    lora="funnier-v1",
)
```

## Constraints

* **Tinker checkpoints only apply through `SailTokenCompleter`.** The adapter is loaded on Sail's raw-token sampling path. A plain text Responses or Chat Completions request that happens to carry Tinker checkpoint metadata is served by the base model. Sample from Tinker checkpoints only via `SailTokenCompleter`.
* **`lora` and `tinker_lora_signed_url` are mutually exclusive.** Pass one LoRA source per completer.
* **`adapter_config` is required with `tinker_lora_signed_url`.** Sail needs the PEFT config to load the checkpoint weights.
* **`model` must support LoRA serving** when a LoRA source is set (see [supported base models](/loras#supported-base-models)).
* **Kimi K2.6 LoRA requests use `balanced` by default.** `SailTokenCompleter` selects it by default. `flex` is available for background LoRA and Tinker work, and `priority` remains accepted for existing clients. The `asap` completion window is not available for LoRA requests.
* **Signed checkpoint URLs expire.** Resolve a fresh URL for each new checkpoint, and re-resolve if a long-running loop reuses an old one.
* **tinker-cookbook must be installed.** Constructing a `SailTokenCompleter` without it raises an error; the rest of the `sail` SDK works without Tinker packages.
