If my agent's core task is stuck to all three properties at once and I can't break apart any single leg, what should I do?
In that situation, it usually means the agent's design itself carries a structural risk at the architectural level, and it's worth stepping back to ask: does this task genuinely need a single agent with all three capabilities at once, or could it be split into multiple sub-agents, each with only two properties, coordinating through an additional verification layer? For example, a composite agent that "reads the inbox, decides whether action is needed, and if so automatically executes the corresponding action" could be split into three roles: an agent that only reads the inbox and produces a structured summary (private data access + untrusted content exposure, but no external communication); a decision agent that decides what to do based on the structured summary (never touching raw email content directly, only processing the already-filtered result); and an execution agent that actually carries out the action (private data access + external communication, but its input comes entirely from the prior agent's structured decision, never directly exposed to raw untrusted content).
After this kind of split, no single role holds all three properties at once — even if one link is breached, the attack chain gets cut at the handoff point between roles. This approach sacrifices overall system complexity and latency in exchange for every role being independently auditable and independently permission-limited.
Approach two (draft first, then confirm) sounds the easiest to implement — should it be the default first choice?
Ease of implementation is genuinely approach two's advantage, but that doesn't mean it should be the default first pick — its actual protective strength depends heavily on a variable you can't fully control: whether the user genuinely reads the draft content carefully. The IBM Bob incident already proved that once approval requests appear frequently enough and the user gets worn down by repeated prompts, "approve" can easily degrade from "a judged gatekeeping action" into "a reflexive button click." Once it degrades to that point, the actual protection approach two provides in practice falls far short of what it looks like on paper.
A more practical way to judge is asking yourself: how often does this agent need approval? If a task workflow requires five or six approvals in a row, approach two's actual effectiveness gets substantially eroded by approval fatigue, and approach one or three (blocking risk with the architecture itself, rather than relying on the user's sustained vigilance) should be prioritized instead. If approval frequency is genuinely low — a task only needs one approval — approach two's effectiveness holds up better, and in that case it's genuinely a relatively simple and effective choice.
Approach three mentions using a "lower-privilege subprocess" for initial filtering — doesn't that subprocess itself become a new attack target?
That's a sharp question, and the answer is "yes, but at a different risk level." The subprocess genuinely does become the attacker's next target, but the key difference from the main agent is its permission scope — the subprocess is designed to only filter and do preliminary processing, with no private data access or external communication ability. Even if the subprocess itself gets breached, the attacker gets, at most, "the ability to manipulate the filtering result," not the direct ability to access private data or send something out. This means breaking apart the untrusted-content leg doesn't make the risk vanish entirely — it downgrades the risk from "the main agent gets breached and data exfiltration happens directly" to "the subprocess gets breached, and the attacker still needs to further break through the main agent's permission restrictions to cause real damage." That's one more obstacle an attacker needs to clear.
This also echoes a more fundamental principle: breaking apart any one leg of the lethal trifecta is fundamentally about migrating risk to a newly created link, not eliminating it. The subprocess's own filtering logic also needs periodic auditing, confirming it hasn't been mistakenly designed into a state that appears to filter but actually passes untrusted content through to the main agent unchanged — a filter in name only. This is also why approach three, with its higher architectural complexity, needs more ongoing maintenance investment than approach one or two.
For an agent that already applies the Rule of Two, how do I avoid accidentally adding the third property back when new features get added later?
The most direct approach is writing "check whether this violates the Rule of Two" into the pre-launch architecture review checklist as a mandatory checkpoint, rather than relying on an engineer remembering it from memory. Concretely, you can require every new feature proposal to explicitly flag: does this new feature give some existing agent role additional private data access, untrusted content exposure, or external communication ability it didn't have before? If yes, the proposal must explicitly state which leg this role originally had removed, and whether the new feature is adding that leg back — if so, this new feature shouldn't be stacked directly onto the existing role; it should instead be considered for splitting into a new, more restricted role.
A common oversight in practice is "gradual feature creep": an agent that originally could only read data (with external communication removed) later gets a "send a notification too" feature bolted directly onto the existing role because users kept asking for it, and the engineering team doesn't realize this small change just re-completed the trifecta for that role. This is also why the architecture review checklist can't just happen once at project kickoff — it needs to be tied to every change request that adds a new permission or a new tool, ensuring the Rule of Two doesn't get quietly broken by everyday feature accumulation.
Knowing what the lethal trifecta is (private data access, exposure to untrusted content, external communication) is one thing; knowing how to actually break it apart in your own agent architecture is another. Meta's AI security team publicly published the "Rule of Two" in October 2025, offering a concrete implementation principle: an agent may satisfy at most two of the three properties within a single session. This article deals with the next step — what breaking apart each of the three properties actually looks like in practice, and what the tradeoffs are for each.
If an agent's core task is processing untrusted content and communicating externally (a web-browsing assistant that auto-replies to email, say), breaking apart the private-data-access leg means confining the agent to a fully isolated environment, or one that only has access to sanitized test data — even if an injection succeeds, the attacker only gets something irrelevant. This approach's advantage is relatively simple implementation: no complex human-approval workflow is needed, and the agent can keep operating autonomously. Its disadvantage is sacrificed functional completeness — many practical scenarios genuinely need an agent to touch real private data to be meaningful (like helping a user look up their own order history); if the core task can't be separated from private data, this approach simply doesn't apply.
If an agent needs both private data access and untrusted content processing (an assistant reading an inbox and organizing to-do items based on email content, say), breaking apart the external-communication leg means changing "auto-send" into "draft first, send only after user confirmation." This approach's advantage is that even if the agent's judgment gets hijacked and generates a draft containing malicious content, it doesn't automatically cause real damage — the user has a chance to spot the anomaly on the confirmation screen. Its disadvantage is disrupted user experience: if the agent needs to complete several steps in a row, the user might be asked to approve multiple times, and this safeguard's actual effectiveness depends entirely on whether the user genuinely reads the draft carefully rather than reflexively clicking confirm at a familiar interface — exactly the same risk seen in the IBM Bob incident, where "human-in-the-loop approval became security theater."
If an agent needs both private data access and external communication ability (a financial assistant that can check account balances and execute transfers, say), breaking apart the untrusted-content leg means strictly limiting the agent to fully trusted, controlled input sources — not reading arbitrary webpage content or third-party documents pasted in by the user directly. If content like that genuinely needs processing, route it first through an independent, lower-privilege subprocess for preliminary handling and filtering, then hand the result — not the raw content — to the main agent that has actual operating authority. This approach's advantage is preserving the agent's autonomy and functional completeness; its disadvantage is the highest architectural complexity, requiring an extra isolation layer and process, and "what counts as trusted input" itself needs continuous maintenance and updating — it's not a one-time setup that stays solved forever.
None of the three approaches is universally better — the choice depends on which property your agent's core value proposition can't do without. If the agent's value is "help me handle my own data," private data access usually can't be removed, so consider approach two or three. If the agent's value is "help me browse the outside world," exposure to untrusted content usually can't be removed, so consider approach one or two. If the agent's value is "help me automatically complete a sequence of actions without me watching constantly," autonomous external communication is usually the core selling point, so consider approach one or three. In practice, many agent systems apply different approaches to different functional modules — the same assistant might follow approach one (never touching private data) for general queries, but approach two (draft first, confirm after) for account operations. There's no rule that an entire system has to follow the same disassembly logic throughout.
If you're designing or auditing an agent system's security architecture, the Rule of Two gives you a concrete acceptance criterion: for every actual operational path, confirm exactly which leg it broke apart, and whether that disassembly is genuinely effective in practice (for instance, does "draft confirmation" actually get read carefully by users, or is it just a formality checkpoint). This bears directly on your accountability foundation — architecture documentation stating clearly "this feature module deliberately removed private data access because the core task doesn't need it" represents an entirely different level of governance responsibility than deploying without ever assessing the trifecta at all. The former can clearly point, in a later investigation, to "this path's risk was already assessed and mitigated"; the latter requires rebuilding the entire judgment process from scratch, and quite possibly only gets forced into doing so after a real incident has already occurred.