Workspace and Session Contract (Evaluation)¶
Status: evaluation draft, 2026-10-24. This page is not an API commitment. It
records the problem, candidate shape, provider questions, and the criteria for
promoting a contract into pkg/.
Why Evaluate This¶
PRAXO-CORE currently separates two seams:
| Seam | Contract | Current use |
|---|---|---|
| Virtual filesystem | vfs.Backend |
Read, write, list, glob, grep, delete |
| Command execution | vfs.Executor |
Optional shell execution on a VFS backend |
| Sandbox | sandbox.Sandbox |
One Run(ctx, Spec, command) call |
| Interpreter | sandbox.Interpreter |
Optional in-process script evaluation |
That is enough for stateless execution and local workspaces. Remote sandbox services such as E2B, OpenSandbox, or CubeSandbox add a lifecycle:
create or attach -> execute -> upload/download -> pause/resume -> close
Deep Agents models this as a pluggable backend protocol, with a sandbox backend that adds execution. PRAXO-CORE should learn from that shape without copying LangGraph state, a graph runtime, or a provider SDK.
The gap is not "more sandbox providers". The gap is a provider-neutral session contract that can be verified against at least two implementations.
Requirements¶
- Stateful lifecycle. Create or attach to a session, run multiple commands, transfer files, and close it. Pause, resume, and snapshot are optional capabilities, not required methods.
- Composition over duplication. A session should expose the existing
sandbox.Sandboxandvfs.Backendbehavior without redefining them. - No provider leakage. The public contract contains no E2B, OpenSandbox, or CubeSandbox types, credentials, endpoints, or control-plane fields.
- Caller-owned auth and tenancy. Products pass credentials and tenant context through adapter configuration, never the core contract.
- Context and timeouts. Every operation accepts
context.Context; timeout and cancellation are observable and do not leak sessions. - Error mapping. Missing sessions, unsupported capabilities, policy failures, and provider errors are distinguishable.
- No control plane. Pooling, image catalogs, snapshots, network policy, quotas, billing, multi-tenant isolation, audit, and SLAs are product-owned.
- Conformance. A shared check suite must run against fakes and at least two live providers before promotion.
Candidate Shape¶
The following is a design sketch, not an exported API.
package workspace
type Spec struct {
Image string
WorkDir string
Env map[string]string
Timeout time.Duration
Metadata map[string]string
}
type Session interface {
ID() string
sandbox.Sandbox
vfs.Backend
Upload(ctx context.Context, path string, data []byte) error
Download(ctx context.Context, path string) ([]byte, error)
Close(ctx context.Context) error
}
type Provider interface {
Create(ctx context.Context, spec Spec) (Session, error)
Attach(ctx context.Context, id string) (Session, error)
}
type Pauser interface {
Pause(ctx context.Context) error
Resume(ctx context.Context) error
}
Alternatives to evaluate:
- Embedding vs composition. Embedding
sandbox.Sandboxandvfs.Backendis convenient but forces every session to support both. ReturningFiles()andSandbox()accessors is more flexible but less ergonomic. - Optional capabilities. Pause/resume should be a separate interface, not a method that fails at runtime. The same applies to snapshots and port access.
- Session identity. Decide whether
ID()is provider-local, globally unique, or opaque. Products must not parse it. - Attach semantics. Attach may be unsupported, may require the same caller identity, or may resume a paused session. These are different capabilities.
- File transfer. Upload/download may be required for providers whose VFS operations are expensive or asynchronous. Do not assume they are cheap.
- Resource and network policy. Keep them in adapter configuration until two providers show a stable common subset.
Provider Evaluation¶
This table records what the offline adapter spikes exercised. "Offline" means the operation passed the shared conformance suite against an in-process fake; it does not prove live provider behavior.
| Question | E2B | Daytona |
|---|---|---|
| Go Core or stable HTTP API | REST plus envd Connect/JSON; no official Go Core | Go Core v0.226.1 |
| Create / attach / close | Offline pass; live pending | Offline pass; live pending |
| Repeated command execution | Offline pass | Offline pass |
| Upload / download | Offline pass | Offline pass |
| Pause / resume | Offline pass; live pending | Offline pass; live pending |
| Snapshot or template | Provider documented; adapter not mapped | Provider documented; adapter not mapped |
| Network and port policy | Provider documented; adapter not exposed | Provider documented; adapter not exposed |
| Timeout and cancellation | Context plus Connect timeout | Context plus execution timeout |
| Error taxonomy | Connect/envd errors; only not-found and closed are mapped | Core errors; only not-found and closed are mapped |
| Auth and tenancy model | API key plus envd access token | API key or JWT, organization and target |
| License compatibility | Apache-2.0 | Apache-2.0 outside cli/; cli/ is AGPL-3.0 |
| Control-plane features | Provider-owned | Provider-owned |
The adapter spike must record the tested version, endpoint type, license, and which capabilities are unavailable.
Spike Findings¶
- The common subset matches the candidate
Session: create/attach, execute, upload/download, VFS reads and writes, and pause/resume. - Embedding
vfs.Backendandsandbox.Sandboxfit both adapters. OptionalPauseralso fit both. - E2B required a custom Connect frame codec and envd headers. Daytona required a Core implementation wrapper because the Core returns one combined command output string.
GlobandGrepare client-side walks on both adapters; neither exposes a portable server-side search contract.- Snapshot and network policy are provider-specific and should not enter the first contract.
- Path and working-directory semantics differ. The adapters normalize relative paths; live verification must confirm home-directory and cwd behavior.
- Before promotion: run live conformance, define a minimal error taxonomy, test cancellation and concurrency, test large file transfer, and decide attach semantics.
Further Candidates¶
Two more providers should join the next spike:
- OpenSandbox (Apache-2.0): Go Core
github.com/alibaba/OpenSandbox/sdks/sandbox/go; lifecycle, execd, and egress APIs; Docker and Kubernetes deployment; Firecracker pause/resume and network policy. Adapter status: offline conformance adapter; live pending. - CubeSandbox (Apache-2.0 except listed third-party components): Go Core
github.com/tencentcloud/CubeSandbox/sdk/go; E2B-compatible API; RustVMM/KVM isolation; pause/resume, snapshots, volumes, and egress policy. Adapter status: offline conformance adapter; live pending. Test whether the E2B adapter can serve as a compatibility profile before keeping the separate implementation.
OpenSandbox adds a self-hosted Go Core path with egress controls. CubeSandbox adds
hardware-level isolation and an E2B-compatible surface. Neither changes the core
contract; they are provider adapters and do not move the control plane into
pkg/.
CubeSandbox and E2B Compatibility¶
The offline review found that CubeSandbox is E2B-compatible at the Core and data plane level, but it is not a drop-in configuration for the current E2B adapter:
- CubeSandbox
Client.CreateandClient.Connectuse/sandboxes, while the E2B adapter uses/v2/sandboxes. CubeSandbox does expose/v2/sandboxesfor listing, but that does not prove the create/connect v2 path is identical. - CubeSandbox data-plane calls send
X-Access-Tokenand alsoe2b-traffic-access-token/cube-traffic-access-token; the E2B adapter sends onlyX-Access-Token. - CubeSandbox accepts
E2B_API_URLandE2B_API_KEYas configuration fallbacks, so a shared profile may be possible after live verification.
Recommendation: keep the dedicated CubeSandbox adapter. Do not treat the E2B adapter as a CubeSandbox profile until a live CubeSandbox endpoint confirms the v2 create/connect paths and traffic-token behavior.
Prototype Plan¶
- Add two adapter modules outside the core, for example
adapters/workspace/e2bandadapters/workspace/opensandbox. Keep each in its owngo.modand tag it independently. - Implement create/attach, execute, upload/download, and close against a caller-supplied credential. Do not add a provider SDK to the core module.
- Add an in-memory fake that implements the same contract for offline tests.
- Run one shared conformance suite against the fake and both adapters. Live provider tests are opt-in and must not run in default CI.
- Record every capability that does not fit, every provider-specific field, and every error that cannot be mapped cleanly.
- Only then propose an additive
pkg/contract. The existingpkg/vfsandpkg/sandboxdeclarations remain unchanged.
Promotion Criteria¶
A workspace/session contract is ready for pkg/ only when:
- two providers implement it without provider-specific fields in the public contract;
- the fake and both adapters pass the same conformance checks;
- cancellation and timeout do not leak sessions;
- error mapping is documented and tested;
- the core module still has no provider SDK dependency;
- the API is additive and does not change
vfs.Backend,vfs.Executor, orsandbox.Sandbox; - the compatibility and migration notes are written.
Until then, the contract stays in an adapter or evaluation module. The current
spike lives in
adapters/workspace
and provides the candidate contract, an in-memory fake, conformance checks, and
offline E2B and Daytona adapters. Neither adapter has been verified against a
live provider in this environment.
The live checks are opt-in and skip unless provider credentials are present:
E2B_API_KEY for E2B, and DAYTONA_API_KEY plus DAYTONA_IMAGE for Daytona.
Run them from each adapter module with go test -run TestLiveConformance.
Non-Goals¶
- A sandbox control plane, scheduler, warm pool, image registry, or billing system.
- A graph runtime or durable workflow engine.
- Provider-specific fields in
pkg/.... - A claim that a sandbox interface provides OS-level isolation. Isolation is provided by the provider or product.
Open Questions¶
- Should
Sessionembed bothvfs.Backendandsandbox.Sandbox, or expose them as accessors? - Is
Attacha core lifecycle operation or a provider capability? - Should pause/resume/snapshot share one optional capability interface?
- How are provider-side session IDs scoped across tenants and regions?
- What is the minimum portable error taxonomy?
- Which file-transfer semantics are safe to standardize: overwrite, atomic write, directory upload, or none?
- Does a workspace session need a lease or heartbeat, or is that product-owned?