Skip to content

agent.*

The pi coding-agent pane (agent: surfaces). See ht agent.

MethodParamsResult
agent.create{}"OK" — new agent pane in a new workspace
agent.create_split{ direction? }"OK" — "right"/"horizontal" (default) or "down"/"vertical"
agent.list{}string[] — live agent ids
agent.count{}number
agent.close{ agent_id | surface_id }"OK"

Agents call agent.ask_user when they need a structured human answer (yes/no, multiple choice, free text, or “confirm this command”). The bun-side queue holds the request until the webview modal, a sibling CLI, or Telegram resolves it. The agent.ask_user call itself is long-pending — it returns the response in one round-trip, no polling required.

MethodParamsResult
agent.ask_user{ surface_id: string, kind: "yesno"|"choice"|"text"|"confirm-command", title: string, body?: string, agent_id?: string, choices?: Array<{ id: string, label?: string }>, default?: string, timeout_ms?: number, unsafe?: boolean }{ request_id: string, action: "ok"|"cancel"|"timeout", value?: string, reason?: string }
agent.ask_pending{ surface_id?: string }{ pending: AskUserRequest[] }
agent.ask_answer{ request_id: string, value: string }{ resolved: boolean }
agent.ask_cancel{ request_id: string, reason?: string }{ resolved: boolean }

The asking call. Validates params strictly, drops a request into the queue, and does not respond until the request is resolved (answered, cancelled, or timed out).

ParamRequiredNotes
surface_idyesOriginating surface — drives modal anchoring + Telegram attribution.
kindyesOne of yesno / choice / text / confirm-command.
titleyesOne-line prompt.
bodynoMulti-line body (plain text; markdown is reserved for a future panel polish).
agent_idnoAttribution tag (e.g. claude:1) — shown in the modal header.
choicesfor kind=choiceNon-empty array. Each entry needs an id; label defaults to id.
defaultnoPre-filled / preselected value (interpreted per kind).
timeout_msnoAuto-resolves with action: "timeout" after this many ms.
unsafenoRender-hint for confirm-command — drives the destructive treatment in the modal and Telegram. The wire flag is preserved end-to-end.

Response value semantics by kind:

Kindvalue on action: "ok"
yesno"yes" or "no"
choicethe chosen choice id
textthe typed string
confirm-command"run" (only after the two-step ack → run gate)

action: "cancel" and action: "timeout" carry no value. action: "cancel" may carry reason.

Snapshot of pending requests. Useful for a webview / panel that just attached and needs to seed its local state, or for a sibling CLI that wants to show what’s open.

{ "id": "1", "method": "agent.ask_pending", "params": { "surface_id": "surface:3" } }
// { "pending": [
// { "request_id": "req:1", "surface_id": "surface:3", "kind": "yesno", "title": "Run install?", "created_at": 1714280000000 }
// ]}

surface_id filters; omit for the whole queue.

Resolve a request as the user’s answer. The original agent.ask_user long-pending call returns with action: "ok" and the supplied value.

{ "id": "2", "method": "agent.ask_answer", "params": { "request_id": "req:1", "value": "yes" } }
// { "resolved": true }

{ "resolved": false } means the id didn’t match — already resolved (timeout, cancel, or another path beat you to it) or never existed. Idempotent on unknown ids.

Resolve a request as cancelled. The original agent.ask_user returns action: "cancel" with the optional reason on stderr of the calling ht ask invocation.

{ "id": "3", "method": "agent.ask_cancel", "params": { "request_id": "req:1", "reason": "user is afk" } }
// { "resolved": true }

The webview and web mirror also receive these as push messages over the bun → client channels:

PushWhenPayload
askUserEvent: kind="shown"A new request lands in the queue.{ request: AskUserRequest }
askUserEvent: kind="resolved"A request resolves (answer/cancel/timeout).{ request_id, response: AskUserResponse }
askUserEvent: kind="snapshot"Reply to a askUserRequestSnapshot ping from the webview.{ pending: AskUserRequest[] }

The webview modal uses these to render in real time without polling.

MethodCLI
agent.ask_user (kind=yesno)ht ask yesno --title "..." --body "..."
agent.ask_user (kind=choice)ht ask choice --title "..." --choices a,b,c
agent.ask_user (kind=text)ht ask text --title "..." --default "..."
agent.ask_user (kind=confirm-command)ht ask confirm-command --title "..." --body "..." --unsafe
agent.ask_pendinght ask pending
agent.ask_answerht ask answer <id> <value>
agent.ask_cancelht ask cancel <id>