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

# SDK reference

> Python SDK API reference

# Client

## Adaptive (Sync)

```python theme={null}
Adaptive(base_url: str, api_key: str | None = None, default_headers: Dict[str, str] | None = None, timeout_secs: float | None = 90.0) -> None
```

Instantiates a new synchronous Adaptive client bounded to a project.

<ParamField body="parameters">
  * **base\_url**: The base URL for the Adaptive API.
  * **api\_key**: API key for authentication.
    Defaults to None, in which case environment variable `ADAPTIVE_API_KEY` needs to be set.
  * **timeout\_secs**: Timeout in seconds for HTTP requests.
    Defaults to 90.0 seconds. Set to None for no timeout.
</ParamField>

## AsyncAdaptive (Async)

```python theme={null}
AsyncAdaptive(base_url: str, api_key: str | None = None, default_headers: Dict[str, str] | None = None, timeout_secs: float | None = 90.0) -> None
```

Instantiates a new asynchronous Adaptive client bounded to a project.

<ParamField body="parameters">
  * **base\_url**: The base URL for the Adaptive API.
  * **api\_key**: API key for authentication.
    Defaults to None, in which case environment variable `ADAPTIVE_API_KEY` needs to be set.
  * **timeout\_secs**: Timeout in seconds for HTTP requests.
    Defaults to 90.0 seconds. Set to None for no timeout.
</ParamField>

***

# Resources

## Ab tests

*Resource to interact with AB Tests.*

Access via `adaptive.ab_tests`

### `cancel`

```python theme={null}
cancel(key: str) -> str
```

Cancel an ongoing AB test.

<ParamField body="parameters">
  * **key**: The AB test key.
</ParamField>

### `create`

```python theme={null}
create(ab_test_key: str, feedback_key: str, models: List[str], traffic_split: float = 1.0, feedback_type: Literal['metric', 'preference'] = 'metric', auto_deploy: bool = False, project: str | None = None) -> AbCampaignCreateData
```

Creates a new A/B test in the client's project.

<ParamField body="parameters">
  * **ab\_test\_key**: A unique key to identify the AB test.
  * **feedback\_key**: The feedback key against which the AB test will run.
  * **models**: The models to include in the AB test; they must be attached to the project.
  * **traffic\_split**: Percentage of production traffic to route to AB test.
    `traffic_split*100` % of inference requests for the project will be sent randomly to one of the models included in the AB test.
  * **feedback\_type**: What type of feedback to run the AB test on, metric or preference.
  * **auto\_deploy**: If set to `True`, when the AB test is completed, the winning model automatically gets promoted to the project default model.
</ParamField>

### `get`

```python theme={null}
get(key: str) -> DescribeAbCampaignAbCampaign | None
```

Get the details of an AB test.

<ParamField body="parameters">
  * **key**: The AB test key.
</ParamField>

### `list`

```python theme={null}
list(active: bool | None = None, status: Literal['warmup', 'in_progress', 'done', 'cancelled'] | None = None, project: str | None = None) -> Sequence[AbCampaignDetailData]
```

List the project AB tests.

<ParamField body="parameters">
  * **active**: Filter on active or inactive AB tests.
  * **status**: Filter on one of the possible AB test status.
  * **project**: Project key. Falls back to client's default if not provided.
</ParamField>

## Artifacts

*Resource to interact with job artifacts.*

Access via `adaptive.artifacts`

### `download`

```python theme={null}
download(artifact_id: str, destination_path: str) -> None
```

Download an artifact file to a local path.

<ParamField body="parameters">
  * **artifact\_id**: The UUID of the artifact to download.
  * **destination\_path**: Local file path where the artifact will be saved.
</ParamField>

## Chat

Access via `adaptive.chat`

### `create`

```python theme={null}
create(messages: List[ChatMessage], stream: bool | None = None, model: str | None = None, stop: List[str] | None = None, max_tokens: int | None = None, temperature: float | None = None, top_p: float | None = None, stream_include_usage: bool | None = None, session_id: str | UUID | None = None, project: str | None = None, user: str | UUID | None = None, ab_campaign: str | None = None, n: int | None = None, labels: Dict[str, str] | None = None, store: bool | None = None) -> ChatResponse | Generator[ChatResponseChunk, None, None]
```

Create a chat completion.

<ParamField body="parameters">
  * **messages**: Input messages, each dict with keys `role` and `content`.
  * **stream**: If `True`, partial message deltas will be returned. If stream is over, chunk.choices will be None.
  * **model**: Target model key for inference. If `None`, the requests will be routed to the project's default model.
  * **stop**: Sequences or where the API will stop generating further tokens.
  * **max\_tokens**: Maximum # of tokens allowed to generate.
  * **temperature**: Sampling temperature.
  * **top\_p**: Threshold for top-p sampling.
  * **stream\_include\_usage**: If set, an additional chunk will be streamed with the token usage statistics for
    the entire request.
  * **session\_id**: Session ID to group related interactions.
  * **project**: Project key. Falls back to client's default if not provided.
  * **user**: ID of user making request. If not `None`, will be logged as metadata for the request.
  * **ab\_campaign**: AB test key. If set, request will be guaranteed to count towards AB test results,
    no matter the configured `traffic_split`.
  * **n**: Number of chat completions to generate for each input messages.
  * **labels**: Key-value pairs of interaction labels.
  * **store**: Whether to store the interaction for future reference. Stores by default.
</ParamField>

Examples:

```
# streaming chat request
stream_response = client.chat.create(
    model="model_key", messages=[{"role": "user", "content": "Hello from SDK"}], stream=True
)

print("Streaming response: ", end="", flush=True)
for chunk in stream_response:
    if chunk.choices:
        content = chunk.choices[0].delta.content
        print(content, end="", flush=True)
```

## Compute pools

*Resource to interact with compute pools.*

Access via `adaptive.compute_pools`

### `list`

```python theme={null}
list()
```

List all compute pools available in the system.

**Returns:** A list of compute pool objects.

### `resize_inference_partition`

```python theme={null}
resize_inference_partition(compute_pool_key: str, size: int) -> list[ResizeResult]
```

Resize the inference partitions of all harmony groups in a compute pool.

## Recipes

*Resource to interact with custom scripts.*

Access via `adaptive.recipes`

### `delete`

```python theme={null}
delete(recipe_key: str, project: str | None = None) -> bool
```

Delete a recipe.

<ParamField body="parameters">
  * **recipe\_key**: The key or ID of the recipe to delete.
  * **project**: Optional project key. Falls back to client's default.
</ParamField>

**Returns:** True if deletion was successful.

### `generate_sample_input`

```python theme={null}
generate_sample_input(recipe_key: str, project: str | None = None) -> dict
```

Generate a sample input dictionary based on the recipe's JSON schema.

<ParamField body="parameters">
  * **recipe\_key**: The key or ID of the recipe.
  * **project**: Optional project key. Falls back to client's default.
</ParamField>

**Returns:** A sample input dictionary conforming to the recipe's schema.

### `get`

```python theme={null}
get(recipe_key: str, project: str | None = None) -> CustomRecipeData | None
```

Get details for a specific recipe.

<ParamField body="parameters">
  * **recipe\_key**: The key or ID of the recipe.
  * **project**: Optional project key. Falls back to client's default.
</ParamField>

**Returns:** The recipe data if found, otherwise None.

### `list`

```python theme={null}
list(project: str | None = None) -> Sequence[CustomRecipeData]
```

List all custom recipes for a project.

<ParamField body="parameters">
  * **project**: Optional project key. Falls back to client's default.
</ParamField>

**Returns:** A sequence of custom recipe data objects.

### `update`

```python theme={null}
update(recipe_key: str, path: str | None = None, entrypoint: str | None = None, entrypoint_config: str | None = None, name: str | None = None, description: str | None = None, labels: Sequence[tuple[str, str]] | None = None, project: str | None = None) -> CustomRecipeData
```

Update an existing recipe.

<ParamField body="parameters">
  * **recipe\_key**: The key of the recipe to update.
  * **path**: Optional new path to a Python file or directory to replace recipe code.
    If None, only metadata (name, description, labels) is updated.
  * **entrypoint**: Optional path to the recipe entrypoint file, relative to the `path` directory.
    **Only applicable when path is a directory.**

  Raises ValueError if:

  * path is a single file (entrypoint not supported for single files)
  * path is a directory that already contains main.py

  Raises FileNotFoundError if:

  * the specified entrypoint file doesn't exist in the directory

  If path is a directory and entrypoint is None:

  * The directory must contain a main.py file, or FileNotFoundError is raised
    * **entrypoint\_config**: Optional path to a separate config file that specifies the InputConfig for the recipe entrypoint.
      **Only applicable when path is a directory.**

  Raises ValueError if:

  * path is a single file (entrypoint\_config not supported for single files)
  * path is a directory that already contains config.py

  Raises FileNotFoundError if:

  * the specified entrypoint\_config file doesn't exist in the directory

  If path is a directory and entrypoint\_config is None:

  * If entrypoint is specified, the InputConfig should be included in it.
  * If entrypoint is not specified, main.py should contain the InputConfig, or a config.py file must be present.
    * **name**: Optional new display name.
    * **description**: Optional new description.
    * **labels**: Optional new key-value labels as tuples of (key, value).
    * **project**: Optional project key. Falls back to client's default.
</ParamField>

**Returns:** The updated recipe data.

### `upload`

```python theme={null}
upload(path: str, recipe_key: str | None = None, entrypoint: str | None = None, entrypoint_config: str | None = None, name: str | None = None, description: str | None = None, labels: dict[str, str] | None = None, project: str | None = None) -> CustomRecipeData
```

Upload a recipe from either a single Python file or a directory (path).

<ParamField body="parameters">
  * **path**: Path to a Python file or directory containing the recipe.
  * **recipe\_key**: Optional unique key for the recipe. If not provided, inferred from:
  * File name (without .py) if path is a file
  * "dir\_name/entrypoint\_name" if path is a directory and custom entrypoint is specified
  * Directory name if path is a directory and no custom entrypoint is specified
    * **entrypoint**: Optional path to the recipe entrypoint file, relative to the `path` directory.
      **Only applicable when path is a directory.**

  Raises ValueError if:

  * path is a single file (entrypoint not supported for single files)
  * path is a directory that already contains main.py

  Raises FileNotFoundError if:

  * the specified entrypoint file doesn't exist in the directory

  If path is a directory and entrypoint is None:

  * The directory must contain a main.py file, or FileNotFoundError is raised
    * **entrypoint\_config**: Optional path to a separate config file that specifies the InputConfig for the recipe entrypoint.
      **Only applicable when path is a directory.**

  Raises ValueError if:

  * path is a single file (entrypoint\_config not supported for single files)
  * path is a directory that already contains config.py

  Raises FileNotFoundError if:

  * the specified entrypoint\_config file doesn't exist in the directory

  If path is a directory and entrypoint\_config is None:

  * If entrypoint is specified, the InputConfig should be included in it.
  * If entrypoint is not specified, main.py should contain the InputConfig, or a config.py file must be present.
    * **name**: Optional display name for the recipe.
    * **description**: Optional description.
    * **labels**: Optional key-value labels.
    * **project**: Optional project identifier.
</ParamField>

### `upsert`

```python theme={null}
upsert(path: str, recipe_key: str | None = None, entrypoint: str | None = None, entrypoint_config: str | None = None, name: str | None = None, description: str | None = None, labels: dict[str, str] | None = None, project: str | None = None) -> CustomRecipeData
```

Upload a recipe if it doesn't exist, or update it if it does.

<ParamField body="parameters">
  * **path**: Path to a Python file or directory containing the recipe.
  * **recipe\_key**: Optional unique key for the recipe. If not provided, inferred from:
  * File name (without .py) if path is a file
  * "dir\_name/entrypoint\_name" if path is a directory and custom entrypoint is specified
  * Directory name if path is a directory and no custom entrypoint is specified
    * **entrypoint**: Optional path to the recipe entrypoint file, relative to the `path` directory.
      **Only applicable when path is a directory.**

  Raises ValueError if:

  * path is a single file (entrypoint not supported for single files)
  * path is a directory that already contains main.py

  Raises FileNotFoundError if:

  * the specified entrypoint file doesn't exist in the directory

  If path is a directory and entrypoint is None:

  * The directory must contain a main.py file, or FileNotFoundError is raised
    * **entrypoint\_config**: Optional path to a separate config file that specifies the InputConfig for the recipe entrypoint.
      **Only applicable when path is a directory.**

  Raises ValueError if:

  * path is a single file (entrypoint\_config not supported for single files)
  * path is a directory that already contains config.py

  Raises FileNotFoundError if:

  * the specified entrypoint\_config file doesn't exist in the directory

  If path is a directory and entrypoint\_config is None:

  * If entrypoint is specified, the InputConfig should be included in it.
  * If entrypoint is not specified, main.py should contain the InputConfig, or a config.py file must be present.
    * **name**: Optional display name for the recipe.
    * **description**: Optional description.
    * **labels**: Optional key-value labels.
    * **project**: Optional project identifier, falls back to client's default if it is set.
</ParamField>

**Returns:** The created or updated recipe data.

## Datasets

*Resource to interact with file datasets.*

Access via `adaptive.datasets`

### `delete`

```python theme={null}
delete(key: str, project: str | None = None) -> bool
```

Delete dataset.

### `get`

```python theme={null}
get(key: str, project: str | None = None) -> DatasetData | None
```

Get details for dataset.

<ParamField body="parameters">
  * **key**: Dataset key.
</ParamField>

### `list`

```python theme={null}
list(project: str | None = None) -> List[ListDatasetsDatasets]
```

List previously uploaded datasets.

### `upload`

```python theme={null}
upload(file_path: str, dataset_key: str, name: str | None = None, project: str | None = None) -> DatasetData
```

Upload a dataset from a file. File must be jsonl, where each line should match supported structure.

<ParamField body="parameters">
  * **file\_path**: Path to jsonl file.
  * **dataset\_key**: New dataset key.
  * **name**: Optional name to render in UI; if `None`, defaults to same as `dataset_key`.
</ParamField>

## Embeddings

*Resource to interact with embeddings.*

Access via `adaptive.embeddings`

### `create`

```python theme={null}
create(input: str, model: str | None = None, encoding_format: Literal['Float', 'Base64'] = 'Float', project: str | None = None, user: str | UUID | None = None) -> EmbeddingsResponseList
```

Creates embeddings inference request.

<ParamField body="parameters">
  * **input**: Input text to embed.
  * **model**: Target model key for inference. If `None`, the requests will be routed to the project's default model.
    Request will error if default model is not an embedding model.
  * **encoding\_format**: Encoding format of response.
  * **user**: ID of user making the requests. If not `None`, will be logged as metadata for the request.
</ParamField>

## Graders

*Resource to interact with grader definitions used to evaluate model completions.*

Access via `adaptive.graders`

### `delete`

```python theme={null}
delete(grader_key: str, project: str | None = None) -> bool
```

Delete a grader. Returns True on success.

### `get`

```python theme={null}
get(grader_key: str, project: str | None = None) -> GraderData | None
```

Retrieve a specific grader by ID or key.

### `list`

```python theme={null}
list(project: str | None = None) -> Sequence[GraderData]
```

List all graders for the given project.

### `lock`

```python theme={null}
lock(grader_key: str, locked: bool, project: str | None = None) -> GraderData
```

Lock or unlock a grader.

<ParamField body="parameters">
  * **grader\_key**: ID or key of the grader.
  * **locked**: Whether to lock (True) or unlock (False) the grader.
  * **project**: Explicit project key. Falls back to client.default\_project.
</ParamField>

### `test_external_endpoint`

```python theme={null}
test_external_endpoint(url: str) -> TestRemoteEnvTestRemoteEnvRemoteEnvTestOnline | TestRemoteEnvTestRemoteEnvRemoteEnvTestOffline
```

Test external endpoint to check if it is reachable from Adaptive and returns a valid response.

## Integrations

*Resource to manage integrations and notification subscriptions.*

Access via `adaptive.integrations`

### `create`

```python theme={null}
create(team: str, name: str, provider: Literal['slack', 'smtp', 'webhook', 'github'], connection: ConnectionConfigInputSlack | ConnectionConfigInputSmtp | ConnectionConfigInputWebhook | ConnectionConfigInputGitHub, subscriptions: Optional[List[SubscriptionInput]] = None, delivery_policy: Literal['multishot', 'singleshot'] | None = None) -> CreateIntegrationCreateIntegration
```

Create a new integration.

<ParamField body="parameters">
  * **team**: Team ID or key.
  * **name**: Human-readable name for the integration.
  * **provider**: Provider name.
  * **connection**: Connection config. Use one of:
  * `ConnectionConfigInputSlack(webhook_url=..., bot_token=...)`
  * `ConnectionConfigInputSmtp(host=..., port=..., username=..., password=..., from_email=..., to_emails=[...])`
  * `ConnectionConfigInputWebhook(url=..., method=..., headers=...)`
  * `ConnectionConfigInputGitHub(api_token=..., org=..., repo=...)`
    * **subscriptions**: Optional list of `SubscriptionInput` notification subscriptions.
    * **delivery\_policy**: Delivery policy, either `"multishot"` or `"singleshot"`.
</ParamField>

**Returns:** The created integration data.

### `delete`

```python theme={null}
delete(id: str) -> bool
```

Delete an integration.

<ParamField body="parameters">
  * **id**: Integration UUID.
</ParamField>

**Returns:** True if the integration was deleted.

### `get`

```python theme={null}
get(id: str) -> Optional[DescribeIntegrationIntegration]
```

Get a specific integration by ID.

<ParamField body="parameters">
  * **id**: Integration UUID.
</ParamField>

**Returns:** The integration data, or None if not found.

### `get_provider`

```python theme={null}
get_provider(name: str) -> Optional[DescribeProviderProvider]
```

Get a specific provider by name.

<ParamField body="parameters">
  * **name**: Provider name.
</ParamField>

**Returns:** The provider data, or None if not found.

### `list`

```python theme={null}
list(team: str) -> List[ListIntegrationsIntegrations]
```

List integrations for a team.

<ParamField body="parameters">
  * **team**: Team ID or key.
</ParamField>

**Returns:** A list of integration objects.

### `list_providers`

```python theme={null}
list_providers() -> List[ListProvidersProviders]
```

List available integration providers.

**Returns:** A list of provider objects.

### `test_notification`

```python theme={null}
test_notification(topic: str, payload: NotificationPayload, scope_user: Optional[List[str]] = None, scope_team: Optional[str] = None, scope_organization: bool = False, scope_admin: bool = False) -> TestNotificationTestNotification
```

Test notification delivery.

<ParamField body="parameters">
  * **topic**: Notification topic string.
  * **payload**: Notification payload, e.g. `NotificationPayload(job_update=JobUpdatePayload(...))`.
  * **scope\_user**: List of user UUIDs to scope the notification to.
  * **scope\_team**: Team ID or key to scope the notification to.
  * **scope\_organization**: If True, scope the notification to the organization.
  * **scope\_admin**: If True, scope the notification to admins.
</ParamField>

**Returns:** The test notification result with eventId and message.

### `update`

```python theme={null}
update(id: str, name: Optional[str] = None, enabled: Optional[bool] = None, connection: ConnectionConfigInputSlack | ConnectionConfigInputSmtp | ConnectionConfigInputWebhook | ConnectionConfigInputGitHub | None = None, subscriptions: Optional[List[SubscriptionInput]] = None, delivery_policy: Literal['multishot', 'singleshot'] | None = None) -> UpdateIntegrationUpdateIntegration
```

Update an existing integration.

<ParamField body="parameters">
  * **id**: Integration UUID.
  * **name**: New name for the integration.
  * **enabled**: Enable or disable the integration.
  * **connection**: Updated connection config. See `create()` for the available types.
  * **subscriptions**: Updated list of `SubscriptionInput` notification subscriptions.
  * **delivery\_policy**: Updated delivery policy, either `"multishot"` or `"singleshot"`.
</ParamField>

**Returns:** The updated integration data.

## Jobs

*Resource to interact with jobs.*

Access via `adaptive.jobs`

### `cancel`

```python theme={null}
cancel(job_id: str) -> JobDataPlus
```

Cancel a running job.

<ParamField body="parameters">
  * **job\_id**: The ID of the job to cancel.
</ParamField>

**Returns:** The updated job data after cancellation.

### `get`

```python theme={null}
get(job_id: str) -> JobDataPlus | None
```

Get the details of a specific job.

<ParamField body="parameters">
  * **job\_id**: The ID of the job to retrieve.
</ParamField>

**Returns:** The job data if found, otherwise None.

### `list`

```python theme={null}
list(first: int | None = 100, last: int | None = None, after: str | None = None, before: str | None = None, kind: list[Literal['TRAINING', 'EVALUATION', 'DATASET_GENERATION', 'MODEL_CONVERSION', 'CUSTOM']] | None = None, project: str | None = None) -> ListJobsJobs
```

List jobs with pagination and filtering options.

<ParamField body="parameters">
  * **first**: Number of jobs to return from the beginning.
  * **last**: Number of jobs to return from the end.
  * **after**: Cursor for forward pagination.
  * **before**: Cursor for backward pagination.
  * **kind**: Filter by job types.
  * **project**: Filter by project key.
</ParamField>

**Returns:** A paginated list of jobs.

### `run`

```python theme={null}
run(recipe_key: str, num_gpus: int, args: dict[str, Any] | None = None, name: str | None = None, project: str | None = None, compute_pool: str | None = None) -> JobDataPlus
```

Run a job using a specified recipe.

<ParamField body="parameters">
  * **recipe\_key**: The key of the recipe to run.
  * **num\_gpus**: Number of GPUs to allocate for the job.
  * **args**: Optional arguments to pass to the recipe; must match the recipe schema.
  * **name**: Optional human-readable name for the job.
  * **project**: Project key for the job.
  * **compute\_pool**: Optional compute pool key to run the job on.
</ParamField>

**Returns:** The created job data.

## Feedback

*Resource to interact with and log feedback.*

Access via `adaptive.feedback`

### `get_key`

```python theme={null}
get_key(project: str, feedback_key: str) -> MetricData | None
```

Get the details of a feedback key.

<ParamField body="parameters">
  * **feedback\_key**: The feedback key.
</ParamField>

return self.\_gql\_client.describe\_metric(input=feedback\_key).metric

### `list_keys`

```python theme={null}
list_keys() -> Sequence[MetricDataAdmin]
```

List all feedback keys.

### `log_metric`

```python theme={null}
log_metric(value: bool | float | int, completion_id: str | UUID, feedback_key: str, user: str | UUID | None = None, details: str | None = None) -> FeedbackOutput
```

Log metric feedback for a single completion, which can be a float, int or bool depending on the kind of `feedback_key` it is logged against.

<ParamField body="parameters">
  * **value**: The feedback values.
  * **completion\_id**: The completion\_id to attach the feedback to.
  * **feedback\_key**: The feedback key to log against.
  * **user**: ID of user submitting feedback. If not `None`, will be logged as metadata for the request.
  * **details**: Textual details for the feedback. Can be used to provide further context on the feedback `value`.
</ParamField>

### `log_preference`

```python theme={null}
log_preference(feedback_key: str, preferred_completion: str | UUID | ComparisonCompletion, other_completion: str | UUID | ComparisonCompletion, user: str | UUID | None = None, messages: List[Dict[str, str]] | None = None, tied: Literal['good', 'bad'] | None = None, project: str | None = None) -> ComparisonOutput
```

Log preference feedback between 2 completions.

<ParamField body="parameters">
  * **feedback\_key**: The feedback key to log against.
  * **preferred\_completion**: Can be a completion\_id or a dict with keys `model` and `text`,
    corresponding the a valid model key and its attributed completion.
  * **other\_completion**: Can be a completion\_id or a dict with keys `model` and `text`,
    corresponding the a valid model key and its attributed completion.
  * **user**: ID of user submitting feedback.
  * **messages**: Input chat messages, each dict with keys `role` and `content`.
    Ignored if `preferred_` and `other_completion` are completion\_ids.
  * **tied**: Indicator if both completions tied as equally bad or equally good.
</ParamField>

### `register_key`

```python theme={null}
register_key(project: str, key: str, kind: Literal['scalar', 'bool'], scoring_type: Literal['higher_is_better', 'lower_is_better'] = 'higher_is_better', name: str | None = None, description: str | None = None) -> MetricData
```

Register a new feedback key. Feedback can be logged against this key once it is created.

<ParamField body="parameters">
  * **key**: Feedback key.
  * **kind**: Feedback kind.
    If `"bool"`, you can log values `0`, `1`, `True` or `False` only.
    If `"scalar"`, you can log any integer or float value.
  * **scoring\_type**: Indication of what good means for this feedback key; a higher numeric value (or `True`)
    , or a lower numeric value (or `False`).
  * **name**: Human-readable feedback name that will render in the UI. If `None`, will be the same as `key`.
  * **description**: Description of intended purpose or nuances of feedback. Will render in the UI.
</ParamField>

## Interactions

*Resource to interact with interactions.*

Access via `adaptive.interactions`

### `create`

```python theme={null}
create(messages: List[ChatMessage], completion: str, model: str | None = None, feedbacks: List[InteractionFeedbackDict] | None = None, user: str | UUID | None = None, session_id: str | UUID | None = None, project: str | None = None, ab_campaign: str | None = None, labels: Dict[str, str] | None = None, created_at: str | None = None) -> AddInteractionsResponse
```

Create/log an interaction.

<ParamField body="parameters">
  * **messages**: Input chat messages, each dict should have keys `role` and `content`.
  * **completion**: Model completion.
  * **model**: Model key.
  * **feedbacks**: List of feedbacks, each dict should with keys `feedback_key`, `value` and optional(`details`).
  * **user**: ID of user making the request. If not `None`, will be logged as metadata for the interaction.
  * **session\_id**: Session ID to group related interactions.
  * **project**: Project key. Falls back to client's default if not provided.
  * **ab\_campaign**: AB test key. If set, provided `feedbacks` will count towards AB test results.
  * **labels**: Key-value pairs of interaction labels.
  * **created\_at**: Timestamp of interaction creation or ingestion.
</ParamField>

### `get`

```python theme={null}
get(completion_id: str, project: str | None = None) -> CompletionData | None
```

Get the details for one specific interaction.

<ParamField body="parameters">
  * **completion\_id**: The ID of the completion.
</ParamField>

### `list`

```python theme={null}
list(order: List[Order] | None = None, filters: ListCompletionsFilterInput | None = None, page: CursorPageInput | None = None, group_by: Literal['model', 'prompt'] | None = None, project: str | None = None) -> ListInteractionsCompletions | ListGroupedInteractionsCompletionsGrouped
```

List interactions in client's project.

<ParamField body="parameters">
  * **order**: Ordering of results.
  * **filters**: List filters.
  * **page**: Paging config.
  * **group\_by**: Retrieve interactions grouped by selected dimension.
</ParamField>

## Models

*Resource to interact with models.*

Access via `adaptive.models`

### `add_external`

```python theme={null}
add_external(name: str, external_model_id: str, api_key: str, provider: Literal['open_ai', 'google', 'azure'], endpoint: str | None = None, extra_params: dict[str, Any] | None = None) -> ModelData
```

Add proprietary external model to Adaptive model registry.

<ParamField body="parameters">
  * **name**: Adaptive name for the new model.
  * **external\_model\_id**: Should match the model id publicly shared by the model provider.
  * **api\_key**: API Key for authentication against external model provider.
  * **provider**: External proprietary model provider.
  * **extra\_params**: Additional provider-specific parameters (supported for open\_ai and azure).
</ParamField>

### `add_hf_model`

```python theme={null}
add_hf_model(hf_model_id: SupportedHFModels, output_model_name: str, output_model_key: str, hf_token: str, compute_pool: str | None = None) -> JobData
```

Add model from the HuggingFace Model hub to Adaptive model registry.
It will take several minutes for the model to be downloaded and converted to Adaptive format.

<ParamField body="parameters">
  * **hf\_model\_id**: The ID of the selected model repo on HuggingFace Model Hub.
  * **output\_model\_key**: The key that will identify the new model in Adaptive.
  * **hf\_token**: Your HuggingFace Token, needed to validate access to gated/restricted model.
</ParamField>

### `add_to_project`

```python theme={null}
add_to_project(model: str, project: str | None = None) -> bool
```

Attach a model to the client's project.

<ParamField body="parameters">
  * **model**: Model key.
  * **project**: Project key. Falls back to client's default if not provided.
</ParamField>

**Returns:** True if the model was successfully attached.

### `attach`

```python theme={null}
attach(model: str, wait: bool = False, make_default: bool = False, project: str | None = None, placement: ModelPlacementInput | None = None, num_draft_steps: int | None = None) -> ModelServiceData
```

Attach a model to the client's project.

<ParamField body="parameters">
  * **model**: Model key.
  * **wait**: If the model is not deployed already, attaching it to the project will automatically deploy it.
    If `True`, this call blocks until model is `Online`.
  * **make\_default**: Make the model the project's default on attachment.
  * **num\_draft\_steps**: Optional number of speculative decoding draft steps.
</ParamField>

### `deploy`

```python theme={null}
deploy(model: str, wait: bool = False, make_default: bool = False, project: str | None = None, placement: ModelPlacementInput | None = None, num_draft_steps: int | None = None) -> ModelServiceData
```

Deploy a model for inference in the specified project.

<ParamField body="parameters">
  * **model**: Model key.
  * **wait**: If `True`, block until the model is online.
  * **make\_default**: Make the model the project's default after deployment.
  * **project**: Project key.
  * **placement**: Optional placement configuration for the model.
  * **num\_draft\_steps**: Optional number of speculative decoding draft steps.
</ParamField>

**Returns:** The model service data after deployment.

### `detach`

```python theme={null}
detach(model: str, project: str) -> bool
```

Detach model from client's project.

<ParamField body="parameters">
  * **model**: Model key.
</ParamField>

### `get`

```python theme={null}
get(model) -> ModelData | None
```

Get the details for a model.

<ParamField body="parameters">
  * **model**: Model key.
</ParamField>

### `list`

```python theme={null}
list(filter: ModelFilter | None = None) -> Sequence[ListModelsModels]
```

List all models in Adaptive model registry.

### `terminate`

```python theme={null}
terminate(model: str, force: bool = False) -> str
```

Terminate model, removing it from memory and making it unavailable to all projects.

<ParamField body="parameters">
  * **model**: Model key.
  * **force**: If model is attached to several projects, `force` must equal `True` in order
    for the model to be terminated.
</ParamField>

### `update`

```python theme={null}
update(model: str, is_default: bool | None = None, desired_online: bool | None = None, project: str | None = None, placement: ModelPlacementInput | None = None, num_draft_steps: int | None = None) -> ModelServiceData
```

Update config of model attached to client's project.

<ParamField body="parameters">
  * **model**: Model key.
  * **is\_default**: Change the selection of the model as default for the project.
    `True` to promote to default, `False` to demote from default. If `None`, no changes are applied.
  * **attached**: Whether model should be attached or detached to/from project. If `None`, no changes are applied.
  * **desired\_online**: Turn model inference on or off for the client project.
    This does not influence the global status of the model, it is project-bounded.
    If `None`, no changes are applied.
  * **num\_draft\_steps**: Optional number of speculative decoding draft steps.
</ParamField>

### `update_compute_config`

```python theme={null}
update_compute_config(model: str, compute_config: ModelComputeConfigInput) -> ModelData
```

Update compute config of model.

## Permissions

*Resource to list permissions.*

Access via `adaptive.permissions`

### `list`

```python theme={null}
list() -> List[str]
```

List all available permissions in the system.

**Returns:** A list of permission identifiers.

## Roles

*Resource to manage roles.*

Access via `adaptive.roles`

### `create`

```python theme={null}
create(key: str, permissions: List[str], name: str | None = None) -> CreateRoleCreateRole
```

Creates new role.

<ParamField body="parameters">
  * **key**: Role key.
  * **permissions**: List of permission identifiers such as `project:read`. You can list all possible permissions with client.permissions.list().
  * **name**: Role name; if not provided, defaults to `key`.
</ParamField>

### `list`

```python theme={null}
list() -> List[ListRolesRoles]
```

List all roles.

**Returns:** A list of role objects.

## Teams

*Resource to manage teams.*

Access via `adaptive.teams`

### `create`

```python theme={null}
create(key: str, name: str | None = None) -> CreateTeamCreateTeam
```

Create a new team.

<ParamField body="parameters">
  * **key**: Unique key for the team.
  * **name**: Human-readable team name. If not provided, defaults to key.
</ParamField>

**Returns:** The created team data.

### `list`

```python theme={null}
list() -> List[ListTeamsTeams]
```

List all teams.

**Returns:** A list of team objects.

## Projects

*Resource to interact with projects.*

Access via `adaptive.projects`

### `create`

```python theme={null}
create(key: str, name: str | None = None, description: str | None = None, team: str | None = None) -> ProjectData
```

Create new project.

<ParamField body="parameters">
  * **key**: Project key.
  * **name**: Human-readable project name which will be rendered in the UI.
    If not set, will be the same as `key`.
  * **description**: Description of model which will be rendered in the UI.
</ParamField>

### `get`

```python theme={null}
get(project: str | None = None) -> ProjectData | None
```

Get details for the client's project.

### `list`

```python theme={null}
list() -> Sequence[ProjectData]
```

List all projects.

### `share`

```python theme={null}
share(project: str, team: str, role: str, is_owner: bool = False) -> ProjectData | None
```

Share project with another team.
Requires project:share permissions on the target project.

<ParamField body="parameters">
  * **project**: Project key.
  * **team**: Team key.
  * **role**: Role key.
</ParamField>

### `unshare`

```python theme={null}
unshare(project: str, team: str) -> ProjectData | None
```

Remove project access for a team.
Requires project:share permissions on the target project.

<ParamField body="parameters">
  * **project**: Project key.
  * **team**: Team key.
</ParamField>

## Users

*Resource to manage users and permissions.*

Access via `adaptive.users`

### `add_to_team`

```python theme={null}
add_to_team(email: str, team: str, role: str) -> UpdateUserSetTeamMember
```

Update team and role for user.

<ParamField body="parameters">
  * **email**: User email.
  * **team**: Key of team to which user will be added to.
  * **role**: Assigned role
</ParamField>

### `create`

```python theme={null}
create(email: str, name: str, teams_with_role: Sequence[tuple[str, str]]) -> UserData
```

Create a user with preset teams and roles.

<ParamField body="parameters">
  * **email**: User's email address.
  * **name**: User's display name.
  * **teams\_with\_role**: Sequence of (team\_key, role\_key) tuples assigning the user to teams with specific roles.
</ParamField>

**Returns:** The created user data.

### `create_service_account`

```python theme={null}
create_service_account(name: str, teams_with_role: Sequence[tuple[str, str]]) -> ServiceAccountCreateResult
```

Create a service account (system user) with an API key.

Service accounts authenticate via API keys only (no OIDC login).
The API key is returned once and cannot be retrieved later.

<ParamField body="parameters">
  * **name**: Account name. Must contain only lowercase letters (a-z), numbers, hyphens, and underscores.
  * **teams\_with\_role**: Sequence of (team\_key, role\_key) tuples.
</ParamField>

**Returns:** ServiceAccountCreateResult with user\_id, email, and api\_key.

### `delete`

```python theme={null}
delete(email: str)
```

Delete a user from the system.

<ParamField body="parameters">
  * **email**: The email address of the user to delete.
</ParamField>

### `list`

```python theme={null}
list() -> Sequence[UserData]
```

List all users registered to Adaptive deployment.

### `me`

```python theme={null}
me() -> UserData | None
```

Get details of current user.

### `remove_from_team`

```python theme={null}
remove_from_team(email: str, team: str) -> UserData
```

Remove user from team.

<ParamField body="parameters">
  * **email**: User email.
  * **team**: Key of team to remove user from.
</ParamField>

***

# Types

### ChatMessage

| Field     | Type                                               |
| --------- | -------------------------------------------------- |
| `role`    | `Required[Literal['system', 'user', 'assistant']]` |
| `content` | `Required[str]`                                    |

### ComparisonCompletion

| Field   | Type            |
| ------- | --------------- |
| `text`  | `Required[str]` |
| `model` | `Required[str]` |

### CompletionComparisonFilterInput

| Field    | Type            |
| -------- | --------------- |
| `metric` | `Required[str]` |

### CompletionFeedbackFilterInput

| Field     | Type                            |
| --------- | ------------------------------- |
| `metric`  | `Required[str]`                 |
| `value`   | `NotRequired[NumericCondition]` |
| `reasons` | `NotRequired[List[str]]`        |
| `user`    | `NotRequired[Any]`              |

### CompletionLabelFilter

| Field   | Type                     |
| ------- | ------------------------ |
| `key`   | `Required[str]`          |
| `value` | `NotRequired[List[str]]` |

### CursorPageInput

| Field    | Type               |
| -------- | ------------------ |
| `first`  | `NotRequired[int]` |
| `after`  | `NotRequired[str]` |
| `before` | `NotRequired[str]` |
| `last`   | `NotRequired[int]` |

### InteractionFeedbackDict

| Field          | Type               |       |         |
| -------------- | ------------------ | ----- | ------- |
| `feedback_key` | `Required[str]`    |       |         |
| `value`        | \`Required\[int    | float | bool]\` |
| `details`      | `NotRequired[str]` |       |         |

### JudgeExampleInput

| Field       | Type                          |
| ----------- | ----------------------------- |
| `input`     | `Required[List[ChatMessage]]` |
| `output`    | `Required[str]`               |
| `passes`    | `Required[bool]`              |
| `reasoning` | `Required[str]`               |

### ListCompletionsFilterInput

| Field           | Type                                                   |
| --------------- | ------------------------------------------------------ |
| `models`        | `NotRequired[List[str]]`                               |
| `timerange`     | `NotRequired['TimeRange']`                             |
| `session_id`    | `NotRequired[Any]`                                     |
| `user_id`       | `NotRequired[Any]`                                     |
| `feedbacks`     | `NotRequired[List['CompletionFeedbackFilterInput']]`   |
| `comparisons`   | `NotRequired[List['CompletionComparisonFilterInput']]` |
| `labels`        | `NotRequired[List['CompletionLabelFilter']]`           |
| `prompt_hash`   | `NotRequired[str]`                                     |
| `completion_id` | `NotRequired[Any]`                                     |
| `source`        | `NotRequired[List[CompletionSource]]`                  |

### ModelComputeConfigInput

| Field          | Type               |
| -------------- | ------------------ |
| `tp`           | `NotRequired[int]` |
| `kv_cache_len` | `NotRequired[int]` |
| `max_seq_len`  | `NotRequired[int]` |

### ModelFilter

| Field        | Type                                                                  |
| ------------ | --------------------------------------------------------------------- |
| `in_storage` | `NotRequired[bool]`                                                   |
| `available`  | `NotRequired[bool]`                                                   |
| `trainable`  | `NotRequired[bool]`                                                   |
| `kind`       | `NotRequired[List[Literal['Embedding', 'Generation']]]`               |
| `view_all`   | `NotRequired[bool]`                                                   |
| `online`     | `NotRequired[List[Literal['ONLINE', 'OFFLINE', 'PENDING', 'ERROR']]]` |

### ModelPlacementInput

| Field           | Type                  |
| --------------- | --------------------- |
| `compute_pools` | `Required[List[str]]` |
| `max_ttft_ms`   | `NotRequired[int]`    |

### NumericCondition

| Field | Type                 |
| ----- | -------------------- |
| `eq`  | `NotRequired[float]` |
| `neq` | `NotRequired[float]` |
| `gt`  | `NotRequired[float]` |
| `gte` | `NotRequired[float]` |
| `lt`  | `NotRequired[float]` |
| `lte` | `NotRequired[float]` |

### Order

| Field   | Type                               |
| ------- | ---------------------------------- |
| `field` | `Required[str]`                    |
| `order` | `Required[Literal['ASC', 'DESC']]` |

### TimeRange

| Field   | Type            |        |
| ------- | --------------- | ------ |
| `from_` | \`Required\[int | str]\` |
| `to`    | \`Required\[int | str]\` |
