Background tasks
How long operations like installs, downloads, and reindexing survive navigation, page close, and bot restart — with live progress bars when you come back.
Why a task system
Installing OpenClaw takes ~5 minutes. Pulling an Ollama embedding model takes 5–15. HTTP timeouts won't hold a connection that long, and users inevitably close the page. If we ran these as synchronous requests, any interruption would leave the server in a half-configured state.
So long operations become backend tasks: fire-and-forget units of work with per-step progress, reconnectable from any client.
Lifecycle
- Frontend POSTs to an endpoint like
/api/servers/:id/rag/install. Backend returns{ taskId: "..." }immediately. - Task runs asynchronously in the task manager. Each phase calls
ctx.step(name).complete(detail)or.fail(detail). - Frontend hook
useTask(taskId)pollsGET /api/tasks/:idevery second and renders a live progress bar. - When the task finishes, polling stops automatically.
Reconnecting
If the user navigates away or closes the bot, the task keeps running on the backend. When the user returns:
useActiveTask(type, serverId)on mount asksGET /api/tasks/active?type=X&serverId=Yand reconnects to any running task of that type for that server.useServerActiveTasks(serverId)pollsGET /api/tasks/active-server?serverId=Yand returns all running tasks — used for the top banner in the RAG manager.
The UI state is also persisted at the module level (not React state), so expanded panels stay expanded across navigation and the progress bar picks up from where it left off.
Deduplication
Starting a task with the same (type, serverId, userId) tuple as an already-running one returns the existing task ID instead of spawning a parallel one. This prevents double-clicks from launching two parallel ollama pull processes that would corrupt each other.
Per-user authorization
Every task GET checks that the caller's JWT user ID matches the task's creator. You can only see and reconnect to your own tasks.
Retention
Completed and failed tasks stay in memory for 1 hour, then get garbage-collected. This gives enough window for the user to read the final error message.
Which operations use tasks
rag-install— installing the Python venv + sqlite-vec + helper scriptsollama-install— 9-step manual Ollama install (nocurl | sh)ollama-pull:<model>— downloading an embedding model- Reindex is not a task (fast enough to be a regular POST)