29 September 2026 · 6 min read
Muse doesn't trust its own model, and that's the whole design
Meta's new personal agent can browse the web, spend your money and read your email. The interesting part isn't the model. It's that the model is never allowed to see the keys.
By Dr. Aki Wijesundara, TAI Labs

Most people building an agent that can act on a person's behalf reach for the same fix when something could go wrong: write a better system prompt. Tell the model not to leak the API key, not to buy the wrong thing, not to fall for a prompt injection hidden in a web page. Meta's new personal agent, Muse, launched September 8, 2026, is built on the opposite assumption. Its own safety engineer, Tarek Sheasha, writes that the team designed the system to assume the agent may be under attack and limit the damage when it is. The model never gets the chance to leak a secret it never held.
The agent runs in a cell that can't see the keys
Muse gives each user a dedicated cloud VM, an isolated Linux box with its own browser, storage and compute. Inside that VM, the actual agent (internally named Hatch) runs in a systemd-nspawn container Meta calls the runtime cell. Root inside that cell maps to an unprivileged host user, so cell root is not host root. The cell gets filtered system calls, limited kernel capabilities and its own filesystem, separate from anything sensitive.
Two services outside that cell do the real work of keeping the agent in check. Sentinel is the gatekeeper: nothing that reaches the outside world, whether that's calling an app's API or sending a request over the network, happens without its approval. authd is the vault: it's the only place that holds your actual passwords and OAuth tokens.
Here's how the two work together. When the agent wants to call an API, it never gets the real key. It gets a surrogate token, a placeholder with no value on its own. Sentinel decides whether that specific request should go through. If it approves, authd swaps the surrogate for the real credential, but only at the network boundary, the exact point where the request leaves the VM. The model itself never sees that swap happen. A third service, hatch-safety, runs its own classifiers on everything going in and out, as one more check the model has no say over.
That design is what defeats the most common attack. If a prompt injection convinces the model to give up its "secret," there's nothing real to give up. The model never held one.

Not every action needs a human, but the risky ones stop and wait
Muse's human-in-the-loop system only interrupts you for actions that are hard to undo, like sending an email or making a purchase. Read-only, previously allowed, or low-risk actions proceed without asking, because the team explicitly designed against banner blindness, the failure mode where people approve everything just to make the dialogs stop.
The mechanism behind that is kernel-level, not prompt-level. Every tool process starts clean and becomes "tainted" the moment it reads real user data. A clean process making a narrowly allow-listed request can pass without interruption. A tainted one falls back to asking. Meta built this with eBPF cgroup programs for network interception and Linux Security Module hooks for taint tracking, which means the taint state can't be argued away by a persuasive prompt. When an approval is needed, Sentinel offers the user a choice of grant: one-time, session-scoped, task-scoped, time-bounded, or perpetual, and every later request has to match that exact scope.

Meta is pricing its own trust gap in public
The team is honest that this doesn't make Muse immune to attack. Prompt injection is still, in their words, an open industry problem. So alongside launch, Meta opened its bug bounty program to the public: up to $300,000 for a valid report, and up to $130,000 specifically for a successful prompt injection attempt that affects one user. That second number is the more informative one. It's Meta's own estimate of what a single compromised Muse account is worth to defend, in a program explicitly built to find the failures their internal red team hasn't yet.

The defense behind that bounty is layered on purpose. Model-level training pushes Muse Spark 1.3, the model at the core, to recognize and resist injected instructions, which Meta says is close to state of the art on that capability, though it publishes no specific number. Anything that enters the model's context from outside is labeled untrusted at the harness level. An ensemble of classifiers, trained separately from the model, screens content for injection attempts in parallel. And the human-in-the-loop approvals sit on top of all of it, as the last check before anything leaves the VM. Software engineer and security researcher Simon Willison's "lethal trifecta", private data access plus untrusted content plus outbound communication, is the framework Meta names directly as the shape of the risk they're defending against.

A purchase is a single-use secret, not your real card
Buying things is one of the most common things people ask Muse to do, and Meta treats it with the most scrutiny of any built-in flow. On a site where you've already saved a card, checkout-page detection triggers a human approval showing the exact purchase details, every time. For a new site, Muse holds funds in a wallet (Stripe Link at launch, with Shop Pay coming) and mints a single-use card number for that specific transaction. That number is tied to one merchant, one dollar amount, and a limited time window. If it leaks through a prompt injection or any other route, it's worthless to whoever steals it, because it was never reusable in the first place.

Build the same pattern into your own agents
You don't need Meta's infrastructure to use this idea. The reusable lesson is simple: never let the model hold a secret it doesn't need to see, and gate any action that's expensive to undo behind an explicit approval step that the model itself cannot skip. The sketch below shows the shape of it with the Anthropic SDK: a purchase tool that only ever hands the model a placeholder, and a human check that has to return true before the real charge goes through.
import anthropic
client = anthropic.Anthropic()
# surrogate id -> real charge details, kept out of context
PENDING = {}
def propose_purchase(merchant, amount_cents, item):
"""Tool the model calls. It never sees a real card number."""
surrogate = f"pending-{len(PENDING) + 1}"
PENDING[surrogate] = {
"merchant": merchant,
"amount_cents": amount_cents,
"item": item,
}
return {"surrogate_id": surrogate,
"status": "awaiting_approval"}
def human_approve(surrogate_id: str) -> bool:
d = PENDING[surrogate_id]
reply = input(
f"Approve ${d['amount_cents']/100:.2f} at {d['merchant']} "
f"for {d['item']}? [y/N] "
)
return reply.strip().lower() == "y"
def execute_if_approved(surrogate_id: str):
"""Only this function ever sees the real payment credential."""
if not human_approve(surrogate_id):
return {"status": "declined"}
d = PENDING.pop(surrogate_id)
real_card = get_scoped_single_use_card(
d["merchant"], d["amount_cents"]
)
return charge(real_card, d["merchant"], d["amount_cents"])
resp = client.messages.create(
model="claude-sonnet-5", max_tokens=1024,
tools=[{"name": "propose_purchase", "input_schema": {
"type": "object",
"properties": {"merchant": {"type": "string"},
"amount_cents": {"type": "integer"},
"item": {"type": "string"}},
"required": ["merchant", "amount_cents", "item"]}}],
messages=[{"role": "user",
"content": "Buy the sweatshirt, size M."}],
)The model calls propose_purchase and gets back nothing but a placeholder id. execute_if_approved is the only code path that ever touches a real credential, and it runs outside the model's control entirely. That's the whole pattern Muse runs at much larger scale: keep the secret out of the context window, and put a human, not a prompt, between the model and anything that's expensive to undo.
This week, pick one tool in an agent you're running that currently gets a real secret in its arguments (an API key, a card number, write access to a mailbox) and rewrite it to take a surrogate id instead, with the real value swapped in by a separate function the model never calls directly. That one change closes the most common way a persuaded model does real damage.
Every figure and architecture detail here is Meta's own account of the system at launch: ai.meta.com/muse, introducing.muse.ai ("How We Designed Muse," Mona Sarantakos with Christine Awad, September 2026), and research.meta.ai ("How We Built Safety Into Muse," Tarek Sheasha, September 8, 2026), read on September 28, 2026.