We spent the first wave of generative AI teaching models how to answer.

Now we are teaching them how to act.

An answer can be wrong, embarrassing, or expensive. An action can delete data, exfiltrate a secret, spend money, launch infrastructure, message a customer, or create another agent with the same ability to act. That is a different class of system.

The interface still looks deceptively familiar. A person types an instruction. A model returns text. Somewhere behind that text, however, a runtime may be opening a browser, reading a repository, calling a payment API, writing to a database, or launching a fleet of workers.

The prompt is no longer the product boundary. The machine is.

A prompt is an instruction. A boundary is something the workload cannot cross.

That distinction is becoming one of the most important architectural choices in agent infrastructure.

Application guardrails are useful—and insufficient

Most agent systems begin with controls at the application layer:

  • a system prompt describing what the agent may do
  • a list of available tools
  • validation around tool arguments
  • a human confirmation step for sensitive actions
  • a policy model asked to classify the next operation
  • logs of what the agent said it intended to do

All of those are valuable. None of them is a machine boundary.

A model can misunderstand a rule. A tool can contain a vulnerability. A dependency can be compromised. A parser can interpret an argument differently than the validator did. An instruction hidden in an untrusted document can redirect the model. A supposedly benign tool can become dangerous when composed with another one.

This is not a criticism of language models. It is a property of software with ambient authority. If a process can reach the network, read credentials, inspect the host filesystem, and spawn more work, then every layer inside that process inherits the consequences of every mistake.

The security question is therefore not only:

“Will the agent choose the right action?”

It is also:

“What is the most harmful action this execution environment can physically perform?”

The second question has to be answered below the model.

Put the contract around the workload

I want an agent execution to begin with a concrete contract, not a collection of hopeful conventions.

That contract should describe:

  • the exact code and image that may run
  • the CPU, memory, storage, wall-clock, and child-execution budgets
  • the files or object references the workload may read
  • the outputs it may create
  • the services it may contact
  • the protocols, domains, methods, and data classes allowed through egress
  • whether it may request another workload
  • the maximum authority that can be delegated to that child
  • the evidence that must be retained after execution

The runtime should then enforce that contract even when the process inside it is buggy, compromised, or adversarial.

A simplified shape looks like this:

human intent


planner / controller

    ├── signed capability lease
    ├── resource budget
    └── expected output contract


isolated microVM
    ├── read-only base image
    ├── bounded scratch space
    ├── no ambient host filesystem
    ├── no ambient network
    └── narrow communication channel


policy gateway
    ├── identity-aware egress
    ├── secret injection at the edge
    ├── request and response limits
    └── immutable audit events


approved external service

The model can still reason creatively inside the box. The box does not need to trust that reasoning.

Why a microVM boundary

Containers are excellent packaging and process-isolation tools. WebAssembly is an excellent capability-oriented execution format for many classes of code. Operating-system sandboxes can be strong when their assumptions are narrow and carefully maintained.

For general agent workloads, though, I keep returning to microVMs.

A microVM gives the workload its own kernel boundary while remaining small enough to launch as infrastructure rather than as a long-lived pet machine. That matters when the workload may include a Python interpreter, browser automation, native libraries, package managers, or software supplied by someone other than the platform operator.

The boundary is not valuable merely because “VMs are secure.” That sentence is too vague to be useful. The value comes from the architecture we can build around the boundary:

  1. The guest starts without ambient access to the host.
  2. Communication crosses a small, inspectable channel.
  3. Network behavior is mediated by the host rather than delegated to the guest.
  4. Storage is explicit, bounded, and disposable.
  5. Resource accounting happens outside the workload.
  6. The workload can be destroyed without leaving authority behind.

A microVM is the beginning of the design, not the end of it.

Six properties I want from an agent runtime

1. Default-deny capabilities

An agent should receive the minimum capability required for the current step, for a limited duration, against a named resource.

“Can use GitHub” is too broad.

“Can read repository x at commit y, create a branch with prefix agent/, and open a draft pull request—but cannot merge, change repository settings, read unrelated private repositories, or modify Actions secrets” is closer to a useful capability.

This contract should be machine-readable and enforced by the runtime and gateways. The model may request more authority, but it should not grant that authority to itself.

2. No ambient network

Putting an allow-list inside the guest is weaker than making the guest unable to reach the network directly.

The workload should communicate through a host-owned transport—such as a narrow vsock or Unix-domain channel—to a policy gateway. The gateway can bind each request to workload identity, inspect the destination and method, enforce byte and rate limits, and record what left the boundary.

This also creates a better place to handle secrets.

Instead of placing a long-lived credential in the guest environment, the gateway can authorize a specific request and inject the credential only at the final hop. The workload proves what it is allowed to ask for; it never possesses the reusable secret.

3. Bounded data in both directions

Security controls often focus on what a workload can call and forget how much data can cross the boundary.

Every channel needs size, rate, and lifetime limits:

  • maximum request and response sizes
  • maximum queued messages
  • maximum log volume
  • maximum file and artifact sizes
  • timeouts and cancellation
  • backpressure rather than unbounded buffering
  • explicit behavior when a limit is reached

A ten-byte permission with an unbounded response is not a ten-byte permission.

The same applies to logs. “Record everything” can become a denial-of-service mechanism or an accidental secret-retention system. Audit evidence needs schemas, redaction rules, quotas, and lifecycle policy.

4. External resource accounting

A process cannot be trusted to report how much resource it consumed or how many children it created.

The host must own the counters.

For a single execution, the budget may include virtual CPUs, resident memory, scratch bytes, I/O bytes, wall time, service requests, token spend, and artifact count. For a workflow, those limits need to aggregate across the entire descendant tree.

A controller asking for twenty workers should not make twenty independent decisions that each appear to fit within budget. The parent needs a total allocation, and every child lease must subtract from it.

This is where security and reliability become the same problem. A benign agent in a retry loop can bring down a host just as effectively as a malicious one.

5. Attenuating delegation

Agent systems increasingly look like graphs: a controller decomposes work, workers produce evidence, and new workers are launched when the plan changes.

Delegation is useful. Authority amplification is not.

A child workload should never receive more authority than its parent possesses. More strongly, every delegation should attenuate the parent’s capability:

parent:
  repositories = [alpha, beta]
  max_children = 6
  network = [api.example.com]
  budget.cpu_ms = 120000

child:
  repositories = [alpha]
  max_children = 0
  network = []
  budget.cpu_ms = 12000

The child receives a narrower lease, a smaller budget, and a shorter lifetime. The runtime can verify that the child request is a subset of the parent contract before anything boots.

This is the difference between a swarm and an uncontrolled fork bomb with an API key.

6. Durable, queryable evidence

When an execution finishes, the ephemeral machinery should disappear. The evidence should not.

I want to be able to answer:

  • which immutable workload image ran?
  • who authorized it?
  • which capabilities were granted?
  • which inputs were mounted or referenced?
  • what requests crossed the policy gateway?
  • which child workloads were created?
  • what limits were approached or exceeded?
  • which artifacts were produced?
  • why did the runtime terminate the workload?

The answer should not require reconstructing a story from interleaved plaintext logs.

Execution events need stable schemas and causal identifiers. At shutdown, active communication can be flushed into an immutable archive, indexed for investigation, and removed from the hot path. The operational database stays small; the evidence remains available.

Performance is part of the security model

A secure mechanism that is too slow will be bypassed.

If an agent runtime adds seconds before every unit of work, teams will keep warm, overly privileged workers alive. They will combine unrelated tasks into larger sandboxes. They will punch holes through mediation because direct access feels faster.

That means startup latency, memory overhead, and policy evaluation are not separate from security. They determine whether the secure path becomes the normal path.

The target should be a boundary cheap enough to use for small work:

  • minimal guest images
  • prebuilt, content-addressed boot artifacts
  • asynchronous setup where it does not weaken verification
  • host-side policy structures that avoid allocation on the hot path
  • bounded, binary-framed messages
  • lazy attachment of optional services
  • warm pools only when identity and state can be reset with confidence

The fast path still needs to be the strict path.

Rust, WebAssembly, and the right layer for each

I am enthusiastic about Rust and WebAssembly, but I do not think every layer should be rewritten into one execution format.

Rust is a strong fit for the host runtime, policy engine, resource accounting, transport, and artifact verification. Those components benefit from explicit ownership, predictable performance, and a small dependency surface.

WebAssembly is compelling for narrow tools whose capabilities can be expressed as imported functions. A WASM tool can receive a tiny interface instead of a simulated general-purpose machine.

A microVM remains useful when the workload needs a conventional operating-system environment or includes code that was not designed around capabilities.

These are complementary boundaries:

microVM: general workload isolation
WASM:    narrow capability-oriented tools
Rust:    host enforcement and performance-critical control

The mistake is choosing one because it is fashionable and then forcing every workload through it. The goal is not architectural purity. The goal is legible authority.

The product interface becomes the guarantee

Today, agent platforms often present a list of integrations and a large “run” button.

A boundary-first platform can present something more meaningful:

This execution may:

✓ read repository alpha at commit 9f31…
✓ write to branch agent/docs-*
✓ call api.example.com/v1/search
✓ use 2 vCPUs, 512 MiB, and 90 seconds
✓ create at most 2 child workloads

This execution may not:

× access the public network
× read other repositories
× possess long-lived credentials
× mount the host filesystem
× delegate broader authority

That is not merely a security dialog. It is a product model for trust.

The user can understand what will happen. The platform can enforce it. The audit trail can prove what happened. The agent can ask for a larger contract when the work genuinely requires it.

Building beneath the prompt

This is the direction I am exploring with MVM: make the machine boundary a first-class part of the agent runtime.

The hard part is not booting a VM. The hard part is preserving a small, understandable security surface while adding workflow graphs, communication, tools, storage, AI access, and recursive execution.

Every useful feature is also a request to expand the blast radius.

The design discipline is to make that expansion explicit, bounded, and attributable—or refuse it.

Agents will become more capable. Models will improve. Tool ecosystems will grow. None of those trends remove the need for a boundary. They make the boundary more important.

We should absolutely teach agents to make better decisions.

We should also build systems that remain safe when they do not.