Skip to main content
The Tasks module manages the full lifecycle of task executions: the unit of work an agent does in response to a prompt. List existing tasks, load a specific one, create new ones, patch their state, or terminate them.

Constructor

Module methods

Task instance methods

The Task object returned by these calls has its own set of methods for runtime control: For the full attribute list, see the Task class reference.

Lifecycle

The AgentExecutionStatus enum (used everywhere status appears) has these values: Pending, Executing, Paused, Error, Failed, Completed, Stopped. String values are lowercase.

Class-level method

Task.areport_external_task(...) is a @classmethod that records an externally-executed run without going through Backend. It mirrors Backend.areport_external_task and exists for cases where you don’t have a Backend instance handy. See report_external_task.

create

Tasks.acreate creates a new task. It’s equivalent to Agent.acreate_task but accepts agent_id directly, so you don’t need to load the Agent first. Use this when you only have an agent ID and want to skip the extra round-trip.

Parameters

Identical to Agent.acreate_task, with agent_id required up front: See Agent.acreate_task for parameter details and examples.

Returns Task

The created task. Starts in Pending. See Task.

When to use this vs. Agent.acreate_task

Both produce identical results; pick the one that matches what you have on hand.

Sync version

Errors

Raises ModuleException. Common statuses:

get

Tasks.aget loads a full Task object: input, status, result, token usage, deep-planning state, attached files, and everything else stored against the task record.

Parameters

Returns Task

A full Task. See the Task class reference for attributes.

Examples

Wait for completion

For finer-grained progress, use task.aevents() instead: see streaming events.

Reload an existing instance

If you already have a Task instance and want fresh data, prefer task.areload() over a fresh aget: it preserves any in-flight deep_planning state that the API might briefly return as empty:

Sync version

Errors

Raises ModuleException on failure. Common statuses:

list

Tasks.alist returns task summaries for a given agent. Tasks.alist_user_tasks does the same scoped to a single end-user across all agents.

Parameters

Returns list[TasksListItem]

To load the full Task (including input, files, deep-planning state, tokens, activity log access), call .aload() on the item or pass item.id to tasks.aget().

Examples

Filter by status

The status filter accepts the lowercase string value: "pending", "executing", "completed", "failed", etc.

Filter by end-user

Tasks for a user

alist_user_tasks searches across every agent the user has interacted with:

Sync versions

Errors

Raises ModuleException on failure. Common statuses:

update

Tasks.aupdate patches selected fields on a task. Pass only the fields you want to change: anything left as None is ignored. For finer control over save semantics (especially when mutating Task attributes locally first), use task.asave() on the instance.

Parameters

Fields with value None are stripped from the request: only what you pass is sent.

Returns Task

The freshly-loaded task with updates applied. See Task.

Examples

Mark complete

Mark errored

Update only payload extension

This is rarely needed: payload extensions are usually set at task creation. Use this when you need to inject context after the task starts.

Sync version

When to use this vs. task.asave()

The @on_task runtime auto-saves the task at the end of the handler: you don’t usually call aupdate or asave yourself inside a handler.

Errors

Raises ModuleException. Common statuses:

stop

Tasks.astop cancels a running task. The platform marks it Stopped, signals the worker to abandon its current step, and returns the updated record.

Parameters

Returns Task

The task record after the stop request was processed. status is Stopped, is_manually_stopped is True, and finished_at is set.

Examples

Stop from a running Task instance

If you already have the Task object, prefer the instance method:
Task.astop() and Tasks().astop(task_id=task.id) are equivalent: the instance method also updates the in-memory object.

Idempotent stop

Calling astop on an already-terminal task is safe: the platform returns the existing record without changing state.

Sync version

Errors

Raises ModuleException. Common statuses:

events

Task.aevents() is an async generator over TaskUpdateEvents emitted by the platform as the task runs: message chunks, tool-call requests/results, reasoning steps, sub-agent triggers, plan updates, and auth events. Use it to build live UIs or to react to specific event types in real time.
The task must be created with events_streaming=True. Calling aevents() on a non-streaming task raises ValueError immediately.

Parameters

None.

Yields TaskUpdateEvent

Each event has:
Event types
If a typed payload fails to parse (e.g. due to schema drift), the SDK still yields the event with data set to the raw dict: the envelope (type, task_id, time) always propagates.

Examples

Filter on event type

Chunk events have a string data payload (the streaming text), making it easy to render token-by-token output.

Render tool calls

Stop on first failure

Track auth flows in-band

If you’ve registered an @on_auth_event handler, it fires automatically: the in-band event lets you also handle it inline.

Sync version

task.events() consumes the async generator on a synchronous executor and yields events in order. Don’t call from inside a running event loop.

Lifecycle

The generator reconnects automatically if the SSE stream drops mid-task. It exits when:
  1. The platform closes the stream (typically after TaskFinished).
  2. The connection fails permanently (network, auth).
  3. You break out of the loop.

Errors

  • ValueError: task wasn’t created with events_streaming=True.
  • Network failures propagate after the SSE retry budget is exhausted.

When not to stream

For batch jobs that don’t care about progress, skip events_streaming and poll task.areload() (or use webhooks). Streaming holds an HTTP connection open per task: fine for one or two, expensive for hundreds.

get_activity_log

Task.aget_activity_log returns the full thread of activity for a task: user messages, assistant messages, tool calls, tool results, reasoning steps, sub-agent triggers, and auth events. Unlike task.aevents() (live SSE for in-flight tasks), the activity log is a historical record you can fetch at any time, including for completed tasks.

Parameters

None.

Returns AgentActivityThread

The messages list is a tagged union. Common variants: (There are additional sub-types for sub-agent triggers and auth events: branch on isinstance or type(msg).__name__ to handle them.)

Examples

Just the user/assistant transcript

Audit tool usage

Reasoning trace

Sync version

Errors

Raises ModuleException if the activity log can’t be retrieved:

report_metrics

Task.areport_metrics records the task’s token usage, tool calls, and execution outcome to the platform’s metrics store. The @on_task runtime calls this automatically at the end of every handler if task.tokens is set, so you only need to invoke it directly when you’re driving a task outside the runtime.
task.tokens must be set before calling areport_metrics. The method raises ValueError if tokens is missing.

Parameters

Returns

None.

What gets reported

The metrics report includes:
  • execution_id: task id.
  • source: task source.
  • memory_thread_id: same as task id (memory and execution share an id).
  • task: input text (task.input.text).
  • status: current task.status.
  • internal_status: current task.internal_status.
  • ai_model: fixed to "xpander".
  • api_calls_made: tool names from task.used_tools (or [] for orchestration tasks with return_metrics=True).
  • result: final result string.
  • llm_tokens: token counts wrapped in ExecutionTokens(worker=task.tokens).

Examples

Inside a custom event loop

If you’re driving an agent without @on_task, report metrics manually before returning to the caller:
This makes the run show up in the dashboard with proper token accounting.

Sync version

Errors

Raises ModuleException on persistence failures, or ValueError if task.tokens is None.

report_external_task

Task.areport_external_task is the @classmethod version of Backend.areport_external_task. It logs a task that was executed outside the xpander.ai runtime so it appears in task history and metrics. Use this form when you don’t have a Backend instance in scope but do have a Configuration.

Parameters

Returns Task

The platform-side Task after persistence. Carries the id, status, and timestamps assigned by the cloud.

When to use this vs. Backend.areport_external_task

Functionally identical. Backend.areport_external_task is more discoverable (it sits next to the other Backend methods you’d be using); this classmethod is convenient when you don’t want to instantiate Backend.
See the Backend page for typical usage patterns (idempotent updates, failure reporting).

Sync version

Task class

Task represents a single agent execution. You get one back from Agent.acreate_task, Tasks.aget, Tasks.acreate, and the @on_task handler. It carries the full task state (input, status, result, deep-planning, tokens, …) and the methods needed to drive it forward.

Class methods

Task.aload(task_id, configuration=None) -> Task

Same as Tasks.aget but available without a Tasks instance. Useful when you have a Configuration but don’t want to instantiate the module class.
The sync sibling is Task.load(...).

Task.areport_external_task(...) (classmethod)

See the dedicated report_external_task page.

Attributes

Identity

Input

State

Output

Timestamps

Internal

Instance methods

save

task.asave(with_deep_plan_update: bool = False): PATCHes the task on the platform with the current in-memory state. By default deep_planning is excluded (the platform’s plan state is authoritative); pass with_deep_plan_update=True to push your plan updates back.
After saving, the response repopulates the local instance, but deep_planning and additional_context are restored from local memory if the API returns empty values (defensive against stale API state during retries). Sync: task.save(...).

set_status

task.aset_status(status, result=None): convenience wrapper that sets status (and optionally result) and calls asave() in one step.
Sync: task.set_status(...).

stop

task.astop(): terminates the task and updates the local instance with the platform’s response. Sync: task.stop().

reload

task.areload(): re-fetches the task from the platform and updates the in-memory instance. deep_planning and additional_context are restored from local memory if the API returns empty values. Sync: task.reload().

events

task.aevents() / task.events(): SSE stream of TaskUpdateEvent. Requires events_streaming=True at task creation. See streaming events.

get_activity_log

task.aget_activity_log() / task.get_activity_log(): full message / tool-call / reasoning thread for the task. See activity log.

report_metrics

task.areport_metrics() / task.report_metrics(): pushes token counts and tool usage to the platform. See report metrics.

get_plan_following_status

task.aget_plan_following_status() -> PlanFollowingStatus: checks whether deep-planning tasks are complete. Returns PlanFollowingStatus(can_finish: bool, uncompleted_tasks: list[DeepPlanningItem]). Used by the runtime to retry the agent until the plan is satisfied. Sync: task.get_plan_following_status().

acompact_session_for_retry

task.acompact_session_for_retry() -> CompactRetryResult: forces L2 (auto) compaction on the agent’s session before a plan-following retry. Used internally by the runtime; rarely needed from user code.

Agno helpers

These methods help shape the task input for Agno agents.
get_files
Returns PDF files from task.input.files as Agno File objects (when Agno is installed). Returns the URL strings as a fallback. Empty list if the task has no PDFs.
get_images
Returns image files as Agno Image objects (or URL strings as fallback). Empty list if no images.
get_human_readable_files
Fetches and parses text-based files (CSV, JSON, TXT, .py, …) and returns [{"url": ..., "content": ...}]. Used by to_message() to inline file contents into the prompt. Honors task.disable_attachment_injection.
to_message
Builds the message string to pass to the framework agent. Format:
On retries (retry_count > 0) and when deep planning is active, it generates a continuation prompt that lists completed/uncompleted tasks and pinpoints the next one to work on. This is the prompt format the runtime feeds to Agno when retrying after an incomplete plan.