The Problem
LLM‑generated Python code needs to be executed safely and with minimal latency. Traditional container‑based sandboxes add hundreds of milliseconds of startup overhead and expose a large attack surface. Teams building AI agents therefore require a tiny, deterministic runtime that can be embedded directly in a service and that guarantees host isolation.
What This Does
monty implements a subset of the Python language in pure Rust, exposing a single binary that can be called from Rust, Python, or JavaScript. The core interpreter lives in crates/monty/src/ (e.g., bytecode/compiler.rs, bytecode/vm/mod.rs, and built‑in functions under builtins/). The CLI front‑end is crates/monty-cli/src/main.rs, which parses command‑line arguments (crates/monty/src/args.rs) and invokes the interpreter.
Bindings for other ecosystems are provided:
JavaScript/TypeScript – crates/monty-js/src/lib.rs builds a Node‑compatible package (crates/monty-js/package.json). Tests such as crates/monty-js/test/basic.spec.ts verify the wrapper. Python – a thin shim in crates/monty-python/python/pydanticmonty/ (e.g., monty.pyi) lets Python code import pydanticmonty and forward calls to the Rust core.
The interpreter enforces host isolation by routing every external operation (filesystem, env, network) through user‑supplied callbacks defined in crates/monty/src/external.rs. It also snapshots state at each external call, enabling persistence of the VM.
How To Use It
Setup
Install Rust toolchain (required for all crates)
curl https://sh.rustup.rs -sSf | sh
Build the core and CLI
cargo build --release # builds everything under crates/
For JavaScript bindings:
cd crates/monty-js npm ci # installs test/dev dependencies npm run build # produces the npm package
Configuration
External callbacks are supplied by the host application. The Rust API expects an implementation of the External trait defined in crates/monty/src/external.rs. For the JS wrapper, the wrapper.ts file re‑exports runCode that accepts a string and an optional hostFns object matching the same callback shape.
No environment variables are required out‑of‑the box; all limits (memory, time, stack depth) are set via the InterpreterOptions struct in crates/monty/src/lib.rs.
Running
CLI – Execute a script directly:
cargo run -p monty-cli -- -c "print('hello')" # -c <code> flag parsed in args.rs
Rust library – Embed in a Rust program:
use monty::Interpreter; let mut interp = Interpreter::new(Default::default()); let result = interp.exec("print('hi')")?;
Node – Use the published package:
const { runCode } = require('monty-js'); runCode("print('hello')").then(console.log);
Python – Import the shim:
import pydanticmonty as monty print(monty.run("print('hi')"))
All entry points are present in the repository and exercised by the respective test suites (crates/monty/tests/, crates/monty-js/test/, crates/monty-python/tests/).
Real‑World Use
An AI‑driven automation service can spin up a monty interpreter per request, feed the LLM‑generated script, and retrieve stdout/stderr without launching a container. Example (Rust):
let mut interp = Interpreter::new(Options { timelimitms: 200, ..Default::default() }); let output = interp.exec(r#" def greet(name): print(f"Hello, {name}!") greet("Alice") "#)?; println!("VM output: {}", output);
The interpreter’s snapshot capability lets the service persist the VM state between calls, enabling multi‑step interactions with the same LLM session.
Code Health & Issues
Bugs / Risks –
Med – External function handling (external.rs) is user‑provided; misuse could re‑introduce host exposure. No default sandbox is enforced. Low – Limited standard‑library support; attempts to import unsupported modules raise ImportError early (see src/modules/mod.rs).
SDLC & Code Violations –
Low – Test coverage is solid (≈40 test files across Rust, JS, Python) and CI is configured (.github/workflows/ci.yml). Low – License file present (LICENSE), CI badges in README, and code‑formatting (rustfmt.toml, .pre-commit-config.yaml). Low – No obvious secret leakage; all lockfiles (Cargo.lock, package-lock.json) are committed.
Overall the repository follows standard Rust conventions, the CI pipeline validates builds for all crates, and the documentation (README.md, RELEASING.md) explains release steps.
The Bottom Line
monty delivers a fast, sandboxed Python runtime that can be embedded in Rust, Node, or Python environments, making it a pragmatic choice for AI agents that need to execute generated code with tight latency budgets. Its primary limitation is the deliberately narrow standard‑library surface; projects that require full CPython compatibility will need a different solution. Teams building LLM‑driven tooling and comfortable with Rust‑or‑JS integration will find the project ready for evaluation.