Torna agli aggiornamenti
New releaseAug 9, 2026

monty v0.0.20

Un interprete Python minimale e sicuro scritto in Rust per uso da parte dell'IA

Condividi

Monty

Un interprete Python minimale e sicuro scritto in Rust, pensato per l'uso da parte di IA.

CI Codspeed Coverage PyPI versions license Join Slack

Sperimentale - Questo progetto è ancora in fase di sviluppo e non è pronto per l'uso in produzione.

Un interprete Python minimale e sicuro scritto in Rust, pensato per l'uso da parte di IA.

Monty evita i costi, la latenza, la complessità e il fastidio generale di usare una sandbox completa basata su container per eseguire codice generato da LLM.

Invece, ti permette di eseguire in sicurezza codice Python scritto da un LLM integrato nel tuo agente, con tempi di avvio misurati in microsecondi a una cifra, non in centinaia di millisecondi.

Cosa Monty può fare:

  • Eseguire un sottoinsieme ragionevole di codice Python, sufficiente affinché il tuo agente possa esprimere ciò che vuole fare
  • Bloccare completamente l'accesso all'ambiente host: filesystem, variabili d'ambiente e accesso alla rete sono tutti implementati tramite chiamate a funzioni esterne che lo sviluppatore può controllare
  • Chiamare funzioni sull'host, solo quelle a cui gli concedi l'accesso
  • Eseguire il typechecking: Monty supporta i moderni type hint di Python e include ty in un singolo binario per eseguire il controllo dei tipi
  • Essere serializzato in byte in corrispondenza delle chiamate a funzioni esterne, consentendo di salvare lo stato dell'interprete in un file o in un database e riprenderlo in seguito
  • Avviarsi estremamente in fretta (<1μs dal codice al risultato dell'esecuzione) e avere prestazioni a runtime simili a CPython (in genere tra 5 volte più veloce e 5 volte più lento)
  • Essere richiamato da Rust, Python o JavaScript: poiché Monty non ha dipendenze da CPython, puoi usarlo ovunque riesca a eseguire Rust
  • Controllare l'uso delle risorse: Monty può tracciare l'uso della memoria, la profondità dello stack e il tempo di esecuzione e annullare l'esecuzione se supera i limiti predefiniti
  • Raccogliere stdout e stderr e restituirli al chiamante
  • Eseguire codice async o sync sull'host tramite codice async o sync sull'host
  • Usare un piccolo sottoinsieme della libreria standard: sys, os, typing, asyncio, re, datetime, json, dataclasses (presto)

Cosa Monty non può fare:

  • Usare il resto della libreria standard
  • Usare librerie di terze parti (come Pydantic); il supporto per librerie Python esterne non è un obiettivo
  • definire classi (il supporto arriverà presto)
  • usare i match statement (anche qui, il supporto arriverà presto)

In breve, Monty è estremamente limitato e progettato per un caso d'uso:

Eseguire codice scritto da agenti.

Per capire perché potresti volerlo fare, vedi:

In parole molto semplici, l'idea alla base di tutto ciò è che gli LLM possono lavorare più velocemente, a costi inferiori e in modo più affidabile se viene chiesto loro di scrivere codice Python (o JavaScript) invece di affidarsi alle tradizionali chiamate a strumenti. Monty rende tutto questo possibile senza la complessità di una sandbox o il rischio di eseguire codice direttamente sull'host.

Nota: Monty verrà (presto) utilizzato per implementare codemode in Pydantic AI

Utilizzo

Monty può essere richiamato da Python, JavaScript/TypeScript o Rust.

Python

Per installare:```bash uv add pydantic-monty

(Oppure `pip install pydantic-monty` per i boomer)

`pydantic-monty` è un metapackage che abbina `pydantic-monty-client` (il
modulo `pydantic_monty`) con `pydantic-monty-runtime` (il binario del
worker `monty`). Installa `pydantic-monty-client` da solo se il binario proviene già da
un'altra parte.

Uso:```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())

L'esecuzione avviene in un pool di subprocessi worker monty, quindi anche un errore di memoria innescato da codice avversario (stack overflow, abort dell'allocatore) non può mai mandare in crash il tuo processo — il worker muore, solleva MontyCrashedError e viene sostituito. C'è anche un'API completamente sincrona:```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

Per installare:```bash
npm install @pydantic/monty

The JS package is a native (napi) binding over the same Rust worker pool the Python package uses — the binding and the monty worker binary ship via platform-specific npm packages:```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

Categorie