The blind spot in current AI guardrails
Guardrail middleware for AI agents is maturing fast. LangChain ships native guardrails. NeMo Guardrails and Guardrails AI are established. Between input filtering, output moderation, tool sandboxing, and audit logging, there’s a real defense-in-depth stack available today.
All four of those layers check one agent, one message, at one point in time. None of them ask a different question: is this same payload echoing across three different agents in my system right now?
That question — propagation across a mesh, not content within a single message — is exactly the mechanism a self-replicating prompt attack (the “Morris-II” class) exploits. An adversarial input tricks Agent A into mirroring that input into its own output. Any downstream agent that consumes A’s output re-triggers the same behavior. No file dropped, no code executed — the conversation itself is the propagation mechanism.
I built ImmuneMesh — a sandboxed research prototype — to test one idea: give a multi-agent mesh a shared memory, the way biological adaptive immunity works, so once one agent is fooled, the rest aren’t. 🧠
How it works ⚙️
ImmuneMesh runs as LangGraph middleware, attached at wrap_model_call. Two independent detection signals feed a shared “antibody store”:
Mirroring score 🪞 — cosine similarity between an agent’s input and its own output embeddings.
Canary token 🐤 — a random per-call token silently injected into the system prompt. A legitimate agent never reproduces it.
Once any agent confirms a threat, every other agent checks new input against that shared memory first — before even calling its own model. A match means instant quarantine of that message, mesh-wide.
def wrap_model_call(self, request, handler):
input_embedding = embed(input_text)
# Check the shared antibody store BEFORE calling the model at all 🛑
matched_antibody, scor``e = self.store.check(input_embedding)
if matched_antibody:
return ModelResponse(result=[AIMessage(
content="[BLOCKED BY IMMUNEMESH — known threat pattern]"
)])
...
What broke: the false-positive problem ⚠️
Every early demo proved the detector catches attacks. The harder question is: how often does it wrongly flag normal work?
Download the Medium app
I ran it against eight realistic benign task categories — summarization, translation, Q&A, proofreading — at a fixed mirroring threshold. Three false-positive:
CaseScoreFlagged?Off-topic summarization0.804
✅ Yes Instruction confirmation 0.920
✅ Yes Verbatim proofreading 0.902
✅ Yes Confirmed Attack0.549❌ No (Caught by Canary)
The fix, and the bootstrap bug 🐛
The fix is a per-agent adaptive baseline. Instead of one global number, each agent learns its own normal. Building this surfaced a real bootstrap deadlock: the first version gated “is this safe to learn from” on the same threshold it was replacing. An agent whose true normal was high could never accumulate enough history to graduate out of cold start.
The Fix: Canary detection now gates learning. Mirroring becomes purely advisory until an agent has enough history. Canary detection stays absolute — a baseline can learn “this agent mirrors 90%,” but it must never learn “leaking my system prompt is normal.”
Research Limitations & Honest Scope 🧐
This is a research prototype. It is not adversarially hardened, and “baseline poisoning” — where an attacker slowly shifts an agent’s “normal” definition — remains an open research problem. This project is my attempt to map the “cross-agent propagation” blind spot. I’d genuinely welcome pushback, alternative approaches, or pointers to prior work I’ve missed.
Explore the Research: ImmuneMesh on GitHub
Top comments (0)