adk_codeact_monty/lib.rs
1//! A Python [`CodeRuntime`] for the ADK-Rust [`CodeActAgent`], backed by
2//! [Pydantic Monty](https://github.com/pydantic/monty) — a minimal, secure,
3//! Rust-native Python interpreter built for running LLM-generated code.
4//!
5//! [`MontyRuntime`] lets a `CodeActAgent` *act by writing Python*: the model emits a
6//! script each turn, invokes your [`Tool`](adk_core::Tool)s with the built-in
7//! `call_tool("name", {"arg": value})` function, composes their results with real
8//! control flow, and returns a tagged value. Monty executes that script
9//! in-process in microseconds, with no container and no subprocess — and can
10//! snapshot a paused run to bytes, which is exactly what the CodeAct
11//! suspend/resume model (HITL confirmation, long-running tools, durable
12//! checkpoints) requires.
13//!
14//! # OS access
15//!
16//! Operating-system effects a script attempts — filesystem reads/writes,
17//! `os.getenv`/`os.environ`, and `date.today()`/`datetime.now()` — are serviced
18//! in-place by the runtime against a host-controlled [`OsAccess`] policy. They
19//! are **not** tools: they never pause the agent loop. By default a runtime is
20//! fully sandboxed (no filesystem access, empty environment), but you can grant
21//! a script specific read-only or read-write paths and an explicit environment
22//! map:
23//!
24//! ```no_run
25//! use adk_codeact_monty::{MontyRuntime, PathAccess};
26//!
27//! let runtime = MontyRuntime::builder()
28//! .allow_path("/data", "/srv/agent/data", PathAccess::ReadOnly)
29//! .allow_path("/out", "/srv/agent/out", PathAccess::ReadWrite)
30//! .environ_var("PROJECT", "acme")
31//! .build();
32//! # let _ = runtime;
33//! ```
34//!
35//! Network and subprocess access have no Monty OS-call surface and remain
36//! unavailable regardless of policy.
37//!
38//! # Quick start
39//!
40//! ```no_run
41//! use std::sync::Arc;
42//! use adk_agent::codeact::CodeActAgent;
43//! use adk_codeact_monty::MontyRuntime;
44//! # use adk_core::Llm;
45//! # fn wire(model: Arc<dyn Llm>) -> Result<(), Box<dyn std::error::Error>> {
46//! let agent = CodeActAgent::builder()
47//! .name("python_agent")
48//! .model(model)
49//! .runtime(Arc::new(MontyRuntime::new()))
50//! .instruction("Solve the task by writing Python.")
51//! // .tool(Arc::new(MyTool))
52//! .build()?;
53//! # let _ = agent;
54//! # Ok(())
55//! # }
56//! ```
57//!
58//! # Resource limits
59//!
60//! Cap a script's time or memory with the builder — limits ride
61//! along inside a serialized continuation, so a resumed run stays bounded:
62//!
63//! ```
64//! use std::time::Duration;
65//! use adk_codeact_monty::MontyRuntime;
66//!
67//! let runtime = MontyRuntime::builder()
68//! .max_duration(Duration::from_secs(2))
69//! .max_memory(64 * 1024 * 1024)
70//! .build();
71//! # let _ = runtime;
72//! ```
73//!
74//! [`CodeActAgent`]: adk_agent::codeact::CodeActAgent
75//! [`CodeRuntime`]: adk_agent::codeact::CodeRuntime
76
77#![warn(missing_docs)]
78
79mod os_access;
80mod prompt;
81mod runtime;
82
83pub use os_access::{OsAccess, OsAccessBuilder, PathAccess};
84pub use runtime::{MontyRuntime, MontyRuntimeBuilder};
85
86/// Re-export of Monty's resource-limit configuration, for
87/// [`MontyRuntimeBuilder::resource_limits`]. Sourced through `adk-code`'s
88/// Monty re-exports, so the Monty release is pinned exactly once.
89pub use adk_code::embedded_python::monty_types::ResourceLimits;