Mainstream messaging
iMessage
Статус: нативная интеграция с внешним CLI. Gateway запускает imsg rpc и взаимодействует через JSON-RPC по stdio (без отдельного демона/порта). Расширенные действия требуют imsg launch и успешной проверки private API.
Ответы, tapback-реакции, эффекты, вложения и управление группами.
Личные сообщения iMessage по умолчанию используют режим сопряжения.
Используйте SSH-обертку, когда Gateway не запущен на Mac с Messages.
Полный справочник по полям iMessage.
Быстрая настройка
Локальный Mac (быстрый путь)
Установите и проверьте imsg
brew install steipete/tap/imsgimsg rpc --helpimsg launchopenclaw channels status --probeНастройте OpenClaw
{channels: {imessage: {enabled: true,cliPath: "/usr/local/bin/imsg",dbPath: "/Users/user/Library/Messages/chat.db",},},}Запустите gateway
openclaw gatewayОдобрите первое сопряжение личного сообщения (dmPolicy по умолчанию)
openclaw pairing list imessageopenclaw pairing approve imessage <CODE>Запросы сопряжения истекают через 1 час.
Удаленный Mac через SSH
OpenClaw требуется только совместимый со stdio cliPath, поэтому можно указать в cliPath скрипт-обертку, который подключается по SSH к удаленному Mac и запускает imsg.
#!/usr/bin/env bashexec ssh -T gateway-host imsg "$@"Рекомендуемая конфигурация, когда вложения включены:
{channels: {imessage: { enabled: true, cliPath: "~/.openclaw/scripts/imsg-ssh", remoteHost: "user@gateway-host", // used for SCP attachment fetches includeAttachments: true, // Optional: override allowed attachment roots. // Defaults include /Users/*/Library/Messages/Attachments attachmentRoots: ["/Users/*/Library/Messages/Attachments"], remoteAttachmentRoots: ["/Users/*/Library/Messages/Attachments"],},},}Если remoteHost не задан, OpenClaw пытается автоматически определить его, разбирая SSH-скрипт-обертку.
remoteHost должен быть host или user@host (без пробелов и SSH-опций).
OpenClaw использует строгую проверку ключей хоста для SCP, поэтому ключ хоста ретрансляции уже должен существовать в ~/.ssh/known_hosts.
Пути вложений проверяются относительно разрешенных корней (attachmentRoots / remoteAttachmentRoots).
Требования и разрешения (macOS)
- На Mac, где запускается
imsg, должен быть выполнен вход в Messages. - Для контекста процесса, запускающего OpenClaw/
imsg, требуется Full Disk Access (доступ к БД Messages). - Для отправки сообщений через Messages.app требуется разрешение Automation.
- Для расширенных действий (реакция / редактирование / отмена отправки / ответ в ветке / эффекты / операции с группами) System Integrity Protection должен быть отключен — см. Включение private API imsg ниже. Базовая отправка и получение текста и медиа работают без этого.
Отправка через SSH-обертку завершается ошибкой AppleEvents -1743
Настройка через удаленный SSH может читать чаты, проходить channels status --probe и обрабатывать входящие сообщения, но исходящая отправка при этом все равно может завершаться ошибкой авторизации AppleEvents:
Not authorized to send Apple events to Messages. (-1743)Проверьте базу TCC пользователя Mac, где выполнен вход, или System Settings > Privacy & Security > Automation. Если запись Automation сохранена для /usr/libexec/sshd-keygen-wrapper вместо процесса imsg или локальной оболочки, macOS может не показать пригодный переключатель Messages для этого серверного SSH-клиента:
kTCCServiceAppleEvents | /usr/libexec/sshd-keygen-wrapper | auth_value=0 | com.apple.MobileSMSВ таком состоянии повторный tccutil reset AppleEvents или повторный запуск imsg send через ту же SSH-обертку может продолжать завершаться ошибкой, потому что контекст процесса, которому нужен Messages Automation, — это SSH-обертка, а не приложение, которому UI может выдать разрешение.
Вместо этого используйте один из поддерживаемых контекстов процесса imsg:
- Запускайте Gateway или хотя бы мост
imsgв локальном сеансе пользователя Messages, где выполнен вход. - Запускайте Gateway через LaunchAgent для этого пользователя после выдачи Full Disk Access и Automation из того же сеанса.
- Если вы сохраняете SSH-топологию с двумя пользователями, проверьте, что реальная исходящая команда
imsg sendуспешно выполняется через точную обертку перед включением канала. Если Automation нельзя выдать, перенастройте систему на однопользовательскую установкуimsgвместо использования SSH-обертки для отправки.
Включение private API imsg
imsg поставляется в двух рабочих режимах:
- Базовый режим (по умолчанию, изменения SIP не нужны): исходящий текст и медиа через
send, входящее наблюдение/история, список чатов. Именно это вы получаете сразу после свежей установкиbrew install steipete/tap/imsgплюс стандартные разрешения macOS выше. - Режим private API:
imsgвнедряет вспомогательную dylib вMessages.app, чтобы вызывать внутренние функцииIMCore. Это открываетreact,edit,unsend,reply(в ветке),sendWithEffect,renameGroup,setGroupIcon,addParticipant,removeParticipant,leaveGroup, а также индикаторы набора и уведомления о прочтении.
Чтобы получить поверхность расширенных действий, описанную на этой странице канала, нужен режим private API. README imsg прямо указывает это требование:
Расширенные функции, такие как
read,typing,launch, расширенная отправка через мост, изменение сообщений и управление чатами, включаются явно. Они требуют отключенного SIP и внедрения вспомогательной dylib вMessages.app.imsg launchотказывается выполнять внедрение, когда SIP включен.
Техника внедрения вспомогательной библиотеки использует собственную dylib imsg для доступа к private API Messages. В пути OpenClaw iMessage нет стороннего сервера или runtime BlueBubbles.
Настройка
-
Установите (или обновите)
imsgна Mac, где работает Messages.app:bash brew install steipete/tap/imsgimsg --versionimsg status --jsonВывод
imsg status --jsonсообщаетbridge_version,rpc_methodsиselectorsпо каждому методу, чтобы вы могли увидеть, что поддерживает текущая сборка, перед началом работы. -
Отключите System Integrity Protection и (на современных macOS) Library Validation. Внедрение вспомогательной dylib не от Apple в подписанное Apple приложение
Messages.appтребует отключенного SIP и ослабленной проверки библиотек. Шаг SIP в Recovery Mode зависит от версии macOS:- macOS 10.13-10.15 (Sierra-Catalina): отключите Library Validation через Terminal, перезагрузитесь в Recovery Mode, выполните
csrutil disable, перезапустите. - macOS 11+ (Big Sur и новее), Intel: Recovery Mode (или Internet Recovery),
csrutil disable, перезапуск. - macOS 11+, Apple Silicon: последовательность запуска кнопкой питания для входа в Recovery; в последних версиях macOS удерживайте клавишу Left Shift, когда нажимаете Continue, затем
csrutil disable. Установки на виртуальных машинах используют отдельный процесс, поэтому сначала сделайте снимок VM.
На macOS 11 и новее одного
csrutil disableобычно недостаточно. Apple все еще применяет library validation кMessages.appкак к platform binary, поэтому helper с adhoc-подписью отклоняется (Library Validation failed: ... platform binary, but mapped file is not) даже при отключенном SIP. После отключения SIP также отключите library validation и перезагрузитесь:bash sudo defaults write /Library/Preferences/com.apple.security.libraryvalidation.plist DisableLibraryValidation -bool truemacOS 26 (Tahoe), проверено на 26.5.1: отключенного SIP плюс команды
DisableLibraryValidationвыше достаточно для внедрения helper во всех версиях с 26.0 по 26.5.x. boot-args не требуются. plist является решающим фактором и самым частым пропущенным шагом, когда внедрение на Tahoe завершается ошибкой:- С plist:
imsg launchвыполняет внедрение, аimsg statusсообщаетadvanced_features: true. - Без plist (даже при отключенном SIP):
imsg launchзавершается ошибкойFailed to launch: Timeout waiting for Messages.app to initialize. AMFI отклоняет adhoc helper при загрузке, поэтому мост так и не становится готовым, а запуск завершается по таймауту. Именно с этим таймаутом чаще всего сталкиваются на Tahoe, и исправление — plist выше, а не более радикальные меры.
Это было подтверждено контролируемой проверкой до/после на macOS 26.5.1 (Apple Silicon): с plist dylib отображается в
Messages.app, и мост запускается; удалите plist и перезагрузитесь — иimsg launchвыдает указанную выше ошибку таймаута, а dylib не отображается.Если внедрение
imsg launchили конкретныеselectorsначинают возвращать false после обновления macOS, эта проверка обычно является причиной. Проверьте состояние SIP и library validation, прежде чем считать, что сам шаг SIP не удался. Если эти настройки корректны, но мост всё равно не может выполнить внедрение, соберитеimsg status --jsonвместе с выводомimsg launchи сообщите об этом в проектimsg, а не ослабляйте дополнительные общесистемные механизмы безопасности.Следуйте процессу Apple в режиме Recovery для вашего Mac, чтобы отключить SIP перед запуском
imsg launch. - macOS 10.13-10.15 (Sierra-Catalina): отключите Library Validation через Terminal, перезагрузитесь в Recovery Mode, выполните
-
Внедрите вспомогательный компонент. При отключенном SIP и выполненном входе в Messages.app:
bash imsg launchimsg launchотказывается выполнять внедрение, если SIP всё ещё включен, поэтому это также служит подтверждением, что шаг 2 сработал. -
Проверьте мост из OpenClaw:
bash openclaw channels status --probeЗапись iMessage должна сообщать
works, аimsg status --json | jq '.selectors'должна показыватьretractMessagePart: trueплюс те селекторы редактирования / набора / прочтения, которые предоставляет ваша сборка macOS. Проверка OpenClaw plugin по методам вactions.tsобъявляет только действия, чей базовый селектор равенtrue, поэтому набор действий, который вы видите в списке инструментов агента, отражает то, что мост действительно может делать на этом хосте.
Если openclaw channels status --probe сообщает, что канал имеет состояние works, но конкретные действия во время отправки выбрасывают ошибку "iMessage <action> requires the imsg private API bridge", снова выполните imsg launch — вспомогательный компонент может отключиться (перезапуск Messages.app, обновление ОС и т. д.), а кэшированный статус available: true будет продолжать объявлять действия до следующего обновления проверки.
Когда нельзя отключить SIP
Если отключение SIP неприемлемо для вашей модели угроз:
imsgвозвращается к базовому режиму — только текст + медиа + получение.- OpenClaw plugin всё ещё объявляет отправку текста/медиа и мониторинг входящих сообщений; он просто скрывает
react,edit,unsend,reply,sendWithEffectи групповые операции из поверхности действий (согласно проверке возможностей по методам). - Можно запустить отдельный Mac не на Apple Silicon (или выделенный bot Mac) с отключенным SIP для нагрузки iMessage, сохранив SIP включенным на основных устройствах. См. Выделенный пользователь macOS для бота (отдельная идентичность iMessage) ниже.
Контроль доступа и маршрутизация
DM policy
channels.imessage.dmPolicy управляет прямыми сообщениями:
pairing(по умолчанию)allowlistopen(требует, чтобыallowFromвключал"*")disabled
Поле списка разрешений: channels.imessage.allowFrom.
Записи списка разрешений должны идентифицировать отправителей: идентификаторы или статические группы доступа отправителей (accessGroup:<name>). Используйте channels.imessage.groupAllowFrom для целей чата, таких как chat_id:*, chat_guid:* или chat_identifier:*; используйте channels.imessage.groups для числовых ключей реестра chat_id.
Group policy + mentions
channels.imessage.groupPolicy управляет обработкой групп:
allowlist(по умолчанию, если настроено)opendisabled
Список разрешенных отправителей группы: channels.imessage.groupAllowFrom.
Записи groupAllowFrom также могут ссылаться на статические группы доступа отправителей (accessGroup:<name>).
Резервное поведение во время выполнения: если groupAllowFrom не задан, проверки отправителей групп iMessage используют allowFrom; задайте groupAllowFrom, когда правила допуска для личных сообщений и групп должны различаться.
Примечание о времени выполнения: если channels.imessage полностью отсутствует, среда выполнения возвращается к groupPolicy="allowlist" и записывает предупреждение в журнал (даже если задан channels.defaults.groupPolicy).
Проверка упоминаний для групп:
- iMessage не имеет нативных метаданных упоминаний
- обнаружение упоминаний использует regex-шаблоны (
agents.list[].groupChat.mentionPatterns, резервноmessages.groupChat.mentionPatterns) - без настроенных шаблонов проверку упоминаний нельзя обеспечить
Управляющие команды от авторизованных отправителей могут обходить проверку упоминаний в группах.
systemPrompt для группы:
Каждая запись в channels.imessage.groups.* принимает необязательную строку systemPrompt. Значение внедряется в системный prompt агента на каждом ходе, который обрабатывает сообщение в этой группе. Разрешение повторяет разрешение prompt для группы, используемое channels.whatsapp.groups:
- Системный prompt конкретной группы (
groups["<chat_id>"].systemPrompt): используется, когда конкретная запись группы существует в карте и ее ключsystemPromptопределен. ЕслиsystemPromptявляется пустой строкой (""), wildcard подавляется и системный prompt не применяется к этой группе. - Wildcard системного prompt для групп (
groups["*"].systemPrompt): используется, когда конкретная запись группы полностью отсутствует в карте или когда она существует, но не задает ключsystemPrompt.
{ channels: { imessage: { groupPolicy: "allowlist", groupAllowFrom: ["+15555550123"], groups: { "*": { systemPrompt: "Use British spelling." }, "8421": { requireMention: true, systemPrompt: "This is the on-call rotation chat. Keep replies under 3 sentences.", }, "9907": { // explicit suppression: the wildcard "Use British spelling." does not apply here systemPrompt: "", }, }, }, },}Prompt для группы применяется только к групповым сообщениям — прямые сообщения в этом канале не затрагиваются.
Sessions and deterministic replies
- Личные сообщения используют прямую маршрутизацию; группы используют групповую маршрутизацию.
- При стандартном
session.dmScope=mainличные сообщения iMessage сворачиваются в основную сессию агента. - Групповые сессии изолированы (
agent:<agentId>:imessage:group:<chat_id>). - Ответы маршрутизируются обратно в iMessage с использованием метаданных исходного канала/цели.
Поведение потоков, похожих на групповые:
Некоторые многопользовательские потоки iMessage могут приходить с is_group=false.
Если этот chat_id явно настроен в channels.imessage.groups, OpenClaw обрабатывает его как групповой трафик (групповая проверка + изоляция групповой сессии).
Привязки разговоров ACP
Устаревшие чаты iMessage также можно привязать к сессиям ACP.
Быстрый операторский процесс:
- Выполните
/acp spawn codex --bind hereвнутри личного сообщения или разрешенного группового чата. - Будущие сообщения в том же разговоре iMessage будут маршрутизироваться в созданную сессию ACP.
/newи/resetсбрасывают ту же привязанную сессию ACP на месте./acp closeзакрывает сессию ACP и удаляет привязку.
Настроенные постоянные привязки поддерживаются через записи верхнего уровня bindings[] с type: "acp" и match.channel: "imessage".
match.peer.id может использовать:
- нормализованный идентификатор личного сообщения, например
+15555550123илиuser@example.com chat_id:<id>(рекомендуется для стабильных групповых привязок)chat_guid:<guid>chat_identifier:<identifier>
Пример:
{ agents: { list: [ { id: "codex", runtime: { type: "acp", acp: { agent: "codex", backend: "acpx", mode: "persistent" }, }, }, ], }, bindings: [ { type: "acp", agentId: "codex", match: { channel: "imessage", accountId: "default", peer: { kind: "group", id: "chat_id:123" }, }, acp: { label: "codex-group" }, }, ],}См. Агенты ACP для общего поведения привязок ACP.
Шаблоны развертывания
Dedicated bot macOS user (separate iMessage identity)
Используйте выделенный Apple ID и пользователя macOS, чтобы трафик бота был изолирован от вашего личного профиля Messages.
Типичный процесс:
- Создайте выделенного пользователя macOS или войдите в него.
- Войдите в Messages с Apple ID бота в этом пользователе.
- Установите
imsgв этом пользователе. - Создайте SSH-обертку, чтобы OpenClaw мог запускать
imsgв контексте этого пользователя. - Укажите
channels.imessage.accounts.<id>.cliPathи.dbPathна профиль этого пользователя.
Первый запуск может потребовать GUI-разрешений (Automation + Full Disk Access) в сессии этого пользователя-бота.
Remote Mac over Tailscale (example)
Распространенная топология:
- gateway работает на Linux/VM
- iMessage +
imsgработает на Mac в вашей tailnet - обертка
cliPathиспользует SSH для запускаimsg remoteHostвключает получение вложений через SCP
Пример:
{ channels: { imessage: { enabled: true, cliPath: "~/.openclaw/scripts/imsg-ssh", remoteHost: "bot@mac-mini.tailnet-1234.ts.net", includeAttachments: true, dbPath: "/Users/bot/Library/Messages/chat.db", }, },}#!/usr/bin/env bashexec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"Используйте SSH-ключи, чтобы и SSH, и SCP были неинтерактивными.
Сначала убедитесь, что ключ хоста доверенный (например, ssh bot@mac-mini.tailnet-1234.ts.net), чтобы known_hosts был заполнен.
Multi-account pattern
iMessage поддерживает конфигурацию по аккаунтам в channels.imessage.accounts.
Каждый аккаунт может переопределять поля, такие как cliPath, dbPath, allowFrom, groupPolicy, mediaMaxMb, настройки истории и списки разрешенных корней вложений.
Direct-message history
Задайте channels.imessage.dmHistoryLimit, чтобы наполнять новые сессии прямых сообщений недавней декодированной историей imsg для этого разговора. Используйте channels.imessage.dms["<sender>"].historyLimit для переопределений по отправителям, включая 0, чтобы отключить историю для отправителя.
История личных сообщений iMessage извлекается по требованию из imsg. Если dmHistoryLimit не задан, глобальное наполнение истории личных сообщений отключено, но положительное значение channels.imessage.dms["<sender>"].historyLimit для конкретного отправителя всё равно включает наполнение для этого отправителя.
Медиа, разбиение на части и цели доставки
Вложения и медиа
- прием входящих вложений по умолчанию отключен — задайте
channels.imessage.includeAttachments: true, чтобы пересылать агенту фотографии, голосовые заметки, видео и другие вложения. Если это отключено, iMessage только с вложениями отбрасываются до попадания к агенту и могут вообще не создать строку журналаInbound message. - удаленные пути вложений можно получать через SCP, когда задан
remoteHost - пути вложений должны соответствовать разрешенным корням:
channels.imessage.attachmentRoots(локально)channels.imessage.remoteAttachmentRoots(режим удаленного SCP)- шаблон корня по умолчанию:
/Users/*/Library/Messages/Attachments
- SCP использует строгую проверку ключа хоста (
StrictHostKeyChecking=yes) - размер исходящих медиа задается через
channels.imessage.mediaMaxMb(по умолчанию 16 МБ)
Разбиение исходящих сообщений
- лимит фрагмента текста:
channels.imessage.textChunkLimit(по умолчанию 4000) - режим разбиения:
channels.imessage.chunkModelength(по умолчанию)newline(разделение сначала по абзацам)
Форматы адресации
Предпочтительные явные цели:
chat_id:123(рекомендуется для стабильной маршрутизации)chat_guid:...chat_identifier:...
Цели по handle также поддерживаются:
imessage:+1555...sms:+1555...user@example.com
imsg chats --limit 20Действия приватного API
Когда imsg launch запущен, а openclaw channels status --probe сообщает privateApi.available: true, инструмент сообщений может использовать нативные для iMessage действия в дополнение к обычной отправке текста.
{ channels: { imessage: { actions: { reactions: true, edit: true, unsend: true, reply: true, sendWithEffect: true, sendAttachment: true, renameGroup: true, setGroupIcon: true, addParticipant: true, removeParticipant: true, leaveGroup: true, }, }, },}Доступные действия
- react: Добавить/удалить tapback-реакции iMessage (
messageId,emoji,remove). Поддерживаемые tapback-реакции сопоставляются с love, like, dislike, laugh, emphasize и question. - reply: Отправить ответ в ветке к существующему сообщению (
messageId,textилиmessage, а такжеchatGuid,chatId,chatIdentifierилиto). - sendWithEffect: Отправить текст с эффектом iMessage (
textилиmessage,effectилиeffectId). - edit: Изменить отправленное сообщение на поддерживаемых версиях macOS/приватного API (
messageId,textилиnewText). - unsend: Отозвать отправленное сообщение на поддерживаемых версиях macOS/приватного API (
messageId). - upload-file: Отправить медиа/файлы (
bufferв base64 или гидратированныеmedia/path/filePath,filename, необязательныйasVoice). Устаревший псевдоним:sendAttachment. - renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup: Управлять групповыми чатами, когда текущая цель является групповым разговором.
Идентификаторы сообщений
Входящий контекст iMessage включает как короткие значения MessageSid, так и полные GUID сообщений, когда они доступны. Короткие идентификаторы ограничены недавним кэшем ответов на базе SQLite и перед использованием проверяются относительно текущего чата. Если срок действия короткого идентификатора истек или он относится к другому чату, повторите попытку с полным MessageSidFull.
Обнаружение возможностей
OpenClaw скрывает действия приватного API только тогда, когда кэшированный статус проверки говорит, что мост недоступен. Если статус неизвестен, действия остаются видимыми, а диспетчеризация запускает проверки лениво, чтобы первое действие могло успешно выполниться после imsg launch без отдельного ручного обновления статуса.
Отчеты о прочтении и набор текста
Когда мост приватного API работает, принятые входящие чаты помечаются прочитанными, а в личных чатах отображается индикатор набора, как только ход принят, пока агент подготавливает контекст и генерирует ответ. Отключите отметку о прочтении так:
{ channels: { imessage: { sendReadReceipts: false, }, },}Более старые сборки imsg, появившиеся до списка возможностей по методам, будут тихо отключать набор текста/прочтение; OpenClaw записывает однократное предупреждение при каждом перезапуске, чтобы отсутствие отчета можно было объяснить.
Входящие tapback-реакции
OpenClaw подписывается на tapback-реакции iMessage и маршрутизирует принятые реакции как системные события вместо обычного текста сообщения, поэтому пользовательская tapback-реакция не запускает обычный цикл ответа.
Режим уведомлений управляется channels.imessage.reactionNotifications:
"own"(по умолчанию): уведомлять только когда пользователи реагируют на сообщения, созданные ботом."all": уведомлять обо всех входящих tapback-реакциях от авторизованных отправителей."off": игнорировать входящие tapback-реакции.
Переопределения для отдельных аккаунтов используют channels.imessage.accounts.<id>.reactionNotifications.
Реакции подтверждения (👍 / 👎)
Когда approvals.exec.enabled или approvals.plugin.enabled имеет значение true и запрос маршрутизируется в iMessage, Gateway доставляет запрос подтверждения нативно и принимает tapback-реакцию для его разрешения:
👍(tapback Like) →allow-once👎(tapback Dislike) →denyallow-alwaysостается ручным запасным вариантом: отправьте/approve <id> allow-alwaysкак обычный ответ.
Обработка реакции требует, чтобы handle реагирующего пользователя был явным подтверждающим. Список подтверждающих читается из channels.imessage.allowFrom (или channels.imessage.accounts.<id>.allowFrom); добавьте номер телефона пользователя в формате E.164 или его адрес электронной почты Apple ID. Подстановочная запись "*" учитывается, но позволяет подтверждать любому отправителю. Сокращение через реакцию намеренно обходит reactionNotifications, dmPolicy и groupAllowFrom, потому что единственным важным барьером для разрешения подтверждения является allowlist явных подтверждающих.
Изменение поведения в этом выпуске: Когда channels.imessage.allowFrom не пуст, текстовая команда /approve <id> <decision> теперь авторизуется по этому списку подтверждающих (а не по более широкому allowlist личных сообщений). Отправители, разрешенные в allowlist личных сообщений, но отсутствующие в allowFrom, получат явный отказ. Добавьте каждого оператора, который должен иметь возможность подтверждать через /approve (и через реакции), в allowFrom, чтобы сохранить прежнее поведение. Когда allowFrom пуст, устаревший «запасной вариант того же чата» остается в силе, и /approve продолжает авторизовать всех, кого допускает allowlist личных сообщений.
Заметки для операторов:
- Привязка реакции хранится как в памяти (с TTL, соответствующим истечению подтверждения), так и в постоянном хранилище Gateway с ключами, поэтому tapback-реакция, поступившая вскоре после перезапуска Gateway, все еще разрешает подтверждение.
- Межустройственные tapback-реакции
is_from_me=true(собственная реакция оператора на сопряженном устройстве Apple) намеренно игнорируются, чтобы бот не мог подтвердить сам себя. - Устаревшие tapback-реакции в текстовом стиле (
Liked "…"обычным текстом от очень старых клиентов Apple) не могут разрешать подтверждения, потому что не несут GUID сообщения; для разрешения через реакцию требуются структурированные метаданные tapback-реакции, которые отправляют актуальные клиенты macOS / iOS.
Запись конфигурации
iMessage по умолчанию разрешает инициированную каналом запись конфигурации (для /config set|unset, когда commands.config: true).
Отключение:
{ channels: { imessage: { configWrites: false, }, },}Объединение личных сообщений с раздельной отправкой (команда + URL в одной композиции)
Когда пользователь вводит команду и URL вместе — например, Dump https://example.com/article — приложение «Сообщения» Apple разделяет отправку на две отдельные строки chat.db:
- Текстовое сообщение (
"Dump"). - Пузырь предпросмотра URL (
"https://...") с изображениями OG-предпросмотра как вложениями.
Эти две строки поступают в OpenClaw с интервалом примерно 0,8-2,0 с в большинстве конфигураций. Без объединения агент получает только команду на ходе 1, отвечает (часто «отправьте мне URL») и видит URL только на ходе 2 — к этому моменту контекст команды уже потерян. Это конвейер отправки Apple, а не что-то, добавленное OpenClaw или imsg.
channels.imessage.coalesceSameSenderDms включает для личных сообщений буферизацию последовательных строк от одного отправителя. Когда imsg предоставляет структурный маркер предпросмотра URL balloon_bundle_id: "com.apple.messages.URLBalloonProvider" в одной из исходных строк, OpenClaw объединяет только эту настоящую раздельную отправку и сохраняет любые другие буферизованные строки как отдельные ходы. В более старых сборках imsg, которые вообще не отправляют метаданные пузыря, OpenClaw не может отличить раздельную отправку от отдельных отправок, поэтому возвращается к объединению корзины. Это сохраняет поведение до появления метаданных, а не регрессирует раздельные отправки Dump <url> в два хода. Групповые чаты продолжают диспетчеризоваться по сообщениям, чтобы сохранялась структура ходов с несколькими пользователями.
Когда включать
Включайте, когда:
- Вы поставляете Skills, которые ожидают
command + payloadв одном сообщении (dump, paste, save, queue и т. д.). - Ваши пользователи вставляют URL рядом с командами.
- Вы можете принять добавленную задержку хода в личных сообщениях (см. ниже).
Оставляйте отключенным, когда:
- Вам нужна минимальная задержка команд для однословных триггеров в личных сообщениях.
- Все ваши потоки — одноразовые команды без последующей полезной нагрузки.
Включение
{ channels: { imessage: { coalesceSameSenderDms: true, // opt in (default: false) }, },}Когда флаг включен и нет явного messages.inbound.byChannel.imessage или глобального messages.inbound.debounceMs, окно debounce расширяется до 7000 мс (устаревшее значение по умолчанию — 0 мс, без debounce). Более широкое окно требуется, потому что ритм раздельной отправки URL-предпросмотра Apple может растянуться на несколько секунд, пока Messages.app отправляет строку предпросмотра.
Чтобы настроить окно самостоятельно:
{ messages: { inbound: { byChannel: { // 7000 ms covers observed Messages.app URL-preview delays. imessage: 7000, }, }, },}Компромиссы
- Точное объединение требует актуальных метаданных полезной нагрузки
imsg. Когда строка URL включаетballoon_bundle_id, объединяется только эта настоящая раздельная отправка, а другие буферизованные строки остаются отдельными. В более старых сборкахimsg, которые не предоставляют метаданные пузыря, OpenClaw возвращается к объединению буферизованной корзины, чтобы раздельные отправкиDump <url>не регрессировали в два хода (временная обратная совместимость, удаляется после того, какimsgначнет объединять раздельные отправки выше по потоку). - Добавленная задержка для сообщений в личных чатах. Когда флаг включен, каждое личное сообщение (включая самостоятельные управляющие команды и одиночные текстовые продолжения) ожидает до окна debounce перед диспетчеризацией на случай, если поступает строка предпросмотра URL. Сообщения групповых чатов сохраняют мгновенную диспетчеризацию.
- Объединенный вывод ограничен. Объединенный текст ограничен 4000 символами с явным маркером
…[truncated]; вложения ограничены 20; исходные записи ограничены 10 (при превышении сохраняются первая и самые последние). Каждый исходный GUID отслеживается вcoalescedMessageGuidsдля последующей телеметрии. - Только личные сообщения. Групповые чаты переходят к диспетчеризации по сообщениям, чтобы бот оставался отзывчивым, когда печатает несколько человек.
- Включается явно, по каналу. Другие каналы (Telegram, WhatsApp, Slack, …) не затрагиваются. Устаревшие конфигурации BlueBubbles, задающие
channels.bluebubbles.coalesceSameSenderDms, должны перенести это значение вchannels.imessage.coalesceSameSenderDms.
Сценарии и что видит агент
Столбец «Флаг включен» показывает поведение в сборке imsg, которая передает balloon_bundle_id. В старых сборках imsg, которые вообще не передают метаданные balloon, строки ниже, помеченные как «Два хода» / «N ходов», вместо этого откатываются к устаревшему объединению (один ход): OpenClaw не может структурно отличить разделенную отправку от отдельных отправок, поэтому сохраняет объединение, использовавшееся до появления метаданных. Точное разделение включается, когда сборка начинает передавать метаданные balloon.
| Пользователь составляет | chat.db создает |
Флаг выключен (по умолчанию) | Флаг включен + окно (imsg передает метаданные balloon) |
|---|---|---|---|
Dump https://example.com (одна отправка) |
2 строки с интервалом ~1 с | Два хода агента: только «Dump», затем URL | Один ход: объединенный текст Dump https://example.com |
Save this 📎image.jpg caption (вложение + текст) |
2 строки без метаданных URL balloon | Два хода | Два хода после обнаружения метаданных; один объединенный ход в старых/дофиксационных сеансах без метаданных |
/status (отдельная команда) |
1 строка | Немедленная отправка | Ждать до конца окна, затем отправить |
| URL вставлен отдельно | 1 строка | Немедленная отправка | Ждать до конца окна, затем отправить |
| Текст + URL отправлены как два намеренно отдельных сообщения с интервалом в минуты | 2 строки вне окна | Два хода | Два хода (окно истекает между ними) |
| Быстрый поток (>10 коротких DM внутри окна) | N строк без метаданных URL balloon | N ходов | N ходов после обнаружения метаданных; один ограниченный объединенный ход в старых/дофиксационных сеансах без метаданных |
| Два человека печатают в групповом чате | N строк от M отправителей | M+ ходов (по одному на корзину отправителя) | M+ ходов — групповые чаты не объединяются |
Входящее восстановление после перезапуска моста или Gateway
iMessage восстанавливает сообщения, пропущенные во время простоя Gateway, и одновременно подавляет устаревшую «бомбу бэклога», которую Apple может сбросить после восстановления Push. Поведение по умолчанию всегда включено и построено на входящей дедупликации.
- Дедупликация повторного воспроизведения. Каждое отправленное входящее сообщение записывается по его Apple GUID в постоянное состояние Plugin (
imessage.inbound-dedupe), заявляется при приеме и фиксируется после обработки (освобождается при временном сбое, чтобы можно было повторить попытку). Все уже обработанное отбрасывается вместо повторной отправки. Именно это позволяет восстановлению агрессивно воспроизводить сообщения без учета каждого сообщения отдельно. - Восстановление после простоя. При запуске монитор запоминает последний отправленный rowid из
chat.db(постоянный курсор на учетную запись) и передает его вimsg watch.subscribeкакsince_rowid, поэтому imsg воспроизводит строки, появившиеся во время простоя Gateway, а затем следит за живым потоком. Повторное воспроизведение ограничено самыми свежими строками и сообщениями возрастом до ~2 часов, а дедупликация отбрасывает все уже обработанное. - Возрастной барьер устаревшего бэклога. Строки выше границы запуска действительно живые; строка, дата отправки которой более чем на ~15 минут старше ее поступления, считается бэклогом после сброса Push и подавляется. Повторно воспроизводимые строки (на границе или ниже нее) вместо этого используют более широкое окно восстановления, поэтому недавно пропущенное сообщение доставляется, а древняя история — нет.
Восстановление работает как с локальными, так и с удаленными настройками cliPath, потому что повторное воспроизведение since_rowid идет через то же RPC-соединение imsg. Разница в окне: когда Gateway может читать chat.db (локально), он привязывает границу rowid запуска, ограничивает диапазон повторного воспроизведения и доставляет пропущенные сообщения возрастом до пары часов. При удаленном SSH cliPath он не может читать базу данных, поэтому повторное воспроизведение не ограничено, а каждая строка использует живой возрастной барьер — недавно пропущенные сообщения все равно восстанавливаются, а старый бэклог все равно подавляется, просто с более узким живым окном. Запускайте Gateway на Mac с Messages, чтобы получить более широкое окно восстановления.
Сигнал, видимый оператору
Подавленный бэклог логируется на уровне по умолчанию и никогда не отбрасывается молча (флаг recovery показывает, какое окно применялось):
imessage: suppressed stale inbound backlog account=<id> sent=<iso> recovery=<bool> (<N> suppressed since start)Миграция
channels.imessage.catchup.* устарел — восстановление после простоя теперь автоматическое и не требует конфигурации для новых установок. Существующие конфигурации с catchup.enabled: true продолжают учитываться как профиль совместимости для окна повторного воспроизведения восстановления. Отключенные блоки catchup (enabled: false или без enabled: true) выведены из использования; openclaw doctor --fix удаляет их.
Устранение неполадок
imsg not found or RPC unsupported
Проверьте бинарный файл и поддержку RPC:
imsg rpc --helpimsg status --jsonopenclaw channels status --probeЕсли probe сообщает, что RPC не поддерживается, обновите imsg. Если действия private API недоступны, выполните imsg launch в пользовательском сеансе macOS с выполненным входом и снова выполните probe. Если Gateway не запущен на macOS, используйте настройку Remote Mac over SSH выше вместо локального пути imsg по умолчанию.
Messages send but inbound iMessages do not arrive
Сначала докажите, что сообщение дошло до локального Mac. Если chat.db не меняется, OpenClaw не может получить сообщение, даже когда imsg status --json сообщает о здоровом мосте.
imsg chats --limit 10 --jsonimsg watch --chat-id <chat-id> --jsonsqlite3 ~/Library/Messages/chat.db \"select datetime(max(date)/1000000000 + 978307200, 'unixepoch', 'localtime'), max(ROWID) from message;"Если сообщения, отправленные с телефона, не создают новых строк, исправьте слой macOS Messages и Apple Push до изменения конфигурации OpenClaw. Одноразового обновления сервисов часто достаточно:
launchctl kickstart -k system/com.apple.apsdlaunchctl kickstart -k gui/$(id -u)/com.apple.CommCenterlaunchctl kickstart -k gui/$(id -u)/com.apple.identityservicesdlaunchctl kickstart -k gui/$(id -u)/com.apple.imagentimsg launchopenclaw gateway restartОтправьте новое iMessage с телефона и подтвердите новую строку chat.db или событие imsg watch перед отладкой сеансов OpenClaw. Не запускайте это как периодический цикл перезапуска моста; повторные imsg launch плюс перезапуски Gateway во время активной работы могут прерывать доставки и оставлять выполняющиеся channel-запуски зависшими.
Gateway is not running on macOS
cliPath: "imsg" по умолчанию должен выполняться на Mac, вошедшем в Messages. На Linux или Windows задайте channels.imessage.cliPath как скрипт-обертку, который подключается по SSH к этому Mac и запускает imsg "$@".
#!/usr/bin/env bashexec ssh -T messages-mac imsg "$@"Затем выполните:
openclaw channels status --probe --channel imessageDMs are ignored
Проверьте:
channels.imessage.dmPolicychannels.imessage.allowFrom- подтверждения сопряжения (
openclaw pairing list imessage)
Group messages are ignored
Проверьте:
channels.imessage.groupPolicychannels.imessage.groupAllowFrom- поведение allowlist
channels.imessage.groups - конфигурацию шаблонов упоминаний (
agents.list[].groupChat.mentionPatterns)
Remote attachments fail
Проверьте:
channels.imessage.remoteHostchannels.imessage.remoteAttachmentRoots- аутентификацию по ключу SSH/SCP с хоста Gateway
- наличие ключа хоста в
~/.ssh/known_hostsна хосте Gateway - доступность удаленного пути для чтения на Mac, где работает Messages
macOS permission prompts were missed
Повторно запустите в интерактивном GUI-терминале в том же пользовательском/сеансовом контексте и подтвердите запросы:
imsg chats --limit 1imsg send <handle> "test"Подтвердите, что Full Disk Access + Automation выданы для контекста процесса, который запускает OpenClaw/imsg.
Указатели на справочник конфигурации
Связанные материалы
- Обзор каналов — все поддерживаемые каналы
- Удаление BlueBubbles и путь imsg для iMessage — объявление и сводка миграции
- Переход с BlueBubbles — таблица перевода конфигурации и пошаговое переключение
- Сопряжение — аутентификация DM и поток сопряжения
- Группы — поведение групповых чатов и ограничение по упоминаниям
- Маршрутизация каналов — маршрутизация сеансов для сообщений
- Безопасность — модель доступа и усиление защиты