Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.qredence.ai/llms.txt

Use this file to discover all available pages before exploring further.

fleet-rlm persistence spans three layers: session manifests on the Daytona mounted volume, the volatile code-interpreter context, and the canonical Neon/Postgres multi-tenant store. Each has a distinct lifetime and authority.

What gets persisted, where

LayerBacked byLifetimeAuthority for
Session manifestDaytona mounted volumeAcross sandbox restarts and resumesRestart-restore, agent state
Code-interpreter contextDaytona sandbox memoryWarm turns in one sandboxLive Python state
Neon/PostgresExternal Postgres / NeonCanonical multi-tenant stateIdentity, tenants, history index
Local sidecarintegrations/local_store.pyPer-processLocal development convenience

Session manifest

Session manifests are the authoritative local restart-restore source. They live on the mounted Daytona volume at:
meta/workspaces/<workspace_id>/users/<user_id>/react-session-<session_id>.json
A best-effort legacy fallback under workspaces/... exists for migration compatibility only. The manifest’s state payload restores:
FieldWhat it restores
historydspy.History conversation turns
core_memoryAgentRuntime core memory — default core memory plus persisted keys
document_pathsSession-local loaded document paths
interpreter_stateDaytona interpreter state — sandbox ID, workspace path, repo URL/ref, context paths, volume name, volume subpath

Import semantics: replace, not merge

Importing a session replaces session-local memory and document state instead of merging into the currently active runtime. This is intentional — merging would silently leak state across sessions. Empty or missing state resets:
  • Conversation history.
  • Core memory.
  • Loaded documents.
  • Sandbox buffers.
Switching sessions therefore cannot leak stale agent context. If you want to carry state forward, do it explicitly via document attachments or core-memory writes, not by relying on residual runtime state.

Three storage layers (recap)

This is the same three-layer model from Daytona runtime, repeated here for the persistence story: Repos, staged context inputs, package installs, caches, and scratch files are not durable by default. They live in the workspace root, not the volume root. Files survive context reset, sandbox restart, or session resume only when they are explicitly written to one of the four canonical durable directories.

Durable volume layout

/home/daytona/memory/
├── memory/        # agent durable memory (writes via core memory APIs)
├── artifacts/     # generated artifacts (reports, exports, exports)
├── buffers/       # streaming buffers and intermediate large files
└── meta/
    └── workspaces/<workspace_id>/users/<user_id>/
        └── react-session-<session_id>.json
Workspace-aware tools target the live sandbox workspace; volume-aware tools target the durable directories. There is no automatic sync between the two.

Neon-backed multi-tenant state

When DATABASE_REQUIRED=true (production default), canonical state lives in Neon/Postgres via SQLAlchemy models under src/fleet_rlm/integrations/database/:
ModuleOwns
models_identity.pyTenants, users, workspace identities
models_jobs.pyBackground job tracking
models_memory.pyPersisted memory items
models_optimization.pyOptimization runs, datasets, results
models_runs.pyExecution run steps
models_sandbox.pySandbox metadata snapshots
repository_*.pyRepository-pattern access to each table set
Row-level security (RLS) is enforced — see ADR-003 in the upstream repo for the policy. Multi-tenant admission happens at the auth boundary: in AUTH_MODE=entra, an Entra bearer token is exchanged for an internal tenant_id + user_id, and every query is scoped to that tenant. When DATABASE_REQUIRED=false (local dev), the runtime falls back to integrations/local_store.py for session history and turn transcripts. This is convenience-only — not a production persistence path.

Session lifecycle endpoints

EndpointMethodPurpose
/api/v1/sessions/stateGETActive session envelope
/api/v1/sessionsGETList sessions
/api/v1/sessions/{id}GETSession detail
/api/v1/sessions/{id}DELETEDelete a session
/api/v1/sessions/{id}/turnsGETConversation turns
/api/v1/sessions/{id}/exportPOSTExport session manifest
Sessions are scoped to the authenticated tenant_id + user_id in AUTH_MODE=entra. Export produces a manifest that round-trips with the local meta/workspaces/.../react-session-*.json shape.

Reset and force-new-session

The runtime forces sandbox recreation only when continuity would be unsafe:
  • Explicit session reset (force_new_session=true).
  • Mounted volume incompatibility.
  • Unrecoverable sandbox or reconcile failure.
  • Resume failure for a persisted sandbox/context snapshot.
WebSocket session switching uses the async reset path (agent.areset(...)) when clearing Daytona sandbox buffers for a fresh or restored session without saved state. This guarantees the live interpreter context is torn down before a new session attaches.

Backup and recovery

The Daytona mounted volume is the durable target. To back up agent state:
  1. Snapshot the mounted volume (Daytona-provider native).
  2. Export sessions via POST /api/v1/sessions/{id}/export.
  3. For Neon/Postgres, use the provider’s native point-in-time recovery.
There is no first-class “export everything” command. The volume + Postgres are the source of truth.

See also