Background Task Tracking for ACP, Subagents, Automation, and CLI
This page explains the background activity ledger for ACP runs, subagent launches, automation jobs, and CLI operations. It clarifies what creates tasks and how they differ from scheduling.
Read this when
- Inspecting background work in progress or recently completed
- Debugging delivery failures for detached agent runs
- Understanding how background runs relate to sessions, automations, and heartbeat
Note
Need to schedule something? Check Automation to pick the right tool. This page covers the record of background activity, not scheduling.
Background tasks keep track of work that happens away from your main conversation: ACP executions, subagent launches, automation job runs, and operations started from the CLI.
Tasks don't replace sessions, automations, or heartbeats. They serve as the activity ledger, logging what detached work occurred, when it ran, and whether it succeeded.
For a quick, throwaway single-agent execution in CI or a script, go with openclaw agent exec rather than managed background work.
Note
Not every agent run results in a task. Heartbeat turns and regular interactive chat don't create them. However, all automation runs, ACP launches, subagent launches, gateway-routed CLI agent commands, and agent-started background
execcommands do.
TL;DR
- Tasks act as records, not schedulers. Automations and heartbeats decide when work runs; tasks track what took place.
- ACP, subagents, every automation job, and CLI operations generate tasks. Heartbeat turns don't.
- Each task passes through
queued → running → terminal(succeeded, failed, timed_out, cancelled, or lost). - Automation tasks stay active while the automations runtime still holds the job; if the in-memory runtime state is gone, task maintenance checks durable automation run history first before labeling a task lost.
- Completion is push-based: detached work can notify directly or wake the requesting session/heartbeat when done, so polling for status is usually the wrong approach.
- Isolated automation runs and subagent completions make a best effort to clean up tracked browser tabs/processes for their child session before final cleanup bookkeeping.
- Isolated automation delivery suppresses stale interim parent replies while descendant subagent work is still draining, and it prefers final descendant output when that arrives before delivery.
- Completion notifications go straight to a channel or get queued for the next heartbeat.
openclaw tasks listdisplays all tasks;openclaw tasks audithighlights issues.- Terminal records persist for 7 days (
lostrecords for 24 hours), then get pruned automatically.
Quick start
List and filter
# List all tasks (newest first)
openclaw tasks list
# Filter by runtime or status
openclaw tasks list --runtime acp
openclaw tasks list --status running
openclaw tasks list --status blocked
Inspect
# Show details for a specific task (by task ID, run ID, or session key)
openclaw tasks show <lookup>
Cancel and notify
# Cancel a running task (kills the child session)
openclaw tasks cancel <lookup>
# Change notification policy for a task
openclaw tasks notify <lookup> state_changes
Recover delivery
# Retry or dismiss up to 10 blocked completion deliveries
openclaw tasks retry <lookup> [lookup...]
openclaw tasks dismiss <lookup> [lookup...]
Audit and maintenance
# Run a health audit
openclaw tasks audit
# Preview or apply maintenance
openclaw tasks maintenance
openclaw tasks maintenance --apply
Task flow
# Inspect TaskFlow state
openclaw tasks flow list
openclaw tasks flow show <lookup>
openclaw tasks flow cancel <lookup>
What creates a task
| Source | Runtime type | When a task record is created | Default notify policy |
|---|---|---|---|
| ACP background runs | acp | Spawning a child ACP session | done_only |
| Subagent orchestration | subagent | Spawning a subagent via sessions_spawn | done_only |
| Automation jobs (all types) | cron | Every automation run (main-session and isolated) | silent |
| CLI operations | cli | openclaw agent commands that run through the gateway | silent |
| Agent media jobs | cli | Session-backed image_generate/music_generate/video_generate runs | silent |
Notify defaults for automations and media
Automation tasks (main-session and isolated) adopt the silent notify policy. They create records for tracking but don't emit their own task notifications; the scheduler handles its own delivery path.
Session-backed image_generate, music_generate, and video_generate runs also follow the silent notify policy. They still produce task records, but completion returns to the original agent session as an internal wake. The requesting agent follows its current visible-reply contract: a successful completion includes a brief user-facing caption and every structured generated attachment from the completion event, while a failure yields a short visible failure. Internal task and session details remain private. If the requesting session is no longer active or its active wake fails, and the completion agent misses some or all generated media, OpenClaw sends an idempotent direct fallback with only the missing media to the original channel target.
Concurrent media-generation guardrail
While a session-backed media-generation task is active, image_generate, music_generate, and video_generate prevent accidental retries: repeating the call for the same prompt/request returns the matching active task status instead of launching a duplicate, while a different prompt can start its own task. Use action: "status" when you need an explicit progress/status lookup from the agent side.
What does not create tasks
- Heartbeat turns, main-session; see Heartbeat
- Normal interactive chat turns
- Direct
/commandresponses
Task lifecycle
stateDiagram-v2
[*] --> queued
queued --> running : agent starts
running --> succeeded : completes ok
running --> failed : error
running --> timed_out : timeout exceeded
queued --> cancelled : operator cancels
running --> cancelled : operator cancels
queued --> lost : backing state gone > 5 min
running --> lost : backing state gone > 5 min
| Status | What it means |
|---|---|
queued | Created, waiting for the agent to start |
running | Agent turn is actively executing |
succeeded | Completed successfully |
failed | Completed with an error |
timed_out | Exceeded the configured timeout |
cancelled | Stopped by the operator via openclaw tasks cancel, or the run was aborted |
lost | The runtime lost authoritative backing state after a 5-minute grace period |
Transitions happen automatically. Agent run lifecycle events (start, end, error) update the task status; you don't manage it manually.
Execution and result delivery operate independently. A subagent task may stay
succeeded while its deliveryStatus is session_queued or failed. The
final outcome becomes succeeded after delivery and blocked when the work
completed but the result could not be returned. This keeps the finished result
intact rather than incorrectly labeling the child execution as failed.
Locate these tasks with openclaw tasks list --status blocked. They also appear
in --status succeeded results because the underlying execution succeeded, and
JSON output retains the stored status plus the blocked terminal outcome.
Agent run completion dictates the final state of active task records. A successful detached run concludes as succeeded, standard run errors conclude as failed, timeouts conclude as timed_out, and cancel/abort outcomes conclude as cancelled. After a task reaches a terminal state, subsequent lifecycle signals cannot lower its status: an operator-cancelled or already-failed/timed_out/lost task remains unchanged even if a success signal follows.
lost understands the runtime context:
- ACP tasks: only an active in-process ACP turn in the Gateway confirms the run is alive; persisted session metadata alone is insufficient. Offline CLI audit remains cautious and never reclaims ACP tasks.
- Subagent tasks: the backing child session vanished from the target agent store (or has a restart-recovery tombstone).
- Automation tasks: the automations runtime no longer tracks the job as active, and durable run history lacks a terminal result for that run. Offline CLI audit does not treat its own empty in-process automations runtime state as authoritative.
- CLI tasks: tasks with a run id/source id rely on the live run context, so lingering child-session or chat-session rows do not keep them alive after the gateway-owned run disappears. Legacy CLI tasks without run identity still depend on the child session. Gateway-backed
openclaw agentruns also finalize from their run result, so completed runs do not remain active until the sweeper labels themlost.
Delivery and notifications
OpenClaw alerts you when a task reaches a terminal state. Two delivery paths exist:
Direct delivery - when the task has a channel target (the requesterOrigin), the completion message goes straight to that channel (Discord, Slack, Telegram, etc.). Group and channel task completions, however, route through the requester session so the parent agent can produce the visible reply. For subagent completions, OpenClaw also retains bound thread/topic routing when available and can supply a missing to / account from the requester session's stored route (lastChannel / lastTo / lastAccountId) before abandoning direct delivery.
Session-queued delivery - if direct delivery fails or no origin is set, the update queues as a system event in the requester's session and appears on the next heartbeat.
When gateway.publicOrigin is configured and the Control UI is enabled,
direct channel notifications include an Inspect link to the task's own
session. Session-queued notifications omit this link.
Durable subagent completion handoffs retry for up to 30 minutes with capped
exponential backoff. A queued handoff is not marked delivered until the
queue settles. If delivery hits its deadline or fails permanently, the task
shows a blocked terminal outcome and keeps its canonical result for 7 days.
Use openclaw tasks retry to create a fenced new delivery generation, or
openclaw tasks dismiss to note intentional non-delivery. Retry can duplicate
a visible result when an earlier provider acknowledgement was ambiguous.
Tip
Session-queued task completions trigger an immediate heartbeat wake, so you see the result quickly: you do not have to wait for the next scheduled heartbeat tick.
The typical workflow is therefore push-based: start detached work once, then let the runtime wake or notify you on completion. Poll task state only when you need debugging, intervention, or an explicit audit.
Notification policies
Choose how much you hear about each task:
| Policy | What is delivered |
|---|---|
done_only (default) | Only terminal state (succeeded, failed, etc.) |
state_changes | Every state transition and progress update |
silent | Nothing at all (default for automation, CLI, and media tasks) |
Adjust the policy while a task is running:
openclaw tasks notify <lookup> state_changes
CLI reference
tasks list
openclaw tasks list [--runtime <acp|subagent|cron|cli>] [--status <status>] [--json]
Output columns: Task, Kind, Status, Delivery, Run, Child Session, Summary. Bare openclaw tasks behaves like openclaw tasks list.
tasks show
openclaw tasks show <lookup> [--json]
The lookup token accepts a task ID, run ID, or session key. Shows the full record including timing, delivery state, error, and terminal summary.
tasks cancel
openclaw tasks cancel <lookup>
For ACP and subagent tasks, this kills the child session; ACP and automation cancellations route through the running Gateway (tasks.cancel). For CLI-tracked tasks, cancellation is recorded in the task registry (there is no separate child runtime handle). Status transitions to cancelled and a delivery notification is sent when applicable.
tasks retry | dismiss
openclaw tasks retry <lookup> [lookup...]
openclaw tasks dismiss <lookup> [lookup...]
These commands recover blocked subagent completion deliveries. Each request accepts 1-10 task lookups. Retry preserves the canonical result and starts a new fenced queue generation; dismiss keeps the task blocked and records that the operator intentionally stopped delivery.
tasks notify
openclaw tasks notify <lookup> <done_only|state_changes|silent>
tasks audit
openclaw tasks audit [--severity <warn|error>] [--code <name>] [--limit <n>] [--json]
Surfaces operational issues for tasks and TaskFlows in one report. Findings also appear in openclaw status when issues are detected.
Task findings:
| Finding | Severity | Trigger |
|---|---|---|
stale_queued | warn | Queued for more than 10 minutes |
stale_running | error | Running for more than 30 minutes |
lost | warn/error | Runtime-backed task ownership disappeared; retained lost tasks warn until cleanupAfter, then become errors |
delivery_failed | warn | Delivery failed and notify policy is not silent |
missing_cleanup | warn | Terminal task with no cleanup timestamp |
inconsistent_timestamps | warn | Timeline violation (for example ended before started) |
TaskFlow findings:
| Finding | Severity | Trigger |
|---|---|---|
restore_failed | error | Flow registry restore from SQLite failed |
stale_running | error | Running flow has not advanced for more than 30 minutes |
stale_waiting | warn | Waiting flow has not advanced for more than 30 minutes |
stale_blocked | warn | Blocked flow has not advanced for more than 30 minutes |
cancel_stuck | warn | Cancel requested over 5 minutes ago, no active child tasks, still nonterminal |
missing_linked_tasks | warn/error | Stale managed flow with no linked tasks or wait state |
blocked_task_missing | warn | Blocked flow points at a task id that no longer exists |
tasks maintenance
openclaw tasks maintenance [--json]
openclaw tasks maintenance --apply [--json]
Apply this to preview or execute reconciliation, cleanup stamping, and pruning across tasks, TaskFlow state, and stale automation run session registry rows.
Reconciliation adapts to the runtime:
- ACP tasks need an active in-process turn within the Gateway; subagent tasks consult their backing child session.
- Subagent tasks with a restart-recovery tombstone on their child session are flagged as lost, not treated as recoverable backing sessions.
- Automation tasks verify the automations runtime still owns the job, then recover terminal status from persisted run logs or job state before falling back to
lost. Only the Gateway process holds authority over the in-memory active-job set; offline CLI audit relies on durable history and does not mark an automation task lost just because that local set is empty. - CLI tasks with run identity check the owning live run context, not just child-session or chat-session rows. Only Gateway maintenance performs that liveness check; standalone CLI audit and maintenance keep active CLI tasks because their local run registry cannot confirm the Gateway run has ended.
Completion cleanup also respects the runtime:
- Subagent completion best-effort closes tracked browser tabs or processes for the child session before announce cleanup proceeds.
- Isolated automation completion best-effort closes tracked browser tabs or processes for the run's session before the run fully tears down.
- Isolated automation delivery waits out descendant subagent follow-up when needed and suppresses stale parent acknowledgement text instead of announcing it.
- Subagent completion delivery uses only the child's latest visible assistant text. Tool or toolResult output is not promoted into child result text. Terminal failed runs announce failure status without replaying captured reply text.
- Cleanup failures do not hide the real task outcome.
When maintenance runs, OpenClaw also removes stale cron:<jobId>:run:<runId> session registry rows older than 7 days, while preserving rows for currently running automation jobs and leaving other session rows untouched.
tasks flow list | show | cancel
openclaw tasks flow list [--status <status>] [--json]
openclaw tasks flow show <lookup> [--json]
openclaw tasks flow cancel <lookup>
The flow lookup token accepts a flow id or owner key. Use these when the orchestrating Task Flow is what you care about rather than one individual background task record.
Chat task board (/tasks)
Run /tasks in any chat session to see background tasks linked to that session. The board shows up to five active and recently completed tasks with runtime, status, timing, and progress or error detail.
When the current session has no visible linked tasks, /tasks falls back to agent-local task counts so you still get an overview without leaking other-session details.
For the full operator ledger, use the CLI: openclaw tasks list.
Control UI
The web Control UI has a Tasks page in the sidebar with live active and recent background tasks. Use it to inspect progress, open linked sessions, refresh the ledger, cancel queued and running tasks, or retry or dismiss a blocked completion delivery. Task detail keeps execution status and delivery status separate and exposes the retained result for copying.
Chat panes also have a collapsible Background tasks rail scoped to the pane's agent, with running work, stop controls, and a finished section. Open it from the activity toggle in the pane header (or the floating activity button in single-pane chat).
Select a task to replace the list with a compact detail view inside the rail; use the back button to return to the list. The detail view shows the bounded input prompt, latest output or error summary, timing, and current tool activity. Subagent details stay in the rail rather than opening their child conversation in the main chat pane; linked-session actions remain available for task runtimes intended for direct inspection. On iOS, open Chat actions → Background Tasks; on Android, open the Chat overflow menu and select Background tasks. Both mobile views use the same Running and Finished grouping and open task details on selection.
Status integration (task pressure)
openclaw status includes an at-a-glance task line:
Tasks 2 active · 1 queued · 1 running · 1 issue · audit clean · 6 tracked
The summary counts active work (queued + running), failures (failed + timed_out + lost), audit findings, and total tracked records; the JSON payload also breaks counts down by runtime (acp, subagent, cron, cli).
Both /status and the session_status tool use a cleanup-aware task snapshot: active tasks are preferred, expired rows are hidden, and terminal tasks only appear for a short recent window (5 minutes), with failures focused when no active work remains. This keeps the status card on what matters right now.
Storage and maintenance
Where tasks live
Task records and delivery state persist in the shared OpenClaw SQLite state database:
~/.openclaw/state/openclaw.sqlite (tables: task_runs, task_delivery_state, flow_runs)
Set OPENCLAW_STATE_DIR to move the whole state root (default ~/.openclaw) elsewhere; the shared database path moves with it.
The registry loads into memory on first use and persists every write back to SQLite, so records survive gateway restarts. WAL growth stays bounded through SQLite's default autocheckpoint threshold plus periodic PASSIVE checkpoints. After a checkpoint completes, the next commit resets the WAL and applies a 64 MiB journal_size_limit ceiling, so a reader cannot leave the file parked at a pathological high-water mark until restart. Shutdown and explicit maintenance checkpoints use TRUNCATE so normal closes reclaim WAL space without making the background sweeper wait on active readers.
Legacy sidecar stores from older installs (tasks/runs.sqlite, flows/registry.sqlite) are imported into the shared database by openclaw doctor.
Automatic maintenance
A sweeper runs every 60 seconds (first pass about 5 seconds after gateway start) and handles five things:
Reconciliation
Checks whether active tasks still have authoritative runtime backing. ACP tasks require a live in-process turn, subagent tasks use child-session state, automation tasks use active-job ownership plus durable run history, and CLI tasks with run identity use the owning run context. If backing state is gone for more than 5 minutes (30 minutes for childless native subagent tasks), the task is marked lost.
ACP session repair
Closes terminal or orphaned parent-owned one-shot ACP sessions, and closes stale terminal or orphaned persistent ACP sessions only when no active conversation binding remains.
Cleanup stamping
Sets a cleanupAfter timestamp on terminal tasks (terminal time + retention window). During retention, lost tasks still appear in audit as warnings; after cleanupAfter expires or when cleanup metadata is missing, they become errors.
Pruning
Deletes records past their cleanupAfter date.
Task Flow retention
Deletes terminal Task Flow records after 7 days. A blocked flow is terminal only when it has endedAt; resumable managed blocked flows remain registered.
Note
Retention: terminal task records are kept for 7 days (
lostrecords for 24 hours), then automatically pruned. No configuration needed.
How tasks relate to other systems
Tasks and Task Flow
Task Flow sits on top of background tasks as the orchestration layer. Over its lifetime, a single flow can coordinate multiple tasks through managed or mirrored sync modes. To look at individual task records, use openclaw tasks, and to examine the orchestrating flow, use openclaw tasks flow.
Tasks and automations
OpenClaw's shared SQLite state database holds automation job definitions, runtime execution state, and run history. A task record is created for every automation run, whether main-session or isolated, using the silent notify policy. This means automation runs get tracked without producing their own task notifications.
Refer to Automations.
Tasks and heartbeat
Heartbeat runs are main-session turns, so they do not generate task records. Upon completion, a task can trigger a heartbeat wake, letting you see the result without delay.
Refer to Heartbeat.
Tasks and sessions
A task can point to a childSessionKey (where the work executes) and a requesterSessionKey (who initiated it). The agent performing the work is identified by its agentId, while the requester and owner fields preserve the launch and control context. Sessions represent conversation context; tasks layer activity tracking on top of that.
Tasks and agent runs
The agent run doing the work is linked through a task's runId. Agent lifecycle events, such as start, end, or error, update the task status automatically, so manual lifecycle management is unnecessary.
When execution identity collection is switched on, OpenClaw also attaches the exact admitted contextId and executionId to Gateway CLI, ACP, and automation task rows, as well as their mirrored flow rows. This serves inspection provenance only: runId stays correlation, task and flow status remain authoritative, and a missing or mismatched binding never alters execution or settlement. openclaw audit --execution <id> --explain modifies the existing rows without copying task or flow content into the generic decision-fact table.
Related
- Automation - a summary of every automation mechanism
- CLI: Tasks - CLI command reference
- Heartbeat - periodic main-session turns
- Automations - scheduling background work
- Task Flow - flow orchestration above tasks