Phantom messages: when your AI teammate speaks as you
There is a bug in Claude Code’s multi-agent system that should worry anyone running team architectures. #40166 documents it with reproduction steps.
The setup: you spawn teammate agents using TeamCreate and Agent. They do work. They report back via SendMessage. Normal multi-agent orchestration.
The problem: the teammate’s SendMessage content sometimes appears as a Human: turn in the conversation. The orchestrator agent sees it as something the user typed. It acts on it. The user did not type it.
In the reported case, phantom messages caused the orchestrator to shut down agents prematurely and take actions the user never requested. The reporter used a canary-word protocol to confirm the messages were fabricated by the system, not injected externally.
Why this matters for hooks
No hook can intercept this. The phantom message appears in conversation turn management, not in a tool call. There is no PreToolUse event because no tool is being used. The model simply receives text labeled as coming from the user, and it complies.
This is the kind of failure that enforcement tools cannot address. The enforce-hooks known limitations catalog now includes 53 documented platform limitations, and this is one of the few where there is no hook-level workaround at all. The trust boundary between agent messages and user messages is broken at the conversation protocol level.
When it happens
The reporter observed phantom messages in two consecutive sessions. Both were long sessions with frequent 529 (overloaded) errors and context compression. That pattern suggests the conversation state gets corrupted when the runtime recovers from API overload or compresses context across agent boundaries.
If you run short sessions with few agents, you may never see this. If you run long sessions with frequent teammate spawns and shutdowns, especially under load, you should watch for it.
What you can do
The reporter’s canary-word approach is the best defense right now: embed a unique word in your actual messages and check whether “user” messages contain it. If a Human: turn appears without your canary, it is a phantom.
Beyond that: monitor. If the orchestrator starts taking actions you did not request, check the conversation history for messages you did not type. The tell is that phantom messages are usually teammate summaries (deploy verification reports, status updates) that got promoted from SendMessage content to Human: turns.
The underlying fix needs to come from the platform. The conversation protocol should distinguish user input from inter-agent messages, and the runtime should never label a SendMessage payload as a Human: turn regardless of context compression state.
Until then, trust but verify. Especially in long sessions under load.