The Trust Boundary
In one line: if the component that decides what to do never reads attacker-controlled text, injected instructions have nowhere to land.
The idea, borrowed from somewhere older
Operating systems solved a version of this decades ago. Privileged code does not parse untrusted input; it delegates parsing to something unprivileged and accepts only a narrow, validated result. The parser can be compromised and the damage stays inside it.
Simon Willison proposed the same shape for language models in 2023 as the dual LLM pattern. Two roles:
- A privileged model that plans and calls tools. It sees the user's request and the tool schemas. It never sees retrieved content.
- A quarantined model that reads untrusted text — documents, pages, tool results — and has no tool access at all.
Between them passes not text but references. The quarantined model returns "the answer is in variable $3"; the privileged model orchestrates without ever reading $3's contents.
An injection inside the document can say anything it likes. It is speaking to a component with no capabilities, whose only output channel is a reference the planner will not interpret as an instruction.
What that buys, and what it costs
The buy is real: the untrusted text and the capability to act are never in the same context, so the injection's instructions reach nothing that can execute them.
The cost is also real, and worth being honest about.
Capability drops. The planner is working blind. "Summarise these three documents and email the one that mentions the outage" requires the planner to know which one mentions the outage — which requires reading them. Strict separation makes a large class of ordinary tasks awkward or impossible.
Data still has to flow somewhere. If the quarantined output is eventually shown to the user or passed to a tool, its content is back in play. The pattern moves the boundary; it does not remove the need for one.
Two models, two bills. Extra latency and extra cost on every request that touches untrusted content.
Capabilities: the extension that makes it practical
Google DeepMind's CaMeL, published in 2025, extends the dual-LLM idea to something more deployable. Rather than forbidding data flow, it tracks it.
The privileged model emits a program rather than prose. That program runs in a custom interpreter that attaches a capability to every value — where it came from, who is allowed to see it, what may be done with it. Untrusted values propagate their provenance through the computation. A security policy is then checked at the point of use: this email address came from an untrusted document, so it may not be a send_email recipient.
The distinction that makes it work: control flow comes from the privileged model, never from data. An injected instruction can influence a value; it cannot influence which operations run.
This is information-flow control, a well-understood security technique, applied to a new kind of program. It is more permissive than strict quarantine — data can flow, and the policy decides whether a particular flow is allowed.
The residual limitation is worth stating: it constrains what can be done with tainted data, not what a model concludes from it. If an injected document convinces the quarantined model that the outage was on Tuesday, and the user is shown that summary, no capability system catches it. Integrity of content is not the same as integrity of control.
The version you can actually propose in an interview
Full CaMeL is a research system. The practical distillation is three rules, and they are defensible in any design:
Label every input by provenance at ingestion. User turn, system policy, retrieved content, tool result. Carry the label with the text; do not reconstruct it later.
Never let untrusted text choose an action. Tool selection and arguments derive from the user's request and validated state. Retrieved content can inform an answer; it cannot nominate a recipient, a file path or an amount.
Check at the sink, not at the source. The decision to allow belongs where the effect happens — the tool call, the render, the write — because that is the only place with enough context to judge it.
Where the boundary usually leaks
Three places, all of them common:
Conversation history. A retrieved document gets summarised into the transcript, and next turn the summary is indistinguishable from the user's own words. Provenance has to survive summarisation, or it survives exactly one turn.
Tool results. An API response is untrusted content too. Teams label retrieval carefully and treat tool output as though it came from their own system, which is how a compromised upstream service becomes an injection channel.
The system prompt itself. Templated user or retrieved data interpolated into the system prompt promotes untrusted text to the highest-trust position in the context. This is the string-concatenation bug, one abstraction layer up.
Key takeaway
Privilege separation is the only defence that does not depend on detection. Keep the planning-and-acting component away from untrusted text, label every input by provenance at ingestion, and enforce at the sink. The practical version is not full quarantine — it is that untrusted content may inform an answer but may never choose an action.
Next: the permission model those tool calls run under.