The universal bridge between agents and environments. Train, evaluate, and collect rollouts across any agent and any sandbox. agentix build packages your stack; sandbox.remote runs callables inside it; abridge captures trajectories for eval and RL—no custom rollout microservice per pairing.
cd examples/hello-world
uv sync
uv run agentix build . --output dist/hello-world.bundle.tar
BUNDLE=$(uv run agentix deploy docker dist/hello-world.bundle.tar --format json | jq -r .bundle)
uv run python main.py --bundle "$BUNDLE"
from agentix import SandboxConfig
from agentix.bash import run
from agentix.provider.docker import DockerProvider

config = SandboxConfig(
    image="python:3.13-slim",
    bundle="/home/me/.cache/agentix/bundles/sha256-...",
)
async with DockerProvider().session(config) as sandbox:
    result = await sandbox.remote(run, command="echo hello from $(uname -a)")
The unit of composition is not a custom runner. It is a function.

The Core Idea

Agentix keeps the execution layer deliberately small:
  • Remote calls run an installed function inside a sandbox worker. sandbox.remote(fn, ...) derives the target from fn.__module__ and fn.__qualname__, ships args/kwargs as one pickle blob, and imports the function inside the worker.
  • Bundles package one Python project and its declared dependencies into a deploy-ready bundle. Agents, tools, benchmark scorers, and user code are just packages in the same runtime venv.

Remote Calls

Call sandbox code with ordinary Python functions instead of bespoke RPC clients.

Bundles

Build a reproducible bundle from pyproject.toml dependencies.

Providers

Run the same bundle through local Docker or a provider backend plugin.

Plugins

Extend runtime side channels with namespaces, logging, and tracing processors.

Integrations

Wrap an agent CLI, benchmark harness, or internal tool as a narrow Python API.

Why This Matters

Agent work tends to sprawl: each agent CLI, benchmark harness, sandbox provider, and training loop grows its own adapter. Agentix collapses that matrix into one rule: if it is installed in the bundle and importable by Python, the host can call it.
You haveYou exposeYou call
Claude Code, Codex, Aider, OpenHands, or an internal agentasync def run(...) -> RunResultawait sandbox.remote(run, ...)
Bash, file operations, repo setup, or local toolsasync def run(command: str) -> BashResultawait sandbox.remote(bash_run, ...)
SWE-bench, MLE-Bench, or an internal evaluatorasync def score(...) -> Scoreawait sandbox.remote(score, ...)

Where It Sits

Trainer / evaluator / script
  imports a function
  calls sandbox.remote(fn, *args, **kwargs)
        |
        v
Sandbox bundle
  imports the same module
  runs the function in a worker process
  returns the result
The same pattern works for a toy function, a CLI-driven coding agent, a benchmark scorer, or a full RL rollout step.

Example Rollout

Start with the complete runnable demo in examples/hello-world (see the agentix-cookbook for more examples):
cd examples/hello-world
uv run agentix build . --output dist/hello-world.bundle.tar
BUNDLE=$(uv run agentix deploy docker dist/hello-world.bundle.tar --format json | jq -r .bundle)
uv run python main.py --bundle "$BUNDLE"
This SWE-bench-shaped flow composes three independent packages in one sandbox: a shell primitive prepares the repo, an agent wrapper edits it, and a scorer wrapper grades the patch.
from datasets import load_dataset
from agentix import SandboxConfig
from agentix.bash import run as bash_run
from agentix.agents.claude_code import run as run_claude
from agentix.plugins.datasets.swe import score
from agentix.provider.docker import DockerProvider

inst = dict(load_dataset("princeton-nlp/SWE-bench_Verified", split="test")[0])

async with DockerProvider().session(SandboxConfig(image=image, bundle=bundle)) as sandbox:
    await sandbox.remote(
        bash_run,
        command=(
            f"git clone https://github.com/{inst['repo']}.git /testbed && "
            f"cd /testbed && git checkout {inst['base_commit']}"
        ),
    )

    await sandbox.remote(
        run_claude,
        instruction=inst["problem_statement"],
        workdir="/testbed",
        env={"ANTHROPIC_API_KEY": api_key},
    )

    diff = await sandbox.remote(
        bash_run,
        command="cd /testbed && git add -A && git diff --cached --no-color",
    )
    report = await sandbox.remote(score, instance=inst, patch=diff.stdout)
Agentix does not special-case Claude Code, SWE-bench, or bash. They are installed modules with functions the worker can import.

Public API

See the stable Python and CLI APIs with compatibility guarantees.

Quickstart

Build a tiny bundle, launch it in Docker, and call a remote function.

Remote Calls

Learn the import-path target and how side channels fit alongside.

Plugins

Understand /rpc, /log, /trace, and plugin-owned namespaces.

Bundles

See how dependency declarations become bundles.

Architecture

Follow the request from client to server to worker and back.