Database Schema
HQ stores shared state in one Supabase project per workspace. The SQL source of truth lives indb/migrations/ and should be applied in filename order.
Migrations
For a fresh Supabase project, the onboarding wizard handles schema installation automatically with a one-click install. You can also run all files in filename order from the SQL Editor manually.
For an existing project, review each migration before applying. All files are idempotent (
IF NOT EXISTS, CREATE OR REPLACE) and safe to re-run.
Trust Model
HQ uses a multi-workspace isolation model.- Each Supabase project is a fully-isolated workspace. Within each database, every table enforces tenant-scoped RLS via
tenant_id. - Every tenant-owned table has a
tenant_idcolumn referencing thetenantstable. RLS policies enforcetenant_id = current_tenant_id()for theauthenticatedrole, wherecurrent_tenant_id()extracts the tenant ID from the JWT’sapp_metadata. - The
service_rolekey bypasses RLS and has unrestricted access (used by daemons and server actions). - Self-hosted deployments use a single default tenant (
00000000-0000-0000-0000-000000000000).
Core Tables
Workspace
workspace— singleton workspace profile, owner preferences, setup state, and budget defaults.audit_log— append-style audit events for important UI and system actions.notifications— operator-visible notifications such as budget warnings and command outcomes.
Agents and Gateways
agents— agent metadata, slug, status, gateway assignment, manager assignment, model/thinking configuration, and template metadata.gateways— registered gateway hosts, heartbeat state, labels, reachable URLs, and backup metadata (last_backup_at,last_backup_size_bytes).gateway_registration_tokens— short-lived hashed tokens used by Settings → Gateways → Add Gateway.agent_commands— command queue consumed by the runner daemon.agent_inbox_items— background-work queue consumed by agents through the dispatcher/runtime path.
lease_command(...)atomically leases pending commands for one gateway.start_command(...),complete_command(...), andfail_command(...)update command lifecycle state.lease_inbox_item(...),complete_inbox_item(...), andfail_inbox_item(...)update inbox lifecycle state.agent_reports_chain(...)returns an agent’s manager chain for cycle detection.
Usage and Budgets
agent_usage— append-only LLM call records with provider, model, tokens, cache tokens, estimated cost, and metadata.agent_budgets— per-agent budget config and current monthly rollup.
agent_usage_rollup trigger updates agent_budgets after each usage row. Budget status changes can create budget.warned and budget.exceeded notifications.
Important RPCs:
recompute_agent_budget(...)— recalculates the budget rollup from raw usage data.get_agent_daily_usage(...)— returns daily spend and token aggregates for the current period.
CRM
contacts— people records, core fields, pipeline status, priority, relationship strength, andextendedcustom data.organizations— company/group records andextendedcustom data.contact_organizations— links between contacts and organizations.interactions— timeline entries for calls, messages, notes, meetings, and other relationship events.templates,campaigns,draft_sets— outreach and campaign workflow data.
Tasks
tasks— operator and agent work items. Supportsmodel_overrideandthinking_overridecolumns for per-task model selection when assigned to an agent. Status enum includesmissedfor overdue escalation. Tasks support subtasks via theparent_idcolumn — tasks withparent_idset are subtasks of the referenced parent task. The main task list filters onparent_id IS NULLto show only top-level tasks; subtasks are displayed inline under their parent.streams— task grouping and workflow lanes.task_series— recurring task definitions. Series-levelmodel_overrideandthinking_overridepropagate to spawned instances.task_relations— task-to-task dependency links. Relation types:blocked_by,blocks,relates_to,parent_of,child_of. Theget_task_relations(p_task_id)RPC returns relations with joined task metadata. Anotify_blocker_resolvedtrigger fires when a blocking task reachesdoneorcancelled, creating inbox items for the unblocked task’s assignee.labels— managed workspace labels withname,color, and optionaldescription.task_labels— junction table linking tasks to labels.task_templates— reusable task group templates. Each template has aname,description, anditemsJSONB array containing task definitions withref,title,priority,assignee_role, andblocked_bydependency references.comments— polymorphic comments with mention support.entity_links— universal polymorphic links from tasks (and other entities) to knowledge items, contacts, organizations, collection records, and URLs. Extended with deliverable support:is_deliverableflag,review_status(draft,in_review,approved,revision_requested,rejected),review_note,reviewed_at, andsubmitted_by_agent_id. Agents submit deliverables via thehq_submit_deliverable.pyskill; humans review them in the task form’s Deliverables tab.
agent_inbox_items for affected agents. When a task has model/thinking overrides, they are included in the inbox item’s context JSONB and passed to the agent’s session at wake time. The escalate_overdue_tasks pg_cron job (every minute) marks tasks past their due date as missed and creates inbox items to notify assigned agents.
Knowledge
knowledge_items— unified knowledge store for pages, skills, files, and sources. Supports scope (workspace,agent, orlibrary), folders, tags, embeddings, and full-text search.knowledge_folders— folder hierarchy for organizing knowledge items.knowledge_item_agents— junction table linking agent-scoped items to specific agents. Also used to track agent-created skills.knowledge_chunks— chunked content with per-chunk embeddings for granular retrieval. Referencesknowledge_item_id.
- A workspace-scoped item is injected in full into every agent’s startup context.
- An agent-scoped item assigned to specific agents via
knowledge_item_agentsis index-only in those agents’ boot context and fetched on demand. - A library-scoped item is not included in boot context. It remains searchable and fetchable on demand.
kind = 'skill', scope = 'agent') via hq_skill_upsert.py. The script inserts into knowledge_items, links via knowledge_item_agents, and logs an audit entry with actor_type = 'agent'. The audit_log.summary field carries the agent’s one-line reason, which is surfaced on the agent detail page.
Important RPCs:
search_knowledge_items(...)— semantic vector search over items.search_knowledge_items_text(...)— full-text search over items.search_knowledge_chunks(...)/search_knowledge_chunks_text(...)— search at the chunk level, joining back to the parent item.lease_knowledge_items_for_indexing(...)— atomic lease for the embedder daemon.mark_knowledge_item_indexed(...)/mark_knowledge_item_failed(...)— embedding pipeline status updates.lease_knowledge_items_for_processing(...)/mark_knowledge_item_processed(...)— file processing pipeline.
Collections
collection_definitions— user-defined table schemas with typed fields.collection_fields— field definitions for each collection (text, number, date, select, etc.).collection_records— JSONB-backed rows belonging to a collection.collection_views— saved views (table, kanban, calendar) with filters and sorting.
Secrets
secrets— encrypted credentials stored as AES-256-GCM ciphertext (enc:v1:prefix format). Scoped per gateway, optionally per agent. Used for channel tokens (Telegram/Discord/Slack), integration OAuth tokens (Notion, Google Drive), and user-managed API keys.
gateway_id(required) — which gateway can decrypt and use this secret.agent_id(nullable) — if set, the secret is scoped to one agent; if NULL, it’s available to all agents on the gateway.key— the environment variable name (e.g.TELEGRAM_BOT_TOKEN,NOTION_SOURCE_A1B2C3D4). Validated/^[A-Z][A-Z0-9_]*$/.encrypted_value— the ciphertext. Never returned in API responses (excluded from SELECT columns in server actions).category—user(operator-managed),channel(auto-created at agent provision), orintegration(auto-created by OAuth flows).sync_status—pending→active(synced to gateway filesystem), orerror/waiting.
REPLICA IDENTITY FULL). The gateway’s secrets_sync daemon picks up INSERT/UPDATE/DELETE events and regenerates .env files within seconds.
Source Connections
source_connections— external source integrations with credentials and sync schedules. Providers are plugin-based — each connector is a self-contained folder undergateway/connectors/<provider>/with amanifest.jsonthat defines auth, UI metadata, and capabilities. Thewritableflag controls whether agents can write back to the source. Referencessecretsviasecret_idFK for encrypted OAuth token storage.source_sync_runs— sync execution history and status tracking.
Entity Links
entity_links— universal polymorphic linking table. Any owner (task, routine, collection_record, agent) can link to any target (knowledge_item, collection_record, contact, organization, task, or URL).
is_deliverable = true, the link represents an agent-submitted work product with a review workflow:
review_status:draft→in_review→approved/revision_requested/rejectedreview_note: human feedback on revision requests or rejectionssubmitted_by_agent_id: which agent submitted the deliverablereviewed_at: timestamp of the last review action
hq_submit_deliverable.py (page, URL, or record types). Humans review and approve/reject from the task form UI.
Routines
routines— event-driven and schedule-driven rules that turn CRM/task/collection/knowledge changes or cron ticks into agent inbox items.agent_inbox_items— stores the resulting work items, lease state, retry counters, dedup keys, and failure state.
spawn_routine_schedule_items via pg_cron to create inbox items at defined intervals.
Plugins
hq_plugins— plugin registry. One row per installed plugin. Source types:builtin,local,webhook,marketplace. Key columns:hooks(text array of subscribed events),config(operator settings JSONB),config_schema(JSON Schema for validation),webhook_url/webhook_secret(for remote plugins),capabilities(declared permissions),is_enabled(toggle). Subscribed to Supabase Realtime for live UI updates.hq_plugin_events— execution log. Every hook dispatch is recorded withplugin_id,hook,status(success/error/timeout/skipped),duration_ms, anderror_message. 30-day retention via pg_cron.hq_plugin_state— scoped key-value store for plugins. Keyed by(plugin_id, scope_kind, scope_id, state_key). Scope kinds:global,agent,task,workspace.hq_plugin_event_queue— lightweight append-only queue bridging SQL triggers to the plugin runner daemon. Triggers on tasks, agents, knowledge_items, inbox, comments, and secrets write here. The plugin runner polls/subscribes and dispatches to matching plugins. Processed rows are cleaned up hourly via pg_cron.
emit_plugin_event() function is a generic trigger function that writes to the event queue and strips sensitive fields (e.g. encrypted_value). It’s attached to 11 triggers across core tables.
See Plugins for the full architecture and Plugin events for the complete event reference.
Configuration Tables
field_definitions— custom fields by entity type.pipeline_stages— runtime-configurable pipeline stages.streams— task stream definitions.labels— managed labels for task categorization (Settings → Labels).task_templates— reusable task group templates with dependency graphs (Settings → Templates).
Status Enums
agent_status: ready, busy, error, provisioning, hibernating
gateway_status: ready, error, paused, provisioning, hibernating
Schema Version
The_schema_version table tracks the current schema version (currently at v31). The UI reads EXPECTED_SCHEMA_VERSION and compares it to the applied version to show update banners when migrations are pending.
Realtime
The runner and dispatcher use Supabase Realtime subscriptions for low-latency wakeups:- Runner listens for inserts into
agent_commands. - Dispatcher listens for inserts into
agent_inbox_items.
Applying Migrations
Fresh project:- Create a Supabase project.
- Open SQL Editor.
- Run the one-click schema install from the onboarding wizard, or manually run every
.sqlfile indb/migrations/in filename order. - Create an auth user and disable public signup unless needed.
- Back up the database.
- Run all migration files — they are idempotent (
IF NOT EXISTS,CREATE OR REPLACE) and safe to re-run. - Confirm the UI onboarding validator passes.

