Everything external talks to the Sirloop orchestrator over one JSON HTTP API at http://127.0.0.1:8080. The dashboard is just its most polished client: if you can curl, you have the whole control tower. This page covers the access rules and the routes you'll actually use — the complete route reference ships inside the product.
Ground rules
- Loopback only. Control endpoints require a loopback peer and a loopback
Hostheader (localhost/127.0.0.1/[::1]). LAN viewers and DNS-rebinding pages get403. The only unauthenticated surface is the hook-relay telemetry pair/v1/agent-eventsand/v1/agent-events/gate, which is receive-only and fail-open. - JSON bodies, capped at 64 KB. Everything you
POSTis JSON. - One error shape. Failures are
{"error": "..."}with a meaningful status:400invalid,403denied,409conflict,422draft failed,429usage-limited. - Reads are cheap, dispatch is not. Poll
GETroutes freely; never start a run just to check status.
Reads — GET
| Route | Returns |
|---|---|
/api/state | The full hub snapshot: agents, recent events, last 30 runs, constraints, pauses, limits, usage, settings, projects, remotes. |
/api/stream | SSE: a hello frame with the full snapshot, then typed deltas (agent_event, run, constraints, catalog, paused, limits, usage, settings, remotes, projects). : ping every 15 s idle. |
/api/runs/<id> | One run record — status, events, timing. 404 if unknown. |
/api/frameworks | Coding-agent CLIs Sirloop can drive, with models and sub-agents per framework. |
/api/sessions | Adoptable on-disk CLI sessions (?tool=&limit=, newest first). |
/api/flows | Flow definitions plus live instances. |
/api/schedules | Schedule definitions plus next-due times. |
/api/projects | The mission board. |
/api/settings | Operator settings. |
/api/usage | Plan-usage cache (?refresh=1 forces a re-probe). |
/api/remotes | Paired-peer registry. |
/api/export | Durable config bundle (download). |
Control — POST
| Route | Body → effect | ||
|---|---|---|---|
/api/instruct | {tool, prompt, cwd?, model?, agent?, session?, worktree?} → dispatch a run → {ok, run_id, warning?}. | ||
/api/flows | `{action: "run" \ | "save_def" \ | "delete_def", ...}`. |
/api/schedules | `{action: "save" \ | "delete" \ | "run", name, def?}`. |
/api/projects | {action: ...} — mission-board CRUD, plan, run_task. | ||
/api/sessions | {action: "add", tool, session_id, cwd?} — adopt a session (visibility, not dispatch). | ||
/api/settings | Partial settings update. | ||
/api/pause | {source, paused} — per-agent kill switch; a paused source is denied at the gate. | ||
/api/constraints | Replace the guardrail constraint list. | ||
/api/prompts | {name, content} — quick prompts (empty content deletes). | ||
/api/import | {format, version, config, mode?} — apply a config bundle. | ||
/api/clear | Wipe the live view (keeps guardrails and pauses). | ||
/v1/agent-events | Ingest one relay event → {ok: true} (never 5xx). | ||
/v1/agent-events/gate | Ask before a risky tool call → {decision, reason} (fail-open). |
Worked examples
Snapshot, trimmed to the runs:
curl -s http://127.0.0.1:8080/api/state
{
"agents": [ { "source": "claude", "status": "idle", "cwd": "C:\\dev\\scratch" } ],
"runs": [ { "id": "r-8f31c2", "status": "done", "tool": "claude" } ],
"events": [ "...last 150, newest last..." ],
"projects": [], "remotes": [], "now": "2026-09-12T09:41:00Z"
}
Dispatch a run:
curl -X POST http://127.0.0.1:8080/api/instruct \
-H "Content-Type: application/json" \
-d "{\"tool\": \"claude\", \"prompt\": \"Summarize today's commits.\", \"cwd\": \"C:\\dev\\repo\"}"
{ "ok": true, "run_id": "r-9a04b7" }
Subscribe to the live stream:
curl -N http://127.0.0.1:8080/api/stream
data: {"type": "hello", "data": { ...full snapshot... }}
data: {"type": "run", "data": {"id": "r-9a04b7", "status": "running"}}
data: {"type": "agent_event", "data": { ...one relayed tool call... }}
A slow consumer that falls behind resyncs simply by calling /api/state — the stream is a convenience, the snapshot is the truth.
Guardrails and the gate
Hook relays report every tool use to POST /v1/agent-events and ask permission first via POST /v1/agent-events/gate. The gate iterates your enabled constraints in order — first pattern hit denies with a human-readable reason, otherwise the call is allowed. Constraints are plain case-insensitive patterns you manage through /api/constraints (or the dashboard settings). The pair is fail-open by design: telemetry must never take your agents down.
Where the full reference lives
The installed product ships the complete route reference, request/response shapes for every endpoint, and the plugin wire protocol under docs/ai/http-api.md next to the binary. What's on this page is the stable core that the dashboard itself uses.