Discord (Bot API)

상태: 공식 Discord 게이트웨이를 통한 DM 및 길드 채널 지원 준비 완료.

빠른 설정

새 애플리케이션과 봇을 생성하고, 서버에 봇을 추가하고, OpenClaw와 페어링해야 합니다. 개인 전용 서버에 봇을 추가하는 것을 권장합니다. 아직 서버가 없다면 먼저 생성하세요 (Create My Own > For me and my friends 선택).

1단계: Discord 애플리케이션 및 봇 생성

[Discord Developer Portal](https://discord.com/developers/applications)로 이동하여 **New Application**을 클릭합니다. "OpenClaw"와 같은 이름을 지정합니다.

사이드바에서 **Bot**을 클릭합니다. **Username**을 OpenClaw 에이전트의 이름으로 설정합니다.

2단계: 특권 인텐트 활성화

**Bot** 페이지에서 아래로 스크롤하여 **Privileged Gateway Intents**에서 다음을 활성화합니다:

- **Message Content Intent** (필수)
- **Server Members Intent** (권장; 역할 허용 목록 및 이름-ID 매칭에 필요)
- **Presence Intent** (선택; 프레즌스 업데이트에만 필요)

3단계: 봇 토큰 복사

**Bot** 페이지에서 위로 스크롤하여 **Reset Token**을 클릭합니다.

> **참고:** 이름과 달리 첫 번째 토큰을 생성하는 것이며, "리셋"하는 것이 아닙니다.

토큰을 복사하여 저장합니다. 이것이 **Bot Token**이며 곧 필요합니다.

4단계: 초대 URL 생성 및 서버에 봇 추가

사이드바에서 **OAuth2**를 클릭합니다. 적절한 권한이 포함된 초대 URL을 생성합니다.

**OAuth2 URL Generator**로 스크롤하여 다음을 활성화합니다:

- `bot`
- `applications.commands`

아래에 **Bot Permissions** 섹션이 나타납니다. 다음을 활성화합니다:

- View Channels
- Send Messages
- Read Message History
- Embed Links
- Attach Files
- Add Reactions (선택)

하단에 생성된 URL을 복사하여 브라우저에 붙여넣고, 서버를 선택하고, **Continue**를 클릭하여 연결합니다. Discord 서버에 봇이 표시되어야 합니다.

5단계: 개발자 모드 활성화 및 ID 수집

Discord 앱으로 돌아가서 내부 ID를 복사할 수 있도록 개발자 모드를 활성화합니다.

1. **User Settings** (아바타 옆 기어 아이콘) -> **Advanced** -> **Developer Mode** 토글 켜기
2. 사이드바에서 **서버 아이콘**을 마우스 오른쪽 클릭 -> **Copy Server ID**
3. **자신의 아바타**를 마우스 오른쪽 클릭 -> **Copy User ID**

**Server ID**와 **User ID**를 Bot Token과 함께 저장합니다 -- 다음 단계에서 세 가지 모두 OpenClaw에 보냅니다.

6단계: 서버 멤버로부터 DM 허용

페어링이 작동하려면 Discord가 봇의 DM을 허용해야 합니다. **서버 아이콘** 마우스 오른쪽 클릭 -> **Privacy Settings** -> **Direct Messages** 토글 켜기.

서버 멤버(봇 포함)가 DM을 보낼 수 있게 됩니다. Discord DM을 OpenClaw와 함께 사용하려면 이를 활성화된 상태로 유지합니다. 길드 채널만 사용할 계획이면 페어링 후 DM을 비활성화할 수 있습니다.

7단계: 봇 토큰을 안전하게 설정 (채팅으로 보내지 마세요)

Discord 봇 토큰은 비밀(비밀번호와 같음)입니다. 에이전트에게 메시지를 보내기 전에 OpenClaw를 실행하는 머신에 설정합니다.
openclaw config set channels.discord.token '"YOUR_BOT_TOKEN"' --json
openclaw config set channels.discord.enabled true --json
openclaw gateway
OpenClaw가 이미 백그라운드 서비스로 실행 중이면 대신 `openclaw gateway restart`를 사용합니다.

8단계: OpenClaw 설정 및 페어링

  #### 에이전트에게 요청
    기존 채널(예: Telegram)에서 OpenClaw 에이전트와 채팅합니다. Discord가 첫 번째 채널이면 CLI / 설정 탭을 사용합니다.

    > "Discord 봇 토큰을 설정에 넣었습니다. User ID `<user_id>`와 Server ID `<server_id>`로 Discord 설정을 완료해 주세요."

  #### CLI / 설정
    파일 기반 설정을 선호하는 경우:
{
  channels: {
    discord: {
      enabled: true,
      token: "YOUR_BOT_TOKEN",
    },
  },
}
    기본 계정의 환경 변수 폴백:
DISCORD_BOT_TOKEN=...
    `channels.discord.token`에는 SecretRef 값도 지원됩니다 (env/file/exec 프로바이더). [Secrets Management](/docs/gateway/secrets)를 참조하세요.

9단계: 첫 DM 페어링 승인

게이트웨이가 실행될 때까지 기다린 후 Discord에서 봇에게 DM을 보냅니다. 페어링 코드로 응답합니다.


  #### 에이전트에게 요청
    기존 채널에서 에이전트에게 페어링 코드를 보냅니다:

    > "이 Discord 페어링 코드를 승인해 주세요: `<CODE>`"

  #### CLI
openclaw pairing list discord
openclaw pairing approve discord <CODE>
페어링 코드는 1시간 후 만료됩니다.

이제 Discord DM을 통해 에이전트와 채팅할 수 있어야 합니다.

참고: 토큰 해석은 계정을 인식합니다. 설정 토큰 값이 환경 변수 폴백보다 우선합니다. DISCORD_BOT_TOKEN은 기본 계정에만 사용됩니다. 고급 아웃바운드 호출 (메시지 도구/채널 액션)의 경우 해당 호출에 명시적 호출별 token이 사용됩니다. 계정 정책/재시도 설정은 활성 런타임 스냅샷의 선택된 계정에서 가져옵니다.

권장: 길드 작업 공간 설정

DM이 작동하면 Discord 서버를 각 채널이 자체 에이전트 세션과 컨텍스트를 가진 완전한 작업 공간으로 설정할 수 있습니다. 봇과 당신만 있는 개인 서버에 권장됩니다.

1단계: 서버를 길드 허용 목록에 추가

에이전트가 DM뿐만 아니라 서버의 모든 채널에서 응답할 수 있게 합니다.


  #### 에이전트에게 요청
    > "내 Discord Server ID `<server_id>`를 길드 허용 목록에 추가해 줘"

  #### 설정
{
  channels: {
    discord: {
      groupPolicy: "allowlist",
      guilds: {
        YOUR_SERVER_ID: {
          requireMention: true,
          users: ["YOUR_USER_ID"],
        },
      },
    },
  },
}

2단계: @멘션 없이 응답 허용

기본적으로 에이전트는 길드 채널에서 @멘션될 때만 응답합니다. 개인 서버에서는 모든 메시지에 응답하도록 설정하는 것이 좋습니다.


  #### 에이전트에게 요청
    > "이 서버에서 @멘션 없이도 에이전트가 응답하도록 허용해 줘"

  #### 설정
    길드 설정에서 `requireMention: false`를 설정합니다:
{
  channels: {
    discord: {
      guilds: {
        YOUR_SERVER_ID: {
          requireMention: false,
        },
      },
    },
  },
}

3단계: 길드 채널에서 메모리 계획

기본적으로 장기 메모리(MEMORY.md)는 DM 세션에서만 로드됩니다. 길드 채널은 MEMORY.md를 자동 로드하지 않습니다.


  #### 에이전트에게 요청
    > "Discord 채널에서 질문할 때 MEMORY.md의 장기 컨텍스트가 필요하면 memory_search 또는 memory_get을 사용해 줘."

  #### 수동
    모든 채널에서 공유 컨텍스트가 필요하면 안정적인 지침을 `AGENTS.md` 또는 `USER.md`에 넣습니다 (모든 세션에 주입됨). 장기 노트는 `MEMORY.md`에 보관하고 메모리 도구로 필요할 때 접근합니다.

이제 Discord 서버에 채널을 만들고 채팅을 시작합니다. 에이전트가 채널 이름을 볼 수 있으며 각 채널은 자체 격리된 세션을 갖습니다 — 워크플로에 맞게 #coding, #home, #research 등을 설정할 수 있습니다.

런타임 모델

  • 게이트웨이가 Discord 연결을 소유합니다.
  • 응답 라우팅은 결정론적: Discord 인바운드는 Discord로 응답합니다.
  • 기본적으로 (session.dmScope=main) 다이렉트 채팅은 에이전트 메인 세션을 공유합니다 (agent:main:main).
  • 길드 채널은 격리된 세션 키입니다 (agent:<agentId>:discord:channel:<channelId>).
  • 그룹 DM은 기본적으로 무시됩니다 (channels.discord.dm.groupEnabled=false).
  • 네이티브 슬래시 명령은 격리된 명령 세션에서 실행되며 (agent:<agentId>:discord:slash:<userId>), 라우팅된 대화 세션에 CommandTargetSessionKey를 전달합니다.

포럼 채널

Discord 포럼 및 미디어 채널은 스레드 게시물만 허용합니다. OpenClaw는 두 가지 생성 방법을 지원합니다:

  • 포럼 부모에 메시지 전송 (channel:<forumId>)으로 자동 스레드 생성. 스레드 제목은 메시지의 첫 비어있지 않은 줄을 사용합니다.
  • openclaw message thread create로 직접 스레드 생성. 포럼 채널에는 --message-id를 전달하지 마세요.

예시: 포럼 부모에 전송하여 스레드 생성

openclaw message send --channel discord --target channel:<forumId> \
  --message "Topic title\nBody of the post"

예시: 포럼 스레드를 명시적으로 생성

openclaw message thread create --channel discord --target channel:<forumId> \
  --thread-name "Topic title" --message "Body of the post"

포럼 부모는 Discord 컴포넌트를 허용하지 않습니다. 컴포넌트가 필요하면 스레드 자체에 전송합니다 (channel:<threadId>).

인터랙티브 컴포넌트

OpenClaw는 에이전트 메시지에 Discord 컴포넌트 v2 컨테이너를 지원합니다. components 페이로드와 함께 메시지 도구를 사용합니다. 인터랙션 결과는 일반 인바운드 메시지로 에이전트에게 라우팅되며 기존 Discord replyToMode 설정을 따릅니다.

지원되는 블록:

  • text, section, separator, actions, media-gallery, file
  • 액션 행에는 최대 5개의 버튼 또는 단일 선택 메뉴 허용
  • 선택 유형: string, user, role, mentionable, channel

기본적으로 컴포넌트는 일회용입니다. components.reusable=true를 설정하면 버튼, 선택, 폼을 만료될 때까지 여러 번 사용할 수 있습니다.

버튼 클릭을 제한하려면 해당 버튼에 allowedUsers를 설정합니다 (Discord 사용자 ID, 태그, 또는 *). 설정된 경우 일치하지 않는 사용자는 일시적 거부 메시지를 받습니다.

/model/models 슬래시 명령은 프로바이더와 모델 드롭다운 및 제출 단계가 있는 인터랙티브 모델 피커를 엽니다. 피커 응답은 일시적이며 호출한 사용자만 사용할 수 있습니다.

파일 첨부:

  • file 블록은 첨부 참조를 가리켜야 합니다 (attachment://<filename>)
  • media/path/filePath로 첨부를 제공합니다 (단일 파일); 여러 파일에는 media-gallery 사용
  • 업로드 이름이 첨부 참조와 일치해야 하는 경우 filename으로 재정의

모달 폼:

  • 최대 5개 필드로 components.modal 추가
  • 필드 유형: text, checkbox, radio, select, role-select, user-select
  • OpenClaw가 자동으로 트리거 버튼 추가

예시:

{
  channel: "discord",
  action: "send",
  to: "channel:123456789012345678",
  message: "Optional fallback text",
  components: {
    reusable: true,
    text: "Choose a path",
    blocks: [
      {
        type: "actions",
        buttons: [
          {
            label: "Approve",
            style: "success",
            allowedUsers: ["123456789012345678"],
          },
          { label: "Decline", style: "danger" },
        ],
      },
      {
        type: "actions",
        select: {
          type: "string",
          placeholder: "Pick an option",
          options: [
            { label: "Option A", value: "a" },
            { label: "Option B", value: "b" },
          ],
        },
      },
    ],
    modal: {
      title: "Details",
      triggerLabel: "Open form",
      fields: [
        { type: "text", label: "Requester" },
        {
          type: "select",
          label: "Priority",
          options: [
            { label: "Low", value: "low" },
            { label: "High", value: "high" },
          ],
        },
      ],
    },
  },
}

접근 제어 및 라우팅

DM 정책

`channels.discord.dmPolicy`로 DM 접근을 제어합니다 (레거시: `channels.discord.dm.policy`):

- `pairing` (기본값)
- `allowlist`
- `open` (`channels.discord.allowFrom`에 `"*"` 필요; 레거시: `channels.discord.dm.allowFrom`)
- `disabled`

DM 정책이 open이 아닌 경우 알 수 없는 사용자는 차단됩니다 (`pairing` 모드에서는 페어링 안내를 받음).

멀티 계정 우선순위:

- `channels.discord.accounts.default.allowFrom`은 `default` 계정에만 적용됩니다.
- 이름이 지정된 계정은 자체 `allowFrom`이 미설정이면 `channels.discord.allowFrom`을 상속합니다.
- 이름이 지정된 계정은 `channels.discord.accounts.default.allowFrom`을 상속하지 않습니다.

전달용 DM 대상 형식:

- `user:<id>`
- `<@id>` 멘션

순수 숫자 ID는 모호하며 명시적 user/channel 대상 종류가 제공되지 않으면 거부됩니다.

길드 정책

길드 처리는 `channels.discord.groupPolicy`로 제어됩니다:

- `open`
- `allowlist`
- `disabled`

`channels.discord`가 존재할 때 안전한 기본값은 `allowlist`입니다.

`allowlist` 동작:

- 길드가 `channels.discord.guilds`와 일치해야 합니다 (`id` 권장, 슬러그도 허용)
- 선택적 발신자 허용 목록: `users` (안정 ID 권장) 및 `roles` (역할 ID만); 둘 중 하나가 설정되면 `users` 또는 `roles`에 일치하는 발신자가 허용됩니다
- 직접 이름/태그 매칭은 기본적으로 비활성화; `channels.discord.dangerouslyAllowNameMatching: true`는 비상 호환 모드로만 활성화
- `users`에 이름/태그를 사용할 수 있지만 ID가 더 안전합니다; `openclaw security audit`은 이름/태그 항목 사용 시 경고합니다
- 길드에 `channels`가 설정되면 나열되지 않은 채널은 거부됩니다
- 길드에 `channels` 블록이 없으면 해당 허용된 길드의 모든 채널이 허용됩니다

예시:
{
  channels: {
    discord: {
      groupPolicy: "allowlist",
      guilds: {
        "123456789012345678": {
          requireMention: true,
          ignoreOtherMentions: true,
          users: ["987654321098765432"],
          roles: ["123456789012345678"],
          channels: {
            general: { allow: true },
            help: { allow: true, requireMention: true },
          },
        },
      },
    },
  },
}
`DISCORD_BOT_TOKEN`만 설정하고 `channels.discord` 블록을 생성하지 않으면, `channels.defaults.groupPolicy`가 `open`이어도 런타임 폴백은 `groupPolicy="allowlist"`입니다 (로그에 경고).

멘션 및 그룹 DM

길드 메시지는 기본적으로 멘션 게이팅됩니다.

멘션 감지 대상:

- 명시적 봇 멘션
- 설정된 멘션 패턴 (`agents.list[].groupChat.mentionPatterns`, 폴백 `messages.groupChat.mentionPatterns`)
- 지원되는 경우에서의 암묵적 봇 답장 동작

`requireMention`은 길드/채널별로 설정됩니다 (`channels.discord.guilds...`).
`ignoreOtherMentions`는 선택적으로 봇이 아닌 다른 사용자/역할을 멘션하는 메시지를 삭제합니다 (@everyone/@here 제외).

그룹 DM:

- 기본: 무시 (`dm.groupEnabled=false`)
- `dm.groupChannels` (채널 ID 또는 슬러그)를 통한 선택적 허용 목록

역할 기반 에이전트 라우팅

bindings[].match.roles를 사용하여 Discord 길드 멤버를 역할 ID별로 다른 에이전트로 라우팅합니다. 역할 기반 바인딩은 역할 ID만 허용하며 peer 또는 parent-peer 바인딩 이후, guild-only 바인딩 이전에 평가됩니다. 바인딩이 다른 매치 필드도 설정하면 (예: peer + guildId + roles) 설정된 모든 필드가 일치해야 합니다.

{
  bindings: [
    {
      agentId: "opus",
      match: {
        channel: "discord",
        guildId: "123456789012345678",
        roles: ["111111111111111111"],
      },
    },
    {
      agentId: "sonnet",
      match: {
        channel: "discord",
        guildId: "123456789012345678",
      },
    },
  ],
}

개발자 포털 설정

앱 및 봇 생성
1. Discord Developer Portal -> **Applications** -> **New Application**
2. **Bot** -> **Add Bot**
3. 봇 토큰 복사
특권 인텐트
**Bot -> Privileged Gateway Intents**에서 활성화:

- Message Content Intent
- Server Members Intent (권장)

Presence intent는 선택 사항이며 프레즌스 업데이트를 수신하려는 경우에만 필요합니다. 봇 프레즌스 설정 (`setPresence`)에는 멤버의 프레즌스 업데이트 활성화가 필요하지 않습니다.
OAuth 스코프 및 기본 권한
OAuth URL 생성기:

- 스코프: `bot`, `applications.commands`

일반적인 기본 권한:

- View Channels
- Send Messages
- Read Message History
- Embed Links
- Attach Files
- Add Reactions (선택)

명시적으로 필요하지 않는 한 `Administrator`는 피합니다.
ID 복사
Discord 개발자 모드를 활성화한 후 복사:

- 서버 ID
- 채널 ID
- 사용자 ID

신뢰할 수 있는 감사 및 프로빙을 위해 OpenClaw 설정에서 숫자 ID를 권장합니다.

네이티브 명령 및 명령 인가

  • commands.native는 기본적으로 "auto"이며 Discord에서 활성화됩니다.
  • 채널별 재정의: channels.discord.commands.native.
  • commands.native=false는 이전에 등록된 Discord 네이티브 명령을 명시적으로 삭제합니다.
  • 네이티브 명령 인가는 일반 메시지 처리와 동일한 Discord 허용 목록/정책을 사용합니다.
  • 인가되지 않은 사용자에게도 Discord UI에 명령이 표시될 수 있지만, 실행 시 OpenClaw 인가를 적용하고 “not authorized”를 반환합니다.

명령 카탈로그 및 동작은 Slash commands를 참조하세요.

기본 슬래시 명령 설정:

  • ephemeral: true

기능 세부사항

응답 태그 및 네이티브 응답
Discord는 에이전트 출력에서 응답 태그를 지원합니다:

- `[[reply_to_current]]`
- `[[reply_to:<id>]]`

`channels.discord.replyToMode`로 제어:

- `off` (기본값)
- `first`
- `all`

참고: `off`는 암묵적 응답 스레딩을 비활성화합니다. 명시적 `[[reply_to_*]]` 태그는 여전히 적용됩니다.

메시지 ID는 에이전트가 특정 메시지를 대상으로 할 수 있도록 컨텍스트/히스토리에 표시됩니다.
실시간 스트림 미리보기
OpenClaw는 임시 메시지를 보내고 텍스트가 도착하면 편집하여 초안 응답을 스트리밍할 수 있습니다.

- `channels.discord.streaming`은 미리보기 스트리밍을 제어합니다 (`off` | `partial` | `block` | `progress`, 기본: `off`).
- `progress`는 크로스 채널 일관성을 위해 허용되며 Discord에서 `partial`로 매핑됩니다.
- `channels.discord.streamMode`는 레거시 별칭이며 자동 마이그레이션됩니다.
- `partial`은 토큰이 도착하면 단일 미리보기 메시지를 편집합니다.
- `block`은 초안 크기의 청크를 생성합니다 (`draftChunk`으로 크기와 분할점 조정).

예시:
{
  channels: {
    discord: {
      streaming: "partial",
    },
  },
}
`block` 모드 청킹 기본값 (`channels.discord.textChunkLimit`으로 클램핑):
{
  channels: {
    discord: {
      streaming: "block",
      draftChunk: {
        minChars: 200,
        maxChars: 800,
        breakPreference: "paragraph",
      },
    },
  },
}
미리보기 스트리밍은 텍스트 전용이며 미디어 응답은 일반 전달로 폴백합니다.

참고: 미리보기 스트리밍은 블록 스트리밍과 별개입니다. Discord에 블록 스트리밍이 명시적으로 활성화되면 OpenClaw는 이중 스트리밍을 방지하기 위해 미리보기 스트림을 건너뜁니다.
히스토리, 컨텍스트, 스레드 동작
길드 히스토리 컨텍스트:

- `channels.discord.historyLimit` 기본 `20`
- 폴백: `messages.groupChat.historyLimit`
- `0`으로 비활성화

DM 히스토리 제어:

- `channels.discord.dmHistoryLimit`
- `channels.discord.dms["<user_id>"].historyLimit`

스레드 동작:

- Discord 스레드는 채널 세션으로 라우팅됨
- 부모 스레드 메타데이터는 부모 세션 연결에 사용 가능
- 스레드 설정은 스레드별 항목이 없으면 부모 채널 설정을 상속

채널 토픽은 **신뢰할 수 없는** 컨텍스트로 주입됩니다 (시스템 프롬프트로가 아님).
서브에이전트를 위한 스레드 바인딩 세션
Discord는 스레드를 세션 대상에 바인딩하여 해당 스레드의 후속 메시지가 동일한 세션(서브에이전트 세션 포함)으로 계속 라우팅되도록 할 수 있습니다.

명령:

- `/focus <target>` 현재/새 스레드를 서브에이전트/세션 대상에 바인딩
- `/unfocus` 현재 스레드 바인딩 제거
- `/agents` 활성 실행 및 바인딩 상태 표시
- `/session idle <duration|off>` 포커스된 바인딩의 비활성 자동 해제 확인/업데이트
- `/session max-age <duration|off>` 포커스된 바인딩의 하드 최대 수명 확인/업데이트

설정:
{
  session: {
    threadBindings: {
      enabled: true,
      idleHours: 24,
      maxAgeHours: 0,
    },
  },
  channels: {
    discord: {
      threadBindings: {
        enabled: true,
        idleHours: 24,
        maxAgeHours: 0,
        spawnSubagentSessions: false, // 옵트인
      },
    },
  },
}
참고:

- `session.threadBindings.*`는 전역 기본값을 설정합니다.
- `channels.discord.threadBindings.*`는 Discord 동작을 재정의합니다.
- `spawnSubagentSessions`가 true여야 `sessions_spawn({ thread: true })`에 대한 스레드를 자동 생성/바인딩합니다.
- `spawnAcpSessions`가 true여야 ACP에 대한 스레드를 자동 생성/바인딩합니다 (`/acp spawn ... --thread ...` 또는 `sessions_spawn({ runtime: "acp", thread: true })`).
- 계정에 스레드 바인딩이 비활성화되면 `/focus` 및 관련 스레드 바인딩 작업을 사용할 수 없습니다.

[Sub-agents](/docs/tools/subagents), [ACP Agents](/docs/tools/acp-agents), [Configuration Reference](/docs/gateway/configuration-reference)를 참조하세요.
영구 ACP 채널 바인딩
안정적인 "항상 켜진" ACP 작업 공간에는 Discord 대화를 대상으로 하는 최상위 타입 ACP 바인딩을 설정합니다.

설정 경로:

- `bindings[]`에 `type: "acp"` 및 `match.channel: "discord"`

예시:
{
  agents: {
    list: [
      {
        id: "codex",
        runtime: {
          type: "acp",
          acp: {
            agent: "codex",
            backend: "acpx",
            mode: "persistent",
            cwd: "/workspace/openclaw",
          },
        },
      },
    ],
  },
  bindings: [
    {
      type: "acp",
      agentId: "codex",
      match: {
        channel: "discord",
        accountId: "default",
        peer: { kind: "channel", id: "222222222222222222" },
      },
      acp: { label: "codex-main" },
    },
  ],
  channels: {
    discord: {
      guilds: {
        "111111111111111111": {
          channels: {
            "222222222222222222": {
              requireMention: false,
            },
          },
        },
      },
    },
  },
}
참고:

- 스레드 메시지는 부모 채널 ACP 바인딩을 상속할 수 있습니다.
- 바인딩된 채널 또는 스레드에서 `/new` 및 `/reset`은 동일한 ACP 세션을 제자리에서 리셋합니다.
- 임시 스레드 바인딩은 여전히 작동하며 활성 상태에서 대상 해석을 재정의할 수 있습니다.

바인딩 동작 세부사항은 [ACP Agents](/docs/tools/acp-agents)를 참조하세요.
리액션 알림
길드별 리액션 알림 모드:

- `off`
- `own` (기본값)
- `all`
- `allowlist` (`guilds.<id>.users` 사용)

리액션 이벤트는 시스템 이벤트로 변환되어 라우팅된 Discord 세션에 첨부됩니다.
수신 확인 리액션
`ackReaction`은 OpenClaw가 인바운드 메시지를 처리하는 동안 확인 이모지를 전송합니다.

해석 순서:

- `channels.discord.accounts.<accountId>.ackReaction`
- `channels.discord.ackReaction`
- `messages.ackReaction`
- 에이전트 ID 이모지 폴백 (`agents.list[].identity.emoji`, 없으면 "👀")

참고:

- Discord는 유니코드 이모지 또는 사용자 정의 이모지 이름을 허용합니다.
- `""`를 사용하여 채널 또는 계정에서 리액션을 비활성화합니다.
설정 쓰기
채널에서 시작된 설정 쓰기는 기본적으로 활성화됩니다.

이는 `/config set|unset` 흐름에 영향을 미칩니다 (명령 기능 활성화 시).

비활성화:
{
  channels: {
    discord: {
      configWrites: false,
    },
  },
}
게이트웨이 프록시
`channels.discord.proxy`로 Discord 게이트웨이 WebSocket 트래픽 및 시작 REST 조회(애플리케이션 ID + 허용 목록 해석)를 HTTP(S) 프록시를 통해 라우팅합니다.
{
  channels: {
    discord: {
      proxy: "http://proxy.example:8080",
    },
  },
}
계정별 재정의:
{
  channels: {
    discord: {
      accounts: {
        primary: {
          proxy: "http://proxy.example:8080",
        },
      },
    },
  },
}
PluralKit 지원
프록시된 메시지를 시스템 멤버 ID로 매핑하기 위해 PluralKit 해석을 활성화합니다:
{
  channels: {
    discord: {
      pluralkit: {
        enabled: true,
        token: "pk_live_...", // 선택; 비공개 시스템에 필요
      },
    },
  },
}
참고:

- 허용 목록에 `pk:<memberId>` 사용 가능
- 멤버 표시 이름은 `channels.discord.dangerouslyAllowNameMatching: true`일 때만 이름/슬러그로 매칭
- 조회는 원본 메시지 ID를 사용하며 시간 창 제한이 있음
- 조회 실패 시 프록시된 메시지는 봇 메시지로 취급되며 `allowBots=true`가 아니면 삭제됨
프레즌스 설정
상태나 활동 필드를 설정하거나 자동 프레즌스를 활성화하면 프레즌스 업데이트가 적용됩니다.

상태만 예시:
{
  channels: {
    discord: {
      status: "idle",
    },
  },
}
활동 예시 (사용자 정의 상태가 기본 활동 유형):
{
  channels: {
    discord: {
      activity: "Focus time",
      activityType: 4,
    },
  },
}
스트리밍 예시:
{
  channels: {
    discord: {
      activity: "Live coding",
      activityType: 1,
      activityUrl: "https://twitch.tv/openclaw",
    },
  },
}
활동 유형 맵:

- 0: Playing
- 1: Streaming (`activityUrl` 필요)
- 2: Listening
- 3: Watching
- 4: Custom (활동 텍스트를 상태로 사용; 이모지는 선택)
- 5: Competing

자동 프레즌스 예시 (런타임 헬스 시그널):
{
  channels: {
    discord: {
      autoPresence: {
        enabled: true,
        intervalMs: 30000,
        minUpdateIntervalMs: 15000,
        exhaustedText: "token exhausted",
      },
    },
  },
}
자동 프레즌스는 런타임 가용성을 Discord 상태에 매핑합니다: healthy => online, degraded 또는 unknown => idle, exhausted 또는 unavailable => dnd. 선택적 텍스트 재정의:

- `autoPresence.healthyText`
- `autoPresence.degradedText`
- `autoPresence.exhaustedText` (`{reason}` 플레이스홀더 지원)
Discord에서의 실행 승인
Discord는 DM에서 버튼 기반 실행 승인을 지원하며 원본 채널에 승인 프롬프트를 선택적으로 게시할 수 있습니다.

설정 경로:

- `channels.discord.execApprovals.enabled`
- `channels.discord.execApprovals.approvers`
- `channels.discord.execApprovals.target` (`dm` | `channel` | `both`, 기본: `dm`)
- `agentFilter`, `sessionFilter`, `cleanupAfterResolve`

`target`이 `channel` 또는 `both`이면 승인 프롬프트가 채널에 표시됩니다. 설정된 승인자만 버튼을 사용할 수 있으며, 다른 사용자는 일시적 거부를 받습니다. 승인 프롬프트에는 명령 텍스트가 포함되므로 신뢰할 수 있는 채널에서만 채널 전달을 활성화합니다. 세션 키에서 채널 ID를 유도할 수 없으면 OpenClaw는 DM 전달로 폴백합니다.

이 핸들러의 게이트웨이 인증은 다른 게이트웨이 클라이언트와 동일한 공유 자격 증명 해석 계약을 사용합니다:

- env 우선 로컬 인증 (`OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD` 그 다음 `gateway.auth.*`)
- 로컬 모드에서 `gateway.auth.*`가 미설정이면 `gateway.remote.*`를 폴백으로 사용 가능; 설정되었지만 해석되지 않은 로컬 SecretRef는 실패 폐쇄
- 적용 가능한 경우 `gateway.remote.*`를 통한 리모트 모드 지원
- URL 재정의는 재정의 안전: CLI 재정의는 암묵적 자격 증명을 재사용하지 않으며 env 재정의는 env 자격 증명만 사용

알 수 없는 승인 ID로 승인이 실패하면 승인자 목록과 기능 활성화를 확인합니다.

관련 문서: [Exec approvals](/docs/tools/exec-approvals)

도구 및 액션 게이트

Discord 메시지 액션에는 메시징, 채널 관리, 모더레이션, 프레즌스, 메타데이터 액션이 포함됩니다.

핵심 예시:

  • 메시징: sendMessage, readMessages, editMessage, deleteMessage, threadReply
  • 리액션: react, reactions, emojiList
  • 모더레이션: timeout, kick, ban
  • 프레즌스: setPresence

액션 게이트는 channels.discord.actions.* 아래에 있습니다.

기본 게이트 동작:

액션 그룹기본값
reactions, messages, threads, pins, polls, search, memberInfo, roleInfo, channelInfo, channels, voiceStatus, events, stickers, emojiUploads, stickerUploads, permissions활성화
roles비활성화
moderation비활성화
presence비활성화

컴포넌트 v2 UI

OpenClaw는 실행 승인 및 크로스 컨텍스트 마커에 Discord 컴포넌트 v2를 사용합니다. Discord 메시지 액션은 사용자 정의 UI를 위한 components도 허용할 수 있으며(고급; Carbon 컴포넌트 인스턴스 필요), 레거시 embeds는 사용 가능하지만 권장되지 않습니다.

  • channels.discord.ui.components.accentColor는 Discord 컴포넌트 컨테이너에 사용되는 강조 색상을 설정합니다 (hex).
  • 계정별로 channels.discord.accounts.<id>.ui.components.accentColor로 설정합니다.
  • 컴포넌트 v2가 있으면 embeds는 무시됩니다.

예시:

{
  channels: {
    discord: {
      ui: {
        components: {
          accentColor: "#5865F2",
        },
      },
    },
  },
}

음성 채널

OpenClaw는 실시간 연속 대화를 위해 Discord 음성 채널에 참가할 수 있습니다. 음성 메시지 첨부와는 별개입니다.

요구 사항:

  • 네이티브 명령 활성화 (commands.native 또는 channels.discord.commands.native).
  • channels.discord.voice 설정.
  • 봇에 대상 음성 채널의 Connect + Speak 권한 필요.

Discord 전용 네이티브 명령 /vc join|leave|status로 세션을 제어합니다. 이 명령은 계정 기본 에이전트를 사용하며 다른 Discord 명령과 동일한 허용 목록 및 그룹 정책 규칙을 따릅니다.

자동 참가 예시:

{
  channels: {
    discord: {
      voice: {
        enabled: true,
        autoJoin: [
          {
            guildId: "123456789012345678",
            channelId: "234567890123456789",
          },
        ],
        daveEncryption: true,
        decryptionFailureTolerance: 24,
        tts: {
          provider: "openai",
          openai: { voice: "alloy" },
        },
      },
    },
  },
}

참고:

  • voice.tts는 음성 재생에만 messages.tts를 재정의합니다.
  • 음성 전사 턴은 Discord allowFrom (또는 dm.allowFrom)에서 소유자 상태를 파생합니다; 비소유자 발화자는 소유자 전용 도구(예: gatewaycron)에 접근할 수 없습니다.
  • 음성은 기본적으로 활성화됩니다; channels.discord.voice.enabled=false로 비활성화합니다.
  • voice.daveEncryptionvoice.decryptionFailureTolerance@discordjs/voice join 옵션으로 전달됩니다.
  • @discordjs/voice 기본값은 미설정 시 daveEncryption=truedecryptionFailureTolerance=24입니다.
  • OpenClaw는 수신 복호화 실패도 모니터링하며 짧은 기간 내 반복 실패 후 음성 채널을 나갔다 다시 참가하여 자동 복구합니다.
  • 수신 로그에 DecryptionFailed(UnencryptedWhenPassthroughDisabled)가 반복적으로 표시되면 discord.js #11419에서 추적되는 upstream @discordjs/voice 수신 버그일 수 있습니다.

음성 메시지

Discord 음성 메시지는 파형 미리보기를 표시하며 OGG/Opus 오디오와 메타데이터가 필요합니다. OpenClaw는 파형을 자동으로 생성하지만, 오디오 파일을 검사하고 변환하려면 게이트웨이 호스트에 ffmpegffprobe가 필요합니다.

요구 사항 및 제약:

  • 로컬 파일 경로를 제공합니다 (URL은 거부됨).
  • 텍스트 콘텐츠를 생략합니다 (Discord는 동일 페이로드에 텍스트 + 음성 메시지를 허용하지 않음).
  • 모든 오디오 형식이 허용됩니다; OpenClaw는 필요 시 OGG/Opus로 변환합니다.

예시:

message(action="send", channel="discord", target="channel:123", path="/path/to/audio.mp3", asVoice=true)

문제 해결

허용되지 않는 인텐트 사용 또는 봇이 길드 메시지를 보지 못함
- Message Content Intent 활성화
- 사용자/멤버 해석에 의존하는 경우 Server Members Intent 활성화
- 인텐트 변경 후 게이트웨이 재시작
길드 메시지가 예상치 못하게 차단됨
- `groupPolicy` 확인
- `channels.discord.guilds`의 길드 허용 목록 확인
- 길드 `channels` 맵이 있으면 나열된 채널만 허용됨
- `requireMention` 동작 및 멘션 패턴 확인

유용한 명령:
openclaw doctor
openclaw channels status --probe
openclaw logs --follow
require mention false이지만 여전히 차단됨
일반적인 원인:

- 일치하는 길드/채널 허용 목록 없이 `groupPolicy="allowlist"`
- 잘못된 위치에 `requireMention` 설정 (`channels.discord.guilds` 또는 채널 항목 아래여야 함)
- 길드/채널 `users` 허용 목록에 의해 발신자 차단
장시간 핸들러 타임아웃 또는 중복 응답
일반적인 로그:

- `Listener DiscordMessageListener timed out after 30000ms for event MESSAGE_CREATE`
- `Slow listener detected ...`
- `discord inbound worker timed out after ...`

리스너 예산 조정:

- 단일 계정: `channels.discord.eventQueue.listenerTimeout`
- 멀티 계정: `channels.discord.accounts.<accountId>.eventQueue.listenerTimeout`

워커 실행 타임아웃 조정:

- 단일 계정: `channels.discord.inboundWorker.runTimeoutMs`
- 멀티 계정: `channels.discord.accounts.<accountId>.inboundWorker.runTimeoutMs`
- 기본: `1800000` (30분); `0`으로 비활성화

권장 기준선:
{
  channels: {
    discord: {
      accounts: {
        default: {
          eventQueue: {
            listenerTimeout: 120000,
          },
          inboundWorker: {
            runTimeoutMs: 1800000,
          },
        },
      },
    },
  },
}
느린 리스너 설정에는 `eventQueue.listenerTimeout`을, 큐에 넣은 에이전트 턴에 대한 별도 안전 밸브가 필요한 경우에만 `inboundWorker.runTimeoutMs`를 사용합니다.
권한 감사 불일치
`channels status --probe` 권한 검사는 숫자 채널 ID에서만 작동합니다.

슬러그 키를 사용하면 런타임 매칭은 여전히 작동할 수 있지만 프로빙으로 권한을 완전히 확인할 수 없습니다.
DM 및 페어링 문제
- DM 비활성화: `channels.discord.dm.enabled=false`
- DM 정책 비활성화: `channels.discord.dmPolicy="disabled"` (레거시: `channels.discord.dm.policy`)
- `pairing` 모드에서 페어링 승인 대기 중
봇 간 루프
기본적으로 봇이 작성한 메시지는 무시됩니다.

`channels.discord.allowBots=true`를 설정하면 루프 동작을 방지하기 위해 엄격한 멘션 및 허용 목록 규칙을 사용합니다.
봇 메시지 중 봇을 멘션하는 것만 수락하려면 `channels.discord.allowBots="mentions"`를 권장합니다.
DecryptionFailed(...)로 음성 STT 드롭
- OpenClaw를 최신 상태로 유지합니다 (`openclaw update`) - Discord 음성 수신 복구 로직이 포함됨
- `channels.discord.voice.daveEncryption=true` 확인 (기본값)
- `channels.discord.voice.decryptionFailureTolerance=24` (upstream 기본값)에서 시작하고 필요할 때만 조정
- 다음 로그를 확인합니다:
  - `discord voice: DAVE decrypt failures detected`
  - `discord voice: repeated decrypt failures; attempting rejoin`
- 자동 재참가 후에도 실패가 계속되면 로그를 수집하고 [discord.js #11419](https://github.com/discordjs/discord.js/issues/11419)와 비교합니다

설정 참조 포인터

기본 참조:

주요 Discord 필드:

  • 시작/인증: enabled, token, accounts.*, allowBots
  • 정책: groupPolicy, dm.*, guilds.*, guilds.*.channels.*
  • 명령: commands.native, commands.useAccessGroups, configWrites, slashCommand.*
  • 이벤트 큐: eventQueue.listenerTimeout (리스너 예산), eventQueue.maxQueueSize, eventQueue.maxConcurrency
  • 인바운드 워커: inboundWorker.runTimeoutMs
  • 응답/히스토리: replyToMode, historyLimit, dmHistoryLimit, dms.*.historyLimit
  • 전달: textChunkLimit, chunkMode, maxLinesPerMessage
  • 스트리밍: streaming (레거시 별칭: streamMode), draftChunk, blockStreaming, blockStreamingCoalesce
  • 미디어/재시도: mediaMaxMb, retry
    • mediaMaxMb는 아웃바운드 Discord 업로드를 제한합니다 (기본: 8MB)
  • 액션: actions.*
  • 프레즌스: activity, status, activityType, activityUrl
  • UI: ui.components.accentColor
  • 기능: threadBindings, 최상위 bindings[] (type: "acp"), pluralkit, execApprovals, intents, agentComponents, heartbeat, responsePrefix

안전 및 운영

  • 봇 토큰은 시크릿으로 취급합니다 (관리 환경에서는 DISCORD_BOT_TOKEN 권장).
  • 최소 권한 Discord 권한을 부여합니다.
  • 명령 배포/상태가 오래된 경우 게이트웨이를 재시작하고 openclaw channels status --probe로 재확인합니다.

관련 문서