Skip to content

Module map

The workspace declares seven members (Cargo.toml:2-9), and the sections below run in the dependency order of the system-overview.md flowchart, bottom-up: the wire contract first, then the two crates that compile against it, then the three surfaces over the client, then the checked model (docs/architecture/system-overview.md:79-97). Each crate’s file list is its src/ tree ranked by size and by how many other files reference it; a crate’s tests/ tier is excluded so the source files a reader is looking for are not crowded out, since agentd/tests/turmoil_transport.rs alone is 2,163 lines. Files belonging to no crate are collected under Supporting code at the end.

protocol is the wire contract expressed as Rust types, split into exec, fs, health, and hook (protocol/src/lib.rs:29-32). The daemon and every Rust client of it compile against the same definitions, so a renamed field breaks compilation on whichever side has not caught up rather than surfacing as a consumer’s runtime bug (protocol/src/lib.rs:10-12). Membership is decided by one rule — pure data that travels on the wire is admitted and machinery for making it travel is not, which is why the SSE event payloads live here and the stream that emits them does not (protocol/src/lib.rs:16-21). Every type derives both halves of serde even where one side needs only one, because the missing half is what a client would otherwise hand-write, and docs/schema.json is generated from those same attributes under both contracts and byte-compared in CI (protocol/src/lib.rs:23-27).

  • protocol/src/exec.rs (496 LOC)
  • protocol/src/lib.rs (68 LOC)
  • protocol/src/hook.rs (380 LOC)
  • protocol/src/health.rs (259 LOC)
  • protocol/src/fs.rs (92 LOC)

agentd is the in-VM daemon supplying the exec and file-transfer APIs AWS Lambda MicroVMs does not have (agentd/src/lib.rs:4-7). Its twelve modules divide by defect class rather than by HTTP surface: state owns the one-shot bootstrap, auth decides authorization before a body byte is read, exec owns idempotent start with ack-gated release, and fs owns streaming tar (agentd/src/lib.rs:31-42). The trust boundary is the crate’s organizing fact — the platform’s own /run hook arrives from 127.0.0.1, indistinguishable at the socket level from a request sent by a process inside the VM, so source-address filtering would reject a legitimate bootstrap and the one-shot property is the only defense left (agentd/src/lib.rs:11-16). routes.rs assembles the router by walking surface_docs, the same twenty-endpoint list /v1/schema publishes, so a documented route with no handler panics at startup, and each endpoint’s declared auth mode decides which of the two routers it joins (agentd/src/routes.rs:31-35, agentd/src/routes.rs:48-58, agentd/src/routes.rs:371, docs/schema.json:497-1154).

  • agentd/src/exec.rs (3798 LOC)
  • agentd/src/fs.rs (2654 LOC)
  • agentd/src/schema.rs (929 LOC)
  • agentd/src/routes.rs (993 LOC)
  • agentd/src/identity.rs (724 LOC)
  • agentd/src/state.rs (592 LOC)
  • agentd/src/disk.rs (435 LOC)
  • agentd/src/config.rs (196 LOC)

microvms-core is the client library and the workspace’s largest crate, holding the control plane, the in-VM session client, the cost engine, and every trap closure (microvms-core/src/lib.rs:2-3). Its own doc comment splits it in two: error, region, sizing, hooks, and constants are the foundation, while cost, control, session, and sandbox are the product surface (microvms-core/src/lib.rs:59-65). Each of the seventeen measured platform findings is spent once here so no caller has to measure it again, and every closure is ranked on a strength ladder where S1 means the mistake cannot be written down at all (microvms-core/src/lib.rs:7-14, microvms-core/src/lib.rs:23-40). cost.rs is the largest file in the repository and carries the rule that makes the rest of it legible — unknown is not zero, so Amount::Unpriced is a distinct variant a consumer has to match on rather than a $0.00 line (microvms-core/src/cost.rs:22-27) — and the crate re-exports protocol so consumers name wire types through here instead of depending on the contract crate (microvms-core/src/lib.rs:79-81). One module sits deliberately above the generic lifecycle: agents is the L3 layer, a dated two-row profile table (Claude Code, Codex), an AgentVm that derives an image, launches with egress, and provisions Bedrock access, and agents::bedrock, which mints the bearer token in process (microvms-core/src/agents/mod.rs, docs/AGENT-VMS.md). Its free functions (image_request_for, launch_request_for, install_access, prompt) are what the bindings drive, because their sandbox sits behind a lock one AgentVm cannot own.

  • microvms-core/src/cost.rs (4156 LOC)
  • microvms-core/src/control/image.rs (3812 LOC)
  • microvms-core/src/session/exec.rs (1712 LOC)
  • microvms-core/src/control/microvm.rs (2467 LOC)
  • microvms-core/src/sandbox.rs (2643 LOC)
  • microvms-core/src/agents/mod.rs (1182 LOC)
  • microvms-core/src/control/ops.rs (2491 LOC)
  • microvms-core/src/control/mod.rs (1737 LOC)
  • microvms-core/src/session/mod.rs (1293 LOC)

microvms-cli builds the microvm binary: twenty-eight subcommands in lifecycle order over microvms-core, and nothing the library does not do (microvms-cli/src/cli.rs:83, microvms-cli/src/main.rs:2). Thinness is checked three ways rather than intended — the direct dependency set contains none of twelve denylisted transport and signing crates, no source file here names a transport or a control-plane operation, and every AWS-touching command must fail when the library seam is made to refuse (microvms-cli/src/main.rs:10-13, microvms-cli/tests/thinness.rs:66). A coding agent is a first-class consumer, so microvm manifest emits the whole command tree with its option domains, exit codes, and envelope schema generated from the parser, and every command writes exactly one envelope object to stdout with progress on stderr (microvms-cli/src/main.rs:17-21). There is no lib target, which is why the modules are declared in main.rs, and guards.rs — the crate’s largest file — holds the three guards that have to inject a refusing seam from inside the crate and so compiles only under cfg(test) (microvms-cli/src/main.rs:23-28, microvms-cli/src/guards.rs:12-20).

  • microvms-cli/src/guards.rs (7192 LOC)
  • microvms-cli/src/cli.rs (3024 LOC)
  • microvms-cli/src/exit.rs (682 LOC)
  • microvms-cli/src/commands/attached.rs (3037 LOC)
  • microvms-cli/src/commands/lifecycle.rs (2620 LOC)
  • microvms-cli/src/render.rs (1018 LOC)
  • microvms-cli/src/seam.rs (620 LOC)
  • microvms-cli/src/envelope.rs (593 LOC)

microvms-py is the PyO3 binding over microvms-core: a total, thin mapping where every public core constructor gets one binding constructor and no arithmetic or coercion surface the core does not have (microvms-py/src/lib.rs:6-11). No validation lives here — no range check, no state check, no region check, no size check — because a guard added in a binding is the copy every Python caller hits and the copy nothing else tests (microvms-py/src/lib.rs:12-18). Four closures a binding could give away for free are each stopped by an absent surface rather than an added check: no __float__ on a dollar amount, no __new__ on a duration, no region string on any method, and the two hook timeouts as separate #[pyclass]es so transposing them is a TypeError before any Rust runs (microvms-py/src/lib.rs:20-40). Methods are synchronous over the async core, blocking on one shared multi-thread tokio runtime with the GIL released first (microvms-py/src/lib.rs:42-46), and module membership is declared inside the #[pymodule] mod so the committed microvms.pyi is a function of this file and mise run stubs:check fails when the two disagree (microvms-py/src/lib.rs:98-101). agents.rs is the L3 layer as Python sees it: AgentVm, AgentSpec, and BearerToken over the same Arc<Mutex<Sandbox>> every session shares, driving the core’s free functions with the specs kept beside the lock (microvms-py/src/agents.rs).

  • microvms-py/src/cost.rs (1124 LOC)
  • microvms-py/src/sandbox.rs (854 LOC)
  • microvms-py/src/agents.rs (674 LOC)
  • microvms-py/src/exec.rs (631 LOC)
  • microvms-py/src/session.rs (707 LOC)
  • microvms-py/src/errors.rs (226 LOC)
  • microvms-py/src/lib.rs (145 LOC)
  • microvms-py/src/hooks.rs (117 LOC)
  • microvms-py/src/runtime.rs (92 LOC)

microvms-js is the napi-rs binding over the same core under the same thin-mapping and no-validation rules as the Python side, plus one module the Python side has no twin for — process, the same exec seen as two byte streams for a consumer shaped like the AI SDK’s SandboxProcess (microvms-js/src/lib.rs:6-17, microvms-js/src/lib.rs:72-74). Its single most important decision is #[napi] classes rather than #[napi(object)] for anything carrying a closure: #[napi(object)] converts by structure, so { seconds: 3600 } would satisfy a RunHookTimeout and { amount: 1.5 } an EstimatedUsd, which is precisely the coercion those types exist to prevent (microvms-js/src/lib.rs:19-35). JS coerces more eagerly than Python, so the money type carries no valueOf, no toJSON, and no Symbol.toPrimitive — the figure comes out only through .amount, a string (microvms-js/src/lib.rs:39-42). Async maps straight through with no block_on bridge, at the cost of the one divergence from the Python twin — napi’s async rejection path is typed over its own closed Status enum, so a caller branches on err.cause.message rather than err.code (microvms-js/src/lib.rs:58-67) — and the generated index.js, index.d.ts, and .node addon are untracked, so they are absent from the list below (.gitignore:27-29). agents.rs is the L3 layer as JS sees it, the twin of the Python file over tokio’s mutex; BearerToken is a #[napi] class rather than an object because it carries a secret, so JSON.stringify gives {} and a look-alike object is rejected by napi’s conversion (microvms-js/src/agents.rs).

  • microvms-js/src/cost.rs (1034 LOC)
  • microvms-js/src/session.rs (675 LOC)
  • microvms-js/src/exec.rs (458 LOC)
  • microvms-js/src/sandbox.rs (680 LOC)
  • microvms-js/src/agents.rs (609 LOC)
  • microvms-js/src/process.rs (544 LOC)
  • microvms-js/src/region.rs (139 LOC)
  • microvms-js/src/lib.rs (98 LOC)
  • microvms-js/src/errors.rs (158 LOC)

model builds the agentd-model crate, an executable specification rather than daemon code: a state machine whose reachable states stateright enumerates exhaustively, plus the safety properties the real daemon must uphold (model/Cargo.toml:2, model/src/lib.rs:3-9). It has one dependency and no edge to any workspace member, because it models the protocol instead of importing it (model/Cargo.toml:9-10). The question it settles is whether an in-VM process can hijack the unauthenticated /run bootstrap hook, and it prices the unenforced invariant instead of asserting it: Config::attacker_before_bootstrap toggles the assumption that no in-VM workload runs before bootstrap, so the model reports both that the attacker never obtains authority while the assumption holds and the concrete path by which it does once the assumption breaks (model/src/lib.rs:20-34). client.rs is the deliberate sibling covering what microvms-core’s Sandbox may do from outside the VM, where State::wire counts the calls the client issued so a property can say no resume ever fires once was_terminated holds (model/src/client.rs:2-9, model/src/client.rs:23-30).

  • model/src/client.rs (982 LOC)
  • model/src/lib.rs (658 LOC)
  • model/Cargo.toml (17 LOC)

Verification tooling, generated surfaces, and requirements data. None of it is a workspace crate (Cargo.toml:2-9), and none of it is a module under the enumeration rule that skips tooling-only paths.

  • conformance/run_rs.py (5055 LOC)
  • microvms-py/microvms.pyi (1759 LOC)
  • scripts/check-model-drift.py (1089 LOC)
  • spec/core.symspec.json (1049 LOC)
  • scripts/check-live-rates.py (625 LOC)
  • scripts/check-live-wiring.py (450 LOC)
  • scripts/generate-py-stubs.py (345 LOC)
  • scripts/check-lint-coverage.py (292 LOC)
  • conformance/infra/main.tf (281 LOC)
  • spec/microvms-core-kickoff.md (175 LOC)
  • scripts/verify-clean.py (589 LOC)
  • examples/coding-agents-on-bedrock/run.sh (145 LOC)
  • spec/agentd.symspec.json (117 LOC)
  • scripts/check-license-headers.py (131 LOC)
  • examples/coding-agents-on-bedrock/Dockerfile (51 LOC)

Related: System overview · Data flow · Contract map · Impact analysis · Tech debt · CLI reference