Mainstream messaging

iMessage

Статус: нативная интеграция с внешним CLI. Gateway запускает imsg rpc и обменивается данными по JSON-RPC через stdio — отдельный демон или порт не требуется. Для полноценного канала iMessage настоятельно рекомендуется режим Private API; ответы, реакции tapback, эффекты, опросы, ответы на вложения и групповые действия требуют imsg launch и успешной проверки Private API.

При распространенной локальной настройке мастер OpenClaw может предложить подтверждаемую пользователем установку или обновление imsg через Homebrew на Mac с выполненным входом в Messages. Ручная настройка и топологии с SSH-оберткой остаются под управлением оператора: устанавливайте или обновляйте imsg в том же пользовательском контексте, в котором будет работать Gateway или обертка.

Быстрая настройка

Локальный Mac (быстрый способ)

  • Установка и проверка imsg

    bash
    brew install steipete/tap/imsgbrew update && brew upgrade imsgimsg rpc --helpimsg launchopenclaw channels status --probe

    Когда локальный мастер настройки обнаруживает отсутствие команды imsg по умолчанию, он может предложить установить steipete/tap/imsg через Homebrew. Если обнаружен управляемый Homebrew экземпляр imsg, мастер может предложить переустановить или обновить его. Пользовательские обертки cliPath не изменяются.

  • Настройка OpenClaw

    json5
    {channels: {imessage: {enabled: true,cliPath: "/usr/local/bin/imsg",dbPath: "/Users/user/Library/Messages/chat.db",},},}
  • Запуск Gateway

    bash
    openclaw gateway
  • Подтверждение сопряжения для первого личного сообщения (dmPolicy по умолчанию)

    bash
    openclaw pairing list imessageopenclaw pairing approve imessage <CODE>

    Срок действия запросов на сопряжение истекает через 1 час.

  • Удаленный Mac через SSH

    В большинстве конфигураций SSH не требуется. Используйте эту топологию, только если Gateway не может работать на Mac с выполненным входом в Messages. OpenClaw требуется только совместимый со stdio cliPath, поэтому в cliPath можно указать скрипт-обертку, который подключается по SSH к удаленному Mac и запускает imsg. Устанавливайте и обновляйте imsg на этом удаленном Mac, а не на хосте Gateway:

    bash
    ssh messages-mac 'brew install steipete/tap/imsg && brew update && brew upgrade imsg'
    bash
    #!/usr/bin/env bashexec ssh -T messages-mac imsg "$@"

    Рекомендуемая конфигурация при включенных вложениях:

    json5
    {channels: {imessage: {  enabled: true,  cliPath: "~/.openclaw/scripts/imsg-ssh",  remoteHost: "user@gateway-host", // используется для получения вложений через SCP  includeAttachments: true,  // Необязательно: дополнительные разрешенные корневые каталоги вложений (объединяются с каталогом по умолчанию  // /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, требуется полный доступ к диску (для доступа к базе данных Messages).
    • Для отправки сообщений через Messages.app требуется разрешение на автоматизацию.
    • Для расширенных действий (реакция / редактирование / отмена отправки / ответ в ветке / эффекты / опросы / групповые операции) необходимо отключить System Integrity Protection — см. Включение Private API imsg. Базовая отправка и получение текста и медиафайлов работают без этого.
    Отправка через SSH-обертку завершается ошибкой AppleEvents -1743

    При настройке через удаленный SSH можно читать чаты, проходить channels status --probe и обрабатывать входящие сообщения, но отправка исходящих сообщений все равно может завершаться ошибкой авторизации AppleEvents:

    text
    Нет разрешения на отправку событий Apple приложению Messages. (-1743)

    Проверьте базу данных TCC пользователя удаленного Mac с выполненным входом или раздел System Settings > Privacy & Security > Automation. Если запись Automation зарегистрирована для /usr/libexec/sshd-keygen-wrapper, а не для imsg или процесса локальной оболочки, macOS может не отображать пригодный переключатель Messages для этого серверного клиента SSH:

    text
    kTCCServiceAppleEvents | /usr/libexec/sshd-keygen-wrapper | auth_value=0 | com.apple.MobileSMS

    В этом состоянии повторное выполнение tccutil reset AppleEvents или повторный запуск imsg send через ту же SSH-обертку могут по-прежнему завершаться ошибкой, поскольку разрешение на автоматизацию Messages требуется контексту процесса SSH-обертки, а не приложению, которому интерфейс может предоставить доступ.

    Вместо этого используйте один из поддерживаемых контекстов процесса imsg:

    • Запускайте Gateway или хотя бы мост imsg в локальном сеансе пользователя, вошедшего в Messages.
    • Запускайте Gateway через LaunchAgent этого пользователя после предоставления полного доступа к диску и разрешения на автоматизацию из того же сеанса.
    • Если сохраняется SSH-топология с двумя пользователями, перед включением канала убедитесь, что фактическая исходящая отправка imsg send успешно выполняется через точную используемую обертку. Если ей невозможно предоставить разрешение на автоматизацию, вместо использования SSH-обертки для отправки перенастройте систему на однопользовательскую конфигурацию imsg.

    Включение Private API imsg

    imsg поставляется с двумя режимами работы. Для OpenClaw рекомендуется режим Private API, поскольку он предоставляет каналу нативные действия iMessage, ожидаемые пользователями. Базовый режим по-прежнему подходит для установок с низким риском, первоначальной проверки или хостов, где SIP невозможно отключить.

    • Базовый режим (по умолчанию, изменения SIP не требуются): исходящие текстовые и мультимедийные сообщения через send, наблюдение за входящими сообщениями и история, список чатов. Это доступно сразу после новой установки brew install steipete/tap/imsg и предоставления стандартных разрешений macOS, перечисленных выше.
    • Режим Private API: imsg внедряет вспомогательную библиотеку dylib в Messages.app, чтобы вызывать внутренние функции IMCore. Это открывает доступ к react, edit, unsend, reply (в ветке), sendWithEffect, poll и poll-vote (нативные опросы Messages), renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup, а также индикаторам набора текста и уведомлениям о прочтении.

    Для рекомендуемого на этой странице набора действий требуется режим Private API. В README imsg это требование указано явно:

    Расширенные функции, такие как read, typing, launch, расширенная отправка через мост, изменение сообщений и управление чатами, включаются отдельно. Для них необходимо отключить SIP и внедрить вспомогательную библиотеку dylib в Messages.app. imsg launch отказывается выполнять внедрение, если SIP включен.

    Метод внедрения вспомогательного компонента использует собственную библиотеку dylib imsg для доступа к закрытым API Messages. В пути iMessage OpenClaw отсутствует сторонний сервер или среда выполнения BlueBubbles.

    Настройка

    1. Установите (или обновите) imsg на Mac, где работает Messages.app:

      bash
      brew install steipete/tap/imsgbrew update && brew upgrade imsgimsg --versionimsg status --json

      Вывод imsg status --json содержит bridge_version, rpc_methods и selectors для каждого метода, чтобы перед началом работы можно было узнать, что поддерживает текущая сборка.

    2. Отключите защиту целостности системы (System Integrity Protection), а в современных версиях macOS — также проверку библиотек (Library Validation). Для внедрения вспомогательной библиотеки dylib не от Apple в подписанный Apple процесс Messages.app необходимо отключить SIP и ослабить проверку библиотек. Порядок отключения SIP в режиме восстановления зависит от версии macOS:

      • macOS 10.13–10.15 (Sierra–Catalina): отключите Library Validation через Terminal, перезагрузитесь в режим восстановления, выполните csrutil disable, перезапустите систему.
      • macOS 11+ (Big Sur и новее), Intel: перейдите в режим восстановления (или восстановления через интернет), выполните csrutil disable, перезапустите систему.
      • macOS 11+, Apple Silicon: для перехода в режим восстановления используйте последовательность запуска с кнопкой питания; в последних версиях macOS удерживайте клавишу Left Shift, когда нажимаете Continue, затем выполните csrutil disable. Для виртуальных машин используется отдельная процедура, поэтому сначала создайте снимок виртуальной машины.

      В macOS 11 и новее одного csrutil disable обычно недостаточно. Apple по-прежнему применяет проверку библиотек к Messages.app как к платформенному исполняемому файлу, поэтому вспомогательный компонент с подписью ad hoc отклоняется (Library Validation failed: ... platform binary, but mapped file is not) даже при отключённом SIP. После отключения SIP также отключите проверку библиотек и перезагрузите систему:

      bash
      sudo defaults write /Library/Preferences/com.apple.security.libraryvalidation.plist DisableLibraryValidation -bool true

      macOS 26 (Tahoe), проверено на версии 26.5.1: для внедрения вспомогательного компонента во всех версиях от 26.0 до 26.5.x достаточно отключённого SIP вместе с приведённой выше командой DisableLibraryValidation. Параметры 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 отклоняет вспомогательный компонент с подписью ad hoc при загрузке, поэтому мост не переходит в состояние готовности, а запуск завершается по тайм-ауту. Именно с таким тайм-аутом чаще всего сталкиваются в Tahoe; решение — приведённый выше файл plist, а не более радикальные меры.

      Если после обновления macOS внедрение imsg launch или отдельные операции selectors начинают возвращать false, обычной причиной является эта проверка. Прежде чем считать, что не сработало само отключение SIP, проверьте состояние SIP и проверки библиотек. Если эти параметры настроены правильно, но мост по-прежнему не может выполнить внедрение, соберите imsg status --json вместе с выводом imsg launch и сообщите об этом проекту imsg, не ослабляя дополнительные общесистемные средства защиты.

    3. Внедрите вспомогательный компонент. При отключённом SIP и выполненном входе в Messages.app:

      bash
      imsg launch

      imsg launch отказывается выполнять внедрение, если SIP всё ещё включён, поэтому эта команда также подтверждает успешное выполнение шага 2.

    4. Проверьте мост из OpenClaw:

      bash
      openclaw channels status --probe

      Запись iMessage должна сообщать works, а imsg status --json | jq '{rpc_methods, selectors}' — показывать возможности, доступные в вашей сборке macOS. Для создания опросов требуется selectors.pollPayloadMessage; для голосования требуются и selectors.pollVoteMessage, и метод RPC poll.vote. Плагин OpenClaw объявляет только действия, поддерживаемые кэшированной проверкой, но при пустом кэше исходит из оптимистичных предположений и выполняет проверку при первой отправке.

    Если openclaw channels status --probe сообщает состояние канала works, но отдельные действия во время отправки вызывают ошибку "iMessage <action> requires the imsg private API bridge", снова выполните imsg launch — вспомогательный компонент может отключиться из-за перезапуска Messages.app, обновления ОС и т. п., а кэшированное состояние available: true продолжит объявлять действия до следующего обновления проверки.

    Если SIP остаётся включённым

    Если отключение SIP неприемлемо для вашей модели угроз:

    • imsg переходит в базовый режим — только текст, мультимедиа и получение сообщений.
    • Плагин OpenClaw по-прежнему объявляет отправку текста и мультимедиа, а также мониторинг входящих сообщений; он скрывает react, edit, unsend, reply, sendWithEffect и групповые операции из набора действий в соответствии с проверкой возможностей каждого метода.
    • Для нагрузки iMessage можно использовать отдельный Mac без Apple Silicon или выделенный Mac для бота с отключённым SIP, сохранив SIP включённым на основных устройствах. См. ниже раздел Выделенный пользователь macOS для бота (отдельная учётная запись iMessage).

    Управление доступом и маршрутизация

    Политика личных сообщений

    channels.imessage.dmPolicy управляет личными сообщениями:

    • pairing (по умолчанию)
    • allowlist (требуется хотя бы одна запись allowFrom)
    • open (требуется, чтобы allowFrom содержал "*")
    • disabled

    Поле списка разрешений: channels.imessage.allowFrom.

    Записи списка разрешений должны идентифицировать отправителей: дескрипторы или статические группы доступа отправителей (accessGroup:<name>). Используйте channels.imessage.groupAllowFrom для целей чата, например chat_id:*, chat_guid:* или chat_identifier:*; для числовых ключей реестра chat_id используйте channels.imessage.groups.

    Политика групп и упоминания

    channels.imessage.groupPolicy управляет обработкой групп:

    • allowlist (по умолчанию)
    • open
    • disabled

    Список разрешённых отправителей групп: channels.imessage.groupAllowFrom.

    Записи groupAllowFrom также могут ссылаться на статические группы доступа отправителей (accessGroup:<name>).

    Резервное поведение среды выполнения: если groupAllowFrom не задан, для проверки отправителей групп iMessage используется allowFrom; задайте groupAllowFrom, если правила допуска для личных сообщений и групп должны различаться. Явно пустой groupAllowFrom: [] не задействует резервное поведение — при allowlist он блокирует всех отправителей групп. Примечание о среде выполнения: если channels.imessage полностью отсутствует, среда выполнения использует groupPolicy="allowlist" и записывает предупреждение в журнал, даже если задан channels.defaults.groupPolicy.

    Проверка упоминаний в группах:

    • iMessage не предоставляет собственных метаданных упоминаний
    • для обнаружения упоминаний используются регулярные выражения (agents.list[].groupChat.mentionPatterns, резервный вариант — messages.groupChat.mentionPatterns)
    • если шаблоны не настроены, проверку упоминаний применить невозможно
    • управляющие команды от авторизованных отправителей обходят проверку упоминаний

    Параметр systemPrompt для отдельных групп:

    Каждая запись в channels.imessage.groups.* принимает необязательную строку systemPrompt, которая добавляется в системный запрос агента при каждом ходе, обрабатывающем сообщение из этой группы. Правила разрешения аналогичны channels.whatsapp.groups:

    1. Системный запрос конкретной группы (groups["<chat_id>"].systemPrompt): используется, если запись конкретной группы присутствует в карте и в ней определён ключ systemPrompt. Если systemPrompt — пустая строка (""), подстановочный вариант подавляется и системный запрос к этой группе не применяется.
    2. Системный запрос для подстановочного значения группы (groups["*"].systemPrompt): используется, если запись конкретной группы полностью отсутствует в карте или присутствует, но не содержит ключ systemPrompt.
    json5
    {  channels: {    imessage: {      groupPolicy: "allowlist",      groupAllowFrom: ["+15555550123"],      groups: {        "*": { systemPrompt: "Используйте британское написание." },        "8421": {          requireMention: true,          systemPrompt: "Это чат дежурной смены. Ответы должны состоять не более чем из 3 предложений.",        },        "9907": {          // явное подавление: подстановочный запрос "Используйте британское написание." здесь не применяется          systemPrompt: "",        },      },    },  },}

    Запросы для отдельных групп применяются только к групповым сообщениям — личные сообщения не затрагиваются.

    Сеансы и детерминированные ответы

    • Для личных сообщений используется прямая маршрутизация, для групп — групповая.
    • При стандартном 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>

    Пример:

    json5
    {  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.

    Схемы развёртывания

    Выделенный пользователь macOS для бота (отдельная учётная запись iMessage)

    Используйте отдельный Apple ID и пользователя macOS, чтобы трафик бота был изолирован от личного профиля Messages.

    Типичная процедура:

    1. Создайте отдельного пользователя macOS или войдите в его учётную запись.
    2. Войдите в Messages с Apple ID бота в учётной записи этого пользователя.
    3. Установите imsg в учётной записи этого пользователя.
    4. Создайте обёртку SSH, чтобы OpenClaw мог запускать imsg в контексте этого пользователя.
    5. Настройте channels.imessage.accounts.<id>.cliPath и .dbPath на использование профиля этого пользователя.

    При первом запуске могут потребоваться разрешения в графическом интерфейсе (Automation + Full Disk Access) в сеансе пользователя бота.

    Удалённый Mac через Tailscale (пример)

    Типовая топология:

    • Gateway работает на Linux/виртуальной машине
    • iMessage и imsg работают на Mac в вашей сети tailnet
    • обёртка cliPath использует SSH для запуска imsg
    • remoteHost позволяет получать вложения по SCP

    Пример:

    json5
    {  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",    },  },}
    bash
    #!/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.

    Схема с несколькими учётными записями

    iMessage поддерживает настройку отдельных учётных записей в channels.imessage.accounts.

    Для каждой учётной записи можно переопределить такие поля, как cliPath, dbPath, allowFrom, groupPolicy, mediaMaxMb, настройки истории и списки разрешённых корневых каталогов вложений.

    История личных сообщений

    Задайте 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 MB)
    Исходящий текст и разбиение на части
    • ограничение размера текстовой части: channels.imessage.textChunkLimit (по умолчанию 4000)
    • режим разбиения на части: channels.imessage.streaming.chunkMode
      • length (по умолчанию)
      • newline (сначала разделение по абзацам)
    • выделение полужирным, курсивом, подчёркиванием и зачёркиванием в исходящем Markdown преобразуется во встроенное форматирование текста (получатели на macOS 15+ видят форматирование, а на более старых версиях — обычный текст без маркеров); таблицы Markdown преобразуются в соответствии с режимом таблиц Markdown канала
    • channels.imessage.sendTransport (по умолчанию auto, также bridge, applescript) определяет, как imsg выполняет отправку
    Форматы адресации

    Предпочтительные явные адресаты:

    • chat_id:123 (рекомендуется для стабильной маршрутизации)
    • chat_guid:...
    • chat_identifier:...

    Также поддерживаются адресаты в виде идентификаторов:

    • imessage:+1555...
    • sms:+1555...
    • user@example.com
    bash
    imsg chats --limit 20

    Действия приватного API

    Когда imsg launch работает, а openclaw channels status --probe сообщает privateApi.available: true, инструмент сообщений может использовать встроенные действия iMessage в дополнение к обычной отправке текста.

    Все действия включены по умолчанию; используйте channels.imessage.actions, чтобы отключить отдельные действия:

    json5
    {  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,        polls: true,      },    },  },}
    Доступные действия
    • react: добавить или удалить реакцию iMessage (messageId, emoji, remove). Поддерживаемые реакции соответствуют вариантам «любовь», «нравится», «не нравится», «смех», «акцент» и «вопрос». Удаление без указания эмодзи сбрасывает любую установленную реакцию.
    • reply: отправить ответ в ветке на существующее сообщение (messageId, text или message, а также chatGuid, chatId, chatIdentifier или to). Для ответа с вложением дополнительно требуется сборка imsg, в которой send-rich поддерживает --file.
    • sendWithEffect: отправить текст с эффектом iMessage (text или message, effect или effectId). Краткие имена: slam, loud, gentle, invisibleink, confetti, lasers, fireworks, balloon, heart, echo, happybirthday, shootingstar, sparkles, spotlight.
    • edit: изменить отправленное сообщение в поддерживаемых версиях macOS и приватного API (messageId, text или newText). Изменять можно только сообщения, отправленные самим Gateway.
    • unsend: отозвать отправленное сообщение в поддерживаемых версиях macOS и приватного API (messageId). Отзывать можно только сообщения, отправленные самим Gateway.
    • upload-file: отправить медиафайлы или другие файлы (buffer в формате base64 либо подготовленный media/path/filePath, filename, необязательный asVoice). Устаревший псевдоним: sendAttachment.
    • renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup: управлять групповыми чатами, когда текущим адресатом является групповая беседа. Эти действия изменяют идентификатор Messages на хосте, поэтому для них требуется отправитель-владелец или клиент Gateway operator.admin.
    • poll: создать встроенный опрос Apple Messages (pollQuestion, pollOption, повторённый от 2 до 12 раз, а также chatGuid, chatId, chatIdentifier или to). Получатели на iOS/iPadOS/macOS 26+ видят опрос и голосуют во встроенном интерфейсе; на более старых версиях ОС отображается резервный текст «Sent a poll». Требуется selectors.pollPayloadMessage.
    • poll-vote: проголосовать в существующем опросе (pollId или messageId, а также ровно один из параметров pollOptionIndex, pollOptionId или pollOptionText). Требуются selectors.pollVoteMessage и метод RPC poll.vote.

    Принятые входящие опросы отображаются агенту с вопросом, пронумерованными подписями вариантов, количеством голосов и идентификатором сообщения опроса, необходимым для poll-vote.

    Идентификаторы сообщений

    Контекст входящего сообщения iMessage содержит как короткие значения MessageSid, так и полные GUID сообщений (MessageSidFull), когда они доступны. Короткие идентификаторы действуют только в пределах недавнего кэша ответов на основе SQLite и перед использованием проверяются на соответствие текущему чату. Если срок действия короткого идентификатора истёк, повторите попытку с его MessageSidFull, указав в качестве адресата беседу, из которой он был получен. Полные идентификаторы не обходят привязку к беседе или учётной записи, поэтому идентификатор из другого чата следует заменить идентификатором текущего адресата. Удалённо делегированные вызовы могут отклонять устаревшие полные идентификаторы, если отсутствуют подтверждающие данные о текущей беседе.

    Определение возможностей

    OpenClaw скрывает действия приватного API, только когда кэшированный результат проверки указывает, что мост недоступен. Если состояние неизвестно, действия остаются видимыми, а при их выполнении проверка запускается отложенно, поэтому первое действие может успешно выполниться после imsg launch без отдельного ручного обновления состояния.

    Уведомления о прочтении и индикатор набора текста

    Когда мост приватного API работает, принятые входящие чаты помечаются как прочитанные, а в личных чатах индикатор набора текста появляется сразу после принятия запроса, пока агент подготавливает контекст и генерирует ответ. Чтобы отключить отметку о прочтении, используйте:

    json5
    {  channels: {    imessage: {      sendReadReceipts: false,    },  },}

    Более старые сборки imsg, выпущенные до появления списка возможностей по отдельным методам, без уведомления отключают набор текста и отметки о прочтении; OpenClaw регистрирует однократное предупреждение при каждом перезапуске, чтобы можно было определить причину отсутствия уведомления.

    Входящие реакции

    OpenClaw подписывается на реакции iMessage и маршрутизирует принятые реакции как системные события вместо обычного текста сообщения, поэтому реакция пользователя не запускает обычный цикл ответа.

    Режим уведомлений управляется параметром channels.imessage.reactionNotifications:

    • "own" (по умолчанию): уведомлять только о реакциях пользователей на сообщения, созданные ботом.
    • "all": уведомлять обо всех входящих реакциях от авторизованных отправителей.
    • "off": игнорировать входящие реакции.

    Переопределения для отдельных учётных записей задаются через channels.imessage.accounts.<id>.reactionNotifications.

    Реакции для подтверждения (👍 / 👎)

    Когда approvals.exec.enabled или approvals.plugin.enabled имеет значение true и запрос направляется в iMessage, Gateway отправляет запрос на подтверждение во встроенном формате и принимает реакцию для его обработки:

    • 👍 (реакция «Нравится») → allow-once
    • 👎 (реакция «Не нравится») → deny
    • allow-always остаётся ручным резервным вариантом: отправьте /approve <id> allow-always как обычный ответ.

    Для обработки реакции идентификатор реагирующего пользователя должен быть явно указан среди подтверждающих лиц. Список подтверждающих лиц считывается из channels.imessage.allowFrom (или channels.imessage.accounts.<id>.allowFrom); добавьте номер телефона пользователя в формате E.164 или адрес электронной почты его Apple ID (адресаты чатов, такие как chat_id:*, не являются допустимыми записями подтверждающих лиц). Запись с подстановочным знаком "*" учитывается, но позволяет подтвердить запрос любому отправителю; пустой список подтверждающих лиц полностью отключает сокращённое подтверждение реакцией. Сокращённое подтверждение реакцией намеренно обходит reactionNotifications, dmPolicy и groupAllowFrom, поскольку единственным значимым условием для обработки подтверждения является явный список разрешённых подтверждающих лиц.

    Авторизация текстовой команды /approve использует тот же список: когда channels.imessage.allowFrom не пуст, /approve <id> <decision> авторизуется по этому списку подтверждающих лиц, а не по более широкому списку разрешённых личных сообщений, и отправители, разрешённые списком личных сообщений, но отсутствующие в allowFrom, получают явный отказ. Когда allowFrom пуст, продолжает действовать резервный вариант для того же чата, а /approve авторизует любого пользователя, разрешённого списком личных сообщений. Добавьте каждого оператора, которому разрешено подтверждать запросы — через /approve или с помощью реакций, — в allowFrom.

    Примечания для операторов:

    • Привязка реакции хранится как в памяти, так и в постоянном хранилище Gateway с ключевым доступом (TTL соответствует сроку действия подтверждения); кроме того, Gateway опрашивает ожидающие запросы на наличие реакций tapback, поэтому реакция tapback, поступившая вскоре после перезапуска Gateway, всё равно обрабатывает подтверждение.
    • Собственная реакция tapback оператора is_from_me=true (например, с сопряжённого устройства Apple) обрабатывает подтверждение, если этот идентификатор явно указан среди подтверждающих лиц.
    • Запросы на подтверждение направляются в групповой разговор только при явно настроенных подтверждающих лицах; иначе подтвердить запрос мог бы любой участник группы.
    • Устаревшие текстовые реакции tapback (Liked "…" в виде обычного текста от очень старых клиентов Apple) не могут обрабатывать подтверждения, поскольку не содержат GUID сообщения; для обработки реакции необходимы структурированные метаданные tapback, передаваемые современными клиентами macOS / iOS.

    Запись конфигурации

    По умолчанию iMessage разрешает запись конфигурации, инициированную каналом (для /config set|unset, когда commands.config: true).

    Отключение:

    json5
    {  channels: {    imessage: {      configWrites: false,    },  },}

    Объединение разделённых личных сообщений (команда + URL в одном составленном сообщении)

    Когда пользователь вводит вместе команду и URL — например, Dump https://example.com/article — приложение Apple Messages разделяет отправку на две отдельные строки chat.db:

    1. Текстовое сообщение ("Dump").
    2. Пузырь предпросмотра 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 в одном сообщении (дамп, вставка, сохранение, постановка в очередь и т. д.).
    • Ваши пользователи вставляют URL вместе с командами.
    • Для вас приемлема дополнительная задержка хода в личных сообщениях (см. ниже).

    Не включайте, если:

    • Вам нужна минимальная задержка выполнения команд для однословных триггеров в личных сообщениях.
    • Все ваши процессы состоят из однократных команд без последующей передачи полезной нагрузки.

    Включение

    json5
    {  channels: {    imessage: {      coalesceSameSenderDms: true, // явное включение (по умолчанию: false)    },  },}

    Если флаг включён, но messages.inbound.byChannel.imessage или глобальный параметр messages.inbound.debounceMs явно не заданы, окно устранения дребезга увеличивается до 7000 мс (устаревшее значение по умолчанию — 0 мс, то есть без устранения дребезга). Более широкое окно необходимо, поскольку интервал разделённой отправки предпросмотра URL в Apple может достигать нескольких секунд, пока Messages.app формирует строку предпросмотра.

    Чтобы настроить окно самостоятельно:

    json5
    {  messages: {    inbound: {      byChannel: {        // 7000 мс покрывают наблюдаемые задержки предпросмотра URL в Messages.app.        imessage: 7000,      },    },  },}

    Компромиссы

    • Для точного объединения необходимы актуальные метаданные полезной нагрузки imsg. При наличии balloon_bundle_id объединяется только фактическая разделённая отправка; описанное выше резервное объединение при отсутствии метаданных служит временной обратной совместимостью и будет удалено, когда imsg начнёт объединять разделённые отправки на своей стороне.
    • Дополнительная задержка личных сообщений. При включённом флаге каждое личное сообщение (включая отдельные управляющие команды и последующие одиночные текстовые сообщения) перед обработкой ожидает до истечения окна устранения дребезга на случай поступления строки предпросмотра URL. Сообщения групповых чатов обрабатываются немедленно.
    • Размер объединённого результата ограничен. Объединённый текст ограничен 4000 символами с явным маркером …[truncated]; количество вложений ограничено 20, а исходных записей — 10 (при превышении сохраняются первая и последние). GUID каждого источника отслеживается в coalescedMessageGuids для последующей телеметрии.
    • Только для личных сообщений. В групповых чатах каждое сообщение обрабатывается отдельно, чтобы бот сохранял отзывчивость, когда одновременно пишут несколько человек.
    • Явное включение для каждого канала. Другие каналы (Discord, Slack, Telegram, WhatsApp, …) не затрагиваются. В устаревших конфигурациях BlueBubbles, где задан channels.bluebubbles.coalesceSameSenderDms, это значение следует перенести в channels.imessage.coalesceSameSenderDms.

    Сценарии и данные, видимые агенту

    Столбец «Флаг включён» показывает поведение сборки imsg, передающей balloon_bundle_id. В старых сборках imsg, которые вообще не передают метаданные пузыря, строки, помеченные ниже как «Два хода» / «N ходов», вместо этого объединяются по устаревшему механизму (один ход): OpenClaw не может структурно отличить разделённую отправку от отдельных сообщений, поэтому сохраняет объединение, применявшееся до появления метаданных. Точное разделение активируется, когда сборка начинает передавать метаданные пузыря.

    Пользователь составляет Результат chat.db Флаг выключен (по умолчанию) Флаг включён + окно (imsg передаёт метаданные пузыря)
    Dump https://example.com (одна отправка) 2 строки с интервалом около 1 с Два хода агента: отдельно «Dump», затем URL Один ход: объединённый текст Dump https://example.com
    Save this 📎image.jpg caption (вложение + текст) 2 строки без метаданных пузыря URL Два хода Два хода после обнаружения метаданных; один объединённый ход в старых сеансах или сеансах до фиксации без метаданных
    /status (отдельная команда) 1 строка Немедленная обработка Ожидание до истечения окна, затем обработка
    Отдельно вставленный URL 1 строка Немедленная обработка Ожидание до истечения окна, затем обработка
    Текст и URL намеренно отправлены двумя отдельными сообщениями с интервалом в несколько минут 2 строки вне окна Два хода Два хода (между ними истекает окно)
    Быстрый поток (>10 небольших личных сообщений в пределах окна) N строк без метаданных пузыря URL N ходов N ходов после обнаружения метаданных; один ограниченный объединённый ход в старых сеансах или сеансах до фиксации без метаданных
    Два человека пишут в групповом чате N строк от M отправителей M+ ходов (по одному на набор каждого отправителя) M+ ходов — сообщения групповых чатов не объединяются

    Восстановление входящих сообщений после перезапуска моста или Gateway

    iMessage восстанавливает сообщения, пропущенные во время остановки Gateway, одновременно подавляя устаревшую «бомбу из накопившихся сообщений», которую Apple может отправить после восстановления Push. Это поведение всегда включено по умолчанию и основано на устранении дубликатов входящих сообщений.

    • Устранение дубликатов при повторном воспроизведении. Каждое обработанное входящее сообщение записывается по своему GUID Apple в постоянное состояние плагина (imessage.inbound-dedupe): резервируется при приёме и фиксируется после обработки (при временном сбое резервирование снимается, чтобы попытку можно было повторить). Уже обработанные сообщения отбрасываются, а не обрабатываются повторно. Благодаря этому восстановление может интенсивно воспроизводить сообщения без отдельного учёта каждого из них.
    • Восстановление после простоя. При запуске монитор получает последний обработанный rowid строки chat.db (сохранённый курсор для каждой учётной записи) и передаёт его в imsg watch.subscribe как since_rowid, поэтому imsg сначала воспроизводит строки, поступившие во время остановки Gateway, а затем отслеживает новые. Повторное воспроизведение ограничено последними 500 строками и сообщениями возрастом до ~2 часов, а механизм устранения дубликатов отбрасывает всё уже обработанное.
    • Возрастной барьер устаревшей очереди. Строки выше границы запуска действительно являются новыми; если дата отправки такой строки более чем на ~15 минут предшествует времени её поступления, она относится к очереди, сброшенной Push, и подавляется. Для повторно воспроизводимых строк (на границе или ниже неё) вместо этого используется более широкое окно восстановления, поэтому недавно пропущенное сообщение доставляется, а давняя история — нет.

    Восстановление работает как в локальных, так и в удалённых конфигурациях cliPath, поскольку повторное воспроизведение since_rowid выполняется через то же RPC-соединение imsg. Отличается только окно: когда Gateway может читать chat.db (локально), он привязывается к границе rowid при запуске, ограничивает диапазон повторного воспроизведения и доставляет пропущенные сообщения возрастом до пары часов. При удалённом подключении cliPath по SSH он не может читать базу данных, поэтому повторное воспроизведение не ограничивается, а для каждой строки применяется возрастной барьер новых сообщений — недавно пропущенные сообщения всё равно восстанавливаются, а старая очередь подавляется, но используется более узкое окно новых сообщений. Для более широкого окна восстановления запускайте Gateway на Mac, где работает Messages.

    Сигнал, видимый оператору

    Подавление накопившихся сообщений регистрируется на стандартном уровне, а не выполняется без уведомления (флаг recovery показывает, какое окно было применено):

    text
    imessage: подавлена устаревшая очередь входящих сообщений account=<id> sent=<iso> recovery=<bool> (&lt;N&gt; подавлено с момента запуска)

    Миграция

    channels.imessage.catchup.* устарел — восстановление после простоя выполняется автоматически и не требует конфигурации для новых установок. Существующие конфигурации с catchup.enabled: true продолжают поддерживаться как профиль совместимости для окна повторного воспроизведения при восстановлении. Отключённые блоки наверстывания (enabled: false или без enabled: true) выведены из эксплуатации; openclaw doctor --fix удаляет их.

    Устранение неполадок

    imsg не найден или RPC не поддерживается

    Проверьте исполняемый файл и поддержку RPC:

    bash
    imsg rpc --helpimsg status --jsonopenclaw channels status --probe

    Если проверка сообщает, что RPC не поддерживается, обновите imsg. Если действия через закрытый API недоступны, запустите imsg launch в сеансе вошедшего в систему пользователя macOS и повторите проверку. Если Gateway работает не на macOS, вместо стандартного локального пути imsg используйте описанную выше конфигурацию удалённого Mac через SSH.

    Сообщения отправляются, но входящие сообщения iMessage не поступают

    Сначала убедитесь, что сообщение достигло локального Mac. Если chat.db не изменяется, OpenClaw не сможет получить сообщение, даже если imsg status --json сообщает об исправном состоянии моста.

    bash
    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;"

    Если сообщения, отправленные с телефона, не создают новых строк, восстановите работу Messages и Apple Push в macOS, прежде чем изменять конфигурацию OpenClaw. Часто достаточно однократного перезапуска службы:

    bash
    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 и, прежде чем отлаживать сеансы OpenClaw, убедитесь, что появилась новая строка chat.db или событие imsg watch. Не запускайте это как периодический цикл перезапуска моста: повторные imsg launch вместе с перезапусками Gateway во время активной работы могут прерывать доставку и оставлять выполняющиеся запуски канала в зависшем состоянии.

    Gateway не запущен в macOS

    Стандартный cliPath: "imsg" должен выполняться на Mac, где выполнен вход в Messages. В Linux или Windows задайте для channels.imessage.cliPath скрипт-обёртку, который подключается к этому Mac по SSH и запускает imsg "$@".

    bash
    #!/usr/bin/env bashexec ssh -T messages-mac imsg "$@"

    Затем выполните:

    bash
    openclaw channels status --probe --channel imessage
    Личные сообщения игнорируются

    Проверьте:

    • channels.imessage.dmPolicy
    • channels.imessage.allowFrom
    • подтверждения сопряжения (openclaw pairing list imessage)
    Групповые сообщения игнорируются

    Проверьте:

    • channels.imessage.groupPolicy
    • channels.imessage.groupAllowFrom
    • channels.imessage.groups поведение списка разрешений
    • настройку шаблона упоминаний (agents.list[].groupChat.mentionPatterns)
    Не удаётся получить удалённые вложения

    Проверьте:

    • channels.imessage.remoteHost
    • channels.imessage.remoteAttachmentRoots
    • аутентификацию по ключу SSH/SCP с хоста Gateway
    • наличие ключа хоста в ~/.ssh/known_hosts на хосте Gateway
    • доступность удалённого пути для чтения на Mac, где работает Messages
    Запросы разрешений macOS были пропущены

    Повторно выполните команды в интерактивном терминале с графическим интерфейсом в контексте того же пользователя и сеанса и подтвердите запросы:

    bash
    imsg chats --limit 1imsg send <handle> "test"

    Убедитесь, что полный доступ к диску и разрешение на автоматизацию предоставлены контексту процесса, в котором работает OpenClaw/imsg.

    Ссылки на справочник по конфигурации

    Связанные материалы

    Was this useful?
    On this page

    On this page