Metadata-Version: 2.5
Name: langchain-prized
Version: 0.1.1
Summary: Prized Sandboxes (Firecracker microVMs) as a sandbox backend for LangChain Deep Agents
Project-URL: Homepage, https://prized.dev/sandboxes
Project-URL: Documentation, https://prized.dev/docs/sandboxes-langchain
Project-URL: API reference, https://prized.dev/docs/sandboxes-api
Author-email: Prized <team@prized.dev>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: agents,code-execution,dcode,deep-agents,deepagents,firecracker,langchain,microvm,prized,sandbox
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: <4.0,>=3.11
Requires-Dist: deepagents<0.8.0,>=0.7.0
Requires-Dist: httpx<1.0.0,>=0.27.0
Description-Content-Type: text/markdown

# langchain-prized

[![PyPI](https://img.shields.io/pypi/v/langchain-prized)](https://pypi.org/project/langchain-prized/) [![Python](https://img.shields.io/pypi/pyversions/langchain-prized)](https://pypi.org/project/langchain-prized/) [![License](https://img.shields.io/pypi/l/langchain-prized)](https://pypi.org/project/langchain-prized/)

[Prized Sandboxes](https://prized.dev/docs/sandboxes) as a sandbox backend for [LangChain Deep Agents](https://docs.langchain.com/oss/python/deepagents/overview). Each sandbox is its own Firecracker microVM: it boots from a template, runs your agent's commands and file edits away from your machine, and can fork into live copies.

## Install

```bash
pip install langchain-prized
```

Python 3.11 or later, with `deepagents` 0.7.

## Quickstart

For a Prized API key, [Open Sandboxes](https://prized.dev/onboarding/sandboxes) and choose **Create API key** (new to Prized, it signs you up with free credit, no card), or make one on the [API keys page](https://prized.dev/dashboard/workspace/api-keys) (Full access, or Custom with **Sandboxes: Write**). Export it with your model provider's key:

```bash
export PRIZED_API_KEY=dcp_...
export ANTHROPIC_API_KEY=sk-ant-...
```

```python
from deepagents import create_deep_agent
from langchain_prized import PrizedSandbox

task = "Write fizzbuzz.py, run it, and show me the output."
with PrizedSandbox() as sandbox:  # creates a sandbox, and deletes it on exit
    agent = create_deep_agent(model="anthropic:claude-sonnet-5-5", backend=sandbox)
    result = agent.invoke({"messages": [{"role": "user", "content": task}]})
    print(result["messages"][-1].text)
```

The agent's `execute`, `read_file`, `write_file`, `edit_file`, `ls`, `glob`, and `grep` tools all run in the sandbox.

## Use it directly

```python
from langchain_prized import PrizedSandbox

sandbox = PrizedSandbox(template="prized-agent-v1", labels={"run": "pr-1874"})
try:
    sandbox.upload_files([("/home/prized/work/app.py", b"print('hi')\n")])
    result = sandbox.execute("python3 app.py | tee out.txt", timeout=600)
    print(result.exit_code, result.output)
    print(sandbox.download_files(["/home/prized/work/out.txt"])[0].content)

    # Fork: live copies with this sandbox's memory, disk, and running processes.
    children = sandbox.fork(3)
    try:
        for child in children:
            print(child.id, child.execute("ls").output)
    finally:
        for child in children:
            child.close()  # deletes the child
finally:
    sandbox.close()  # deletes the sandbox
```

The sandbox is created on first use (or by `start()`), and `close()` deletes it. If a create's answer is lost, the next `start()` gets the sandbox it made instead of making a second, and `close()` deletes it. To use one that already exists, pass `sandbox_id="sbx_..."`; it is left running on close unless you pass `delete_on_close=True`. `pause()` keeps memory and disk and stops compute billing; the next command or file transfer wakes it.

## Options

| Argument | Default | Meaning |
| --- | --- | --- |
| `template` | `prized-base-v1` | `prized-base-v1` (Ubuntu 24.04, Python 3, Node.js 22, build tools) or `prized-agent-v1` (adds Claude Code and Codex) |
| `api_key` | `PRIZED_API_KEY` | API key (`dcp_...`) |
| `api_url` | `PRIZED_API_URL`, else `https://api.prized.dev` | API origin |
| `vcpu`, `memory_mb`, `disk_gb` | The template's (4 vCPU, 8 GB, 10 GB) | Shape of a new sandbox, up to 32 vCPU, 128 GB of memory, and 128 GB of disk |
| `env_vars` | None | Variables for every command, stored encrypted |
| `labels` | None | Labels to filter on in the dashboard and API |
| `auto_pause_min`, `auto_delete_min`, `max_runtime_min` | Off, off, 1,440 (24 hours; 60 on the free tier) | Timers: pause when idle, delete when paused, delete after this many minutes of running (up to 10,080, 7 days) |
| `timeout` | 1800 | Default command timeout in seconds; at most 3600 |
| `cwd`, `env` | `/home/prized/work`, none | Defaults for every command |
| `sandbox_id` | None | Use an existing sandbox instead of creating one |
| `delete_on_close` | `True` if created here | Whether `close()` deletes the sandbox |
| `auto_resume` | `True` | A command or transfer wakes a paused sandbox. With `False` it stays paused: attaching raises `PrizedError` until `resume()`, and a command raises `sandbox_not_running` |
| `python_alias` | `True` | Put `python` (pointing at `python3`) on every command's PATH |
| `startup_timeout` | 180 | Seconds to wait for a create, resume, or pause to finish |
| `http_client` | None | An `httpx.Client` to send requests with (proxies); never closed by the backend |

`execute()` also takes `timeout`, `cwd`, and `env` per call. Its output is stdout, then stderr inside `<stderr>` tags; a timed-out command returns exit code 124.

## Inside a sandbox

- **User.** Commands run under `bash -c` as `prized`, without sudo, in `/home/prized/work` by default.
- **Files.** Any absolute path: files under `/home/prized` go through the files API, and others (such as `/tmp`) are staged under `/home/prized/.cache/langchain-prized` and put in place. Each file is written whole or not at all, so a write that fails (a full disk) leaves the old file, and a file it replaces keeps its mode, so a script you made executable stays executable. A symlink is written through: the file it points to changes and the link stays. Up to 100 MiB per file.
- **Output.** Each stream keeps its first 4 MiB; `truncated` is set past that.
- **Lost answers.** A command whose answer is lost is never sent again, and its `PrizedAPIError` says which of three it was: it never reached the sandbox, it may or may not have run, or it ran but the answer could not be read. A file goes up under a temporary name, sent again if need be (no copy after 11 minutes, so one that timed out is not sent again), and one step that is never sent again puts it in place; a file's `error` says the same of that step. A download is not sent again after 11 minutes either.
- **Run time.** 24 hours of running by default, up to 7 days with `max_runtime_min`. On a paid workspace the clock stops while a sandbox is paused and starts again on every resume. A running sandbox you forget is deleted when its run time ends; a paused one is kept until you delete it (on the free tier, 30 days after its last use).

## Free tier

A new workspace gets free credit, and on the free credit alone sandboxes run within these limits ([Free tier](https://prized.dev/docs/sandboxes#free-tier)):

| Free tier | Limit |
| --- | --- |
| Sandboxes at once | 10; paused ones count toward the disk instead |
| Per sandbox | 2 vCPU and 4 GB of memory (a template's larger default is capped to this) |
| Across the workspace | 20 vCPU and 40 GB running, 100 GB of disk |
| Run time | 60 minutes of running in all; a larger `max_runtime_min` is refused. A paused sandbox is kept 30 days after its last use |

Past a limit the API answers `sandbox_quota_exceeded` or `invalid_resources`, raised as `PrizedAPIError` with `code`, `status`, and the answer's `body`. A plan or a top-up lifts the workspace to the full quotas.

## Deep Agents Code

With this package installed next to `deepagents-code`, `dcode --sandbox prized` runs the session in a new Prized sandbox; `--sandbox-id sbx_...` attaches to an existing one and leaves it running.

```bash
dcode install langchain-prized --package
```

The provider reads these variables; a `DEEPAGENTS_CODE_` prefixed name wins over the plain one, as for dcode's own providers. The sandbox ones shape a new sandbox only.

| Variable | Default | Meaning |
| --- | --- | --- |
| `PRIZED_API_KEY` | None | API key (`dcp_...`), required |
| `PRIZED_API_URL` | `https://api.prized.dev` | API origin |
| `PRIZED_SANDBOX_TEMPLATE` | `prized-base-v1` | `prized-agent-v1` adds Claude Code and Codex |
| `PRIZED_SANDBOX_VCPU`, `PRIZED_SANDBOX_MEMORY_MB` | The template's | vCPUs, and memory in MiB |
| `PRIZED_SANDBOX_LABELS` | None | Labels, as `key=value,key=value` (a value may hold `=`, not `,`) |
| `PRIZED_SANDBOX_AUTO_PAUSE_MIN` | 15 | Pause after this many idle minutes; `0` is off. The session's next command wakes it |

```bash
PRIZED_SANDBOX_VCPU=2 PRIZED_SANDBOX_MEMORY_MB=4096 PRIZED_SANDBOX_LABELS=team=evals,session=s1 dcode --sandbox prized
```

To keep these settings in dcode's own config instead, declare the provider in `~/.deepagents/config.toml`. Its `params` (`template`, `vcpu`, `memory_mb`, `auto_pause_min`) win over the variables, and its `labels` are added to `PRIZED_SANDBOX_LABELS` (on a shared key, the config's wins). Keep `working_dir` as shown, since dcode tells the agent to work there.

```toml
[sandboxes.providers.prized]
class_path = "langchain_prized.provider:PrizedSandboxProvider"
working_dir = "/home/prized/work"
params = { template = "prized-agent-v1", vcpu = 2, memory_mb = 4096, auto_pause_min = 30, labels = { team = "evals" } }
```

As of `deepagents-code` 0.1.88, dcode does not delete the sandbox when the session ends. So a sandbox made for dcode pauses after 15 idle minutes by default: it keeps its memory and files and bills storage, not compute, and in a session still open the next command wakes it. A paused sandbox is kept until you delete it (on the free tier, 30 days after its last use), and its disk counts toward your workspace's disk quota; with `PRIZED_SANDBOX_AUTO_PAUSE_MIN=0` it runs instead, billing compute, until its run time ends (24 hours by default; 60 minutes on the free tier). Give each session its own label in `PRIZED_SANDBOX_LABELS`, as `session=s1` above, and delete its sandbox when you are done: `prized sandbox rm --label session=s1`, or `DELETE /api/v1/sandboxes?label=session=s1`. A label in `config.toml` is the same for every session, so deleting by it reaches the sandboxes of sessions still open.

## Development

```bash
uv sync
uv run pytest tests/unit_tests    # offline, against a fake of the API
PRIZED_LIVE_TESTS=1 PRIZED_API_KEY=dcp_... uv run pytest tests/integration_tests    # live
PRIZED_API_KEY=dcp_... uv run python scripts/live_smoke.py    # live, a Deep Agent end to end, timed
uv run ruff check . && uv run ty check langchain_prized
uv run --group release python tests/package_check.py    # the wheel and sdist as PyPI gets them
```

The unit tests include LangChain's standard sandbox suite, run against the fake; the integration tests run it against the live API. Reference: [Sandbox API](https://prized.dev/docs/sandboxes-api).

## License

Apache-2.0. The full text is in the `LICENSE` file that ships with the package.
