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 toAgent.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
RaisesModuleException. 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
task.aevents() instead: see streaming events.
Reload an existing instance
If you already have aTask 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
RaisesModuleException 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
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
RaisesModuleException 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
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
RaisesModuleException. 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
Callingastop on an already-terminal task is safe: the platform returns the existing record without changing state.
Sync version
Errors
RaisesModuleException. 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.
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
@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:- The platform closes the stream (typically after
TaskFinished). - The connection fails permanently (network, auth).
- You
breakout of the loop.
Errors
ValueError: task wasn’t created withevents_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, skipevents_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
RaisesModuleException 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: currenttask.status.internal_status: currenttask.internal_status.ai_model: fixed to"xpander".api_calls_made: tool names fromtask.used_tools(or[]for orchestration tasks withreturn_metrics=True).result: final result string.llm_tokens: token counts wrapped inExecutionTokens(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:
Sync version
Errors
RaisesModuleException 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.
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.
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.
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.
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
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
Image objects (or URL strings as fallback). Empty list if no images.
get_human_readable_files
[{"url": ..., "content": ...}]. Used by to_message() to inline file contents into the prompt. Honors task.disable_attachment_injection.
to_message
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.

