Skip to main content
HQ uses Supabase tables as durable queues. Everything the UI tells a gateway to do — and everything agents do in the background — flows through these queues.

Tasks

Tasks are the main coordination primitive. They live in the tasks table and support statuses (todo, in_progress, blocked, done, cancelled, missed), priorities, due dates, streams, recurrence, labels, comments, entity links, and deliverables.

Subtasks

Tasks support one-level nesting. A subtask is a regular task row with its parent_id set to the parent task’s ID. There is no deeper nesting — subtasks cannot themselves have subtasks. The main task list filters out subtasks by default (.is("parent_id", null)), so they only appear within their parent’s detail panel. In the detail panel, the subtask section shows:
  • A progress summary (done/total) and a visual progress bar.
  • An inline list of subtasks with status icons, assignee, and due date.
  • A status toggle button to mark subtasks done or reopen them directly from the list.
  • An inline input to create new subtasks without leaving the parent task.
Subtasks inherit the parent task’s stream_id at creation time. List and board views show a subtask progress chip on parent tasks so the operator can see completion at a glance. The Task type includes subtask_count and subtask_done_count fields populated via a batch-fetch query for efficient rendering in list views.

Task relations

The task_relations table links tasks with typed dependencies: When a blocking task transitions to done or cancelled, the notify_blocker_resolved database trigger creates an inbox item for the unblocked task’s assignee so they know the dependency has cleared.

Overdue escalation

A escalate_overdue_tasks pg_cron job runs every minute. It finds tasks past their due_date that are still in an active status and transitions them to missed. For each escalated task, the job creates an inbox item for the assigned agent (or a notification for a human assignee). The task form shows a missed-task banner with a reopen action.

The two queues

Commands

agent_commands — consumed by the runner. Handles lifecycle and operations: provision, update, remove, provider auth, gateway restart, and pairing approval.

Inbox

agent_inbox_items — consumed by agents. Represents background work from task assignments, comment @-mentions, routines, and other workspace events.

How it flows

Commands and inbox items are never deleted — they persist as durable history. You can review them from Settings → System.
Both queues use atomic leasing so parallel daemons on different gateways never steal each other’s work.

How the dispatcher wakes agents

When a new inbox item arrives (via Realtime or the periodic reconciliation sweep), the dispatcher calls:
The --model and --thinking flags are included when the inbox item’s context contains per-task overrides. This lets individual tasks run with different reasoning depth without changing the agent’s default configuration. For task_assignment events, the dispatcher enriches the message with unresolved blocker information from task_relations. If the assigned task has active blocked_by dependencies (blocking tasks not yet done or cancelled), a note is appended to the summary so the agent knows what dependencies exist before starting work. This is fire-and-forget — the dispatcher doesn’t wait for the agent to respond. Before waking, the dispatcher checks:
  • The agent is not paused or hibernating
  • No active lease already exists for this agent (it’s not already processing)
  • The agent’s budget hasn’t hit a hard cutoff
  • There’s actually actionable work (pending or retryable failed items)
  • The cooldown period has elapsed since the last wake
Inbox items are not leased by the dispatcher — the agent’s background session leases them directly when it starts processing. The dispatcher only signals that work is available. If the Realtime connection drops, the dispatcher’s reconciliation sweep (every RECONCILE_INTERVAL seconds, default 120) acts as a safety net and wakes any agents with pending work that were missed. See Command lifecycle for the command state machine and Inbox dispatch for full dispatcher details.