Skip to main content

Axern Python SDK

The Axern Python SDK is the first-class programmable interface for Axern sandboxes. It exposes both the control plane client and a high-level Sandbox API for lifecycle, command execution, attached processes, file operations, directory transfer, tunnels, capability discovery, and diagnostics.

Install

Install the published package:

uv add axern-sdk

For repository development, build and run examples through the root uv workspace:

uv build --no-sources sdk/python
uv run --package axern-sdk python sdk/python/examples/sandbox_programming.py

Connect

from axern_sdk import AxernClient

client = AxernClient.from_context("~/.config/axern/config.json")

TLS-enabled local compose setups can pass certificate paths directly:

client = AxernClient(
    "127.0.0.1:25000",
    tls_ca_cert=".dev/certs/ca.crt",
    tls_cert=".dev/certs/client.crt",
    tls_key=".dev/certs/client.key",
)

AsyncAxernClient provides the same control-plane surface for asyncio code. Constructors are explicit and never read the user directory. from_context() loads a named CLI context from the supplied path; from_env() is available for environment-driven automation and reads AXERN_ENDPOINT plus the gateway TLS and proxy variables.

Sandbox Sources

Create a sandbox from exactly one source:

  • image="docker.io/library/python:3.12-slim" for an OCI image.
  • template_id="python311" for a deployment-provided template input.
  • environment_id="..." for an existing environment.
from axern_sdk import AxernClient, Sandbox

client = AxernClient("127.0.0.1:25000")

with Sandbox(client=client, image="docker.io/library/python:3.12-slim") as sandbox:
    print(sandbox.metadata.allocation_id)

client.close()

Network Policies

Omitting network_policy requests unrestricted networking. Strict policies are fail-closed; deny_dns only refuses matching traditional UDP/TCP DNS queries and does not block direct IP traffic, DoH, DoT, or already-resolved addresses.

from axern_sdk import NetworkPolicy, Sandbox

with Sandbox(
    client=client,
    image="docker.io/library/python:3.12-slim",
    network_policy=NetworkPolicy.deny_dns(
        "github.com",
        "*.github.com",
        "githubusercontent.com",
        "*.githubusercontent.com",
        "gitlab.com",
        "*.gitlab.com",
        "bitbucket.org",
        "*.bitbucket.org",
    ),
) as sandbox:
    print(sandbox.metadata.allocation_id)

NetworkPolicy.allow_domains("example.com", "*.example.com") is strict: only HTTP/HTTPS traffic whose controlled DNS result and HTTP Host or TLS SNI match is allowed. Use NetworkPolicy.strict(..., cidr_rules=(CIDRRule(...),)) for explicit TCP/UDP CIDR and port grants, and NetworkPolicy.deny_all() for no egress.

Allocation-Local Files

Writable files belong to the sandbox allocation and are not preserved across replacement or node loss. Use the file APIs while the sandbox is alive and explicitly download or publish outputs that must outlive it.

from axern_sdk import Sandbox

with Sandbox(
    client=client,
    image="docker.io/library/python:3.12-slim",
) as sandbox:
    sandbox.write_text("/tmp/result.txt", "allocation-local output\n")
    sandbox.download_file("/tmp/result.txt", "result.txt")

Exec

Use exec() for command-result workflows. Set text=True to decode stdout and stderr; set check=True to raise SandboxExecError on non-zero exit.

with Sandbox(client=client, image="docker.io/library/python:3.12-slim") as sandbox:
    result = sandbox.exec("python -c \"print('hello')\"", text=True, check=True)
    print(result.stdout)

Use exec_stream() when stdout/stderr should be consumed as events:

for event in sandbox.exec_stream(["python", "-u", "-c", "print('streamed')"]):
    if event.stream == "stdout":
        print(event.text(), end="")

Attached Process

Use process() when your program needs to control stdin, observe output, wait, or terminate a running command.

with sandbox.process(["python", "-u", "-c", "import sys; print(sys.stdin.read().upper())"]) as process:
    process.write("hello process\n")
    process.close_stdin()

    for event in process.events():
        if event.stream == "stdout":
            print(event.text(), end="")

    result = process.wait()
    print(result.exit_code)

AsyncSandbox.process() returns AsyncSandboxProcess with async equivalents of write(), close_stdin(), events(), wait(), terminate(), and kill().

Files

Single-file APIs are byte-safe. Text helpers only encode/decode at the SDK boundary.

sandbox.write_text("/tmp/message.txt", "payload\n")
print(sandbox.read_text("/tmp/message.txt"))

sandbox.write_bytes("/tmp/blob.bin", b"\x00\x01")
data = sandbox.read_bytes("/tmp/blob.bin")

Platform file operations are handled by the node/runtime file service, not by SDK-side shell fallbacks:

sandbox.copy("/tmp/message.txt", "/tmp/message-copy.txt", overwrite=True)
sandbox.move("/tmp/message-copy.txt", "/tmp/message-final.txt")
sandbox.chmod("/tmp/message-final.txt", 0o600)
sandbox.touch("/tmp/message-final.txt")

info = sandbox.stat("/tmp/message-final.txt")
entries = sandbox.list_dir("/tmp")
exists = sandbox.exists("/tmp/message-final.txt")

Directory Transfer

Directory upload/download uses archive streaming. The SDK packages local directories with tarfile and safely extracts downloaded archives; remote file semantics remain owned by the platform file service.

from pathlib import Path

source = Path("example-upload")
source.mkdir(exist_ok=True)
source.joinpath("data.txt").write_text("directory payload\n")

sandbox.upload_dir(source, "/tmp/example-upload", overwrite=True)
sandbox.download_dir("/tmp/example-upload", "example-download", overwrite=True)

Local symlinks are rejected during upload. Download extraction rejects absolute paths, parent traversal, symlinks, and hardlinks.

Tunnel

Pass upstream to expose a local TCP service to code running inside the sandbox. The SDK owns the tunnel connector and renews finite tunnel TTLs while the sandbox is active.

from axern_sdk import Sandbox

with Sandbox(
    client=client,
    image="docker.io/library/python:3.12-slim",
    upstream="127.0.0.1:8080",
    remote_port=8786,
) as sandbox:
    print(sandbox.bound_addr)

Metadata

Sandbox.state is the lightweight runtime state. Sandbox.metadata is stable for logs and diagnostics:

metadata = sandbox.metadata
print(metadata.environment_id, metadata.run_id, metadata.allocation_id)
print(metadata.node_id, metadata.run_id, metadata.tunnel_session_id)

Capabilities

Use capability_status() to discover baseline and optional sandboxd-backed providers before calling Computer Use APIs:

status = sandbox.capability_status()
print(status.ready, status.capabilities)

for provider in status.providers:
    print(provider.name, provider.state, provider.available, provider.reason)

Errors

SDK exceptions expose fields for programmatic handling:

from axern_sdk import (
    SandboxConnectionError,
    SandboxPermissionError,
    SandboxPreconditionError,
    SandboxRpcError,
)

try:
    sandbox.exec("python -V", check=True)
except SandboxConnectionError as exc:
    if exc.retryable:
        print("temporary node/control-plane connectivity issue")
    raise
except SandboxPermissionError as exc:
    print("credentials do not permit this operation", exc.operation)
    raise
except SandboxPreconditionError as exc:
    if exc.capability:
        print(
            exc.capability.capability,
            exc.capability.provider,
            exc.capability.provider_state,
            exc.capability.missing_dependencies,
        )
    raise
except SandboxRpcError as exc:
    print(exc.operation, exc.code, exc.details, exc.allocation_id)
    raise

Common error classes:

  • SandboxNotStartedError: operation requires an active sandbox.
  • SandboxExecError: exec(..., check=True) observed non-zero exit.
  • SandboxConnectionError: transport or connectivity failure.
  • SandboxPermissionError: authentication or authorization failure.
  • SandboxRpcError: gRPC status mapped from node/runtime APIs.
  • SandboxTimeoutError: SDK-side timeout.

Sandboxd-backed capability failures keep their normal SDK exception class and also expose exc.capability when the node returns provider diagnostics. That object contains capability, provider, provider_state, reason, and missing_dependencies, so callers can branch on missing Computer Use dependencies without parsing the full error string.

Async

Async APIs mirror the synchronous shape:

from axern_sdk import AsyncAxernClient, AsyncSandbox

async with AsyncAxernClient("127.0.0.1:25000") as client:
    async with AsyncSandbox(client=client, template_id="python311") as sandbox:
        result = await sandbox.exec("python -c \"print('hello async')\"", text=True, check=True)
        print(result.stdout)

        async with await sandbox.process(["python", "-u", "-c", "import sys; print(sys.stdin.read())"]) as process:
            await process.write("async input\n")
            await process.close_stdin()
            async for event in process.events():
                if event.stream == "stdout":
                    print(event.text(), end="")

Examples

Runnable examples live in examples:

Examples expect a reachable Axern gateway control edge at 127.0.0.1:25000.

Validation

make test-py
make lint-py
make sdk-python-verify
make local-compose-python-sdk-e2e

Run Output Retention

Run output reads expose Allocation-local stdout/stderr after runtime cleanup until output_expires_at, fixed at 15 minutes after cleanup begins. The combined readable limit is 64 MiB, with an explicit truncation signal. Node-process restart preserves sealed output; node-disk loss does not. Ordinary writable files still require explicit download before termination. No durable output object or persistent workspace is created.

Metadata

Release files for axern-sdk 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for axern-sdk 0.7.0
File Size Uploaded
axern_sdk-0.7.0.tar.gz 114.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for axern-sdk 0.7.0
File Interpreter ABI Platform
axern_sdk-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 271.3 kB

Release files / axern_sdk-0.7.0.tar.gz

Download URL axern_sdk-0.7.0.tar.gz
Size 114.3 kB
Tags Source
SHA-256 checksum
How to use checksums
8b0b8469e3a38a6f2bc700b37f28b3aa2c18aa91ee5997f80088ceda68739e21
BLAKE2b-256 checksum
How to use checksums
6626d20dba682e68a9e44c046b94c78565adfa0041e8e2d84dc842ad205d7914
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","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}

Release files / axern_sdk-0.7.0-py3-none-any.whl

Download URL axern_sdk-0.7.0-py3-none-any.whl
Size 157.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7e1b4ab05f28a585c64491bb1afd1caead511a2f901738780c07797534db8c73
BLAKE2b-256 checksum
How to use checksums
d059a2a986c88d2a830dfc468a1667f4b58d39f661b681b7a85ae8c28e7712ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","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}

Release history Release notifications | RSS feed

0.12.1

2 release files

0.12.0

2 release files

0.11.4

2 release files

0.11.3

2 release files

0.11.2

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.8.1

2 release files

0.8.0

2 release files

This release

0.7.0 This release

2 release files

0.6.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.2.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page