HTTP API Reference

aoe serve exposes a small HTTP API so external orchestrators (other agents, MCP tools, CI scripts) can drive sessions without attaching to a terminal. This page documents the orchestration endpoints. The web dashboard uses the same API surface plus additional internal routes.

Authentication

All endpoints require a token unless the server was started with --no-auth. The token is the one printed by aoe serve (or visible in the TUI’s Serve panel). Three transports are accepted:

TransportExample
Bearer header (recommended for clients)Authorization: Bearer <token>
Query parameter?token=<token>
Cookieaoe_token=<token> (set automatically by the dashboard)

Read-only mode (aoe serve --read-only) blocks every write endpoint with 403 read_only. Read endpoints work normally.

POST /api/sessions/{id}/send

Type a message into the agent and press Enter, the same way the TUI’s send-message dialog and the aoe send CLI do. Honors the per-agent paste-burst delay (e.g. Codex needs ~150 ms between text and Enter so its burst-detection window expires before Enter arrives).

Request body (JSON)

{ "message": "review the diff and pick the smallest fix" }

message is sent literally. Newlines inside the string are sent as shift-Enter (line break in the agent’s input box) and a final Enter submits the whole message.

Responses

StatusBodyWhen
200{"sent": true}Keys delivered to the tmux pane
400{"error": "message_empty"}message is empty or whitespace-only
403{"error": "read_only"}Server is in read-only mode
404{"error": "not_found"}No session with that id
409{"error": "session_not_running"}Session exists but the tmux pane is gone
500{"error": "tmux_error"} or {"error": "internal"}Unexpected failure (logged server-side)

Concurrent POSTs to the same id are serialized server-side, so two orchestrators racing on the same session won’t interleave keystrokes inside the pane. Concurrent POSTs to different ids run in parallel.

Example

curl -sS -X POST \
  -H "Authorization: Bearer $AOE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message":"summarize the failing test"}' \
  "http://localhost:7777/api/sessions/abc123/send"

GET /api/sessions/{id}/output

Snapshot of the session’s tmux pane. Use this after send to read what the agent printed back, or as a polling read-only view.

Query parameters

NameDefaultNotes
lines200Number of trailing lines to capture. Clamped to 1..=2000.
formattexttext strips ANSI escape sequences. ansi returns the raw pane bytes (use this if your client renders color).

Responses

StatusBodyWhen
200{"id": "...", "lines": N, "format": "text", "content": "..."}Pane captured
400{"error": "format_invalid", "allowed": ["text", "ansi"]}format was something other than text or ansi
404{"error": "not_found"}No session with that id
409{"error": "session_not_running"}Session exists but the tmux pane is gone
500{"error": "tmux_error"} or {"error": "internal"}Unexpected failure

output does not require write access, so it works under --read-only.

Example

curl -sS \
  -H "Authorization: Bearer $AOE_TOKEN" \
  "http://localhost:7777/api/sessions/abc123/output?lines=80&format=text"

Driving a session as a subagent

Together, send and output are the minimum primitive needed to run an aoe session as a controlled subagent. A typical loop:

  1. POST /api/sessions/{id}/send with the prompt.
  2. Poll GET /api/sessions/{id}/output until the pane content stabilizes (no change between two reads spaced ~1 s apart) or the session list shows the session’s status back at Idle.
  3. Capture the trailing region of content as the agent’s reply.

For long-running prompts, prefer polling status via GET /api/sessions over polling output, then read output once when status returns to Idle. Status transitions are also broadcast to push subscribers if the dashboard’s push notifications are configured.