Skip to main content

Docker sandbox backend for LangChain DeepAgents Harness.

Project description

langchain-dockersandbox

langchain-dockersandbox implements Deep Agents BaseSandbox contract:

  • id
  • execute()
  • upload_files()
  • download_files()

Install

pip install langchain-dockersandbox

or

uv add langchain-dockersandbox

Requirements:

  • Docker daemon running
  • Docker CLI available on PATH (needed for fallback paths)
  • gVisor installed and configured as runtime for docker. check Security Model Section
  • Envars: DOCKERSANDBOX_TEST_IMAGE

Quick Start

from deepagents import create_deep_agent
from langchain_anthropic import ChatAnthropic
from langchain_dockersandbox import DockerSandbox

sandbox = DockerSandbox(image="python:3.11-slim", verbose=True)
sandbox.open()
try:
    agent = create_deep_agent(
        model=ChatAnthropic(model="claude-sonnet-4-20250514"),
        system_prompt="Use sandbox for shell and files.",
        backend=sandbox,
    )
    result = agent.invoke(
        {"messages": [{"role": "user", "content": "Create main.py and run it"}]}
    )
finally:
    sandbox.close()

Attach Existing Container (No Context Manager)

from langchain_dockersandbox import DockerSandbox

sandbox = DockerSandbox.from_container("assistant-workspace")  # or container ID
sandbox.open()
try:
    out = sandbox.execute("python --version")
    print(out.output.strip())
finally:
    sandbox.close()

Thread-scoped sandboxes

Create one Docker container per conversation/thread. This is the safest default because each thread gets a clean filesystem and process space.

from deepagents import create_deep_agent
from langchain_dockersandbox import DockerSandbox

thread_id = "thread-123"

with DockerSandbox(image="python:3.11-slim") as sandbox:
    agent = create_deep_agent(
        model=model,
        backend=sandbox,
        system_prompt="Use the sandbox for shell commands and generated files.",
    )
    agent.invoke(
        {"messages": [{"role": "user", "content": "Create a package and run pytest"}]},
        config={"configurable": {"thread_id": thread_id}},
    )


## Resuing Containers

Reuse a container across many threads for a given assistant. This is useful when a coding assistant should keep a cloned repository, installed dependencies, or generated files.

```python
from langchain_dockersandbox import DockerSandbox

sandbox = DockerSandbox.from_container("assistant-workspace") # or container ID
sandbox.open()
try:
    result = sandbox.execute("git status --short")
finally:
    sandbox.close()  # Detaches; it does not stop an existing container.

Direct Backend Usage

You can call the backend directly from application code:

from langchain_dockersandbox import DockerSandbox

with DockerSandbox(image="python:3.11-slim") as sandbox:
    result = sandbox.execute("python - <<'PY'\nprint('hello from docker')\nPY")
    print(result.output)
    print(result.exit_code)

File Transfer APIs

Deep Agents filesystem tools operate through execute(). Your application should use upload_files() and download_files() to move files across the host/container boundary.

from langchain_dockersandbox import DockerSandbox

with DockerSandbox(image="python:3.11-slim") as sandbox:
    sandbox.upload_files([
        ("/tmp/lc-sandbox/app.py", b"print('uploaded')\n"),
        ("/tmp/lc-sandbox/data.txt", b"hello\n"),
    ])

    sandbox.execute("python /tmp/lc-sandbox/app.py > /tmp/lc-sandbox/output.txt")

    results = sandbox.download_files(["/tmp/lc-sandbox/output.txt"])
    for result in results:
        if result.content is not None:
            print(result.content.decode())
        else:
            print(result.error)

Security Model

For production isolation, configure Docker to use gVisor at the daemon level after installing runsc. With Docker default-runtime set to runsc, every container created by this library runs through gVisor without any library-managed isolation layer.

{
  "default-runtime": "runsc",
  "runtimes": {
    "runsc": {
      "path": "/usr/bin/runsc",
      "runtimeArgs": [
        "--platform=systrap",
        "--overlay2=root:self",
        "--directfs=true",
        "--dcache=5000",
        "--network=sandbox",
        "--log-packets=false",
        "--rootless=false"
      ]
    }
  },
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Restart Docker after changing daemon.json

Quick verify (before/after gVisor):

# Before enabling gVisor default runtime
docker run --rm python:3.11-slim id
6.8.0-51-generic
# After enabling gVisor
docker run --rm --runtime=runsc python:3.11-slim id
4.4.0-gvisor

Deepagents Sandbox Integration

uv add langchain-tests
"""LangChain standard sandbox integration tests.

"""

from __future__ import annotations

import os
from typing import TYPE_CHECKING

import pytest
from langchain_tests.integration_tests import SandboxIntegrationTests

from langchain_dockersandbox import DockerSandbox

if TYPE_CHECKING:
    from collections.abc import Iterator

    from deepagents.backends.protocol import SandboxBackendProtocol

TEST_IMAGE = "python:3.11-slim"



class TestDockerSandboxStandard(SandboxIntegrationTests):
    """Standard LangChain sandbox integration tests for DockerSandbox."""

    @pytest.fixture(scope="class")
    def sandbox(self) -> Iterator[SandboxBackendProtocol]:
        backend = DockerSandbox(
            image=TEST_IMAGE,
            verbose=False,
        )
        backend.open()
        try:
            yield backend
        finally:
            backend.close()
uv run --group test pytest tests/integration_tests/test_integration.py

Notes

  • Default image: python:3.11-slim
  • gVisor supported (gvisor=True or daemon default-runtime=runsc)
  • On some runsc hosts, Docker archive API fails -> package falls back to CLI copy/exec paths

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langchain_docker-0.1.0.tar.gz (140.0 kB view details)

Uploaded Source

File details

Details for the file langchain_docker-0.1.0.tar.gz.

File metadata

  • Download URL: langchain_docker-0.1.0.tar.gz
  • Upload date:
  • Size: 140.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for langchain_docker-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ad7beea8710003135e6b4f6aee91fd4065f0253a64d4b10d312ece7a7ae3d0a8
MD5 3c59c9739f528916b027aae78b60d9db
BLAKE2b-256 aaf9a5dcced6469add044acf8de66195c007e041e5fc191e277aedde0f2f4cee

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page