그룹 메시지 (WhatsApp 웹 채널)

목표: Clawd가 WhatsApp 그룹에 참여하고, 호출될 때만 깨어나며, 해당 스레드를 개인 DM 세션과 분리합니다.

참고: agents.list[].groupChat.mentionPatterns는 이제 Telegram/Discord/Slack/iMessage에서도 사용됩니다. 이 문서는 WhatsApp 특화 동작에 중점을 둡니다. 다중 에이전트 설정에서는 에이전트별로 agents.list[].groupChat.mentionPatterns를 설정하세요 (또는 전역 폴백으로 messages.groupChat.mentionPatterns를 사용하세요).

구현된 기능 (2025-12-03)

  • 활성화 모드: mention (기본값) 또는 always. mention은 핑이 필요합니다 (WhatsApp mentionedJids를 통한 실제 @멘션, 정규식 패턴, 또는 텍스트 내 봇의 E.164 번호). always는 모든 메시지에 에이전트를 깨우지만 의미 있는 가치를 더할 수 있을 때만 응답해야 하며, 그렇지 않으면 무응답 토큰 NO_REPLY를 반환합니다. 기본값은 설정에서 설정할 수 있고 (channels.whatsapp.groups) 그룹별로 /activation으로 재정의할 수 있습니다. channels.whatsapp.groups가 설정되면 그룹 허용 목록으로도 작용합니다 (모두 허용하려면 "*" 포함).
  • 그룹 정책: channels.whatsapp.groupPolicy는 그룹 메시지 허용 여부를 제어합니다 (open|disabled|allowlist). allowlistchannels.whatsapp.groupAllowFrom을 사용합니다 (폴백: 명시적 channels.whatsapp.allowFrom). 기본값은 allowlist입니다 (발신자를 추가할 때까지 차단됨).
  • 그룹별 세션: 세션 키는 agent:<agentId>:whatsapp:group:<jid> 형태이므로 /verbose on이나 /think high 같은 명령을 독립 메시지로 보내면 해당 그룹에만 적용됩니다. 개인 DM 상태는 영향받지 않습니다. 그룹 스레드에서는 하트비트가 건너뛰어집니다.
  • 컨텍스트 주입: 실행을 트리거하지 않은 대기 중인 그룹 메시지 (기본 50개)가 [Chat messages since your last reply - for context] 아래에 접두사로 붙고, 트리거 메시지는 [Current message - respond to this] 아래에 표시됩니다. 이미 세션에 있는 메시지는 다시 주입되지 않습니다.
  • 발신자 표시: 모든 그룹 배치 끝에 [from: Sender Name (+E164)]가 추가되어 누가 말하는지 알 수 있습니다.
  • 임시/일회성 보기: 텍스트/멘션을 추출하기 전에 이를 풀어내므로 그 안의 핑도 트리거됩니다.
  • 그룹 시스템 프롬프트: 그룹 세션의 첫 턴에 (그리고 /activation이 모드를 변경할 때마다) 시스템 프롬프트에 짧은 소개가 주입됩니다. 메타데이터를 사용할 수 없는 경우에도 그룹 채팅임을 알립니다.

설정 예시 (WhatsApp)

~/.openclaw/openclaw.jsongroupChat 블록을 추가하여 WhatsApp이 텍스트 본문에서 시각적 @를 제거하더라도 표시 이름 핑이 작동하도록 합니다:

{
  channels: {
    whatsapp: {
      groups: {
        "*": { requireMention: true },
      },
    },
  },
  agents: {
    list: [
      {
        id: "main",
        groupChat: {
          historyLimit: 50,
          mentionPatterns: ["@?openclaw", "\\+?15555550123"],
        },
      },
    ],
  },
}

참고:

  • 정규식은 대소문자를 구분하지 않습니다. @openclaw 같은 표시 이름 핑과 + 유무에 관계없는 번호를 커버합니다.
  • WhatsApp은 연락처를 탭할 때 mentionedJids를 통해 정식 멘션을 보내므로 번호 폴백은 드물게 필요하지만 유용한 안전망입니다.

활성화 명령 (소유자 전용)

그룹 채팅 명령을 사용하세요:

  • /activation mention
  • /activation always

소유자 번호 (channels.whatsapp.allowFrom에서, 또는 미설정 시 봇 자신의 E.164)만 이를 변경할 수 있습니다. 그룹에서 독립 메시지로 /status를 보내면 현재 활성화 모드를 확인할 수 있습니다.

사용 방법

  1. OpenClaw를 실행하는 WhatsApp 계정을 그룹에 추가합니다.
  2. @openclaw …라고 말하세요 (또는 번호를 포함하세요). groupPolicy: "open"으로 설정하지 않는 한 허용된 발신자만 트리거할 수 있습니다.
  3. 에이전트 프롬프트에 최근 그룹 컨텍스트와 [from: …] 마커가 포함되어 올바른 사람에게 응답할 수 있습니다.
  4. 세션 수준 지시어 (/verbose on, /think high, /new 또는 /reset, /compact)는 해당 그룹의 세션에만 적용됩니다. 독립 메시지로 보내야 등록됩니다. 개인 DM 세션은 독립적으로 유지됩니다.

테스트/확인

  • 수동 테스트:
    • 그룹에서 @openclaw 핑을 보내고 발신자 이름을 참조하는 응답을 확인합니다.
    • 두 번째 핑을 보내고 히스토리 블록이 포함된 후 다음 턴에 삭제되는지 확인합니다.
  • 게이트웨이 로그 (--verbose로 실행)에서 inbound web message 항목의 from: <groupJid>[from: …] 접미사를 확인합니다.

알려진 고려 사항

  • 그룹에서 노이즈가 많은 브로드캐스트를 피하기 위해 하트비트는 의도적으로 건너뛰어집니다.
  • 에코 억제는 결합된 배치 문자열을 사용합니다. 멘션 없이 동일한 텍스트를 두 번 보내면 첫 번째에만 응답합니다.
  • 세션 저장소 항목은 세션 저장소에 agent:<agentId>:whatsapp:group:<jid>로 나타납니다 (기본값 ~/.openclaw/agents/<agentId>/sessions/sessions.json). 항목이 없으면 해당 그룹이 아직 실행을 트리거하지 않았음을 의미합니다.
  • 그룹의 타이핑 표시기는 agents.defaults.typingMode를 따릅니다 (기본값: 멘션되지 않을 때 message).