Skip to main content
Daytona is the only Run Environment for fleet-rlm. The canonical set is daytona. Every Turn acquires a fresh Interpreter Lease, mounts a Workspace Volume Scope on an ephemeral Sandbox for grouped I/O, and returns cleanly before the next Turn starts. This page is the deep cut on how that runtime is shaped. For the higher-level layering, see Architecture.

One process-owned AsyncDaytona

The process owns a single AsyncDaytona client. It owns provisioning, Sandbox lifecycle, filesystem calls, and Workspace operations, and every path through the runtime is native async. The only synchronous seam is DSPy’s CodeInterpreter.execute(). That seam receives an explicit, allowlisted async-to-sync view of a small set of interpreter methods, and it blocks only the DSPy worker thread. No other collaborator gets sync access to the client. You should treat AsyncDaytona as a process-lifetime resource. It is not per-Turn, per-Run, or per-Session.

Provisioning and snapshot policy

Every Sandbox boots from a base snapshot named by [defaults.daytona] snapshot. The current default is fleet-rlm-python313-v5. Recursive delegations bootstrap from the same snapshot, which lets them skip the per-run image pull. Build or refresh the snapshot with the CLI:
Verify the snapshot exists with make daytona-snapshot-check. Diagnostics for the full runtime path live under uv run fleet doctor daytona and are described below. Provisioning code lives in src/fleet_rlm/daytona/provisioning.py. The SDK boundary itself is in src/fleet_rlm/daytona/broker_source.py and src/fleet_rlm/daytona/http_broker.py.

Volume policy

The runtime provisions exactly one Daytona Volume per configured deployment, and every Sandbox mounts it at a fixed path. The API URL and target are not configured through Fleet env vars. They come from the Daytona SDK defaults or the Daytona profile you have selected on the host. See Configuration for the full [defaults.daytona] reference.

Workspace Volume Scope

WorkspaceVolumeGateway.open_workspace() in src/fleet_rlm/daytona/workspace_gateway.py opens a Workspace Volume Scope. It scopes each grouped I/O operation to one ephemeral Sandbox, and it deletes that Sandbox before the context exits. The Gateway only provisions namespaces it owns. Everything else on the Volume is off-limits.
Bundled Skills stay host-owned. They are not copied into the Volume. Recursive child scopes are siblings of workspaces/<workspace-id>. A recursive child cannot reach the Root workspaces/<workspace-id> mount, even though both scopes share the same underlying Volume ID.

Interpreter Leases

Every Turn acquires a fresh Interpreter Lease. Within a single Run, interpreter calls reuse one context, so Python state persists across RLM iterations in the same Run. Every later Run receives a fresh context. If Daytona replaces the underlying Sandbox, the runtime remounts the Workspace Volume Scope, but Python globals are not preserved across that replacement. The following runtime settings bound Lease behavior: The interpreter facade lives in src/fleet_rlm/daytona/interpreter.py. Session lifecycle around a Lease lives in src/fleet_rlm/daytona/session_manager.py.

Recursive child Sandboxes

Recursive delegations run through src/fleet_rlm/daytona/recursive_child_runtime.py under the daytona-recursive runtime label. Each child receives a fresh, dedicated Daytona Sandbox with ordinary Daytona network egress. The child mounts the same Volume ID at recursive/<workspace-id>/<run-id>/<call-index>. That is a private sibling scope. It cannot reach the Root workspaces/<workspace-id> mount. The child receives no Fleet Tools and no credentials. Cleanup is strict. Scope purge and Sandbox deletion both happen before the Root success can commit. A recursive child cannot leak state into the Root scope, and a Root Run cannot commit success while a child Sandbox is still alive. For the delegation contract itself, see Recursive RLM.

Attachments and Artifacts

Attachment bytes are written to the Workspace Volume Scope before their metadata, and they are staged for the Runs that reference them. That ordering means metadata never points at bytes that are not yet on disk. Artifact Candidates remain private Run outputs until two conditions hold: verified bytes have reached UUID-unique durable paths, and their metadata commits with the Turn. Failed metadata commits may leave GC-eligible orphan bytes on the Volume, but they never leave public rows.

Workspace files API

The /api/files* endpoints always resolve the process-local Workspace. Callers cannot select a Workspace, and they cannot address a Daytona Volume, mount, Sandbox, Attachment, Artifact, Session, or Run identifier through this API. The API offers bounded list and read pagination, append, in-place unique fragment edits, whole-file replacement, and strict delete. Writes, appends, edits, and deletes accept optional SHA-256 preconditions. The runtime never follows symlinks, holds a target lock across the operation, and revalidates the target inode across I/O Sandboxes. Implementation lives in src/fleet_rlm/daytona/workspace_agent.py and src/fleet_rlm/daytona/workspace_fs.py. Endpoint shapes are in HTTP API.

Workspace Memory

Workspace Memory is a single fixed file, MEMORIES.md, at memory/ under the mounted workspaces/<workspace-id> Volume subpath. The RLM Tools that operate on it are read_workspace_memory, remember, list_memories, search_memories, edit_memory, and forget. Each Turn also receives a bounded workspace_memory tail digest in session_context. The digest is capped at 4 KiB. It gives the model a small, always-fresh window over recent memory without forcing a Tool call. Memory Tool wiring lives in src/fleet_rlm/daytona/workspace_memory.py. For persistence guarantees around Memory across Sessions, see Sessions and persistence.

Volume tree endpoint

GET /api/volume/tree returns a bounded, read-only view of the relative paths inside the mounted Workspace Volume. It is a process-local logical view. It is not a general-purpose Sandbox filesystem browser, and it does not accept Sandbox or Volume identifiers.

Diagnostics

Validate the full runtime path with the doctor command:
The command validates the required settings, database connectivity and Alembic head, provider authentication, Volume visibility, scoped mounting, and interpreter execution. It creates exactly one uniquely labelled disposable Sandbox and deletes it in finally. It creates no Fleet domain rows. Output is limited to bounded categories and corrective actions. There is no fleet-rlm daytona-smoke command. fleet doctor daytona replaces it. There is also no POST /api/v1/runtime/tests/daytona endpoint.

Implementation pointers

See also

Architecture

Three layers of fleet-rlm and where the Daytona substrate sits.

Recursive RLM

How recursive children are scheduled and isolated.

Sessions and persistence

Session lifecycle, Workspace Memory continuity, and Run identifiers.

HTTP API

/api/files* and /api/volume/tree endpoint shapes.

Configuration

Full [defaults.daytona] and runtime.* settings reference.

CLI

fleet doctor daytona, fleet-rlm daytona-snapshot, and related commands.
Last modified on August 13, 2026