Rust SDK
The Rust SDK at crates/mvmforge-sdk/ is the build-time
counterpart to the Python and TypeScript SDKs (see
ADR-0015).
It uses an explicit builder pattern rather than decorators — no globals, no implicit registration — and produces canonical IR byte-identical to the Python and TS SDKs for the same logical workload, gated by the cross-SDK corpus (ADR-0003 §7).
Install
The SDK ships as a workspace crate inside this repo. From a Rust
project that depends on mvmforge:
[dependencies]mvmforge-sdk = { path = "path/to/mvmforge/crates/mvmforge-sdk" }A published crates.io release is part of ADR-0015 Phase 2; until
then, use a path or git dependency.
Authoring
use mvmforge_sdk::*;
fn main() -> Result<(), Box<dyn std::error::Error>> { let wl = workload("hello") .app( app("hello") .source(local_path(".")) .image(nix_packages(["python312"])) .entrypoint(entrypoint_command(["python", "-m", "hello"])) .resources(resources(1, 256, 512)) .build()?, ) .build()?; emit(&wl)?; Ok(())}The builders enforce required-field presence at .build() time
so the rest of the SDK can take typed values. Errors surface as
BuildError and EmitError.
Function entrypoints
let ep = entrypoint_function( /* module */ "math", /* function */ "add",).language("python") // defaults to "rust"; cross-language manifest authoring.format(Format::Json).args_schema(args) // optional JSON Schema.return_schema(ret) // optional JSON Schema.build()?;Constructor helpers
Mirroring the Python and TypeScript surfaces:
| Concept | Helpers |
|---|---|
| Sources | local_path, nix_derivation, oci_image |
| Images | nix_packages, oci_base |
| Entrypoints | entrypoint_command, entrypoint_function |
| Resources | resources(cpu_cores, memory_mb, rootfs_size_mb) |
| Network | network, egress, host_port, dns_none/system/resolver |
| Dependencies | python_deps[_with], node_deps[_with], no_deps |
Two-layer architecture
Per ADR-0003:
- Lower layer — IR types re-exported as-is from
mvmforge-ir. No codegen needed; the Rust IR types are alreadyserde + JsonSchema + deny_unknown_fields, which satisfies the schema-driven contract that Python and TypeScript SDKs achieve viadatamodel-code-generator/json-schema-to-typescript. - Upper layer — hand-authored builders rooted at
workloadandapp.
Imports under mvmforge_sdk::Ir* re-export the IR types under
Ir-prefixed aliases for callers who want to deal with raw types
directly.
Subprocess contract
Per ADR-0002:
emit(&workload) honors MVMFORGE_IR_OUT. When set, writes the
canonical IR to that path and returns Ok(()). When unset,
writes to stdout. Validation errors and write errors return
non-zero through EmitError.
emit_json(&workload) is the in-process variant — returns the
canonical IR as a String for callers that want to post-process
before writing.
CLI dispatch
mvmforge emit <entry> recognizes Rust entries via two paths:
- A
.rsfile with amain()— emits viacargo runagainst the containing project. - A
Cargo.tomldirectory — emits viacargo run --manifest-path <Cargo.toml>against the project’s default binary.
Per-language dispatch lives in crates/mvmforge/src/sdk_dispatch.rs.
Adding a new SDK is a new dispatch arm + a new corpus runner.
Out of scope (v1)
ADR-0015 carves these out for future ADRs / plans:
- Function-entrypoint Rust language support (a workload whose
entrypoint is a Rust function dispatched in-VM by a hardened
wrapper at
nix/wrappers/rust.rs). Build-time DSL only in v1. - Runtime SDK (
Session,RemoteFunction). - Procedural-macro sugar over the builder API.
See also
- ADR-0015 — Rust SDK — design rationale.
- Python SDK and TypeScript SDK for the matching surfaces.
- Workload IR for the canonical shape both layers produce.