Skip to content
Agora by Olimpia
Esc
↑↓navigate↵open⌘Jpreview
On this page

HTTP API

Every endpoint of the Agora daemon, with authentication, request bodies and errors.

The daemon serves a JSON API under /v1 on 127.0.0.1:7788, plus the dashboard at /.

Conventions

  • Auth: Authorization: Bearer <token> on every endpoint except GET /v1/health. Streaming endpoints also accept ?token=. See tokens.
  • Acting as a cursor: with the admin token, send X-Agora-Cursor: <cursor id> to act as that cursor.
  • self: in /v1/cursors/{id}/..., a cursor token can use self as the id.
  • Errors: {"error": "..."} with 400 (bad request), 401 (missing or invalid token), 403 (not allowed), 404 (not found), 409 (surface locked; the body includes the lock) or 504 (timeout).
  • Durations in workspace config are strings like "10m" or numbers of seconds.

System

Method and path Description
GET /v1/health Liveness, no auth.
GET /v1/system Version, uptime, daemon resources, per-workspace memory and CPU.
GET /v1/me {admin, cursor} for the calling token.
POST /v1/viewer-tokens Admin. {workspace, control, ttl_seconds} → {token, expires_in}. TTL defaults to 3600, at most 86400.

Workspaces

Method and path Description
POST /v1/workspaces Admin or workspace permission. {name, config, start, labels} → 201 workspace. See configuration.
GET /v1/workspaces Workspaces visible to the token, with state, resources, viewers and cursors.
GET /v1/workspaces/{id} One workspace. ?detail=1 refreshes the detailed usage first.
DELETE /v1/workspaces/{id} Admin. Destroy. ?purge=1 also deletes its home, checkpoints, events and its profile (unless another workspace shares it).
POST /v1/workspaces/{id}/{op} Lifecycle and control operations, below.

Operations

POST /v1/workspaces/{id}/{op} with an optional JSON body:

op Body Description
start Boot the display.
suspend reason Checkpoint, close the browser and free everything. Needs workspace.
resume Rebuild and restore tabs to their owners.
freeze Stop all processes, keep RAM. Needs workspace.
thaw Continue a frozen workspace.
checkpoint reason, snapshot Record state; snapshot: true also copies the profile.
fork name New workspace with a copy of profile and home. Needs workspace.
resize width, height Change the screen size.
layout layout tile, max or float.
clipboard text Set the clipboard; returns {text}.
browser-restart Restart Chromium.
request-human reason Mark the calling cursor needs_human and emit human.requested.
control-take Human-priority lock on the whole workspace. Needs workspace.
control-return Release it; emits control.returned. Needs workspace.
acquire surface, ttl_ms, reason Lock win:<id> or tab:<target> for the calling cursor.
release surface Release a lock.
usage Detailed memory and CPU per process.

Desktop

Method and path Description
GET /v1/workspaces/{id}/windows Top-level windows: id, title, class, geometry.
POST /v1/workspaces/{id}/windows/{win} {action, x, y, width, height} with raise, move, resize, release (back to the layout) or close.
GET /v1/workspaces/{id}/screenshot Image. Query: window, x, y, w, h, format (jpeg or png), quality, max_width. The X-Agora-Shot header has an id for /v1/shots/{sid}.
GET /v1/shots/{sid} A stored screenshot.
POST /v1/workspaces/{id}/input Input on the caller’s own seat, below.
POST /v1/workspaces/{id}/apps Needs process. {command, args, restore} → 201 process. Runs as the apps user with DISPLAY set.
GET /v1/workspaces/{id}/processes Processes started in the workspace.
DELETE /v1/workspaces/{id}/processes/{pid} Kill one.
GET /v1/workspaces/{id}/clipboard {text}.
GET /v1/workspaces/{id}/locks Current surface locks.
GET /v1/workspaces/{id}/board Shared board: claims and posts after ?since=<seq> (limit).
POST /v1/workspaces/{id}/board {kind, topic, text} → 201 post. kind is claim, done, release, finding or note. A claim fails while another live cursor holds the topic or once it is done.

Input

POST /v1/workspaces/{id}/input:

action Fields
click x, y, button (1 left, 2 middle, 3 right), count
move x, y
drag x, y, x2, y2
scroll x, y, dx, dy (notches; dy > 0 scrolls down)
type text, optional window to focus first, delay_ms
key keys such as Enter, ctrl+l, alt+F4; optional window

no_raise: true clicks without raising the window.

Browser

Method and path Description
GET /v1/workspaces/{id}/tabs Tabs with owners.
POST /v1/workspaces/{id}/tabs {url, isolated, same_window, observe} → 201 {target, url, context}; with observe, also observation.
POST /v1/workspaces/{id}/tabs/{target} A tab action, below. Times out after 60 s, or timeout_ms + 5 s.

Tab actions

Body: {"action": "...", ...}. With observe: true, actions that change the page return observation: what is visible now, diffed against the last view of that tab.

action Fields Returns
navigate url, wait (load, domcontentloaded, none)
back, forward, reload
snapshot max_text (default 3000) snapshot, challenge
screenshot full_page, format, quality, max_width image (base64), mime, shot
click ref or x,y; button, count
hover ref or x,y
drag x, y, x2, y2 (HTML5 drag supported)
fill ref, text, submit
type text, optional ref to click first
insert_text text
press keys
scroll dx, dy (pixels), optional x, y
select ref, values (values or labels)
upload files (host paths), optional ref (otherwise the open file chooser)
eval expression (promises are awaited) the JSON value
wait selector, text or url_contains; timeout_ms (default 15000)
dialog accept, text
challenge challenge
audit audit
emulate width, height, scale, mobile (width 0 resets)
focus, info, close info returns tab

Streaming

These accept a viewer token, a cursor token of the same workspace (watch only) or the admin token, as a header or ?token=. ?mode=observation lowers the frame rate to 8 fps.

Method and path Description
GET /v1/workspaces/{id}/stream/ws WebSocket. Binary messages are H.264 frames with a 13-byte header (key flag, 64-bit PTS, 16-bit width and height). Text messages from the client are input events when the token allows control.
POST /v1/workspaces/{id}/stream/webrtc {sdp, mode} with an SDP offer → {sdp, viewer} with the answer.
GET /v1/workspaces/{id}/stream/jpeg Damage-driven JPEG frames for light clients; unchanged frames are skipped. ?cursor=<id> crops to that cursor’s window, ?window=<id> to one window.

Cursors

Method and path Description
POST /v1/cursors Admin or spawn. Body below → 201 {cursor, token}. If the launch fails, the cursor is still returned with error.
GET /v1/cursors Query: workspace, parent, root, active=1.
GET /v1/cursors/{id} Status, progress, result, usage.
GET /v1/cursors/{id}/inbox Messages after ?since=<seq>.
DELETE /v1/cursors/{id} Delete a cursor.
POST /v1/cursors/{id}/{op} Operations, below.
POST /v1/wait {ids, all, timeout_ms} → {cursors, timeout}. Waits for all (default) or any.

Create body:

Field Description
name, goal, labels
workspace Defaults to the parent’s.
parent Defaults to the calling cursor.
permissions Subset of desktop, browser, process, spawn, message, workspace; intersected with the parent’s.
budget max_cursors (direct children), max_depth.
launch {adapter, model, effort, prompt, command, tools, profile, env}. See launching subagents.
worktree {repo, branch, base, ports}.

Operations (POST /v1/cursors/{id}/{op}, by the cursor itself, an ancestor or the admin):

op Body
status status, detail
report message, percent
complete result (any JSON)
fail error
cancel reason, cascade (default true)
pause, resume
message body (any JSON). Any cursor can message another.
transfer parent, workspace
wait timeout_ms → {cursor, timeout}

Events

Method and path Description
GET /v1/events Query: workspace, cursor, types (comma-separated, * suffix allowed), since, limit (≤ 500), wait_ms (long poll, ≤ 120000) → {events, seq}.
GET /v1/events/stream Server-sent events with the same filters. Heartbeat every 25 s.

Non-admin tokens only see events of their own workspace.

Event types: workspace.created, workspace.state, workspace.checkpoint, workspace.forked, workspace.resumed, workspace.recovered, workspace.expired, workspace.destroyed, workspace.budget_exceeded, desktop.started, desktop.resized, desktop.window, desktop.windows, desktop.screenshot, desktop.crashed, browser.started, browser.stopped, browser.crashed, browser.tab.created, browser.tab.opened, browser.tab.navigated, browser.tab.closed, browser.tab.restored, browser.page.loaded, browser.dialog.opened, browser.dialog.closed, browser.filechooser.opened, browser.download.*, browser.challenge.detected, cursor.created, cursor.status, cursor.progress, cursor.action, cursor.pointer, cursor.message, cursor.transferred, cursor.ended, cursor.deleted, board.post, agent.launched, agent.usage, agent.exited, control.acquired, control.released, control.lost, control.taken, control.returned, human.requested, process.started, process.exited, viewer.attached, viewer.detached, stream.state, scheduler.suspend, scheduler.tab_closed, worktree.created, worktree.removed.

Worktrees

Method and path Description
POST /v1/worktrees Admin or process. {repo, branch, base, ports} → 201 worktree with path, port_base, ports.
GET /v1/worktrees All worktrees.
DELETE /v1/worktrees/{id} Admin. ?force=1 removes even with changes.

Last updated on

Was this page helpful?