Littrs is a Python sandbox that you embed directly into your Rust or Python application. There's no container to start, no runtime to boot, no network call to make — just a library that executes LLM-generated Python safely, with only the tools you give it.
It was built for a specific workflow: an LLM writes Python code that calls your functions, and you need to run that code without giving it access to anything else. Littrs compiles Python to bytecode and runs it on a stack-based VM with zero ambient capabilities. The only way sandboxed code can interact with the outside world is through tools you explicitly register.
Installation
pip install littrs
Quick Start
from littrs import Sandbox
sandbox = Sandbox()
@sandbox.tool
def get_weather(city: str, units: str = "celsius") -> dict:
"""Get current weather for a city."""
return {"city": city, "temp": 22, "units": units}
result = sandbox("get_weather('London')")
# result == {"city": "London", "temp": 22, "units": "celsius"}
The @sandbox.tool decorator registers your function with its full signature — the LLM code calls it like a normal Python function. The sandbox is also callable: sandbox(code) is shorthand for sandbox.run(code).
Variables persist across calls, and you can inject values directly:
sandbox["user_id"] = 42
sandbox("name = get_weather('London')['city']")
sandbox("name") # "London"
Resource Limits
Prevent runaway code from consuming unbounded resources:
sandbox.limit(max_instructions=10_000, max_recursion_depth=50)
try:
sandbox.run("while True: pass")
except RuntimeError as e:
print(e) # "Instruction limit exceeded (limit: 10000)"
Resource limit errors are uncatchable — try/except in the sandbox code cannot suppress them. This is by design: the host must always be able to regain control.
Capturing Print Output
capture() returns both the result and everything that was print()-ed:
result, printed = sandbox.capture("""
for i in range(5):
print(i)
"done"
""")
# result == "done"
# printed == ["0", "1", "2", "3", "4"]
Tool Documentation for LLM Prompts
describe() auto-generates Python-style signatures and docstrings from registered tools, ready to embed in a system prompt:
print(sandbox.describe())
# def get_weather(city: str, units: str = 'celsius') -> dict:
# """Get current weather for a city."""
Low-level Registration
If you need to bypass the decorator (e.g. registering a function that takes raw positional args):
def fetch_data(args):
return {"id": args[0], "name": "Example"}
sandbox.register("fetch_data", fetch_data)
File Mounting
Mount host files into the sandbox so LLM-generated code can read input and write output without full filesystem access:
sandbox.mount("data.json", "./data/input.json") # read-only (default)
sandbox.mount("output.txt", "./output/result.txt", writable=True) # read-write
result = sandbox("""
f = open("data.json")
data = f.read()
f.close()
f = open("output.txt", "w")
f.write("processed: " + data)
f.close()
""")
# Inspect written files from the host
sandbox.files() # {"output.txt": "processed: ..."}
Unmounted paths raise FileNotFoundError; writing to read-only mounts raises PermissionError. Both are catchable with try/except inside the sandbox.
WASM Sandbox (Stronger Isolation)
For stronger isolation, Littrs can run the interpreter inside a WebAssembly guest module with memory isolation and fuel-based computation limits:
from littrs import WasmSandbox, WasmSandboxConfig
config = WasmSandboxConfig().with_fuel(1_000_000).with_max_memory(32 * 1024 * 1024)
sandbox = WasmSandbox(config)
result = sandbox.run("sum(range(100))")
assert result == 4950
Littrs does not support third-party packages, classes, closures, async/await, finally, or match. See the full list of supported Python features.
Citation
If you use Littrs in your research, please cite it as:
@software{littrs,
title = {Littrs: A Minimal, Secure Python Sandbox for AI Agents},
author = {Chonkie Inc.},
url = {https://github.com/chonkie-inc/littrs},
license = {Apache-2.0},
year = {2025}
}
Release files for littrs 0.6.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| littrs-0.6.2-cp312-cp312-win_amd64.whl | CPython 3.12 | CPython 3.12 | Windows x86-64 | Details |
| littrs-0.6.2-cp312-cp312-manylinux_2_34_x86_64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.34+ x86-64 | Details |
| littrs-0.6.2-cp312-cp312-macosx_11_0_arm64.whl | CPython 3.12 | CPython 3.12 | macOS 11.0+ ARM64 | Details |
Total release size: 24.9 MB
Release files / littrs-0.6.2-cp312-cp312-win_amd64.whl
| Download URL | littrs-0.6.2-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 7.9 MB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
1b6169417f3ab1cdce2cf6ef915ba1eba07fba69e08a81b1b3fda9bdb99dbee5
|
|
BLAKE2b-256 checksum How to use checksums |
24fc6e472993789494e86a517268d94142b4267b6d8fe57da1e63cb88ba83a09
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / littrs-0.6.2-cp312-cp312-manylinux_2_34_x86_64.whl
| Download URL | littrs-0.6.2-cp312-cp312-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 9.1 MB |
| Tags | CPython 3.12 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
f9efd1cc74bdffdb156d27005fc5bb8b1a9e6971725b81d672a93347c551de14
|
|
BLAKE2b-256 checksum How to use checksums |
5dc0e3051fb2930eef391b2c27f298eb612c9c68afd65c9dccf3d2816cc91c57
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / littrs-0.6.2-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | littrs-0.6.2-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 7.9 MB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
54681e7b5c4345a17933ad4165d9db9d33464f323f8ac1a37ffd2392eda9e809
|
|
BLAKE2b-256 checksum How to use checksums |
dea6f39710ebb9f2f27d43f8b383187b34935027d54d4d7c1babdc54f07b5277
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|