ARL Infrastructure - Python SDK for Kubernetes-based Agent Runtime Layer
Project description
arl-env Python SDK
High-level Python SDK for the agent-env Gateway API. The SDK creates sandbox
sessions, runs commands, streams output, transfers files, opens interactive
shells, and manages SandboxWarmPool resources through the gateway.
Release and Migration
Installation
pip install arl-env
# or
uv add arl-env
Interactive shell support needs the optional dependency:
pip install "arl-env[shell]"
Authentication
If gateway authentication is enabled, provide a bearer API key through the environment or constructor:
export ARL_API_KEY="your-api-key"
from arl import SandboxSession
session = SandboxSession(
image="python:3.12",
gateway_url="http://localhost:8080",
api_key="your-api-key",
)
Basic Usage
from arl import SandboxSession
with SandboxSession(
image="python:3.12",
gateway_url="http://localhost:8080",
) as session:
result = session.execute([
{"name": "hello", "command": ["echo", "Hello, World!"]},
])
print(result.results[0].output.stdout)
Commands run in the executor container, which uses the requested image. The sidecar only exposes the gRPC control plane and proxies execution to the executor-agent over a Unix socket.
Profile Semantics
profile is a pool-selection key, not a resource specification. The gateway
uses it to choose which SandboxWarmPool can satisfy a session request.
The caller does not choose a Kubernetes namespace. The gateway is deployed with one namespace scope, and all session and pool operations use that scope.
For a session request, selection works as follows:
- Empty
profileis normalized todefault. - If
imageis provided, the gateway looks for a scoped pool with the sameimageandprofile. If none exists, it creates an image-backed pool for that pair. - If only
profileis provided, the gateway selects an existing scoped pool with the same profile. - When several pools match, the gateway picks the one with the most available warm capacity.
The value does not create CPU, memory, GPU, or scheduling behavior by itself.
Those come from how the matching pool was created. A profile named gpu only
means "select pools labeled gpu"; it should point to pools that were actually
created with GPU resources.
Common patterns:
# Use the default profile. The gateway creates/reuses an image-backed pool.
session = SandboxSession(image="python:3.12")
# Select a pre-created profile. The selected pool determines the image.
session = SandboxSession(profile="gpu")
# Require both the image and the profile to match.
session = SandboxSession(image="python:3.12", profile="large-memory")
Use stable short names such as default, cpu, gpu, large-memory, or a
pool family name such as python-pool. Keep the same value on pool creation
and session creation when the session should target that pool family.
Persistent Sessions
Use manual lifecycle management when several operations should share the same
workspace. A context manager deletes the session on exit; close() only closes
the local HTTP client and leaves the remote session available for reattach.
Always call delete_sandbox() when the session is no longer needed.
from arl import SandboxSession
session = SandboxSession(image="python:3.12", gateway_url="http://localhost:8080")
session.create_sandbox()
session_id = session.session_id
session.execute([
{"name": "init", "command": ["sh", "-c", "echo 0 > /workspace/count.txt"]},
])
session.close() # detach; the remote session remains active
Attach to an existing session:
from arl import SandboxSession
session = SandboxSession.attach(session_id, gateway_url="http://localhost:8080")
try:
result = session.execute([{"name": "read", "command": ["cat", "/workspace/count.txt"]}])
print(result.results[0].output.stdout)
finally:
session.delete_sandbox()
session.close()
Streaming Output
execute() uses the gateway SSE endpoint when available. Pass on_output to
receive stdout/stderr chunks while the step is still running.
def on_output(stdout: str, stderr: str) -> None:
if stdout:
print(stdout, end="")
if stderr:
print(stderr, end="")
result = session.execute(
[{"name": "loop", "command": ["sh", "-c", "for i in 1 2 3; do echo $i; sleep 1; done"]}],
on_output=on_output,
)
File Transfer
Paths are relative to the session workspace.
session.upload_file("input.txt", "hello\n")
data = session.download_file("input.txt")
session.upload_path("local.bin", "data/local.bin")
session.download_path("data/local.bin", "out/local.bin")
History, Restore, and Trajectory
Each executed step is recorded in session history. Snapshot IDs are step-index strings used by the gateway's replay-based restore implementation.
r1 = session.execute([{"name": "write", "command": ["sh", "-c", "echo one > /workspace/x"]}])
snapshot_id = r1.results[0].snapshot_id
session.execute([{"name": "change", "command": ["sh", "-c", "echo two > /workspace/x"]}])
session.restore(snapshot_id)
history = session.get_history()
jsonl = session.export_trajectory()
WarmPool Management
WarmPoolManager uses the gateway pool endpoints. Pool creation is an admin
operation when gateway auth is enabled.
from arl import ResourceRequirements, WarmPoolManager
manager = WarmPoolManager(gateway_url="http://localhost:8080")
manager.create_warmpool(
name="python-pool",
image="python:3.12",
profile="python-pool",
replicas=2,
resources=ResourceRequirements(
requests={"cpu": "500m", "memory": "512Mi"},
limits={"cpu": "1", "memory": "1Gi"},
),
)
info = manager.wait_for_ready("python-pool", min_ready=1)
print(info.ready_replicas)
manager.scale_warmpool("python-pool", replicas=3)
manager.delete_warmpool("python-pool") # drain sessions/claims and scale to zero
# manager.destroy_warmpool("python-pool") # physically delete the WarmPool/template
Current sandbox-backed sessions support claim-scoped config_env.vars and
string-valued config_env.envVars environment injection. Pool creation still
rejects config_env, and sandbox-backed sessions still reject tools
provisioning and config_env ConfigMap/Secret/valueFrom provisioning requests.
list_tools() and call_tool() only work when the executor image already
contains /opt/arl/tools/registry.json and matching tool files.
Managed Sessions
ManagedSession creates or reuses a server-side managed pool for an image and
groups sessions by experiment ID.
from arl import ManagedSession
with ManagedSession(
image="python:3.12",
experiment_id="exp-1",
gateway_url="http://localhost:8080",
) as session:
result = session.execute([
{"name": "hello", "command": ["python", "-c", "print('ok')"]},
])
print(result.results[0].output.stdout)
Clean up an experiment:
from arl import GatewayClient
client = GatewayClient(base_url="http://localhost:8080")
deleted = client.delete_experiment("exp-1")
Core Classes
SandboxSession: session lifecycle, execute, replay, restore, files, logs, history, trajectory.ManagedSession: image + experiment session flow with server-side pool creation.GatewayClient: low-level HTTP client for all public gateway REST endpoints.WarmPoolManager: pool create/list/get/wait/scale/logs/drain/destroy helpers.InteractiveShellClient: WebSocket shell client.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arl_env-0.19.1.tar.gz.
File metadata
- Download URL: arl_env-0.19.1.tar.gz
- Upload date:
- Size: 43.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ed360091eac9b1d820e478311176b51bc7bb17bc423dae72e53426d74b285fe
|
|
| MD5 |
a03afd723a533b1ad7790356716ed100
|
|
| BLAKE2b-256 |
c42cd803e1b8b2bd5c902311c0a1ebee3118a656ba7fc99a8a90f63a8764d7b3
|
File details
Details for the file arl_env-0.19.1-py3-none-any.whl.
File metadata
- Download URL: arl_env-0.19.1-py3-none-any.whl
- Upload date:
- Size: 39.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ab6f575a1ce98f165f769b06255d981ebd4e02f3fa6adcddc10873083e2ead1
|
|
| MD5 |
b0febc85524e8a619b04a40d1d74375e
|
|
| BLAKE2b-256 |
6e77bc11e60526007e45c411825eeb9b1e6511e7de8ef93b2b0ce0cf6c6fa5a3
|