Summary
When replying to an iMessage, OpenClaw correctly tracks the replyToId (message GUID) and prepends a [[reply_to:<guid>]] tag to the outbound message text via prependReplyTagIfNeeded(). However, this tag is not extracted and passed as reply_to_guid in the params sent to the imsg RPC send call.
The imsg CLI (v0.4.0) already supports reply_to_guid / replyToGUID in its send API, which creates a native iMessage threaded reply (using associatedMessageGuid). The plumbing exists on both sides — the bridge is just missing.
Current behavior
- Gateway resolves
replyToId from the incoming message
prependReplyTagIfNeeded() prepends [[reply_to:<guid>]] to the message text
sendMessageIMessage() builds params = { text, service, region } — no reply_to_guid
client.request("send", params) sends to imsg — reply tag stays as literal text prefix
- Reply shows up as a standalone message, not a threaded reply
Expected behavior
- Extract the GUID from the
[[reply_to:]] tag
- Strip the tag from the message text
- Pass
reply_to_guid in the params to imsg
- Reply shows up as a native iMessage threaded reply
Suggested fix
In src/imessage/send.ts, after prependReplyTagIfNeeded():
message = prependReplyTagIfNeeded(message, opts.replyToId);
// Extract reply_to tag and pass as native reply_to_guid to imsg
const replyTagMatch = message.match(/^\s*\[\[\s*reply_to\s*:\s*([^\]\n]+)\s*\]\]\s*/i);
const replyToGuid = replyTagMatch ? replyTagMatch[1].trim() : undefined;
if (replyTagMatch) message = message.slice(replyTagMatch[0].length);
const params: Record<string, string> = {
text: message,
service: service || "auto",
region,
};
if (replyToGuid) params.reply_to_guid = replyToGuid;
This is a ~4 line change. The imsg binary already handles reply_to_guid to set associatedMessageGuid on the outbound message.
Environment
- OpenClaw: 2026.3.13 (61d171a)
- imsg: 0.4.0
- macOS 26.2.0
- Channel: BlueBubbles (iMessage via Private API)
Summary
When replying to an iMessage, OpenClaw correctly tracks the
replyToId(message GUID) and prepends a[[reply_to:<guid>]]tag to the outbound message text viaprependReplyTagIfNeeded(). However, this tag is not extracted and passed asreply_to_guidin the params sent to theimsgRPCsendcall.The
imsgCLI (v0.4.0) already supportsreply_to_guid/replyToGUIDin its send API, which creates a native iMessage threaded reply (usingassociatedMessageGuid). The plumbing exists on both sides — the bridge is just missing.Current behavior
replyToIdfrom the incoming messageprependReplyTagIfNeeded()prepends[[reply_to:<guid>]]to the message textsendMessageIMessage()buildsparams = { text, service, region }— noreply_to_guidclient.request("send", params)sends toimsg— reply tag stays as literal text prefixExpected behavior
[[reply_to:]]tagreply_to_guidin the params toimsgSuggested fix
In
src/imessage/send.ts, afterprependReplyTagIfNeeded():This is a ~4 line change. The
imsgbinary already handlesreply_to_guidto setassociatedMessageGuidon the outbound message.Environment