iMessage (imsg)

Trạng thái: tích hợp CLI bên ngoài. Gateway khởi chạy imsg rpc (JSON-RPC qua stdio).

Cài đặt nhanh (dành cho người mới)

  1. Đảm bảo Messages đã đăng nhập trên Mac này.
  2. Cài đặt imsg:
    • brew install steipete/tap/imsg
  3. Cấu hình OpenClaw với channels.imessage.cliPathchannels.imessage.dbPath.
  4. Khởi động Gateway và chấp nhận các yêu cầu quyền của macOS (Automation + Full Disk Access).

Config tối thiểu:

{
  channels: {
    imessage: {
      enabled: true,
      cliPath: "/usr/local/bin/imsg",
      dbPath: "/Users/<you>/Library/Messages/chat.db",
    },
  },
}

Đây là gì

  • Channel iMessage được hỗ trợ bởi imsg trên macOS.
  • Routing xác định: các phản hồi luôn quay lại iMessage.
  • DM dùng chung Session chính của Agent; nhóm được tách riêng (agent:<agentId>:imessage:group:<chat_id>).
  • Nếu một cuộc trò chuyện nhiều người đến với is_group=false, các bạn vẫn có thể tách riêng nó theo chat_id bằng cách dùng channels.imessage.groups (xem phần “Group-ish threads” bên dưới).

Ghi config

Mặc định, iMessage được phép ghi cập nhật config khi dùng lệnh /config set|unset (yêu cầu commands.config: true).

Tắt tính năng này bằng:

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

Yêu cầu

  • macOS với Messages đã đăng nhập.
  • Full Disk Access cho OpenClaw + imsg (để truy cập Messages DB).
  • Quyền Automation khi gửi tin nhắn.
  • channels.imessage.cliPath có thể trỏ đến bất kỳ lệnh nào proxy stdin/stdout (ví dụ: một wrapper script SSH đến Mac khác và chạy imsg rpc).

Cài đặt (đường đi nhanh)

  1. Đảm bảo Messages đã đăng nhập trên Mac này.
  2. Cấu hình iMessage và khởi động Gateway.

Tài khoản bot macOS riêng (để tách danh tính)

Nếu các bạn muốn bot gửi tin từ một danh tính iMessage riêng (và giữ Messages cá nhân của mình sạch sẽ), hãy dùng Apple ID riêng + tài khoản macOS riêng.

  1. Tạo Apple ID riêng (ví dụ: [email protected]).
    • Apple có thể yêu cầu số điện thoại để xác minh / 2FA.
  2. Tạo tài khoản macOS (ví dụ: openclawhome) và đăng nhập vào đó.
  3. Mở Messages trong tài khoản macOS đó và đăng nhập iMessage bằng Apple ID của bot.
  4. Bật Remote Login (System Settings → General → Sharing → Remote Login).
  5. Cài đặt imsg:
    • brew install steipete/tap/imsg
  6. Thiết lập SSH để ssh <bot-macos-user>@localhost true hoạt động không cần mật khẩu.
  7. Trỏ channels.imessage.accounts.bot.cliPath đến một SSH wrapper chạy imsg với tư cách bot user.

Lưu ý lần chạy đầu: gửi/nhận có thể yêu cầu phê duyệt GUI (Automation + Full Disk Access) trong tài khoản macOS bot. Nếu imsg rpc bị treo hoặc thoát, hãy đăng nhập vào tài khoản đó (Screen Sharing giúp được), chạy một lần imsg chats --limit 1 / imsg send ..., chấp nhận các yêu cầu, rồi thử lại.

Ví dụ wrapper (chmod +x). Thay <bot-macos-user> bằng tên người dùng macOS thực tế của các bạn:

#!/usr/bin/env bash
set -euo pipefail

# Chạy SSH interactive một lần đầu để chấp nhận host keys:
#   ssh <bot-macos-user>@localhost true
exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T <bot-macos-user>@localhost \
  "/usr/local/bin/imsg" "$@"

Ví dụ config:

{
  channels: {
    imessage: {
      enabled: true,
      accounts: {
        bot: {
          name: "Bot",
          enabled: true,
          cliPath: "/path/to/imsg-bot",
          dbPath: "/Users/<bot-macos-user>/Library/Messages/chat.db",
        },
      },
    },
  },
}

Với cài đặt một tài khoản, dùng các tùy chọn phẳng (channels.imessage.cliPath, channels.imessage.dbPath) thay vì map accounts.

Biến thể Remote/SSH (tùy chọn)

Nếu các bạn muốn iMessage trên Mac khác, đặt channels.imessage.cliPath thành một wrapper chạy imsg trên máy macOS từ xa qua SSH. OpenClaw chỉ cần stdio.

Ví dụ wrapper:

#!/usr/bin/env bash
exec ssh -T gateway-host imsg "$@"

Remote attachments: Khi cliPath trỏ đến máy từ xa qua SSH, đường dẫn attachment trong Messages database tham chiếu đến file trên máy từ xa. OpenClaw có thể tự động tải chúng qua SCP bằng cách đặt channels.imessage.remoteHost:

{
  channels: {
    imessage: {
      cliPath: "~/imsg-ssh", // SSH wrapper đến Mac từ xa
      remoteHost: "user@gateway-host", // cho SCP file transfer
      includeAttachments: true,
    },
  },
}

Nếu remoteHost không được đặt, OpenClaw sẽ cố tự động phát hiện bằng cách phân tích lệnh SSH trong wrapper script của các bạn. Mình khuyên nên cấu hình rõ ràng để đảm bảo độ tin cậy.

Mac từ xa qua Tailscale (ví dụ)

Nếu Gateway chạy trên Linux host/VM nhưng iMessage phải chạy trên Mac, Tailscale là cầu nối đơn giản nhất: Gateway nói chuyện với Mac qua tailnet, chạy imsg qua SSH, và SCP attachments về.

Kiến trúc:

┌──────────────────────────────┐          SSH (imsg rpc)          ┌──────────────────────────┐
│ Gateway host (Linux/VM)      │──────────────────────────────────▶│ Mac with Messages + imsg │
│ - openclaw gateway           │          SCP (attachments)        │ - Messages signed in     │
│ - channels.imessage.cliPath  │◀──────────────────────────────────│ - Remote Login enabled   │
└──────────────────────────────┘                                   └──────────────────────────┘

              │ Tailscale tailnet (hostname or 100.x.y.z)

        user@gateway-host

Ví dụ config cụ thể (Tailscale hostname):

{
  channels: {
    imessage: {
      enabled: true,
      cliPath: "~/.openclaw/scripts/imsg-ssh",
      remoteHost: "[email protected]",
      includeAttachments: true,
      dbPath: "/Users/bot/Library/Messages/chat.db",
    },
  },
}

Ví dụ wrapper (~/.openclaw/scripts/imsg-ssh):

#!/usr/bin/env bash
exec ssh -T [email protected] imsg "$@"

Lưu ý:

  • Đảm bảo Mac đã đăng nhập Messages và Remote Login được bật.
  • Dùng SSH keys để ssh [email protected] hoạt động không cần nhập gì.
  • remoteHost nên khớp với SSH target để SCP có thể tải attachments.

Hỗ trợ nhiều tài khoản: dùng channels.imessage.accounts với config riêng cho từng tài khoản và name tùy chọn. Xem gateway/configuration để biết pattern chung. Đừng commit ~/.openclaw/openclaw.json (thường chứa token).

Kiểm soát truy cập (DM + nhóm)

DM:

  • Mặc định: channels.imessage.dmPolicy = "pairing".
  • Người gửi không xác định sẽ nhận mã Pairing; tin nhắn bị bỏ qua cho đến khi được phê duyệt (mã hết hạn sau 1 giờ).
  • Phê duyệt qua:
    • openclaw pairing list imessage
    • openclaw pairing approve imessage <CODE>
  • Pairing là cơ chế trao đổi token mặc định cho DM iMessage. Chi tiết: Pairing

Nhóm:

  • channels.imessage.groupPolicy = open | allowlist | disabled.
  • channels.imessage.groupAllowFrom kiểm soát ai có thể kích hoạt trong nhóm khi allowlist được đặt.
  • Mention gating dùng agents.list[].groupChat.mentionPatterns (hoặc messages.groupChat.mentionPatterns) vì iMessage không có metadata mention gốc.
  • Ghi đè multi-agent: đặt pattern riêng trên agents.list[].groupChat.mentionPatterns.

Cách hoạt động (behavior)

  • imsg stream các sự kiện tin nhắn; Gateway chuẩn hóa chúng thành shared channel envelope.
  • Các phản hồi luôn route lại về cùng chat id hoặc handle.

Group-ish threads (is_group=false)

Một số cuộc trò chuyện iMessage có thể có nhiều người tham gia nhưng vẫn đến với is_group=false tùy thuộc vào cách Messages lưu trữ chat identifier.

Nếu các bạn cấu hình rõ ràng một chat_id trong channels.imessage.groups, OpenClaw sẽ coi cuộc trò chuyện đó là “nhóm” cho:

  • session isolation (khóa Session riêng agent:<agentId>:imessage:group:<chat_id>)
  • hành vi group allowlisting / mention gating

Ví dụ:

{
  channels: {
    imessage: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["+15555550123"],
      groups: {
        "42": { requireMention: false },
      },
    },
  },
}

Điều này hữu ích khi các bạn muốn một personality/model riêng cho một cuộc trò chuyện cụ thể (xem Multi-agent routing). Để tách riêng filesystem, xem Sandboxing.

Media + giới hạn

  • Tùy chọn nhập attachment qua channels.imessage.includeAttachments.
  • Giới hạn media qua channels.imessage.mediaMaxMb.

Giới hạn

  • Văn bản gửi đi được chia nhỏ theo channels.imessage.textChunkLimit (mặc định 4000).
  • Tùy chọn chia theo dòng mới: đặt channels.imessage.chunkMode="newline" để chia theo dòng trống (ranh giới đoạn văn) trước khi chia theo độ dài.
  • Tải lên media bị giới hạn bởi channels.imessage.mediaMaxMb (mặc định 16).

Addressing / delivery targets

Ưu tiên chat_id cho routing ổn định:

  • chat_id:123 (ưu tiên)
  • chat_guid:...
  • chat_identifier:...
  • direct handles: imessage:+1555 / sms:+1555 / [email protected]

Liệt kê các chat:

imsg chats --limit 20

Tham chiếu cấu hình (iMessage)

Cấu hình đầy đủ: Configuration

Các tùy chọn provider:

  • channels.imessage.enabled: bật/tắt khởi động Channel.
  • channels.imessage.cliPath: đường dẫn đến imsg.
  • channels.imessage.dbPath: đường dẫn Messages DB.
  • channels.imessage.remoteHost: SSH host cho SCP attachment transfer khi cliPath trỏ đến Mac từ xa (ví dụ: user@gateway-host). Tự động phát hiện từ SSH wrapper nếu không đặt.
  • channels.imessage.service: imessage | sms | auto.
  • channels.imessage.region: vùng SMS.
  • channels.imessage.dmPolicy: pairing | allowlist | open | disabled (mặc định: pairing).
  • channels.imessage.allowFrom: danh sách cho phép DM (handles, emails, số E.164, hoặc chat_id:*). open yêu cầu "*". iMessage không có username; dùng handles hoặc chat targets.
  • channels.imessage.groupPolicy: open | allowlist | disabled (mặc định: allowlist).
  • channels.imessage.groupAllowFrom: danh sách cho phép người gửi trong nhóm.
  • channels.imessage.historyLimit / channels.imessage.accounts.*.historyLimit: số tin nhắn nhóm tối đa để đưa vào Context (0 để tắt).
  • channels.imessage.dmHistoryLimit: giới hạn lịch sử DM theo lượt người dùng. Ghi đè theo người dùng: channels.imessage.dms["<handle>"].historyLimit.
  • channels.imessage.groups: mặc định theo nhóm + allowlist (dùng "*" cho mặc định toàn cục).
  • channels.imessage.includeAttachments: nhập attachments vào Context.
  • channels.imessage.mediaMaxMb: giới hạn media gửi/nhận (MB).
  • channels.imessage.textChunkLimit: kích thước chunk gửi đi (ký tự).
  • channels.imessage.chunkMode: length (mặc định) hoặc newline để chia theo dòng trống (ranh giới đoạn văn) trước khi chia theo độ dài.

Các tùy chọn toàn cục liên quan:

  • agents.list[].groupChat.mentionPatterns (hoặc messages.groupChat.mentionPatterns).
  • messages.responsePrefix.