Tasks API
Task reads (list, detail, tree, bulk-delete) live under /projects/{slug}/tasks. Mutating actions (retry, cancel, bulk-retry, purge a queue, plus worker control) go through /projects/{slug}/commands so the brain can mint an audit-chained command record and dispatch it to the responsible agent.
List tasks
Section titled “List tasks”GET /api/v1/projects/{slug}/tasksRole: viewer.
| Query param | Type | Notes |
|---|---|---|
state | string | One of received, started, succeeded, failed, cancelled, retried, lost. |
priority | string | Comma-separated, e.g. critical,high. |
name | string | Exact match on task name. |
search | string | Full-text across name, queue, worker. |
queue | string | Exact match. |
worker | string | Exact match on worker_name. |
since / until | RFC 3339 | Bound on received_at. |
cursor | opaque | Pagination cursor from the prior page. |
limit | int | 1..5000. Default from server settings. |
format | string | csv, xlsx, or json. Non-JSON overrides pagination and streams the full result. |
fields | string | Comma-separated projection for export. |
Response (JSON mode):
{ "items": [ { "id": "01H...", "project_id": "...", "engine": "celery", "task_id": "9d2c...", "name": "email.send", "queue": "default", "state": "failed", "priority": "normal", "args": ["<redacted>"], "kwargs": {"to": "<email>"}, "result": null, "exception": "ValueError: ...", "traceback": "...", "retry_count": 0, "eta": null, "received_at": "...", "started_at": "...", "finished_at": "...", "runtime_ms": 142, "worker_name": "worker-1@host", "parent_task_id": null, "root_task_id": null, "tags": [], "created_at": "...", "updated_at": "..." } ], "next_cursor": "..."}Get task
Section titled “Get task”GET /api/v1/projects/{slug}/tasks/{engine}/{task_id}Role: viewer. Same TaskPublic shape as the list endpoint.
Get task tree (canvas / chain / group)
Section titled “Get task tree (canvas / chain / group)”GET /api/v1/projects/{slug}/tasks/{engine}/{task_id}/treeRole: viewer. Walks to the task’s root via root_task_id (or treats the task itself as root if the field is null) and returns every task in the project sharing that root. Capped at 500 nodes; the response carries truncated: true when the cap kicks in.
Bulk delete
Section titled “Bulk delete”POST /api/v1/projects/{slug}/tasks/bulk-deleteRole: admin. CSRF-protected. Throttled by a per-route bulk-action limiter.
{ "task_ids": ["..."], "filter_state": "failed", "filter_name": "email.send", "filter_queue": "default", "filter_since": "2026-04-16T00:00:00Z", "filter_until": "2026-04-16T23:59:59Z"}task_ids is capped at 1000 entries. The handler scopes every delete to the project regardless of any body field. Returns {"deleted_count": N}.
Commands (retry, cancel, bulk-retry, purge-queue)
Section titled “Commands (retry, cancel, bulk-retry, purge-queue)”Every action that needs an agent round-trip is issued as a command. The brain inserts a row in commands, signs it, and pushes it over the agent’s WebSocket; the agent runs the action and POSTs the result back, which the brain records as the command outcome.
List commands
Section titled “List commands”GET /api/v1/projects/{slug}/commands?status=&cursor=&limit=Role: viewer. status is one of issued, dispatched, succeeded, failed, timed_out.
Get command
Section titled “Get command”GET /api/v1/projects/{slug}/commands/{command_id}Role: viewer.
Retry one task
Section titled “Retry one task”POST /api/v1/projects/{slug}/commands/retry-taskRole: operator.
{ "agent_id": "...", "engine": "celery", "task_id": "9d2c...", "idempotency_key": "optional-string", "override_kwargs": {"foo": "bar"}}override_kwargs is capped at 64 KiB JSON.
Cancel one task
Section titled “Cancel one task”POST /api/v1/projects/{slug}/commands/cancel-taskRole: operator.
{ "agent_id": "...", "engine": "celery", "task_id": "9d2c...", "idempotency_key": "optional-string"}Bulk retry
Section titled “Bulk retry”POST /api/v1/projects/{slug}/commands/bulk-retryRole: operator.
{ "agent_id": "...", "filter": {"state": "failed", "queue": "default", "name": "email.send"}, "max": 1000, "idempotency_key": "optional-string"}max is bounded 1..10000.
Purge a queue
Section titled “Purge a queue”POST /api/v1/projects/{slug}/commands/purge-queueRole: admin.
{ "agent_id": "...", "queue": "default", "confirm_token": "<hmac of (queue_name, observed_depth)>", "force": false, "idempotency_key": "optional-string"}Either confirm_token (computed from the current queue depth via the engine adapter’s expected_confirm_token helper) or force=true (logged at CRITICAL on the agent) is required.
Worker-control commands
Section titled “Worker-control commands”The same /commands router exposes five worker-control verbs the dashboard uses to manage running workers without touching the application code. Each command is signed, audit-logged, and dispatched to the named agent over the WebSocket.
Restart a worker
Section titled “Restart a worker”POST /api/v1/projects/{slug}/commands/restart-workerRole: admin.
{ "agent_id": "...", "worker_name": "celery@worker-1", "idempotency_key": "optional-string"}The agent sends a graceful restart signal to the named worker. The host process is unaffected; only the worker’s adapter state is recycled.
Resize a worker’s process pool
Section titled “Resize a worker’s process pool”POST /api/v1/projects/{slug}/commands/pool-resizeRole: admin.
{ "agent_id": "...", "worker_name": "celery@worker-1", "delta": 2, "idempotency_key": "optional-string"}delta is bounded -100..100. Positive grows the pool, negative shrinks it. The agent’s engine adapter translates the delta into the engine-native call (Celery’s pool_grow / pool_shrink, etc.). Workers that do not support pool resize return ok: false on the resulting command_result.
Add a consumer
Section titled “Add a consumer”POST /api/v1/projects/{slug}/commands/add-consumerRole: admin.
{ "agent_id": "...", "worker_name": "celery@worker-1", "queue": "billing", "idempotency_key": "optional-string"}Tells the worker to start consuming from the named queue.
Cancel a consumer
Section titled “Cancel a consumer”POST /api/v1/projects/{slug}/commands/cancel-consumerRole: admin. Same body shape as add-consumer. The worker stops consuming from queue but keeps running on its remaining queues.
Set a per-task rate limit
Section titled “Set a per-task rate limit”POST /api/v1/projects/{slug}/commands/rate-limitRole: admin.
{ "agent_id": "...", "task_name": "myapp.tasks.send_email", "rate": "100/m", "worker_name": "celery@worker-1", "idempotency_key": "optional-string"}rate follows Celery’s grammar: integer optionally suffixed with /s, /m, or /h; "0" clears the limit. The pattern is enforced server-side so an obvious typo is rejected before the command row is minted. worker_name is optional: an omitted or empty value broadcasts the new rate to every worker subscribed to the broker. The agent-side action logs at CRITICAL when this global-throttle path fires, and the audit row carries the same flag.
Agent targeting
Section titled “Agent targeting”Every worker-control command requires an agent_id, which the agents API returns from its list endpoint. Use the agents list to discover the right id; the worker_name field references the engine-native worker identifier (e.g. Celery’s worker@host string), which the workers list under agents surfaces alongside the agent.