Python SDK

Tasks

Run agents in the background, on demand or on a schedule, and follow each run with the Python SDK.

client.tasks runs an agent in the background. A task is a saved prompt for one agent; each time it runs, on demand or on a schedule, you get a task run with its own status and transcript. Use tasks for work that should not block a request, such as nightly reports.

Examples assume client = BlazingAgents() and an agent_id. Every method also accepts extra_headers and timeout. On AsyncBlazingAgents, await the same method names and use async for with iter() and iter_runs().

created = client.tasks.create(
    agent_id=agent_id,
    name="Daily summary",
    prompt="Summarize yesterday's open support cases.",
    submit=True,
)
run = client.tasks.get_run(created.task.id, created.run_id)
print(run.status)

Runs and their status

A run moves from "queued" to "running", then ends as "succeeded", "failed", "canceled", or "blocked". "blocked" means the run was not allowed to start, for example because your tenant's quota ran out; it is not an execution failure. A task has at most one active run at a time, and a scheduled run that would overlap an active one is skipped.

Each run gets a fresh session. session_id stays None until that session exists, and turn_id identifies the run's metered turn.

Tasks never wait for a person. Under the agent's approval_in_tasks policy, a tool call that needs manual approval is denied, and the model is told so it can continue with other work. See tool approvals.

Available operations

MethodDescriptionReturns
create()Create a task, and optionally run itTaskCreateResponse
list()Get one page of tasksTasksPage
iter()Iterate every taskIterator[TaskListItem]
get()Get one taskTask
update()Change a taskTask
delete()Delete a taskNone
submit()Start a run nowTaskRunSubmission
list_runs()Get one page of runsTaskRunsPage
iter_runs()Iterate every runIterator[TaskRun]
get_run()Get one runTaskRun
run_messages()Read or poll a run's transcriptTaskRunMessagesPage
cancel_run()Ask a run to stopNone

Methods

create()

Creates a task that runs on demand or on a schedule.

created = client.tasks.create(
    agent_id=agent_id,
    name="Weekday digest",
    prompt="Summarize open support cases.",
    schedule={
        "kind": "cron",
        "config": {"expression": "0 9 * * 1-5", "timezone": "Europe/London"},
    },
)
task = created.task

Signature: create(*, agent_id: str, name: str, prompt: str, agent_version=..., schedule=..., enabled=..., submit=..., user_id=..., metadata=...) -> TaskCreateResponse

ParameterTypeDefaultDescription
agent_idstrrequiredAgent that runs the task
namestrrequired1 to 80 characters
promptstrrequiredMessage sent to the agent, up to 6,000 characters
agent_versionint | NoneNonePin a version; None always uses the latest
scheduleTaskScheduleInput | NoneNoneWhen to run; None means on demand only
enabledboolTrueWhether the schedule fires
submitboolFalseAlso start the first run now
user_idstr""End user; fixed after creation and copied to every run
metadatadict[str, object]{}Your own data, copied to every run

A schedule is one of:

kindconfig
"once"{"at": "2026-10-01T09:00:00+01:00"}, an ISO datetime with an offset
"interval"{"every_ms": 3_600_000}, at least 60000
"cron"{"expression": "0 9 * * 1-5"}, a five-field expression, with optional "timezone" (default "UTC") and "stagger_ms"

The SDK checks the schedule shape before sending and raises TypeError or ValueError for a malformed one. submit=True does not make creation safe to retry: retrying creates another task.

Returns TaskCreateResponse with task and run_id, which is set only when submit=True. Raises APIStatusError with validation_failed, agent_version_not_found, or agent_disabled when submit=True and the agent is disabled.

list()

Gets one page of tasks, newest first.

page = client.tasks.list(agent_id=agent_id, limit=25)

Signature: list(*, agent_id=..., user_id=..., cursor=..., limit=...) -> TasksPage

Both filters are optional; user_id="" returns tenant-level tasks. limit is 1 to 200 and defaults to 50. Returns TasksPage with data: list[TaskListItem] and next_cursor. Raises validation_failed or invalid_cursor.

iter()

Iterates every matching task, fetching pages as you go.

for task in client.tasks.iter(agent_id=agent_id):
    print(task.name, task.latest_run.status if task.latest_run else None)

Signature: iter(*, agent_id=..., user_id=..., cursor=..., limit=...) -> Iterator[TaskListItem]

Takes the same parameters as list(). No request is sent until you start iterating.

get()

Gets one task. This does not start a run.

task = client.tasks.get(task.id)

Signature: get(task_id: str) -> Task

Returns Task. Raises validation_failed or not_found.

update()

Changes a task's prompt, schedule, version pin, or other settings.

task = client.tasks.update(task.id, enabled=False, metadata={"paused_by": "ops"})

Signature: update(task_id: str, *, agent_version=..., name=..., prompt=..., schedule=..., enabled=..., metadata=...) -> Task

Omitted parameters keep their current value. agent_version=None unpins the task, and schedule=None makes it on demand only. agent_id and user_id cannot change, and past runs are unaffected. Calling update() with nothing to change raises ValueError before any request.

Returns Task. Raises validation_failed, not_found, or agent_version_not_found.

delete()

Deletes a task. Its past runs and their sessions stay readable.

client.tasks.delete(task.id)

Signature: delete(task_id: str) -> None

Raises task_active_run_exists while a run is queued or running, validation_failed, or not_found.

submit()

Starts a run now.

submission = client.tasks.submit(task.id, idempotency_key="daily-summary:2026-10-01")
run_id = submission.run_id

Signature: submit(task_id: str, *, idempotency_key=...) -> TaskRunSubmission

With an idempotency_key, retrying with the same key returns the same run_id instead of starting another run. The key must not be blank. Without a key, or with a different one, a submit while another run is active raises task_active_run_exists.

Returns TaskRunSubmission with run_id. Also raises validation_failed, not_found, agent_version_not_found, or agent_disabled.

list_runs()

Gets one page of a task's runs, newest first.

page = client.tasks.list_runs(task.id, limit=25)

Signature: list_runs(task_id: str, *, cursor=..., limit=...) -> TaskRunsPage

Returns TaskRunsPage with data: list[TaskRun] and next_cursor. Raises validation_failed, invalid_cursor, or not_found.

iter_runs()

Iterates every run of a task, fetching pages as you go.

for run in client.tasks.iter_runs(task.id):
    print(run.id, run.status)

Signature: iter_runs(task_id: str, *, cursor=..., limit=...) -> Iterator[TaskRun]

Takes the same parameters as list_runs(). On the async client, use async for directly on iter_runs(...).

get_run()

Gets one run's current state.

run = client.tasks.get_run(task.id, run_id)
if run.status == "failed":
    print(run.error)

Signature: get_run(task_id: str, run_id: str) -> TaskRun

Returns TaskRun. Poll it until status is final. Raises validation_failed or not_found, including when the run belongs to another task.

run_messages()

Reads a run's transcript, or polls it for new messages.

page = client.tasks.run_messages(task.id, run_id, limit=50)
if page.latest_cursor is not None:
    newer = client.tasks.run_messages(task.id, run_id, after=page.latest_cursor)

Signature: run_messages(task_id: str, run_id: str, *, cursor=..., after=..., limit=...) -> TaskRunMessagesPage

Works like sessions.messages(): cursor pages backward, after polls forward, and you cannot pass both. The prompt appears when the run starts and the agent's answer when it ends. Before the run has a session, the page is empty.

Returns TaskRunMessagesPage: the messages page fields plus the run's status, error, and finished_at. Raises validation_failed, invalid_cursor, or not_found.

cancel_run()

Asks a run to stop.

client.tasks.cancel_run(task.id, run_id)

Signature: cancel_run(task_id: str, run_id: str) -> None

A queued run is canceled right away. A running one stops at its next safe point, so poll get_run() to see "canceled". Canceling a finished, missing, or mismatched run does nothing. Raises validation_failed or not_found only when the task itself is missing.

Response models

Task

FieldTypeDescription
idstrTask ID (tk_...)
tenant_id, agent_idstrOwner and agent
name, promptstrName and prompt
agent_versionint | NonePinned version, or None for the latest
scheduleTaskSchedule | NoneSchedule, or None for on demand
enabledboolWhether the schedule fires
active_run_id, latest_run_idstr | NoneCurrent and most recent runs
user_idstrEnd user, or "" for tenant level
metadatadict[str, object]Your own data
deleted_atdatetime | NoneDeletion time
created_at, updated_atdatetimeTimestamps

TaskListItem adds latest_run, with the latest run's id, status, and finished_at.

TaskRun

FieldTypeDescription
idstrRun ID (tr_...)
task_id, tenant_id, agent_idstrOwners
agent_versionintVersion the run used
session_idstr | NoneThe run's session, once created
turn_idstr | NoneThe run's metered turn, once started
statusstrqueued, running, blocked, succeeded, failed, or canceled
errorstr | NoneFailure reason
user_id, metadatastr, dict[str, object]Copied from the task
started_at, finished_atdatetime | NoneLifecycle times
cancel_requested_at, canceled_atdatetime | NoneCancellation times
created_at, updated_atdatetimeTimestamps

Next

On this page