Agent HTTP Reference
Every runtime endpoint with full request/response shapes — conversations, messages, queue, crons, auth.
The complete HTTP reference for the runtime (default http://localhost:4484).
All endpoints accept auth via Authorization: Bearer <key>, X-API-Key: <key>,
or ?api_key=<key>.
For WebSocket events, see Agent WebSocket events.
Health
GET /health
Base fields are always public; extra fields appear when the caller is authenticated (or when no API key is configured):
// Always present
{
"status": "ok",
"conversations": 0,
"authEnabled": true,
"timestamp": 1775845291793
}
// Additional fields when authenticated:
// "homePath": "/data/my-agent",
// "defaultModelProfileId": "smart",
// "allowedModelProfileIds": ["smart", ...],
// "signedIn": true,
// "productId": "..."
Wait for a successful health check before sending other requests.
Use
GET /healthfor readiness checks. (GET /health/readyis not currently implemented.)
Conversations
GET /conversations/stats Aggregate stats (totals, groups, time buckets)
POST /conversations Create a conversation
GET /conversations List / filter conversations
GET /conversations/:id Get conversation
PATCH /conversations/:id Update conversation
DELETE /conversations/:id Delete conversation
GET /conversations/:id/summary Message count + latest checkpoint
POST /conversations/:id/fork Fork a conversation
Create a conversation (all body fields optional):
POST /conversations
{
"title": "My Assistant",
"workspacePath": "/home/user/project",
"modelProfileId": "smart",
"metadata": { "groupId": "proj-1", "groupName": "Project 1" },
"browserProfile": "default",
"browserHeadless": true
}
modelProfileIdmay also be passed asllmIdorprovider. All three are accepted aliases for the same field.
List conversations (pagination + filtering):
GET /conversations?limit=50&offset=0
GET /conversations?groupId=proj-1
GET /conversations?timeBucket=today
GET /conversations?category=direct|subagent
| Param | Description |
|---|---|
limit | Max number to return |
offset | Pagination offset (default 0) |
groupId | Filter by metadata.groupId |
timeBucket | today, yesterday, last7Days, older |
category | direct (normal) or subagent |
When any of
groupId,timeBucket, orcategoryis present, filtered listing is used; otherwise simple listing withlimit.
Stats for dashboards:
GET /conversations/stats
{
"total": 42,
"directCount": 38,
"subagentCount": 4,
"groups": [{ "id": "proj-1", "name": "Project 1", "count": 12 }],
"timeBuckets": { "today": 3, "yesterday": 7, "last7Days": 20, "older": 12 }
}
Patch a conversation (all fields optional):
PATCH /conversations/:id
{
"title": "New title",
"status": "idle|running|error",
"modelProfileId": "smart",
"workspacePath": "/path",
"metadata": {},
"browserProfile": "default",
"browserHeadless": true
}
Fork a conversation (creates a new one copied from an existing one):
POST /conversations/:id/fork
{
"title": "Forked chat",
"afterMessageId": "msg_xxx",
"beforeMessageId": "msg_yyy",
"modelProfileId": "smart",
"workspacePath": "/home/user/project",
"browserProfile": "default",
"browserHeadless": true,
"metadata": {}
}
Use afterMessageId or beforeMessageId to control where the fork splits the
history.
Messages (running the agent)
POST /conversations/:id/messages Send a message (enqueued, returns 202)
GET /conversations/:id/messages List messages (cursor pagination)
List messages:
GET /conversations/:id/messages?limit=50&before=1775845291793
GET /conversations/:id/messages?since=1775845291793
GET /conversations/:id/messages?last=true
| Param | Description |
|---|---|
limit | Positive integer; max messages to return |
before | Messages with timestamp before this value (ms epoch) |
since | Messages with timestamp after this value (ms epoch) |
last | When true, return only the most recent message |
Send a message:
POST /conversations/:id/messages
{ "content": "Check the server health every 5 minutes" }
Messages may include images. images accepts HTTPS image URLs,
data:image/...;base64,... URLs, or objects with
{ "data": "<base64>", "mimeType": "image/png" }. Images are only forwarded
when the selected model advertises vision support; text-only models reject the
run before the image payload is sent upstream.
POST /conversations/:id/messages
{
"content": "Describe this screenshot",
"images": [
{ "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...", "detail": "high" }
]
}
Response (202 Accepted):
{
"accepted": true,
"conversationId": "conv_abc123",
"queueItem": { "id": "queue_xyz", "status": "queued" },
"status": "queued"
}
The agent processes asynchronously — track progress over WebSocket.
Queue management
GET /conversations/:id/queue List queue items
DELETE /conversations/:id/queue Bulk remove items (body: { "ids": [...] })
DELETE /conversations/:id/queue/:qid Remove a single queue item
POST /conversations/:id/cancel Cancel current run
POST /conversations/:id/interrupt Cancel and prepend a new message
List queue items supports the same cursor params as messages plus
includeTerminal:
GET /conversations/:id/queue?limit=50&since=...&includeTerminal=true
| Param | Description |
|---|---|
limit | Positive integer; max items to return |
before | Items with timestamp before this value |
since | Items with timestamp after this value |
includeTerminal | When true, include completed/failed items (excluded by default) |
Bulk delete:
DELETE /conversations/:id/queue
{ "ids": ["queue_a", "queue_b"] }
// → { "removed": ["queue_a", "queue_b"], "removedCount": 2 }
Cancel and interrupt accept optional control flags:
POST /conversations/:id/cancel
{ "clearQueued": true } // optional — also drop pending queued items
POST /conversations/:id/interrupt
{
"content": "Actually, do this instead",
"dropQueued": true, // optional — drop pending queued items
"images": [] // optional — same image format as messages
}
Compaction & checkpoints
The runtime auto-compacts long conversations to fit the context window
(controlled by compactionSoftThreshold / compactionHardThreshold in
runtime.json). Each compaction produces a checkpoint:
GET /conversations/:id/checkpoints List compaction checkpoints
GET /conversations/:id/compaction-events List compaction event records
POST /conversations/:id/compact Trigger manual compaction
GET /conversations/:id/compaction-events?limit=20&before=...&since=...
POST /conversations/:id/compact // → { "checkpoint": { "id": "ckpt_..." } }
Subagents
Conversations can spawn isolated subagent runs (e.g. via the delegate tool).
Subagents run in their own context and cannot re-delegate (prevents infinite
recursion).
GET /conversations/:id/subagents List subagents of a conversation
GET /conversations/:id/subagents/:subagentId Get a subagent + its messages
The detail endpoint returns { "conversation": {...}, "messages": [...] } for
the subagent.
Cron jobs
POST /crons Create a cron job
GET /crons List all cron jobs
GET /crons/:id Get a cron job
PATCH /crons/:id Update a cron job
DELETE /crons/:id Delete a cron job
POST /crons/:id/toggle Enable/disable a cron job
POST /crons/:id/run Run a cron job immediately
Create a recurring task (new conversation each time):
POST /crons
{
"name": "Health Check",
"content": "Check if https://example.com is up and report the status code",
"schedule": "*/5 * * * *",
"workspacePath": "/home/user/project",
"modelProfileId": "smart",
"titlePrefix": "Health Check",
"enabled": true
}
Create a recurring task in an existing conversation:
POST /crons
{
"name": "Daily Summary",
"conversationId": "conv_abc123",
"content": "Summarize what happened today",
"schedule": "0 9 * * *"
}
| Body field | Description |
|---|---|
content | Required. Message sent when the job fires |
schedule | Required. Standard 5-field cron expression |
name | Human-readable label |
conversationId | Run in an existing conversation; omit to create a new one each fire |
modelProfileId | Model to use (alias: llmId) |
workspacePath | Workspace for newly-created conversations |
titlePrefix | Prefix applied to auto-created conversation titles |
enabled | Default true; set false to create paused |
The same fields are accepted on PATCH /crons/:id (all optional). Run on demand:
POST /crons/:id/run
// → 200 { "status": "started", "accepted": true, ... }
// → 202 if already running: { "status": "already_running", "accepted": true }
Authentication (cloud)
GET /auth/status Check cloud auth status (auto-refreshes expiring tokens)
POST /auth/session Exchange bootstrap token for session
POST /auth/dev-session Exchange dev credentials for session
DELETE /auth/session Sign out
GET /entitlements/cache Read cached entitlements (plan, models, usage)
GET /auth/status transparently refreshes the access token if it's within 60s of
expiry; permanent failures (expired/revoked) clear the session, while transient
failures (network/5xx) leave it intact.
Observability
GET /workspace-sync-audit?limit=50 Workspace sync audit log (trigger, etag, file counts)
GET /events/recent?since=<seq> Recent buffered runtime events (HTTP fallback for WS)
GET /events/recent returns events from the in-memory buffer (the same buffer
WebSocket clients replay from). Pass since=<seq> for events after a sequence
number, or omit for all buffered events:
GET /events/recent
{ "events": [{ "seq": 42, "payload": "{\"type\":\"message.delta\",...}" }] }
LLMs
GET /llms List available LLM models (refreshes the in-memory catalog)
Agent tools
During a run the agent can use: bash (shell), browser (web automation/screenshots), cron (scheduling), and delegate (spawn an isolated subagent that cannot re-delegate). It can self-manage cron jobs — saying "check my site every 10 minutes" is enough.