Skip to content

Go library

Last updated: 2026-08-17

New to the library? Start with the library overview or the smallest useful Go program. This page is the package reference.

Most programs want exactly this: boot a microVM from an OCI image, run a command inside it, read the output. workspace.Run does all of it in one call:

package main
import (
"context"
"fmt"
"github.com/geoffbelknap/microagent/pkg/workspace"
)
func main() {
opts := workspace.DefaultOptions()
opts.Name = "demo-vm"
opts.ImageRef = "docker.io/library/ubuntu:24.04"
opts.ExecCommand = "uname -a"
result, err := workspace.Run(context.Background(), opts)
if err != nil {
panic(err)
}
if result.Result != nil {
fmt.Print(result.Result.Stdout)
}
}

DefaultOptions picks the host backend, kernel, and state directory; you set only what your program cares about. The rest of this page covers the packages behind this call and the lower-level APIs around it.

The library doesn’t require agent semantics. The same packages back the CLI’s agent-flavored workflows and any program that just wants microVMs: build a rootfs from an OCI image, boot a VM, run a command, tear it down. The high-level pkg/workspace API treats every workspace as a workload-role identity by default. You get caller-visible identity for free without writing agent-aware code, and you can drop down to pkg/vmkit when you need a different role or a custom supervisor request.

These are the core packages — the ones most embedding programs import first:

Package Purpose
pkg/vmkit supervisor request/response types, validation, and executable supervisor client
pkg/workspace workspace lifecycle API, options, defaults, request construction, backend supervisor selection, and shared helpers
pkg/operation stable operation error categories shared by library, CLI, and MCP adapters
pkg/kernel kernel default manifest, install, verify, update checks, and support checks
pkg/imagecache reusable rootfs image cache indexing, pull, tag, remove, and prune
pkg/diagnostics backend host diagnostics and support summaries
pkg/perf cold, restore, fork, resume, interactive, footprint, and steady-state performance measurements
pkg/rootfs OCI image and tar bundle conversion into ext4 disks
pkg/supervisors/firecracker Linux Firecracker supervisor implementation

A second tier of supporting packages backs specific CLI workflows. Import them when the CLI ↔ library mapping table at the bottom of this page points at them:

Package Purpose
pkg/workspace/exec/protocol the structured exec wire protocol (ExecRequest, ExecResult, ExecStatus); every workspace.Exec caller imports this
pkg/workspace/exec/client host-side client for the guest structured exec service (used internally by workspace.Exec; import it only for custom transports)
pkg/scaffold generates a starter agent project (microagent.yaml plus supporting files); backs microagent init
pkg/commit snapshots a stopped workspace’s rootfs back into an OCI image and pushes it; backs microagent commit / microagent image push
pkg/model manages local GGUF model files pulled from Hugging Face (pull, list, remove, prune)
pkg/modelrunner manages host-local model server processes (llama.cpp, vLLM, or custom commands); modelrunner.Ensure starts or reuses a runner
pkg/volume user-defined named volumes: VM-independent ext4 disks created, attached, and removed by name
pkg/secret resolves scheme-prefixed secret references (env:/file:/dotenv:/vault:/helper:) to values held host-side only
pkg/registryauth OCI registry credential login, logout, and listing without a Docker dependency

The CLI is an adapter over these packages. Go callers should use the library directly for workspace lifecycle operations instead of shelling out to microagent.

These exported symbols are part of the documented Go API. Helper functions and backend plumbing can remain exported for package boundaries without being promoted here, but caller-facing symbols should be added to this page when they are introduced.

Package Documented symbols
pkg/operation ErrorKind, Error, New, Wrap, IsKind, ProgressStatus, ProgressRunning, ProgressSucceeded, ProgressFailed, ProgressCanceled, ProgressEvent, ProgressFunc
pkg/vmkit Request, Response, DatapathStartupFailure, Config, Identity, Disk, NetworkConfig, PortForward, MediationConfig, VsockListener, RuntimeArtifacts, ArtifactRef, RuntimeResult, Event, VMState, StateUnknown, RoleWorkload, Supervisor, SupervisorClient, ExecutableSupervisor, NewRuntimeContract, FeatureContract, OperationContract, OperationID, OperationEffect, OperationIdempotency, OperationConfirmation, OperationSideEffect, OperationTypeID, OperationEffectRead, OperationEffectMutation, OperationEffectDestructive, OperationIdempotencyReadOnly, OperationIdempotencyReplayable, OperationIdempotencyKeyedReplay, OperationIdempotencyNotIdempotent, OperationConfirmationPreview, OperationSideEffectHostState, OperationSideEffectWorkspaceState, OperationWorkspaceDispatch, OperationWorkspaceExec, OperationWorkspaceConsole, OperationWorkspaceResult, OperationWorkspaceLogs, OperationWorkspaceEvents, OperationWorkspaceStats, OperationWorkspaceEgress, OperationWorkspaceCost, OperationWorkspaceObserve, OperationWorkspaceCreate, OperationWorkspaceStart, OperationWorkspaceInspect, OperationWorkspaceWait, OperationWorkspaceStop, OperationWorkspaceHalt, OperationWorkspaceKill, OperationWorkspaceQuarantine, OperationWorkspaceDelete, OperationWorkspaceList, OperationWorkspaceClone, OperationFileCopyOffline, OperationFileCopyLive, OperationArtifactList, OperationArtifactGet, OperationArtifactRead, OperationWorkspaceCommit, OperationWorkspaceApply, OperationNetworkPublish, OperationNetworkApplyLive, OperationNetworkInspect, OperationWorkspacePause, OperationWorkspaceResume, OperationSnapshotCreate, OperationSnapshotRestore, OperationSnapshotFork, OperationSnapshotList, OperationSnapshotDelete, OperationSnapshotCatalog, OperationVolumeCreate, OperationVolumeList, OperationVolumeInspect, OperationVolumeDelete, OperationVolumeResize, OperationWorkspaceResize, FeatureCapabilityResize, OperationImagePull, OperationImageList, OperationImagePush, OperationImageTag, OperationImageDelete, OperationImagePrune, OperationModelPull, OperationModelList, OperationModelRemove, OperationModelPrune, OperationModelServe, OperationModelStop, OperationModelRunners, OperationModelPolicyCheck, OperationModelPolicyEval, OperationKernelInstall, OperationKernelVerify, OperationKernelList, OperationKernelCheck, OperationRootfsBuild, OperationHostInspect, OperationDoctorCheck, OperationProfilesList, OperationContractGet, OperationDescribe, OperationProjectInit, OperationSecretCheck, OperationSecretAudit, OperationPerfBoot, OperationPerfReady, OperationPerfFootprint, OperationPerfSteady, OperationSupervise, OperationBrokerConfigure, OperationRegistryLogin, OperationRegistryLogout, OperationRegistryList, OperationServeMCP, OperationHostGC, OperationPing, FeatureScope, FeatureBackendNeutral, FeatureCapability, FeatureCapabilityStructuredExec, FeatureCapabilityNetworkPublish, FeatureCapabilityOfflineFileCopy, FeatureCapabilityLiveFileCopy, FeatureCapabilityEgressMediation, CapabilityTier, CapabilityTierCore, CapabilityTierSafety, CapabilityTierFeature, CapabilityTierOf, VerdictOK, VerdictDegraded, VerdictFailed, FeatureBackend, FeatureGap, UnsupportedFeatureError, FeatureContracts, OperationContracts, FeatureBackendSupport, BackendSupportsFeature, BackendSupportsOperation, FeatureForCLICommand, FeatureForMCPTool, OperationForCLICommand, OperationForMCPTool, OperationContractByID, NewUnsupportedFeatureError, NewUnsupportedFeatureCapabilityError, NewUnsupportedOperationError, ContractDurability, ContractDurabilityTier, ContractDurabilityTransition, DurabilityTier, DurabilityRuntime, DurabilityWorkspace, DurabilitySnapshot, DurabilityIndependent, DurabilityEffect, DurabilityPreserved, DurabilityDiscarded, DurabilityCaptured, DurabilityRestored, DurabilityCopied, DurabilityReset, DurabilityRemoved, DurabilityNotGuaranteed, DurabilityContract, ContractPersistence, ContractPersistenceTier, PersistedArtifact, PersistenceTier, PersistenceRecoverable, PersistenceOperational, PersistenceAudit, PersistenceEvidence, PersistenceContract, IsKnownBackend, Capabilities, BackendCapabilities, EgressDatapathBinEnv, ResolveEgressDatapathBin, SnapshotManifest, SnapshotArtifact, SnapshotInfo, SnapshotManifestName, SnapshotVMStateName, SnapshotMemoryName, SnapshotRootfsName, SnapshotAppleVFMachineState, SnapshotAppleVFConfig, SnapshotsDir, SnapshotDir, SnapshotStagingParent, PublishSnapshotDir, SnapshotRootfsArtifact, SnapshotMachineStateArtifacts, FirecrackerSnapshotArtifacts, AppleVFSnapshotArtifacts, WriteSnapshotManifest, ReadSnapshotManifest, ListSnapshots, RemoveSnapshot, MaterializedSecretsDeclared, ValidateSnapshotSecretCapture, ValidateSnapshotSecretRestore, EgressModeBroker, EgressModeMITM, EgressModeOff, EgressMediationOn, EgressModeForgesCerts, NetworkModeMediates, ValidateEgressMode, ResolveEgressModeDefault, EgressPolicy, EgressCaps, NormalizeEgressPolicy, ReadinessSignal, RuntimeReadiness, MediationReadinessSignal, BrokerConfig, BrokerAssurance, BrokerAssuranceSemantic, BrokerAssuranceTrustedUpstream, BrokerGrant, BrokerOperationGrant, BrokerValueGrant, BrokerBodyGrant, BrokerJSONSchema, BrokerResponseGrant, BrokerRedirectGrant, BrokerEffect, BrokerEffectRead, BrokerEffectWrite, ValidateBrokerSecurity, BrokerListenerTarget, ValidateBackendVsockListeners, GuestBootParam, GuestBootParams, AppleVFUndecodedConfigFields
pkg/workspace Options, OptionsFromRequest, EgressPolicyFromOptions, DefaultOptions, Spec, SpecApplyOptions, ApplyResult, Manifest, CapabilityComposition, EvaluateCapabilityComposition, ModelRunnerSpec, ModelMediationSpec, Result, GuestResult, CopyResult, ListEntry, SuperviseOptions, SuperviseResult, ConsoleOptions, ShellTarget, ConsoleReadTimeoutError, ConsoleCompletionUnknownError, ShellReadinessProbeMode, ShellReadinessProbeTCP, ShellReadinessSignalWithMode, DefaultModelGuestPort, ExecReadyProbeTimeout, ExecReadyWait, ExecMaxTransientRetries, CleanStopSyncTimeout, ExecPort, ExecPortForName, ExecRetryExhaustedError, ExecRetryMetadata, ExecReadinessSignal, Create, CreateFromSnapshot, Run, RandomName, Start, Inspect, Status, Wait, WaitOptions, WaitResult, WaitTimeoutError, WaitStateOK, IsWaitTerminalState, ResultStatus, GC, GCResult, GCReap, GCFailure, ArtifactsFor, GetArtifact, ArtifactGetOptions, GetArtifactWithOptions, Copy, CopyOptions, CopyWithOptions, GuestRootfsLayerTar, Clone, CloneOptions, CloneWithOptions, ReadLogs, ReadSupervisorLogs, ReadEvents, EventsPath, ReadEgressAudit, EgressAuditPath, ReadBrokerAccess, BrokerAccessPath, MergeEgressEvents, EgressEvent, AuditIntegrityError, EgressAuditSummary, SummarizeEgressAudit, RunDispatch, DispatchResult, SampleStats, Stats, Network, List, Control, Pause, Resume, DefaultSnapshotTag, DefaultForensicSnapshotTag, Snapshot, SnapshotForensic, SnapshotList, SnapshotRemove, Apply, Exec, ExecWithMetadata, ExecStream, MarkActivity, IsRetryableExecTransient, DialConsole, WaitConsoleCommandReady, SendConsoleCommand, ConsoleTarget, ProbeShellCommand, Supervise, ReadSpec, ApplySpec, ApplySpecFile, ReadManifest, WriteManifest, ProfileNames, LookupProfile, NormalizeArch, ValidateArch, WorkspaceNotFoundError, Supervisor, FirecrackerSupervisorPathFromExecutable, LookupE2fsprogsTool, Mke2fsPath, DebugfsPath, Resize2fsPath, Resize, ResizeOptions, ResizeResult, KernelInstaller, ProgressKernelInstaller, RegisterKernelInstaller, RegisterProgressKernelInstaller, EnsureKernel, ShellReadinessProbeCommand, BrokerSecurityOptions, ParseBrokerConfig, ParseBrokerEndpoints
pkg/kernel InstallOptions, InstallResult, Install, VerifyOptions, VerifyResult, Verify, DefaultSource, Support, CheckUpdate
pkg/imagecache PullOptions, PruneOptions, Record, PruneResult, Pull, Find, List, Tag, Remove, Prune, PruneWithOptions, ReadIndex, FromProvenance
pkg/diagnostics Options, Check, DeriveVerdict, EgressTProxyRemediation
pkg/perf BootOptions, BootReport, BootProgressPhase, BootProgressWorkspace, BootProgressTeardown, BootProgressComplete, BootProgressEvent, BootProgressFunc, MeasurementBoundary, ReadyOptions, ReadyStartMode, ReadyStartColdBoot, ReadyStartSnapshotFork, ReadyStartSnapshotRestore, ReadyStartPausedResume, ReadyProbeMode, ReadyProbeStructuredExec, ReadyProbeInteractiveShell, ReadyReport, ReadyBoundary, ReadySetup, ReadyWarmup, ReadyIteration, ReadyPhases, ReadySummary, ReadyProgressRun, ReadyProgressSetup, ReadyProgressWarmup, ReadyProgressMeasurement, ReadyProgressPhase, ReadyProgressWorkspacePrepare, ReadyProgressLifecycle, ReadyProgressInterface, ReadyProgressProbe, ReadyProgressTeardown, ReadyProgressComplete, ReadyProgressEvent, ReadyProgressFunc, Distribution, FootprintReport, SteadyOptions, SteadyReport, SteadyProgressEvent, SteadyProgressFunc, Iteration, Summary, RSSSample, RSSSummary, RootfsSourceBaseline, RootfsSourceBuild, Boot, Ready, ParseReadyStartMode, ParseReadyProbeMode, Footprint, Steady, SteadyWithOptions, ProcessRSSKiB, ParseRSSKiB, SampleProcessRSS, SummarizeIterations, SummarizeReadyIterations, SummarizeRSSSamples
pkg/rootfs BuildRequest, BundleRequest, BundleProvenance, Builder, NewBuilder, NormalizeRequest, NormalizeBundleRequest, Platform, Provenance
pkg/supervisors/firecracker Supervisor

perf.ReadyOptions.Warmups controls excluded full-path runs before measured iterations. perf.ReadyReport.Warmup records those runs separately, so they never enter ReadyReport.Summary. Set ReadyOptions.Progress to receive typed perf.ReadyProgressEvent values for setup, warm-up, measurement, and teardown phases. The callback owns presentation; the library does not write progress to a terminal.

perf.BootOptions.Progress reports disposable workspace, rootfs, teardown, and completion phases through perf.BootProgressEvent. Use perf.SteadyWithOptions when a caller needs perf.SteadyProgressEvent values for individual memory samples. The original perf.Steady function remains the compact no-callback form.

Use pkg/vmkit when you need the shared request/response schema or want to call an executable supervisor.

package main
import (
"context"
"fmt"
"github.com/geoffbelknap/microagent/pkg/vmkit"
)
func main() {
resp, err := vmkit.ExecutableSupervisor{
Path: "microagent-firecracker-supervisor",
}.Do(context.Background(), vmkit.Request{Command: "host"})
if err != nil {
panic(err)
}
fmt.Println(resp.Backend, resp.OK)
}

On Linux, Go callers can also use github.com/geoffbelknap/microagent/pkg/supervisors/firecracker directly. The package name is firecracker; alias it if you like. The req below is any vmkit.Request you construct:

import (
firecrackersupervisor "github.com/geoffbelknap/microagent/pkg/supervisors/firecracker"
)
resp, err := firecrackersupervisor.Supervisor{}.Do(ctx, req)

An application embedding pkg/workspace on macOS must set MICROAGENT_EGRESS_DATAPATH_BIN to an installed microagent CLI before it starts a mediated Apple VF workspace. The library does not assume the embedding process implements microagent’s hidden datapath command. Startup returns Response.DatapathStartupFailure when the selected executable exits early or its CA material is unavailable.

firecracker.ResolveBinaryFrom(anchor) is the one place the Firecracker VMM binary is located: MICROAGENT_FIRECRACKER, then PATH, then ../libexec/firecracker relative to anchor (normally the supervisor executable). The supervisor’s boot path and doctor’s probe both call it, so a diagnostic verdict and an actual boot can never resolve different binaries. Pass the supervisor’s path as the anchor to see exactly what a boot would use.

firecracker.ReadEgressL4DropCounts(tap) reads the cumulative datapath drop counter for a workspace’s tap and returns it as []egress.DropCount under the class firecracker.EgressL4DropClass. It is the backend half of egress.Options.DropCounters. Guest traffic with no allowlistable destination identity (IPv4 ICMP and other non-TCP/UDP L4) is dropped at the firewall and never reaches the mediator. A sampled counter is the only way those drops can be reported at all. It must be called from the workspace’s own network namespace, where those rules are visible. A missing rule is not an error — it is the ordinary state for a workspace with no mediated egress — so it returns no counts instead of failing.

For backend-independent code, depend on the interface:

func inspect(ctx context.Context, supervisor vmkit.Supervisor, req vmkit.Request) (vmkit.Response, error) {
req.Command = "inspect"
return supervisor.Do(ctx, req)
}

vmkit.NewRuntimeContract() exposes high-level feature records, lifecycle durability, the persisted-artifact catalog, and the typed operation registry shared by the CLI and MCP adapters. vmkit.PersistenceContract() classifies every microagent-owned file family as recoverable, operational, audit, or evidence and declares its permissions, writer, cleanup owner, integrity, retention, and recovery behavior. Use vmkit.OperationContracts() for stable operation identities, adapter aliases, operation-level capability requirements, and canonical request/result type IDs. Library code should resolve stable IDs with vmkit.OperationContractByID(); adapter coverage can use vmkit.OperationForCLICommand() and vmkit.OperationForMCPTool(). If a library path rejects an operation, return vmkit.NewUnsupportedOperationError() so CLI and MCP callers see the same structured error shape.

Use pkg/rootfs when your program needs to build a VM rootfs from an OCI image without shelling out to microagent rootfs.

package main
import (
"context"
"github.com/geoffbelknap/microagent/pkg/rootfs"
)
func main() {
_, err := rootfs.NewBuilder().Build(context.Background(), rootfs.BuildRequest{
ImageRef: "docker.io/library/ubuntu:24.04",
Platform: rootfs.Platform{OS: "linux", Architecture: "amd64"},
OutputPath: "/tmp/rootfs.ext4",
StateDir: "/tmp/microagent-build",
SizeMiB: 2048,
})
if err != nil {
panic(err)
}
}

rootfs.ValidateImageRef(ref) checks that a reference parses — the same normalization and parse the builder runs first, with no network or filesystem access. Call it to reject a doomed configuration before spending anything on it. workspace.Create and workspace.Run run the same check ahead of their dry-run returns, so a dry run and a real run refuse the same references with the same error.

Set BuildRequest.BaseCacheDir to reuse extracted base image content across builds; rootfs.BaseCacheDirFor(stateDir) derives the standard location the CLI uses (honoring its environment override). The builder resolves the manifest digest from the source on every build and consults the cache by that digest, so a cached build and a fresh build of the same digest are byte-identical inputs. The returned Provenance.BaseSource says which happened (rootfs.BaseSourceRegistry, rootfs.BaseSourceLocalLayout, or rootfs.BaseSourceCache). rootfs.ClearBaseCache(dir, selector) removes entries (each reported as a rootfs.BaseCacheEntry) — the image cache’s delete/prune purge path is its main caller.

Builds strip setuid/setgid bits from the image by default; set BuildRequest.AllowGuestSetuid to preserve them for images that need a non-root user with working sudo. Provenance.SetuidPolicy records which happened (rootfs.SetuidPolicyStripped or rootfs.SetuidPolicyPreserved), with the removed paths in SetuidStripped and the uncapped total in SetuidStrippedCount. The policy keys the base-stage cache, so the two variants never share extracted trees.

rootfs.BuildRequest.DebugfsPath selects the e2fsprogs debugfs binary used to apply OCI inode metadata after the ext4 image is created. The returned rootfs.Provenance.ImageDefaults is a rootfs.ImageDefaults value containing the image user, environment, entrypoint/command, working directory, stop signal, exposed ports, volumes, and labels. Status responses expose that same shape as vmkit.OCIImageDefaults so persisted and inspected values stay aligned.

Use pkg/workspace when your program wants to create, run, start, inspect, and control named workspaces without parsing CLI flags.

workspace.DefaultOptions() picks the host backend (Firecracker on Linux or Apple Virtualization.framework on macOS), guest architecture, default kernel path, and default state directory. You override only what your program needs. The common pattern example at the top of this page shows the canonical DefaultOptions + Run call.

Leave Options.Name empty and Run mints a readable, collision-safe name via RandomName (for example run-brave-otter-4f9c); RunDispatch does the same with a dispatch- prefix. RandomName(prefix) is exported for programs that want the same naming for workspaces they create themselves.

Result.Result is a *GuestResult with Stdout, Stderr, and ExitCode captured from the guest. Result.Response carries the supervisor’s structured response (state, identity, verification).

Status responses expose declared egress coverage through Response.EgressCapture. When the backend can observe its mediator process, EgressCapture.Live is non-nil and reports current liveness; nil means the backend did not make a liveness observation. Quiescent workspace states also recompute and enforce the recorded rootfs hash, while running workspaces measure it without treating expected guest writes as divergence. EgressCapture.EncryptedDNS is an EgressEncryptedDNSCoverage value. It is EgressEncryptedDNSDeniedHTTP1 for mitm, where recognizable HTTP/1 DNS requests are denied, and EgressEncryptedDNSOpaque for broker, where TLS request content is not observable.

workspace.Run has three behaviors worth knowing before you ship:

  • The run phase is bounded by Options.Timeout. DefaultOptions sets it to workspace.DefaultTimeout (5 minutes). The rootfs build and image pull run first, under your own ctx; Run then wraps Options.Timeout around the supervisor run — the boot and your guest command. A guest command that legitimately needs more than 5 minutes (a compile, a large in-guest download) is killed at the deadline. Raise Options.Timeout for long-running commands; the tighter of it and the parent ctx deadline wins.
  • Cleanup happens only on success. When the run completes and the supervisor reports OK, Run removes the scratch state — unless Options.Keep is set. A run that fails (boot error, supervisor error, timeout) deliberately leaves its state directory under <StateDir>/workspaces/<name>/ for debugging. Remove it explicitly with workspace.Control(ctx, opts, "delete"), or pick a fresh name for the next attempt. run is one-shot and discards by default; Create+Start are the durable path where delete is always the explicit removal.
  • A command is required. Run returns an error when Options.ExecCommand is empty, unless Options.UseImageCommand is set to run the OCI image’s own entrypoint/command instead. With an empty Options.Name, Run generates a unique run-<timestamp> name; with an empty Options.ImageRef it falls back to the default per-architecture Python image.

workspace.Options is a plain value struct — copy it freely; each call gets its own copy. The exported fields, grouped by concern:

Workspace identity and image

Field Meaning
Name workspace name; becomes the RuntimeID in requests, state paths, and events
ImageRef OCI image reference the rootfs is built from
ImageDefaults persisted rootfs.ImageDefaults applied to normal workload boots and reported by status
Hostname guest hostname
Architecture guest architecture (amd64/arm64)
Backend backend id; must match the host backend (ValidateHostBackend)
Profile / ProfileExplicit named resource profile (tiny/small/medium/large) and whether it was set explicitly

Command and lifecycle

Field Meaning
ExecCommand one-shot command Run executes in the guest
UseImageCommand run the image’s own entrypoint/command instead of ExecCommand
ServiceCommand long-running service command for durable workspaces
Entrypoint entrypoint override
SetupCommands commands run once during rootfs preparation
ConsoleShell absolute guest path of the interactive console shell
RestartPolicy restart policy for Supervise (default never)
Health health-check declaration
Timeout run deadline (default 5 minutes; see the lifecycle contract above)
LeaseSeconds lifetime lease measured from VM start; activity does not renew it. Create/CreateFromSnapshot default this to DefaultLeaseSeconds (7 days) unless LeaseSecondsExplicit is set — including an explicit 0, which still means permanent
Keep retain scratch state after a successful Run
SerialLogMaxBytes bytes of console log inlined in Result.SerialLog as a tail (0 = workspace.DefaultSerialLogMaxBytes, 8192; negative = full log). Result.SerialLogBytes/SerialLogTruncated report the full size and whether the inline copy is an excerpt; the full log stays at Result.SerialPath while the workspace is kept
DryRun validate and prepare without booting
PrepareForStart prepare state for a later Start
FromSnapshot restore in place from this snapshot tag on Start
MaintenanceBoot boot with only shell/exec channels (no service, no secrets) for file operations
SerialInput enable serial console input

Resources and network

Field Meaning
MemoryMiB, CPUCount, SizeMiB explicit resource sizing (override the profile)
SpecMemory, SpecCPU, SpecSize mark which resources came from an explicit spec
Network vmkit.NetworkConfig: mode (user default), port forwards, DNS, routes. A forward bound to a concrete IPv4 Host preserves that address as the guest application’s local address
Mediation optional vmkit.MediationConfig guest-to-host mediation channel
ResultPort, ShellPort, ExecPort, GuestShellPort, GuestExecPort vsock/TCP port assignments (defaulted per workspace name)
VsockListeners extra host vsock listeners
BakedVsockUDSPath source snapshot’s baked vsock path when starting from a snapshot

Files, disks, and outputs

Field Meaning
Files host files copied into the rootfs at build time
Disks extra data disks (including named managed volumes)
Outputs declared egress artifacts retrievable by name with GetArtifact
Env guest environment variables

Secrets and credentials

Field Meaning
Secrets name → scheme-prefixed reference, resolved and delivered at start
SecretEnvFiles dotenv file paths re-read on each start
OnDemandSecrets lazy references, never materialized in the guest
SecretsAudit append every secret access to the audit log
CapabilityRiskAcknowledgement operator reason accepting a hazardous complete grant set; persisted and reported, never treated as a validation bypass
CredSwapProviders parsed --cred-swap specs; provider keys injected host-side, never in the guest

Egress and broker

Field Meaning
EgressMode broker (default), mitm, or off
EgressAllow allowlisted egress destination hosts
EgressPassthrough allowed hosts that are not TLS-intercepted
EgressAllowlistLocked restrict egress to allowlisted destinations only
EgressSwapConfigPath operator credential-swap config (host-side injection)
EgressMaxBytesPerSec, EgressMaxTotalBytes, EgressMaxConcurrentConns per-mediator-process caps (ASK tenet 8); EgressPolicyFromOptions defaults EgressMaxTotalBytes/EgressMaxConcurrentConns to DefaultEgressMaxTotalBytes (50 GiB) / DefaultEgressMaxConcurrentConns (256) under broker/mitm unless the paired *Explicit field is set
Broker / Brokers egress broker endpoint(s); setting both is rejected — see the broker section

Bounded operations

Beyond the egress caps above, pkg/workspace bounds one more dimension by default (ASK tenet 8, operations-bounded): the host-wide workspace-count ceiling. EnsureWorkspaceCapacity fails closed at Create/CreateFromSnapshot/Start once CountActiveWorkspaces (running/starting/paused) reaches the ceiling MaxWorkspaces resolves. MaxWorkspaces also returns a MaxWorkspacesSource naming where the ceiling came from. MaxWorkspacesSourceOperator means the MaxWorkspacesEnv (MICROAGENT_MAX_WORKSPACES) environment variable is set. Otherwise it is MaxWorkspacesSourceComputed from DefaultMaxWorkspaces (detected host memory, clamped to 4-100), or MaxWorkspacesSourceFallback (10) when memory detection is unavailable. Inspect/Status attach a vmkit.BoundedOperationsStatus as Response.BoundedOperations, reporting every bound in force plus the current active-workspace count.

EvaluateCapabilityComposition derives stable categories from the complete effective options. Create, Run, snapshot forks, and Start reject the combination of guest private data, injected external content, and unmediated outbound before boot unless CapabilityRiskAcknowledgement records an operator reason. The same CapabilityComposition is returned in structured results and stored in the workspace manifest.

Model pairing

Field Meaning
Model canonical model ref the workspace is paired with (persisted; re-paired each start)
ModelTarget host host:port of a paired model server, realized as a guest→host vsock channel
ModelRunner ModelRunnerSpec: runner selection, GPU intent, backend model id, command template, args
ModelMediation ModelMediationSpec: mediation mode and policy source

Advanced paths and hooks

Field Meaning
StateDir state root (default ~/.microagent)
KernelPath / KernelExplicit kernel image path and whether it was set explicitly
SupervisorPath supervisor companion binary override
GuestInitPath microagent-guestinit binary override
Mke2fsPath mke2fs binary used for ext4 builds
DebugfsPath debugfs binary used to apply OCI filesystem metadata; workspace.DebugfsPath resolves the packaged default
Verification pre-computed runtime verification to attach
RootfsBase immutable image-store lineage for a private writable rootfs; normally populated by baseline reuse
Progress operation.ProgressFunc callback for typed workspace and rootfs phases; the library never renders terminal output

Paired model workspaces set Options.Model, Options.ModelRunner, and Options.ModelMediation. ModelRunnerSpec stores the runner selection (llamacpp, vllm, or custom), GPU intent, backend model id, custom command template, and repeatable runner args. ModelMediationSpec stores the mediation mode, policy source (PolicyFile or PolicyURL), and an optional PolicyTimeout for policy fetches. Runner env is transient and is intentionally not persisted to workspace manifests.

For non-defaults - backend override, custom kernel, sized memory/CPUs, networking

  • set the matching Options fields before calling Run. The lifecycle API:
Function Purpose
workspace.Create Build and prepare a named workspace rootfs and manifest
workspace.Run Build, run, collect result state, and optionally clean up
workspace.Start Start an existing named workspace from its manifest
workspace.Apply Apply declared restart/network changes and stopped-workspace agent egress policy changes while preserving unrelated manifest fields; live egress changes fail before any write
workspace.Delete Stop or kill a live workspace as requested, then delete its disk and state. Idempotent and explicit: an absent workspace returns success with Deleted false and no event, so retried teardown never fails but a caller can tell nothing was removed
workspace.DeleteOptions Select graceful stop or forced kill before deletion
workspace.DeleteResult The shared lifecycle Response, plus Deleted distinguishing “removed” from “was already absent”
workspace.Absent Report whether nothing of the workspace exists (no records, no root directory); a partially created workspace is present
workspace.Inspect Ask the backend supervisor for current runtime state
workspace.Status Read enriched local workspace status from state files
workspace.VolumeDiskUsage Measure a named volume’s backing image: provisioned, filesystem-used, and host-allocated MiB (vmkit.DiskUsage; nil when unreadable)
vmkit.DiskAssessmentOverprovisioned / vmkit.DiskAssessmentNearlyFull The advisory DiskUsage.Assessment verdict values
vmkit.DiskUsage The three sizes of a disk image — provisioned capacity, filesystem-used, and sparse host allocation — carried as RootfsUsage on inspect/status responses, with an advisory Assessment (overprovisioned / nearly-full)
workspace.Resize Grow or shrink a stopped workspace’s rootfs disk in place (ResizeOptions.Progress reports typed check, disk, filesystem, verification, and publication phases; refuses while running or while snapshots exist; returns ResizeResult with the new vmkit.DiskUsage)
workspace.Wait Block until the workspace reaches a terminal state (WaitOptions bounds it; returns a WaitResult, or WaitTimeoutError on timeout)
workspace.ResultStatus Read status plus guest result output
workspace.ArtifactsFor Read declared ingress and egress artifacts
workspace.GetArtifact / workspace.GetArtifactWithOptions Copy a declared output artifact from a stopped workspace; the options form reports typed phase and byte progress
workspace.Copy / workspace.CopyWithOptions Copy files between the host and a stopped workspace disk; the options form reports typed phase and byte progress
workspace.GuestRootfsLayerTar Export a stopped workspace’s filesystem as an OCI layer tar via a guest maintenance boot (backends without host ext4 tooling)
workspace.Clone / workspace.CloneWithOptions Clone a stopped/prepared workspace; the options form reports typed copy progress against the source workspace’s logical byte total
workspace.ReadLogs Read a workspace serial log
workspace.ReadSupervisorLogs Read a workspace’s host-side supervisor companion logs
workspace.ReadEvents Read the concurrency-safe, bounded lifecycle event history; malformed persistence returns an error
workspace.ReadEgressAudit Read the egress mediator’s recorded allow/deny/MITM/DNS/UDP decisions (EgressEvent, from EgressAuditPath)
workspace.ReadBrokerAccess Read the egress broker’s per-request decision records (EgressEvent, from BrokerAccessPath)
workspace.MergeEgressEvents Merge the mediator and broker streams into one time-ordered view
workspace.SampleStats Sample CPU, memory, and I/O for a running workspace
workspace.Network Read configured and runtime network state
workspace.List List named workspaces from local state
workspace.Control Run a lifecycle control action (halt, quarantine, pause, resume, stop, kill, delete, gc). quarantine uses the complete ordered containment primitive and returns its typed phases and capture tag in vmkit.Response.Containment; use workspace.Quarantine when the incident receipt is also needed
workspace.RequestShutdown Ask guest PID 1 to begin graceful shutdown through the structured exec control channel; lifecycle callers normally use Control("halt") instead
workspace.Quarantine Atomically mark containment, freeze vCPUs, sever host authority, capture evidence while frozen, and stop into custody. Takes workspace.QuarantineOptions and returns the typed result of every phase. Capture failure never resumes execution or authority
workspace.QuarantineOptions SkipCapture freezes and severs but omits the snapshot before final custody (accepting loss of volatile evidence); CaptureTag overrides the generated tag
workspace.QuarantineResult Response, typed Containment phases, evidence capture fields, and an IncidentReceipt summarizing host-observed lifecycle, egress, broker, and secret-access records for the quarantined session
workspace.ReadContainment Read the durable phase result. Marker presence remains an execution fence even when this document is missing or malformed
vmkit.ContainmentResult Durable typed result with freeze, severance, capture, stop, and custody phases, plus the accepted time, backend, captureRequired, capture tag, and overall state
vmkit.ContainmentPhaseStatus / vmkit.ContainmentPhaseResult Phase state and observation; statuses are vmkit.ContainmentPhasePending, vmkit.ContainmentPhaseCompleted, vmkit.ContainmentPhaseSkipped, and vmkit.ContainmentPhaseFailed
vmkit.ValidateContainmentResult Reject malformed phase status, missing observation times, out-of-order completion, or final custody without a completed stop
vmkit.ContainmentMarkerDirName / vmkit.ContainmentResultName / vmkit.ContainmentMarkerDir / vmkit.ContainmentResultPath Stable containment persistence names and paths for integrations that inspect host-owned workspace state
vmkit.ContainmentMarked Fail-closed marker-presence check; any filesystem error other than a confirmed missing marker is treated as contained
workspace.IncidentReceipt Self-contained, session-scoped incident summary. It reports destinations, byte counts, and secret names and outcomes without storing content or secret values; Complete and Errors make audit-read failures explicit
workspace.BrokerAuditSummary Broker request totals, destination verdicts, byte counts, and the names of swapped secret references
workspace.SecretAuditSummary Secret-access totals grouped by secret name and outcome; values are never present
workspace.ForensicCaptureTagPrefix Tag prefix (forensic-) for automatic quarantine captures, so they are identifiable on sight and never collide with operator tags
workspace.Pause / workspace.Resume Freeze and thaw a running workspace’s vCPUs in place
workspace.Snapshot Capture a tagged memory-plus-disk snapshot of a running or paused workspace. Ordinary snapshot dispatch is denied after containment is marked; quarantine owns its frozen-capture exception
workspace.SnapshotForensic Capture for investigation rather than restore: the guest secret purge is skipped, because credential material is the evidence and lives only in volatile memory. The manifest records forensic and frozenProcessState; secrets remain materialized and NOT purged, which the restore path refuses, so the capture cannot be rehydrated as a workspace
workspace.CreateFromSnapshot Fork a new workspace from another workspace’s snapshot and resume it
workspace.SnapshotList / workspace.SnapshotRemove List or delete a workspace’s snapshots (host-side). Removal refuses the capture named by an active containment custody record
vmkit.SafeSnapshotTag Report whether a snapshot tag is a bounded, path-safe identifier
workspace.Supervise Run the optional restart-policy loop for a workspace
workspace.GC Reconcile running workspace records as one bounded batch; returns GCResult with reaped targets and per-target GCFailure values instead of stopping at the first failure
workspace.ReadManifest / workspace.WriteManifest Manage workspace manifests directly

workspace.Control(ctx, opts, command) takes the action as its positional command argument — one of halt, quarantine, pause, resume, stop, kill, delete, or gc — and rejects anything else. The CLI’s stop is a registry-level alias of halt: typing microagent stop runs the identical graceful-shutdown mechanism and records the identical halted outcome on a clean exit. Calling workspace.Control(ctx, opts, "stop") directly, though, is a distinct library command — same shutdown mechanism as halt, but it records the terminal state stopped, not halted. Both clean commands make a two-second, best-effort structured exec request for the guest to run sync before dispatching shutdown. The attempt and outcome are written to lifecycle event history. A failed or timed-out flush never lets the guest block the halt; the control operation proceeds. kill and quarantine do not make this preparation request. Raw quarantine dispatch is refused so every library adapter uses the ordered primitive. The terminal event also carries vmkit.LifecycleAudit. It combines the provenance-labeled Options.Caller, Options.Purpose, host-declared manifest commands, notification ownership, and a bounded best-effort guest process snapshot. Guest processes are explicitly guestReported; kill skips that request. Quarantine freezes first and preserves process state in the forensic memory capture rather than asking the guest for a process list. It links a successful capture through the audit record’s evidence reference.

Type or function Purpose
vmkit.CallerAttribution Adapter channel plus optional caller-supplied subject and delegated authority, with explicit assurance
vmkit.DeclaredWork One host-recorded manifest command and its role
vmkit.GuestProcess One bounded, guest-reported process observation
vmkit.WorkInFlight Declared work, guest observations, capture status, and evidence reference
vmkit.NotificationRecord Records that notification was not performed and remains caller-owned
vmkit.ValidateLifecycleAudit Validates provenance vocabulary and bounds before supervisor dispatch
workspace.LifecycleInspectTimeout Maximum delay allowed for the guest process snapshot

For a running workspace, both graceful commands then call workspace.RequestShutdown before dispatching host lifecycle control. Guest PID 1 sends the persisted OCI stop signal to the workload process group and powers off; a rejection or timeout fails closed without escalating to a hard VMM signal. delete also removes the local state directory after the supervisor confirms; gc sweeps workspaces whose start-time lifetime lease expired. workspace.Pause and workspace.Resume are thin wrappers over the pause and resume actions and share their capability gate.

workspace.Copy(ctx, stateDir, debugfsPath, source, target) and workspace.GetArtifact(ctx, stateDir, debugfsPath, name, artifactName, target) operate on a stopped workspace’s disk. On hosts with ext4 tooling they shell out to debugfs from e2fsprogs: pass the binary path in debugfsPath. There is no in-library default — pass "debugfs" to resolve via PATH (the CLI’s own default is a PATH lookup with a /opt/homebrew/opt/e2fsprogs/sbin/debugfs fallback for macOS Homebrew); an empty string fails.

CopyWithOptions, GetArtifactWithOptions, and CloneWithOptions accept an operation.ProgressFunc. The original functions are shorthand with no callback. Progress messages describe operations rather than caller paths, and completed transfers report trustworthy byte totals.

pkg/workspace boots VMs through companion binaries that ship with the CLI: microagent-firecracker-supervisor and microagent-guestinit on Linux, microagent-applevf-supervisor on macOS. The library resolves them relative to an install base: first the running executable’s own directory (and its ../libexec), then the directory of microagent found on PATH. The second base is what makes resolution work for embedders: your program’s os.Executable() is not microagent’s install prefix. Without a microagent install on PATH (or explicit overrides) the lookup falls back to bare names like microagent-firecracker-supervisor, which fail unless those are themselves on PATH. The same two-base resolution covers the packaged kernel (../libexec/kernels/<backend>/<arch>/Image).

Deploying an embedder to a host without the microagent CLI therefore means shipping the companions yourself. Either place them next to your binary, set Options.SupervisorPath / Options.GuestInitPath / Options.KernelPath, or set the MICROAGENT_FIRECRACKER_SUPERVISOR / MICROAGENT_APPLEVF_SUPERVISOR environment variables (checked before the install-base search). Installers that need to mirror packaged resolution can use workspace.FirecrackerSupervisorPathFromExecutable (and the AppleVFSupervisorPathFromExecutable / GuestInitPathFromExecutable equivalents) to derive a companion path from a bin/microagent executable. workspace.Supervisor(opts) returns the resolved vmkit.Supervisor for the selected backend if you want to verify resolution up front.

Application operations return operation.Error for stable categories: validation, state conflict, not found, resource exhaustion, unsupported behavior, policy denial, and transient failure. Use errors.As or operation.IsKind; do not classify an operation by matching its message:

result, err := workspace.Start(ctx, opts)
if operation.IsKind(err, operation.ErrorConflict) {
// inspect current workspace state before retrying
}

The error unwraps its cause, so ordinary errors.Is and errors.As checks continue to work. CLI and MCP render the same category independently of the message wording.

workspace.WorkspaceNotFoundError is the structured “no such workspace” error. It is returned by the console helpers, workspace.Exec (and the other structured-exec entry points), workspace.SampleStats, and workspace.Status when a workspace has no runtime or event state. It supports errors.Is, so classify missing workspaces separately from stopped, halted, or quarantined ones:

if _, err := workspace.Status(opts); errors.Is(err, workspace.WorkspaceNotFoundError{}) {
// never created, or already deleted
}

Options is a plain value: every lifecycle function takes its own copy, so sharing a template Options across goroutines and customizing per call is safe. Structured exec is safe to run concurrently against one running workspace. Each Exec/ExecStream call dials its own connection and the guest service handles each connection in its own goroutine, running each command as an independent guest process. Lifecycle mutations are a different story — Run, Start, Control, Snapshot, Copy, and the other lifecycle functions read and write shared per-workspace state files. The package makes no documented guarantee about concurrent mutations of the same workspace name. Treat the lifecycle of a given workspace as single-threaded (operations on different workspace names are independent) unless you have verified a specific interleaving yourself.

workspace.SendConsoleCommand returns workspace.ConsoleReadTimeoutError when --send-style command completion is not observed before the send timeout; the error carries any partial output captured before the deadline. If the console connection closes before the completion marker arrives, SendConsoleCommand returns workspace.ConsoleCompletionUnknownError with any partial output captured before EOF. workspace.ProbeShellCommand uses the same marker protocol with a no-op command to verify a shell target can complete a command round trip. Callers that need explicit readiness semantics can use workspace.ShellReadinessSignalWithMode with workspace.ShellReadinessProbeTCP for TCP accept reachability or the command probe mode for end-to-end command readiness. workspace.WaitConsoleCommandReady waits for that command readiness without opening a second interactive session for the caller. Use workspace.DialConsole when the caller needs the returned connection. A terminal client can call workspace.ResizeConsole with that connection and the current rows and columns. The returned supported value is false for an older guest that did not negotiate resize support.

Structured exec uses workspace.Exec(ctx, opts, request) with pkg/workspace/exec/protocol.ExecRequest — callers import the protocol package for the request and result types. Build a request with protocol.NewExecRequest(argv) (which sets the protocol version and single-response mode) and set what you need:

  • Argv — the command as an argument vector; no shell is implied.
  • Env, Cwd, Stdin — environment, working directory, and stdin bytes (stdin is capped at protocol.DefaultOutputLimitBytes).
  • TimeoutMS — per-command guest-side timeout; the service default is protocol.DefaultTimeout (5 minutes).
  • OutputLimitBytesStdout / OutputLimitBytesStderr — per-stream capture caps, each at most protocol.DefaultOutputLimitBytes (10 MiB). Output beyond a cap is dropped and the result’s StdoutTruncated / StderrTruncated flag is set.

A nil Go error means the host reached the guest exec service and decoded a structured result — it says nothing about the command’s outcome. Check ExecResult.Status (protocol.ExecStatus) first:

Status Meaning
exited the process ran to completion; ExitCode is set
signaled the process was killed by a signal
timed_out the per-command timeout elapsed and the process was terminated
failed_to_start the command never started (bad path, invalid request)

ExecResult.ExitCode is a *int (JSON tag exit_code) and is nil unless Status is exited — dereferencing it unconditionally panics exactly when a command times out or fails to start. Guard it:

result, err := workspace.Exec(ctx, opts, req)
if err != nil { /* transport / workspace-state error */ }
switch {
case result.Status == protocol.ExecStatusExited && *result.ExitCode == 0:
// success
case result.Status == protocol.ExecStatusExited:
// nonzero guest exit — not a Go error
default:
// timed_out, signaled, or failed_to_start: ExitCode is nil
}

Nonzero guest exit codes are not Go errors. Use workspace.ExecWithMetadata when callers need retry accounting via workspace.ExecRetryMetadata. Transient transport failures are retried by the shared exec layer before the final result or workspace.ExecRetryExhaustedError is returned. workspace.IsRetryableExecTransient exposes the same classifier for callers that need to reason about exec transport errors directly. The execReady readiness signal in the runtime contract (vmkit.RuntimeReadiness.ExecReady, produced by workspace.ExecReadinessSignal) uses the same protocol with a no-op command to verify the service end-to-end. Exec gates on it for up to workspace.ExecReadyWait after start so an immediate post-start command does not surface a transient failure.

workspace.ExecStream(ctx, opts, request, onChunk) runs the same request in streaming mode: the guest emits stdout/stderr chunk frames as the command runs (delivered to onChunk) followed by a terminal result frame. In stream mode the returned ExecResult carries status, exit code, timing, and truncation flags but not the output bytes - those arrive as chunks. The CLI exposes this as microagent exec --stream.

Set workspace.Options.Progress to receive typed connect, retry, execute, and first-output boundaries. The first-output event is emitted before its chunk is delivered, so a presentation adapter can stop before writing stream data.

workspace.MarkActivity(opts) stamps a per-workspace activity marker file (mtime = last genuine use) and is called on each real exec/connect. The deadman watcher and gc sweep read it to measure idleness, so a declared --ttl lease is renewed by activity and only an idle VM is reaped. Internal readiness probes do not call it, so background liveness traffic cannot keep an abandoned VM alive.

The egress broker is a host-side forward proxy served on a vsock listener. The guest sends a reference and the broker injects the credential into the upstream request. Response-side guarantees depend on the endpoint’s explicit assurance. Declare it per workspace with Options.Broker (*vmkit.BrokerConfig) or Options.Brokers (multiple endpoints — setting both is rejected). vmkit.BrokerConfig carries the terminate-mode Upstream, the host-side Secret reference, and guest wiring (GuestListen, BaseURLEnv, Proxy). It also carries the Capture opt-in, optional UpstreamCAFile, Assurance, optional semantic Grant, and proxy ConnectAllowlist. Request fills transport defaults such as the vsock port and guest listen address. BrokerCredentialDisclosure names the response disclosure mode; BrokerCredentialDisclosureDenyExact is the required semantic value.

Rather than constructing the struct by hand, use the shared parsers — they fail closed on partial declarations and pasted literal secrets, so every surface (CLI, Agentfile, MCP, your program) builds an identical broker:

cfg, err := workspace.ParseBrokerConfig(
"https://api.anthropic.com", // upstream
"ANTHROPIC_API_KEY=env:ANTHROPIC_API_KEY", // NAME=<scheme>:<ref>, held host-side
[]string{"ANTHROPIC_BASE_URL"}, // base-URL env keys pointed at the broker
false, // proxy: set HTTPS_PROXY/HTTP_PROXY in the guest
false, // capture: governed raw-capture opt-in
"", // ca: PEM bundle for a private upstream cert
workspace.BrokerSecurityOptions{
Assurance: "semantic", // finite typed operations
GrantPath: "./anthropic-grant.yaml", // YAML/JSON operation contract
},
)
if err != nil {
panic(err)
}
opts.Broker = cfg

workspace.ParseBrokerEndpoints(specs) parses the repeatable ;-separated key=value endpoint spec strings (the --broker-endpoint grammar) into Options.Brokers. For what the broker enforces and how it relates to EgressMode and MITM mediation, see semantic broker grants and egress mediation.

Mediation readiness uses vmkit.MediationReadinessSignal(ctx, mediation, state, observedAt, timeout) to apply the shared live reachability contract. It returns ready only when the workspace is running and the declared mediation target accepts a bounded TCP probe. Required mediation target failures include an error; optional mediation target failures are reported as not ready without a hard error.

Use pkg/kernel when your program wants microagent to manage backend kernel assets directly.

result, err := kernel.Install(ctx, kernel.InstallOptions{
Backend: vmkit.BackendLinuxKVM,
Architecture: "amd64",
})
if err != nil {
panic(err)
}
verified, err := kernel.Verify(kernel.VerifyOptions{
Path: result.Path,
SHA256: result.SHA256,
})
if err != nil {
panic(err)
}
_ = verified

kernel.DefaultSource() returns the production manifest source: the TUF trust root embedded in the binary plus the canonical metadata/targets URLs. Pass it (or your own ManifestSource) to kernel.FetchTargets and feed the targets to kernel.CheckUpdate to classify an installed kernel as current, optional (behind latest but at the security floor), security (missing security fixes), or unknown. kernel.Support(backend, arch) reports whether a kernel image is present at the resolved path for a backend/architecture pair without installing anything.

You normally don’t call Install for the boot path: workspace.EnsureKernel runs inside workspace.Create/Run/Start/CreateFromSnapshot and installs the default kernel into the managed per-user path when none is present. Importing pkg/kernel is what arms it - the package registers the installer at init via workspace.RegisterProgressKernelInstaller (a workspace.ProgressKernelInstaller func; the indirection exists because pkg/kernel depends on pkg/workspace). The callback receives the same typed kernel progress that an explicit kernel.InstallOptions.Progress callback would receive. The older RegisterKernelInstaller remains available for embedders that do not need progress. A program that imports only pkg/workspace performs no implicit downloads: a missing kernel surfaces at boot. Add a blank import of pkg/kernel (or ship a kernel yourself) to choose the behavior you want. An explicit Options.KernelPath is always used as-is.

Use pkg/imagecache when an orchestrator wants reusable rootfs baselines.

record, err := imagecache.Pull(ctx, imagecache.PullOptions{
StateDir: "/home/me/.microagent",
ImageRef: "docker.io/library/ubuntu@sha256:...",
Architecture: "amd64",
})
if err != nil {
panic(err)
}
_ = record

workspace.CanReuseRootfsBaseline(opts) is the predicate that decides whether a workspace can clone a pulled baseline instead of building. It is true when the requested size and setuid policy can use the standard baseline. Commands, env, declared files, disks, ports, shells, and hostnames travel on the per-boot config disk or kernel command line. They do not change rootfs bytes. Wire a resolver into Options.RootfsBaseline (typically imagecache.Find) and workspace.Create clones automatically when the predicate holds. The store seeds itself: Options.RootfsBaselineSave (wired by the CLI to imagecache.SaveBaseline) records the first plain build of an image as a baseline, so later creates and runs clone without an explicit image pull. perf.BootOptions carries the same pair, so a boot benchmark measures the clone path a repeat run takes instead of a rebuild that path skips. Baseline records carry the hash of the guest init they were built with (workspace.GuestInitSHA256) and the rootfs SHA-256. Publication removes the shared rootfs’s host write bits; reuse requires the init to match and validates that the baseline still has its recorded immutable posture. imagecache.ValidateImmutableRootfs(record) exposes that posture check to other library consumers. Derived rootfs.Provenance.RootfsBase, workspace manifests, and vmkit.Response.RootfsBase preserve that source identity without claiming the private workspace disk is immutable. workspace.CopyFile reflinks on filesystems that support it (btrfs/XFS/APFS), so a clone is metadata-only where possible; workspace.CopyFileReplace is the overwrite variant. workspace.BuildVerification uses the measured base SHA-256 as a fresh private clone’s initial identity after checking the clone’s type and size. It does not reread a multi-gigabyte disk before first boot; quiescent status verification still hashes the private disk normally. workspace.BaselineSatisfiesSize(prov, opts) is the companion check the clone path applies to the resolved baseline. Its recorded bytes must cover the workspace’s effective size (profile-implied sizes the predicate cannot see), or the clone falls through to a real build.

Nothing per-workspace is baked into a rootfs. Each boot, the lifecycle assembles a guest run config (workspace.GuestBootConfigworkspace.GuestRunConfig: command, mode, env, ports, mounts, forwards, console shell, maintenance flag). It writes the config with any declared files as a raw tar stream to the workspace’s config disk (workspace.WriteConfigDisk; path from workspace.ConfigDiskFile). The supervisor attaches that file read-only as the last block device (vmkit.Config.ConfigDiskPath; guest device path math in vmkit.VirtioBlockDevice) and names it on the kernel command line. Declared file contents are captured once at create into a durable archive (workspace.WriteFilesArchive, path from workspace.FilesArchivePath; modes parsed by rootfs.ParseFileMode) so later boots deliver the create-time bytes even if the sources change. Each regeneration re-records the disk’s hash in the manifest verification block via workspace.RefreshManifestVerificationConfig, so the command and files the guest runs never escape attestation.

After a successful create-time setup boot, the lifecycle records the modified rootfs and final boot config together with SetupComplete. Failed setup boots leave that checkpoint untouched, so a later start retries setup instead of trusting a partial result.

imagecache.PruneWithOptions accepts PruneOptions.Progress and reports one bounded current/total counter while reconciling the index. Prune is the source-compatible no-callback shorthand. The model store offers the same pair as model.PruneWithOptions and model.Prune.

Use pkg/diagnostics for host preflight checks.

resp, err := diagnostics.Check(ctx, diagnostics.Options{
Backend: vmkit.BackendLinuxKVM,
Arch: "amd64",
})
if err != nil {
// resp still carries structured support details when available, so
// inspect both. Surface the error rather than swallowing it.
log.Printf("diagnostics.Check: %v", err)
}
_ = resp

Set diagnostics.Options.Progress to receive typed probe boundaries. Fast checks may replace one another without presentation; a slow current probe can be shown without parsing diagnosis text.

The CLI contains presentation, flag parsing, build metadata output, and raw terminal handling. microVM orchestration and management capabilities are exposed through the Go packages, and the mapping below shows the equivalent library entry points.

If you already know the CLI, this is the lookup for the equivalent library call:

CLI command Library call
microagent run workspace.Run
microagent dispatch workspace.RunDispatch
microagent init scaffold.Generate
microagent create workspace.Create
microagent start workspace.Start
microagent create --from-snapshot workspace.CreateFromSnapshot
microagent start --from-snapshot workspace.Start with Options.FromSnapshot
microagent status workspace.Status (local) / workspace.Inspect (live, via supervisor)
microagent wait / microagent start --wait workspace.Wait
microagent result workspace.ResultStatus
microagent list / microagent ls / microagent ps workspace.List
microagent halt / microagent stop / microagent kill / microagent delete workspace.Control (one function; the action is the positional command argument: halt, quarantine, pause, resume, stop, kill, delete, or gc)
microagent gc workspace.GC (bounded batch reconciliation with per-target failures)
microagent quarantine workspace.Quarantine (mark, freeze, sever, frozen capture, stop, custody). workspace.Control(ctx, opts, "quarantine") uses the same primitive with capture skipped
microagent pause / microagent resume workspace.Pause / workspace.Resume
microagent snapshot create / list / delete workspace.Snapshot / workspace.SnapshotList / workspace.SnapshotRemove
microagent apply workspace.Apply
microagent supervise workspace.Supervise
microagent connect workspace.DialConsole / ResizeConsole / SendConsoleCommand (raw terminal mode stays CLI-only)
microagent exec workspace.Exec
microagent logs workspace.ReadLogs
microagent events workspace.ReadEvents (text lifecycle view) / workspace.ReadTrajectory (structured joined view)
microagent egress workspace.ReadEgressAudit + workspace.ReadBrokerAccess (merged via workspace.MergeEgressEvents)
microagent stats workspace.SampleStats
microagent cp workspace.Copy
microagent clone workspace.Clone
microagent commit / microagent image push commit.Commit / commit.Push (commit.Options.Progress spans local commit phases; push has its own progress callback)
microagent artifact / microagent artifact get workspace.ArtifactsFor / workspace.GetArtifact
microagent network workspace.Network

workspace.NewSessionID creates an execution-lifetime identifier for callers that build raw requests. workspace.TrajectoryRecord is the common envelope returned by workspace.ReadTrajectory; its Raw field preserves the complete source record. The joined view includes constraint revisions from workspace.ReadConstraintHistory. Each revision carries an independently reconstructable manifest snapshot plus config-disk and verification hashes. workspace.ConstraintRevision is the complete record, and workspace.ConstraintHistoryPath returns its host-owned path. Retention uses workspace.DefaultMaxConstraintRevisions.

Status responses summarize the bounded history in Response.ConstraintHistory. The field uses vmkit.ConstraintHistoryStatus; its oldest and latest entries are vmkit.ConstraintRevisionRef values without embedded manifests.

workspace.Options.Purpose and CorrelationID are opaque caller context persisted in vmkit.Identity; the library records them verbatim and does not use them for policy decisions. For lifecycle mutations, set Options.Purpose to the operator’s reason before calling Control, Quarantine, or Delete; adapters expose that same value as reason. Set Options.Caller only from caller context your integration already holds. Use Assurance: "caller_asserted" when microagent has not authenticated the subject; leaving the caller unset produces a library-channel attribution with unavailable assurance rather than a fabricated principal. | microagent model | model.Pull / model.List / model.Remove / model.Prune / modelrunner.Ensure | | microagent volume | volume.CreateWithOptions / volume.ResizeWithOptions for progress-aware mutations; volume.Create / volume.Resize are no-callback shorthands; volume.List / volume.Get / volume.Remove / volume.Attach cover the remaining lifecycle | | microagent secret check | secret.DefaultRegistry / secret.Registry.Check | | microagent doctor / microagent host | diagnostics.Check | | microagent contract | vmkit.NewRuntimeContract | | microagent kernel install / microagent kernel verify | kernel.Install / kernel.Verify | | microagent rootfs build | rootfs.Builder.Build | | microagent image | imagecache.Pull / List / Tag / Remove / Prune | | microagent registry login / logout / list | registryauth.Login / registryauth.Logout / registryauth.List | | microagent perf / microagent perf boot / microagent perf ready / microagent perf footprint / microagent perf steady | perf.Boot / Ready / Footprint / Steady | | microagent profiles | workspace.ProfileNames / workspace.LookupProfile | | microagent serve mcp | CLI-only MCP stdio transport over the existing package APIs | | microagent model serve | modelrunner.Ensure (start or reuse a host-local model runner process) | | microagent version | CLI-only build metadata output | | microagent.yaml (spec parsing) | workspace.ReadSpec / ApplySpecFile |

The library calls take options structs and return typed responses. For reusable runtime behavior, prefer the package API. The remaining CLI-only commands are presentation concerns such as help, version, and raw terminal mode around an already-open console connection.