Rust API reference¶
This page documents the application-facing vsh facade. Rustdoc remains the
exhaustive source for every re-exported lower-level field and error variant.
Use the complete Rust cookbook for a compiled example. Unlike Python,
the Rust preview API accepts a borrowed RunRequest; it does not emulate Python's
source-string overload. The guest vsh_* surface is included in VSH.
The AgentJson compatibility mode, extra host materialization limits and nested
Monty vsh_bash support below are unreleased development-checkout additions.
Constants and diagnostics¶
VERSION is shared with the Python wheel and worker. engine_kind() returns "rust".
RuntimeConfig¶
let config = RuntimeConfig::new(workspace_root)
.with_data_directory(trusted_data_root)
.with_worker_path(worker)
.with_max_idle_workers(4)
.with_policy_profile(PolicyProfile::Strict)
.with_result_compatibility(ResultCompatibility::Native);
| Builder/accessor | Purpose |
|---|---|
new(workspace_root) |
Balanced configuration with protected .vsh-runtime/data |
with_data_directory(path) |
Select a trusted external durable-data capability |
with_worker_path(path) |
Select the exact supervised worker executable |
with_bash(BashConfig) |
Opt into the separate bounded Bash frontend (bash feature) |
with_max_idle_workers(count) |
Bound reusable clean workers; zero disables pooling |
with_result_compatibility(kind) |
Require Native, Python, or pre-commit AgentJson result compatibility |
with_in_process_execution() |
Trusted-only correctness/benchmark harness |
with_virtual_root(root) |
Change the synthetic absolute namespace shown to Monty |
with_policy(policy) |
Supply a custom validated deterministic policy |
with_policy_profile(profile) |
Select balanced, strict, or paranoid presets |
with_snapshot_limits(limits) |
Bound metadata traversal plus aggregate/per-file lazy host capture |
with_commit_config(config) |
Replace trusted commit/recovery ceilings |
with_store_config(config) |
Replace durable transaction-log ceilings |
with_artifact_limits(limits) |
Replace pending-artifact and cache ceilings |
with_commit_hook(hook) |
Bind a hook identity, scope, approval lifetime, and feedback bound |
workspace_root() |
Return the host workspace root |
data_directory() |
Return the trusted artifact root |
worker_path() |
Return the worker path or None in trusted in-process mode |
policy() |
Borrow the deterministic transaction policy |
Builder values contribute to runtime configuration identity where security relevant.
SnapshotLimits::max_materialized_bytes (64 MiB) and
max_materialized_file_bytes (4 MiB) bound host reads including content captured during
canonical diff generation. They are separate from guest read counters. Nested
vsh_bash(code) is enabled by the same bash feature and with_bash configuration as
top-level Bash; it borrows the current VFS and budget, not another Runtime.
Idle-pool capacity is not an admission limit on concurrent calls. Reusing a runtime
retains clean workers and capabilities, but every execution captures a fresh snapshot.
RunRequest<'a>¶
pub struct RunRequest<'a> {
pub code: &'a str,
pub language: Language,
pub intent: Option<&'a str>,
pub mode: RunMode,
pub detail: ReceiptDetail,
pub budget: ExecutionBudget,
}
RunRequest::new(code) creates a compact preview with default limits. Chain
with_language, with_intent, with_mode, with_detail, and with_budget to replace one choice.
Language::Monty is the default; Bash requires explicit host configuration.
Modes and detail¶
Preview does not apply user-file changes; runtime metadata/storage can still be written.
Auto commits only deterministic AutoApproved work.
Compact omits per-path entries while retaining identity and counts; Full retains the
complete bounded canonical diff.
Runtime¶
| Method | Result | Contract |
|---|---|---|
Runtime::open(config) |
Runtime |
Establish capabilities, stores, worker supervision, and startup recovery |
startup_recovery() |
&RecoveryReport |
Inspect recovery performed during open |
run(request) |
Receipt |
Execute according to request mode |
preview(request) |
Receipt |
Execute without applying proposed user-file changes |
discard_preview(id) |
bool |
Release a process-local auto-approved artifact |
approve(id, principal, issued, expires) |
TransactionRecord |
Bind an independent time-limited approval |
commit(id, now) |
Receipt |
Single-use reserve, revalidate, apply, verify |
recover() |
RecoveryReport |
Resolve bounded durable commit state |
transaction(id) |
TransactionRecord |
Read current durable lifecycle state |
prepare_commit(id) |
CommitPreparation |
Freeze an exact hook event without invoking host code |
resolve_commit(preparation, decision, now) |
CommitResolution |
Revalidate and apply one typed hook decision |
fail_hook(preparation) |
() |
Move an interrupted automatic approval into pending review |
All fallible methods return Result<_, VshError>.
Auto-approved preview IDs must be consumed by the same live runtime. The default
fail-closed retention caps are 64 artifacts and 128 MiB encoded bytes. Discard completed
analysis too. Pending approval artifacts are durable and can survive a compatible
runtime reopen; approve binds a PrincipalId but does not authenticate its owner.
Commit hooks¶
HookedRuntime<H: CommitHook> is the synchronous Rust convenience owner. The default
HookScope::ReviewRequired invokes H only for deterministic policy escalations;
HookScope::AllRequests also includes successful read-only and auto-approved
simulations. Hard policy denial never invokes a hook.
Handlers receive an immutable RequestEvent containing the canonical diff, ordered
effects, risk evidence and all transaction-binding digests. They return
HookDecision::{FollowPolicy, Approve, Review, Reject}. Review uses the existing
PendingApproval state and carries feedback in HookDecisionRecord; there is no
separate review-only lifecycle state.
Async Rust hosts should call prepare_commit, await their own handler outside VSH
locks, then call resolve_commit. If handler execution fails, call fail_hook before
propagating the error. Direct Runtime::commit cannot bypass a configured applicable
hook.
HookConfig::with_max_content_bytes(maximum) opts into immutable content evidence;
the default is zero. When the hook is in scope, VSH captures eligible bounded before
content before final binding, then recomputes the canonical diff and policy. Native
content-read permissions also govern review capture and delivery.
RequestEvent::contents contains ReviewContent { path, blob, bytes } for canonical
before/after states and observed content reads. content_complete distinguishes full
content coverage from structural evidence_complete; oversized, stamped or protected
content must not be assumed reviewed. Bytes are loaded from hash-verified blobs, not
from current host paths during handler execution.
A valid HookDecision::Approve directly approves pending work and attempts its exact
commit. An additional human approval is not required. The Python
LLM commit judge uses this same native protocol; Rust
applications can call their chosen model/service inside their own handler without
adding a provider dependency to the core.
Receipt¶
pub struct Receipt {
pub transaction: TransactionId,
pub base_snapshot: SnapshotId,
pub state: TransactionState,
pub decision: RuntimeDecision,
pub diff: DiffDigest,
pub changed_paths: usize,
pub changes: Vec<DiffEntry>,
pub output: ExecutionOutput,
pub execution: ExecutionStats,
pub timings: StageTimings,
pub commit: Option<CommitReceipt>,
}
RuntimeDecision is one of:
Denied(DenyManifest);AutoApproved;PendingApproval(RiskManifest).
Pattern-match the decision rather than parsing its display text.
diff is a digest. Each full DiffEntry includes path, kind, before and after
NodeState values, not text hunks. ExecutionOutput::Monty { value, stdout } retains
the typed MontyObject, whereas Python
projects it to a Python object. Native compatibility can represent values the pinned
Python converter cannot; choose ResultCompatibility::Python when that projection is
part of your downstream contract.
ExecutionOutput::Bash(BashResult) carries profile, exit_code and authoritative
Vec<u8> stdout/stderr. Use output.language(), output.monty_value(),
output.stdout_bytes() and output.stderr_bytes() for borrowed access.
The old Rust receipt.value / receipt.stdout fields move under receipt.output;
Python's existing properties remain available. See bounded Bash.
ExecutionCancellation is a one-request shared handle. run_cancellable,
commit_cancellable and resolve_commit_cancellable accept it. cancel() returns
false once commit has entered; after entry, the actual commit/recovery result wins.
discard_cancelled(id) is ownership-scoped host cleanup for an undelivered receipt:
ephemeral artifacts are dropped; durable automatic approvals move to pending review.
StageTimings¶
All fields are nanoseconds measured with a monotonic clock:
| Field | Includes |
|---|---|
snapshot_ns |
Fresh capability-rooted metadata traversal and lazy snapshot construction |
execute_ns |
Monty, IPC, typed VirtualFs calls and their call-policy checks |
diff_ns |
Canonical diff freeze |
policy_ns |
Deterministic policy evaluation |
bind_and_store_ns |
Artifact binding and lifecycle writes |
commit_ns |
Committer revalidation, application and verification; excludes preceding persistence, plan creation and reservation |
total_ns |
Complete run elapsed time; separate promotion retains preview total plus measured commit interval |
Measure outer wall time for complete commit() API latency. Its receipt total does
not include reviewer wait time and is not a stopwatch for just that API invocation.
ExecutionBudget¶
ExecutionBudget aliases vsh_monty::ExecutionLimits and has public fields for source
bytes, duration, recursion, memory, typed OS plus high-level VSH calls, read/write bytes,
per-call I/O, path bytes, directory entries, stdout, returned value, and exception
payload. Prefer struct update syntax from Default so later compatible fields receive
safe defaults. vsh_monty::MONTY_VSH_TOOL_NAMES exposes the stable in-sandbox function
names; see VSH functions inside Monty.
ArtifactLimits¶
Trusted-host bounds for durable pending artifacts:
- total encoded artifact bytes;
- encoded result and retained stdout;
- canonical entries and dependencies;
- one-path bytes;
- process-local preview count and aggregate encoded bytes.
These do not replace execution budgets; they constrain the artifact VSH retains after execution.
Monty's guest duration is cumulative bytecode time. Bash applies it to the interpreter and parser timeout, alongside the parent's watchdog. The heap cap applies to the supervised worker, not total parent-process RSS. The guest duration alone is not an end-to-end request deadline. For all defaults and measurement scope, see policies and budgets.
VshError¶
VshError is #[non_exhaustive]. Important categories include data-directory,
blob-store, commit, execution, VFS, state-store, approval, artifact, result-compatibility,
unsafe-overlap, binding mismatch, recovery conflict, missing/duplicate pending artifact,
ephemeral capacity, and poisoned pending state.
Match categories you can handle and keep a fallback arm:
match runtime.commit(transaction, now_ms) {
Ok(receipt) => consume(receipt),
Err(vsh::VshError::Commit(error)) => report_commit_error(error),
Err(other) => report_runtime_error(other),
}
Do not use formatted error strings as state-machine input. Stable typed variants and sources are the API contract.
Re-exported lower-level surfaces¶
The facade re-exports canonical types from vsh-types, vsh-vfs, vsh-policy,
vsh-monty, vsh-store, and vsh-commit. Use them to configure the facade or process
receipts. Constructing a parallel commit path from lower-level parts defeats the
single-writer architecture and is not recommended.