설치
채널을 구성하기 전에 Mattermost를 설치하세요.- npm registry
- Local checkout
빠른 설정
네이티브 슬래시 명령
네이티브 슬래시 명령은 명시적으로 선택해야 합니다. 활성화하면 OpenClaw가 Mattermost API를 통해oc_* 슬래시 명령을 등록하고 Gateway HTTP 서버에서 콜백 POST를 수신합니다.
Behavior notes
Behavior notes
native: "auto"는 Mattermost에서 기본적으로 비활성화됩니다. 활성화하려면native: true를 설정하세요.callbackUrl을 생략하면 OpenClaw가 Gateway 호스트/포트 +callbackPath에서 이를 파생합니다.- 다중 계정 설정에서는
commands를 최상위 수준에 설정하거나channels.mattermost.accounts.<id>.commands아래에 설정할 수 있습니다(계정 값이 최상위 필드를 재정의함). - 명령 콜백은 OpenClaw가
oc_*명령을 등록할 때 Mattermost가 반환하는 명령별 토큰으로 검증됩니다. - OpenClaw는 각 콜백을 수락하기 전에 현재 Mattermost 명령 등록을 새로 고치므로, 삭제되었거나 재생성된 슬래시 명령의 오래된 토큰은 Gateway 재시작 없이도 더 이상 수락되지 않습니다.
- Mattermost API가 명령이 여전히 최신 상태임을 확인할 수 없으면 콜백 검증은 폐쇄적으로 실패합니다. 실패한 검증은 짧게 캐시되고, 동시 조회는 병합되며, 새 조회 시작은 재생 압력을 제한하기 위해 명령별로 속도 제한됩니다.
- 등록이 실패했거나 시작이 부분적으로만 완료되었거나 콜백 토큰이 확인된 명령의 등록 토큰과 일치하지 않으면 슬래시 콜백은 폐쇄적으로 실패합니다(한 명령에 유효한 토큰은 다른 명령의 업스트림 검증에 도달할 수 없음).
Reachability requirement
Reachability requirement
콜백 엔드포인트는 Mattermost 서버에서 도달 가능해야 합니다.
- Mattermost가 OpenClaw와 동일한 호스트/네트워크 네임스페이스에서 실행되지 않는 한
callbackUrl을localhost로 설정하지 마세요. - 해당 URL이
/api/channels/mattermost/command를 OpenClaw로 리버스 프록시하지 않는 한callbackUrl을 Mattermost 기본 URL로 설정하지 마세요. - 빠른 확인 방법은
curl https://<gateway-host>/api/channels/mattermost/command입니다. GET은 OpenClaw에서404가 아니라405 Method Not Allowed를 반환해야 합니다.
Mattermost egress allowlist
Mattermost egress allowlist
콜백 대상이 비공개/tailnet/내부 주소이면 콜백 호스트/도메인을 포함하도록 Mattermost
ServiceSettings.AllowedUntrustedInternalConnections를 설정하세요.전체 URL이 아니라 호스트/도메인 항목을 사용하세요.- 좋음:
gateway.tailnet-name.ts.net - 나쁨:
https://gateway.tailnet-name.ts.net
환경 변수(기본 계정)
환경 변수를 선호한다면 Gateway 호스트에 다음을 설정하세요.MATTERMOST_BOT_TOKEN=...MATTERMOST_URL=https://chat.example.com
환경 변수는 기본 계정(
default)에만 적용됩니다. 다른 계정은 구성 값을 사용해야 합니다.MATTERMOST_URL은 워크스페이스 .env에서 설정할 수 없습니다. 워크스페이스 .env 파일을 참조하세요.채팅 모드
Mattermost는 DM에 자동으로 응답합니다. 채널 동작은chatmode로 제어됩니다.
- oncall (default)
- onmessage
- onchar
채널에서 @멘션된 경우에만 응답합니다.
onchar는 명시적인 @멘션에도 계속 응답합니다.channels.mattermost.requireMention은 레거시 구성에서 존중되지만chatmode가 권장됩니다.- 봇이 채널 스레드에 표시되는 답글을 보낸 후에는 같은 스레드의 이후 메시지가 새 @멘션이나
onchar접두사 없이 응답됩니다. 따라서 다중 턴 스레드 대화가 계속 이어집니다. 참여 상태는 스레드 비활성 7일 동안 기억되며(각 답글마다 갱신됨) Gateway 재시작 후에도 유지됩니다. 봇이 관찰만 한 스레드는 영향을 받지 않습니다. 다시 명시적 멘션을 요구하려면 새 최상위 메시지를 시작하세요.
스레드와 세션
channels.mattermost.replyToMode를 사용하여 채널 및 그룹 답글이 기본 채널에 남을지, 트리거 게시물 아래에 스레드를 시작할지 제어합니다.
off(기본값): 인바운드 게시물이 이미 스레드에 있는 경우에만 스레드에 답글을 답니다.first: 최상위 채널/그룹 게시물의 경우 해당 게시물 아래에 스레드를 시작하고 대화를 스레드 범위 세션으로 라우팅합니다.all: 현재 Mattermost에서는first와 동일한 동작입니다.- 다이렉트 메시지는 이 설정을 무시하고 스레드 없이 유지됩니다.
- 스레드 범위 세션은 트리거 게시물 ID를 스레드 루트로 사용합니다.
- Mattermost에 스레드 루트가 생기면 후속 청크와 미디어가 같은 스레드에서 계속되므로 현재
first와all은 동일합니다.
접근 제어(DM)
- 기본값:
channels.mattermost.dmPolicy = "pairing"(알 수 없는 발신자는 페어링 코드를 받음). - 승인 방법:
openclaw pairing list mattermostopenclaw pairing approve mattermost <CODE>
- 공개 DM:
channels.mattermost.dmPolicy="open"및channels.mattermost.allowFrom=["*"]. channels.mattermost.allowFrom은accessGroup:<name>항목을 허용합니다. 접근 그룹을 참조하세요.
채널(그룹)
- 기본값:
channels.mattermost.groupPolicy = "allowlist"(멘션 게이트 적용). channels.mattermost.groupAllowFrom으로 발신자를 허용 목록에 추가하세요(사용자 ID 권장).channels.mattermost.groupAllowFrom은accessGroup:<name>항목을 허용합니다. 접근 그룹을 참조하세요.- 채널별 멘션 재정의는
channels.mattermost.groups.<channelId>.requireMention아래에 두거나, 기본값은channels.mattermost.groups["*"].requireMention아래에 둡니다. @username매칭은 변경 가능하며channels.mattermost.dangerouslyAllowNameMatching: true일 때만 활성화됩니다.- 공개 채널:
channels.mattermost.groupPolicy="open"(멘션 게이트 적용). - 런타임 참고:
channels.mattermost가 완전히 없으면 런타임은 그룹 검사에groupPolicy="allowlist"로 폴백합니다(channels.defaults.groupPolicy가 설정되어 있더라도).
아웃바운드 전달 대상
openclaw message send 또는 cron/Webhook과 함께 다음 대상 형식을 사용하세요.
- 채널의 경우
channel:<id> - DM의 경우
user:<id> - DM의 경우
@username(Mattermost API를 통해 확인됨)
DM 채널 재시도
OpenClaw가 Mattermost DM 대상으로 보내면서 먼저 다이렉트 채널을 확인해야 하는 경우, 기본적으로 일시적인 다이렉트 채널 생성 실패를 재시도합니다. Mattermost Plugin 전체에 대해 이 동작을 조정하려면channels.mattermost.dmChannelRetry를 사용하고, 한 계정에 대해서는 channels.mattermost.accounts.<id>.dmChannelRetry를 사용하세요.
- 이는 모든 Mattermost API 호출이 아니라 DM 채널 생성(
/api/v4/channels/direct)에만 적용됩니다. - 재시도는 속도 제한, 5xx 응답, 네트워크 또는 시간 초과 오류와 같은 일시적 실패에 적용됩니다.
429가 아닌 4xx 클라이언트 오류는 영구 오류로 처리되며 재시도되지 않습니다.
미리보기 스트리밍
Mattermost는 사고 과정, 도구 활동, 부분 답글 텍스트를 하나의 초안 미리보기 게시물로 스트리밍하며, 최종 답변을 보내도 안전해지면 그 자리에서 최종화합니다. 미리보기는 채널에 청크별 메시지를 반복해서 보내는 대신 같은 게시물 ID에서 업데이트됩니다. 미디어/오류 최종 응답은 대기 중인 미리보기 편집을 취소하고 일회성 미리보기 게시물을 플러시하는 대신 일반 전달을 사용합니다.channels.mattermost.streaming으로 활성화하세요.
Streaming modes
Streaming modes
partial은 일반적인 선택입니다. 하나의 미리보기 게시물이 답글이 늘어남에 따라 편집된 다음, 완전한 답변으로 최종화됩니다.block은 미리보기 게시물 안에서 추가 방식의 초안 청크를 사용합니다.progress는 생성 중 상태 미리보기를 표시하고 완료 시 최종 답변만 게시합니다.off는 미리보기 스트리밍을 비활성화합니다.
Streaming behavior notes
Streaming behavior notes
- 스트림을 그 자리에서 최종화할 수 없는 경우(예: 게시물이 스트림 중간에 삭제됨), OpenClaw는 답글이 손실되지 않도록 새 최종 게시물을 보내는 방식으로 폴백합니다.
- 사고 과정 전용 페이로드는
> Thinking블록 인용으로 도착하는 텍스트를 포함하여 채널 게시물에서 억제됩니다. 다른 표면에서 사고 과정을 보려면/reasoning on을 설정하세요. Mattermost 최종 게시물은 답변만 유지합니다. - 채널 매핑 행렬은 스트리밍을 참조하세요.
반응(메시지 도구)
channel=mattermost와 함께message action=react를 사용하세요.messageId는 Mattermost 게시물 ID입니다.emoji는thumbsup또는:+1:같은 이름을 허용합니다(콜론은 선택 사항).- 반응을 제거하려면
remove=true(불리언)를 설정하세요. - 반응 추가/제거 이벤트는 라우팅된 에이전트 세션에 시스템 이벤트로 전달됩니다.
channels.mattermost.actions.reactions: 반응 작업을 활성화/비활성화합니다(기본값 true).- 계정별 재정의:
channels.mattermost.accounts.<id>.actions.reactions.
대화형 버튼(메시지 도구)
클릭 가능한 버튼이 포함된 메시지를 보냅니다. 사용자가 버튼을 클릭하면 에이전트가 선택 내용을 받고 응답할 수 있습니다. 일반 에이전트 응답에는 의미론적presentation 페이로드도 포함될 수 있습니다. OpenClaw는 값 버튼을 Mattermost 대화형 버튼으로 렌더링하고, URL 버튼은 메시지 텍스트에 표시된 상태로 유지하며, 선택 메뉴는 읽기 쉬운 텍스트로 다운그레이드합니다.
채널 기능에 inlineButtons를 추가하여 버튼을 활성화합니다:
buttons 매개변수와 함께 message action=send를 사용합니다. 버튼은 2D 배열(버튼 행)입니다:
표시 레이블입니다.
클릭 시 다시 전송되는 값입니다(액션 ID로 사용됨).
버튼 스타일입니다.
구현 참고 사항
구현 참고 사항
- 버튼 콜백은 HMAC-SHA256 검증을 사용합니다(자동, 설정 필요 없음).
- Mattermost는 API 응답에서 콜백 데이터를 제거하므로(보안 기능), 클릭 시 모든 버튼이 제거됩니다. 부분 제거는 불가능합니다.
- 하이픈 또는 밑줄이 포함된 액션 ID는 자동으로 정리됩니다(Mattermost 라우팅 제한).
직접 API 통합(외부 스크립트)
외부 스크립트와 Webhook은 에이전트의message 도구를 거치지 않고 Mattermost REST API를 통해 버튼을 직접 게시할 수 있습니다. 가능하면 Plugin의 buildButtonAttachments()를 사용하고, 원시 JSON을 게시하는 경우 다음 규칙을 따르세요:
페이로드 구조:
Python 예시:
일반적인 HMAC 함정
일반적인 HMAC 함정
- Python의
json.dumps는 기본적으로 공백을 추가합니다({"key": "val"}). JavaScript의 압축 출력({"key":"val"})과 일치시키려면separators=(",", ":")를 사용하세요. - 항상 모든 컨텍스트 필드(
_token제외)에 서명하세요. Gateway는_token을 제거한 다음 남은 모든 항목에 서명합니다. 일부만 서명하면 조용히 검증에 실패합니다. sort_keys=True를 사용하세요. Gateway는 서명 전에 키를 정렬하며, Mattermost는 페이로드를 저장할 때 컨텍스트 필드 순서를 바꿀 수 있습니다.- 무작위 바이트가 아니라 봇 토큰에서 비밀값을 파생하세요(결정적). 버튼을 생성하는 프로세스와 검증하는 Gateway에서 비밀값이 동일해야 합니다.
디렉터리 어댑터
Mattermost Plugin에는 Mattermost API를 통해 채널 및 사용자 이름을 해석하는 디렉터리 어댑터가 포함되어 있습니다. 이를 통해openclaw message send와 Cron/Webhook 전달에서 #channel-name 및 @username 대상을 사용할 수 있습니다.
설정은 필요 없습니다. 어댑터는 계정 설정의 봇 토큰을 사용합니다.
다중 계정
Mattermost는channels.mattermost.accounts 아래에서 여러 계정을 지원합니다:
문제 해결
채널에 응답이 없음
채널에 응답이 없음
봇이 채널에 있는지 확인하고 멘션하거나(oncall), 트리거 접두사(onchar)를 사용하거나,
chatmode: "onmessage"를 설정하세요.인증 또는 다중 계정 오류
인증 또는 다중 계정 오류
- 봇 토큰, 기준 URL, 계정 활성화 여부를 확인하세요.
- 다중 계정 문제: env vars는
default계정에만 적용됩니다.