Skip to main content

levain-runtime

Run a Levain agent on your own machine or in your own container image. The platform keeps the recipe, its versions, the run history and the improvement loop; this runtime executes the agent's nodes where your data, tools and dependencies live.

The runtime never accepts inbound connections. It opens one outbound tunnel to the platform and serves node execution over it. Model calls either go through the platform (metered as usual) or use the Claude login present on the runtime host, as configured per runtime.

Install

uv tool install levain-runtime

Set up

# Run nodes directly on this host:
levain-runtime init --mode direct

# Direct mode serving four sessions at once (Linux with bubblewrap):
levain-runtime init --mode direct --sessions 4

# Or run each session in a container built from your own image:
levain-runtime init --mode docker --image ghcr.io/you/agent-runtime:latest

Direct mode shows nodes /workspace, /recipes, /sdk and /sandbox from the runtime's home directory (~/.levain/runtime). On Linux with bubblewrap installed each node sees them inside its sandbox and init needs no root; runtimes with different homes (LEVAIN_RUNTIME_HOME) can share a filesystem. Without bubblewrap the command prints and runs ln commands linking them at the filesystem root, with sudo when / is not writable. On macOS the links come from /etc/synthetic.conf: init writes the entries and asks for one restart.

A docker image needs Python 3.12 or later with levain-sdk[review,models] installed, plus whatever your recipes import.

Register and run

export LEVAIN_API_KEY=...   # a workspace API key
levain-runtime register --name workstation --model-auth local
levain-runtime up

register creates the runtime in your workspace and stores its credentials here. If the runtime was created elsewhere (the Levain app or API), pass the credentials it returned instead: levain-runtime connect --credentials runtime-credentials.json.

Re-running register with a name the workspace already holds reclaims that runtime with new credentials; the agents bound to it stay bound. It is refused while the runtime is online or unreachable, unless you pass --take-over.

up starts the local node server, the tunnel client and a heartbeat so the platform can show whether the runtime is online. It fetches the current tunnel settings from the platform on every start. levain-runtime status prints the configuration and the sessions on this runtime.

Upgrade

A platform release can need a newer runtime: the node and turn entrypoints under /sandbox ship with this package, and runs wait while the runtime is too old for them. The Runtimes page in the Levain app, and runner_version in GET /api/v1/runtimes, show the version each runtime runs; levain-runtime --version prints it here.

While up runs, the platform's heartbeat reply names the version it needs. levain-runtime status prints it (required: 0.1.15 (upgrade needed)), and GET http://127.0.0.1:17777/v1/health carries version, required_version and upgrade_needed, so whatever keeps the runtime running can upgrade it before any run waits.

uv tool upgrade levain-runtime
systemctl --user restart levain-runtime  # or however `up` runs on this host

up rewrites /sandbox from the installed release on every start, so an upgrade needs no new init. Restarting ends the nodes the runtime was running, so upgrade between runs.

How it works

Each agent session gets a workspace directory under the runtime home (sessions/<id>/workspace, or agents/<id>/workspace for agents with a persistent workspace). The platform delivers the recipe and SDK into /recipes and /sdk, then runs each node as a short-lived process with the session's environment. Everything a node prints is streamed back and lands in the run's logs on the platform.

Direct mode serves as many sessions at once as the machine can isolate, or up to --sessions N: each node runs under bubblewrap with its session's folders mounted at /workspace, /recipes/active and /sdk/active; the real workspace path is in LEVAIN_HOST_WORKSPACE for tools outside the sandbox such as Docker. Without bubblewrap it serves one session at a time, with /workspace linked to the active session. Docker mode starts one container per session and has no such limit.

Sessions and your Claude login

In direct mode an agent's turns run in the session's workspace directory with this machine's Claude login and config dir (CLAUDE_CONFIG_DIR, or ~/.claude). Claude Code files the agent's sessions where it files yours, under that directory's entry, so from the workspace directory claude --resume lists the agent's sessions next to your own and continues any of them. levain-runtime status prints each session's workspace and the Claude session it continues.

The map from a Levain session to its Claude session lives in <config dir>/levain-sessions/. To have an agent continue a session you started yourself in its workspace directory:

levain-runtime adopt <levain session id> <claude session id>

The agent's next turn resumes that session. Docker mode copies your login into each container instead; its sessions stay in the container.

Per-turn environment

In direct mode the runtime reads env.json in its home before every node it runs, so you can change a node's environment between turns without a restart. For example, you can point one agent at another Claude login:

{
  "all": { "HTTP_PROXY": "http://127.0.0.1:3128" },
  "agents": {
    "<agent id>": { "CLAUDE_CONFIG_DIR": "/home/me/.claude-second" }
  }
}

An agent's entry wins over all, and both win over anything the platform sends for the session or the turn. The session map follows the CLAUDE_CONFIG_DIR a turn gets, as do status and adopt. To switch the value a turn starts with, write the new file next to it and rename it into place.

The file must belong to the user the runtime runs as, and no one else may be able to write it (chmod 600). If it is not, or it is malformed, nodes fail with an error that names the file, never its values. The values stay on this machine: they are not logged and not sent to the platform. Without the file, nodes get the runtime's own environment. Docker mode ignores the file.

Waiting sessions

In direct mode, when an agent's turn stops to wait, the platform gives the session's slot back and tells the runtime what the session waits on. The runtime keeps one file per waiting session, waiting/<session id>.json under its home, so a process on this machine can react without polling the API:

{
  "session_id": "…",
  "agent_id": "…",
  "workspace_id": "…",
  "run_id": "…",
  "reason": "user_input",
  "payload": { "question": "…" },
  "since": "2026-10-29T08:12:44.018311+00:00"
}

reason is user_input (a person's reply), child_agent (another agent's run) or external (an outside event); payload is what the agent passed with the wait. Each file is renamed into place, so a watcher of *.json only sees whole files. It is removed when the session resumes, is provisioned again or is deleted; a restart of the runtime keeps it.

Metadata

Release files for levain-runtime 0.1.30

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

Source distribution (sdist)

Source distribution for levain-runtime 0.1.30
File Size Uploaded Provenance Actions
levain_runtime-0.1.30.tar.gz 44.4 kB With provenance Details for levain_runtime-0.1.30.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for levain-runtime 0.1.30
File Interpreter ABI Platform Actions
levain_runtime-0.1.30-py3-none-any.whl Python 3 none any Details for levain_runtime-0.1.30-py3-none-any.whl

Total release size: 95.4 kB

Release files / levain_runtime-0.1.30.tar.gz

Download URL levain_runtime-0.1.30.tar.gz
Size 44.4 kB
Tags Source
SHA-256 checksum
How to use checksums
d845b0cece5fa1350b2bd59bc25d9ebc6515c4c537dcc17ac933fb6c3798c958
BLAKE2b-256 checksum
How to use checksums
4f958be60312966a553649a7ca32b573d8d744d678e28894eeb21486e3149709
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Release files / levain_runtime-0.1.30-py3-none-any.whl

Download URL levain_runtime-0.1.30-py3-none-any.whl
Size 51.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0014bba5dcf054087fe742c489b35dae0ea50a8c7236aca7ba08b86266998872
BLAKE2b-256 checksum
How to use checksums
819b40307d8311c600a876216a5bcf468a72ff889e23c05c08d16e385795b14e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Security for levain-runtime 0.1.30

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for levain_runtime-0.1.30.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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