Skip to main content
control plane
Humans use a user PAT (cliq_tok_…, including session-scoped login PATs) with a grant. Daemons use a realm token (cliq_dt_…).
Interactive OpenAPI on this site: Hub API tab — one catalog covering /v1, /internal (BFF-only), and /a2a.

Auth

User PATs are rejected for daemon enroll / claim. Grants: Auth.

Realms & tokens

Realm CRUD, members, desired teams (add_team / remove_team), and A2A admin (POST /v1/realms/a2a { action }) are under /v1/realms/* — see Realms. Roster: POST /v1/teams/get { realm_id }. Invite search: POST /v1/users/get { realm_id, query }. A2A bearer: POST /v1/auth/generate_token | rotate_token { type: "a2a", realm_id }. Public card/send: A2A tab.
Or: cliq auth token laptop --realm <realm_id>. Create response is { token, name, id, realm_ids } (plaintext once). Revoke via /auth/revoke_token with type: "realm". Public invoke (host root, not /v1): GET /a2a/o/{org}/r/{slug}/.well-known/agent-card.json, POST /a2a/o/{org}/r/{slug}/send.

Platform agents (catalog)

Hub SoT is cliq.agent_catalog (AgentCatalogEntry), exposed as Hub API → Agents (/v1/agents/*). Overview: Agents. Built-ins (is_system: true) ship with cliqd — there is no /v1/agent-pack/*. Daemons resolve agents from the local agents path (CLIQ_AGENTS_PATH / agents.path); register custom agents with cliq agent register. Team install does not download agent binaries. Realm-scoped agent settings use /v1/agents/get_settings and update_settings with optional realm_id (no /v1/realms/agents/*).

Daemon enroll

Daemons join a realm with a realm token (cliq_dt_…), not with /v1/realms/* connect/disconnect. On cliq login / daemon boot, the daemon orchestrates mint + key fetch itself (no Hub shortcut endpoint):
  1. POST /v1/auth/generate_token { type: "realm", realm_ids, permissions: { auto_enrolled: true, … } }
  2. POST /v1/auth/get_dispatch_public_key { realm_id }
  3. POST /v1/daemons/register with the minted cliq_dt_…
  4. Heartbeat for liveness
auto_enrolled: true marks bootstrap tokens for bulk revoke on logout. POST /v1/realms/a2a actions mesh_connect / mesh_disconnect talk to an external A2A mesh (e.g. Svantic) — they do not register daemons. POST /daemons/get (user credential) returns daemons in your realm intersection — same data as CliqHub Daemons.

Daemon → Hub durability

Every daemon buffers state changes (runs, teams, workspaces, events) in a local SQLite hub_outbox and ships them to Hub with retry. Hub → daemon commands use the separate command_outbox. There is no operator HTTP admin surface for either queue (no /daemons/outbox/*, no daemon /v1/outbox/*). When the local dead count crosses zero, the daemon emits daemon.outbox.dead / daemon.outbox.recovered catalog events — wire notification rules on those types for paging. For default-notify realm events (run.failed, phase.input_required, …), Hub prefers matching notification rules over the built-in realm:all_users in-app channel. Explicit notify.channels refs still win; with no rules and no refs, delivery falls back to all-users.

Dispatch

Exactly one of daemon_ids or realm_id for install. Realm run (Hub UI):
Pin to one daemon: POST /runs/enqueue with daemon_id + workspace_id + team_id.
Enqueue is a write on dispatch / runs. Daemon claims via POST /runs/claim, then Hub calls local /v1/execute.
Team install / uninstall (fleet fan-out): POST /v1/teams/install, /teams/uninstall — daemon_ids or realm_id. Live daemon inventory: POST /v1/teams/get / /workspaces/get { daemon_id } (live pull + Hub cache). Run mirror: daemon outboxes POST /v1/runs/create with workspace_id + workspace_path (+ optional name); Hub ensures the workspace row and team link in that call (no separate workspace upsert/add_team routes). Dispatch wire keys: POST /v1/auth/get_dispatch_public_key, /auth/rotate_dispatch_key { realm_id }.
Daemon wire JWT: POST /v1/auth/generate_token { type: "daemon_wire", realm_id }.
Run controls (user → daemon command outbox): POST /v1/runs/cancel, /runs/resume_from_phase, /runs/supply_inputs, /runs/force_terminate. See Concepts.

Internal vs public