Environments
Portable access to files, commands, processes, and ports in local, container, cloud, and remote targets.
An Environment gives portable access to files, commands, processes, retained output, and ports. Use it directly in automation, or supply a fresh adapter to Harness so an Agent can work in a selected workspace, sandbox, container, VM, or remote execution target. It requires no Agent, model credential, or hosted service.
Environment Providers ship in a13n-harness; only vendor SDKs live behind extras. You do not need an Environment for an Agent that only calls ordinary application tools or remote APIs.
Start here
| Task | Guide |
|---|---|
| Read and write a file with no network dependencies | Getting started |
| Choose local, sandbox, container, or remote execution | Choose a backend |
| Understand close, state, re-entry, and destruction | Lifecycle and state |
| Configure built-ins, credentials, and runtime collaborators | Provider configuration |
| Compare the six cloud providers | Cloud providers |
| Implement a Provider or supply Host runtimes | Providers and runtime |
| Run commands, inspect processes, and read retained output | Commands and processes |
| Understand paths, search patterns, and output limits | Operations |
| Run a complete built-in lifecycle | Runnable examples |
| Connect HTTP or reverse WebSocket Envd | Remote Envd |
| Expose Environment tools to an Agent | Harness integration |
Three concepts
- Provider definition: validates account inputs, credentials, and the target recipe, then constructs adapters without target I/O.
- Environment: one single-use adapter that prepares a target, exposes operations, and closes local resources.
EnvironmentState: portable Provider-owned target evidence, supplied to a later fresh adapter.
close() is non-destructive; explicit destroy() is a separate Host decision. Some Providers, including Direct Local, have no portable target state and own no target destruction. A root directory, target ID, or successful connection is not proof of isolation.
Choose a backend
Use no Environment when the Agent needs only ordinary tools or remote APIs. Otherwise select a Native or Envd route:
| Route | Provider | Use it for | Operation and ownership boundary |
|---|---|---|---|
| Native | direct_local | Trusted local automation | Host OS operations; existing directory, no sandbox claim |
| Native | e2b | Native managed cloud sandbox | E2B SDK; sandbox create/pause/resume/renew/destroy |
| Native | daytona | Cloud sandbox | Native stop/start and preserved files |
| Native | modal | Cloud sandbox | Snapshot-backed stop/resume; fixed running lifetime |
| Native | vercel | Cloud sandbox | Named persistent sandbox with native sessions |
| Native | sprites | Cloud sandbox | Persistent disk and automatic sleep/wake |
| Native | runloop | Cloud sandbox | Devbox suspend/resume and idle keepalive |
| Envd | local_envd | CLI and local Agents | Private stdio daemon; close preserves workspace |
| Native | docker | Single-host services | Docker Engine lifecycle and exec; close preserves container |
| Envd | http_envd | Network-reachable external environments | HTTP(S) EIP; connect-only |
| Envd | websocket_envd | Environments that connect back to a Host | Reverse WebSocket EIP; Host-integrated SDK, connect-only |
Try the remote examples locally without a model, Docker or cloud account.
How the layers fit
- Host selects a trusted Provider, desired configuration, current state, runtime collaborators, retention policy, and authorization.
- Environment Provider definition validates account inputs, credentials, and the target recipe, then constructs fresh single-use adapters; it acquires a live collaborator only in its runtime factory.
- Environment enters or creates one exact target, exposes typed operations, caches the latest state, closes process-local resources, and supports explicit Host destruction.
- Agent Harness owns Run-local mount names, access ceilings, routing, state aggregation, and non-destructive cleanup.
- EIP is the typed operation protocol used by
a13n-envdand remote backends.
EnvironmentState and HarnessState are different records. The former is a Provider-owned soft reference to a target; the latter is Agent continuation state. Neither restores current credentials or authorization.
Build an Environment-aware Agent
Binding an Environment supplies runtime authority but does not automatically expose operations to the model. Add the dynamic Environment Capability; it derives model-visible tools from each mount's effective access and Provider capabilities:
from a13n_harness import AgentSpec, HarnessBuilder
from a13n_harness.environment import (
DynamicEnvironmentCapability,
DynamicEnvironmentConfiguration,
)
executable = HarnessBuilder().build(
AgentSpec(model="openai-responses:gpt-5"),
output_type=str,
capabilities=(
DynamicEnvironmentCapability(DynamicEnvironmentConfiguration()),
),
)Configure the selected model provider before running the examples, or replace the model with a deterministic FunctionModel in tests.
Start with Direct Local
Direct Local exposes an existing directory selected by the Host:
from pathlib import Path
from a13n_harness.providers.environment.builtins import select_builtin_environment_providers
(direct_local,) = select_builtin_environment_providers(("direct_local",))
environment = await direct_local.create(
{"root": {"path": str(Path("./workspace").resolve())}},
environment_id="workspace",
)
result = await executable.run(
"Inspect the workspace",
environment=environment,
)The Provider inspects the directory during preparation, not scope entry. Harness closes the adapter after the Run but never destroys a target. Direct Local preserves the directory on close and rejects target destruction.
Direct Local restrictions apply through the current Environment mount. They do not isolate an allowed child process from the Host user account.
Use Local Envd
The Host owns a shared Local Envd runtime and its lazily launched Device. Each fresh adapter opens an independent Session with a fixed Device working directory:
from a13n_harness.providers.environment.builtins import select_builtin_environment_providers
from a13n_harness.providers.environment.local_envd.runtime import (
LocalEnvdProviderRuntime,
TemporaryLocalEnvdRuntimeAllocator,
resolve_a13n_envd_executable,
)
(local_envd,) = select_builtin_environment_providers(("local_envd",))
async with LocalEnvdProviderRuntime(
executable=resolve_a13n_envd_executable(),
allocate_private_runtime=TemporaryLocalEnvdRuntimeAllocator(),
) as runtime:
environment = await local_envd.create(
{"working_directory": "/absolute/path/to/workspace"},
environment_id="workspace",
runtime=runtime,
)
result = await executable.run(
"Inspect the working directory",
environment=environment,
)
# Harness closes this adapter's Session. The Host can use another adapter
# on the same runtime; leaving this context closes the shared Device.Executable resolution checks an explicit argument, A13N_ENVD_EXECUTABLE, then a13n-envd on PATH. The client and Provider packages do not install or download the native binary.
Local Envd validates exact daemon/client compatibility and never falls back to Direct Local. Envd paths address the Device filesystem; a fixed cwd is not containment. Host-managed accounts, containers, or sandboxes own filesystem and network isolation. Read the a13n-envd guide for setup and security boundaries.
Re-enter and retain a target
A stateful Provider such as Docker returns EnvironmentState. The Host persists the latest state and supplies it when constructing the next fresh adapter:
current_state = await state_store.load(environment_key)
environment = await docker.create(
recipe,
configuration={"docker_host": "unix:///var/run/docker.sock"},
environment_id="workspace",
state=current_state,
)
try:
result = await executable.run(
"Continue the task",
environment=environment,
previous_state=previous_harness_state,
)
finally:
await state_store.publish(environment_key, environment.dump_state())dump_state() is a synchronous detached read of the adapter's latest validated cache. The Host can call it after entry failure, cancellation, Run failure, or close failure without causing more provider I/O.
Close and destruction are deliberately separate:
| Operation | Owner | Effect |
|---|---|---|
| Enter and Run-local use | Harness | Enters one fresh adapter and mounts its operations |
close() | Harness | Releases process-local resources without removing the target |
| State persistence | Host | Selects and stores the latest authoritative EnvironmentState |
Fresh-adapter destroy() | Host | Removes the exact Provider-owned target and bootstrap material when retention selects it |
A suspended or failed Run still closes its adapter non-destructively. Harness never infers temporary ownership and never calls destroy().
Use several Environments
Pass multiple fresh adapters with explicit Run-local policy:
from a13n_harness import EnvironmentMount
from a13n_harness.environment import FILE_READ_ACTIONS, EnvironmentPermissionSet
result = await executable.run(
"Read the source data and write the build output",
environments={
"build": build_environment,
"data": EnvironmentMount(
data_environment,
permission_ceiling=EnvironmentPermissionSet(operations=FILE_READ_ACTIONS),
),
},
default_environment="build",
)The default mount is available at /workspace; named mounts are available at /environment/{name}. When several entries are present, select default_environment explicitly or leave /workspace unbound. Mapping order never grants authority.
Harness validates the complete mount set before entry. If one adapter fails, it closes every supplied adapter that may own process-local resources and publishes no partial mount set. It never destroys a target during unwind.
Select only required operations
EnvironmentMount narrows Provider capability with an exact permission_ceiling; FILE_READ_ACTIONS and FILE_ACTIONS are the shared action sets. DynamicEnvironmentConfiguration controls which stable Environment Toolsets the model can see. Keep shell, background-process, retained-output, and port operations absent unless the Agent definition requires them.
The Harness Environment guide covers complete Capability configuration, deterministic routing, state export, portable process references, and advanced Host runtimes.
Next steps
- Run the built-in Provider examples
- Use Environments from Agent Harness
- Manage Provider state and implement a Provider plugin
- Operate and configure
a13n-envd - Read the EIP and a13n-envd specifications
Hosted preparation and recovery
The Service builds on these providers: it creates managed Docker and cloud sandbox environments from templates, connects to external envd targets by endpoint and token, and freezes each run's mounts; see Service environments. The embedded Provider lifecycle described above remains usable independently.
For direct SDK integrations, use Environment lifecycle and errors and remote Envd.