Background task dock
Where long-running work lives while you keep typing.
Real agent products can't stop the conversation to wait for a ten-minute job. They need somewhere to put the job while it runs, so the user can keep typing, come back, and not lose the thread. That somewhere is the dock.
The dock is the difference between a chat app and an operating system. It's the moment the product stops pretending that every interaction is a turn-by-turn dialogue and admits that some of its work is long, some is parallel, and most deserves a persistent surface the user can glance at.
"Long tasks need a home that isn't the scroll."
Four states, one row each.
A task in the dock is always in one of four states: queued, running, done, paused. Each state has its own shape — a ring that fills, a pulse, a checkmark, a muted dash — so the user can read state at a glance without decoding a status string.
Every row surfaces the two most useful pieces of information for that state. For running, that's ETA and what the task is currently doing. For done, that's how long ago, with a click-to- expand receipt. For queued, that's why it hasn't started yet.
- Draft quarterly reviewmerging 4 docs, drafting exec summary● running~2m
- Audit invoice set · 134 rowscross-checking vendor names against contracts● running~5m
- Summarize 9 customer callswaiting for composer to free up● queuedstarts after #1
- Migrate 6 Notion pages to Docscompleted 2m ago● donedone · 14 edits
The dock persists while you keep typing. A task you can see is a task you can cancel.
Long tasks are a different trust surface.
When a user starts a task that will take minutes, they make a small loan of trust: I believe this will finish, I believe you will tell me when, I believe I can cancel without breaking the product. The dock is how you service that loan — by keeping the task visible, making its state legible, and honoring cancel as a real primitive.
A product that loses a long task in a scroll, or shows "complete" on something the user can't find, spends that trust down fast.
The dock I'd ship.
- One tray, not many. If background tasks live in three places — a notification, a toast, and a tray — the user has to learn three habits. One tray, one place, one set of shortcuts.
- Ring over bar. A ring progress is more readable at small sizes than a bar, and holds its meaning when truncated. Pair the ring with a numeric percent only if the task is long enough that the user might want to estimate time.
- Done expands in place. When a task completes, its row should expand into the receipt — what was done, what was touched, what to click next. Do not open a new tab. Do not open a modal.
The orphaned task.
The worst failure mode for this pattern is the orphaned task: a job that keeps running on the server after the user dismissed it, because cancel-in-the-UI doesn't wire all the way through to cancel-in-the-backend. The user thinks it's gone. Compute is still burning.
Make cancel mean cancel. If the system can't truly stop the task, tell the user what it can and can't do.
What this pattern gets wrong when it gets wrong.
- Orphaned task
- A task that was started, never completed, and is no longer visible in the interface, even though compute may still be running.
- Ambiguous state
- Running, done, errored, paused all look the same. The user has to infer from context.
- Throttle silence
- A rate limit, queue, or budget cap that silently slows or stops the product without telling the user why.
Three shipping variants worth copying.
- A bottom-right dock with four rows, one per state
- A ring progress that fills as the task completes
- A done-task card that expands into the full receipt in place