fleet-rlm’s execution substrate is Daytona. The interpreter, recursive child sandboxes, durable storage, and host-callback bridge all live in src/fleet_rlm/integrations/daytona/. The Fleet-facing provider contract is async-first: DaytonaInterpreter.astart(), ashutdown(), aexecute(), aconfigure_workspace(), aimport_session_state(), and the DaytonaSandboxSession file/lifecycle a* methods are real coroutines. Sync helpers remain as compatibility shims for notebooks, tests, and direct Python API users.
This page is the deep cut on what DaytonaInterpreter actually does. For the higher-level architecture, see Architecture.
What is directly built on the Daytona SDK
The runtime uses the official Daytona Python SDK directly — no abstraction layer in between:| Need | Daytona SDK surface |
|---|---|
| Client construction | from daytona import AsyncDaytona, DaytonaConfig |
| Sandbox bootstrap and resume | DaytonaSandboxRuntime over the native SDK |
| Repo checkout | sandbox.git.clone(...) |
| Local context staging | sandbox.fs.* (aread_file, awrite_file, alist_files) |
| Persistent volume | client.volume.get(volume_name, create=True) + VolumeMount(...) |
| Stateful Python execution | sandbox.code_interpreter.create_context(...) + run_code(...) |
| Process sessions (broker) | sandbox.process.create_session(...) + execute_session_command(...) |
| Preview URLs | sandbox.get_preview_link(...) |
daytona_pilot is the public runtime path, built on the shared dspy.ReAct + dspy.RLM architecture.
DaytonaInterpreter: the public facade
src/fleet_rlm/integrations/daytona/interpreter.py exposes DaytonaInterpreter, the single facade everything outside integrations/daytona/ uses. Behind it sit typed collaborators with narrow responsibilities:
| Collaborator | Owns |
|---|---|
workspace_manager.py | Workspace config, session lifecycle, persisted Daytona state, runtime metadata, import/export |
sandbox_executor.py | Code execution, sanitization, bridge/setup state, tool callback dispatch, result finalization |
isolation.py | Recursive child policy/delegation, host-mediated evidence persistence, and local context staging |
models.py | Sandbox specs, workspace config, staged-context records, smoke results, chat/session normalization contracts |
runtime.py | Runtime facade around workspace bootstrap and session creation |
workspace_runtime.py | Workspace path, repo checkout, and session reconciliation helpers |
sdk_ops.py | Volume, snapshot, lifecycle, and lower-level Daytona SDK helpers |
session_runtime.py | Session-scoped runtime helpers |
bridge.py | Minimal sandbox-side broker for host callbacks |
diagnostics.py | Structured diagnostics + smoke validation |
errors.py | Provider-local error types |
WorkspaceConfig); hot execution-path carriers (DaytonaExecutionResponse) remain lightweight dataclasses.
Sandbox lifecycle
Snapshot vs. image fallback
Sandbox creation prefers the reusablefleet-rlm-base Daytona snapshot, an environment template pre-baking the default Python runtime packages (dspy-ai, numpy, pandas, httpx, pydantic).
If the snapshot is missing or not active, sandbox creation falls back to the same declarative image build so startup still has the expected dependencies. Operators bootstrap or refresh the template with:
Session continuity model
The Daytona runtime treats sandbox continuity as the default operating mode for a chat session:- One long-lived root Daytona sandbox session per agent session.
- One persistent Daytona code-interpreter context reused across warm turns.
- Repo/ref/context changes reconcile in place inside that sandbox.
- The mounted volume remains the canonical durable target for
memory/,artifacts/,buffers/, andmeta/.
- Sandbox identity — the long-lived Daytona sandbox and mounted volume.
- Workspace configuration — the repo checkout, ref selection, staged
.fleet-rlm/contextinputs, and helper setup inside that sandbox.
- Clones a repo if the desired checkout is missing.
- Fetches and updates the checkout in place when the ref changes.
- Clears and re-stages
.fleet-rlm/contextwhen host context inputs change. - Reruns sandbox helper setup so the live interpreter context retargets the new workspace path without discarding its in-memory state.
- Explicit session reset /
force_new_session. - Mounted volume incompatibility.
- Unrecoverable sandbox or reconcile failure.
- Resume failure for a persisted sandbox/context snapshot.
dspy.RLM analysis flows — warm turns continue in the same sandbox, durable outputs accumulate on the mounted volume, and resumed sessions become a first-class continuity path.
Three storage layers
The Daytona runtime separates three distinct memory layers. Mixing them is the most common source of confusion.| Layer | Lifetime | What lives there |
|---|---|---|
| Reusable environment template | Across sandboxes | fleet-rlm-base snapshot — only for faster sandbox creation; not a session persistence mechanism |
| Volatile execution-context state | Across warm turns in one sandbox | Python globals, imports, helper functions, in-memory objects in the code-interpreter context |
| Durable mounted-volume storage | Across sandbox restarts | Files under /home/daytona/memory/ with memory/, artifacts/, buffers/, meta/ |
Workspace vs. volume vs. context
| Root | Purpose |
|---|---|
| Workspace root | Live repo checkout plus transient execution files inside the sandbox |
| Context root | Run-scoped host inputs staged into the workspace under .fleet-rlm/context |
| Mounted volume root | Durable storage only — /home/daytona/memory |
Volume naming
- The Daytona persistent volume name is derived from the authenticated workspace/tenant claim.
DAYTONA_TARGETis only Daytona SDK routing/config input — never a workspace id, sandbox id, or volume name.- Session manifests live under
meta/workspaces/<workspace_id>/users/<user_id>/react-session-<session_id>.json. - Root and recursive child runs share the same workspace-scoped volume when one is configured, while still using distinct sandbox sessions per child.
The host-callback bridge
The provider is intentionally hybrid:- Direct async Daytona SDK calls for client, sandbox, volume, filesystem, preview, process-session, and code-interpreter operations.
- A minimal guide-style broker bridge (
bridge.py) for host callbacks only.
sandbox.process.create_session(...). It exists so code running inside the sandbox can reach back to the host for:
llm_query/llm_query_batched— semantic LLM calls.sub_rlm/sub_rlm_batched— recursive child RLM creation.- Custom tool dispatch.
SUBMIT(...)— final-artifact capture.
Execution path
The interpreter uses Daytona’s stateful Python execution context, not a fresh REPL per call:sandbox.code_interpreter.create_context(...)is created once at sandbox start. Python state lives here across calls.sandbox.code_interpreter.run_code(code, context_id=...)is the primary execution path.- The broker process is started only when host callbacks are needed.
SUBMIT(...), and stable result translation.
Filesystem helpers
Sandbox/file helper code should treatDaytonaSandboxSession as the canonical interface:
- Async flows use
aread_file,awrite_file,alist_files. - Sync helpers use
_ensure_session_sync()only at the public sync boundary. - Helper code should not fall back to raw
sandbox.fs.*access or mixed ad-hoc session shapes.
AsyncDaytona clients owned by an interpreter must be closed when the interpreter is discarded — otherwise HTTP sessions leak.
What is intentionally not Daytona’s responsibility
The runtime is SDK-owned. Repo-side.daytona configs, devcontainer configs, and Declarative Builder configs are not consulted at runtime in this iteration. Declarative Builder is relevant only as a future base-image strategy.
Diagnostics and smoke validation
Validate sandbox connectivity in isolation, without invoking an LM:fleet_rlm.integrations.daytona.types.DaytonaSmokeResult.
For programmatic checks, hit the runtime test endpoints:
POST /api/v1/runtime/tests/daytonaPOST /api/v1/runtime/tests/lm
See also
- Recursive RLM — how child sandboxes are scheduled.
- Sessions & persistence — manifests, restore, multi-tenant state.
- Configuration — Daytona env vars.