Use the SDKs to launch remote sandboxes for agents, execute tools, transfer files, and collect results. Start with a complete example in the SDK tutorial, or the package guide for Rust, Python, or Node/TypeScript.
| Task | API |
|---|---|
| Launch a VM from an existing image | Sandbox and RunRequest |
| Execute a command or transfer files | Session |
| Stream, wait for, or cancel a command | ExecHandle |
| Run Claude Code or Codex with Bedrock access | AgentVm |
| Terminate and check cleanup | TeardownOpts and TeardownReport |
| Build images or call the control plane directly | ControlPlane and CreateImageRequest |
microvms-core is the Rust client. The Python microvms package and Node
microvms package expose bindings to it. Core re-exports protocol, the shared
wire types. This page is a selected API reference; see
Rust API docs for the complete Rust surface and
CLI reference for microvm commands.
Launch networking
Section titled “Launch networking”Rust RunMicrovmRequest and RunRequest accept egress_network_connectors.
Python run accepts egress_network_connectors=[arn]; Node run accepts
egressNetworkConnectors: [arn]. These attach existing VPC connector ARNs;
creation and VPC configuration use the separate AWS Lambda core API.
Custom connectors conflict with the managed egress option. Supplying an ARN
does not certify isolation: no internet egress requires a VPC without an IGW
or NAT gateway and no alternative internet route. See Networking.
microvms-core
Section titled “microvms-core”#[derive(Debug, thiserror::Error)]#[error("{message}")]pub struct Error {A failure classified once at the point it is raised, deliberately a struct with a private body rather than an enum, because an enum over every raise site would make each new failure a breaking change for a binding that matched exhaustively.
microvms-core/src/error.rs:41-43
Region
Section titled “Region”#[derive(Clone, Debug, Eq, Hash, PartialEq)]pub enum Region {An AWS region, closed over the five that run MicroVMs plus a named escape hatch, so a typo’d region is a compile error rather than an AccessDeniedException carrying a null message.
microvms-core/src/region.rs:44-45
ErrorKind
Section titled “ErrorKind”#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]pub enum ErrorKind {The coarse failure classes, one per non-zero row of the CLI’s exit table, with the integer exit code left to the CLI because a library owning process exit codes would be a library with an opinion about being a process.
microvms-core/src/error.rs:126-127
SizeClass
Section titled “SizeClass”#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]pub enum SizeClass { Mib512, Mib1024, Mib2048, Mib4096, Mib8192,}The five documented size classes, named for the baseline a caller writes into minimumMemoryInMiB and deliberately not for the peak, since naming both would suggest the two are picked independently.
microvms-core/src/sizing.rs:118-125
Session
Section titled “Session”pub struct Session {The control API of one running MicroVM.
microvms-core/src/session/mod.rs:196
ControlPlane
Section titled “ControlPlane”pub struct ControlPlane {The control-plane client, holding its transport and clock behind Arc so a caller keeping one across tasks does not need a second credential chain.
microvms-core/src/control/mod.rs:171
Sandbox
Section titled “Sandbox”pub struct Sandbox {One MicroVM’s whole life: the state machine, the suspended window, and explicit teardown.
microvms-core/src/sandbox.rs:548
RunRequest
Section titled “RunRequest”let mut request = RunRequest::new().with_image(&image_arn);request.execution_role_arn = Some(execution_role_arn);let session = sandbox.run(request).await?;Use microvms_core::sandbox::RunRequest to launch an image containing agentd.
Pass the actual image ARN returned by a build; the SDK does not perform the CLI’s
friendly image-name lookup. Defaults are a ten-minute idle window, a ten-minute
suspended window, a one-hour maximum lifetime, and no auto-resume. Network
connector omission does not establish internet isolation; see launch networking
above. Wait for session.wait_until_ready before executing commands.
TeardownOpts and TeardownReport
Section titled “TeardownOpts and TeardownReport”let report = sandbox.terminate(TeardownOpts::default()).await;These types live in microvms_core::sandbox. Termination returns a report
instead of an error: inspect failures and undeleted. Defaults request VM
termination and retain the image and logs. Add .waiting_for_terminated() to the
options when the caller must observe the final state. Sandbox does not clean
up on drop, so call terminate on both success and failure paths; the
Rust quickstart shows that pattern.
AgentVm
Section titled “AgentVm”pub struct AgentVm {One VM with coding agents in it: the Sandbox plus the AgentSpecs it was built for, with image_request, build, launch_request, launch, install_access, prompt, and terminate as the L3 steps over the lifecycle. The free functions beside it (image_request_for, launch_request_for, install_access, prompt, installed_agents, spec_for) are the same steps for a caller holding the sandbox and the specs separately, which is how the bindings drive it; agents::bedrock::mint is the in-process Bedrock bearer token.
microvms-core/src/agents/mod.rs
WireKind
Section titled “WireKind”#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]pub enum WireKind {The daemon-side failure classes the conformance suite asserts on, several of which collapse onto one ErrorKind at the exit code rather than at the raise site.
microvms-core/src/error.rs:218-219
RunHookTimeout
Section titled “RunHookTimeout”#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]pub struct RunHookTimeout(u32);A timeout for the run, resume, suspend, or terminate hook, accepting 1..=60 seconds and offering no conversion from BuildHookTimeout.
microvms-core/src/hooks.rs:47-48
Transport
Section titled “Transport”pub struct Transport {A backend, the agent token, and the proxy auth every request needs, kept separate from Session because ExecHandle needs it and holding a whole session would make the two mutually recursive.
microvms-core/src/session/mod.rs:75
BuildHookTimeout
Section titled “BuildHookTimeout”#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]pub struct BuildHookTimeout(u32);A timeout for the ready or validate image-build hook, accepting 1..=3600 seconds, and a distinct type so a build-sized value cannot reach a field that caps at 60.
microvms-core/src/hooks.rs:53-54
EstimatedUsd
Section titled “EstimatedUsd”#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]pub struct EstimatedUsd(Decimal);Dollars derived from published rates and not the bill, with no From<EstimatedUsd> for f64, no Into, no Deref, and no as_f64, so laundering an estimate into a float does not compile.
microvms-core/src/cost.rs:513-514
ExecHandle
Section titled “ExecHandle”pub struct ExecHandle {One exec addressed by its caller-minted id, which is also the idempotency key, so rebuilding a handle with the same id after a process restart still addresses the same server-side exec.
microvms-core/src/session/exec.rs:214
RateTable
Section titled “RateTable”#[derive(Clone, Debug, Eq, PartialEq)]pub struct RateTable {The five us-east-1 rates, held privately so that pricing compute from the ARM rate is a property of the type rather than of a code path a caller can bypass.
microvms-core/src/cost.rs:838-839
CostReport
Section titled “CostReport”#[derive(Clone, Debug, Eq, PartialEq)]pub struct CostReport {Per-phase cost attribution for one sandbox, measured or projected, holding the rate table it was computed against so it stays reproducible after pinned_rates is updated.
microvms-core/src/cost.rs:1467-1468
ExecResult
Section titled “ExecResult”#[derive(Debug)]pub struct ExecResult { pub exec_id: String, pub phase: protocol::exec::Phase, /// `None` while running. Present once the child has exited. pub outcome: Option<protocol::exec::Outcome>,}An exec’s phase and, once it has one, its outcome — a thin wrapper over the daemon’s PollResponse rather than a re-modelling of it, so the two cannot disagree.
microvms-core/src/session/exec.rs:66-72
#[derive(Clone, Debug, Eq, PartialEq)]pub struct Image {A built image, and the log group the service created alongside it.
microvms-core/src/control/image.rs:58-59
protocol
Section titled “protocol”protocol::exec::Phase
Section titled “protocol::exec::Phase”#[derive(Clone, Copy, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]#[serde(rename_all = "snake_case")]pub enum Phase {An exec’s phase on the wire, with schemars reading the same #[serde(...)] attributes serde does so the published schema describes what the daemon actually emits.
protocol::health::Health
Section titled “protocol::health::Health”#[derive(Debug, Deserialize, JsonSchema, Serialize)]pub struct Health {The GET /v1/health response: daemon version, bootstrap state, disk pressure, whether startup identity repair degraded, and the exec-activity pair busy / execs.
protocol::exec::StartRequest
Section titled “protocol::exec::StartRequest”#[derive(Debug, Deserialize, JsonSchema, Serialize)]pub struct StartRequest {The POST /v1/exec/start body, whose command field is either an argv array or, with shell: true, a single script string.
protocol::exec::Outcome
Section titled “protocol::exec::Outcome”#[derive(Clone, Debug, Default, Deserialize, JsonSchema, Serialize)]pub struct Outcome {Captured output and exit status of a finished exec.
protocol::exec::PollResponse
Section titled “protocol::exec::PollResponse”#[derive(Debug, Deserialize, JsonSchema, Serialize)]pub struct PollResponse { pub exec_id: String, pub phase: Phase, #[serde(skip_serializing_if = "Option::is_none")] #[serde(flatten)] pub result: Option<Outcome>,}The GET /v1/exec/{id} body, which flattens the outcome into the response and omits it entirely while the exec is still running.
microvms-py
Section titled “microvms-py”The Python module is declared rather than assembled: a #[pymodule] mod microvms lists its members in #[pymodule_export] use statements, 30 classes and 12 functions (the agent layer’s AgentSpec, AgentVm, and BearerToken, with mint_bedrock_token, installed_agents, install_agent_access, prompt_agent, and agent_constants, arrived with docs/AGENT-VMS.md), so the macro can see the whole membership and maturin generate-stubs emits the real surface instead of a __getattr__ escape hatch (microvms-py/src/lib.rs:110-136). The exception hierarchy stays imperative in #[pymodule_init], because create_exception! builds its types at runtime and leaves no introspection record for #[pymodule_export] to carry (microvms-py/src/lib.rs:105-144). Every method is sync, blocking on one shared multi-thread tokio runtime with py.detach first (microvms-py/src/lib.rs:42-46). The generated stub and its PEP 561 marker are committed as microvms-py/microvms.pyi and microvms-py/py.typed, and mise run stubs:check fails when the committed stub no longer matches the pyo3 surface (mise.toml:216-218).
microvms-py Region
Section titled “microvms-py Region”#[pyclass(frozen, from_py_object, name = "Region", module = "microvms")]#[derive(Clone)]pub struct PyRegion {An AWS region, closed over the five that run MicroVMs plus a named escape hatch, exported to Python as Region.
microvms-py/src/region.rs:30-32
microvms-py Sandbox
Section titled “microvms-py Sandbox”#[pyclass(frozen, name = "Sandbox", module = "microvms")]pub struct PySandbox {One MicroVM’s whole life, with build_image, run, suspend, resume, and terminate as the five transitions and every state guard left in the core.
microvms-py/src/sandbox.rs:294-295
microvms-py Session
Section titled “microvms-py Session”#[pyclass(frozen, name = "Session", module = "microvms")]pub struct PySession {One running MicroVM’s control API, with the proxy auth handled for you.
microvms-py/src/session.rs:258-259
microvms-py EstimatedUsd
Section titled “microvms-py EstimatedUsd”#[pyclass( frozen, skip_from_py_object, name = "EstimatedUsd", module = "microvms")]#[derive(Clone, Copy)]pub struct PyEstimatedUsd {A dollar figure with no __float__, __int__, __index__, or __add__, whose amount answers a string, so float(usd) raises TypeError — the Python equivalent of the core’s missing impl.
microvms-py/src/cost.rs:169-176
microvms-js
Section titled “microvms-js”The Node surface has no barrel: every #[napi] item in the crate is exported, and index.d.ts plus the index.js loader and the compiled .node addon are generated by napi build and excluded from the repository as one platform’s build output (.gitignore:27-29). Two shapes appear side by side and mean different things: #[napi] on a struct is a JS class with methods, while #[napi(object)] is a copied plain object with no methods, which is how the same wire results that pyo3 renders as frozen classes arrive in Node (microvms-js/src/exec.rs:65-66, microvms-js/src/session.rs:48-49). Construction diverges from Python for a reason that is structural rather than stylistic: PySandbox has a #[new] constructor that blocks on the shared runtime (microvms-py/src/sandbox.rs:344-350), and a #[napi(constructor)] cannot be async, so the Node class is built through a static factory instead (microvms-js/src/sandbox.rs:411-415).
microvms-js Region
Section titled “microvms-js Region”#[napi]#[derive(Clone)]pub struct Region {An AWS region, closed over the five that run MicroVMs plus a named escape hatch, taken as an instance rather than a string everywhere on this surface.
microvms-js/src/region.rs:33-35
microvms-js Session
Section titled “microvms-js Session”#[napi]pub struct Session {One running MicroVM’s control API, with the proxy auth handled for you.
microvms-js/src/session.rs:269-270
microvms-js Sandbox
Section titled “microvms-js Sandbox”#[napi]pub struct Sandbox {One MicroVM’s whole life, with buildImage, run, suspend, resume, and terminate as the five transitions and every state guard left in the core.
microvms-js/src/sandbox.rs:394-395
microvms-js ExecProcess
Section titled “microvms-js ExecProcess”#[napi]pub struct ExecProcess {A long-running exec in the AI SDK’s SandboxProcess shape, built by Session.spawn and never by a constructor, and the one entry on this surface with no peer in microvms-py.
microvms-js/src/process.rs:192-193
The daemon serves 20 routes. All of them come from one list, surface_docs, which app walks to build the router and GET /v1/schema walks to publish the document (agentd/src/routes.rs:419-728). A route cannot be served unless it appears in that list, and a listed route with no handler panics at startup rather than serving an undocumented surface (agentd/src/routes.rs:110-142). Each row also declares its auth, which is what splits the router in two: Auth::Bearer rows go behind the token guard, Auth::Open and Auth::PlatformHook rows do not (agentd/src/routes.rs:51-59).
The six lifecycle hooks sit under a prefix fixed by the service, /aws/lambda-microvms/runtime/v1 (protocol/src/hook.rs:15). They are unauthenticated because the platform has no token to present, and a consumer must never call them.
POST /aws/lambda-microvms/runtime/v1/ready
Section titled “POST /aws/lambda-microvms/runtime/v1/ready”The image-build readiness probe, answering 200 even before bootstrap, because the question it answers is whether the daemon started.
POST /aws/lambda-microvms/runtime/v1/resume
Section titled “POST /aws/lambda-microvms/runtime/v1/resume”Acknowledged; the token, filesystem, exec records, and even backgrounded processes survive a suspend/resume cycle, but the guest’s view of time jumps, so any timeout or lease held by a running command expires at once.
POST /aws/lambda-microvms/runtime/v1/run
Section titled “POST /aws/lambda-microvms/runtime/v1/run”The one-shot token bootstrap and the optional launch environment beside it, both one JSON parse deeper than the request body inside runHookPayload, sharing the platform’s 4096-byte payload budget.
POST /aws/lambda-microvms/runtime/v1/suspend
Section titled “POST /aws/lambda-microvms/runtime/v1/suspend”Acknowledged and logged.
POST /aws/lambda-microvms/runtime/v1/terminate
Section titled “POST /aws/lambda-microvms/runtime/v1/terminate”Acknowledged; begins graceful shutdown with in-flight requests draining.
POST /aws/lambda-microvms/runtime/v1/validate
Section titled “POST /aws/lambda-microvms/runtime/v1/validate”The image-build validation probe, on the same reasoning as ready.
POST /v1/exec/start
Section titled “POST /v1/exec/start”Starts a command under a caller-minted exec_id, idempotent on that id, so a retry returns success without spawning a second child.
GET /v1/exec/{id}
Section titled “GET /v1/exec/{id}”Polls status and output, read-only, so polling never mutates the entry and output survives until an explicit ack.
POST /v1/exec/{id}/ack
Section titled “POST /v1/exec/{id}/ack”Releases output and enters TTL collection; only acked entries are ever collected, so output nobody read is never destroyed.
POST /v1/exec/{id}/kill
Section titled “POST /v1/exec/{id}/kill”Sends SIGTERM then SIGKILL to the whole process group rather than the direct child alone, because a shell that backgrounded a server leaves the interesting process outside the child pid.
POST /v1/exec/{id}/stdin
Section titled “POST /v1/exec/{id}/stdin”Writes to a child’s stdin or signals EOF, a separate request from the output stream so a dropped attach does not cost the ability to feed the process.
GET /v1/procs
Section titled “GET /v1/procs”Process accounting: every registered exec with its process group’s live pids, read from /proc inside the guest so the image needs no ps. child_exited: true beside a non-empty pids is a command that finished while something it backgrounded did not; reap echoes the start request’s reap_group_on_exit.
agentd/src/routes.rs
GET /v1/tcp
Section titled “GET /v1/tcp”A WebSocket relayed to 127.0.0.1:<port> in the guest, loopback-only, one connection per socket, with the outcome carried in close codes because the route leaves HTTP behind after its 101.
agentd/src/routes.rs
GET /v1/exec/{id}/stream
Section titled “GET /v1/exec/{id}/stream”Follows output as Server-Sent Events from a byte offset, resumable with ?offset=N; a body that ends without an exit event means the connection failed, not the command.
GET /v1/fs/file
Section titled “GET /v1/fs/file”Reads one file, or a 1-based inclusive line range of it, always streamed — an end_line past the last line reads through EOF without error, and omitting both bounds returns the whole file byte-identically.
PUT /v1/fs/file
Section titled “PUT /v1/fs/file”Writes one file, deliberately not confined to a root, because the same token authorizes exec and a root prefix would add no security while breaking harnesses that write to home directories and /etc.
GET /v1/fs/tar
Section titled “GET /v1/fs/tar”Downloads a tree as tar, packing symlinks as symlinks, which is the producing half of what extraction accepts.
PUT /v1/fs/tar
Section titled “PUT /v1/fs/tar”Uploads and extracts a tar under ?path=, the one confined write path because member paths come from the archive rather than the caller, mirroring the CPython tarfile data filter.
GET /v1/health
Section titled “GET /v1/health”Reports liveness, daemon version, bootstrap completion, and whether any exec is still running; busy exists so an orchestrator outside the VM can hold it alive, since the platform measures idleness by inbound traffic through a proxy that terminates outside the guest.
GET /v1/schema
Section titled “GET /v1/schema”Returns this document: every route, shape, status code, and operative limit.
See also
Section titled “See also”- contract map — 22 shared source citations
- impact analysis — 21 shared source citations
- business logic — 13 shared source citations
- system overview — 8 shared source citations
- debugging guide — 8 shared source citations