# docker-agent-sandbox A Docker-based sandbox and LangChain tool set for LLM agents that need a safe, isolated shell environment. ## What it provides - **`DockerSandbox`** — manages a single long-running Docker container: lifecycle (`start`/`stop`), file writes via the tar archive API, and command execution with timeout enforcement. Volumes, ports, environment variables, and capabilities are all caller-supplied. - **LangChain tools** — a ready-to-use set of tools that expose the sandbox to an agent: `bash`, `read_file`, `write_file`, `edit_file`, `list_dir`, `delete_file`, `move_file`, `copy_file`, `make_dir`, `search_files`, `grep`. ## Requirements - Python ≥ 3.11 - Docker daemon running locally - A Docker image to run (either pre-built or built via `build_image_if_missing`) ## Installation ```bash pip install docker-agent-sandbox ``` Or with uv, pointing at a local checkout: ```toml # pyproject.toml [tool.uv.sources] docker-agent-sandbox = { path = "../docker-agent-sandbox" } ``` ## Usage ### 1. Create and start a sandbox ```python from docker_agent_sandbox import DockerSandbox sandbox = DockerSandbox( container_name="my-agent-run", image="my-agent-image", dockerfile_dir="/path/to/dockerfile", # only needed if building the image volumes={"/host/sandbox": {"bind": "/workspace", "mode": "rw"}}, ports={"8080/tcp": None}, # Docker assigns a random host port environment={"MY_VAR": "value"}, working_dir="/workspace", cap_drop=["ALL"], cap_add=["SYS_PTRACE"], security_opt=["no-new-privileges"], ) sandbox.build_image_if_missing() sandbox.start() ``` ### 2. Inspect mapped ports ```python host_port = sandbox.get_host_port("8080/tcp") ``` ### 3. Run commands and write files ```python exit_code, output = sandbox.exec("ls -la") sandbox.write_file("/workspace/hello.py", "print('hello')") exit_code, output = sandbox.exec("python /workspace/hello.py") ``` ### 4. Bind tools to a LangChain agent ```python from docker_agent_sandbox import make_bash_tool, make_file_ops_tools tools = make_file_ops_tools(sandbox) + [make_bash_tool(sandbox)] # Pass `tools` to your LangChain / LangGraph agent as usual. ``` ### 5. Tear down ```python sandbox.stop() ``` ## API reference ### `DockerSandbox(container_name, image, dockerfile_dir, volumes, ports, environment, working_dir, network_mode, cap_drop, cap_add, security_opt)` | Parameter | Default | Description | |---|---|---| | `container_name` | — | Docker container name | | `image` | `"docker-agent-sandbox"` | Docker image tag to run | | `dockerfile_dir` | `None` | Directory containing the `Dockerfile`; required only if calling `build_image_if_missing` | | `volumes` | `{}` | Volume bindings passed directly to Docker (same format as `docker-py`) | | `ports` | `{}` | Port bindings passed directly to Docker, e.g. `{"8080/tcp": None}` for a random host port | | `environment` | `{}` | Environment variables injected into the container | | `working_dir` | `None` | Default working directory for `exec` calls (uses image `WORKDIR` if omitted) | | `network_mode` | `"bridge"` | Docker network mode | | `cap_drop` | `None` | Linux capabilities to drop | | `cap_add` | `None` | Linux capabilities to add | | `security_opt` | `None` | Docker security options | #### Methods | Method | Description | |---|---| | `build_image_if_missing()` | Builds the image from `dockerfile_dir` if not already present locally | | `start()` | Removes any existing container with the same name and starts a fresh one | | `stop()` | Removes the container | | `get_host_port(container_port)` | Returns the host port Docker mapped to `container_port` (e.g. `"8080/tcp"`) | | `exec(command, timeout=120)` | Runs a bash command; returns `(exit_code, stdout+stderr)` | | `write_file(path, content)` | Writes a UTF-8 file inside the container using the tar archive API | ### Tools | Factory | Tool name | Description | |---|---|---| | `make_bash_tool(sandbox)` | `bash` | Execute a shell command | | `make_file_ops_tools(sandbox)` | — | Returns all tools below as a list | | `make_read_file_tool(sandbox)` | `read_file` | Read a file with offset/length pagination | | `make_write_file_tool(sandbox)` | `write_file` | Write a file | | `make_edit_file_tool(sandbox)` | `edit_file` | `str_replace`-style editing | | `make_list_dir_tool(sandbox)` | `list_dir` | `ls -lA` a directory | | `make_delete_file_tool(sandbox)` | `delete_file` | Delete a file or empty directory | | `make_move_file_tool(sandbox)` | `move_file` | Move or rename | | `make_copy_file_tool(sandbox)` | `copy_file` | Copy a file | | `make_make_dir_tool(sandbox)` | `make_dir` | `mkdir -p` | | `make_search_files_tool(sandbox)` | `search_files` | `find` by name glob | | `make_grep_tool(sandbox)` | `grep` | Extended-regex search with optional recursion |