Skip to main content
Hugs
A hug is chosen by the team’s author in team.yml, or by agent code. The rest of asking — channels, expiry, reminders, policies, block and yield — works the same for every hug (Asking people).

In team.yml

A phase’s hug: block holds the defaults for the Hugs its agent opens, and name — the hug they ask with:
  • Built-ins need no install: form, approval.
  • A missing hug is caught before the run starts, like a missing agent: the pre-run check reports hug_unknown for a phase whose hug.name this daemon can’t find (Installing).
  • The review gate (agent: hug) always asks with approval; review: configures it — reviewers, message, inputs, labels (review.params), route targets (gate fields). For a different review page, use an ordinary phase with its own hug:, or a gate agent of your own.

In agent code

Every answer is checked against the definition before the policy sees it — with the params this Hug was opened with. An answer that fails is never treated as valid: it isn’t counted, the run’s log records the problems, the Hug page shows “1 answer couldn’t be used; waiting for a valid one”, and the person may answer again while the Hug is open (on_invalid: 'ignore', the only choice for now). res.value is only ever a checked value. The options — title, params, summary, attachments, channels, expires_in_min, reminders, policy, wait, on_invalid — and the errors are in ctx.ask options.

Attaching files

A hug’s page has no network: the files it shows are attachments, run files the agent attaches when it asks.
ctx.attach(paths) uploads workspace files (paths or globs; at most 25 files of 25 MB each) and returns references ({ artifact_id, name, size, content_type, sha256 }). A file that can’t be attached (no match, too large, outside the workspace) is logged and left out. The page reads attachments through the Hub with the viewer’s permissions — pass their artifact_ids in the params so it knows which is which.

Waiting, and the re-entry rule

With wait: 'yield' the agent’s process ends while people answer, and cliqd runs the phase again when the Hug has news. The agent’s code runs again from the top — each ctx.ask finds its Hug again and returns its answer, so nobody is asked twice. Code before a yielding ctx.ask must be safe to run again: don’t attach files again on a resume (ctx.hug.resumed().length > 0 says you are resuming), and keep loops deterministic.

In LLM and CLI phases

Agents that drive a model (claude-api, openai-api, gemini-api, claude-code, codex, gemini, cursor) ask with the phase’s hug — hug.name, else form:
  • form: the model writes a cliq_hug block with { title, prompt, requested_inputs }, or a closing QUESTION: line.
  • Any other hug: the model is told the hug’s title, description and params (as JSON Schema, from its definition), and writes { "title": …, "params": { … } } in its cliq_hug block. Params the definition refuses go back to the model to fix (a CLI agent fails INVALID_HUG instead). The checked answer comes back as the next turn, as JSON, with files as saved paths.
A QUESTION: line is a one-answer form in any phase. Write the hug’s description for the model: what it asks, what each param means, and what comes back.

Answering locally

A cliqd that isn’t signed in to CliqHub serves the same page: cliq run prints the Hug’s link and opens it in your browser. See On your machine, including answering from scripts.