Environment File

One repo-committed .praisonai/environment.yaml that every compute backend uses

One .praisonai/environment.yaml file declares your project’s execution environment; every compute= backend reads it automatically.

Diagram

Environment File

📄 .praisonai/environment.yaml

🔧 load_environment_definition

⚙️ ComputeConfig

✅ Docker / E2B / Modal / Daytona / Novita

Quick Start

  1. Create the file

    Commit .praisonai/environment.yaml at your repo root with an image and one package:

    yaml
    # .praisonai/environment.yaml
    image: python:3.12-slim
    packages:
      pip: [requests]
  2. Enable compute — the file is picked up automatically

    Add compute="docker". No image or packages kwargs; the file supplies them.

    python
    from praisonai import LocalAgent, LocalAgentConfig
    from praisonaiagents import Agent
    
    # No image/packages kwargs — the file supplies them
    local = LocalAgent(compute="docker", config=LocalAgentConfig(model="gpt-4o-mini"))
    agent = Agent(name="assistant", backend=local)
    agent.start("Fetch example.com and summarise it")

How It Works

provision_compute() walks up from the current directory, loads the file into a ComputeConfig, then provisions the backend.

Diagram
Docker providerload_environment_definition()provision_compute()AgentUserDocker providerload_environment_definition()provision_compute()AgentUserkwargs > instance cfg > file > defaultsagent.start(“…”)kwargs (maybe empty)walk up for .praisonai/environment.yamlComputeConfig (or None)provision(ComputeConfig)install packagesrun setup[] (fail-loud)instance readyresponse
AspectDetail
Location.praisonai/environment.yaml at (or above) your working directory
Loaderload_environment_definition() returns a ComputeConfig, or None when no file exists
ConsumerEvery compute= backend (Docker, E2B, Modal, Daytona, Novita, Flyio, local)
Resolution orderkwargs > instance cfg > file > defaults

The Full File

Exactly these top-level keys are accepted; anything else raises ValueError with the file path.

yaml
# .praisonai/environment.yaml
image: python:3.12-slim
packages:
  pip: [pytest, requests]
  apt: [git, curl]
setup:                        # scalar string OR list of strings; scalar is normalised to [scalar]
  - pip install -e .
refresh:                      # optional; runs ONLY on capture-based starts (docker reuse)
  - pip install -e .
capture: true                 # optional; opt-in for cloud backends (docker is always-on)
env:
  PYTHONPATH: src
resources: {cpu: 2, memory_mb: 2048}   # gpu also supported
network: allowlist            # off | allowlist | full   → stored as ComputeConfig.networking = {"type": <value>}
backend: docker               # docker | e2b | modal | daytona | novita | flyio | local → stored as ComputeConfig.metadata["backend"]
working_dir: /workspace
mount_paths: []

Configuration Options

Every top-level key maps onto a ComputeConfig field.

YAML keyComputeConfig fieldTypeDefault
imageimagestr"python:3.12-slim"
packagespackagesDict[str, List[str]]{}
setupsetup (new)List[str][]
envenvDict[str, str]{}
working_dirworking_dirstr"/workspace"
mount_pathsmount_pathsList[str][]
resources.cpucpuint1
resources.memory_mbmemory_mbint1024
resources.gpugpuOptional[str]None
networknetworking = {"type": <value>}Dict{}
backendmetadata["backend"]strunset
refreshmetadata["refresh"]List[str]unset
capturemetadata["capture"]boolunset
ComputeConfig fields

TypeScript / Python ComputeConfig reference


Precedence

Explicit kwargs win, then the instance config, then the file, then hard-coded defaults — so no file means today’s behaviour, byte-identical.

Diagram

Explicit kwargs

Instance _cfg

.praisonai/environment.yaml

Hard-coded defaults

Pick the surface that matches where your config should live:

Diagram

One-off Python call

Shared across a team + reviewable in PRs

Programmatic per-tenant

Where does this config live?

kwargs on provision_compute

.praisonai/environment.yaml

ComputeConfig instance in code


setup: Commands

setup: runs once, post-provision, before any agent work — perfect for bootstrapping the repo.

yaml
# .praisonai/environment.yaml
image: python:3.12-slim
packages:
  pip: [pytest]
setup:
  - pip install -e .
  • Runs once, after packages install, before the agent starts.
  • Output is streamed to logs ([docker_compute] setup: <cmd> then setup output: <stdout>).
  • A failing command raises RuntimeError — it is not silently swallowed.
  • On failure during packages or setup, the just-started container is torn down so no orphan is leaked; the caller never receives an instance_id.

Faster reruns

The docker backend automatically captures the environment after setup: runs and reuses it on the next provision — no pull, no install, no setup:. Add refresh: if you have a cheap incremental step to run on reuse (e.g. pip install -e .).

Card

Reuse a provisioned docker environment across runs — skip pull, install, and setup


Common Patterns

Pin the image

Lock the base image so every teammate and CI run starts identical.

yaml
# .praisonai/environment.yaml
image: python:3.12-slim

Bootstrap the repo

Install the current project in editable mode before the agent runs.

yaml
# .praisonai/environment.yaml
image: python:3.12-slim
packages:
  pip: [pytest]
setup:
  - pip install -e .

Per-CI vs per-dev env

Set project variables in the file so they travel with the repo.

yaml
# .praisonai/environment.yaml
image: python:3.12-slim
env:
  PYTHONPATH: src
  LOG_LEVEL: info

Loader used directly

Read the file yourself when you need the resolved config in code.

python
from praisonaiagents.managed import (
    load_environment_definition,
    find_environment_definition,
)

path = find_environment_definition()     # walks up like config discovery
cfg = load_environment_definition(path)  # returns ComputeConfig or None
print(cfg.image, cfg.packages, cfg.setup)

Best Practices

Keep it opt-in

No file means today’s behaviour, byte-identical. Add the file only when you want file-based defaults — nothing else changes.

Prefer file over kwargs

Commit .praisonai/environment.yaml so the environment is reviewable in PRs and reproducible across CI and dev. kwargs still win when you need a one-off override.

Set explicit resources

State resources.cpu and resources.memory_mb in CI instead of relying on the 1 CPU / 1024 MB default.

Fail-loud setup

Let setup: commands raise on error. Don’t append || true — you’ll want the failure surfaced, not hidden.


Errors

The loader raises ValueError (prefixed with the file path) for malformed files.

text
ValueError: <path>: unknown key(s) ['imagz']; allowed keys are ['backend', 'env', 'image', 'mount_paths', 'network', 'packages', 'resources', 'setup', 'working_dir']
text
ValueError: <path>: environment definition must be a mapping, got list
text
ValueError: <path>: 'packages' must be a mapping, got list

The last shape also applies to env, setup, image, and resources when their nested type is wrong.


Related