Bug type
Regression (worked before, now fails)
Beta release blocker
No
Summary
iMessage reflects assistant outbound text back as inbound user messages in direct chat, causing loops.
Steps to reproduce
- send message to agent in imessage.
- agent sends message back
- agent receives its own message back
- agent keeps replying to its own messages
- eventually agent stops replying to self, but echo persists
Expected behavior
expected behavior is that the agent would not see its own message returned. there would be a smooth conversation with no filtering required.
Actual behavior
Evidence:
-
Session metadata shows self-addressed route:
~/.openclaw/agents/main/sessions/sessions.json
origin.from == origin.to == imessage:+xxxxxxxxxx
-
In session log, assistant messages are re-ingested as user content with control-char prefixes (e.g. ��\u0000):
~/.openclaw/agents/main/sessions/6b18f336-84ff-4525-9736-32eaece59b25.jsonl
-
Runtime decision path:
/opt/homebrew/lib/node_modules/openclaw/dist/monitor-provider-ClqFz1Hj.js
function resolveIMessageInboundDecision()
around line ~917 (params.message.is_from_me branch)
Root cause:
For self-chat-shaped routing, is_from_me messages could continue if echo-cache match missed, so reflected assistant text could dispatch as inbound.
Local hotfix that resolved it:
Force-drop all inbound is_from_me iMessage events (including self-chat) in resolveIMessageInboundDecision:
if (params.message.is_from_me) {
params.selfChatCache?.remember(selfChatLookup);
return { kind: "drop", reason: isSelfChat ? "from me self-chat" : "from me" };
}
Request:
Please patch upstream iMessage monitor so inbound is_from_me cannot dispatch, and harden reflection detection against control-char-prefixed reflected payloads.
OpenClaw version
2026.3.31 / 2026.4.1
Operating system
macOS Tahoe 26.3
Install method
Install method: npm (global install) under Homebrew Node on macOS arm64; CLI at /opt/homebrew/bin/openclaw, package root /opt/homebrew/lib/node_modules/openclaw. Gateway launched as macOS LaunchAgent (ai.openclaw.gateway.plist).
Model
google/gemini-3.1-flash-lite-preview, openrouter/qwen/qwen3.6-plus-preview:free
Provider / routing chain
Provider / routing chain: iMessage (Apple Messages) -> local imsg CLI bridge (channels.imessage.cliPath="imsg", service="imessage") -> OpenClaw local gateway (LaunchAgent, ws://127.0.0.1:18789, no reverse proxy/tailscale) -> agent runtime -> model router/provider (OpenRouter; observed on qwen/qwen3.6-plus-preview:free during failures) -> response back through OpenClaw -> imsg send -> Apple Messages. Reflection path seen in this bug: outbound imsg send is re-emitted by imsg watch as inbound (is_from_me=true) in the same thread, then re-dispatched by OpenClaw.
Additional provider/model setup details
OpenClaw 2026.4.1 iMessage echo bug report
Issue:
iMessage reflects assistant outbound text back as inbound user messages in direct chat, causing loops.
Evidence:
-
Session metadata shows self-addressed route:
~/.openclaw/agents/main/sessions/sessions.json
origin.from == origin.to == imessage:+xxxxxxxxxx
-
In session log, assistant messages are re-ingested as user content with control-char prefixes (e.g. ��\u0000):
~/.openclaw/agents/main/sessions/6b18f336-84ff-4525-9736-32eaece59b25.jsonl
-
Runtime decision path:
/opt/homebrew/lib/node_modules/openclaw/dist/monitor-provider-ClqFz1Hj.js
function resolveIMessageInboundDecision()
around line ~917 (params.message.is_from_me branch)
Root cause:
For self-chat-shaped routing, is_from_me messages could continue if echo-cache match missed, so reflected assistant text could dispatch as inbound.
Local hotfix that resolved it:
Force-drop all inbound is_from_me iMessage events (including self-chat) in resolveIMessageInboundDecision:
if (params.message.is_from_me) {
params.selfChatCache?.remember(selfChatLookup);
return { kind: "drop", reason: isSelfChat ? "from me self-chat" : "from me" };
}
Request:
Please patch upstream iMessage monitor so inbound is_from_me cannot dispatch, and harden reflection detection against control-char-prefixed reflected payloads.
Logs, screenshots, and evidence
# OpenClaw iMessage Echo Evidence (Redacted, Compact)
Generated: Wed Apr 1 22:57:18 EDT 2026
## Summary
- Direct iMessage thread intermittently reflected assistant outbound text back as inbound user input.
- Session metadata showed self-addressed routing shape (origin.from == origin.to).
- Reflected payloads often contained leading control chars (e.g., ���).
- Local mitigation (drop all inbound is_from_me events) stopped the loop in live testing.
## 1) Session Origin Metadata
{
"key": "agent:main:main",
"sessionId": "6b18f336-84ff-4525-9736-32eaece59b25",
"chatType": "direct",
"deliveryContext": {
"channel": "imessage",
"to": "imessage:<USER_E164>",
"accountId": "default"
},
"origin": {
"label": "imessage:<USER_E164>",
"provider": "heartbeat",
"surface": "imessage",
"chatType": "direct",
"from": "imessage:<USER_E164>",
"to": "imessage:<USER_E164>",
"accountId": "default"
}
}
## 2) Reflected Inbound Sequence (selected events)
[2026-04-02T01:57:20.579Z] assistant: All good now — message came through clean, no echoes. Whatever was causing the loop, restarting the Messages app on your Mac broke it. 👻
[2026-04-02T01:57:21.304Z] user: Conversation info (untrusted metadata): { "message_id": "7274", "sender_id": "<USER_E164>", "sender": "<USER_E164>", "timestamp": "Wed 2026-04-01 21:57 EDT", "was_mentioned": true } Sender (untrusted metadata): { "label": "+1…
[2026-04-02T01:57:24.141Z] assistant: NO_REPLY
[2026-04-02T01:57:46.538Z] user: Conversation info (untrusted metadata): { "message_id": "7276", "sender_id": "<USER_E164>", "sender": "<USER_E164>", "timestamp": "Wed 2026-04-01 21:57 EDT", "was_mentioned": true } Sender (untrusted metadata): { "label": "+1…
[2026-04-02T01:57:49.488Z] assistant: NO_REPLY
[2026-04-02T01:58:16.193Z] user: Conversation info (untrusted metadata): { "message_id": "7278", "sender_id": "<USER_E164>", "sender": "<USER_E164>", "timestamp": "Wed 2026-04-01 21:58 EDT", "was_mentioned": true } Sender (untrusted metadata): { "label": "+1…
[2026-04-02T01:58:18.533Z] assistant: NO_REPLY
## 3) Gateway Delivery Burst During Echo Window
## 4) Local Mitigation Diff
--- /opt/homebrew/lib/node_modules/openclaw/dist/monitor-provider-ClqFz1Hj.js.bak-20260401-221750-fromme-drop 2026-04-01 22:17:50
+++ /opt/homebrew/lib/node_modules/openclaw/dist/monitor-provider-ClqFz1Hj.js 2026-04-01 22:18:17
@@ -916,27 +916,9 @@
const hasInboundGuid = Boolean(normalizeReplyField(params.message.guid));
if (params.message.is_from_me) {
params.selfChatCache?.remember(selfChatLookup);
- if (isSelfChat) {
- const echoScope = buildIMessageEchoScope({
- accountId: params.accountId,
- isGroup,
- chatId,
- sender
- });
- if (params.echoCache && (bodyText || inboundMessageId) && hasIMessageEchoMatch({
- echoCache: params.echoCache,
- scope: echoScope,
- text: bodyText || void 0,
- messageIds: inboundMessageIds,
- skipIdShortCircuit: !hasInboundGuid
- })) return {
- kind: "drop",
- reason: "agent echo in self-chat"
- };
- skipSelfChatHasCheck = true;
- } else return {
+ return {
kind: "drop",
- reason: "from me"
+ reason: isSelfChat ? "from me self-chat" : "from me"
};
}
if (isGroup && !chatId) return {
## 5) Validation
- After applying the mitigation and restarting gateway, live tests no longer produced agent-side echo loops.
- This is a hotfix in installed dist code and may be overwritten by future openclaw update.
Impact and severity
Affected: imessage/agents
Severity: Annoying, even the agent said it was annoying. Blocks workflows because agent kept replying to self, data risk because agent was caught in a feedback loop and thought I had confirmed I wanted it to do whatever it was suggesting. Eventually the agent would calm down and stop messaging itself. I thought it was the model at first but after changing models it still persisted.
Frequency: always. every message.
Consequence: Feedback loop caused non-approved config edits, churn and gateway crashes, LOTS of api token usage.
Additional information
Pretty sure last known clean version without the bug was 2026.3.28 but it could have been an earlier one. It seems like this started with 2026.3.31.
Bug type
Regression (worked before, now fails)
Beta release blocker
No
Summary
iMessage reflects assistant outbound text back as inbound user messages in direct chat, causing loops.
Steps to reproduce
Expected behavior
expected behavior is that the agent would not see its own message returned. there would be a smooth conversation with no filtering required.
Actual behavior
Evidence:
Session metadata shows self-addressed route:
~/.openclaw/agents/main/sessions/sessions.json
origin.from == origin.to == imessage:+xxxxxxxxxx
In session log, assistant messages are re-ingested as user content with control-char prefixes (e.g. ��\u0000):
~/.openclaw/agents/main/sessions/6b18f336-84ff-4525-9736-32eaece59b25.jsonl
Runtime decision path:
/opt/homebrew/lib/node_modules/openclaw/dist/monitor-provider-ClqFz1Hj.js
function resolveIMessageInboundDecision()
around line ~917 (params.message.is_from_me branch)
Root cause:
For self-chat-shaped routing, is_from_me messages could continue if echo-cache match missed, so reflected assistant text could dispatch as inbound.
Local hotfix that resolved it:
Force-drop all inbound is_from_me iMessage events (including self-chat) in resolveIMessageInboundDecision:
if (params.message.is_from_me) {
params.selfChatCache?.remember(selfChatLookup);
return { kind: "drop", reason: isSelfChat ? "from me self-chat" : "from me" };
}
Request:
Please patch upstream iMessage monitor so inbound is_from_me cannot dispatch, and harden reflection detection against control-char-prefixed reflected payloads.
OpenClaw version
2026.3.31 / 2026.4.1
Operating system
macOS Tahoe 26.3
Install method
Install method: npm (global install) under Homebrew Node on macOS arm64; CLI at /opt/homebrew/bin/openclaw, package root /opt/homebrew/lib/node_modules/openclaw. Gateway launched as macOS LaunchAgent (ai.openclaw.gateway.plist).
Model
google/gemini-3.1-flash-lite-preview, openrouter/qwen/qwen3.6-plus-preview:free
Provider / routing chain
Provider / routing chain: iMessage (Apple Messages) -> local imsg CLI bridge (channels.imessage.cliPath="imsg", service="imessage") -> OpenClaw local gateway (LaunchAgent, ws://127.0.0.1:18789, no reverse proxy/tailscale) -> agent runtime -> model router/provider (OpenRouter; observed on qwen/qwen3.6-plus-preview:free during failures) -> response back through OpenClaw -> imsg send -> Apple Messages. Reflection path seen in this bug: outbound imsg send is re-emitted by imsg watch as inbound (is_from_me=true) in the same thread, then re-dispatched by OpenClaw.
Additional provider/model setup details
OpenClaw 2026.4.1 iMessage echo bug report
Issue:
iMessage reflects assistant outbound text back as inbound user messages in direct chat, causing loops.
Evidence:
Session metadata shows self-addressed route:
~/.openclaw/agents/main/sessions/sessions.json
origin.from == origin.to == imessage:+xxxxxxxxxx
In session log, assistant messages are re-ingested as user content with control-char prefixes (e.g. ��\u0000):
~/.openclaw/agents/main/sessions/6b18f336-84ff-4525-9736-32eaece59b25.jsonl
Runtime decision path:
/opt/homebrew/lib/node_modules/openclaw/dist/monitor-provider-ClqFz1Hj.js
function resolveIMessageInboundDecision()
around line ~917 (params.message.is_from_me branch)
Root cause:
For self-chat-shaped routing, is_from_me messages could continue if echo-cache match missed, so reflected assistant text could dispatch as inbound.
Local hotfix that resolved it:
Force-drop all inbound is_from_me iMessage events (including self-chat) in resolveIMessageInboundDecision:
if (params.message.is_from_me) {
params.selfChatCache?.remember(selfChatLookup);
return { kind: "drop", reason: isSelfChat ? "from me self-chat" : "from me" };
}
Request:
Please patch upstream iMessage monitor so inbound is_from_me cannot dispatch, and harden reflection detection against control-char-prefixed reflected payloads.
Logs, screenshots, and evidence
Impact and severity
Affected: imessage/agents
Severity: Annoying, even the agent said it was annoying. Blocks workflows because agent kept replying to self, data risk because agent was caught in a feedback loop and thought I had confirmed I wanted it to do whatever it was suggesting. Eventually the agent would calm down and stop messaging itself. I thought it was the model at first but after changing models it still persisted.
Frequency: always. every message.
Consequence: Feedback loop caused non-approved config edits, churn and gateway crashes, LOTS of api token usage.
Additional information
Pretty sure last known clean version without the bug was 2026.3.28 but it could have been an earlier one. It seems like this started with 2026.3.31.