Skip to main content

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

PyPI Python versions CI License: MIT

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, or numpy
  • 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 to create_deep_agent(backend=...).
  • system_prompt: optional replacement for the default prompt that describes python_repl to 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 to True.

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

deepagents_monty-0.1.0.tar.gz (13.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

deepagents_monty-0.1.0-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

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

Hashes for deepagents_monty-0.1.0.tar.gz
Algorithm Hash digest
SHA256 73744cfa5660c6ed4297f85e45e8d5a8ba967f1b38aecaf3884a81fe980d42d0
MD5 8a340400e86414560b82124dd5abd007
BLAKE2b-256 67095e7bea381ad2f1e21f1ad931dd8072be274808769fbd27b405a3ee2d0811

See more details on using hashes here.

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

Hashes for deepagents_monty-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 054fe8beba6fca28e14da9d07185ef25ac2d9eaa7e4bc07ace60857fecb13eb5
MD5 4cfb23c9b05dd5015f359815685d22ff
BLAKE2b-256 8ad742d4c21217075a796e46b56c460f295ef449b6a6809906897729f2bbdbe9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page