> ## 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.

# Daytona runtime

> How fleet-rlm uses one process-owned AsyncDaytona client, per-Turn Interpreter Leases, and scoped Volume mounts to run every Turn on Daytona.

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](/fleet-rlm/concepts/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:

```bash theme={null}
uv run fleet-rlm daytona-snapshot
uv run fleet-rlm daytona-snapshot --refresh
```

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.

| Setting                                | Default                  | Purpose                                               |
| -------------------------------------- | ------------------------ | ----------------------------------------------------- |
| `[defaults.daytona] snapshot`          | `fleet-rlm-python313-v5` | Base snapshot for Sandbox provisioning.               |
| `[defaults.daytona] volume_name`       | `fleet-volume`           | Daytona Volume ID mounted on every Sandbox.           |
| `[defaults.daytona] volume_mount_path` | `/home/daytona/fleet`    | Absolute mount path inside every Sandbox.             |
| `[defaults.daytona] api_key_env`       | `FLEET_DAYTONA_API_KEY`  | Name of the env var that carries the Daytona API key. |

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](/fleet-rlm/reference/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.

```text theme={null}
<volume_mount_path>/
├── workspaces/<workspace-id>/          # Root Session scope
│   ├── memory/                         # MEMORIES.md and Workspace Memory state
│   ├── projects/<slug>/
│   ├── sessions/<session-id>/
│   └── runs/<run-id>/
├── attachments/                        # Shared, staged for referenced Runs
├── artifacts/                          # Shared, verified Run outputs
└── recursive/<workspace-id>/<run-id>/<call-index>/
                                        # Private sibling scope per recursive child
```

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:

| Setting                             | Default | Effect                                                          |
| ----------------------------------- | ------- | --------------------------------------------------------------- |
| `runtime.max_active_daytona_leases` | `8`     | Upper bound on concurrent Interpreter Leases.                   |
| `runtime.turn_timeout_seconds`      | `1800`  | Wall-clock bound on a single Turn.                              |
| `runtime.heartbeat_seconds`         | `10`    | Cadence of transient `data-status` chunks during a Turn.        |
| `runtime.stale_after_seconds`       | `60`    | Liveness bound on heartbeat before a Lease is treated as stale. |

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](/fleet-rlm/concepts/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](/fleet-rlm/reference/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](/fleet-rlm/concepts/sessions-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:

```bash theme={null}
uv run fleet doctor daytona
```

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

| Module                                             | Owns                                                                    |
| -------------------------------------------------- | ----------------------------------------------------------------------- |
| `src/fleet_rlm/daytona/interpreter.py`             | Interpreter facade and allowlisted async-to-sync view.                  |
| `src/fleet_rlm/daytona/workspace_gateway.py`       | Workspace Volume Scope and ephemeral Sandbox context.                   |
| `src/fleet_rlm/daytona/workspace_agent.py`         | Workspace agent that services `/api/files*`.                            |
| `src/fleet_rlm/daytona/workspace_fs.py`            | Workspace filesystem operations with locking and SHA-256 preconditions. |
| `src/fleet_rlm/daytona/workspace_memory.py`        | Workspace Memory Tools and tail digest.                                 |
| `src/fleet_rlm/daytona/recursive_child_runtime.py` | Dedicated child Sandbox lifecycle.                                      |
| `src/fleet_rlm/daytona/provisioning.py`            | Sandbox provisioning and snapshot policy.                               |
| `src/fleet_rlm/daytona/session_manager.py`         | Session lifecycle around Interpreter Leases.                            |
| `src/fleet_rlm/daytona/broker_source.py`           | Daytona SDK boundary source.                                            |
| `src/fleet_rlm/daytona/http_broker.py`             | HTTP transport to the Daytona SDK.                                      |

## See also

<CardGroup cols={2}>
  <Card title="Architecture" href="/fleet-rlm/concepts/architecture">
    Three layers of fleet-rlm and where the Daytona substrate sits.
  </Card>

  <Card title="Recursive RLM" href="/fleet-rlm/concepts/recursive-rlm">
    How recursive children are scheduled and isolated.
  </Card>

  <Card title="Sessions and persistence" href="/fleet-rlm/concepts/sessions-persistence">
    Session lifecycle, Workspace Memory continuity, and Run identifiers.
  </Card>

  <Card title="HTTP API" href="/fleet-rlm/reference/http-api">
    `/api/files*` and `/api/volume/tree` endpoint shapes.
  </Card>

  <Card title="Configuration" href="/fleet-rlm/reference/configuration">
    Full `[defaults.daytona]` and `runtime.*` settings reference.
  </Card>

  <Card title="CLI" href="/fleet-rlm/reference/cli">
    `fleet doctor daytona`, `fleet-rlm daytona-snapshot`, and related commands.
  </Card>
</CardGroup>
