Skip to content

microvms: functions, constants, and exceptions

Everything microvms exports at module level that is not a class of its own: the functions, the constants, and the exception hierarchy. Import any of them with from microvms import ....

def agent_constants() -> dict

The layer’s fixed values, for a caller that wants to reason about the guest.

def build_unpriced_reason() -> str

Why the image build has no price, as the reason that lands on the line item.

def check_budget(report: CostReport, max_usd: str, on_breach: str) -> BudgetVerdict

Judges report’s total against a ceiling of max_usd (a decimal string, such as "1.50"), with on_breach ("warn" or "abort") saying what a breach does.

on_breach has no default, because a breach of a lower-bound total has already been exceeded by an unknown margin, and whether that warns or refuses is the caller’s call. Core’s Budget::check, the gate microvm cost --max-cost applies.

def compare_residency(
size: SizeClass,
hold_seconds: SupportsFloat | SupportsIndex,
cycles: SupportsIndex = ...,
*,
rates: RateTable | None = None,
) -> ResidencyComparison

The warm-pool argument, with its own counter-argument attached.

Leave cycles out and the comparison prices one suspend/resume cycle, the core’s default and the one microvm cost --compare applies: the per-cycle figure is what keeps the argument honest. A report’s suspend_resume_cycles defaults to none instead.

def core_version() -> str

The core crate’s version, for a doctor or manifest command to report.

The core’s version and not this crate’s: what a caller needs to know is which client they are talking through, and a binding version that drifted from it would be a second number nobody can act on.

def cost_constants() -> dict

The documented facts a caller may want to assert on, as strings and flags.

A dict rather than a class because it is a transcription of published constants, and the Python client publishes the same set. provenances and phases are here so a caller can enumerate the closed sets rather than hardcoding spellings.

def egress_posture_for(
egress: bool = False,
connectors: SupportsGetItem[int, str] | None = None,
deny_egress: bool = False,
*,
region: Region | None = None,
) -> str

The egress posture Sandbox.run with these options would report, without launching.

One of "open", "unsealed", "best-effort", or "sealed": the value the launched session’s egress_posture and the CLI envelope’s egressPosture carry. Raises the launch’s own InvalidArgError for options it would refuse. No AWS call and no credentials, so a harness can decide before a build whether a no-network task is satisfiable.

Only "sealed" is network isolation, and no option answers it: isolation needs a VPC egress connector and separately verified VPC routing without an internet gateway or NAT gateway. Omitting egress is "unsealed"; deny_egress is "best-effort". Without a region, each connector ARN is checked against the region it names.

def estimate_run(
size: SizeClass,
*,
running_seconds: SupportsFloat | SupportsIndex = 0.0,
suspended_seconds: SupportsFloat | SupportsIndex = 0.0,
image_gb: SupportsFloat | SupportsIndex | None = None,
image_retained_seconds: SupportsFloat | SupportsIndex | None = None,
suspend_resume_cycles: SupportsIndex = ...,
snapshot_gb: SupportsFloat | SupportsIndex | None = None,
launched: bool | None = None,
label: str | None = None,
rates: RateTable | None = None,
) -> CostReport

What a plan will cost, before spending anything (COST-10).

Takes plain seconds and marks every one of them projected. That is the difference from [run_report]: not the arithmetic, which is shared, but what the durations admit about themselves — and it is why this signature has no Duration parameter at all, so an accidentally-measured one is not something a caller can write.

Leave launched out and the core infers it: running time, or an image of non-zero size, so a plan of suspended time alone reads no launch snapshot. Leave label out and the report is labelled "estimate", what microvm cost --estimate labels the same plan (#255). Leave suspend_resume_cycles out and the plan counts none, as microvm cost --estimate does.

def install_agent_access(
session: Session,
agents: SupportsGetItem[int, AgentSpec],
token: BearerToken,
) -> None

Installs Bedrock access for agents into a running VM over session.

Three uploads (the environment file, Codex’s config when Codex is among the agents, the marker) and one root chown of /workspace to uid 1000. Re-runnable: a fresh token overwrites the same files, which is how a twelve-hour token is refreshed.

def install_agent_access_async(
session: Session,
agents: SupportsGetItem[int, AgentSpec],
token: BearerToken,
) -> None

The awaitable twin of install_agent_access.

def installed_agents(session: Session) -> list[AgentSpec]

The agents a running VM was provisioned with, read from its guest marker.

For a process holding only a session (Session.direct from the identifier triple): this is how a credential refresh learns which agents and models to re-provision. A VM with no marker is refused as a precondition, naming agent-up.

def installed_agents_async(session: Session) -> list[AgentSpec]

The awaitable twin of installed_agents.

def mint_bedrock_token(
region: Region,
*,
ttl_seconds: SupportsFloat | SupportsIndex | None = None,
) -> BearerToken

Mints a Bedrock bearer token from the default credential chain.

A SigV4 presign of POST https://bedrock.amazonaws.com/?Action=CallWithBearerToken, base64, prefixed bedrock-api-key- — the reference generator’s recipe, in process. ttl_seconds defaults to the ceiling, twelve hours; more is refused by the core.

def mint_bedrock_token_async(
region: Region,
*,
ttl_seconds: SupportsFloat | SupportsIndex | None = None,
) -> BearerToken

The awaitable twin of mint_bedrock_token.

def mint_bedrock_token_with_credentials(
region: Region,
*,
access_key_id: str,
secret_access_key: str,
session_token: str | None = None,
credentials_expires_at: SupportsFloat | SupportsIndex,
ttl_seconds: SupportsFloat | SupportsIndex | None = None,
) -> BearerToken

Mint with explicit STS credentials and their expiry without changing process env. credentials_expires_at is Unix seconds from STS Expiration. Secrets never enter repr.

def preflight(region: Region | None = None) -> PreflightReport

Whether a harness can launch in region (default: $AWS_REGION, $AWS_DEFAULT_REGION, then us-east-1), checked before it queues work.

Three checks: the region resolves (advisory outside Region.measured()), the credential chain resolves credentials (no AWS call), and one ListManagedMicrovmImages page answers in that region, the only AWS operation, free and read-only. A check after a failure is reported with ran=False and makes no call. Nothing billable, nothing mutating. It does not check roles, the artifact bucket, quotas, or VPC connectors, and there is no boto3 service-model check: this client speaks the API version it was built against, and the listing is the evidence the endpoint accepts it. Never raises; read report.ok.

def preflight_async(region: Region | None = None) -> PreflightReport

The awaitable twin of preflight. Never raises either; read report.ok.

def prompt_agent(
session: Session,
agent: AgentSpec,
task: str,
*,
timeout_sec: SupportsFloat | SupportsIndex | None = None,
exec_id: str | None = None,
permission_mode: str = 'agent-default',
reap_group_on_exit: bool = False,
) -> ExecHandle

Starts one task for agent over session and returns its handle. Does not wait.

Runs the agent’s headless command as uid 1000 in /workspace, sourcing the installed environment file. timeout_sec is the daemon-side budget for the agent process; exec_id is the idempotency key for a retry that must not spawn twice. permission_mode is agent-default or unrestricted. reap_group_on_exit stops residual children after the main agent exits. Neither option grants guest root.

def prompt_agent_async(
session: Session,
agent: AgentSpec,
task: str,
*,
timeout_sec: SupportsFloat | SupportsIndex | None = None,
exec_id: str | None = None,
permission_mode: str = 'agent-default',
reap_group_on_exit: bool = False,
) -> ExecHandle

The awaitable twin of prompt_agent.

def provision_agentd(
version: str | None = None,
state_dir: str | PathLike[str] | None = None,
binary: str | PathLike[str] | None = None,
) -> bytes

The agentd daemon binary for version (default: this client’s own), as bytes.

Answered from binary or $MICROVM_AGENTD when either names a file, else the version’s cache entry under state_dir (default: the CLI’s, so both share one cache), else the GitHub release asset, verified in-process against the release workflow’s Sigstore attestation or, only when GitHub can’t be reached for one, the release’s SHA256SUMS. A fetch that cannot be verified raises PreconditionError, and so does any binary that is not an aarch64 ELF. Neither gh nor curl is needed. Blocking: a fetch downloads a few MiB and can take seconds.

def provision_agentd_async(
version: str | None = None,
state_dir: str | PathLike[str] | None = None,
binary: str | PathLike[str] | None = None,
) -> bytes

The awaitable twin of provision_agentd.

def provision_agentd_report(
version: str | None = None,
state_dir: str | PathLike[str] | None = None,
binary: str | PathLike[str] | None = None,
) -> ProvisionedAgentd

provision_agentd, answering with the bytes and how they got here: the source, the verification, the path, the version, and the digest.

def provision_agentd_report_async(
version: str | None = None,
state_dir: str | PathLike[str] | None = None,
binary: str | PathLike[str] | None = None,
) -> ProvisionedAgentd

The awaitable twin of provision_agentd_report.

def run_report(
size: SizeClass,
*,
running: Duration | None = None,
suspended: Duration | None = None,
image_build: Duration | None = None,
image_gb: SupportsFloat | SupportsIndex | None = None,
image_retained: Duration | None = None,
suspend_resume_cycles: SupportsIndex = ...,
snapshot_gb: SupportsFloat | SupportsIndex | None = None,
launched: bool | None = None,
label: str | None = None,
rates: RateTable | None = None,
) -> CostReport

Per-phase attribution for one sandbox’s lifecycle.

Every duration parameter takes a [PyDuration] and not a number, which is what keeps the provenance label attached: passing seconds here would need this function to pick a provenance, and the one it would pick is the stronger claim.

today is the core’s CalendarDate::today_utc() rather than a parameter. The core takes it so a report is a pure function of its inputs and a test does not have to travel in time; a Python caller who needs that reaches for the core through Rust, and exposing a date here would be a knob whose only use is faking staleness.

Leave launched out and the core infers it: running time, or an image of non-zero size (a launch reads a snapshot, so claiming one adds a transfer line). Leave label out and the report is labelled "run". Leave suspend_resume_cycles out and the report counts none, so it has no suspend or resume line: a report claims only what the caller says happened. All three defaults are the core’s, the ones microvm cost applies.

def session_constants() -> dict

The daemon’s protocol constants, for a caller asserting against the wire contract.

def wrap_dockerfile(
task_dockerfile: str,
*,
port: SupportsIndex | None = None,
workdir: str | None = None,
inherit_workdir: bool = False,
) -> str

A task Dockerfile with the agentd stanza appended, ready for build_image.

The result is the task text, a newline if it lacked one, USER root when the task’s last USER is anyone else, then the stanza the default Dockerfile uses: COPY agentd /agentd, the chmod, ENV AGENTD_PORT, EXPOSE, ENTRYPOINT [] and CMD ["/agentd"]. Pass the result to build_image with base_image=BaseImage.from_dockerfile(result).

port is the agent port (9000 by default) and must match the sandbox’s. workdir creates and sets a working directory, as the default Dockerfile does. inherit_workdir refuses a result with no WORKDIR anywhere.

Raises InvalidArgError for a task with no FROM, one that ends inside a line continuation or an unterminated heredoc (either would swallow the stanza), a keepalive the client cannot tolerate, a port of 0, a workdir that is not one absolute path, or inherit_workdir with nothing to inherit.

def wrap_dockerfile_preserving_user(
task_dockerfile: str,
*,
port: SupportsIndex | None = None,
workdir: str | None = None,
inherit_workdir: bool = False,
) -> str

Preserve the final Dockerfile USER’s uid and primary gid as the workload default. The builder resolves stage inheritance, variables and names. Explicit image AGENTD_DEFAULT_USER and request users win. The daemon starts as root and workloads start only after readiness. Requires COPY --chmod.

__version__: Final[str] = '1.3.0'

Every exception derives from MicrovmError, so one except clause catches anything this package raises.

class MicrovmError(Exception)

Base of every exception this library raises. Carries .code, .kind, .wire_kind, and .retryable so nothing has to parse a message.

class BuildWedgedError(MicrovmError)

ERR_BUILD_WEDGED — the image build was never scheduled: the clientToken replay signature.

class CredentialsError(MicrovmError)

ERR_CREDENTIALS — an identity is wrong or absent; waiting will not fix it.

class ExecFailedError(MicrovmError)

ERR_EXEC_FAILED — the sandbox worked and the command in it exited non-zero. The one failure that means nothing is wrong with the platform.

class InterruptedError(MicrovmError)

ERR_INTERRUPTED — interrupted after launch; teardown ran and any leak is named.

class InvalidArgError(MicrovmError)

ERR_INVALID_ARG — refused locally, before any AWS call. Every trap closure lands here.

class LaunchDiedError(MicrovmError)

ERR_LAUNCH_DIED — the MicroVM reached a terminal state before RUNNING. Read the message’s stateReason.

class PlatformError(MicrovmError)

ERR_PLATFORM — a control-plane failure with no more specific class.

class PreconditionError(MicrovmError)

ERR_PRECONDITION — a prerequisite is missing.

class ProtocolError(MicrovmError)

ERR_PROTOCOL — the daemon rejected the request on its merits. Read .wire_kind to tell a 400 from a 404.

class RetryableError(MicrovmError)

ERR_RETRYABLE — transient. Run the identical request again.

class TimeoutError(MicrovmError)

ERR_TIMEOUT — a client-side deadline elapsed. The VM and the exec are untouched.

class UnexpectedError(MicrovmError)

ERR_UNEXPECTED — no handler claimed this. A bug in the client, not the platform.

class WindowClosedError(MicrovmError)

ERR_WINDOW_CLOSED — the MicroVM ended before the resume (the suspended window, the maximum duration, or a terminate), and it can’t be resumed; launch a new one. The suspended window ends a VM the idle policy suspended; an explicit suspend stayed resumable 1283 s into a 60 s window (measured 2026-10-12, us-east-1).

This page is generated from bindings/microvms-py/microvms.pyi by Griffe 2.3.0, run from site/scripts/gen-reference.mjs on every pnpm run sync, so an edit made here is overwritten by the next run.

To change the page, change the doc comment in the binding’s Rust source, then regenerate the declarations with mise run stubs. mise run stubs:check fails when the committed file no longer matches the source.