Monty-backed Python REPL middleware for Deep Agents, with a shared filesystem between the sandbox and the agent's file tools.
Project description
deepagents-monty
deepagents-monty adds a secure python_repl tool to
Deep Agents using Pydantic's
Monty sandboxed Python interpreter.
Agent-generated Python can inspect and transform the same virtual files used by
read_file, write_file, ls, glob, grep, and edit_file, without giving
that code host filesystem or network access.
Why use it?
- Run model-written Python in a sandbox instead of on the host.
- Let the model use loops, parsing, aggregation, and data transforms when file tools would be awkward.
- Share one Deep Agents backend between the normal file tools and Monty code.
- Expose carefully scoped host capabilities with
external_functions.
Install
uv add deepagents-monty
Or with pip:
pip install deepagents-monty
Until the package is published on PyPI, install from this repository:
uv add 'deepagents-monty @ git+https://github.com/yesh0907/deepagents-monty'
Quickstart
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from deepagents_monty import MontyCodeMiddleware
backend = StateBackend()
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
backend=backend,
middleware=[MontyCodeMiddleware(backend=backend)],
)
result = await agent.ainvoke({
"messages": [{
"role": "user",
"content": "Find all Python files larger than 1000 bytes and list their sizes.",
}]
})
The model can now call python_repl with code like:
from pathlib import Path
sizes = []
for p in Path("/").iterdir():
if str(p).endswith(".py"):
content = p.read_text()
if len(content) > 1000:
sizes.append((str(p), len(content)))
sorted(sizes, key=lambda x: -x[1])
The files visible to Path("/") are the same files visible to the Deep Agents
filesystem tools. python_repl preserves variables, imports, and function
definitions between calls; pass restart=True to reset the REPL.
Security Model
Monty code runs in a restricted interpreter. By default, it has:
- no host filesystem access
- no network access
- no arbitrary third-party imports
- no access to environment variables
- only the virtual filesystem backed by the Deep Agents backend you provide
Host capabilities must be explicitly exposed through external_functions. Treat
those functions as part of the trusted boundary: validate inputs, keep return
values simple, and expose only the operations the model should be allowed to use.
Limitations
deepagents-monty inherits Monty's current Python subset:
- no class definitions
- no match statements, generators, or context managers
- no third-party libraries such as
pandas,requests, ornumpy - only a small standard-library subset
- no wall-clock or timing primitives
- no file deletes or renames through
pathlib - filesystem bridging expects sync Deep Agents backend methods
See docs/limitations.md for the detailed list.
External Functions
Use external_functions when sandboxed code needs a carefully scoped host
capability, such as CSV parsing, an API client, or a domain-specific helper.
from typing import Any
from deepagents import create_deep_agent
from deepagents.backends import StateBackend
from deepagents_monty import MontyCodeMiddleware
def read_csv(path: str) -> list[dict[str, Any]]:
...
backend = StateBackend()
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
backend=backend,
middleware=[
MontyCodeMiddleware(
backend=backend,
external_functions={"read_csv": read_csv},
)
],
)
The model can call the function from python_repl:
rows = read_csv("/transactions.csv")
sum(row["Amount"] for row in rows if row["Category"] == "Groceries")
Async external functions are supported. Sandbox code must call them with
await:
data = await fetch_json("https://example.com/data.json")
Function signatures are inferred from Python annotations and added to Monty's
type checker. Pass type_check_stubs when the public sandbox contract should be
more precise than the host function signature.
API
MontyCodeMiddleware(
*,
backend,
system_prompt=None,
external_functions=None,
type_check_stubs=None,
max_duration_secs=10.0,
type_check=True,
)
backend: required Deep Agents backend. Pass the same backend you pass tocreate_deep_agent(backend=...).system_prompt: optional replacement for the default prompt that describespython_replto the model.external_functions: optional host functions exposed as global names inside Monty code.type_check_stubs: optional Python stub text for external functions and model-facing types.max_duration_secs: per-call wall-clock cap for sandbox execution.type_check: enables Monty's parse-time type checker. Defaults toTrue.
Advanced users can also build the standalone python_repl tool with
make_execute_python(...).
Examples
Analyze Agent Files
from pathlib import Path
import json
records = []
for path in Path("/").iterdir():
if str(path).endswith(".json"):
records.append(json.loads(path.read_text()))
len(records)
Expose a Safe Reader
def read_transactions() -> list[dict[str, str]]:
...
middleware = MontyCodeMiddleware(
backend=backend,
external_functions={"read_transactions": read_transactions},
)
Use an Async Helper
async def lookup_customer(customer_id: str) -> dict[str, str]:
...
middleware = MontyCodeMiddleware(
backend=backend,
external_functions={"lookup_customer": lookup_customer},
)
Sandbox code:
customer = await lookup_customer("cust_123")
customer["segment"]
Development
uv sync --all-extras
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run pyright
Build the package locally:
uv build
uvx twine check dist/*
More Documentation
Credits
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file deepagents_monty-0.1.0.tar.gz.
File metadata
- Download URL: deepagents_monty-0.1.0.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73744cfa5660c6ed4297f85e45e8d5a8ba967f1b38aecaf3884a81fe980d42d0
|
|
| MD5 |
8a340400e86414560b82124dd5abd007
|
|
| BLAKE2b-256 |
67095e7bea381ad2f1e21f1ad931dd8072be274808769fbd27b405a3ee2d0811
|
File details
Details for the file deepagents_monty-0.1.0-py3-none-any.whl.
File metadata
- Download URL: deepagents_monty-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
054fe8beba6fca28e14da9d07185ef25ac2d9eaa7e4bc07ace60857fecb13eb5
|
|
| MD5 |
4cfb23c9b05dd5015f359815685d22ff
|
|
| BLAKE2b-256 |
8ad742d4c21217075a796e46b56c460f295ef449b6a6809906897729f2bbdbe9
|