Python 3.14 compatibility stops where the sandbox boundary begins
Monty implements a Python 3.14 subset in Rust, and the missing pieces are central to its design. Sandboxed code has no filesystem, environment variables, sockets, subprocesses, threads, native extensions, or third-party packages by default. It can calculate, transform data, define functions and simple classes, handle exceptions, and call a selected standard-library subset. That is a useful language for an agent to express a small job, but it is not a drop-in CPython runtime.
The limitations guide is unusually direct. Generator functions, class inheritance, method decorators, match, wildcard imports, and several other constructs are rejected. The standard library list contains 20 named modules, and each may expose only part of CPython's API. Common modules such as logging, hashlib, uuid, urllib, socket, and subprocess are absent. If a model has learned ordinary Python habits, type checking and clear retry instructions matter because valid CPython can still be invalid Monty code.
Three opt-in mechanisms define what code can reach
Monty's security guide names 3 paths from the interpreter to the host: functions, wrapped objects or classes, and filesystem or OS callbacks. With none configured, there is no ambient authority for the snippet to discover. A host function suspends the interpreter, runs application code outside the sandbox, then returns a converted result. That design makes the boundary visible in code review because every external capability begins with something the host supplied.
The same design can be weakened by a careless adapter. A callback that accepts any URL becomes a network primitive, and a callback that reads an arbitrary path becomes a filesystem primitive. The docs say host functions run with the full authority of the host process. Read-write mounts carry a similar warning because untrusted code can write files into a real directory. Monty can restrict the interpreter, but it cannot repair an overpowered function or an unsafe mount chosen by the application.
What happened when we ran it
Our measurement setup used a fresh unprivileged Debian container with 3 CPUs, 8 GB of RAM, Python 3.12, and no secrets. In our run, 34 packages installed in 28 seconds and occupied 37 MB. Pip-audit found 0 known vulnerabilities in those installed Python packages. The repository itself contained 1,374 files and about 289,541 source lines at commit 037e91c.
The build exited 1 after 6 seconds. The final log lines were Python SyntaxWarning messages about return and break in finally blocks and identity checks against tuple literals inside crates/monty/test_cases. That tail does not contain the actual reason for the nonzero exit, so we are not treating the warnings as the cause. Our harness found no test script or target and skipped tests rather than claiming a pass or failure.
Resource limits reduce damage but do not promise session survival
Monty exposes limits for memory, feed duration, host-round-trip duration, recursion, garbage collection, suspensions, and total sleep. Some limits are optional, while recursion depth and suspension count retain defaults. This gives a host several ways to stop generated code that allocates or loops forever. The memory budget covers requested allocations inside the worker rather than acting as a simple ceiling on the whole process's resident memory.
Open issue 921, filed against 1.0.0b2, demonstrates why limit behavior still deserves application tests. Nine very large keyword names in a functools.partial can cause a memory-limited worker to terminate when the function is called. The reporter explicitly did not show a parent-process crash, sandbox escape, or cross-session effect. That scope matters: the finding is worker availability under a tight limit, not evidence that Monty's isolation failed.
Snapshots help agents pause, but only trusted bytes should return
Monty can dump a session between feeds or snapshot execution while it is suspended on a host call. The resulting bytes preserve interpreter state so another process can resume the work. That is attractive for durable agent jobs because a request does not have to keep one worker occupied while an external tool runs. It also makes provenance part of the security design.
The snapshot guide says loaders are for unmodified bytes from a trusted, compatible producer. Monty does not authenticate snapshots or fully validate arbitrary contents. Store them behind access control or attach an integrity check before loading. Long-lived sessions have their own caveats: open issue 895 describes a name table filling after roughly 65,000 inputs because each REPL feed interns a new filename. That is a specialized workload, but agent loops can be specialized workloads.
Beta.3 is active, while Python compatibility is still moving
GitHub recorded release v1.0.0-beta.3 and a repository push on September 24, 2026. The repository had 8,268 stars and 118 open issues and pull requests when fetched. The release changed session dump serialization and added source positions for suspensions. Same-day code and release activity show maintenance, while the beta label and open compatibility reports show that API and behavior checks still belong in an upgrade process.
Monty makes the most sense when generated code needs a calculator-sized Python environment plus a few named tools. Its language boundary is easier to reason about than a full interpreter with a long package list, and its documentation tells you where that boundary ends. If the agent needs pandas, shell commands, arbitrary HTTP, or faithful CPython behavior, forcing those needs through host callbacks defeats the point. Put a normal interpreter inside OS isolation instead.

