Most agent products describe their safety work as making the model behave. Meta’s engineering write-up for Muse takes the opposite position and states it in one sentence: “The right mental model is two isolated security domains on one box, not an LLM powered agent with root.”

That is a design premise, not a feature list. It says the agent is the thing being contained. Everything else in the document follows from it, and the mechanisms are specific enough to be worth walking through.

The cell

Each user gets a dedicated cloud VM. Inside it, the agent harness, the user’s files, and every binary the agent runs sit in a systemd-nspawn runtime container that Meta calls the runtime cell.

The isolation is described precisely. Root inside the cell maps to an unprivileged host user, “so runtime cell root is not host root.” The cell has its own root filesystem, a virtual network interface, filtered system calls with io_uring named as one that is blocked, and reduced kernel capabilities with CAP_SYS_PTRACE and CAP_NET_ADMIN named as two that are withheld.

The reason given for the split is the interesting part: “the runtime cell is expected to process untrusted data.” Not might. Expected to.

What lives outside the cell, and why

Four services run as separate systemd units beyond the agent’s reach.

hatch-safety runs classifiers that inspect requests and responses going to and from model inference. Meta’s stated reason for placing it outside: “Running these outside of the runtime cell means that attackers cannot disable these protections.”

privsep workers execute connector code with narrow privileges, “keeping the connected credentials out of scope of the agent.” The document explains what this is defending against. The common pattern is CLI connectors running in the same environment as the harness, and the risk is that “the agent could be coerced to change the tool code via prompt injection.”

hatch-authd stores credentials, including OAuth tokens, and the page specifies these are “stored in your VM, not in centralized Meta infrastructure.”

Sentinel is “the sole permission authority for connector actions and network egress.”

Communication between the cell and these services goes over Unix domain sockets with SO_PEERCRED and peer ACLs, which the write-up describes as “kernel authenticated, least-privilege interprocess communication with no secrets to steal.”

Surrogate tokens

The credential handling deserves separating out, because it answers a question every agent product dodges.

Code inside the cell never receives a real secret. It gets a “surrogate” token minted by authd. When a request is authorised, Sentinel swaps the surrogate for the real credential at the network boundary. Meta draws the conclusion directly: “The agent never sees real tokens, which means any attempt to coerce the agent to reveal the actual secrets via prompt-injection or otherwise is futile.”

That is a structural answer rather than a behavioural one. The agent is not trained to refuse to leak keys. It is not given keys.

Tainted egress

Every network request is evaluated by Sentinel at egress, which can inspect hostname, resolved and final destination IP, port, protocol, HTTP method, path, and the decoded request body. SSRF protection is called out specifically: restrictions “prevent an apparently public hostname resolving private infrastructure after DNS lookup.”

Asking the user to approve all of that would be unusable, so Muse tracks data flow at the kernel level. Each tool process starts clean and “becomes tainted if it reads user data.” Clean processes hitting narrowly bounded destinations can be auto-allowed. “Tainted or unverifiable processes lose auto-allow and fall back to the normal approval flow.”

The implementation is named: eBPF cgroup programs for network interception and process attribution, plus eBPF programs on Linux Security Module hooks Meta added for taint propagation.

So the question the system asks before a request leaves is not what the agent intends. It is whether this process has touched your data.

One detail is easy to skim past and is arguably the sharpest idea in the document. When Sentinel decides to ask the user, it sends the request “directly to the Muse client,” and the dialog appears “within the client UI — not via their conversation with Muse.” The answer routes back to Sentinel, not through the agent.

That closes an obvious attack. If consent happened inside the conversation, injected text could fabricate an approval, or the agent could misreport what it was asking for. Routing the prompt around the agent means a compromised agent cannot forge its own permission.

Approvals are also described as “strict capabilities, not conversational suggestions,” bound to a specific connector and use case, available as one-time, session-scoped, task-scoped, time-bounded, or perpetual.

The browser

The browser sub-agent sees “an accessibility tree snapshot of the page — not the raw DOM.” It cannot run JavaScript in the page context, has no exec in the browser process, and Chrome devtools are disabled. Credentials the user types go to secure storage and are injected at point of need, invisible to the main agent.

For purchases, the generated credential is “tied to that particular merchant, a particular dollar amount, and only valid for a limited period of time,” so a stolen one “would not be particularly useful to the attacker.”

Where Meta says this stops

The document cites Simon Willison’s “lethal trifecta” framing for prompt injection from June 2025, and says the problem “has been an obsession for us.” It claims Muse Spark 1.3 is “close to SOTA” at resisting injection, without publishing the eval numbers behind that.

Then it concedes the limit plainly: “Muse isn’t immune to attack. Prompt injection remains an open problem in the industry — and Muse will sometimes make mistakes.” The bug bounty is open to anyone, paying up to $300,000, including up to $130,000 for a successful prompt injection affecting one user.

Paying six figures for one-user injection is a reasonable proxy for how hard Meta thinks the remaining problem is.

What the architecture does not decide

Reading this alongside a user’s account of letting Muse run his Facebook Marketplace listings is instructive, because the incident is not a hole in any of the above. He reported that it gave out his home address and agreed a price he had not approved.

Every layer described here worked as documented. Sentinel governs whether an action may reach a connector or the network, at the granularity of destination, method and scope. It is not a judge of whether the sentence inside an authorised message is a good idea. Tainted egress asks whether a process read user data, not whether disclosing this particular fact to this particular stranger is wise.

The containment story is genuinely strong and the write-up is unusually specific for a launch document. It bounds what a compromised agent can reach. Deciding what an uncompromised agent should choose to say is a different problem, and this architecture does not claim to solve it.