Why this is a platform feature
In Capsule, background execution is part of the same app model as chat, pages, and deploys. That means:- tasks can share the same collections, settings, filesystems, and integrations as the rest of the app
- the UI can render task state directly with task cards and task boards
- you do not need to split the app across a request stack and a second job stack before the product is even useful
Tasks
Tasks are declared with@app.task() or @cpsl.task().
They are useful for:
- slow API calls
- report generation
- batch processing
- retries and cancellation
- work that should continue after the current reply
TaskHandle objects from .submit() and .schedule().
What belongs in a task?
As a rule of thumb, put work in a task when any of these are true:- it talks to an external system
- it might take more than a quick request-response turn
- it should retry safely
- the user should be able to leave the page while it keeps running
- the result should show up later in collections or a workflow page
Schedules
Schedules are declared with@app.schedule(cron) or @cpsl.schedule(cron).
Use them for:
- recurring syncs
- periodic cleanup
- digests
- precomputation and cache warming
Task UI
Capsule has first-class task UI:session.show_task(handle)renders an inline task cardcpsl.ui.TaskBoard(...)renders a full-page kanban view
How background work stays observable
Capsule gives you a few ways to make async work visible to the user:session.show_task(handle)for inline task cards from chatTaskBoard(...)for page-level visibility- collections and data handlers for richer audit trails or workflow state
Runtime context
Tasks can optionally receive asession:
- with a bound
session, the task can reply, notify, stream, and accesssession.db - without one, the task still runs, but there is no live chat target
cpsl.current_session() when they need owner-scoped runtime identity.
Process isolation
Setprocess=True when the task should run in a separate OS process for:
- CPU parallelism
- crash isolation
- heavy local computation
Locking
Tasklock= values prevent duplicate work for the same logical key:
How background work stays safe
The safety model is a mix of ordinary engineering and Capsule primitives:- use
lock=when duplicate work would be harmful - use
retries=when a task should self-heal from transient failures - keep the side-effecting code inside the task instead of the chat turn
- write the resulting state back to collections so pages and later turns can inspect it