Skip to main content
fleet-rlm exposes a small, deterministic HTTP surface under /api/* and one Server-Sent Events stream for Turn execution. The canonical schema lives in openapi.yaml; this page is a high-level map. Fleet uses one deterministic local User and Workspace scope. It accepts no Authorization header or caller-supplied identity headers. There is no /api/v1 prefix, no WebSocket execution surface, no optimization/evaluation API, no runtime-admin API, no caller-selected BYOK profile API, and no public Artifact creation endpoint. Backend launchers default to binding 127.0.0.1 and reject non-loopback hosts unless --allow-non-loopback-bind is passed. The /api/settings endpoint is a separate local administration surface: it rejects non-loopback clients even when the API has been explicitly bound to another interface. See the security model for the full trust boundary.

Endpoint map

Turn creation

POST /api/sessions/{session_id}/turns executes exactly one Turn on the Session’s resident native dspy.RLM, creating or rotating the runtime as needed. Idempotency is mandatory. Required headers: Request body: Explicit skill_selections become authoritative for the Turn and are folded into its idempotency fingerprint. Omitting skill_selections supplies the full bounded catalog to the RLM and permits it to progressively load up to four advertised Skills. Providing selections preloads those exact versions and restricts loading to that set. Structurally malformed selections fail pre-stream with 422 invalid_skill_selection. Catalog-rejected selections (missing, unauthorized, or version-mismatched) resolve during in-stream Turn opening and surface as a stream error chunk with the generic message Invalid Skill selection. Both paths avoid revealing hidden catalog entries.

Streaming contract

The response opens the AI SDK UI message stream immediately instead of holding headers until preparation finishes. Transport 200 no longer implies a successful Turn; the Run id lives in the start chunk metadata. While the Turn claim and preparation resolve, the server emits a transient data-status chunk:
Fleet re-emits this chunk every runtime.heartbeat_seconds (configured in config/fleet.toml) until coordinator.open completes. Prelude chunks are client-facing keep-alives only; they never enter durable Turn history or the event log and may repeat. After opening, exactly one of three closings applies:
  • Success streams Runtime Events, ends with finish, then [DONE].
  • Claim or preparation failures close the stream with error + finish chunks that map to the same messages the old prepare-before-headers boundary surfaced as HTTP statuses (Session not found, A Turn is already running, Idempotency key input mismatch, Invalid Skill selection, Turn preparation timed out, Turn is unavailable, Invalid request), then [DONE].
  • Run cancellation ends the live stream with one terminal abort chunk and nothing after it. No finish, no data-usage, no checkpoint metadata.
Once cancellation settlement completes, the cancelled attempt persists a bounded tombstone in committed history so GET /api/sessions/{session_id}/turns shows the attempt: the original user input plus one assistant message carrying only a cancelled data-status part, observed usage, and the closed text Turn cancelled. Cancelled tombstones never contain reasoning, code, output, or Tool evidence parts.

Example

Run cancellation

PUT /api/runs/{run_id}/cancellation requests durable cancellation of an owned Run. The active stream closes with a single abort chunk. Fleet writes a bounded tombstone after settlement so history remains consistent.

Files API

GET /api/files, GET /api/files/stat, GET /api/files/content, PUT /api/files/content, POST /api/files/append, PATCH /api/files/content, and DELETE /api/files/content operate on the process-local Workspace files/ root. Callers cannot select a Workspace or address Daytona Volume, mount, Sandbox, Attachment, Artifact, Session, or Run identifiers through this API. The Files API has no rename operation and accepts an optional current SHA-256 on overwrite, append, delete, and patch. Stale preconditions return 409.
  • DELETE /api/files/content removes one file or one empty directory. Non-empty directories return 409.
  • PATCH /api/files/content applies one unique find/replace whose old text must occur exactly once. Absent or ambiguous matches return 409. The response returns the fresh content checksum for precondition chaining.

Attachments and Artifacts

POST /api/attachments uploads one durable Attachment and returns its id for future Turn requests. GET /api/artifacts/{artifact_id} and GET /api/artifacts/{artifact_id}/content return committed metadata and verified bytes. There is no POST /api/artifacts. Artifacts become public only when the host-mediated create_artifact produces a private candidate that is then promoted through Turn Commit.

Volume tree

GET /api/volume/tree (Daytona only) returns a bounded, read-only view of relative paths within the mounted Workspace Volume. It is a process-local logical view, not a general-purpose Sandbox filesystem browser.

Skills

GET /api/skills returns bounded Skill Cards for the five bundled system Skills (data-analysis, dspy-rlm, long-context, report-builder, workspace-files). GET /api/skills/{skill_id} returns one Skill Card by id. Selecting a Skill on a Turn preloads that exact expected_version and restricts progressive load_skill calls to the authorized set.

Health probes

GET /health and GET /health/ready are public probes for orchestrators, supervisors, and load balancers. Neither probe requires an identity header, a loopback client, or an existing Session. GET /health answers liveness while the process serves HTTP, even before startup composition wires the runtime inventory. It performs no dependency checks and returns the application name and version:
GET /health/ready answers readiness. Before startup composition installs, it returns 503 with the closed service_not_ready error envelope:
Once composed, it probes the configured database with one bounded SELECT 1 round-trip and returns 200:
When no database URL is set, database reports "not_configured" and the probe still returns 200. An unreachable configured database degrades readiness back to the same service_not_ready 503. Point orchestrator liveness checks at /health to detect a dead process, and readiness checks at /health/ready to hold traffic until the database answers:

Local settings

GET /api/settings and PATCH /api/settings read and revision-update the non-secret config/fleet.toml policy. This endpoint rejects any non-loopback client — including when the main API is bound to another interface — and never reads or returns .env values, provider credentials, or database URLs. Saved policy applies only after Fleet is restarted. Every PATCH carries the revision returned by the last read. If the file changed since that read, Fleet rejects the request with 409 settings_revision_conflict; reload and retry. The request body takes one of three shapes:
  • Batch update — an updates array of set or reset operations, with an optional default_profile. Fleet validates the whole batch against every profile and writes it atomically; either every operation lands or none do. An operation with unset: true removes a profile override so the field inherits the [defaults] value again (defaults themselves cannot be reset).
  • Single field — scope, path, and value update one policy field.
  • Profile selection — profile writes config.default_profile for the next restart.

Source of truth

  • Routes: src/fleet_rlm/api/routes/
  • Turn runtime: src/fleet_rlm/chat/turn_runtime.py
  • SSE stream projection: src/fleet_rlm/api/sse.py and api/ui_stream.py
  • Canonical schema: openapi.yaml
Last modified on September 4, 2026