Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
monty — Безопасная песочница Python, написанная на Rust, для кода, созданного ИИ. | Kitploit
Инструменты/GitHubGitHub/pydantic/monty
Утилиты общего назначенияАнализ КодаСкриптинг и автоматизацияОбучение и ОбразованиеБезопасность ИИ
GitHubpydantic/monty

monty

Безопасная песочница Python, написанная на Rust, для кода, созданного ИИ.

Репозиторий
8.0k4011794 ч 40 мин назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
<div align="center">
  <h1>Monty</h1>
</div>
<div align="center">
  <h3>Минимальный, безопасный интерпретатор Python, написанный на Rust для использования ИИ.</h3>
</div>
<div align="center">
  <a href="https://github.com/pydantic/monty/actions/workflows/ci.yml?query=branch%3Amain"><img src="https://github.com/pydantic/monty/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="https://codspeed.io/pydantic/monty?utm_source=badge"><img src="https://img.shields.io/badge/CodSpeed-Performance%20Tracked-blue?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNOCAwTDAgOEw4IDE2TDE2IDhMOCAwWiIgZmlsbD0id2hpdGUiLz48L3N2Zz4=" alt="Codspeed"></a>
  <a href="https://codecov.io/gh/pydantic/monty"><img src="https://codecov.io/gh/pydantic/monty/graph/badge.svg?token=HX4RDQX5OG" alt="Coverage"></a>
  <a href="https://pypi.python.org/pypi/pydantic-monty"><img src="https://img.shields.io/pypi/v/pydantic-monty.svg" alt="PyPI"></a>
  <a href="https://github.com/pydantic/monty"><img src="https://img.shields.io/pypi/pyversions/pydantic-monty.svg" alt="versions"></a>
  <a href="https://github.com/pydantic/monty/blob/main/LICENSE"><img src="https://img.shields.io/github/license/pydantic/monty.svg?v=2" alt="license"></a>
  <a href="https://logfire.pydantic.dev/docs/join-slack/"><img src="https://img.shields.io/badge/Slack-Join%20Slack-4A154B?logo=slack" alt="Join Slack" /></a>
</div>

---

**Экспериментально** — проект всё ещё находится в разработке и пока не готов к использованию в продакшене.

Минимальный, безопасный интерпретатор Python, написанный на Rust для использования ИИ.

Monty позволяет избежать затрат, задержек, сложности и лишней возни, связанных с полноценной песочницей на основе контейнеров для выполнения кода, сгенерированного LLM.

Вместо этого он позволяет безопасно запускать Python-код, написанный LLM, встроенным в вашего агента, со временем запуска, измеряемым в однозначных микросекундах, а не в сотнях миллисекунд.

Что Monty **может**:

- Выполнять достаточное подмножество Python-кода — достаточно, чтобы ваш агент мог выразить то, что он хочет сделать
- Полностью блокировать доступ к хостовому окружению: файловая система, переменные окружения и сетевой доступ реализованы через внешние вызовы функций, которые разработчик может контролировать
- Вызывать функции на хосте — только те функции, к которым вы предоставили доступ
- Выполнять проверку типов — Monty поддерживает современные подсказки типов Python и поставляется с [ty](https://docs.astral.sh/ty/) в одном бинарном файле для проверки типов
- Сохраняться в байты в точках внешних вызовов функций, что позволяет хранить состояние интерпретатора в файле или базе данных и возобновлять работу позже
- Запускаться чрезвычайно быстро (<1мкс от кода до результата выполнения), а производительность во время выполнения сопоставима с CPython (обычно от 5 раз быстрее до 5 раз медленнее)
- Вызываться из Rust, Python или JavaScript — поскольку Monty не зависит от CPython, его можно использовать везде, где можно запустить Rust
- Контролировать использование ресурсов — Monty может отслеживать использование памяти, глубину стека и время выполнения, а также отменять выполнение при превышении заданных лимитов
- Собирать stdout и stderr и возвращать их вызывающему коду
- Выполнять асинхронный или синхронный код на хосте через асинхронный или синхронный код на хосте
- Использовать небольшое подмножество стандартной библиотеки: `sys`, `os`, `typing`, `asyncio`, `re`, `datetime`, `json`, `dataclasses` (скоро)

Что Monty **не может**:

- Использовать остальную часть стандартной библиотеки
- Использовать сторонние библиотеки (например, Pydantic); поддержка внешних библиотек Python не является целью
- определять классы (поддержка должна появиться в ближайшее время)
- использовать match-выражения (опять же, поддержка должна появиться в ближайшее время)

---

Короче говоря, Monty крайне ограничен и предназначен для **одного** сценария использования:

**Для запуска кода, написанного агентами.**

О мотивации, почему вам может это понадобиться, см.:

- [Codemode](https://blog.cloudflare.com/code-mode/) от Cloudflare
- [Programmatic Tool Calling](https://platform.claude.com/docs/en/agents-and-tools/tool-use/programmatic-tool-calling) от Anthropic
- [Code Execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp) от Anthropic
- [Smol Agents](https://github.com/huggingface/smolagents) от Hugging Face

Если очень просто, идея всего вышеперечисленного в том, что LLM могут работать быстрее, дешевле и надёжнее, если их просить писать код на Python (или JavaScript) вместо традиционных вызовов инструментов. Monty делает это возможным без сложности песочницы и без риска запуска кода напрямую на хосте.

**Примечание:** Monty (в ближайшее время) будет использоваться для реализации `codemode` в [Pydantic AI](https://github.com/pydantic/pydantic-ai)

## Использование

Monty можно вызывать из Python, JavaScript/TypeScript или Rust.

### Python

Для установки:```bash
uv add pydantic-monty
```
(Или `pip install pydantic-monty` для бумеров)

`pydantic-monty` — это метапакет, объединяющий `pydantic-monty-client` (модуль `pydantic_monty`) с `pydantic-monty-runtime` (двоичный файл воркера `monty`). Установите только `pydantic-monty-client`, если двоичный файл уже поступает откуда-то ещё.

Использование:```python
from typing import Any

import pydantic_monty

code = """
async def agent(prompt: str, messages: Messages):
    while True:
        print(f'messages so far: {messages}')
        output = await call_llm(prompt, messages)
        if isinstance(output, str):
            return output
        messages.extend(output)

await agent(prompt, [])
"""

type_definitions = """
from typing import Any

Messages = list[dict[str, Any]]

async def call_llm(prompt: str, messages: Messages) -> str | Messages:
    raise NotImplementedError()

prompt: str = ''
"""


Messages = list[dict[str, Any]]


async def call_llm(prompt: str, messages: Messages) -> str | Messages:
    if len(messages) < 2:
        return [{'role': 'system', 'content': 'example response'}]
    else:
        return f'example output, message count {len(messages)}'


async def main():
    async with pydantic_monty.AsyncMonty() as pool:
        async with pool.checkout(
            script_name='agent.py',
            type_check=True,
            type_check_stubs=type_definitions,
        ) as session:
            output = await session.feed_run(
                code,
                inputs={'prompt': 'testing'},
                external_lookup={'call_llm': call_llm},
            )
    print(output)
    #> example output, message count 2


if __name__ == '__main__':
    import asyncio

    asyncio.run(main())
```
Выполнение происходит в пуле рабочих подпроцессов `monty`, поэтому даже ошибка
памяти, вызванная вредоносным кодом (переполнение стека, прерывание аллокатора),
никогда не приведёт к падению вашего процесса — рабочий процесс погибает,
вызывает `MontyCrashedError` и заменяется. Существует также полностью синхронный API:```python
import pydantic_monty

with pydantic_monty.Monty() as pool:
    with pool.checkout() as session:
        # session state persists between feed_run calls
        session.feed_run('x = 21')
        print(session.feed_run('x * 2'))
        #> 42
```
### JavaScript / TypeScript

Для установки:```bash
npm install @pydantic/monty
```
Пакет JS — это нативный (napi) биндинг поверх того же пула воркеров Rust, что
использует пакет Python — биндинг и рабочий бинарник `monty` поставляются через
платформозависимые npm-пакеты:```ts
import { Monty } from '@pydantic/monty'

await using pool = await Monty.create()
await using session = await pool.checkout()

// session state persists between feedRun calls
await session.feedRun('x = 21')
console.log(await session.feedRun('x * 2')) // 42

// external functions may be async
const result = await session.feedRun('await fetch_data()', {
  externalLookup: { fetch_data: async () => 'data' },
})
```
Для браузеров (или везде, где невозможны подпроцессы) тот же пакет
предоставляет внутрипроцессную сборку WebAssembly по подпути `@pydantic/monty/wasm`
(без изоляции сбоев: сбой песочницы там означает сбой хоста).

### Rust

Для запуска недоверенного кода из Rust мы рекомендуем
крейт [`monty-pool`](https://crates.io/crates/monty-pool), а не внутрипроцессный API ниже.
`monty-pool` запускает код только в рабочих подпроцессах `monty`, что даёт дополнительные защиты:
сбой, вызванный вредоносным кодом (переполнение стека, аварийное завершение аллокатора), убивает только рабочий процесс —
пул обнаруживает гибель и заменяет рабочий процесс — а родительский watchdog может убивать рабочие процессы,
превысившие жёсткий тайм-аут. Это тот же движок, на котором построены пакеты Python и JavaScript выше.
См. [monty-pool README](https://github.com/pydantic/monty/tree/main/crates/monty-pool)
для использования.

Сам крейт `monty` предоставляет внутрипроцессный интерпретатор:```rust
use monty::MontyRun;
use monty_types::{CompileOptions, ResourceTracker, MontyObject, PrintWriter, ResourceLimits};

let code = r#"
def fib(n):
    if n <= 1:
        return n
    return fib(n - 1) + fib(n - 2)

fib(x)
"#;

let runner = MontyRun::new(code.to_owned(), "fib.py", vec!["x".to_owned()], CompileOptions::default()).unwrap();
let result = runner.run(vec![MontyObject::Int(10)], ResourceTracker::default(), PrintWriter::Stdout).unwrap();
assert_eq!(result, MontyObject::Int(55));
```
#### Сериализация

Сессия REPL может быть сериализована с помощью `dump()` и восстановлена с помощью `Dump::load()`. Дамп содержит метаданные сеанса (имя скрипта, заглушки проверки типов) вместе с состоянием интерпретатора, под версией, которую проверяет загружающая сборка:```rust
use monty::{Dump, MontyRepl, Session, SessionRef, dump};
use monty_types::{CompileOptions, MontyObject, PrintWriter, ResourceTracker};

// Snapshot a session between snippets
let mut repl = MontyRepl::new("main.py", ResourceTracker::default(), CompileOptions::default());
repl.feed_run("x = 41", vec![], PrintWriter::Stdout).unwrap();
let bytes = dump("main.py", None, SessionRef::Idle(&repl)).unwrap();

// Later, restore and carry on feeding
let Session::Idle(mut restored) = Dump::load(&bytes).unwrap().state else {
    panic!("dumped an idle session")
};
let result = restored.feed_run("x + 1", vec![], PrintWriter::Stdout).unwrap();
assert_eq!(result, MontyObject::Int(42));
```
`MontyRun` и `RunProgress` не имеют собственного формата дампа, но оба реализуют `serde::Serialize`/`Deserialize`, поэтому хост может сериализовать разобранный код или приостановленный запуск в любом формате, который он уже использует.

## Ограничения памяти в воркерах

`max_memory` сеанса измеряется аллокатором воркера. Интерпретатор
сообщает о штатной `MemoryError` после пересечения мягкого предела; более высокий жёсткий
предел убивает и заменяет воркера, если одно выделение памяти перескакивает слишком далеко между контрольными точками.

См. [`limitations/resource_limits.md`](https://github.com/pydantic/monty/blob/main/limitations/resource_limits.md) о том, как
превышение лимита проявляется для хоста, и `monty-alloc` — об аллокаторе, под управлением которого работают как
субпроцессы, так и WebAssembly-воркеры.

## Интеграция PydanticAI

Monty будет обеспечивать работу code-mode в
[Pydantic AI](https://github.com/pydantic/pydantic-ai). Вместо выполнения
последовательных вызовов инструментов LLM пишет Python-код, который вызывает ваши инструменты
как функции, и Monty безопасно выполняет его.```python test="skip"
import asyncio
import json

import logfire
from httpx import AsyncClient
from pydantic_ai import Agent, RunContext
from pydantic_ai.toolsets.code_mode import CodeModeToolset
from pydantic_ai.toolsets.function import FunctionToolset
from typing_extensions import TypedDict

logfire.configure()
logfire.instrument_pydantic_ai()


class LatLng(TypedDict):
    lat: float
    lng: float


weather_toolset: FunctionToolset[AsyncClient] = FunctionToolset()


@weather_toolset.tool
async def get_lat_lng(
    ctx: RunContext[AsyncClient], location_description: str
) -> LatLng:
    """Get the latitude and longitude of a location."""
    # NOTE: the response here will be random, and is not related to the location description.
    r = await ctx.deps.get(
        'https://demo-endpoints.pydantic.workers.dev/latlng',
        params={'location': location_description},
    )
    r.raise_for_status()
    return json.loads(r.content)


@weather_toolset.tool
async def get_temp(ctx: RunContext[AsyncClient], lat: float, lng: float) -> float:
    """Get the temp at a location."""
    # NOTE: the responses here will be random, and are not related to the lat and lng.
    r = await ctx.deps.get(
        'https://demo-endpoints.pydantic.workers.dev/number',
        params={'min': 10, 'max': 30},
    )
    r.raise_for_status()
    return float(r.text)


@weather_toolset.tool
async def get_weather_description(
    ctx: RunContext[AsyncClient], lat: float, lng: float
) -> str:
    """Get the weather description at a location."""
    # NOTE: the responses here will be random, and are not related to the lat and lng.
    r = await ctx.deps.get(
        'https://demo-endpoints.pydantic.workers.dev/weather',
        params={'lat': lat, 'lng': lng},
    )
    r.raise_for_status()
    return r.text


agent = Agent(
    'gateway/anthropic:claude-sonnet-4-5',
    # toolsets=[weather_toolset],
    toolsets=[CodeModeToolset(weather_toolset)],
    deps_type=AsyncClient,
)


async def main():
    async with AsyncClient() as client:
        await agent.run('Compare the weather of London, Paris, and Tokyo.', deps=client)


if __name__ == '__main__':
    asyncio.run(main())
```
## Биндинги сообщества

- **Go**: [gomonty](https://github.com/ewhauser/gomonty/) — биндинги Go для интерпретатора Monty
- **Dart/Flutter**: dart_monty [(github)](https://github.com/runyaga/dart_monty) [(pub.dev)](https://pub.dev/packages/dart_monty) — биндинги Dart/Flutter для Monty

# Альтернативы

Обычно, когда показываешь людям Monty, получаешь один из двух ответов:

1. О боже, это решает столько проблем, я хочу это.
2. Почему не X?

Где X — некая альтернативная технология. Как ни странно, эти ответы часто сочетаются, что говорит о том, что люди ещё не нашли альтернативу, которая им подходит, но не могут поверить, что созданию целой реализации Python с нуля действительно нет хорошей альтернативы.

Я постараюсь пройтись по самым очевидным альтернативам и объяснить, почему они не подходят для того, что мы хотели.

ПРИМЕЧАНИЕ: все эти технологии впечатляют и широко используются; этот комментарий об их ограничениях для нашего сценария использования не следует воспринимать как критику. Большинство этих решений не задумывались с целью предоставления песочницы для LLM, поэтому они не обязательно хороши в этом.

| Технология          | Полнота языка           | Безопасность | Задержка запуска | FOSS       | Сложность настройки | Монтирование файлов | Снапшоты   |
| ------------------ | --------------------- | ------------ | ------------- | ---------- | ---------------- | -------------- | ------------ |
| Monty              | частичная             | строгая      | 0.06ms        | бесплатно / OSS | легко            | легко          | легко       |
| Docker             | полная                | хорошая      | 195ms         | бесплатно / OSS | средне           | легко          | средне      |
| Pyodide            | полная                | слабая       | 2800ms        | бесплатно / OSS | средне           | легко          | сложно      |
| starlark-rust      | очень ограниченная    | хорошая      | 1.7ms         | бесплатно / OSS | легко            | недоступно?    | невозможно? |
| WASI / Wasmer      | частичная, почти полная | строгая     | 66ms          | бесплатно \*   | средне           | легко          | средне      |
| сервис песочницы   | полная                | строгая      | 1033ms        | платно         | средне           | сложно         | средне      |
| YOLO Python        | полная                | отсутствует  | 0.1ms / 30ms  | бесплатно / OSS | легко            | легко / страшно | сложно      |

См. [./scripts/startup_performance.py](https://github.com/pydantic/monty/blob/main/scripts/startup_performance.py) — скрипт, использованный для расчёта показателей производительности запуска.

Подробности по каждой строке ниже:

### Monty

- **Полнота языка**: нет классов (пока), ограниченная стандартная библиотека, нет сторонних библиотек
- **Безопасность**: явно контролируемый доступ к файловой системе, сети и переменным окружения, строгие ограничения на время выполнения и использование памяти
- **Задержка запуска**: запускается за микросекунды
- **Сложность настройки**: просто `pip install pydantic-monty` или `npm install @pydantic/monty`, загрузка ~4.5MB
- **Монтирование файлов**: строго контролируется, см. [#85](https://github.com/pydantic/monty/pull/85)
- **Снапшоты**: функциональность паузы и возобновления Monty с помощью `dump()` и `load()` делает паузу, возобновление и форкинг выполнения тривиальными

### Docker

- **Полнота языка**: полный CPython с любой библиотекой
- **Безопасность**: изоляция процессов и файловой системы, сетевые политики, но существуют побеги из контейнеров; ограничение памяти возможно
- **Задержка запуска**: накладные расходы на запуск контейнера (~195ms по замерам)
- **Сложность настройки**: требует демона Docker, образов контейнеров, оркестрации; `python:3.14-alpine` весит 50MB — docker нельзя установить через PyPI
- **Монтирование файлов**: монтирование томов работает хорошо
- **Снапшоты**: возможно с решениями для долговечного выполнения, такими как Temporal, или созданием снимка образа и сохранением его как Docker-образа.

### Pyodide

- **Полнота языка**: полный CPython, скомпилированный в WASM, доступны почти все библиотеки
- **Безопасность**: полагается на песочницу браузера/WASM — не предназначена для серверной изоляции; python-код может выполнять произвольный код в JS-рантайме, изоляцию обеспечивает только deno; ограничения памяти с deno обеспечить трудно или невозможно
- **Задержка запуска**: загрузка WASM-рантайма медленная (~2800ms холодный старт)
- **Сложность настройки**: нужно загрузить WASM-рантайм, обрабатывать асинхронную инициализацию; NPM-пакет pyodide ~12MB, deno ~50MB — Pyodide нельзя вызвать, используя только PyPI-пакеты
- **Монтирование файлов**: виртуальная файловая система через API браузера
- **Снапшоты**: предположительно возможно с решениями для долговечного выполнения, такими как Temporal, но сложно

### starlark-rust

См. [starlark-rust](https://github.com/facebook/starlark-rust).

- **Полнота языка**: конфигурационный язык, а не Python — нет классов, исключений, async
- **Безопасность**: детерминированный и герметичный по замыслу
- **Задержка запуска**: работает встроенно в процесс, как Monty, отсюда впечатляющее время запуска
- **Сложность настройки**: можно использовать в Python через [starlark-pyo3](https://github.com/inducer/starlark-pyo3)
- **Монтирование файлов**: файловых операций по замыслу нет, насколько я знаю?
- **Снапшоты**: невозможно, насколько я знаю?

### WASI / Wasmer

Запуск Python в WebAssembly через [Wasmer](https://wasmer.io/).

- **Полнота языка**: полный CPython; чистые Python-пакеты работают через монтирование, внешние пакеты с C-биндингами не работают
- **Безопасность**: в принципе, WebAssembly должен обеспечивать строгие гарантии песочницы.
- **Задержка запуска**: python-пакет [wasmer](https://pypi.org/project/wasmer/) не обновлялся 3 года, и я не смог найти документацию о вызове Python в wasmer из Python, поэтому я вызывал его через subprocess. Задержка запуска составила 66ms.
- **Сложность настройки**: загрузка wasmer — 100mb, пакет "python/python" — 50mb.
- **FOSS**: я отметил это как "бесплатно \*", поскольку стоимость нулевая, но не всё, похоже, является открытым исходным кодом. По состоянию на 2026-02-10 пакет [`python/python` wasmer package](https://wasmer.io/python/python) не имеет readme, лицензии, ссылки на исходный код и указаний на то, как он собран; недавно загруженные версии показывают размер "0B", хотя загрузка составляет ~50MB — процесс сборки бинарника Python не является ясным и прозрачным. _(Если я здесь ошибаюсь, пожалуйста, создайте issue, чтобы меня поправить)_
- **Монтирование файлов**: поддерживается
- **Снапшоты**: поддерживается через журналирование

### Сервис песочницы

Сервисы вроде [Daytona](https://daytona.io), [E2B](https://e2b.dev), [Modal](https://modal.com).

Здесь схожие проблемы: больше сложности в настройке, но ниже сетевая задержка, чем при развёртывании собственной песочницы на k8s.

- **Полнота языка**: полный CPython с любой библиотекой
- **Безопасность**: профессионально управляемая изоляция контейнеров
- **Задержка запуска**: сетевой обход и время запуска контейнера. У меня получилось ~1s холодного старта с Daytona EU из Лондона; Daytona рекламирует задержку ниже 90ms, предположительно для уже существующего контейнера, неясно, включает ли она сетевую задержку
- **FOSS**: оплата за выполнение или вычислительное время, некоторые реализации с открытым исходным кодом
- **Сложность настройки**: интеграция API, токены аутентификации — нормально для стартапов, но обычно не вариант для предприятий
- **Монтирование файлов**: загрузка/скачивание через вызовы API
- **Снапшоты**: возможно с решениями для долговечного выполнения, такими как Temporal; также сервисы предлагают некоторые решения для этого, думаю, основанные на docker-контейнерах

### YOLO Python

Запуск Python напрямую через `exec()` (~0.1ms) или subprocess (~30ms).

- **Полнота языка**: полный CPython с любой библиотекой
- **Безопасность**: никакой — полный доступ к файловой системе, сети, переменным окружения, системным командам
- **Задержка запуска**: почти нулевая для `exec()`, ~30ms для subprocess
- **Сложность настройки**: никакой
- **Монтирование файлов**: прямой доступ к файловой системе (в этом и проблема)
- **Снапшоты**: возможно с решениями для долговечного выполнения, такими как Temporal

## Часть стека Pydantic

Стек Pydantic — это всё, что нужно для выпуска AI-агентов продакшен-уровня:

- [Pydantic AI](https://pydantic.dev/pydantic-ai?utm_source=github&utm_medium=readme&utm_campaign=monty) — типобезопасный фреймворк для агентов
- [Pydantic Logfire](https://pydantic.dev/logfire?utm_source=github&utm_medium=readme&utm_campaign=monty) — наблюдаемость полного стека с приоритетом AI
- [Logfire AI Gateway](https://pydantic.dev/ai-gateway?utm_source=github&utm_medium=readme&utm_campaign=monty) — единый прокси для LLM
Скачать инструмент