Sandbox Web Dashboard, Snapshot Registry, and Multi-Profile Workspace Discovery¶
Status: Accepted (Amends ADR 0024, ADR 0003, and ADR 0040)
We introduce a unified browser management dashboard (sandbox/web.py), a persistent snapshot catalog backed by modal.Dict (sandbox/snapshots.py), and multi-profile workspace discovery (sandbox/profiles.py) into the Hosted Sandbox Control Plane and local developer CLI.
Context¶
Prior to this change, managing active Modal sandboxes required terminal commands (scripts/manage_sandboxes.py) or navigating Modal's generic web console. Inspecting sandboxes provisioned with custom tags, instance names, and forwarded ports lacked an integrated, visual dashboard.
Furthermore, filesystem snapshots captured via --snapshot recorded point-in-time container filesystems into modal.Image, but their image IDs and metadata (associated repository, description, timestamps, and size) were only printed to terminal logs without persistent indexing. Because Modal does not provide an image search API by tag or metadata, snapshot references were easily lost across developer sessions and machines.
Finally, developers often work across multiple Modal accounts and workspace profiles configured in ~/.modal.toml. Discovering and terminating sandboxes or browsing snapshots in different profiles required manual shell environment switching (MODAL_PROFILE=...).
Considered Options¶
- Separate Full-Stack Web Application (Node/React/Next.js): Build an independent frontend dashboard hosted outside Modal (e.g. Vercel or cloud container). Rejected because it introduces external hosting dependencies, build toolchains (npm/vite), and separate credential synchronization away from the Python/Modal core codebase.
- External Database for Snapshot Indexing (PostgreSQL/Turso): Store snapshot metadata in an external SQL database. Rejected to avoid third-party storage credentials and stateful database migrations for lightweight sandbox metadata that naturally belongs to the Modal workspace.
- Embedded Single-Page Dashboard in Control Plane with
modal.DictRegistry (Accepted): - Serve an embedded HTML5 single-page application (
sandbox/static/index.html) directly through FastAPI (sandbox/web.py) with zero build step, dark/light theme, and live polling. - Store snapshot metadata in a named
modal.Dict(sandbox-snapshots) with an automatic local JSON file fallback (~/.modal/sandbox-snapshots.json) when operating without active cloud Dict access. - Expose workspace profile inspection and client scoping (
sandbox/profiles.py) by parsing~/.modal.toml, allowing users to query and switch workspaces from the UI or REST API. - Provide a standalone launcher script (
scripts/web_ui.py) and mount the web routes directly onto the deployed cloud control plane (sandbox/function.py).
Architecture & Components¶
1. Web UI & REST Endpoints (sandbox/web.py)¶
- Frontend Delivery: Serves
sandbox/static/index.htmlatGET /and/ui. - REST Endpoints:
GET /api/sandboxes: Lists active sandboxes across specified or active profiles with metadata (sandbox ID, app, state, instance name, created at).DELETE /api/sandboxes/{sandbox_id}: Terminate a running sandbox.GET /api/snapshots: Lists recorded filesystem snapshots from the registry.POST /api/snapshots: Captures a snapshot from a running sandbox and registers its metadata.DELETE /api/snapshots/{snapshot_id}: Removes snapshot metadata from the registry.GET /api/profiles: Lists configured Modal profiles and identifies the active default.POST /launch: Synchronous sandbox launch endpoint (delegating tosandbox/core.py).GET /health: Health and readiness probe.
2. Snapshot Registry & Retention (sandbox/snapshots.py)¶
- Named Dict Persistence: Uses
modal.Dict.from_name("sandbox-snapshots", create_if_missing=True)to persist snapshot records containing: snapshot_id: Canonical snapshot identifier.image_id: Modal image identifier for container resurrection (--from-snapshot).description: Human-readable label or purpose.created_at: ISO 8601 UTC timestamp.ttl_days/ttl_seconds: Expiration horizon matching Modal image retention.tags: Key-value tags including repository provenance and author.- Local Fallback: Automatically falls back to reading/writing
~/.modal/sandbox-snapshots.jsonwhen cloud Dict access is unavailable. - Snapshot Retention & Invariant Pruning: To prevent displaying unlaunchable snapshot images, snapshot records are bounded by TTL and pruned when underlying image references expire or become unavailable.
3. Multi-Profile Workspace Discovery (sandbox/profiles.py)¶
- Parses
~/.modal.tomlusing Python's standardtomllibwithout invoking shell subshells or exposing secrets. - Maintains an in-memory client cache (
_CLIENT_CACHE) of authenticatedmodal.Clientinstances keyed by profile name. - Enables multi-tenant sandbox enumeration and administration from a single dashboard instance.
- Ambient Cloud Fallback: When deployed in cloud container environments lacking
~/.modal.toml, profile resolution degrades gracefully to the ambient execution client (modal.Client.from_env()) with a default profile label, avoiding parsing errors while restricting multi-profile switching to local environments.
4. Sandbox Lifecycle Extraction (sandbox/lifecycle.py)¶
- Centralizes sandbox discovery, instance name extraction (inspecting tags, Antigravity logs, and configs), and termination routines into a reusable module shared between
sandbox/web.pyandscripts/manage_sandboxes.py.
Consequences¶
- Developers can visually manage sandboxes and snapshots via
python3 scripts/web_ui.pyor the hosted cloud control plane endpoint. - Captured snapshots are permanently indexed and searchable by description and tags, preventing lost image identifiers.
- Multi-workspace switching is seamless locally, while cloud deployments operate reliably under ambient authentication.
- All modules remain strictly within the universal <= 500 lines budget ratchet (ADR 0027 / AGENTS.md).