You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make provisioned agent environments fast to reuse: after the environment definition's packages install and setup: commands run once, capture that state and start subsequent runs from the capture instead of re-installing from scratch every time. Target: second-and-later runs start in seconds. This is the speed half of the environments work and depends on the definition sibling (#3669) — the capture is keyed by a hash of the definition, so any change to it invalidates cleanly.
Current behaviour (every run pays full setup; capture primitives unused)
Validated on current main:
Zero environment snapshots anywhere.grep -rni "snapshot" across all packages returns only file/context/skill/config snapshots (paths.py:200-207, trace/context_events.py:155, skills/manager.py:865-871, …). praisonai_sandbox/ contains 0 occurrences of the word. No commit, pause, fork, or image-cache concept in either execution stack.
Everything is ephemeral by design today: the docker sandbox backend's start() only pulls the base image and each execute() is a fresh docker run (praisonai_sandbox/docker.py:79-100, 278, 430-457); the daytona backend creates a sandbox per session and destroys it on cleanup (daytona.py:96-116). ComputeProviderProtocol has provision/execute/shutdown — no snapshot method (praisonaiagents/managed/protocols.py:91+).
The cloud SDKs already support capture and it's unused: the E2B and Daytona SDKs natively support sandbox pause/snapshot/resume; PraisonAI's adapters never call them. Docker supports commit for image capture; unused.
The only related CLI verb is the opposite of a capture: praisonai sandbox recreatedeletes containers so they rebuild from base (praisonai_code/cli/commands/sandbox.py:230-292).
docker → docker commit to a local image praisonai-env:{hash12};
e2b / daytona → the SDK's native snapshot/pause primitive, id recorded;
subprocess/sandlock/ssh → no capture (documented no-op; nothing to capture or capture is meaningless).
Reuse on match: next provision with the same definition hash starts from the capture (skip pull+install+setup). Any change to the definition file → new hash → fresh build then new capture. Manual refresh: praisonai env rebuild (capture invalidate + rebuild).
Optional refresh hook: a refresh: command list in the definition runs when starting from a capture (e.g. pip install -e . to catch code changes) — cheap incremental step, never the full setup.
Bookkeeping: captures recorded in ~/.praisonai/environments/registry.json{definition_hash: {backend, ref, created_at, last_used}}; praisonai env list shows them; age-based GC (default 14 days unused) with praisonai env prune.
Safety/defaults: capture is on by default only for backends where it is free and local (docker commit); cloud snapshot capture is opt-in per definition (capture: true) since it may carry provider cost. A failed capture degrades to today's ephemeral behaviour with a log line — never blocks the run.
Layer placement
Core (praisonaiagents): one optional protocol addition — capture(instance) -> ref / provision_from(ref) on the compute/sandbox protocols (default NotImplemented → ephemeral path), plus the definition-hash helper.
definition_hash(defn) -> str — stable sha256 over the normalised definition (image, packages, setup, env names, resources; exclude values marked secret).
Protocol: SupportsCapture (optional) on ComputeProviderProtocol/sandbox backend protocol; provision flow becomes: registry lookup by hash → provision_from(ref) + refresh: if hit → else full provision + setup → capture() → registry record.
Docker: docker commit {container} praisonai-env:{hash12} after setup (praisonai_sandbox/docker.py post-setup site; also the compute docker provider); provision-from = use that image instead of base.
Docs: the run-twice contract — first run builds and captures; subsequent runs start from capture; edit the file → automatic rebuild.
Tests (TDD)
test_definition_hash_stable_and_sensitive — reordering keys → same hash; changing a package → new hash.
test_docker_capture_and_reuse — second provision with same definition skips setup (setup command spy called once) and starts from praisonai-env:{hash12}.
test_definition_change_invalidates — edited file → full rebuild + new capture.
test_refresh_runs_on_capture_start — refresh: executes only on capture-based starts.
test_capture_failure_degrades_ephemeral — commit error → run proceeds as today, warning logged.
test_registry_gc_prune — unused entries pruned by age; env prune removes refs and (docker) images.
Severity
Medium-High — without reuse, the environment definition (#3669) makes every provision slower in exchange for reproducibility; with it, PraisonAI matches the fast-start property the major cloud coding agents converge on (setup-once-then-cached), and multi-worker kanban boards amortise setup across the fleet. The primitives (docker commit, cloud SDK snapshots) already exist under the adapters — this is wiring plus bookkeeping.
Validation (current main)
No env snapshots: repo-wide grep (only file/context/skill snapshots); 0 hits in praisonai_sandbox/; no commit/pause/fork in either stack.
Aim
Make provisioned agent environments fast to reuse: after the environment definition's packages install and
setup:commands run once, capture that state and start subsequent runs from the capture instead of re-installing from scratch every time. Target: second-and-later runs start in seconds. This is the speed half of the environments work and depends on the definition sibling (#3669) — the capture is keyed by a hash of the definition, so any change to it invalidates cleanly.Current behaviour (every run pays full setup; capture primitives unused)
Validated on current
main:grep -rni "snapshot"across all packages returns only file/context/skill/config snapshots (paths.py:200-207,trace/context_events.py:155,skills/manager.py:865-871, …).praisonai_sandbox/contains 0 occurrences of the word. Nocommit,pause,fork, or image-cache concept in either execution stack.start()only pulls the base image and eachexecute()is a freshdocker run(praisonai_sandbox/docker.py:79-100, 278, 430-457); the daytona backend creates a sandbox per session and destroys it on cleanup (daytona.py:96-116).ComputeProviderProtocolhasprovision/execute/shutdown— no snapshot method (praisonaiagents/managed/protocols.py:91+).commitfor image capture; unused.praisonai sandbox recreatedeletes containers so they rebuild from base (praisonai_code/cli/commands/sandbox.py:230-292)..praisonai/environment.yaml(image/packages/setup/resources) consumed by sandbox, compute, and kanban workers +praisonai envCLI #3669 lands: a definition withpackages+setup:would re-run installs on every provision — kanban boards spawning many workers pay it per worker; iterativesandbox runpays it per invocation.Desired behaviour
.praisonai/environment.yaml(Environments: no repo-committed execution-environment definition — add.praisonai/environment.yaml(image/packages/setup/resources) consumed by sandbox, compute, and kanban workers +praisonai envCLI #3669), after packages+setup:succeed the backend captures the state:docker committo a local imagepraisonai-env:{hash12};praisonai env rebuild(capture invalidate + rebuild).refresh:command list in the definition runs when starting from a capture (e.g.pip install -e .to catch code changes) — cheap incremental step, never the full setup.~/.praisonai/environments/registry.json{definition_hash: {backend, ref, created_at, last_used}};praisonai env listshows them; age-based GC (default 14 days unused) withpraisonai env prune.capture: true) since it may carry provider cost. A failed capture degrades to today's ephemeral behaviour with a log line — never blocks the run.Layer placement
praisonaiagents): one optional protocol addition —capture(instance) -> ref/provision_from(ref)on the compute/sandbox protocols (defaultNotImplemented→ ephemeral path), plus the definition-hash helper.praisonai-sandbox/ wrapperintegrations/compute/: per-backend implementations (docker commit; e2b/daytona SDK snapshot calls behind their existing extras).praisonai-code:env rebuild/list/pruneverbs besideenv init/validate/show(Environments: no repo-committed execution-environment definition — add.praisonai/environment.yaml(image/packages/setup/resources) consumed by sandbox, compute, and kanban workers +praisonai envCLI #3669)..praisonai/environment.yaml(image/packages/setup/resources) consumed by sandbox, compute, and kanban workers +praisonai envCLI #3669 (the definition is the cache key and the setup being amortised).Implementation plan
definition_hash(defn) -> str— stable sha256 over the normalised definition (image, packages, setup, env names, resources; exclude values marked secret).SupportsCapture(optional) onComputeProviderProtocol/sandbox backend protocol; provision flow becomes: registry lookup by hash →provision_from(ref)+refresh:if hit → else full provision + setup →capture()→ registry record.docker commit {container} praisonai-env:{hash12}after setup (praisonai_sandbox/docker.pypost-setup site; also the compute docker provider); provision-from = use that image instead of base.praisonai_sandbox/e2b.py,daytona.py,integrations/compute/{e2b,daytona}.py) behindcapture: true.praisonai_code/cli/commands/):env list,env rebuild,env prune.Tests (TDD)
test_definition_hash_stable_and_sensitive— reordering keys → same hash; changing a package → new hash.test_docker_capture_and_reuse— second provision with same definition skips setup (setup command spy called once) and starts frompraisonai-env:{hash12}.test_definition_change_invalidates— edited file → full rebuild + new capture.test_refresh_runs_on_capture_start—refresh:executes only on capture-based starts.test_capture_failure_degrades_ephemeral— commit error → run proceeds as today, warning logged.test_noncapturing_backend_noop— subprocess backend unchanged.test_registry_gc_prune— unused entries pruned by age;env pruneremoves refs and (docker) images.Severity
Medium-High — without reuse, the environment definition (#3669) makes every provision slower in exchange for reproducibility; with it, PraisonAI matches the fast-start property the major cloud coding agents converge on (setup-once-then-cached), and multi-worker kanban boards amortise setup across the fleet. The primitives (docker commit, cloud SDK snapshots) already exist under the adapters — this is wiring plus bookkeeping.
Validation (current main)
praisonai_sandbox/; nocommit/pause/forkin either stack.praisonai_sandbox/docker.py:79-100, 278, 430-457;daytona.py:96-116;ComputeProviderProtocollacks capture (managed/protocols.py:91+).sandbox recreatedestroys rather than captures:praisonai_code/cli/commands/sandbox.py:230-292.Related
.praisonai/environment.yaml(image/packages/setup/resources) consumed by sandbox, compute, and kanban workers +praisonai envCLI #3669 — the environment definition (prerequisite; provides the cache key and the setup to amortise).