A system designed around an untrusted model can be secure even when the model is not. Six architectural patterns buy injection resistance by giving up generality, and the strongest of them keeps 77% of task utility against 84% undefended — a real seven-point cost, and the only defence family in this wiki whose guarantee does not depend on the model behaving.
The mechanism
The pattern is Willison’s, from April 2023: a privileged LLM that plans and holds tools but never reads untrusted content, and a quarantined LLM that reads untrusted content but has no tools. Between them sits a non-LLM controller. The load-bearing detail is easy to miss: the planner never dereferences untrusted values. Tool outputs live in variables or symbolic references that only the controller resolves, and a second model without that indirection buys nothing.
CaMeL is the first concrete instantiation and the one worth understanding, because its numbers are public. The quarantined model parses untrusted data into a schema the planner specified; the planner writes Python calling tools and calling the quarantined model as a function; a custom interpreter enforces per-value capability tags carrying provenance and an allowed-reader set before any tool call fires. Control and data flow are extracted from the trusted query, so untrusted data can never affect program flow.
The measured results, dated to June 2025 on the AgentDojo suite:
- 77% of tasks solved with provable security, against 84% undefended. Older write-ups quote 67%, which was the March 2025 version. The utility gap is about seven points rather than zero.
- Isolation alone, with no security policies installed, took successful attacks against one frontier model from 300 to 0 out of 949. That is attributable to explicit planner/quarantine separation by itself. It is also against a fixed, non-adaptive attack suite, so it should not be read as “prompt injection eliminated.”
- A cheap quarantined model costs almost nothing: pairing a small model as quarantine with a frontier planner gave roughly 1% utility loss for an estimated 12% median-task cost reduction.
- Overhead is the real price: 2.82× input tokens and 2.73× output tokens at the median task, the highest of any defence measured, driven by the language-specification system prompt and error-fixing retries. Spotlighting, by comparison, costs about 1×.
The pattern family sits on one trade-off curve from most restrictive to most general:
- Action-selector: the model is a switch statement over predefined calls with no feedback from results. The paper calls such agents immune, the strongest claim in the set and the least capable design.
- Plan-then-execute: fix the plan before untrusted reading starts. This gives control-flow integrity; the residual risk is argument content, not action choice.
- LLM map-reduce: one isolated agent per untrusted document, so a malicious file cannot influence how the others are processed. (This is a special case of dual LLM, not a separate lineage; the map-reduce framing traces to Dean and Ghemawat, not to Willison.)
- Dual LLM: the pattern above.
- Code-then-execute: the agent writes a program rather than a plan; CaMeL is the instantiation.
- Context-minimization: strip prior content from context to blunt user-prompt injections, including payloads pasted from the web. The only pattern aimed at the user prompt rather than at tool output, which makes it the one that matters most for citizen developers pasting prompts they found online.
OWASP has canonized the top of this list: separate control-flow generation from untrusted data processing, name CaMeL as the reference architecture, and enforce data flow through system design rather than relying on model alignment. Its complementary recommendation is worth pairing: prefer API templates over model-generated calls, letting the model fill established parameters only, the parameterized-SQL move applied to tools.
Two independent research groups, a workshop paper and a standards body state the same thesis: a system designed around an untrusted model can be secure even when the model is not. That is the best-sourced claim on this page, and why architecture beats guardrails here.
What to do
For any citizen agent that reads external content, fix the plan before the reading starts. Plan-then-execute is the cheapest member of this family, needs no special infrastructure, and converts “the injected text chose a different action” into “the injected text supplied a bad argument”, a large reduction for a small change.
Use one isolated pass per untrusted document when processing many. Map-reduce isolation is trivially implementable on any platform and stops a poisoned file from steering how the other forty are read.
Give the planner references rather than values. One implementation detail matters most here: the
privileged model should see $DOC1 and the controller should resolve it. Two models where the
planner still reads the content is theatre.
Put quarantine on a cheap model. The measured pairing costs about 1% utility and saves money, one of the few security controls with a negative price.
Reserve full capability-tracking for agents the firm would gate anyway. Whole-ecosystem participation is expensive and the authors say so, citing CHERI as precedent, with their own qualifier: inside a controlled environment where the firm owns all the tools, it may be feasible. That describes an internal agent estate, and not an agent wired to arbitrary third-party MCP servers.
Measure it rather than asserting it: injection resistance is testable against a public benchmark; see evals. One preprint’s harness shows the isolation trade in the MCP setting, directionally useful rather than an industry measurement: strict isolation cut attack success roughly sevenfold and cost about a third of task completion.
How you’d know it’s working
An injection string in the test corpus provably cannot alter the action sequence, because the plan can be shown to have been fixed before the untrusted read. That is a demonstrable structural property, unlike a filter’s catch rate.
Someone can name the tasks the architecture makes impossible. If nothing broke, nothing was actually separated.
The planner’s context can be dumped and contains no untrusted content. That is a one-line check and the whole pattern.
What this doesn’t solve
The quarantined model is still injectable. It cannot call tools, but it can encode sensitive data in its structured output or pass an injection onward to a colleague. Quarantine bounds the blast radius without cleaning the data.
Control-flow integrity leaves data flow unprotected. Plain dual LLM protects which actions run, not what goes into them. The SQL-injection-parameters analogy is the authors’ own, and CaMeL’s paper pushes it further than most retellings: in their setting, argument manipulation can escalate to arbitrary code execution.
Side channels are unsolved, and the CaMeL authors devote a section to saying so. So is the de-classification tension: every prompt asking a user to approve a data flow is one more approval to fatigue.
“Data requires action” tasks cannot be planned at all. When the actions to take are specified inside the untrusted data (“do what this email asks”), no model in the evaluation solves them, because the pattern’s whole premise is that untrusted data must not determine control flow. This is a structural limit rather than a tuning problem, it is independently named as an open problem elsewhere, and some real workflows are simply out of reach.
Text-to-text attacks with no data-flow consequence are explicit non-goals, including injection-induced phishing where the agent’s output manipulates the reader.
The benchmark results are static. Every out-of-band defence in this family reports near elimination on AgentDojo, and adaptive, defence-aware attacks previously broke twelve in-band defences at over 90% success. As of mid-2026 no adaptive attack on CaMeL is published: the adaptive-evaluation work lists it as a future target. The authors themselves speculate a return-oriented-programming-style attack could compose individually permitted control-flow blocks into a malicious sequence, open rather than refuted. Newer work extending the family to computer-use agents already names a new attack class, “branch steering,” against plan-locked architectures.
And none of this is a product. These are papers and a reference implementation; there is
nothing a citizen developer can switch on. Enterprise gap analyses name three real limits: CaMeL
assumes a trusted user prompt, ignores side channels, and pays a dual-model performance cost. This
is what a platform team builds into the agent runtime, so it sits in patterns/ rather than
controls/. The fine-tuning-based alternatives in this space are unavailable to anyone on
hosted frontier models, while dual-LLM separation needs no model access at all, its underrated
advantage.
See also
- Prompt injection and goal hijack — the failure these patterns are designed against.
- The lethal trifecta — the mental model these patterns implement by cutting a leg architecturally.
- Data exfiltration — what leaks when quarantine is absent.
- Three-zone architecture — the coarser containment this refines.
- Runtime guardrails and policy enforcement — the layer that goes on top, after the architecture.
- Evals — where injection resistance gets measured rather than claimed.
- MCP — why the capability approach stops working once tools are third-party.