Skip to content

Tasks

A task says what a robot should do and how success shows: five fields of prose (description, scene, steps, success, failure) and an optional procedure, in one editable draft. Publishing writes an immutable, numbered revision. The Robots and Tasks guide walks through it.

Every method takes a task’s id, put under your account, or its full name, accounts/<ACCOUNT_UUID>/tasks/<TASK_ID>. An API key acts as the person who created it.

from qualia import Qualia
client = Qualia()
task = client.tasks.create(
"Restock shelf",
draft={"description": "Move every box from the tray to the shelf"},
)
task = client.tasks.update(task.id, success="The tray is empty")
revision = client.tasks.publish(task.id, etag=task.etag, note="first cut")
client.tasks.list(limit=20) # PaginatedPage of Task, newest first
client.tasks.get(task.id) # the task with its draft
client.tasks.revisions(task.id) # PaginatedPage of TaskRevision
client.tasks.revision(task.id, 1) # one published revision
client.tasks.delete(task.id, force=True) # account owners only

update saves only the fields you pass; draft= replaces the whole draft. A stale etag is refused with 409.

A reference is an episode that shows success, or a named failure or recovery mode. A task holds 1 to 3 success references and any number of modes, each with 1 or 2.

episode = "accounts/<ACCOUNT_UUID>/datasets/<DATASET_ID>/episodes/<EPISODE_ID>"
ref = client.tasks.add_reference(task.id, {"role": "SUCCESS", "episode": episode})
client.tasks.add_reference(
task.id,
{"role": "FAILURE", "mode": "slip", "episode": episode,
"startSeconds": 1.5, "endSeconds": 4.0},
)
page = client.tasks.references(task.id) # PaginatedPage of TaskReference
for r in page.items:
print(r.id, r.role, r.mode, r.episode)
client.tasks.delete_reference(task.id, ref.id) # the episode is untouched

client.task_drafts asks a VLM to draft the task from exactly its references. It never publishes.

client.task_drafts.estimate(task.id) # {"estimated_credits": ..., "min_cost": ...}
draft = client.task_drafts.create(task.id)
draft = client.task_drafts.wait(draft.name)
client.task_drafts.apply(draft) # saves the proposal as the task's draft
client.task_drafts.list(task.id) # PaginatedPage of TaskDraft

A draft needs a signed-in person: with an API key, estimate and create are refused (a person must draft a Task). list, get, wait and apply work with a key.

A task links the datasets and episodes recorded against it. A link is not an edit: the label training reads stays as it is.

where = f'linked_task = "{task.name}"'
client.datasets.list(filter=where) # PaginatedPage of qualia.v1.Dataset
client.episodes.list("-", filter=where) # every dataset's linked episodes
client.episodes.link_task(episode, task.id) # link one episode
client.episodes.link_task(episode, "") # remove its own link

An episode with no link of its own reads its dataset’s link (linked_task_inherited is true). Link a whole upload with client.datasets.update(dataset, linked_task=task.name).