메인 콘텐츠로 건너뛰기

Documentation Index

Fetch the complete documentation index at: https://docs.openclaw.ai/llms.txt

Use this file to discover all available pages before exploring further.

상태: 다운로드 가능한 Plugin(봇 토큰 + WebSocket 이벤트). 채널, 그룹, DM이 지원됩니다. Mattermost는 자체 호스팅 가능한 팀 메시징 플랫폼입니다. 제품 세부 정보와 다운로드는 공식 사이트 mattermost.com을 참조하세요.

설치

채널을 구성하기 전에 Mattermost를 설치하세요:
openclaw plugins install @openclaw/mattermost
세부 정보: Plugins

빠른 설정

1

Plugin이 사용 가능한지 확인

현재 패키징된 OpenClaw 릴리스에는 이미 번들로 포함되어 있습니다. 더 오래된 설치 또는 사용자 지정 설치에서는 위 명령으로 수동 추가할 수 있습니다.
2

Mattermost 봇 생성

Mattermost 봇 계정을 만들고 봇 토큰을 복사합니다.
3

기본 URL 복사

Mattermost 기본 URL(예: https://chat.example.com)을 복사합니다.
4

OpenClaw 구성 및 Gateway 시작

최소 구성:
{
  channels: {
    mattermost: {
      enabled: true,
      botToken: "mm-token",
      baseUrl: "https://chat.example.com",
      dmPolicy: "pairing",
    },
  },
}

네이티브 슬래시 명령

네이티브 슬래시 명령은 선택 사항입니다. 활성화하면 OpenClaw가 Mattermost API를 통해 oc_* 슬래시 명령을 등록하고 Gateway HTTP 서버에서 콜백 POST를 수신합니다.
{
  channels: {
    mattermost: {
      commands: {
        native: true,
        nativeSkills: true,
        callbackPath: "/api/channels/mattermost/command",
        // Mattermost가 Gateway에 직접 접근할 수 없을 때 사용합니다(리버스 프록시/공개 URL).
        callbackUrl: "https://gateway.example.com/api/channels/mattermost/command",
      },
    },
  },
}
  • native: "auto"는 Mattermost에서 기본적으로 비활성화됩니다. 활성화하려면 native: true를 설정하세요.
  • callbackUrl이 생략되면 OpenClaw는 Gateway 호스트/포트 + callbackPath에서 이를 파생합니다.
  • 다중 계정 설정에서는 commands를 최상위 수준 또는 channels.mattermost.accounts.<id>.commands 아래에 설정할 수 있습니다(계정 값이 최상위 필드를 재정의함).
  • 명령 콜백은 OpenClaw가 oc_* 명령을 등록할 때 Mattermost가 반환하는 명령별 토큰으로 검증됩니다.
  • OpenClaw는 각 콜백을 수락하기 전에 현재 Mattermost 명령 등록을 새로 고치므로, 삭제되거나 재생성된 슬래시 명령의 오래된 토큰은 Gateway를 다시 시작하지 않아도 더 이상 수락되지 않습니다.
  • Mattermost API가 명령이 아직 최신 상태임을 확인할 수 없으면 콜백 검증은 닫힌 상태로 실패합니다. 실패한 검증은 짧게 캐시되고, 동시 조회는 통합되며, 새로운 조회 시작은 재전송 압력을 제한하기 위해 명령별로 속도 제한됩니다.
  • 등록에 실패했거나, 시작이 부분적으로만 완료되었거나, 콜백 토큰이 확인된 명령의 등록 토큰과 일치하지 않으면 슬래시 콜백은 닫힌 상태로 실패합니다(한 명령에 유효한 토큰은 다른 명령에 대한 업스트림 검증에 도달할 수 없음).
콜백 엔드포인트는 Mattermost 서버에서 접근 가능해야 합니다.
  • Mattermost가 OpenClaw와 같은 호스트/네트워크 네임스페이스에서 실행되지 않는 한 callbackUrllocalhost로 설정하지 마세요.
  • 해당 URL이 /api/channels/mattermost/command를 OpenClaw로 리버스 프록시하지 않는 한 callbackUrl을 Mattermost 기본 URL로 설정하지 마세요.
  • 빠른 확인 방법은 curl https://<gateway-host>/api/channels/mattermost/command입니다. GET은 404가 아니라 OpenClaw의 405 Method Not Allowed를 반환해야 합니다.
콜백 대상이 비공개/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로 제어됩니다:
채널에서 @멘션된 경우에만 응답합니다.
구성 예시:
{
  channels: {
    mattermost: {
      chatmode: "onchar",
      oncharPrefixes: [">", "!"],
    },
  },
}
참고:
  • onchar는 명시적 @멘션에도 계속 응답합니다.
  • channels.mattermost.requireMention은 레거시 구성에서 존중되지만 chatmode가 권장됩니다.

스레드 및 세션

channels.mattermost.replyToMode를 사용하여 채널 및 그룹 답장이 기본 채널에 남을지, 트리거한 게시물 아래에서 스레드를 시작할지 제어합니다.
  • off(기본값): 인바운드 게시물이 이미 스레드에 있는 경우에만 스레드에서 답장합니다.
  • first: 최상위 채널/그룹 게시물의 경우 해당 게시물 아래에서 스레드를 시작하고 대화를 스레드 범위 세션으로 라우팅합니다.
  • all: 현재 Mattermost에서는 first와 동일하게 동작합니다.
  • 직접 메시지는 이 설정을 무시하고 스레드 없이 유지됩니다.
구성 예시:
{
  channels: {
    mattermost: {
      replyToMode: "all",
    },
  },
}
참고:
  • 스레드 범위 세션은 트리거한 게시물 ID를 스레드 루트로 사용합니다.
  • Mattermost에 스레드 루트가 생기면 후속 청크와 미디어가 같은 스레드에서 계속되므로 현재 firstall은 동일합니다.

접근 제어(DM)

  • 기본값: channels.mattermost.dmPolicy = "pairing"(알 수 없는 발신자는 페어링 코드를 받음).
  • 승인 방법:
    • openclaw pairing list mattermost
    • openclaw pairing approve mattermost <CODE>
  • 공개 DM: channels.mattermost.dmPolicy="open"channels.mattermost.allowFrom=["*"].
  • channels.mattermost.allowFromaccessGroup:<name> 항목을 허용합니다. 접근 그룹을 참조하세요.

채널(그룹)

  • 기본값: channels.mattermost.groupPolicy = "allowlist"(멘션으로 제한됨).
  • channels.mattermost.groupAllowFrom으로 발신자를 허용 목록에 추가합니다(사용자 ID 권장).
  • channels.mattermost.groupAllowFromaccessGroup:<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가 설정되어 있더라도).
예시:
{
  channels: {
    mattermost: {
      groupPolicy: "open",
      groups: {
        "*": { requireMention: true },
        "team-channel-id": { requireMention: false },
      },
    },
  },
}

아웃바운드 전달 대상

openclaw message send 또는 cron/webhooks에서 다음 대상 형식을 사용하세요:
  • 채널의 경우 channel:<id>
  • DM의 경우 user:<id>
  • DM의 경우 @username(Mattermost API를 통해 확인됨)
접두사 없는 불투명 ID(예: 64ifufp...)는 Mattermost에서 모호합니다(사용자 ID와 채널 ID).OpenClaw는 이를 사용자 우선으로 확인합니다:
  • ID가 사용자로 존재하면(GET /api/v4/users/<id> 성공), OpenClaw는 /api/v4/channels/direct를 통해 직접 채널을 확인하여 DM을 보냅니다.
  • 그렇지 않으면 ID는 채널 ID로 처리됩니다.
결정적 동작이 필요하면 항상 명시적 접두사(user:<id> / channel:<id>)를 사용하세요.

DM 채널 재시도

OpenClaw가 Mattermost DM 대상으로 전송하고 먼저 직접 채널을 확인해야 하는 경우, 기본적으로 일시적인 직접 채널 생성 실패를 재시도합니다. Mattermost Plugin 전체에 대해 이 동작을 조정하려면 channels.mattermost.dmChannelRetry를 사용하고, 한 계정에 대해서는 channels.mattermost.accounts.<id>.dmChannelRetry를 사용하세요.
{
  channels: {
    mattermost: {
      dmChannelRetry: {
        maxRetries: 3,
        initialDelayMs: 1000,
        maxDelayMs: 10000,
        timeoutMs: 30000,
      },
    },
  },
}
참고:
  • 이는 모든 Mattermost API 호출이 아니라 DM 채널 생성(/api/v4/channels/direct)에만 적용됩니다.
  • 재시도는 속도 제한, 5xx 응답, 네트워크 또는 시간 초과 오류 같은 일시적 실패에 적용됩니다.
  • 429 이외의 4xx 클라이언트 오류는 영구 오류로 처리되어 재시도되지 않습니다.

미리보기 스트리밍

Mattermost는 사고 과정, 도구 활동, 부분 답장 텍스트를 단일 초안 미리보기 게시물로 스트리밍하며, 최종 답변을 보내도 안전해지면 제자리에서 확정합니다. 미리보기는 청크별 메시지로 채널을 도배하지 않고 같은 게시물 ID에서 업데이트됩니다. 미디어/오류 최종 응답은 대기 중인 미리보기 편집을 취소하고 임시 미리보기 게시물을 플러시하는 대신 일반 전달을 사용합니다. channels.mattermost.streaming으로 활성화합니다:
{
  channels: {
    mattermost: {
      streaming: "partial", // off | partial | block | progress
    },
  },
}
  • partial은 일반적인 선택입니다. 답장이 커지는 동안 편집되는 하나의 미리보기 게시물을 사용한 뒤, 완성된 답변으로 확정합니다.
  • block은 미리보기 게시물 안에서 추가 방식의 초안 청크를 사용합니다.
  • progress는 생성 중 상태 미리보기를 표시하고 완료 시 최종 답변만 게시합니다.
  • off는 미리보기 스트리밍을 비활성화합니다.
  • 스트림을 제자리에서 확정할 수 없는 경우(예: 스트리밍 도중 게시물이 삭제됨), OpenClaw는 답장이 손실되지 않도록 새 최종 게시물을 보내는 방식으로 대체합니다.
  • 추론 전용 페이로드는 > Reasoning: 인용문으로 도착하는 텍스트를 포함하여 채널 게시물에서 억제됩니다. 다른 표면에서 사고 과정을 보려면 /reasoning on을 설정하세요. Mattermost 최종 게시물은 답변만 유지합니다.
  • 채널 매핑 매트릭스는 Streaming을 참조하세요.

반응(메시지 도구)

  • channel=mattermost와 함께 message action=react를 사용합니다.
  • messageId는 Mattermost 게시물 ID입니다.
  • emojithumbsup 또는 :+1: 같은 이름을 허용합니다(콜론은 선택 사항).
  • 반응을 제거하려면 remove=true(부울)를 설정합니다.
  • 반응 추가/제거 이벤트는 시스템 이벤트로 라우팅된 에이전트 세션에 전달됩니다.
예시:
message action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsup
message action=react channel=mattermost target=channel:<channelId> messageId=<postId> emoji=thumbsup remove=true
구성:
  • channels.mattermost.actions.reactions: 반응 작업 활성화/비활성화(기본값 true).
  • 계정별 재정의: channels.mattermost.accounts.<id>.actions.reactions.

대화형 버튼(메시지 도구)

클릭 가능한 버튼이 있는 메시지를 보냅니다. 사용자가 버튼을 클릭하면 에이전트가 선택을 수신하고 응답할 수 있습니다. 채널 기능에 inlineButtons를 추가하여 버튼을 활성화합니다:
{
  channels: {
    mattermost: {
      capabilities: ["inlineButtons"],
    },
  },
}
buttons 매개변수와 함께 message action=send를 사용합니다. 버튼은 2차원 배열(버튼 행)입니다:
message action=send channel=mattermost target=channel:<channelId> buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]]
Button 필드:
text
string
필수
표시 레이블.
callback_data
string
필수
클릭 시 다시 전송되는 값(작업 ID로 사용됨).
style
"default" | "primary" | "danger"
Button 스타일.
사용자가 Button을 클릭하면:
1

Button이 확인으로 대체됨

모든 Button이 확인 줄로 대체됩니다(예: ”✓ Yes selected by @user”).
2

Agent가 선택 항목을 수신함

Agent는 선택 항목을 인바운드 메시지로 수신하고 응답합니다.
  • Button 콜백은 HMAC-SHA256 검증을 사용합니다(자동, 설정 필요 없음).
  • Mattermost는 API 응답에서 콜백 데이터를 제거하므로(보안 기능), 클릭 시 모든 Button이 제거됩니다. 부분 제거는 불가능합니다.
  • 하이픈 또는 밑줄이 포함된 작업 ID는 자동으로 정리됩니다(Mattermost 라우팅 제한).
  • channels.mattermost.capabilities: 기능 문자열 배열입니다. Agent 시스템 프롬프트에서 Button 도구 설명을 활성화하려면 "inlineButtons"를 추가하세요.
  • channels.mattermost.interactions.callbackBaseUrl: Button 콜백을 위한 선택적 외부 기본 URL입니다(예: https://gateway.example.com). Mattermost가 바인드 호스트에서 Gateway에 직접 도달할 수 없을 때 사용하세요.
  • 다중 계정 설정에서는 channels.mattermost.accounts.<id>.interactions.callbackBaseUrl 아래에도 같은 필드를 설정할 수 있습니다.
  • interactions.callbackBaseUrl이 생략되면 OpenClaw는 gateway.customBindHost + gateway.port에서 콜백 URL을 파생한 다음 http://localhost:<port>로 폴백합니다.
  • 도달 가능성 규칙: Button 콜백 URL은 Mattermost 서버에서 도달 가능해야 합니다. localhost는 Mattermost와 OpenClaw가 같은 호스트/네트워크 네임스페이스에서 실행될 때만 작동합니다.
  • 콜백 대상이 비공개/tailnet/internal인 경우 해당 호스트/도메인을 Mattermost ServiceSettings.AllowedUntrustedInternalConnections에 추가하세요.

직접 API 통합(외부 스크립트)

외부 스크립트와 Webhook은 Agent의 message 도구를 거치지 않고 Mattermost REST API를 통해 Button을 직접 게시할 수 있습니다. 가능하면 Plugin의 buildButtonAttachments()를 사용하세요. 원시 JSON을 게시하는 경우 다음 규칙을 따르세요: 페이로드 구조:
{
  channel_id: "<channelId>",
  message: "Choose an option:",
  props: {
    attachments: [
      {
        actions: [
          {
            id: "mybutton01", // alphanumeric only - see below
            type: "button", // required, or clicks are silently ignored
            name: "Approve", // display label
            style: "primary", // optional: "default", "primary", "danger"
            integration: {
              url: "https://gateway.example.com/mattermost/interactions/default",
              context: {
                action_id: "mybutton01", // must match button id (for name lookup)
                action: "approve",
                // ... any custom fields ...
                _token: "<hmac>", // see HMAC section below
              },
            },
          },
        ],
      },
    ],
  },
}
중요 규칙
  1. 첨부 파일은 최상위 attachments가 아니라 props.attachments에 들어갑니다(조용히 무시됨).
  2. 모든 작업에는 type: "button"이 필요합니다. 없으면 클릭이 조용히 삼켜집니다.
  3. 모든 작업에는 id 필드가 필요합니다. Mattermost는 ID가 없는 작업을 무시합니다.
  4. 작업 id영숫자만 사용할 수 있습니다([a-zA-Z0-9]). 하이픈과 밑줄은 Mattermost의 서버 측 작업 라우팅을 깨뜨립니다(404 반환). 사용하기 전에 제거하세요.
  5. 확인 메시지가 원시 ID 대신 Button 이름(예: “Approve”)을 표시하도록 context.action_id는 Button의 id와 일치해야 합니다.
  6. context.action_id는 필수입니다. 없으면 상호작용 핸들러가 400을 반환합니다.
HMAC 토큰 생성 Gateway는 HMAC-SHA256으로 Button 클릭을 검증합니다. 외부 스크립트는 Gateway의 검증 로직과 일치하는 토큰을 생성해야 합니다:
1

bot token에서 시크릿 파생

HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)
2

컨텍스트 객체 빌드

_token제외한 모든 필드로 컨텍스트 객체를 빌드합니다.
3

정렬된 키로 직렬화

정렬된 키공백 없음으로 직렬화합니다(Gateway는 정렬된 키와 함께 JSON.stringify를 사용하며, 이는 압축된 출력을 생성합니다).
4

페이로드 서명

HMAC-SHA256(key=secret, data=serializedContext)
5

토큰 추가

결과 16진수 다이제스트를 컨텍스트의 _token으로 추가합니다.
Python 예시:
import hmac, hashlib, json

secret = hmac.new(
    b"openclaw-mattermost-interactions",
    bot_token.encode(), hashlib.sha256
).hexdigest()

ctx = {"action_id": "mybutton01", "action": "approve"}
payload = json.dumps(ctx, sort_keys=True, separators=(",", ":"))
token = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest()

context = {**ctx, "_token": token}
  • Python의 json.dumps는 기본적으로 공백을 추가합니다({"key": "val"}). JavaScript의 압축 출력({"key":"val"})과 일치시키려면 separators=(",", ":")를 사용하세요.
  • 항상 모든 컨텍스트 필드(_token 제외)에 서명하세요. Gateway는 _token을 제거한 다음 남은 모든 항목에 서명합니다. 일부만 서명하면 조용한 검증 실패가 발생합니다.
  • sort_keys=True를 사용하세요. Gateway는 서명 전에 키를 정렬하며, Mattermost는 페이로드를 저장할 때 컨텍스트 필드 순서를 바꿀 수 있습니다.
  • 무작위 바이트가 아니라 bot token에서 시크릿을 파생하세요(결정적). 시크릿은 Button을 생성하는 프로세스와 검증하는 Gateway에서 동일해야 합니다.

디렉터리 어댑터

Mattermost Plugin에는 Mattermost API를 통해 채널 및 사용자 이름을 확인하는 디렉터리 어댑터가 포함되어 있습니다. 이를 통해 openclaw message send 및 cron/webhook 전달에서 #channel-name@username 대상을 사용할 수 있습니다. 설정은 필요하지 않습니다. 어댑터는 계정 설정의 bot token을 사용합니다.

다중 계정

Mattermost는 channels.mattermost.accounts 아래에서 여러 계정을 지원합니다:
{
  channels: {
    mattermost: {
      accounts: {
        default: { name: "Primary", botToken: "mm-token", baseUrl: "https://chat.example.com" },
        alerts: { name: "Alerts", botToken: "mm-token-2", baseUrl: "https://alerts.example.com" },
      },
    },
  },
}

문제 해결

봇이 채널에 있는지 확인하고 멘션하거나(oncall), 트리거 접두사를 사용하거나(onchar), chatmode: "onmessage"를 설정하세요.
  • bot token, 기본 URL, 계정 활성화 여부를 확인하세요.
  • 다중 계정 문제: 환경 변수는 default 계정에만 적용됩니다.
  • Unauthorized: invalid command token.: OpenClaw가 콜백 토큰을 수락하지 않았습니다. 일반적인 원인:
    • 슬래시 명령 등록이 실패했거나 시작 시 부분적으로만 완료됨
    • 콜백이 잘못된 Gateway/계정으로 전달됨
    • Mattermost에 이전 콜백 대상을 가리키는 오래된 명령이 아직 있음
    • Gateway가 슬래시 명령을 다시 활성화하지 않고 재시작됨
  • 네이티브 슬래시 명령이 작동을 멈추면 로그에서 mattermost: failed to register slash commands 또는 mattermost: native slash commands enabled but no commands could be registered를 확인하세요.
  • callbackUrl이 생략되어 있고 로그에서 콜백이 http://127.0.0.1:18789/...로 해석되었다고 경고하는 경우, 해당 URL은 Mattermost가 OpenClaw와 같은 호스트/네트워크 네임스페이스에서 실행될 때만 도달 가능할 가능성이 높습니다. 대신 명시적으로 외부에서 도달 가능한 commands.callbackUrl을 설정하세요.
  • Button이 흰색 상자로 표시됨: Agent가 잘못된 형식의 Button 데이터를 보내고 있을 수 있습니다. 각 Button에 textcallback_data 필드가 모두 있는지 확인하세요.
  • Button은 렌더링되지만 클릭해도 아무 일도 일어나지 않음: Mattermost 서버 설정의 AllowedUntrustedInternalConnections127.0.0.1 localhost가 포함되어 있고, ServiceSettings에서 EnablePostActionIntegrationtrue인지 확인하세요.
  • 클릭 시 Button이 404를 반환함: Button id에 하이픈 또는 밑줄이 포함되어 있을 가능성이 높습니다. Mattermost의 작업 라우터는 영숫자가 아닌 ID에서 깨집니다. [a-zA-Z0-9]만 사용하세요.
  • Gateway 로그 invalid _token: HMAC 불일치입니다. 모든 컨텍스트 필드(일부가 아님)에 서명하고, 정렬된 키를 사용하며, 압축 JSON(공백 없음)을 사용하는지 확인하세요. 위의 HMAC 섹션을 참조하세요.
  • Gateway 로그 missing _token in context: _token 필드가 Button의 컨텍스트에 없습니다. 통합 페이로드를 빌드할 때 포함되었는지 확인하세요.
  • 확인에 Button 이름 대신 원시 ID가 표시됨: context.action_id가 Button의 id와 일치하지 않습니다. 둘 다 같은 정리된 값으로 설정하세요.
  • Agent가 Button을 알지 못함: Mattermost 채널 설정에 capabilities: ["inlineButtons"]를 추가하세요.

관련 항목