Manage resource lifecycle
Every project, SUT, connection, dataset, eval config, and run you create stays on the platform until you remove it. This section collects the teardown and cancellation operations so you can clean up demo state, rotate a misconfigured resource, or stop a run that is taking too long. Resources are removed from the leaf inward — cancel or finish runs, then delete configs, SUTs, and datasets, and only tear down the workspace when you want everything under it gone.
Cancelling an in-flight run
Cancellation targets a run that has not reached a terminal state — one that is still pending, queued, or running. The platform dequeues the job if it is still pending and cooperatively stops it otherwise; afterwards the run reports status = "cancelled". A run that has already finished (completed, failed, or cancelled) cannot be cancelled again — the request returns 409.
SDK
Call run.cancel() on a live run inside the aip.run(...) context, or attach to an earlier run by id with aip.get_run() and cancel it from anywhere. The example below does both: it first attaches to an earlier run by id and cancels it, then cancels the live run inside the context manager. Either way cancel() requests graceful cancellation, after which run.status reads "cancelled". A rejected cancel — including calling it on an already-terminal run — surfaces as RunCancelledError (error_code="RUN_CANCELLED").
import aip_sdk as aip
run = aip.get_run(run_id)
run.cancel()
print(run.status)
with aip.run(project=project.id, dataset=f"{dataset.id}@v1") as run:
...
run.cancel()
API
The endpoint returns 200 when the run was non-terminal and 409 if it had already finished.
curl -sS -X POST "$AIP_API_URL/runs/<run_id>/cancel" \
-H "Authorization: Bearer $AIP_TOKEN"
Deleting a SUT and its connections
A SUT owns one or more connections (the HTTP endpoints AIP calls). You can drop a single connection while keeping the SUT framework in place, or delete the whole SUT — which cascades to every connection attached to it. After a SUT delete, the id no longer appears in aip.Sut.list(...).
SDK
There are two levels of teardown:
conn.delete()removes a single connection and retains the SUT.sut.delete()removes the SUT plus every connection attached to it.
The example below shows both levels: first disconnecting a single connection while retaining the SUT, then deleting the SUT so the cascade removes its connections and the id drops out of inventory.
sut.connections()[-1].delete()
print([c.id for c in sut.connections()])
target_id = sut.id
sut.delete()
gone = target_id not in [s.id for s in aip.Sut.list(project_id=project.id)]
print("SUT removed from inventory:", gone)
API
The first endpoint deletes a single connection; the second deletes the SUT and cascades to its connections.
curl -sS -X DELETE "$AIP_API_URL/suts/<sut_id>/connections/<connection_id>" \
-H "Authorization: Bearer $AIP_TOKEN"
curl -sS -X DELETE "$AIP_API_URL/suts/<sut_id>" \
-H "Authorization: Bearer $AIP_TOKEN"
Deleting an eval config
A published eval config lives in its workspace until you delete it by id. There is no dedicated high-level SDK helper for deleting it.
SDK
Delete it through the low-level platform client. After deletion the id no longer appears in aip.list_eval_configs(...).
client = aip._context.get_default_client()
client.delete(f"/eval-configs/{config_id}")
ids = [c.id for c in aip.list_eval_configs(workspace_id=ws.id, per_page=100)]
print("deleted:", config_id not in ids)
API
Hit the delete endpoint directly.
curl -sS -X DELETE "$AIP_API_URL/eval-configs/<config_id>" \
-H "Authorization: Bearer $AIP_TOKEN"
Deleting a dataset
Deleting a dataset is irreversible: it removes the dataset, every one of its versions, and the underlying stored files. Deprecation is the reversible alternative — aip.datasets.patch_dataset_status(dataset_id, "deprecated") retires a dataset while keeping it readable and hides it from the default listing. Deleting requires the workspace_admin or workspace_editor role.
Two dependencies are refused rather than cascaded, so a delete can never orphan evaluation history:
- Evaluation runs. If any run references a version of the dataset, the delete is refused with
409. Runs cannot be deleted on the platform, so a dataset that has been evaluated stays blocked by design — deprecate it instead. - Derived datasets. If another dataset was generated from this one — a synthetic data generation child, for example — the delete is refused until those are removed first.
SDK
Call delete() on a loaded dataset, or aip.delete_dataset(dataset_id) by id. A refusal raises DatasetInUseError, whose blocking_runs and dependent_datasets name what is holding the dataset.
import aip_sdk as aip
dataset = aip.load_dataset(id=dataset_id)
try:
dataset.delete()
except aip.DatasetInUseError as err:
print("blocked by runs:", err.blocking_runs)
print("blocked by derived datasets:", err.dependent_datasets)
aip.datasets.patch_dataset_status(dataset_id, "deprecated")
API
The endpoint returns 204 on success and 409 when a run or a derived dataset still depends on the dataset; the response body names the blockers.
curl -sS -X DELETE "$AIP_API_URL/datasets/<dataset_id>" \
-H "Authorization: Bearer $AIP_TOKEN"
Tearing down a project
The platform does not expose a self-service delete for an individual project — the Projects REST surface offers create, read, update, and move (to another workspace), but no DELETE /projects/{id}. To retire a project, remove the resources scoped to it (cancel outstanding runs, delete its SUTs and eval configs as above). When you want to discard a project together with everything under it, the coarse-grained teardown is at the workspace level, which is an admin-only cascade that removes the workspace and everything scoped to it.
SDK
Call delete() on the workspace.
ws.delete()
API
The admin-only workspace delete is a single call.
curl -sS -X DELETE "$AIP_API_URL/workspaces/<workspace_id>" \
-H "Authorization: Bearer $AIP_TOKEN"
Idempotency and soft-delete behavior
Most deletes are hard removals — the record is gone and a second attempt on the same id returns 404. One documented exception is notification configs, whose delete() is a soft-delete: the row is retained server-side with deleted_at set but excluded from every subsequent read, so a repeated delete() raises NotFoundError and a cross-workspace lookup returns 404 rather than leaking existence. Because notification configs have no exposed update(), rotation is done by delete() + create().
SDK
cfg.delete() performs the soft-delete.
cfg.delete()
API
The endpoint returns 204 on success; a cross-workspace id returns 404.
curl -sS -X DELETE "$AIP_API_URL/notifications/config/<config_id>" \
-H "Authorization: Bearer $AIP_TOKEN"