devin-remote binary distribution, and the spawn contract for custom orchestrators.
Authentication
Workers and orchestrators authenticate with a v3 API token belonging to a service user. The role assigned to the service user grants the token its Outposts scopes:
Outposts are scoped to your account and shared across all of its organizations.
CLI
devin worker start
Polls an outpost’s queue, claims sessions, downloads the correct devin-remote binary, and serves sessions. Run it from the directory containing the session’s checked-out repositories.
The worker’s environment can also carry
DEVIN_CHROME_PATH to point sessions at a Chrome/Chromium binary for browser features.
devin worker outpost create
Creates an outpost — a named queue of sessions served by your infrastructure. Requires the orchestrator scope.
Prints the new outpost’s ID (
outpost_env-...). You can also create outposts in the web app under Settings → Environment → Outposts.
devin worker outpost delete
Deletes an outpost. Requires the orchestrator scope.
Fleet API
All endpoints live underhttps://api.devin.ai/opbeta/outposts/ and take a bearer token:
metadata / spec / status shape, and the queue follows Kubernetes list-then-watch semantics with at-least-once delivery.
Objects
Queue entry (devins)
Each queued session is represented by one queue entry:
spec.network_policy reports whether the session’s network access is restricted (enabled) and the allowed destinations (allow): hostname globs ({"hostname": ...}), IPv4 addresses/CIDRs ({"ipv4": ...}), or IPv6 addresses/CIDRs ({"ipv6": ...}).
Outpost
List queued sessions
Example response:
- Pass each response’s
cursorinto the next request whilehas_next_pageistrue. - Delivery is at-least-once: a session at a page boundary can appear in both pages, so upsert entries by
metadata.session_idrather than treating every item as new (the claim CAS makes duplicates harmless). - When
has_next_pagebecomesfalse, save the returned cursor as the starting position for a watch.
Watch for changes
MODIFIED events fire when a session’s queue entry changes (newly queued sessions also arrive as MODIFIED); DELETED events fire when it is removed. Each SSE data field contains:
- Persist each event’s top-level
cursorafter processing it; reconnect with the last persisted cursor to replay changes that occurred while disconnected. - Delivery is at-least-once — tolerate duplicate events.
- Streams end after at most five minutes; a reconnecting watch loop is expected.
phaseandacceptor_idfilters are ignored whenwatch=true; filter watched events using the fields in each event’sobject.- Omitting the cursor starts from the beginning, so use list-then-watch for normal reconciliation.
Get a queue entry
Claim a session
409. A successful claim response includes status.connect_token and status.gateway_url — the credentials devin-remote needs to connect (see the spawn contract).
Claiming promises that a worker will be ready within the server-assigned claim deadline (status.claim_deadline); expired claims return to the queue automatically.
Release a claim
Outposts
status.queue_depth and status.active_claims.
Remote binary distribution
Thedevin worker start command automatically downloads the correct devin-remote binary. Custom orchestrators that do not use the Devin CLI can fetch it directly from:
If the session’s queue entry includes a
spec.remote_binary_sha, use that SHA instead of latest — it pins the session to a specific tested version.
Spawn contract
If your orchestrator launchesdevin-remote itself instead of using devin worker start, spawn it as:
Give the remote a clean environment containing only the variables above plus basic system variables (
PATH, HOME, USER, LOGNAME, TMPDIR, LANG, TZ, and — for the desktop stream’s screen capture on Linux/X11 — DISPLAY, WAYLAND_DISPLAY, XAUTHORITY). Do not leak anything the agent should not be able to see into the remote: it is inherited by the agent’s shell.
Additional lifecycle expectations:
- Working directory: launch the remote from the directory containing the session’s repositories (the same rule as
devin worker start). - Session end: when the session ends (sleeps or terminates), Devin notifies the remote and it exits with status 0 on its own. Treat a clean exit as the end of the session: confirm the queue entry’s
status.session_statusissuspendedorterminated(the status update can lag the exit by a few seconds, so re-read a few times), then release the claim. As a fallback, also pollstatus.session_statuswhile the remote runs and kill the process yourself once it reachesterminated(or the queue entry disappears).

