POST /api/sessions/{session_id}/turns streams a Turn attempt, and only a successful commit advances Session history, publishes Artifact identity, and writes the Turn/Run/Checkpoint/Artifact rows atomically.
For the sandbox and volume mechanics that sit under this model, see Daytona runtime.
The three persistence layers
Every later Run receives a fresh interpreter context. Workspace files and Postgres rows outlive Sandbox replacement independently.
Alembic-managed Postgres
The relational store is the canonical record. Domain repository interfaces live undersrc/fleet_rlm/persistence/, and Alembic owns the live schema. Runtime startup never applies migrations.
Apply the head schema explicitly before serving traffic:
FLEET_DATABASE_URL. Local SQLite is suitable for development only. Fleet runs under one deterministic local User + Workspace scope, so requests carry no Authorization header and there is no row-level security scoping to configure.
Committed Turn history
A Turn attempt is streamed through:Turn, Run, Checkpoint, and Artifact tables in one transaction. A failed commit advances no Session history, publishes no Artifact identity, and still releases owned resources.
Cancelled attempts persist a bounded tombstone:
- The original user input.
- One assistant message carrying only a
cancelleddata-statuspart. - Observed usage counters.
- The closed text
Turn cancelled.
read_session_history Tool rather than by loading transcripts into a prompt.
Session catalog
Sessions are owned by the local scope and addressed under/api/sessions (no /v1 prefix).
There is no export endpoint. Backup is handled at the Postgres and Volume layers, not through an application-level dump.
Daytona Workspace Volume Scope
The Volume mount is fixed at/home/daytona/fleet, configured through [defaults.daytona] volume_mount_path. Fleet provisions only the namespaces it owns and leaves bundled Skills host-owned — they are not copied into the Volume.
Attachments and Artifacts
Attachments and Artifacts share the Volume Scope but move through very different lifecycles. Attachments.POST /api/attachments uploads durable bytes to Workspace Volume Scope before writing metadata, then stages the file for the referenced Runs. Attachment identity is public at upload time.
Artifacts. A candidate lives privately in the Run scope until Turn Commit. The path is:
- The host-mediated
create_artifactproduces a private Run candidate. - Verified bytes reach a UUID-unique durable path under
artifacts/. - Turn Commit atomically writes the Artifact row and publishes identity.
POST /api/artifacts. Read paths are:
GET /api/artifacts/{artifact_id}— metadata.GET /api/artifacts/{artifact_id}/content— verified bytes.
Session Workspace files
Session Workspace files are immediate private state under the Session Volume path. Daytona exposes bounded operations against them:- List and read with pagination.
- Append, in-place unique fragment edit, and whole-file replacement.
- Strict delete for files and empty directories only. No recursion, no force flag.
result.json snapshot and the Artifact lifecycle.
The Files API surface
The Files API (/api/files*) always resolves the process-local Workspace. Callers cannot select a Workspace or address Daytona Volume, mount, Sandbox, Attachment, Artifact, Session, or Run identifiers.
- No rename operation.
DELETE /api/files/contentremoves one file or one empty directory. Non-empty targets return409.PATCH /api/files/contentrequires theoldtext to occur exactly once. Absent or ambiguous matches return409. The response returns the fresh checksum so callers can chain preconditions.
Workspace Memory
Workspace Memory is separate workspace-wide immediate state, not Session history and not a Turn-commit record. It lives at a fixed path:MEMORIES.md migrates on first open without losing content. Session and Run state retain their nested paths below that root.
The RLM accesses memory through a bounded Tool set:
read_workspace_memoryrememberlist_memoriessearch_memoriesedit_memoryforgetupdate_workspace_memory(back-compat alias)
workspace_memory tail digest of relevant plus newest records into each Turn’s session_context. The digest is capped at 4 KiB, so the RLM has recent context without needing a Tool call.
The RLM may append a record only when the user explicitly asks to remember something. remember writes v3 records with a fresh id and up to 4 KiB of formatted UTF-8. Records are durable immediately. Reads return the newest complete records within a fixed 256 KiB byte budget, and the configured max_upload_bytes caps the whole memory file.
Memory survives failed Runs and Sandbox replacement.
Interpreter context
Interpreter calls within one Run reuse a single context, so Python globals, imports, and helper functions persist across RLM iterations inside that Run. The context is volatile:- It never crosses Run boundaries.
- Every later Run receives a fresh context.
- It carries no durable state — anything meant to outlive the Run must reach the Volume or Postgres.
Backup and recovery
- Postgres. Alembic head is the durable schema baseline. Use
uv run alembic upgrade headfor explicit deployment anduv run alembic checkto verify. - Volume. Daytona Volume snapshots taken through the provider are the durable-state backup path for Workspace Memory, Session Workspace files, Attachments, and Artifact bytes.
- No first-class export. Fleet does not ship an “export everything” command. Postgres and the Volume are the source of truth, backed up in place.
See also
Daytona runtime
Sandbox lifecycle, volume mount, and the host-callback bridge under this persistence model.
HTTP API
Session, Turn, Attachment, Artifact, and Files endpoint reference.
Configuration
FLEET_DATABASE_URL, [defaults.daytona] volume_mount_path, and related policy in config/fleet.toml.Architecture
Where the three persistence layers sit inside the overall Fleet layering.