콘텐츠로 이동

OpenClaw Signal 연동 가이드: 5분 만에 봇 연결하기

  • 서버에 OpenClaw가 설치되어 있어야 해요 (아래 Linux 가이드는 Ubuntu 24에서 테스트되었어요).
  • Gateway가 실행되는 호스트에서 signal-cli를 사용할 수 있어야 해요.
  • SMS 등록을 위해 인증 문자를 받을 수 있는 전화번호가 필요해요.
  • 등록 과정에서 Signal captcha(signalcaptchas.org)를 확인하기 위해 브라우저 접근이 필요해요.
  1. 봇 전용으로 사용할 별도의 Signal 번호를 쓰는 것이 좋아요.
  2. signal-cli를 설치해 주세요 (JVM 빌드를 사용한다면 Java가 필요해요).
  3. 다음 두 가지 방법 중 하나를 선택해서 설정하세요:
    • 방법 A (QR 링크): signal-cli link -n "OpenClaw" 명령어를 실행하고 Signal 앱으로 스캔하세요.
    • 방법 B (SMS 등록): captcha와 SMS 인증을 통해 전용 번호를 등록하세요.
  4. OpenClaw를 설정하고 Gateway를 다시 시작하세요.
  5. 첫 DM을 보내고 페어링을 승인하세요 (openclaw pairing approve signal <CODE>).

최소 설정 예시예요:

{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}

설정 필드 상세 내용이에요:

필드설명
accountE.164 형식의 봇 전화번호 (+15551234567)
cliPathsignal-cli 실행 경로 (PATH에 등록되어 있다면 signal-cli)
dmPolicyDM 접근 정책 (보안을 위해 pairing 방식을 추천해요)
allowFromDM 전송이 허용된 전화번호 또는 uuid:<id> 값
  • libsignal을 직접 내장하지 않고 signal-cli를 통해 Signal 채널을 연동해요.
  • 결정론적 라우팅(Deterministic routing)을 지원해요. 답장은 항상 Signal로 다시 돌아가요.
  • DM은 에이전트의 메인 세션을 공유하지만, 그룹은 독립적으로 격리돼요 (agent:<agentId>:signal:group:<groupId>).

기본적으로 Signal은 /config set|unset 명령어로 실행되는 설정 업데이트를 허용해요 (이 기능을 사용하려면 commands.config: true 설정이 필요해요).

이 기능을 비활성화하려면 다음과 같이 설정하세요:

{
channels: { signal: { configWrites: false } },
}
  • Gateway는 Signal device(signal-cli 계정)에 연결돼요.
  • 개인 Signal 계정에서 봇을 실행하면, 봇은 본인이 보낸 메시지를 무시해요 (루프 방지).
  • “내가 봇에게 메시지를 보내고 봇이 답장하는” 구조를 원한다면, 별도의 봇 번호를 사용하는 것이 좋아요.

설정 방법 A: 기존 Signal 계정 연결 (QR)

섹션 제목: “설정 방법 A: 기존 Signal 계정 연결 (QR)”
  1. signal-cli를 설치하세요 (JVM 또는 native build).
  2. 봇 계정을 연결하세요:
    • signal-cli link -n "OpenClaw" 명령어를 실행한 뒤 Signal 앱에서 QR 코드를 스캔하세요.
  3. Signal을 설정하고 Gateway를 시작하세요.

예시:

{
channels: {
signal: {
enabled: true,
account: "+15551234567",
cliPath: "signal-cli",
dmPolicy: "pairing",
allowFrom: ["+15557654321"],
},
},
}

다중 계정 지원: 계정별 설정과 선택 사항인 name 필드가 포함된 channels.signal.accounts를 사용하세요. 공통 패턴은 gateway/configuration 문서를 참고하면 돼요.

설정 방법 B: 전용 봇 번호 등록 (SMS, Linux)

섹션 제목: “설정 방법 B: 전용 봇 번호 등록 (SMS, Linux)”

기존 Signal 앱 계정을 연결하는 대신, 전용 봇 번호를 새로 만들고 싶을 때 이 방법을 사용하세요.

  1. SMS를 받을 수 있는 번호를 준비하세요 (유선전화라면 음성 인증 가능).
    • 계정이나 세션 충돌을 피하려면 전용 봇 번호를 쓰는 것이 가장 깔끔해요.
  2. Gateway 호스트에 signal-cli를 설치하세요:
Terminal window
VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/AsamK/signal-cli/releases/latest | sed -e 's/^.*\/v//')
curl -L -O "https://github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}-Linux-native.tar.gz"
sudo tar xf "signal-cli-${VERSION}-Linux-native.tar.gz" -C /opt
sudo ln -sf /opt/signal-cli /usr/local/bin/
signal-cli --version

JVM 빌드(signal-cli-${VERSION}.tar.gz)를 사용한다면 JRE 25 이상을 먼저 설치해야 해요. signal-cli를 항상 최신 버전으로 유지하세요. Signal 서버 API가 변경되면 이전 릴리스는 작동하지 않을 수 있다고 개발 측에서 명시하고 있어요.

  1. 번호를 등록하고 인증하세요:
Terminal window
signal-cli -a +<BOT_PHONE_NUMBER> register

캡차(captcha)가 필요한 경우:

  1. https://signalcaptchas.org/registration/generate.html 페이지를 여세요.
  2. 캡차를 완료하고, “Open Signal” 버튼에서 signalcaptcha://...로 시작하는 링크 주소를 복사하세요.
  3. 가급적 브라우저 세션과 동일한 외부 IP에서 명령어를 실행하는 것이 좋아요.
  4. 캡차 토큰은 금방 만료되니 즉시 등록 과정을 다시 진행하세요:
Terminal window
signal-cli -a +<BOT_PHONE_NUMBER> register --captcha '<SIGNALCAPTCHA_URL>'
signal-cli -a +<BOT_PHONE_NUMBER> verify <VERIFICATION_CODE>
  1. OpenClaw를 설정하고 Gateway를 재시작한 뒤, 채널 상태를 확인하세요:
Terminal window
# If you run the gateway as a user systemd service:
systemctl --user restart openclaw-gateway
# Then verify:
openclaw doctor
openclaw channels status --probe
  1. DM 발신자를 페어링하세요:
    • 봇 번호로 아무 메시지나 보내세요.
    • 서버에서 코드를 승인하세요: openclaw pairing approve signal <PAIRING_CODE>.
    • “알 수 없는 연락처”로 뜨지 않도록 폰 연락처에 봇 번호를 저장해 두는 것이 좋아요.

중요: signal-cli로 전화번호 계정을 등록하면 해당 번호를 사용 중인 메인 Signal 앱 세션의 인증이 해제될 수 있어요. 전용 봇 번호를 사용하거나, 기존 폰 앱 설정을 그대로 유지해야 한다면 QR 연결 모드를 추천해요.

참고 자료:

  • signal-cli README: https://github.com/AsamK/signal-cli
  • 캡차 진행 방법: https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha
  • 기기 연결 방법: https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)

JVM의 느린 콜드 스타트나 컨테이너 초기화, CPU 공유 문제 등으로 signal-cli를 직접 관리하고 싶다면, 데몬을 별도로 실행하고 OpenClaw가 해당 주소를 바라보게 설정할 수 있어요.

{
channels: {
signal: {
httpUrl: "http://127.0.0.1:8080",
autoStart: false,
},
},
}

이 설정을 사용하면 OpenClaw 내부에서 프로세스를 자동으로 띄우거나 시작될 때까지 기다리는 과정을 생략해요. 만약 자동 실행 모드에서 시작 속도가 너무 느리다면 channels.signal.startupTimeoutMs 값을 조절해 보세요.

DM 설정부터 살펴볼까요?

  • 기본 설정: channels.signal.dmPolicy = "pairing"
  • 모르는 발신자가 메시지를 보내면 페어링 코드가 생성돼요. 승인하기 전까지 메시지는 무시되며, 코드는 1시간 후에 만료됩니다.
  • 승인하려면 다음 명령어를 사용하세요:
    • openclaw pairing list signal
    • openclaw pairing approve signal <CODE>
  • Signal DM의 기본 토큰 교환 방식은 페어링이에요. 자세한 내용은 Pairing 문서를 참고해 보세요.
  • sourceUuid를 사용하는 UUID 전용 발신자는 channels.signal.allowFrom에 uuid:<id> 형식으로 저장돼요.

그룹 설정은 다음과 같아요:

  • channels.signal.groupPolicy 옵션으로 open, allowlist, disabled 중 하나를 선택할 수 있어요.
  • allowlist로 설정된 경우, channels.signal.groupAllowFrom을 통해 누가 그룹에서 트리거를 실행할 수 있는지 제어해요.
  • channels.signal.groups["<group-id>" | "*"] 설정을 사용하면 requireMention, tools, toolsBySender 같은 그룹별 동작을 개별적으로 지정할 수 있어요.
  • 다중 계정을 사용한다면 channels.signal.accounts.<id>.groups에서 계정별 설정을 덮어쓸 수 있습니다.
  • 런타임 주의 사항: 만약 channels.signal 설정이 아예 없다면, channels.defaults.groupPolicy 설정 여부와 상관없이 그룹 체크 시 groupPolicy="allowlist"가 기본으로 적용돼요.

OpenClaw가 내부적으로 어떻게 움직이는지 알려드릴게요.

  • signal-cli는 데몬(daemon) 모드로 실행되며, Gateway는 SSE를 통해 이벤트를 실시간으로 읽어와요.
  • 들어오는 모든 메시지는 공유 채널 엔벨로프(envelope) 형식으로 정규화되어 처리됩니다.
  • 답장은 항상 메시지가 처음 들어왔던 동일한 번호나 그룹으로 다시 라우팅돼요.

메시지 전송 시 몇 가지 제한 사항이 있어요.

  • 나가는 텍스트는 channels.signal.textChunkLimit에 따라 나뉘어 전송돼요 (기본값 4000자).
  • 문단 단위로 깔끔하게 나누고 싶다면 channels.signal.chunkMode="newline" 설정을 추천해요. 이렇게 하면 길이에 맞춰 자르기 전에 빈 줄(문단 경계)을 기준으로 먼저 나눕니다.
  • 첨부 파일도 지원해요 (signal-cli에서 base64 데이터를 가져오는 방식이에요).
  • 미디어 용량 제한은 channels.signal.mediaMaxMb에서 설정하며, 기본값은 8MB입니다.
  • 미디어 다운로드를 건너뛰고 싶다면 channels.signal.ignoreAttachments를 사용해 보세요.
  • 그룹 히스토리 컨텍스트는 channels.signal.historyLimit (또는 계정별 설정)을 따르며, 설정이 없으면 messages.groupChat.historyLimit을 사용해요. 비활성화하려면 0으로 설정하세요 (기본값 50).

사용자 경험을 높여주는 기능들이에요.

  • 타이핑 인디케이터: OpenClaw는 signal-cli sendTyping을 통해 타이핑 신호를 보내고, 답장이 생성되는 동안 이 신호를 계속 갱신해요.
  • 읽음 확인: channels.signal.sendReadReceipts가 true로 설정되어 있으면, 허용된 DM에 대해 읽음 확인을 전달합니다.
  • 참고로 signal-cli는 현재 그룹 메시지에 대한 읽음 확인 기능을 제공하지 않아요.

AI Setup Assistant

  • channel=signal과 함께 message action=react를 사용하세요.
  • 대상(Targets): 발신자의 E.164 번호나 UUID를 사용합니다 (pairing 출력값의 uuid:<id>를 사용하세요. 일반 UUID도 잘 작동해요).
  • messageId는 리액션을 남기려는 메시지의 Signal 타임스탬프를 의미해요.
  • 그룹 리액션에는 targetAuthor 또는 targetAuthorUuid가 필요합니다.

예시:

message action=react channel=signal target=uuid:123e4567-e89b-12d3-a456-426614174000 messageId=1737630212345 emoji=🔥
message action=react channel=signal target=+15551234567 messageId=1737630212345 emoji=🔥 remove=true
message action=react channel=signal target=signal:group:<groupId> targetAuthor=uuid:<sender-uuid> messageId=1737630212345 emoji=✅

설정:

  • channels.signal.actions.reactions: 리액션 액션 활성화/비활성화 여부입니다 (기본값은 true예요).
  • channels.signal.reactionLevel: off | ack | minimal | extensive 설정을 지원해요.
  • 리액션 레벨 상세: off/ack는 기능을 끄고(에러 발생), minimal/extensive는 가이드 수준과 함께 기능을 켭니다.
  • 계정별 개별 설정: channels.signal.accounts.<id>.actions.reactions 또는 channels.signal.accounts.<id>.reactionLevel을 사용하세요.
  • DM: signal:+15551234567 (또는 일반 E.164 형식).
  • UUID DM: uuid:<id> (또는 일반 UUID).
  • 그룹: signal:group:<groupId>.
  • 사용자 이름: username:<name> (사용 중인 Signal 계정에서 지원하는 경우에 사용하세요).

먼저 이 단계들을 순서대로 실행해 보세요:

Terminal window
openclaw status
openclaw gateway status
openclaw logs --follow
openclaw doctor
openclaw channels status --probe

그다음, 필요하다면 DM 페어링 상태를 확인하세요:

Terminal window
openclaw pairing list signal

자주 발생하는 오류들입니다:

  • 데몬에 연결은 되지만 응답이 없는 경우: 계정/데몬 설정(httpUrl, account)과 수신 모드를 확인하세요.
  • DM이 무시되는 경우: 보낸 사람이 페어링 승인 대기 중입니다.
  • 그룹 메시지가 무시되는 경우: 그룹 발신자/멘션 제한 설정이 전송을 차단하고 있습니다.
  • 수정 후 설정 검증 오류가 발생하는 경우: openclaw doctor --fix를 실행하세요.
  • 진단 결과에서 Signal이 보이지 않는 경우: channels.signal.enabled: true 설정을 확인하세요.

추가 확인 사항입니다:

Terminal window
openclaw pairing list signal
pgrep -af signal-cli
grep -i "signal" "/tmp/openclaw/openclaw-$(date +%Y-%m-%d).log" | tail -20

문제 분석 흐름은 여기를 참고하세요: /channels/troubleshooting.

  • signal-cli는 계정 키를 로컬에 저장해요 (보통 ~/.local/share/signal-cli/data/ 경로예요).
  • 서버를 이전하거나 재구축하기 전에 Signal 계정 상태를 백업해 두세요.
  • 더 넓은 DM 접근 권한이 꼭 필요한 게 아니라면 channels.signal.dmPolicy: "pairing" 설정을 유지하는 게 좋아요.
  • SMS 인증은 등록이나 복구 시에만 필요하지만, 번호나 계정 제어권을 잃으면 재등록이 어려워질 수 있어요.

전체 설정: Configuration

프로바이더 옵션:

  • channels.signal.enabled: 채널 시작 여부를 설정해요.
  • channels.signal.account: 봇 계정의 E.164 번호예요.
  • channels.signal.cliPath: signal-cli 경로예요.
  • channels.signal.httpUrl: 전체 데몬 URL이에요 (host/port 설정을 덮어써요).
  • channels.signal.httpHost, channels.signal.httpPort: 데몬 바인드 설정이에요 (기본값 127.0.0.1:8080).
  • channels.signal.autoStart: 데몬 자동 실행 여부예요 (httpUrl이 설정되지 않은 경우 기본값은 true예요).
  • channels.signal.startupTimeoutMs: 시작 대기 시간(ms)이에요 (최대 120000).
  • channels.signal.receiveMode: on-start | manual 중 하나를 선택해요.
  • channels.signal.ignoreAttachments: 첨부 파일 다운로드를 건너뛰어요.
  • channels.signal.ignoreStories: 데몬의 스토리를 무시해요.
  • channels.signal.sendReadReceipts: 읽음 확인을 전달해요.
  • channels.signal.dmPolicy: pairing | allowlist | open | disabled 중 설정해요 (기본값: pairing).
  • channels.signal.allowFrom: DM 허용 목록이에요 (E.164 또는 uuid:<id>). open 모드에서는 "*"가 필요해요. Signal은 사용자 이름이 없으므로 전화번호나 UUID ID를 사용하세요.
  • channels.signal.groupPolicy: open | allowlist | disabled 중 설정해요 (기본값: allowlist).
  • channels.signal.groupAllowFrom: 그룹 발신자 허용 목록이에요.
  • channels.signal.groups: Signal 그룹 ID(또는 "*" )별 개별 설정이에요. requireMention, tools, toolsBySender 필드를 지원해요.
  • channels.signal.accounts.<id>.groups: 다중 계정 설정 시 사용하는 계정별 channels.signal.groups 버전이에요.
  • channels.signal.historyLimit: 컨텍스트에 포함할 최대 그룹 메시지 수예요 (0으로 설정하면 비활성화돼요).
  • channels.signal.dmHistoryLimit: 사용자 턴 기준 DM 기록 제한이에요. channels.signal.dms["<phone_or_uuid>"].historyLimit을 통해 사용자별로 다르게 설정할 수 있어요.
  • channels.signal.textChunkLimit: 아웃바운드 청크 크기(글자 수)예요.
  • channels.signal.chunkMode: length(기본값) 또는 newline을 선택해요. newline은 길이 기준으로 나누기 전에 빈 줄(단락 구분선)에서 먼저 텍스트를 나눠요.
  • channels.signal.mediaMaxMb: 인바운드 및 아웃바운드 미디어 용량 제한(MB)이에요.

관련 글로벌 옵션:

  • agents.list[].groupChat.mentionPatterns (Signal은 네이티브 멘션을 지원하지 않아요).
  • messages.groupChat.mentionPatterns (글로벌 폴백).
  • messages.responsePrefix.
OpenClaw

OpenClaw Expert

아직 막혀 있나요?

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