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

> ## Agent Instructions
> Choose User guide for browser tasks, Developers for CLI, SDK and external agents, and Administration for organization management.
> Confirm identity and organization/project context before operations. Documentation access does not grant ThinkPlatform permissions.
> Review side effects, verify changes with a read, and do not blindly retry an operation with an uncertain outcome.
> Use documented UI steps for the web app and documented public CLI or SDK interfaces for automation. Follow each page’s prerequisites and authentication requirements.

# Python API reference

> Look up client setup, credentials, resource methods, defaults, and return types in client 0.6.134.

Import the client, credentials, factories, and response models from `thinkplatform.sdk`. Follow [Installation](https://docs.thinkplatform.ai/cli/get-started/installation.md) to install the SDK.

This reference describes the synchronous SDK. For runnable examples, start with [resource workflows](https://docs.thinkplatform.ai/python-sdk/resources.md) and [database tables](https://docs.thinkplatform.ai/python-sdk/database.md). Response fields, aliases, and defaults are listed separately in [models and results](https://docs.thinkplatform.ai/python-sdk/models.md).

| Area | Reference |
| - | - |
| Client setup | [Lifecycle](#create-and-close-a-client), [factories](#factories), [credentials](#credentials), [raw requests](#low-level-requests-and-uploads) |
| Identity and scope | [User](#authenticated-user), [organizations](#organizations), [projects](#projects) |
| Canvas | [Home](#home), [pages](#home-pages), [dashboard](#home-dashboard), [visualizations](#home-visualizations), [dynamic UI](#home-dynamic-ui) |
| Shared database | [Tables](#database-tables), [rows](#database-rows), [workflow](https://docs.thinkplatform.ai/python-sdk/database.md) |
| Data lake | [Paths, listing, transfer, and signed access](#data-lake) |
| Agents | [Agents](#agents), [teams](#agent-teams), [workspaces](#agent-workspaces), [memories](#agent-memories) |
| Tasks | [Tasks, messages, goals, and follow-ups](#tasks), [agent task checkpoints](#agent-tasks) |
| Apps and delivery | [Cycle apps](#cycle-apps), [UI apps](#ui-apps), [inbound hooks](#inbound-hooks), [outbound webhooks](#outbound-webhooks) |
| Reusable execution | [Modules](#modules), [skills](#skills), [flows](#flows), [CodeFlow](#codeflow-entrypoints) |
| MLOps | [Models](#mlops-models), [jobs](#mlops-jobs), [data](#mlops-data), [environments](#mlops-environments), [hyperparameters](#mlops-hyperparameters) |
| Devices | [Devices, modules, twins, and tags](#devices) |

## Reading signatures

Signatures omit `self`. A `*` makes every following parameter keyword-only. Parameters without a default are required. `Optional[T]` means `T` or `None`; `Mapping` and `Iterable` are standard Python typing interfaces. `Any` means the SDK does not impose a more specific result schema. The signature blocks show how to call each method; use the workflow guides for executable examples.

Where present, `org_id=None` and `project_id=None` fall back independently to the client's context. Project-scoped methods require both values and raise `MissingContextError` when they are absent. Organization-scoped methods require `org_id`. Context selects a scope; the credential and server still determine access. Methods whose signatures omit these keywords do not accept them.

A `Mapping[str, Any]` payload is an endpoint-specific request object. Returned models describe responses. Before using their data to create or update a resource, check the deployed endpoint schema for required write fields. Mapping results use key access; models use attributes.

## Create and close a client

```text theme={"system"}
ThinkPlatformClient(
    *,
    base_url: str,
    credential: ThinkPlatformCredential,
    audience: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
    timeout_seconds: float=30.0,
) -> None
```

`base_url` is your API endpoint and `credential` supplies tokens. `timeout_seconds` configures HTTP request timeouts. `audience` identifies the API token audience where required by the credential.

Use `with ThinkPlatformClient(...) as client:` to close the client on exit, or call `close()` in `finally`. `with_context()` returns a client with the supplied context; `None` preserves the existing value, so it cannot clear a context value. Context clients share the original HTTP connection pool. Keep the original client open until every context client has finished, then close the original.

```text theme={"system"}
close() -> None

with_context(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> ThinkPlatformClient
```

## Factories

`client_from_env` and `client_from_profile` are available from `thinkplatform.sdk`. Pass an explicit endpoint or configure `THINKPLATFORM_API_BASE_URL`. Do not rely on a development endpoint default. `env=None` reads the process environment; an explicit mapping provides the environment source for the factory.

```text theme={"system"}
client_from_env(
    *,
    env: Optional[Mapping[str, str]]=None,
    base_url: Optional[str]=None,
    audience: Optional[str]=None,
    auth_mode: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
    timeout_seconds: float=30.0,
) -> ThinkPlatformClient

client_from_profile(
    profile_name: Optional[str]=None,
    *,
    config_path: Optional[Any]=None,
    env: Optional[Mapping[str, str]]=None,
    base_url: Optional[str]=None,
    audience: Optional[str]=None,
    auth_mode: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
    timeout_seconds: float=30.0,
) -> ThinkPlatformClient
```

`client_from_env()` resolves supplied settings before environment settings and defaults its authentication mode to `azure-cli` when none is selected. `client_from_profile()` resolves a saved CLI profile and explicit overrides; see [authentication](https://docs.thinkplatform.ai/python-sdk/authentication.md) for configuration. Both return clients with the same lifecycle as the constructor.

Import the token convenience factory from the client submodule: `from thinkplatform.sdk.client import client_from_token`. It is not exported from `thinkplatform.sdk` itself.

```text theme={"system"}
client_from_token(
    *,
    base_url: str,
    token: str,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
    timeout_seconds: float=30.0,
) -> ThinkPlatformClient
```

## Credentials

All classes below are exported from `thinkplatform.sdk`. Credentials are used by the client; creating one does not verify token acquisition or API permissions. Token acquisition may fail when a request first needs it. See [authentication](https://docs.thinkplatform.ai/python-sdk/authentication.md) and [errors](https://docs.thinkplatform.ai/python-sdk/errors.md).

### StaticTokenCredential

```text theme={"system"}
StaticTokenCredential(
    token: str,
    *,
    expires_on: Optional[int]=None,
    source: str='static',
    claims: Optional[Mapping[str, Any]]=None,
) -> None
```

### AzureCliCredential

```text theme={"system"}
AzureCliCredential(
    *,
    env: Optional[Mapping[str, str]]=None,
    tenant_id: Optional[str]=None,
    client_id: Optional[str]=None,
    refresh_buffer_seconds: int=300,
) -> None
```

### DeviceCodeCredential

```text theme={"system"}
DeviceCodeCredential(
    *,
    env: Optional[Mapping[str, str]]=None,
    tenant_id: Optional[str]=None,
    client_id: Optional[str]=None,
    refresh_buffer_seconds: int=300,
) -> None
```

### InteractiveBrowserCredential

```text theme={"system"}
InteractiveBrowserCredential(
    *,
    env: Optional[Mapping[str, str]]=None,
    tenant_id: Optional[str]=None,
    client_id: Optional[str]=None,
    refresh_buffer_seconds: int=300,
) -> None
```

### WorkspaceDelegationCredential

```text theme={"system"}
WorkspaceDelegationCredential(
    *,
    env: Optional[Mapping[str, str]]=None,
    managed_identity_client_id: Optional[str]=None,
    workspace_id: Optional[int]=None,
    workspace_name: Optional[str]=None,
    workspace_assertion: Optional[str]=None,
    requested_scopes: Optional[list[str]]=None,
    refresh_buffer_seconds: int=300,
    timeout_seconds: float=30.0,
) -> None
```

`StaticTokenCredential` returns the supplied token information; cache invalidation does not refresh a static token. Replace it with a current token when needed. `expires_on` is an optional expiry timestamp in Unix seconds; `source` and `claims` describe token metadata.

`AzureCliCredential` uses an existing Azure CLI login. `DeviceCodeCredential` and `InteractiveBrowserCredential` require an appropriate application client ID and may require a user to sign in. Their `env`, `tenant_id`, and `client_id` parameters select configuration; `refresh_buffer_seconds` controls cached-token refresh timing.

`WorkspaceDelegationCredential` is for a configured managed workspace. Supply workspace configuration through its supported parameters or the environment provided to that workspace. `requested_scopes` specifies the scopes to request; it does not grant additional permissions. Consult your deployment's workspace setup before choosing this credential.

### Custom credentials

Implement the exported `ThinkPlatformCredential` protocol. Return an [AccessTokenInfo](https://docs.thinkplatform.ai/python-sdk/models.md#accesstokeninfo) from `get_token_info()`. `invalidate_cache()` lets the client invalidate cached token state before a refresh attempt.

```text theme={"system"}
get_token_info(
    *,
    base_url: str,
    audience: Optional[str],
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
    force_refresh: bool=False,
) -> AccessTokenInfo

invalidate_cache() -> None
```

## Low-level requests and uploads

Use these methods when you already know the API contract. `path` is an API request path. They do not discover payload schemas. `request_json()` and `request_multipart()` decode JSON; an empty body becomes `None`, and a non-JSON body becomes text. `request_raw()` preserves bytes in `RawResponse`.

`MultipartFieldItems` means a mapping of field names to values or an iterable of `(name, value)` pairs. `MultipartFileItems` means the same structure with `MultipartFile` values; pairs permit repeated field names. `MultipartFile(filename, content, content_type=None)` takes bytes; `MultipartFile.from_text(filename, content, *, content_type=None, encoding="utf-8")` encodes text.

```text theme={"system"}
request_json(
    method: str,
    path: str,
    *,
    params: Optional[Mapping[str, Any]]=None,
    json_body: Optional[Any]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Any

request_multipart(
    method: str,
    path: str,
    *,
    fields: Optional[MultipartFieldItems]=None,
    files: Optional[MultipartFileItems]=None,
    params: Optional[Mapping[str, Any]]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Any

request_raw(
    method: str,
    path: str,
    *,
    params: Optional[Mapping[str, Any]]=None,
    json_body: Optional[Any]=None,
    multipart_fields: Optional[MultipartFieldItems]=None,
    multipart_files: Optional[MultipartFileItems]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> RawResponse

upload_to_url(
    url: str,
    *,
    content: bytes,
    content_type: Optional[str]=None,
    headers: Optional[Mapping[str, str]]=None,
    method: str='PUT',
) -> RawResponse
```

Authenticated requests accept relative paths or absolute URLs whose HTTP(S) origin exactly matches the configured API origin (scheme, normalized host, and effective port). Explicitly configured HTTP deployments are supported; a request cannot downgrade an HTTPS API. Invalid or ambiguous URLs and origin mismatches are rejected before credential acquisition. Redirects are not followed. Injected HTTP-client default headers, cookies, query parameters, and authentication are not inherited; explicit request headers and parameters still apply.

`request_raw()` raises `ValueError` if a JSON body is combined with nonempty multipart fields or files. `upload_to_url()` sends bytes directly to a signed storage URL without API credentials. It preserves ordinary explicitly supplied storage headers and signed query parameters, but rejects `Authorization`, `Proxy-Authorization`, `Cookie`, and `X-TP-*` headers. Authorization-based storage transfers are unsupported; use the storage provider's client for those schemes.

## Resource namespaces

Use namespace attributes on the client; do not construct resource implementation classes. The top-level namespaces are `auth`, `home`, `organizations`, `projects`, `mlops`, `datalake`, `skills`, `modules`, `flows`, `devices`, `db`, `agents`, `tasks`, `apps`, `hosted_apps`, `lakehouse`, `hooks`, and `webhooks`. `dashboard` and `canvas` are aliases of `home`.

The nested containers are `home.pages`, `home.dashboard`, `home.visualizations`, `home.dynamic_ui`; `db.tables`, `db.rows`; `agents.tasks`, `agents.teams`, `agents.workspaces`, `agents.memories`; `apps.cycle`, `apps.ui`; `lakehouse.statements`; and `mlops.models`, `mlops.jobs`, `mlops.data`, `mlops.environments`, `mlops.hyperparameters`. Containers such as `db`, `apps`, and `mlops` have no create, read, update, or delete methods of their own.

### Authenticated user

Namespace: `client.auth`.

`whoami()` identifies the authenticated user. It has no context arguments.

```text theme={"system"}
whoami() -> AuthenticatedUser
```

### Home

Namespace: `client.home`.

`data()` returns dashboard data for the selected project. `client.dashboard` and `client.canvas` refer to this same namespace.

```text theme={"system"}
data(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]
```

### Home pages

Namespace: `client.home.pages`.

Page results are mappings. `create`, `update`, and `delete` write to the server. `update()` sends your payload without automatically fetching an `updated_at` value or adding an optimistic concurrency condition. A separate read and write are not atomic.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[Mapping[str, Any]]

get(page_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]

create(
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Mapping[str, Any]

update(
    page_id: str,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Mapping[str, Any]

delete(page_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> None
```

### Home dashboard

Namespace: `client.home.dashboard`.

`lint()` validates a supplied dashboard definition. `query_dataset()` requests data for one dataset; `limit=500` bounds that request and `use_cache=True` permits caching. `inspect_schema()` requests its schema. These return mappings rather than typed dataset models.

```text theme={"system"}
lint(
    dashboard_definition: Mapping[str, Any],
    *,
    widgets: Optional[list[Mapping[str, Any]]]=None,
) -> Mapping[str, Any]

query_dataset(
    dashboard_definition: Mapping[str, Any],
    dataset_id: str,
    *,
    filter_values: Optional[Mapping[str, Any]]=None,
    limit: int=500,
    use_cache: bool=True,
    warehouse_id: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Mapping[str, Any]

inspect_schema(
    dashboard_definition: Mapping[str, Any],
    dataset_id: str,
    *,
    warehouse_id: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Mapping[str, Any]
```

### Home visualizations

Namespace: `client.home.visualizations`.

Read visualization collections and individual visualization records. `list()` returns a mapping, not a Python list.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]

get(visualization_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]
```

### Home dynamic UI

Namespace: `client.home.dynamic_ui`.

Read and write dynamic UI records. `list()` can filter by thread or canvas page and omits payloads by default (`include_payload=False`).

```text theme={"system"}
list(
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
    thread_id: Optional[str]=None,
    canvas_page_id: Optional[str]=None,
    include_payload: bool=False,
) -> list[Mapping[str, Any]]

get(ui_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]

create(
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Mapping[str, Any]

update(
    ui_id: str,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Mapping[str, Any]

delete(ui_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> None
```

### Organizations

Namespace: `client.organizations`.

List accessible organizations. No pagination parameters are accepted.

```text theme={"system"}
list() -> list[Organization]
```

### Projects

Namespace: `client.projects`.

List accessible projects in an organization. `org_id` falls back to client context; no pagination parameters are accepted.

```text theme={"system"}
list(*, org_id: Optional[int]=None) -> list[Project]
```

### Database tables

Namespace: `client.db.tables`.

Discover existing tables and retrieve their schema, columns, access metadata, and schema version. See the [database workflow](https://docs.thinkplatform.ai/python-sdk/database.md). Table creation and schema mutation are not exposed by this namespace.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[SharedDbTableSummary]

get(table_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> SharedDbTable
```

### Database rows

Namespace: `client.db.rows`.

Read, query, create, and update rows in an existing table. `data` is a mapping of column keys to values; the SDK wraps it in a `data` envelope. For `create_many`, pass an iterable of these plain column-value mappings. Only `create_many()` accepts `expected_schema_version`. There is no row delete method.

```text theme={"system"}
get(table_id: str, row_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> SharedDbRow

query(
    table_id: str,
    query: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> SharedDbRowQueryResult

create(
    table_id: str,
    data: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> SharedDbRow

create_many(
    table_id: str,
    rows: Iterable[Mapping[str, Any]],
    *,
    expected_schema_version: Optional[int]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Mapping[str, Any]

update(
    table_id: str,
    row_id: str,
    data: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> SharedDbRow
```

### Agents

Namespace: `client.agents`.

List and maintain agents, discover available models and system tools, and request workspace upload metadata. `list()` uses `limit` and `offset`. `create()` and `update()` reject nonempty legacy `knowledge_store` attachments with `ValueError` before writing. You can still read this field in historical records. `issue_workspace_upload()` requests upload metadata; it does not itself transfer file bytes.

```text theme={"system"}
list(
    *,
    q: Optional[str]=None,
    limit: int=50,
    offset: int=0,
    include_tools: bool=False,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> list[AgentSummary]

create(payload: Mapping[str, Any], *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> AgentDetail

update(
    agent_id: int,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> AgentDetail

delete(agent_id: int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]

models() -> AgentAvailableModels

system_tools_catalog(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> SystemToolCatalog

issue_workspace_upload(
    agent_id: int,
    files: Iterable[Mapping[str, Any]],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> AgentWorkspaceUpload
```

### Agent tasks

Namespace: `client.agents.tasks`.

Create and list tasks for agents or teams. Listing uses `limit` and `offset`. `checkpoints()` takes a thread ID and a direction, and returns messages and count metadata; it has no offset or continuation-token argument. Prefer the top-level `tasks` namespace for task status, messages, follow-ups, and goals.

```text theme={"system"}
create(
    *,
    title: str,
    description: Optional[str]=None,
    agent_id: Optional[int]=None,
    team_id: Optional[int]=None,
    thread_id: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Task

list(
    *,
    agent_id: Optional[int]=None,
    team_id: Optional[int]=None,
    user_id: Optional[int]=None,
    task_type: Optional[str]=None,
    status: Optional[str]=None,
    q: Optional[str]=None,
    limit: int=100,
    offset: int=0,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> list[Task]

checkpoints(
    thread_id: str,
    *,
    limit: int=100,
    direction: str='newest',
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> TaskCheckpointPage
```

### Agent teams

Namespace: `client.agents.teams`.

List, create, update, or delete agent teams. `Team.agents` and `Team.subteams` contain numeric IDs.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[Team]

create(payload: Mapping[str, Any], *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Team

update(
    team_id: int,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Team

delete(team_id: int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> None
```

### Agent workspaces

Namespace: `client.agents.workspaces`.

List and maintain managed agent workspaces. `rollout_image()` requests an image rollout; track completion using the returned workspace status and the monitoring process for your deployment.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[AgentWorkspace]

get(workspace_id: int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> AgentWorkspace

create(
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> AgentWorkspace

update(
    workspace_id: int,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> AgentWorkspace

rollout_image(
    workspace_id: int,
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> AgentWorkspace

delete(workspace_id: int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> None
```

### Agent memories

Namespace: `client.agents.memories`.

Search and maintain an agent’s memories, or import and export memory items. `context` defaults to `"all"`; search and export limits apply to a single response. These methods expose no continuation token or offset. `import_items()` returns counts of imported and failed items, along with any errors.

```text theme={"system"}
search(
    agent_id: int,
    *,
    q: str='',
    context: str='all',
    limit: int=20,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> MemorySearchResponse

create(
    agent_id: int,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> MemoryItem

update(
    agent_id: int,
    memory_id: str,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> MemoryItem

delete(
    agent_id: int,
    memory_id: str,
    *,
    context: str='all',
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> None

export(
    agent_id: int,
    *,
    context: str='all',
    limit: int=500,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> MemoryExportResponse

import_items(
    agent_id: int,
    items: Iterable[Mapping[str, Any]],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> MemoryImportResponse
```

### Tasks

Namespace: `client.tasks`.

`list()` supports filters and offset pagination; `status` can be a string or iterable of strings. `create()` creates a task, and `prepare_runtime()` requests runtime preparation. Methods for a known task ID such as `get`, `update`, `status`, `messages`, and goal operations do not accept context override keywords. `post_message()` sends a prompt and/or event; it does not return a typed completion stream. Follow-up methods return mappings; `include_inactive=False` is the default. Goal methods return a wrapper whose `goal` may be absent.

```text theme={"system"}
list(
    *,
    user_id: Optional[int]=None,
    agent_id: Optional[int]=None,
    team_id: Optional[int]=None,
    thread_id: Optional[str]=None,
    status: Optional[str | Iterable[str]]=None,
    q: Optional[str]=None,
    activity_from: Optional[str]=None,
    activity_to: Optional[str]=None,
    include_legacy_chat: bool=False,
    limit: int=100,
    offset: int=0,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> list[Task]

create(
    *,
    title: Optional[str]=None,
    description: Optional[str]=None,
    agent_id: Optional[int]=None,
    team_id: Optional[int]=None,
    thread_id: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Task

prepare_runtime(
    *,
    agent_id: Optional[int]=None,
    team_id: Optional[int]=None,
    is_private: bool=False,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> TaskRuntimePrepareResponse

get(task_id: int) -> Task

update(task_id: int, payload: Mapping[str, Any]) -> Task

delete(task_id: int) -> Mapping[str, Any]

status(task_id: int) -> Mapping[str, Any]

messages(task_id: int) -> Mapping[str, Any]

post_message(task_id: int, *, prompt: Optional[str]=None, event: Optional[str]=None) -> Mapping[str, Any]

scheduled_followups(task_id: int, *, include_inactive: bool=False, limit: int=100) -> Mapping[str, Any]

scheduled_followups_for_tasks(
    task_ids: Iterable[int],
    *,
    include_inactive: bool=False,
    limit: int=10,
) -> Mapping[str, Any]

cancel_scheduled_followup(task_id: int, followup_id: int) -> Mapping[str, Any]

goal(task_id: int) -> TaskGoalResponse

create_goal(task_id: int, *, objective: str, token_budget: Optional[int]=None) -> TaskGoalResponse

pause_goal(task_id: int) -> TaskGoalResponse

resume_goal(task_id: int) -> TaskGoalResponse

delete_goal(task_id: int) -> TaskGoalResponse
```

### Cycle apps

Namespace: `client.apps.cycle`.

Maintain cycle apps, change status, and retrieve logs. `log()` requires `device_id`; `agent_log()` supports a time range and limit. Your deployed API determines accepted status strings and validates payloads.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[CycleApp]

create(payload: Mapping[str, Any], *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> CycleApp

update(
    app_id: int,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> CycleApp

update_status(
    app_id: int,
    status: str,
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> CycleApp

delete(app_id: int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]

log(
    app_id: int,
    *,
    device_id: str,
    flow_id: str='',
    tail: int=100,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Mapping[str, Any]

agent_log(
    app_id: int,
    *,
    limit: int=50,
    from_date: Optional[str]=None,
    to_date: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Mapping[str, Any]
```

### UI apps

Namespace: `client.apps.ui`.

Maintain UI apps and load or save their layout. `save_layout()` takes an iterable of layout mappings; `load_layout()` returns a list of dictionaries.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[UiApp]

create(payload: Mapping[str, Any], *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> UiApp

update(
    app_id: int,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> UiApp

delete(app_id: int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]

load_layout(app_id: int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[dict[str, Any]]

save_layout(
    app_id: int,
    layout: Iterable[Mapping[str, Any]],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Mapping[str, Any]
```

### Inbound hooks

Namespace: `client.hooks`.

Manage inbound hook apps, rotate secrets, and inspect recent deliveries. `invoke()` addresses an endpoint key with a body and optional headers and query parameters; it does not accept organization/project override keywords. The hook configuration determines endpoint authorization. Delivery listing accepts a limit but no cursor.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[HookApp]

create(payload: Mapping[str, Any], *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> HookApp

update(
    hook_id: int,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> HookApp

delete(hook_id: int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]

rotate_secret(hook_id: int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> HookApp

deliveries(
    hook_id: int,
    *,
    limit: int=50,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> list[HookDelivery]

invoke(
    endpoint_key: str,
    *,
    body: Any=None,
    headers: Optional[Mapping[str, str]]=None,
    params: Optional[Mapping[str, Any]]=None,
) -> HookInvokeAccepted
```

### Outbound webhooks

Namespace: `client.webhooks`.

Manage outbound webhook subscriptions, discover event types, inspect deliveries, send tests, or retry one delivery. `send_test()` and `retry_delivery()` can cause outbound requests. Delivery listing accepts a limit but no cursor.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[WebhookSubscription]

event_types(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[WebhookEventTypeOption]

create(
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> WebhookSubscription

update(
    subscription_id: int,
    payload: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> WebhookSubscription

delete(subscription_id: int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]

deliveries(
    subscription_id: int,
    *,
    limit: int=50,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> list[WebhookDelivery]

send_test(
    subscription_id: int,
    payload: Optional[Mapping[str, Any]]=None,
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> WebhookTestSendResponse

retry_delivery(
    delivery_id: int,
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> WebhookDelivery
```

### MLOps models

Namespace: `client.mlops.models`.

Discover model assets and versions, inspect or download artifacts, request upload and download metadata, and register an asset. `download()` returns bytes and headers in `RawResponse`; `file_name=None` leaves file selection to the endpoint. Organization-scoped methods have no `project_id` parameter. Registration returns asset metadata; it does not upload model bytes.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[MLOpsAsset]

versions(model_name: str, *, org_id: Optional[int]=None) -> list[str]

artifacts(model_name: str, model_version: str, *, org_id: Optional[int]=None) -> MLOpsArtifact

download(
    model_name: str,
    model_version: str,
    *,
    file_name: Optional[str]=None,
    org_id: Optional[int]=None,
) -> RawResponse

next_version(name: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> str

sas(
    paths: Iterable[str],
    *,
    expires_in_minutes: int=180,
    datastore: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> list[Mapping[str, Any]]

register(
    *,
    name: str,
    version: str,
    base_path: str,
    model_type: str='custom_model',
    datastore: Optional[str]=None,
    description: str='',
    tags: Optional[Mapping[str, str]]=None,
    properties: Optional[Mapping[str, str]]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> MLOpsAsset
```

### MLOps jobs

Namespace: `client.mlops.jobs`.

Job listing returns `jobs` plus a continuation token. `get()` and `metrics()` preserve the decoded endpoint result as `Any`. Individual job reads are organization-scoped.

```text theme={"system"}
list(
    *,
    continuation_token: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> MLOpsJobsPage

get(job_id: str, *, org_id: Optional[int]=None) -> Any

logs(job_id: str, *, org_id: Optional[int]=None) -> MLOpsJobLogs

metrics(job_id: str, *, org_id: Optional[int]=None) -> Any
```

### MLOps data

Namespace: `client.mlops.data`.

List data assets and versions, page through asset files, discover datastores, and request folder access metadata. `files()` returns `items`, `continuation_token`, and `root_prefix`; preserve the asset name, version, and path when following a token.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[MLOpsAsset]

versions(data_asset_name: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[str]

files(
    data_asset_name: str,
    version: str,
    *,
    path: Optional[str]=None,
    continuation_token: Optional[str]=None,
    page_size: Optional[int]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> MLOpsDataFilesPage

datastores(*, org_id: Optional[int]=None) -> list[str]

sas_folder(
    folder_path: str,
    *,
    data_asset_name: str,
    version: str,
    expires_in_minutes: int=180,
    datastore: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> MLOpsFolderSas
```

### MLOps environments

Namespace: `client.mlops.environments`.

List project MLOps environments. No pagination parameters are accepted.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[MLOpsEnvironment]
```

### MLOps hyperparameters

Namespace: `client.mlops.hyperparameters`.

Discover architecture names and the schema for one architecture. These methods have no organization/project override parameters; `schema()` preserves the decoded response as `Any`.

```text theme={"system"}
architectures() -> list[str]

schema(architecture: str) -> Any
```

### Data lake

Namespace: `client.datalake`.

Resolve paths; list a tree or one file-list page; preview, download, or upload content; and request signed access metadata. `list()` returns `items` plus a continuation token. `preview_text()` returns a preview model, while `download_text()` decodes downloaded bytes using `encoding` and `errors`. `upload_text()` encodes text first. Upload methods write content and return the storage response as `RawResponse`. Requested access durations are in minutes.

```text theme={"system"}
resolve(path: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> DatalakeResolvedPath

list_tree(*, path: str='', org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[DatalakeTreeItem]

list(
    *,
    path: str='',
    continuation_token: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> DatalakeListPage

preview_text(path: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> DatalakeTextPreview

preview_raw(path: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> RawResponse

sas(
    paths: Iterable[str],
    *,
    operation: str='download',
    expires_in_minutes: int=60,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> list[Mapping[str, Any]]

download_bytes(
    path: str,
    *,
    expires_in_minutes: int=30,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> bytes

download_text(
    path: str,
    *,
    encoding: str='utf-8',
    errors: str='replace',
    expires_in_minutes: int=30,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> str

upload_bytes(
    path: str,
    content: bytes,
    *,
    content_type: Optional[str]=None,
    expires_in_minutes: int=60,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> RawResponse

upload_text(
    path: str,
    text: str,
    *,
    content_type: str='text/plain; charset=utf-8',
    encoding: str='utf-8',
    expires_in_minutes: int=60,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> RawResponse

sas_folder(
    folder_path: str,
    *,
    expires_in_minutes: int=60,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> DatalakeFolderSas
```

### Skills

Namespace: `client.skills`.

List, inspect, download, upload, or delete skills. `download()` returns `RawResponse`; read the downloaded bytes from its `body` attribute. `upload()` accepts multipart fields and files in the format required by your deployed API and returns `SkillMetadata`.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[SkillMetadata]

get(skill_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> SkillDetail

download(skill_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> RawResponse

upload(
    *,
    fields: Optional[MultipartFieldItems]=None,
    files: Optional[MultipartFileItems]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> SkillMetadata

delete(skill_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Mapping[str, Any]
```

### Modules

Namespace: `client.modules`.

List or search modules, retrieve details, resolve tool schemas, and invoke tools. `search()` filters the fetched module list locally and truncates it to `limit`; it is not a server paginator. `describe()` resolves an ID or name and raises `ValueError` for missing or ambiguous identifiers. `resolve()` may require `tool_name` when a module has multiple tools. `invoke_tool()` resolves an identifier before invocation, preserves its original result in `raw_result`, and normalizes `result`. `invoke()` returns the endpoint response without that additional normalization. Invocation returns `ModuleInvocationResult`; use `result`, `raw_result`, or the computed `normalized_result` according to the endpoint response.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[ModuleSummary]

search(
    query: str='',
    *,
    limit: int=20,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> list[ModuleSummary]

get(module_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> ModuleDetail

describe(identifier: str | int, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> ModuleDetail

resolve(
    identifier: str | int,
    *,
    tool_name: Optional[str]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> ModuleResolvedTool

invoke(
    module_id: str,
    tool_name: str,
    *,
    input_data: Optional[Mapping[str, Any]]=None,
    config: Optional[Mapping[str, Any]]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> ModuleInvocationResult

invoke_tool(
    identifier: str | int,
    tool_name: str,
    *,
    input_data: Optional[Mapping[str, Any]]=None,
    config: Optional[Mapping[str, Any]]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> ModuleInvocationResult
```

### Flows

Namespace: `client.flows`.

List or create flows, save a flow definition, or run a flow with inputs and optional execution settings. `save()` and `run()` return dictionaries. `timeout_seconds` is an optional run request parameter, separate from the client HTTP timeout.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[FlowSummary]

create(payload: Mapping[str, Any], *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> FlowDetail

save(
    flow_id: str,
    flow_data: Mapping[str, Any],
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> dict[str, Any]

run(
    flow_id: str,
    *,
    inputs: Optional[Mapping[str, Any]]=None,
    device: Optional[str]=None,
    trigger: Optional[Mapping[str, Any]]=None,
    target: Optional[Mapping[str, Any]]=None,
    timeout_seconds: Optional[int]=None,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> dict[str, Any]
```

### Devices

Namespace: `client.devices`.

List devices and modules, read module status and twins, and retrieve device tags. Status and twin results are untyped decoded values. The SDK exposes no device mutation methods here.

```text theme={"system"}
list(*, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[IoTDevice]

modules(device_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> list[IoTModule]

modules_status(device_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> Any

module_twin(
    device_id: str,
    module_id: str,
    *,
    org_id: Optional[int]=None,
    project_id: Optional[int]=None,
) -> Any

tags(device_id: str, *, org_id: Optional[int]=None, project_id: Optional[int]=None) -> DeviceTag
```

## Pagination

Pagination settings vary by method and must be supplied explicitly. The SDK does not provide a universal paginator or automatically fetch all pages.

| Method | Page input | Result and next request |
| - | - | - |
| `datalake.list()` | `continuation_token=None` | Read `items`; pass a nonempty `continuation_token` back with the same path/context. |
| `mlops.jobs.list()` | `continuation_token=None` | Read `jobs`; pass a nonempty `continuation_token` into the next call. |
| `mlops.data.files()` | `continuation_token=None`, `page_size=None` | Read `items`; pass the returned token back with the same asset/version/path/context. |
| `tasks.list()`, `agents.tasks.list()` | `limit=100`, `offset=0` | Return a plain list. Request another offset explicitly; no total or cursor is attached. |
| `agents.list()` | `limit=50`, `offset=0` | Return a plain list with no cursor metadata. |
| `db.rows.query()` | The supplied query mapping | Read `items` and `meta.page`, `meta.page_size`, `meta.total`; see [database tables](https://docs.thinkplatform.ai/python-sdk/database.md). No SDK page arguments are added. |

Methods with only a `limit` parameter do not accept an offset or continuation token. Other lists and mapping responses have only the arguments shown in their signatures. Use bounded loops and, for token pagination, guard against repeated tokens.

## CodeFlow entrypoints

These helpers are exported from `thinkplatform.sdk` for Python Code Flow entrypoints. They attach and inspect metadata; decorating a function does not deploy, register, or execute it.

```text theme={"system"}
codeflow(
    *,
    input_schema: Optional[dict[str, Any]]=None,
    output_schema: Optional[dict[str, Any]]=None,
    name: Optional[str]=None,
) -> Callable[[F], F]

get_codeflow_definition(func: Callable[..., Any]) -> Optional[CodeFlowDefinition]
```

`codeflow()` accepts optional JSON-schema dictionaries and a name, and returns a decorator that preserves the original function. A non-dictionary schema raises `TypeError`. `get_codeflow_definition()` returns `CodeFlowDefinition` for a decorated function, or `None`.

`CodeFlowContext(org_id=None, project_id=None, workspace_url=None, metadata=...)` provides a lazily created `client` and a `tools` helper. Its organization and project fields are optional strings. The metadata mapping defaults to a fresh dictionary. The lazily created client uses SDK environment configuration; close `ctx.client` when your code owns that client’s lifecycle. `CodeFlowTools(ctx)` describes the tools selected for the entrypoint:

```text theme={"system"}
list() -> list[dict[str, Any]]

get(alias: str) -> dict[str, Any]

invoke(
    alias: str,
    input_data: Optional[Mapping[str, Any]]=None,
    *,
    config: Optional[Mapping[str, Any]]=None,
) -> ModuleInvocationResult
```

`list()` returns selected tool metadata; `get(alias)` raises `KeyError` when the alias is unavailable. `invoke()` calls the selected module tool and returns `ModuleInvocationResult`, preserving the original result in `raw_result` and normalizing `result`. It can raise `ValueError` when selected tool metadata lacks a module identifier.

## Errors and retry behavior

Resource methods use the same [SDK exceptions](https://docs.thinkplatform.ai/python-sdk/errors.md): `MissingContextError` for absent required context, `TokenAcquisitionError` for credential failures, and `ThinkPlatformApiError` for HTTP or transport failures. HTTP errors expose `status_code` and `response_body`; transport errors may have no status. Unexpected response structures can raise `ValueError` or Pydantic validation errors. Local validation and identifier resolution can raise errors before any request.

The API request path retries once after an HTTP 401 by asking the credential to refresh. A static token remains the same token. There is no general retry policy for rate limits, server errors, or failed writes; check whether the endpoint can safely repeat an operation before adding retries. Direct signed-URL transfers do not refresh API credentials.

## Hosted Apps

Namespace: `client.hosted_apps`. Available since client 0.6.133. Management calls require an authorized developer client and an enabled deployment. These methods use the client's organization/project context; they do not accept per-call context overrides.

```text theme={"system"}
publish(app_id: str, *, name: str, image: str, ui_id: str, request_id: str,
        cpu: float=0.5, memory: str="1Gi", table_id: Optional[str]=None,
        replaces: Optional[str]=None, replaces_stopped: bool=False,
        permissions: Optional[HostedAppPermissions]=None) -> HostedAppDeployment

publish_source(app_id: str, *, name: str, ui_id: str, request_id: str,
               source: bytes | None=None, cpu: float=0.5, memory: str="1Gi",
               table_id: str | None=None, replaces: str | None=None,
               replaces_stopped: bool=False,
               permissions: HostedAppPermissions | None=None) -> HostedAppDeployment

list() -> list[HostedAppPublication]
get(app_id: str) -> HostedAppPublication
stop(app_id: str, release: str) -> None
```

`request_id` is a UUID. `publish_source()` accepts a gzip context of at most 50 MiB; use `source=None` to advance a build that already has its source, retaining the same options and request ID. Retain the expected previous release for updates. A returned deployment is not confirmation of readiness; read publication state. See [Publish a web app](https://docs.thinkplatform.ai/cli/guides/apps.md).

### Request-bound client factory

```text theme={"system"}
client_from_hosted_request(headers: Mapping[str, str], *,
                           env: Optional[Mapping[str, str]]=None) -> ThinkPlatformClient
```

Import from `thinkplatform.sdk`. The factory validates current invocation information and the configured gateway before creating a project-bound client with a 20-second request timeout. It raises `TokenAcquisitionError` for missing or invalid invocation configuration. Close it within the current app request; method availability does not establish delegated API permission. See [Hosted App authentication](https://docs.thinkplatform.ai/python-sdk/hosted-apps.md).

## Lakehouse statements

Namespace: `client.lakehouse.statements`. Available since client 0.6.133. Methods use the client's organization/project context and the configured warehouse.

```text theme={"system"}
execute(statement: str, *, parameters: Iterable[LakehouseStatementParameter]=(),
        schema: Optional[str]=None, wait_timeout: str="0s") -> LakehouseStatement
get(statement_id: str) -> LakehouseStatement
result_chunk(statement_id: str, chunk_index: int) -> LakehouseStatementResult
cancel(statement_id: str) -> LakehouseStatement
```

The chunk index must be nonnegative. Submission, completion and cancellation are distinct observations; inspect status and retain the statement ID when polling times out. Results can include further chunks and numeric strings. See [Lakehouse statements](https://docs.thinkplatform.ai/python-sdk/lakehouse.md) for a complete submission/status example and the [result models](https://docs.thinkplatform.ai/python-sdk/models.md#lakehousestatement).


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