一个用 Rust 编写的极简、安全 Python 解释器,专为 AI Agent 代码执行设计,具备微秒级启动延迟与状态快照能力。
项目概述#
Monty 是一个由 Pydantic 团队开发的实验性 Python 解释器,核心完全由 Rust 编写。它不是 CPython 的替代品,而是专为 AI Agent 场景定制的运行时环境,允许 LLM(大语言模型)生成 Python 代码,并在高度受控、隔离的环境中执行,实现 "Code Mode" 或 "Programmatic Tool Calling"。
解决的问题#
- 安全风险:直接使用
exec()或subprocess运行 LLM 生成的代码存在严重安全隐患;Monty 默认隔离文件系统、网络和环境变量,仅执行纯计算逻辑 - 性能瓶颈:传统沙箱方案(Docker、Pyodide、WASM)启动延迟高(毫秒到秒级),Monty 启动延迟 <1μs
- 状态持久化难:传统解释器难以在执行中途暂停并保存状态;Monty 支持在调用外部函数边界进行快照,可将运行状态序列化存入数据库
核心能力#
执行核心#
- Rust 实现解释器:不依赖 CPython,核心逻辑全由 Rust 编写,通过 PyO3 提供绑定
- Python 子集支持:支持合理的 Python 语法子集,足够表达 Agent 逻辑
- 类型检查集成:内置
ty类型检查器,支持现代 Python 类型提示 - 同步/异步支持:支持主机端同步或异步代码调用
- Stdout/Stderr 捕获:标准输出与错误流被捕获并返回给调用者
安全与隔离#
- 完全环境隔离:默认无文件系统、网络、环境变量访问权限
- 外部函数调用:仅能调用开发者显式授权的函数,由宿主控制权限边界
- 资源限制追踪:可监控内存分配次数、栈深度、执行时间;支持设定阈值并自动取消执行
状态管理与持久化#
- 执行快照:可在外部函数调用点将解释器完整状态序列化为字节
- 状态恢复:支持从快照恢复执行上下文,可跨进程/机器迁移
- 预编译序列化:已解析的代码对象可
dump/load,避免重复解析开销
性能对比#
| 方案 | 语言完整性 | 安全性 | 启动延迟 | 快照支持 |
|---|---|---|---|---|
| Monty | 部分 | 严格 | 0.06ms | 容易 |
| Docker | 完整 | 良好 | 195ms | 中等 |
| Pyodide | 完整 | 较弱 | 2800ms | 困难 |
| starlark-rust | 极有限 | 良好 | 1.7ms | 不支持 |
| WASI/Wasmer | 近完整 | 严格 | 66ms | 中等 |
多语言绑定#
| 语言 | 包名 |
|---|---|
| Python | pydantic-monty (PyPI) |
| JavaScript/TypeScript | @pydantic/monty (npm) |
| Rust | 直接引用 crates |
安装方式#
Python#
uv add pydantic-monty
# 或
pip install pydantic-monty
JavaScript/TypeScript#
npm install @pydantic/monty
使用示例#
基础运行#
import pydantic_monty
m = pydantic_monty.Monty('1 + 2')
print(m.run()) # 输出: 3
带输入变量与资源限制#
m = pydantic_monty.Monty('x * y', inputs=['x', 'y'])
limits = pydantic_monty.ResourceLimits(max_duration_secs=1.0)
result = m.run(inputs={'x': 2, 'y': 3}, limits=limits)
外部函数与快照恢复#
code = "data = fetch(url); len(data)"
m = pydantic_monty.Monty(code, inputs=['url'], external_functions=['fetch'])
progress = m.start(inputs={'url': 'https://example.com'})
snapshot_data = progress.dump()
restored = pydantic_monty.MontySnapshot.load(snapshot_data)
result = restored.resume(return_value='hello world')
Rust 使用#
use monty::{MontyRun, MontyObject, NoLimitTracker, PrintWriter};
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()], vec![]).unwrap();
let result = runner.run(vec![MontyObject::Int(10)], NoLimitTracker, &mut PrintWriter::Stdout).unwrap();
核心 API#
Monty(code, inputs, external_functions): 主入口类MontyRun: Rust 侧的运行器封装MontySnapshot: 执行中途的快照对象ResourceLimits: 资源限制配置对象.run(inputs, limits, external_functions): 同步执行.start(inputs): 启动执行,遇到外部函数时暂停.resume(return_value): 恢复执行.dump()/.load(): 序列化与反序列化
当前限制#
- 标准库受限:仅支持
sys,typing,asyncio;dataclasses与json即将支持 - 不支持第三方库:无法导入 Pydantic、NumPy 等
- 语法限制:暂不支持
class定义与match语句(计划中)
适用场景#
- AI Agent 的工具调用(LLM 写代码调用工具而非生成 JSON)
- 需要极速启动的 Serverless 或无状态计算环境
- 需要在不可信代码执行与严格资源控制之间取得平衡的场景
- 长任务的中断与恢复(如 Human-in-the-loop 交互)
相关生态#
- PydanticAI(计划集成 Monty 实现 code-mode)
- 参考:Cloudflare Codemode、Anthropic Programmatic Tool Calling、Hugging Face Smol Agents