HTTP API¶
The daemon exposes HTTP routes for the dashboard, hooks, CLI helpers, and client libraries. The stable public client surface is the CLI, MCP tools, and Python client; raw HTTP routes may move faster.
Primary route groups¶
/healthand status routes for daemon checks./peersfor peer registration, listing, lookup, and lifecycle operations. Peer records include optionalmodel, the last observed runtime model reported by the backend. IncludesGET /peers/{id}/doctor(read-only diagnostic report with contradiction detection) andPOST /peers/{id}/rehook(non-destructive inbound ws-hook recovery, same-host, dry-run by default).POST /peers/{id}/offlineaccepts an optional body{reason, source, detail, terminal}recording the truthful cause in the event log (e.g.session_end,agent_exited,pane_takeover).terminal: trueretires the peer: its websocket is severed and reconnects claiming that peer_id are rejected (HTTP 409 / ws errorpeer_retired) unless they carry a liveagent_pid. An empty body keeps the legacy plain-offline behavior.GET /panes/orphanslists local tmux panes not bound to any registered peer (with a display-only backend hint);POST /panes/{pane_id}/linkadopts one — registers the peer AND establishes its inbound ws-hook, rolling the registration back if no live transport connects (fail-closed against ghosts). Driven byrepowire link./ask,/ack, and/asks/pendingfor ask lifecycle.POST /asks/{correlation_id}/waitblocks (bounded, ~50s per call) until the ask is answered or acked, returning a resolution snapshot{status, reply, outcome, close_reason, ...}or{status: "pending"}on timeout with nothing recorded. First wait switches the ask to pull reply delivery so the reply is retained on the ask instead of injected at the asker. Backs the MCPwait_on_acktool./answerrecords a typed answer to a structured question;POST /questions/ask-blockingregisters a blocking structured question (tool permission) and holds the connection open until it is answered or the daemon's wait cap elapses, then returns the typed answer (fail-closed: a tool-permission question denies on timeout). Used by blocking transports such as the ACP broker and the Claude CodePreToolUseapproval hook./queryis a legacy blocking compatibility route. It opens a structured text ask through the ask lifecycle, waits for the recipient's answer/ack, and returns the old{text, error, status}response shape for existing clients./traces/{trace_id}returns the recorded delivery stages for an ask (correlation_id) or notify (delivery_id) from the local delivery trace ledger./messagesand WebSocket routes for live delivery./schedulesfor one-shot and recurring scheduled messages./jobs/ work routes for durable tracked work./attachmentsfor upload and download./dashboardfor the static dashboard bundle.
Jobs Execution Policy¶
POST /jobs accepts process_scope and continuity for path/backend durable
jobs. Unassigned path/backend jobs default to process_scope=per_fire, so each
run uses a daemon-spawned or backend-resumed executor process that is released
after terminal completion. Reused persistent executors and explicitly assigned
peers are not killed by per-fire cleanup. One-shot jobs default to
continuity=fresh; recurring jobs default to continuity=resume, so the next
fire resumes backend-native runtime context when a runtime session id is
available. Use continuity=fresh to avoid backend resume.
Jobs State Semantics¶
Fire completion is structural: dispatch asks come from the built-in @jobs
service peer, the daemon arms the fire when the executor's prompt turn is
observed (running / phase turn_started), and the executor's next assistant
turn completes it with the final message as result_summary. Executor death
(terminal peer offline or daemon-restart reconcile) fails in-flight fires with
executor_died. Only the runner's dispatching phase is lease-bounded —
delivered fires are never reaped by a wall clock. Every state transition
emits a job_state_changed event, and terminal states best-effort notify the
owner (owner → creator → circle orchestrator). PATCH /jobs/{id} remains
available for progress enrichment and the explicit hold-open escape hatch.
Jobs List Views¶
GET /jobs returns the full durable-work list by default. Dashboard-style clients that only need row data can use:
The summary view keeps the same { "work": [...], "recurring": [...] } envelope and preserves ids, state, timestamps, ownership/routing fields, result summaries, and trimmed execution target/delivery metadata. It omits heavier detail fields such as full requests, provenance, runner state, prompt bodies, and progress history. Fetch GET /jobs/{id}/status for the selected job or recurring cal-* template when full detail is needed.
Auth¶
When daemon.auth_token is configured, clients send: