Metadata-Version: 2.4
Name: withruntime
Version: 0.44.1
Summary: Runtime Cloud: one client (sync and async) for every Runtime product. Sandboxes first.
License: Apache-2.0
Project-URL: Homepage, https://withruntime.com
Project-URL: Documentation, https://withruntime.com/docs/python
Project-URL: Source, https://github.com/withruntime/runtime/tree/main/sdks/python
Project-URL: Issues, https://github.com/withruntime/runtime/issues
Keywords: sandbox,ai-agents,agents,microvm,firecracker,code-execution,code-interpreter,mcp,llm
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: tomli>=1.1.0; python_version < "3.11"
Provides-Extra: e2b
Requires-Dist: httpx<1.0.0,>=0.27.0; extra == "e2b"
Provides-Extra: openai-agents
Requires-Dist: openai-agents>=0.22.3; extra == "openai-agents"
Provides-Extra: deepagents
Requires-Dist: deepagents>=0.7; extra == "deepagents"
Provides-Extra: harbor
Requires-Dist: harbor>=0.23.0; extra == "harbor"
Provides-Extra: inspect-ai
Requires-Dist: inspect-ai>=0.3.268; extra == "inspect-ai"
Dynamic: license-file

# Runtime Cloud Python SDK

One client for every Runtime Cloud product, sync and async. It needs Python 3.9
or later (the `python3` that a Mac comes with). It uses only the standard
library.

```bash no-run
pip install withruntime
```

The client uses `RUNTIME_API_KEY` if it is set. If not, it uses the connection
that this machine saved when you ran `npx withruntime login`. That takes one
approval in the browser. You do not copy a key. On a server or a CI runner, set
`RUNTIME_API_KEY` from your secret manager. To get a new key, run
`npx withruntime keys create`. It prints the key once, after an owner, admin or
developer of the account approves it in the browser. You can also create a key
at https://withruntime.com/account/keys. Never put a key in source code, a URL
or a command-line argument.

```python
from withruntime import Sandbox

with Sandbox.create() as sbx:
    sbx.files.write("/workspace/invoice.py", "print(sum([125, 250, 375]))\n")
    result = sbx.exec("python3 /workspace/invoice.py")
    print(result.exit_code, result.stdout)
```

`Sandbox.create()` takes no arguments. It returns when the sandbox is running.
Leaving the `with` block deletes the sandbox. Set `keep=True` to stop it
instead. Its disk stays.

With no arguments, you get the free usage. No card is needed. You can run up to
four sandboxes at once without credit. The current default image
includes NumPy, pandas and matplotlib. See the
[sandbox environment](https://withruntime.com/docs/sandbox-environment). The
free usage is spent first, then prepaid credit. You do not choose. `funding` is
accepted and ignored.

`AsyncRuntime` is the same client for asyncio, with the same methods:

```python
import asyncio
from withruntime import AsyncRuntime


async def main():
    async with AsyncRuntime() as runtime:
        async with await runtime.sandboxes.create() as sbx:
            print((await sbx.exec("uname -a")).stdout)


asyncio.run(main())
```

A sandbox has these methods and products:

- Methods: `exec`, `exec_stream`, `spawn`, `terminal`, and `forward_port` (which
  maps a TCP port in the sandbox to a local port).
- `files`: read, write, list, glob, stat, rename and remove. Upload and download
  directories.
- Lifecycle: `pause`, `wake`, `extend`, `update` (its name, environment and
  settings), `keep_alive`, `fork`, `snapshot`, `switch_image` (moves it to a new
  image and keeps /workspace), and `delete` (removes it for good).
- Products: `interpreter`, `network`, `previews`, `desktop`, `mounts` (your S3,
  R2 or Google Cloud Storage bucket as a folder), `tailscale` (a paid sandbox on
  your own tailnet), `metrics`, and `mcp` (servers from the MCP catalog, run in
  the sandbox).

A paused sandbox also wakes by itself on the next call. `Sandbox.get_or_create(name)`
returns the sandbox with that name, or creates it.

A sandbox pauses itself after 300 seconds with nothing happening in it. It
keeps its memory and processes, so an idle sandbox uses no compute.
`idle_pause_seconds` sets the idle time from 60 to
86,400. A shorter time is raised to 60. Set it to 0
to never pause.

Each product has one plural name, as in the CLI: `runtime.sandboxes`,
`snapshots`, `images`, `volumes`, `jobs`, `domains`, `ports`, `ips` and
`networks`. The old singular names (`runtime.sandbox`, `address`, `tunnel` and
the rest) still work for now. The [guide](https://withruntime.com/docs/python)
lists them.

The client has `sandboxes`, `images`, `volumes`, `snapshots`, `jobs`, `secrets`,
`limits`, `feedback` and `support`. It has `webhooks`, `events`, `otel` and
`audit` to watch the account. It has `domains`, `ports`, `ips` and `networks`
(with `networks.wireguard`) to connect sandboxes to your own systems (paid
accounts). It has `mcp`, `sso`, `billing`, `referrals` and `switching`.

`runtime.limits.get()` (0.3.1 and later) says whether the key is read-only, and
what its agent may still spend today. Every write carries an idempotency key, so
a retry never runs a write twice. Errors are typed. They carry `code`, `hint` and
`request_id`.

`RuntimeAPIError` and `RuntimeConnectionError` are the SDK's error names. They do
not shadow Python's built-in errors. The older `RuntimeError` and
`ConnectionError` exports are still aliases.

`runtime.usage_requests("7d")` reads the account's API call counts and error
rates. Counts are exact decimal strings. An empty window has `errorPercent: None`.

`runtime.usage_export(since, until, cursor=...)` reads one page of settled usage
over a UTC range, with its server CSV. `finalThrough` is the time before which
no more charges will settle. Each row's `final` is True once its resource is
deleted. After that, it cannot be charged anything more.

## Behind a proxy

The client reads `HTTPS_PROXY`, `HTTP_PROXY` and `NO_PROXY`, for sync and async
calls. The names work in upper or lower case. If both cases are set, lower case
wins.

Calls to the API and terminal WebSockets go through `HTTPS_PROXY` as a CONNECT
tunnel. Any `user:password@` in the proxy address is sent to the proxy.
`HTTP_PROXY` is used only for `http://` addresses. It is never used for the
HTTPS API.

`NO_PROXY` lists hosts to reach directly. Split them with commas or spaces. A
name covers its subdomains. A leading dot is allowed. `host:port` limits the
rule to one port. `*` means every host.

A proxy address without a scheme is treated as `http://`. Only `http://` proxies
are supported. Any other scheme fails at once with `invalid_proxy`.

When a call cannot get through, the error names the proxy it tried. It leaves
out the password. For example: `No answer from Runtime at https://api.withruntime.com through the
proxy http://proxy.internal:3128 (HTTPS_PROXY).`

## Code written for E2B

`withruntime.e2b` translates supported E2B Python sandbox calls. Change the
import and set `RUNTIME_API_KEY`:

```python no-run
from withruntime.e2b import Sandbox, AsyncSandbox  # was: from e2b import ...
from withruntime.e2b.code_interpreter import Sandbox  # was: from e2b_code_interpreter import Sandbox
```

Sandboxes get E2B's defaults: 2 vCPU and 512 MiB. There is no time limit unless
you pass `timeout`. A sandbox runs while it works, and pauses itself when it is
idle. Timeouts are in seconds, as in E2B's Python SDK. `runtime_create={...}`
passes Runtime's own create fields, for example `{"idle_pause_seconds": 0}`.

A call that Runtime does not handle the way E2B does raises
`NotSupportedException` before anything happens. The error names what to use
instead. Importing `withruntime` alone does not load it. The sync `Sandbox` is
generated from the async one by `scripts/generate_e2b_sync.py`.

## Code written for Daytona or Vercel Sandbox

`withruntime.daytona` and `withruntime.vercel` do the same for Daytona's Python
SDK and Vercel Sandbox's. Change the import:

```python no-run
from withruntime.daytona import Daytona, AsyncDaytona  # was: from daytona import ...
from withruntime.vercel import sandbox  # was: from vercel import sandbox
from withruntime.vercel.sandbox import sync as sandbox  # was: from vercel.sandbox import sync as sandbox
```

Sandboxes get the rival's defaults. For Daytona, that is 1 vCPU, 1 GiB and a
3 GiB disk. It pauses after 15 idle minutes. For Vercel, that is 2 vCPUs with
2048 MiB each. Vercel sandboxes are persistent, with no time limit unless you
pass one. `runtime_create={...}` passes Runtime's own create fields.

A Daytona or Vercel key is never sent anywhere. A call that Runtime does not
handle the same way raises `NotSupportedError` before anything happens. The
error names what to use instead. The sync modules are generated from the async
ones by `scripts/generate_dropin_sync.py`. `DAYTONA.md` and `VERCEL.md` in the
JavaScript package list every mapping and gap.

## Code written for Blaxel

`withruntime.blaxel` translates supported Blaxel Python sandbox calls (`blaxel`
0.4.11) on Runtime. Change the import and set `RUNTIME_API_KEY`. Or run
`npx withruntime login` once:

```python no-run
from withruntime.blaxel import SandboxInstance  # was: from blaxel.core import SandboxInstance
from withruntime.blaxel import SyncSandboxInstance  # was: from blaxel.core import SyncSandboxInstance
```

`withruntime.blaxel.core` holds the same names. So replacing `blaxel.` with
`withruntime.blaxel.` also works. A Runtime key in `BL_API_KEY` is used. A
Blaxel key is never sent anywhere.

How it maps:

- **Sandboxes.** `create`, `create_if_not_exists` (one sandbox when two calls
  race), `get`, `get_by_external_id`, `list`, `delete`, `fork`, `snapshots` and
  the `update_*` calls work. `memory` is kept, with one vCPU for every 2048 MB.
  Blaxel's general templates run on Runtime's image: `blaxel/base-image`,
  `py-app`, `ts-app`, `node`, `jupyter-server` and `docker-in-sandbox`. Any other
  image `ns/name:tag` starts from the ready Runtime image `ns-name:tag`. Every
  `/` becomes `-`. The tag is `latest` when none is given. So the code keeps
  Blaxel's image string. A missing image raises `NotSupportedError` with the
  build command. For example: `npx withruntime images build
--dockerfile Dockerfile --name my-company-agent-image -t
my-company-agent-image:latest`. Volumes mount Runtime volumes of the same
  name. Without credit, a sandbox has at most 4096 MB of memory (2 vCPUs).
- **Standby.** A sandbox pauses after a minute with no call. Blaxel's standby
  time is about 15 seconds. A paused sandbox keeps its memory and processes. It
  wakes on the next command, file call or preview visit. `archive` pauses it and
  keeps its memory too. A sandbox has no time limit, so a long command is never
  paused by a clock. `keep_alive` raises the idle pause to the process's time
  limit. For a process with no time limit, it turns the idle pause off. The
  first call from any client that finds no `keep_alive` process running brings
  back the old idle pause.
- **How long it is kept.** A paused sandbox with no `ttl` or `lifecycle` is kept
  365 days. Blaxel keeps it until you delete it. A limit is rounded up to whole
  days of pause. A limit of an hour or less, counted from creation, also ends the
  sandbox at that time. Without credit, a paused sandbox is kept seven days. That
  is the most Blaxel's first tier keeps.
- **Envs** reach every process, from any client. They are kept on the sandbox. A
  process's own `env` wins.
- **Paths.** `/blaxel` is Blaxel's working directory and `HOME`. On Runtime it is
  `/workspace`. Relative paths and `~` start there.
- **Processes.** You can find a process by name from any client, as long as
  Runtime still has its record. Runtime keeps the running processes and the last
  16 that ended.
- **Previews** are Runtime previews of each port. A private preview's
  `tokens.create(expires_at)` gives a token. The token works as Blaxel's
  `X-Blaxel-Preview-Token` header or `bl_preview_token` address parameter.
  `fetch(port)` uses a private preview for you.
- **Code interpreter.** `CodeInterpreter.run_code` and `create_code_context` run
  on Runtime's interpreter. They return Blaxel's result classes.
- **Errors.** Errors keep Blaxel's classes: `SandboxAPIError`, `ResponseError`
  and `SnapshotAPIError`. Each one also carries Runtime's `code`, `hint` and
  `request_id`.
- **Runtime fields.** `runtime_create={...}` passes Runtime's own create fields,
  for example `{"idle_pause_seconds": 0}`. `sandbox.withruntime` is the Runtime
  sandbox underneath.

Differences you can hit:

- Commands run as root, as on Blaxel, with the sandbox's `PATH` and `HOME`
  (`/workspace`). File calls act as the sandbox user. They fall back to `sudo`
  where only root may act. So they reach files that a root process made,
  including private ones. A file they write belongs to the sandbox user.
- A key sees the sandboxes it made. Another key's calls get 404. The exception is
  when an owner or admin makes the key account-wide, as a Blaxel workspace key is
  ([teams](https://withruntime.com/docs/teams#keys-in-a-team)).
- Public previews need a paid sandbox.
- A process's `pid` is Runtime's process id. It is not an operating-system number.
- `sandbox.sessions` makes a Runtime sandbox session. `SandboxInstance.from_session`
  drives the sandbox with its token. That gives commands, files and previews of
  that one sandbox. A session lasts a day at most. `Access-Control-Allow-Origin`
  in `response_headers` names the page that may use it.

These raise `NotSupportedError` before anything happens. The error names what to
use instead: regions outside the US, read-only and ephemeral volumes, drives,
`extra_args` other than `iptables`, egress and subnet settings, preview headers,
custom domains and preview expiry, restoring a snapshot in place (fork from it
instead), codegen, `system`, schedules, and Blaxel's agents, models, tools, jobs
and applications. The sync module is generated from the async one by
`scripts/generate_dropin_sync.py`.

## Code written for Modal Sandboxes

`withruntime.modal` runs code written for Modal's Sandboxes (`modal` 1.6.2),
sync and `.aio`. Change the import and set `RUNTIME_API_KEY`:

```python no-run
from withruntime import modal  # was: import modal
```

Modal's own sandbox examples run unchanged if they use none of the features
refused below. A Modal token is never needed or sent. Commands run as root, as
in a Modal container. A `timeout` ends the sandbox. An `idle_timeout` pauses it
and keeps its memory. The next call wakes it.

Images build from Modal's recipes. `publish(name)` makes a Runtime image name
that `Image.from_name` finds. Memory snapshots (`_experimental_enable_snapshot`)
keep the running entrypoint.

These raise `CompatibilityError` before anything is created. The error names
what to use instead: GPUs; Modal Functions and Dicts; named secrets; volumes
made on first use; sidecars; connect tokens; and directory snapshots. `COMPATIBILITY.md`
lists every mapping.

## Agent frameworks

`withruntime.openai_agents` is a sandbox client for the OpenAI Agents SDK's
`SandboxAgent`. Install it with `pip install "withruntime[openai-agents]"`.
`withruntime.deepagents` is a Deep Agents sandbox backend. `withruntime.tools`
gives LangChain, CrewAI, LlamaIndex, Pydantic AI, Google ADK and any framework
that takes typed functions four sandbox tools. See
https://withruntime.com/docs/frameworks.

## How Runtime compares

For typical agent work, Runtime costs 42% to 88% less than fourteen
other sandbox providers at their published rates. These pages show the
arithmetic. Each one lists the rates it used and the date they were read:

- [Best sandbox for AI agents](https://withruntime.com/compare/best-sandbox-for-ai-agents)
- Alternatives to [E2B](https://withruntime.com/compare/e2b-alternatives),
  [Daytona](https://withruntime.com/compare/daytona-alternatives),
  [Modal](https://withruntime.com/compare/modal-alternatives) and
  [Vercel Sandbox](https://withruntime.com/compare/vercel-sandbox-alternatives)
- [E2B vs Daytona](https://withruntime.com/compare/e2b-vs-daytona), and
  [every comparison](https://withruntime.com/compare)
- [The agent sandbox price index](https://withruntime.com/pricing/agent-sandbox-price-index):
  every provider's rates, also as CSV and JSON
- [Sandbox cost calculator](https://withruntime.com/calculators/sandbox-cost-calculator)
  and [Runtime's pricing](https://withruntime.com/pricing)

## Reliability and support

- **Status:** https://withruntime.com/status checks the API from outside every
  two minutes. It starts a real sandbox every ten minutes. It keeps every day's
  record. The same status is also at https://withruntime.com/status.md and
  https://withruntime.com/status.json.
- **Uptime Promise:** we promise paid accounts 99% API uptime
  each calendar month. If a month falls below that, 10% of that
  month's charges is paid back as credit. This is automatic
  (https://withruntime.com/legal/sla).
- **Security and compliance:** https://withruntime.com/docs/trust.
- **What changed:** https://withruntime.com/changelog.
- **Help:** `npx withruntime support "<question>"`, or
  `npx withruntime feedback "<text>"` for anything that got in your way.

Docs: https://withruntime.com/docs/python.

The package was called `withruntime-cloud`, imported as `runtime_cloud`, until
0.3.0. That name stopped at 0.5.1. It gets no new releases. Use `withruntime`.
