콘텐츠로 이동

OpenClaw와 BlueBubbles 연동: iMessage 통합 가이드

현재 OpenClaw 릴리스에는 BlueBubbles가 포함되어 있으므로, 일반적인 패키지 빌드를 사용하는 경우 별도의 openclaw plugins install 단계를 거칠 필요가 없습니다.

OpenClaw BlueBubbles 통합은 macOS의 iMessage 기능을 활용하여 메시지를 주고받는 강력한 방법입니다.

  1. BlueBubbles 도우미 앱(bluebubbles.app)을 통해 macOS에서 실행됩니다.
  2. 권장 및 테스트 완료 환경: macOS Sequoia (15). macOS Tahoe (26)에서도 작동하지만, 현재 Tahoe에서는 편집 기능이 작동하지 않으며 그룹 아이콘 업데이트 시 성공으로 표시되어도 동기화되지 않을 수 있습니다.
  3. OpenClaw는 REST API(GET /api/v1/ping, POST /message/text, POST /chat/:id/*)를 통해 통신합니다.
  4. 수신 메시지는 webhook을 통해 전달되며, 발신 답장, 입력 표시기, 읽음 확인 및 tapback은 REST 호출로 처리됩니다.
  5. 첨부 파일과 스티커는 인바운드 미디어로 수집되어 가능한 경우 에이전트에게 표시됩니다.
  6. 페어링 및 허용 목록은 channels.bluebubbles.allowFrom과 페어링 코드를 사용하여 다른 채널과 동일한 방식으로 작동합니다.
  7. 반응(Reactions)은 Slack이나 Telegram처럼 시스템 이벤트로 표시되므로, 에이전트가 답장을 보내기 전에 해당 반응을 “언급”할 수 있습니다.
  8. 고급 기능: 메시지 편집, 전송 취소, 답장 스레딩, 메시지 효과, 그룹 관리 기능을 지원합니다.

BlueBubbles 서버를 설정하고 OpenClaw와 연결하려면 다음 단계를 따르세요.

  1. Mac에 BlueBubbles 서버를 설치하세요(bluebubbles.app/install의 지침을 따르세요).

  2. BlueBubbles 설정에서 web API를 활성화하고 비밀번호를 설정하세요.

  3. openclaw onboard를 실행하여 BlueBubbles를 선택하거나, 수동으로 구성하세요:

    {
    channels: {
    bluebubbles: {
    enabled: true,
    serverUrl: "http://192.168.1.100:1234",
    password: "example-password",
    webhookPath: "/bluebubbles-webhook",
    },
    },
    }
  4. BlueBubbles webhook을 Gateway로 지정하세요(예: https://your-gateway-host:3000/bluebubbles-webhook?password=<password>).

  5. Gateway를 시작하면 webhook 핸들러가 등록되고 페어링이 시작됩니다.

보안 참고 사항:

  • 항상 webhook 비밀번호를 설정하세요.
  • Webhook 인증은 항상 필수입니다. OpenClaw는 루프백이나 프록시 구성과 관계없이 channels.bluebubbles.password와 일치하는 비밀번호/guid(예: ?password=<password> 또는 x-password)가 포함되지 않은 BlueBubbles webhook 요청을 거부합니다.
  • 비밀번호 인증은 전체 webhook 본문을 읽거나 파싱하기 전에 확인됩니다.

Messages.app 활성 상태 유지 (VM / 헤드리스 설정)

섹션 제목: “Messages.app 활성 상태 유지 (VM / 헤드리스 설정)”

일부 macOS VM이나 상시 가동 환경에서는 Messages.app이 “유휴(idle)” 상태가 되어 앱을 열거나 포그라운드로 가져오기 전까지 수신 이벤트가 중단될 수 있습니다. 간단한 해결책은 AppleScript와 LaunchAgent를 사용하여 5분마다 Messages.app을 확인하는 것입니다.

다음 경로에 파일을 저장하세요:

  • ~/Scripts/poke-messages.scpt

예시 스크립트(비대화형; 포커스를 가로채지 않음):

try
tell application "Messages"
if not running then
launch
end if
-- Touch the scripting interface to keep the process responsive.
set _chatCount to (count of chats)
end tell
on error
-- Ignore transient failures (first-run prompts, locked session, etc).
end try

다음 경로에 파일을 저장하세요:

  • ~/Library/LaunchAgents/com.user.poke-messages.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.poke-messages</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-lc</string>
<string>/usr/bin/osascript &quot;$HOME/Scripts/poke-messages.scpt&quot;</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>300</integer>
<key>StandardOutPath</key>
<string>/tmp/poke-messages.log</string>
<key>StandardErrorPath</key>
<string>/tmp/poke-messages.err</string>
</dict>
</plist>

참고:

  • 이 작업은 300초마다 그리고 로그인 시 실행됩니다.
  • 처음 실행할 때 macOS 자동화(Automation) 권한 요청(osascript → Messages)이 나타날 수 있습니다. LaunchAgent를 실행하는 동일한 사용자 세션에서 이를 승인하세요.

로드 방법:

Terminal window
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist

AI Setup Assistant

OpenClaw는 대화형 온보딩 프로세스를 통해 BlueBubbles 설정을 간편하게 도와줍니다. 다음 명령어를 실행하여 설정을 시작하세요.

openclaw onboard

마법사는 다음 항목들을 차례로 물어봅니다:

  1. Server URL (필수): BlueBubbles 서버 주소 (예: http://192.168.1.100:1234)
  2. Password (필수): BlueBubbles Server 설정에 있는 API 비밀번호
  3. Webhook path (선택): 기본값은 /bluebubbles-webhook입니다.
  4. DM policy: pairing, allowlist, open, 또는 disabled 중 선택
  5. Allow list: 전화번호, 이메일 또는 대화 대상

CLI를 사용하여 직접 BlueBubbles를 추가할 수도 있습니다:

openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>

DM과 그룹 대화에 대한 접근 제어는 보안과 운영 효율성을 위해 매우 중요합니다. OpenClaw BlueBubbles 설정에서 대화 정책을 세밀하게 조정할 수 있습니다.

DM:

  1. 기본값: channels.bluebubbles.dmPolicy = "pairing".
  2. 알 수 없는 발신자는 페어링 코드를 받게 되며, 승인 전까지 메시지는 무시됩니다 (코드는 1시간 후 만료).
  3. 승인 방법:
    • openclaw pairing list bluebubbles
    • openclaw pairing approve bluebubbles <CODE>
  4. 페어링은 기본적인 토큰 교환 방식입니다. 자세한 내용은 Pairing을 확인하세요.

그룹:

  1. channels.bluebubbles.groupPolicy = open | allowlist | disabled (기본값: allowlist).
  2. channels.bluebubbles.groupAllowFrom은 allowlist가 설정되었을 때 그룹 내에서 누가 트리거를 사용할 수 있는지 제어합니다.

BlueBubbles 그룹 webhook은 종종 원시 참가자 주소만 포함합니다. GroupMembers 컨텍스트에 로컬 연락처 이름을 표시하고 싶다면 macOS에서 연락처 정보를 가져오도록 설정할 수 있습니다.

  1. channels.bluebubbles.enrichGroupParticipantsFromContacts = true를 설정하여 조회를 활성화합니다. 기본값은 false입니다.
  2. 조회는 그룹 접근, 명령어 권한, 멘션 게이팅이 메시지를 허용한 후에만 실행됩니다.
  3. 이름이 없는 전화번호 참가자만 정보가 보강됩니다.
  4. 로컬 일치 항목이 없을 경우 원시 전화번호가 대체 값으로 유지됩니다.
{
channels: {
bluebubbles: {
enrichGroupParticipantsFromContacts: true,
},
},
}

BlueBubbles는 iMessage나 WhatsApp과 유사하게 그룹 채팅에 대한 멘션 게이팅을 지원합니다.

  1. agents.list[].groupChat.mentionPatterns (또는 messages.groupChat.mentionPatterns)를 사용하여 멘션을 감지합니다.
  2. 그룹에 requireMention이 활성화되면, 에이전트는 멘션되었을 때만 응답합니다.
  3. 권한이 있는 발신자의 제어 명령어는 멘션 게이팅을 우회합니다.

그룹별 설정 예시:

{
channels: {
bluebubbles: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: {
"*": { requireMention: true }, // default for all groups
"iMessage;-;chat123": { requireMention: false }, // override for specific group
},
},
},
}
  1. 제어 명령어(예: /config, /model)는 권한 부여가 필요합니다.
  2. allowFrom 및 groupAllowFrom을 사용하여 명령어 권한을 결정합니다.
  3. 권한이 있는 발신자는 그룹에서 멘션 없이도 제어 명령어를 실행할 수 있습니다.

BlueBubbles 대화는 전송 계층을 변경하지 않고도 지속적인 ACP 워크스페이스로 전환할 수 있습니다.

빠른 운영자 흐름:

  1. DM 또는 허용된 그룹 채팅 내에서 /acp spawn codex --bind here를 실행합니다.
  2. 해당 BlueBubbles 대화의 향후 메시지는 생성된 ACP 세션으로 라우팅됩니다.
  3. /new 및 /reset은 바인딩된 동일한 ACP 세션을 현재 위치에서 초기화합니다.
  4. /acp close는 ACP 세션을 종료하고 바인딩을 제거합니다.

설정된 지속적 바인딩은 type: "acp" 및 match.channel: "bluebubbles"를 포함하는 최상위 bindings[] 항목을 통해 지원됩니다.

match.peer.id는 지원되는 모든 BlueBubbles 대상 형식을 사용할 수 있습니다:

  1. +15555550123 또는 user@example.com과 같은 정규화된 DM 핸들
  2. chat_id:<id>
  3. chat_guid:<guid>
  4. chat_identifier:<identifier>

안정적인 그룹 바인딩을 위해서는 chat_id:* 또는 chat_identifier:*를 사용하는 것이 좋습니다.

예시:

{
agents: {
list: [
{
id: "codex",
runtime: {
type: "acp",
acp: { agent: "codex", backend: "acpx", mode: "persistent" },
},
},
],
},
bindings: [
{
type: "acp",
agentId: "codex",
match: {
channel: "bluebubbles",
accountId: "default",
peer: { kind: "dm", id: "+15555550123" },
},
acp: { label: "codex-imessage" },
},
],
}

공유 ACP 바인딩 동작에 대해서는 ACP Agents를 참조하세요.

  1. Typing indicators: 응답 생성 전과 생성 중에 자동으로 전송됩니다.
  2. Read receipts: channels.bluebubbles.sendReadReceipts에 의해 제어됩니다 (기본값: true).
  3. Typing indicators: OpenClaw는 타이핑 시작 이벤트를 전송하며, BlueBubbles는 전송 시 또는 타임아웃 시 자동으로 타이핑 상태를 지웁니다 (DELETE를 통한 수동 중지는 신뢰할 수 없습니다).
{
channels: {
bluebubbles: {
sendReadReceipts: false, // disable read receipts
},
},
}

AI Setup Assistant

OpenClaw BlueBubbles 설정을 통해 메시지 전송 시 다양한 고급 기능을 활용할 수 있습니다. 설정 파일에서 다음 옵션을 활성화하여 기능을 제어해 보세요.

{
channels: {
bluebubbles: {
actions: {
reactions: true, // tapbacks (default: true)
edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe)
unsend: true, // unsend messages (macOS 13+)
reply: true, // reply threading by message GUID
sendWithEffect: true, // message effects (slam, loud, etc.)
renameGroup: true, // rename group chats
setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe)
addParticipant: true, // add participants to groups
removeParticipant: true, // remove participants from groups
leaveGroup: true, // leave group chats
sendAttachment: true, // send attachments/media
},
},
},
}

사용 가능한 작업 목록은 다음과 같습니다.

  1. react: Tapback 반응을 추가하거나 제거합니다 (messageId, emoji, remove).
  2. edit: 전송된 메시지를 수정합니다 (messageId, text).
  3. unsend: 메시지 전송을 취소합니다 (messageId).
  4. reply: 특정 메시지에 답장을 보냅니다 (messageId, text, to).
  5. sendWithEffect: iMessage 효과를 적용하여 전송합니다 (text, to, effectId).
  6. renameGroup: 그룹 채팅 이름을 변경합니다 (chatGuid, displayName).
  7. setGroupIcon: 그룹 채팅 아이콘이나 사진을 설정합니다 (chatGuid, media). macOS 26 Tahoe에서는 불안정할 수 있으며, API가 성공을 반환해도 아이콘이 동기화되지 않을 수 있습니다.
  8. addParticipant: 그룹에 참가자를 추가합니다 (chatGuid, address).
  9. removeParticipant: 그룹에서 참가자를 제거합니다 (chatGuid, address).
  10. leaveGroup: 그룹 채팅에서 나갑니다 (chatGuid).
  11. upload-file: 미디어나 파일을 전송합니다 (to, buffer, filename, asVoice).
    • 음성 메모: MP3 또는 CAF 오디오 파일과 함께 asVoice: true를 설정하면 iMessage 음성 메시지로 전송됩니다. BlueBubbles는 음성 메모 전송 시 MP3를 CAF로 변환합니다.
    • 레거시 별칭: sendAttachment도 여전히 작동하지만, upload-file이 표준 작업 이름입니다.

OpenClaw는 토큰을 절약하기 위해 단축(short) 메시지 ID(예: 1, 2)를 노출할 수 있습니다.

  1. MessageSid / ReplyToId는 단축 ID일 수 있습니다.
  2. MessageSidFull / ReplyToIdFull에는 제공업체의 전체 ID가 포함됩니다.
  3. 단축 ID는 메모리에 저장되므로, 재시작하거나 캐시가 삭제되면 만료될 수 있습니다.
  4. 작업 시 단축 ID와 전체 messageId를 모두 사용할 수 있지만, 단축 ID가 더 이상 유효하지 않으면 오류가 발생합니다.

지속적인 자동화와 저장을 위해서는 전체 ID를 사용하세요.

  • 템플릿: {{MessageSidFull}}, {{ReplyToIdFull}}
  • 컨텍스트: 인바운드 페이로드의 MessageSidFull / ReplyToIdFull

템플릿 변수에 대한 자세한 내용은 Configuration을 확인하세요.

응답을 단일 메시지로 보낼지, 아니면 블록 단위로 스트리밍할지 제어할 수 있습니다.

{
channels: {
bluebubbles: {
blockStreaming: true, // enable block streaming (off by default)
},
},
}

수신되는 첨부 파일은 미디어 캐시에 다운로드되어 저장됩니다. OpenClaw 미디어 처리 기능을 사용할 때 참고하세요.

  1. 인바운드 및 아웃바운드 미디어에 대한 미디어 용량 제한은 channels.bluebubbles.mediaMaxMb를 통해 설정하며, 기본값은 8MB입니다.
  2. 아웃바운드 텍스트는 channels.bluebubbles.textChunkLimit 설정에 따라 청크 단위로 나뉘며, 기본값은 4000자입니다.

전체 구성에 대한 자세한 내용은 Configuration 문서를 확인해 주세요. OpenClaw 구성 옵션은 다음과 같습니다.

제공자 옵션:

  1. channels.bluebubbles.enabled: 채널 활성화 또는 비활성화 여부를 결정합니다.
  2. channels.bluebubbles.serverUrl: BlueBubbles REST API의 기본 URL입니다.
  3. channels.bluebubbles.password: API 비밀번호입니다.
  4. channels.bluebubbles.webhookPath: webhook 엔드포인트 경로이며, 기본값은 /bluebubbles-webhook입니다.
  5. channels.bluebubbles.dmPolicy: pairing | allowlist | open | disabled 중 선택하며, 기본값은 pairing입니다.
  6. channels.bluebubbles.allowFrom: DM 허용 목록으로, 핸들, 이메일, E.164 번호, chat_id:*, chat_guid:* 등을 처리합니다.
  7. channels.bluebubbles.groupPolicy: open | allowlist | disabled 중 선택하며, 기본값은 allowlist입니다.
  8. channels.bluebubbles.groupAllowFrom: 그룹 발신자 허용 목록입니다.
  9. channels.bluebubbles.enrichGroupParticipantsFromContacts: macOS에서 게이팅 통과 후 로컬 연락처를 기반으로 이름 없는 그룹 참가자 정보를 보강할지 여부를 결정하며, 기본값은 false입니다.
  10. channels.bluebubbles.groups: 그룹별 설정(requireMention 등)입니다.
  11. channels.bluebubbles.sendReadReceipts: 읽음 확인 메시지 전송 여부이며, 기본값은 true입니다.
  12. channels.bluebubbles.blockStreaming: 블록 스트리밍 활성화 여부이며, 기본값은 false입니다(스트리밍 응답에 필요).
  13. channels.bluebubbles.textChunkLimit: 아웃바운드 텍스트 청크 크기(문자 단위)이며, 기본값은 4000입니다.
  14. channels.bluebubbles.sendTimeoutMs: /api/v1/message/text를 통한 아웃바운드 텍스트 전송 시 요청당 제한 시간(밀리초)이며, 기본값은 30000입니다. macOS 26 설정에서 Private API iMessage 전송이 iMessage 프레임워크 내에서 60초 이상 지연될 수 있으므로, 필요 시 45000 또는 60000으로 높이세요. 프로브, 채팅 조회, 반응, 편집 및 상태 확인은 현재 10초의 짧은 기본값을 유지하며, 향후 반응 및 편집까지 범위를 넓힐 계획입니다. 계정별 재정의는 channels.bluebubbles.accounts.<accountId>.sendTimeoutMs를 사용하세요.
  15. channels.bluebubbles.chunkMode: length(기본값)는 textChunkLimit를 초과할 때만 분할하며, newline은 길이 제한 적용 전 빈 줄(단락 경계)에서 분할합니다.
  16. channels.bluebubbles.mediaMaxMb: 인바운드/아웃바운드 미디어 용량 제한(MB 단위)이며, 기본값은 8입니다.
  17. channels.bluebubbles.mediaLocalRoots: 아웃바운드 로컬 미디어 경로에 대해 허용되는 절대 로컬 디렉토리 목록입니다. 이 설정이 없으면 로컬 경로 전송은 기본적으로 거부됩니다. 계정별 재정의는 channels.bluebubbles.accounts.<accountId>.mediaLocalRoots를 사용하세요.
  18. channels.bluebubbles.historyLimit: 컨텍스트를 위한 최대 그룹 메시지 수이며, 0으로 설정 시 비활성화됩니다.
  19. channels.bluebubbles.dmHistoryLimit: DM 기록 제한입니다.
  20. channels.bluebubbles.actions: 특정 작업의 활성화/비활성화 여부입니다.
  21. channels.bluebubbles.accounts: 다중 계정 구성입니다.

관련 전역 옵션:

  1. agents.list[].groupChat.mentionPatterns (또는 messages.groupChat.mentionPatterns).
  2. messages.responsePrefix.

메시지를 보낼 때 안정적인 라우팅을 위해 chat_guid를 사용하는 것을 권장합니다.

  1. chat_guid:iMessage;-;+15555550123 (그룹 채팅에 권장)
  2. chat_id:123
  3. chat_identifier:...
  4. 직접 핸들: +15555550123, user@example.com
    • 만약 직접 핸들에 대한 기존 DM 채팅이 없다면, OpenClaw는 POST /api/v1/chat/new를 통해 새로운 채팅을 생성합니다. 이 기능을 사용하려면 BlueBubbles Private API가 활성화되어 있어야 합니다.

webhook 요청은 guid/password 쿼리 매개변수나 헤더를 channels.bluebubbles.password와 비교하여 인증합니다.

  1. API 비밀번호와 webhook 엔드포인트는 자격 증명처럼 취급하여 안전하게 보관하세요.
  2. BlueBubbles webhook 인증에는 localhost 우회 기능이 없습니다. webhook 트래픽을 프록시하는 경우, 요청의 처음부터 끝까지 BlueBubbles 비밀번호를 유지해야 합니다. gateway.trustedProxies는 여기서 channels.bluebubbles.password를 대체하지 않습니다. 자세한 내용은 Gateway 보안 문서를 확인하세요.
  3. BlueBubbles 서버를 LAN 외부로 노출하는 경우, 반드시 HTTPS를 활성화하고 방화벽 규칙을 설정하세요.

메시지 입력이나 읽음 상태 이벤트가 제대로 작동하지 않는다면, BlueBubbles webhook 로그를 확인하고 Gateway 경로가 channels.bluebubbles.webhookPath 설정과 일치하는지 확인해 보세요.

  1. 페어링 코드는 한 시간 뒤에 만료됩니다. 코드를 다시 확인하려면 CLI에서 openclaw pairing list bluebubbles를 입력하고, 승인하려면 openclaw pairing approve bluebubbles <code>를 사용하세요.
  2. 메시지 반응(Reactions) 기능을 사용하려면 BlueBubbles API의 private API(POST /api/v1/message/react)가 필요합니다. 서버 버전이 해당 기능을 지원하는지 꼭 확인해 주세요.
  3. 메시지 수정 및 전송 취소 기능은 macOS 13 이상과 호환되는 BlueBubbles 서버 버전이 필요합니다. macOS 26(Tahoe)에서는 private API 변경으로 인해 현재 수정 기능이 정상적으로 작동하지 않습니다.
  4. 그룹 아이콘 업데이트는 macOS 26(Tahoe)에서 불안정할 수 있습니다. API는 성공 응답을 보내더라도 실제 아이콘은 동기화되지 않을 수 있습니다.
  5. OpenClaw는 BlueBubbles 서버의 macOS 버전을 감지하여 알려진 문제가 있는 동작을 자동으로 숨깁니다. 만약 macOS 26(Tahoe)에서 수정 버튼이 계속 보인다면, channels.bluebubbles.actions.edit=false 설정을 통해 수동으로 비활성화하세요.
  6. 상태 및 시스템 진단 정보가 필요할 때는 openclaw status --all 또는 openclaw status --deep 명령어를 실행하세요.

채널 워크플로우에 대한 일반적인 정보는 Channels 가이드와 Plugins 문서를 참고해 주세요.

  • Channels Overview — 지원되는 모든 채널 정보
  • Pairing — DM 인증 및 페어링 흐름 안내
  • Groups — 그룹 채팅 동작 및 멘션 제어 설정
  • Channel Routing — 메시지 세션 라우팅 방식
  • Security — 접근 모델 및 보안 강화 가이드

AI Setup Assistant

OpenClaw

OpenClaw Expert

아직 막혀 있나요?

이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.