Developers

AgentFleet API docs

Run and monitor Claude Code sessions from anywhere. Connect a runner to a machine, then launch sessions, tail their output, and send follow-ups over a clean REST API. Every endpoint is org-scoped and returns JSON.

Connect a runner

A runner is a small Node daemon you run on any machine you want to launch sessions on. It only makes outbound calls (pull model), so there are no inbound firewall holes. Create an API key under Settings → API Keys, then start the daemon:

PowerShell — start the runner
$env:AGENTFLEET_URL="https://your-host"
$env:AGENTFLEET_API_KEY="af_live_..."   # from Settings → API Keys
$env:ALLOWED_DIRS="C:\Users\you\code" # only these dirs are runnable
$env:RUNNER_NAME="home-desktop"
node runner/agentfleet-runner.mjs

On macOS / Linux use export for each variable; ALLOWED_DIRS is colon- or comma-separated. The runner enforces the directory allowlist: any working directory outside it is rejected. Once it heartbeats, it shows up under Runners in the app.

Authentication

Generate an API key in the app under Settings → API Keys. Keys look like af_live_AbC123... and are shown once at creation — store it somewhere safe. Pass it as a Bearer token on every request:

Authorization header
Authorization: Bearer af_live_AbC123...

Missing or invalid credentials return 401 with an error envelope:

401 response
{ "error": { "code": "UNAUTHORIZED", "message": "Authentication required" } }

API reference

All endpoints live under /api/v1. Errors use the shape { "error": { "code", "message" } }.

MethodPathDescription
GET/api/v1/runnersList your runners
GET/api/v1/runners/:idRunner detail + sessions
POST/api/v1/runsLaunch a session (enqueues)
GET/api/v1/runs/:idGet a session incl. logs
GET/api/v1/runs/:id/eventsStream session output
POST/api/v1/runs/:id/followupResume with a follow-up

Sessions

Launch a Claude Code session by POSTing a prompt and a cwd. This enqueues a task (status QUEUED) — a runner claims it and executes asynchronously. Optionally pin a runnerId, permissionMode (default, acceptEdits, bypassPermissions, plan), or model.

POST /api/v1/runs
curl -X POST https://your-host/api/v1/runs \
  -H "Authorization: Bearer af_live_..." \
  -H "Content-Type: application/json" \
  -d '{"prompt":"add a health check route","cwd":"C:\\Users\\you\\code\\api","permissionMode":"acceptEdits"}'
Response (201, bare object)
{
  "id": "clr...",
  "status": "QUEUED",
  "input": "add a health check route",
  "cwd": "C:\\Users\\you\\code\\api",
  "permissionMode": "acceptEdits",
  "runnerId": "run_..."
}

Fetch a session (including its logs and final cost / token usage) with GET /api/v1/runs/:id.

Live tail

Stream a session's output incrementally. Poll GET /api/v1/runs/:id/events with ?after=<seq> to fetch only events newer than the last sequence number you saw.

GET /api/v1/runs/:id/events?after=0
curl "https://your-host/api/v1/runs/clr.../events?after=0" \
  -H "Authorization: Bearer af_live_..."
Response
{ "data": [
  { "seq": 1, "kind": "system",    "message": "session started" },
  { "seq": 2, "kind": "assistant", "message": "Adding the route…" },
  { "seq": 3, "kind": "tool_use",  "message": "Edit src/app.ts" },
  { "seq": 4, "kind": "result",    "message": "done" }
] }

Follow-ups

Continue a session by resuming it with a new prompt. POST to /api/v1/runs/:id/followup — this creates a new child session that resumes the parent's Claude session, inheriting its runner, cwd, permission mode, and model.

POST /api/v1/runs/:id/followup
curl -X POST https://your-host/api/v1/runs/clr.../followup \
  -H "Authorization: Bearer af_live_..." \
  -H "Content-Type: application/json" \
  -d '{"prompt":"now add a test for it"}'
Response (bare object)
{ "id": "clr2...", "status": "QUEUED", "parentRunId": "clr..." }