Mainstream messaging
Discord
Готово для личных сообщений и каналов серверов через официальный Discord gateway.
Личные сообщения Discord по умолчанию используют режим сопряжения.
Нативное поведение команд и каталог команд.
Межканальная диагностика и процесс исправления.
Быстрая настройка
Вам нужно создать новое приложение с ботом, добавить бота на свой сервер и выполнить его сопряжение с OpenClaw. Рекомендуем добавить бота на собственный приватный сервер. Если у вас его еще нет, сначала создайте его (выберите Create My Own > For me and my friends).
Создайте приложение и бота Discord
Перейдите в Discord Developer Portal и нажмите New Application. Назовите его, например, "OpenClaw".
Нажмите Bot на боковой панели. Задайте для Username любое имя, которым вы называете своего агента OpenClaw.
Включите привилегированные intents
Оставаясь на странице Bot, прокрутите вниз до Privileged Gateway Intents и включите:
- Message Content Intent (обязательно)
- Server Members Intent (рекомендуется; требуется для списков разрешенных ролей и сопоставления имени с ID)
- Presence Intent (необязательно; требуется только для обновлений присутствия)
Скопируйте токен бота
Прокрутите страницу Bot обратно вверх и нажмите Reset Token.
Скопируйте токен и сохраните его где-нибудь. Это ваш Bot Token, и он скоро понадобится.
Сгенерируйте URL приглашения и добавьте бота на сервер
Нажмите OAuth2 на боковой панели. Вы сгенерируете URL приглашения с правильными разрешениями для добавления бота на сервер.
Прокрутите вниз до OAuth2 URL Generator и включите:
botapplications.commands
Ниже появится раздел Bot Permissions. Включите как минимум:
General Permissions
- Просмотр каналов Text Permissions
- Отправка сообщений
- Чтение истории сообщений
- Встраивание ссылок
- Прикрепление файлов
- Добавление реакций (необязательно)
Это базовый набор для обычных текстовых каналов. Если вы планируете публиковать сообщения в ветках Discord, включая рабочие процессы форумных или медиа-каналов, которые создают или продолжают ветку, также включите Send Messages in Threads. Скопируйте сгенерированный URL внизу, вставьте его в браузер, выберите свой сервер и нажмите Continue, чтобы подключить. Теперь вы должны увидеть своего бота на сервере Discord.
Включите режим разработчика и соберите свои ID
Вернувшись в приложение Discord, нужно включить режим разработчика, чтобы копировать внутренние ID.
-
Нажмите User Settings (значок шестеренки рядом с вашим аватаром) → прокрутите до Developer на боковой панели → включите Developer Mode
(Примечание: в мобильном приложении Discord режим разработчика находится в App Settings → Advanced)
-
Щелкните правой кнопкой мыши по значку сервера на боковой панели → Copy Server ID
-
Щелкните правой кнопкой мыши по собственному аватару → Copy User ID
Сохраните Server ID и User ID рядом с Bot Token — на следующем шаге вы отправите все три значения в OpenClaw.
Разрешите личные сообщения от участников сервера
Чтобы сопряжение работало, Discord должен разрешить вашему боту отправлять вам личные сообщения. Щелкните правой кнопкой мыши по значку сервера → Privacy Settings → включите Direct Messages.
Это позволяет участникам сервера (включая ботов) отправлять вам личные сообщения. Оставьте это включенным, если хотите использовать личные сообщения Discord с OpenClaw. Если вы планируете использовать только каналы сервера, можно отключить личные сообщения после сопряжения.
Безопасно задайте токен бота (не отправляйте его в чат)
Токен бота Discord — это секрет (как пароль). Задайте его на машине, где работает OpenClaw, перед тем как писать агенту.
export DISCORD_BOT_TOKEN="YOUR_BOT_TOKEN"cat > discord.patch.json5 <<'JSON5'{channels: {discord: { enabled: true, token: { source: "env", provider: "default", id: "DISCORD_BOT_TOKEN" },},},}JSON5openclaw config patch --file ./discord.patch.json5 --dry-runopenclaw config patch --file ./discord.patch.json5openclaw gatewayЕсли OpenClaw уже работает как фоновая служба, перезапустите его через приложение OpenClaw для Mac или остановив и снова запустив процесс openclaw gateway run.
Для установок управляемой службы выполните openclaw gateway install из shell, где присутствует DISCORD_BOT_TOKEN, или сохраните переменную в ~/.openclaw/.env, чтобы служба могла разрешить env SecretRef после перезапуска.
Если ваш хост заблокирован или ограничен по частоте стартовым поиском приложения в Discord, задайте ID приложения/клиента Discord из Developer Portal, чтобы запуск мог пропустить этот REST-вызов. Используйте channels.discord.applicationId для учетной записи по умолчанию или channels.discord.accounts.<accountId>.applicationId, когда запускаете несколько ботов Discord.
Настройте OpenClaw и выполните сопряжение
Спросите своего агента
Напишите своему агенту OpenClaw в любом существующем канале (например, Telegram) и сообщите ему это. Если Discord — ваш первый канал, используйте вместо этого вкладку CLI / конфигурации.
"Я уже указал токен бота Discord в конфигурации. Заверши настройку Discord с User ID
<user_id>и Server ID<server_id>."
CLI / конфигурация
Если вы предпочитаете файловую конфигурацию, задайте:
{channels: {discord: {enabled: true,token: {source: "env",provider: "default",id: "DISCORD_BOT_TOKEN",},},},}Резервное значение env для учетной записи по умолчанию:
DISCORD_BOT_TOKEN=...Для скриптовой или удаленной настройки запишите тот же блок JSON5 с помощью openclaw config patch --file ./discord.patch.json5 --dry-run, а затем повторно запустите без --dry-run. Значения token в виде открытого текста поддерживаются. Значения SecretRef также поддерживаются для channels.discord.token через провайдеры env/file/exec. См. Управление секретами.
Для нескольких ботов Discord храните токен каждого бота и ID приложения в его учетной записи. Верхнеуровневый channels.discord.applicationId наследуется учетными записями, поэтому задавайте его там только если каждая учетная запись должна использовать один и тот же ID приложения.
{channels: {discord: {enabled: true,accounts: {personal: { token: { source: "env", provider: "default", id: "DISCORD_PERSONAL_TOKEN" }, applicationId: "111111111111111111",},work: { token: { source: "env", provider: "default", id: "DISCORD_WORK_TOKEN" }, applicationId: "222222222222222222",},},},},}Одобрите первое сопряжение через личные сообщения
Дождитесь, пока gateway запустится, затем отправьте личное сообщение своему боту в Discord. Он ответит кодом сопряжения.
Спросите своего агента
Отправьте код сопряжения своему агенту в существующем канале:
"Одобри этот код сопряжения Discord:
<CODE>"
CLI
openclaw pairing list discordopenclaw pairing approve discord <CODE>Коды сопряжения истекают через 1 час.
Теперь вы должны иметь возможность общаться со своим агентом в Discord через личные сообщения.
Рекомендуется: настройте рабочую область сервера
Когда личные сообщения заработают, вы можете настроить свой сервер Discord как полноценную рабочую область, где каждый канал получает собственную сессию агента со своим контекстом. Это рекомендуется для приватных серверов, где есть только вы и ваш бот.
Добавьте свой сервер в allowlist серверов
Это позволяет вашему агенту отвечать в любом канале на вашем сервере, а не только в личных сообщениях.
Спросите своего агента
"Добавь мой Discord Server ID
<server_id>в allowlist серверов"
Конфигурация
{channels: {discord: {groupPolicy: "allowlist",guilds: {YOUR_SERVER_ID: { requireMention: true, users: ["YOUR_USER_ID"],},},},},}Разрешите ответы без @mention
По умолчанию ваш агент отвечает в каналах сервера только при @mention. Для приватного сервера, вероятно, вы захотите, чтобы он отвечал на каждое сообщение.
В каналах сервера обычные ответы по умолчанию публикуются автоматически. Для общих постоянно активных комнат включите messages.groupChat.visibleReplies: "message_tool", чтобы агент мог находиться в режиме наблюдения и публиковать сообщение только когда решит, что ответ в канале полезен. Это лучше всего работает с моделями последнего поколения с надежной работой инструментов, такими как GPT 5.5. Фоновые события комнаты остаются тихими, если инструмент не отправляет сообщение. Полную конфигурацию режима наблюдения см. в фоновых событиях комнаты.
Если Discord показывает ввод текста, а журналы показывают использование токенов, но опубликованного сообщения нет, проверьте, был ли ход настроен как фоновое событие комнаты или включал видимые ответы через инструмент сообщений.
Спросите своего агента
"Разреши моему агенту отвечать на этом сервере без необходимости @mention"
Конфигурация
Задайте requireMention: false в конфигурации сервера:
{channels: {discord: {guilds: {YOUR_SERVER_ID: { requireMention: false,},},},},}Чтобы требовать отправку через инструмент сообщений для видимых ответов в группе/канале, задайте messages.groupChat.visibleReplies: "message_tool".
Спланируйте память в каналах сервера
По умолчанию долгосрочная память (MEMORY.md) загружается только в сессиях личных сообщений. Каналы сервера не загружают MEMORY.md автоматически.
Спросите своего агента
"Когда я задаю вопросы в каналах Discord, используй memory_search или memory_get, если тебе нужен долгосрочный контекст из MEMORY.md."
Вручную
Если вам нужен общий контекст в каждом канале, поместите стабильные инструкции в AGENTS.md или USER.md (они внедряются в каждую сессию). Храните долгосрочные заметки в MEMORY.md и обращайтесь к ним по необходимости с помощью инструментов памяти.
Теперь создайте несколько каналов на своем сервере Discord и начните общаться. Ваш агент видит имя канала, и каждый канал получает собственную изолированную сессию — так что можно настроить #coding, #home, #research или любые другие каналы под ваш рабочий процесс.
Модель runtime
- Gateway управляет подключением Discord.
- Маршрутизация ответов детерминирована: входящие ответы Discord возвращаются в Discord.
- Метаданные гильдии/канала Discord добавляются в промпт модели как недоверенный контекст, а не как видимый пользователю префикс ответа. Если модель копирует этот конверт обратно, OpenClaw удаляет скопированные метаданные из исходящих ответов и из будущего контекста воспроизведения.
- По умолчанию (
session.dmScope=main) прямые чаты используют общий основной сеанс агента (agent:main:main). - Каналы гильдий изолированы отдельными ключами сеансов (
agent:<agentId>:discord:channel:<channelId>). - Групповые DM по умолчанию игнорируются (
channels.discord.dm.groupEnabled=false). - Нативные slash-команды выполняются в изолированных командных сеансах (
agent:<agentId>:discord:slash:<userId>), при этом по-прежнему передаваяCommandTargetSessionKeyв маршрутизированный сеанс беседы. - Доставка текстовых объявлений cron/heartbeat в Discord использует итоговый видимый ассистенту ответ один раз. Медиа и полезные нагрузки структурированных компонентов остаются многосообщенческими, когда агент отправляет несколько доставляемых полезных нагрузок.
Форумные каналы
Форумные и медиа-каналы 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 для этой кнопки (ID пользователей Discord, теги или *). При настройке пользователи без совпадения получают ephemeral-отказ.
Срок действия callback-компонентов по умолчанию истекает через 30 минут. Установите channels.discord.agentComponents.ttlMs, чтобы изменить срок жизни реестра callback для учетной записи Discord по умолчанию, или channels.discord.accounts.<accountId>.agentComponents.ttlMs, чтобы переопределить одну учетную запись в конфигурации с несколькими учетными записями. Значение указывается в миллисекундах, должно быть положительным целым числом и ограничено 86400000 (24 часа). Более длинные TTL полезны для рабочих процессов проверки или утверждения, где кнопки должны оставаться доступными, но они также расширяют окно, в течение которого старое сообщение Discord все еще может запустить действие. Предпочитайте самый короткий TTL, подходящий для рабочего процесса, и оставляйте значение по умолчанию, когда устаревшие callback были бы неожиданными.
Slash-команды /model и /models открывают интерактивный выбор модели с выпадающими списками провайдера, модели и совместимой среды выполнения, а также шагом Submit. /models add устарела и теперь возвращает сообщение об устаревании вместо регистрации моделей из чата. Ответ выбора является ephemeral, и использовать его может только пользователь, который его вызвал. Меню выбора Discord ограничены 25 вариантами, поэтому добавляйте записи provider/* в agents.defaults.models, когда хотите, чтобы выбор показывал динамически обнаруженные модели только для выбранных провайдеров, таких как openai или vllm.
Вложения файлов:
- Блоки
fileдолжны указывать на ссылку вложения (attachment://<filename>) - Передайте вложение через
media/path/filePath(один файл); используйтеmedia-galleryдля нескольких файлов - Используйте
filename, чтобы переопределить имя загрузки, когда оно должно совпадать со ссылкой вложения
Модальные формы:
- Добавьте
components.modalс максимум 5 полями - Типы полей:
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 policy
channels.discord.dmPolicy управляет доступом DM. channels.discord.allowFrom является каноническим списком разрешений для DM.
pairing(по умолчанию)allowlistopen(требует, чтобыchannels.discord.allowFromвключал"*")disabled
Если политика DM не открыта, неизвестные пользователи блокируются (или получают запрос на pairing в режиме pairing).
Приоритет для нескольких учетных записей:
channels.discord.accounts.default.allowFromприменяется только к учетной записиdefault.- Для одной учетной записи
allowFromимеет приоритет над устаревшимdm.allowFrom. - Именованные учетные записи наследуют
channels.discord.allowFrom, когда их собственныеallowFromи устаревшийdm.allowFromне заданы. - Именованные учетные записи не наследуют
channels.discord.accounts.default.allowFrom.
Устаревшие channels.discord.dm.policy и channels.discord.dm.allowFrom по-прежнему читаются для совместимости. openclaw doctor --fix переносит их в dmPolicy и allowFrom, когда это можно сделать без изменения доступа.
Формат цели DM для доставки:
user:<id>- упоминание
<@id>
Голые числовые ID обычно разрешаются как ID каналов, когда активен канал по умолчанию, но ID, перечисленные в эффективном DM allowFrom учетной записи, рассматриваются как цели пользовательских DM для совместимости.
Access groups
DM Discord и авторизация текстовых команд могут использовать динамические записи accessGroup:<name> в channels.discord.allowFrom.
Имена групп доступа являются общими для каналов сообщений. Используйте type: "message.senders" для статической группы, участники которой выражены в обычном синтаксисе allowFrom каждого канала, или type: "discord.channelAudience", когда текущая аудитория ViewChannel канала Discord должна динамически определять членство. Общее поведение групп доступа описано здесь: Группы доступа.
{accessGroups: {operators: { type: "message.senders", members: { "*": ["global-owner-id"], discord: ["discord:123456789012345678"], telegram: ["987654321"], },},},channels: {discord: { dmPolicy: "allowlist", allowFrom: ["accessGroup:operators"],},},}У текстового канала Discord нет отдельного списка участников. type: "discord.channelAudience" моделирует членство так: отправитель DM является участником настроенной гильдии и в текущий момент имеет эффективное разрешение ViewChannel на настроенный канал после применения ролей и переопределений канала.
Пример: разрешить всем, кто видит #maintainers, отправлять DM боту, сохраняя DM закрытыми для всех остальных.
{accessGroups: {maintainers: { type: "discord.channelAudience", guildId: "1456350064065904867", channelId: "1456744319972282449", membership: "canViewChannel",},},channels: {discord: { dmPolicy: "allowlist", allowFrom: ["accessGroup:maintainers"],},},}Можно смешивать динамические и статические записи:
{accessGroups: {maintainers: { type: "discord.channelAudience", guildId: "1456350064065904867", channelId: "1456744319972282449",},},channels: {discord: { dmPolicy: "allowlist", allowFrom: ["accessGroup:maintainers", "discord:123456789012345678"],},},}Поиски завершаются закрыто при ошибке. Если Discord возвращает Missing Access, поиск участника завершается неудачно или канал принадлежит другой гильдии, отправитель DM считается неавторизованным.
Включите Server Members Intent для бота в Discord Developer Portal при использовании групп доступа на основе аудитории канала. DM не содержат состояние участника гильдии, поэтому OpenClaw разрешает участника через Discord REST во время авторизации.
Guild policy
Обработка гильдий управляется channels.discord.groupPolicy:
openallowlistdisabled
Безопасная базовая конфигурация при наличии channels.discord — allowlist.
Поведение allowlist:
- гильдия должна соответствовать
channels.discord.guilds(idпредпочтителен, slug принимается) - необязательные списки разрешенных отправителей:
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, резервное поведение среды выполнения — groupPolicy="allowlist" (с предупреждением в логах), даже если channels.defaults.groupPolicy равно open.
Mentions and group DMs
Сообщения гильдий по умолчанию требуют упоминания.
Обнаружение упоминаний включает:
- явное упоминание бота
- настроенные шаблоны упоминаний (
agents.list[].groupChat.mentionPatterns, резервное значениеmessages.groupChat.mentionPatterns) - неявное поведение ответа боту в поддерживаемых случаях
При написании исходящих сообщений Discord используйте канонический синтаксис упоминаний: <@USER_ID> для пользователей, <#CHANNEL_ID> для каналов и <@&ROLE_ID> для ролей. Не используйте устаревшую форму упоминания никнейма <@!USER_ID>.
requireMention настраивается для каждой гильдии/канала (channels.discord.guilds...).
ignoreOtherMentions опционально отбрасывает сообщения, которые упоминают другого пользователя/роль, но не бота (исключая @everyone/@here).
Групповые DM:
- по умолчанию: игнорируются (
dm.groupEnabled=false) - необязательный список разрешений через
dm.groupChannels(ID каналов или slug)
Маршрутизация агентов на основе ролей
Используйте bindings[].match.roles, чтобы направлять участников гильдии Discord к разным агентам по ID роли. Привязки на основе ролей принимают только ID ролей и оцениваются после привязок peer или parent-peer и перед привязками только к гильдии. Если привязка также задает другие поля сопоставления (например, peer + guildId + roles), должны совпасть все настроенные поля.
{ bindings: [ { agentId: "opus", match: { channel: "discord", guildId: "123456789012345678", roles: ["111111111111111111"], }, }, { agentId: "sonnet", match: { channel: "discord", guildId: "123456789012345678", }, }, ],}Нативные команды и авторизация команд
commands.nativeпо умолчанию имеет значение"auto"и включен для Discord.- Переопределение для отдельного канала:
channels.discord.commands.native. commands.native=falseпропускает регистрацию и очистку слэш-команд Discord при запуске. Ранее зарегистрированные команды могут оставаться видимыми в Discord, пока вы не удалите их из приложения Discord.- Авторизация нативных команд использует те же списки разрешений/политики Discord, что и обычная обработка сообщений.
- Команды могут по-прежнему быть видимыми в UI Discord для неавторизованных пользователей; выполнение все равно применяет авторизацию OpenClaw и возвращает "не авторизован".
См. Слэш-команды, чтобы узнать о каталоге команд и поведении.
Настройки слэш-команд по умолчанию:
ephemeral: true
Сведения о функциях
Теги ответов и нативные ответы
Discord поддерживает теги ответов в выводе агента:
[[reply_to_current]][[reply_to:<id>]]
Управляется через channels.discord.replyToMode:
off(по умолчанию)firstallbatched
Примечание: off отключает неявную привязку ответов к цепочкам. Явные теги [[reply_to_*]] по-прежнему учитываются.
first всегда прикрепляет неявную нативную ссылку ответа к первому исходящему сообщению Discord за ход.
batched прикрепляет неявную нативную ссылку ответа Discord только тогда, когда
входящее событие было отложенной пакетной обработкой нескольких сообщений. Это полезно,
когда нативные ответы нужны в основном для неоднозначных всплесков чата, а не для каждого
хода из одного сообщения.
ID сообщений выводятся в контексте/истории, чтобы агенты могли обращаться к конкретным сообщениям.
Предпросмотры ссылок
Discord по умолчанию создает насыщенные встраивания ссылок для URL. OpenClaw по умолчанию подавляет эти сгенерированные встраивания в исходящих сообщениях Discord, поэтому отправленные агентом URL остаются обычными ссылками, если вы не включите другое поведение:
{channels: {discord: { suppressEmbeds: false,},},}Задайте channels.discord.accounts.<id>.suppressEmbeds, чтобы переопределить один аккаунт. Отправки через инструмент сообщений агента также могут передать suppressEmbeds: false для одного сообщения. Явные полезные нагрузки Discord embeds не подавляются настройкой предпросмотра ссылок по умолчанию.
Предпросмотр прямой трансляции
OpenClaw может транслировать черновики ответов, отправляя временное сообщение и редактируя его по мере поступления текста. channels.discord.streaming принимает off | partial | block | progress (по умолчанию). progress сохраняет один редактируемый черновик статуса и обновляет его прогрессом инструментов до финальной доставки; общая начальная метка является бегущей строкой, поэтому она прокручивается вверх вместе с остальным, когда появляется достаточно работы. streamMode — устаревший псевдоним среды выполнения. Запустите openclaw doctor --fix, чтобы переписать сохраненную конфигурацию на канонический ключ.
Задайте channels.discord.streaming.mode в off, чтобы отключить правки предпросмотра Discord. Если потоковая передача блоками Discord явно включена, OpenClaw пропускает поток предпросмотра, чтобы избежать двойной потоковой передачи.
{channels: {discord: { streaming: { mode: "progress", progress: { label: "auto", maxLines: 8, maxLineChars: 120, toolProgress: true, commentary: false, }, },},},}partialредактирует одно сообщение предпросмотра по мере поступления токенов.blockотправляет фрагменты размером с черновик (используйтеdraftChunk, чтобы настроить размер и точки разрыва, с ограничением доtextChunkLimit).- Медиа, ошибки и финальные сообщения с явным ответом отменяют ожидающие правки предпросмотра.
streaming.preview.toolProgress(по умолчаниюtrue) управляет тем, переиспользуют ли обновления инструмента/прогресса сообщение предпросмотра.- Строки инструмента/прогресса отображаются как компактные эмодзи + заголовок + детали, когда доступны, например
🛠️ Bash: run testsили🔎 Web Search: for "query". streaming.progress.commentary(по умолчаниюfalse) включает текст комментария/преамбулы ассистента во временном черновике прогресса. Комментарий очищается перед показом, остается временным и не меняет доставку финального ответа.streaming.progress.maxLineCharsуправляет лимитом предпросмотра прогресса на строку. Проза сокращается по границам слов; сведения о командах и путях сохраняют полезные суффиксы.streaming.preview.commandText/streaming.progress.commandTextуправляет деталями команд/exec в компактных строках прогресса:raw(по умолчанию) илиstatus(только метка инструмента).
Скрыть необработанный текст команд/exec, сохранив компактные строки прогресса:
{ "channels": { "discord": { "streaming": { "mode": "progress", "progress": { "toolProgress": true, "commandText": "status" } } } }}Потоковая передача предпросмотра поддерживает только текст; медиаответы возвращаются к обычной доставке. Когда потоковая передача block явно включена, OpenClaw пропускает поток предпросмотра, чтобы избежать двойной потоковой передачи.
История, контекст и поведение веток
Контекст истории гильдии:
channels.discord.historyLimitпо умолчанию20- резервный вариант:
messages.groupChat.historyLimit 0отключает
Управление историей DM:
channels.discord.dmHistoryLimitchannels.discord.dms["<user_id>"].historyLimit
Поведение веток:
- Ветки Discord маршрутизируются как сессии канала и наследуют конфигурацию родительского канала, если она не переопределена.
- Сессии веток наследуют выбранную на уровне сессии родительского канала настройку
/modelкак резервный вариант только для модели; локальные для ветки выборы/modelпо-прежнему имеют приоритет, а история родительской расшифровки не копируется, если наследование расшифровки не включено. channels.discord.thread.inheritParent(по умолчаниюfalse) включает для новых автоматических веток начальное заполнение из родительской расшифровки. Переопределения для отдельных аккаунтов находятся вchannels.discord.accounts.<id>.thread.inheritParent.- Реакции инструмента сообщений могут разрешать DM-цели
user:<id>. guilds.<guild>.channels.<channel>.requireMention: falseсохраняется при резервной активации на этапе ответа.
Темы каналов внедряются как недоверенный контекст. Списки разрешений ограничивают, кто может запустить агента, но не являются полноценной границей редактирования дополнительного контекста.
Сессии подагентов, привязанные к ветке
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, spawnSessions: true, defaultSpawnContext: "fork", },},},}Примечания:
session.threadBindings.*задает глобальные значения по умолчанию.channels.discord.threadBindings.*переопределяет поведение Discord.spawnSessionsуправляет автоматическим созданием/привязкой веток дляsessions_spawn({ thread: true })и порождений веток ACP. По умолчанию:true.defaultSpawnContextуправляет нативным контекстом подагента для порождений, привязанных к ветке. По умолчанию:"fork".- Устаревшие ключи
spawnSubagentSessions/spawnAcpSessionsмигрируются черезopenclaw doctor --fix. - Если привязки веток отключены для аккаунта,
/focusи связанные операции привязки веток недоступны.
Постоянные привязки каналов ACP
Для стабильных рабочих пространств ACP, работающих "всегда включено", настройте типизированные привязки ACP верхнего уровня, нацеленные на разговоры Discord.
Путь конфигурации:
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 spawn codex --bind hereпривязывает текущий канал или ветку на месте и сохраняет будущие сообщения в той же сессии ACP. Сообщения ветки наследуют привязку родительского канала.- В привязанном канале или ветке
/newи/resetсбрасывают ту же сессию ACP на месте. Временные привязки веток могут переопределять разрешение цели, пока активны. spawnSessionsограничивает создание/привязку дочерних веток через--thread auto|here.
См. Агенты ACP, чтобы узнать подробности о поведении привязок.
Уведомления о реакциях
Режим уведомлений о реакциях для отдельной гильдии:
offown(по умолчанию)allallowlist(используетguilds.<id>.users)
События реакций превращаются в системные события и прикрепляются к маршрутизированной сессии Discord.
Реакции подтверждения
ackReaction отправляет эмодзи подтверждения, пока OpenClaw обрабатывает входящее сообщение.
Порядок разрешения:
channels.discord.accounts.<accountId>.ackReactionchannels.discord.ackReactionmessages.ackReaction- резервный эмодзи идентичности агента (
agents.list[].identity.emoji, иначе "👀")
Примечания:
- Discord принимает Unicode-эмодзи или имена пользовательских эмодзи.
- Используйте
"", чтобы отключить реакцию для канала или аккаунта.
Записи конфигурации
Записи конфигурации, инициированные каналом, включены по умолчанию.
Это влияет на потоки /config set|unset (когда функции команд включены).
Отключение:
{channels: {discord: { configWrites: false,},},}Прокси Gateway
Направляйте WebSocket-трафик Gateway Discord и стартовые REST-запросы (ID приложения + разрешение списка разрешений) через HTTP(S)-прокси с channels.discord.proxy.
{channels: {discord: { proxy: "http://proxy.example:8080",},},}Переопределение для отдельного аккаунта:
{channels: {discord: { accounts: { primary: { proxy: "http://proxy.example:8080", }, },},},}Поддержка PluralKit
Включите разрешение PluralKit, чтобы сопоставлять проксированные сообщения с идентичностью участника системы:
{channels: {discord: { pluralkit: { enabled: true, token: "pk_live_...", // optional; needed for private systems },},},}Примечания:
- списки разрешенных могут использовать
pk:<memberId> - отображаемые имена участников сопоставляются по имени/slug только когда
channels.discord.dangerouslyAllowNameMatching: true - поиск использует исходный ID сообщения и ограничен временным окном
- если поиск не удается, проксированные сообщения считаются сообщениями бота и отбрасываются, если только
allowBots=true
Псевдонимы исходящих упоминаний
Используйте mentionAliases, когда агентам нужны детерминированные исходящие упоминания для известных пользователей Discord. Ключи — это handles без начального @; значения — ID пользователей Discord. Неизвестные handles, @everyone, @here и упоминания внутри Markdown code spans остаются без изменений.
{channels: {discord: { mentionAliases: { Vladislava: "123456789012345678", }, accounts: { ops: { mentionAliases: { OpsLead: "234567890123456789", }, }, },},},}Настройка присутствия
Обновления присутствия применяются, когда вы задаете поле статуса или активности либо включаете автоматическое присутствие.
Пример только со статусом:
{channels: {discord: { status: "idle",},},}Пример активности (пользовательский статус — тип активности по умолчанию):
{channels: {discord: { activity: "Focus time", activityType: 4,},},}Пример стриминга:
{channels: {discord: { activity: "Live coding", activityType: 1, activityUrl: "https://twitch.tv/openclaw",},},}Карта типов активности:
- 0: Игра
- 1: Стриминг (требует
activityUrl) - 2: Прослушивание
- 3: Просмотр
- 4: Пользовательский (использует текст активности как состояние статуса; emoji необязателен)
- 5: Соревнование
Пример автоматического присутствия (сигнал состояния runtime):
{channels: {discord: { autoPresence: { enabled: true, intervalMs: 30000, minUpdateIntervalMs: 15000, exhaustedText: "token exhausted", },},},}Автоматическое присутствие сопоставляет доступность runtime со статусом Discord: исправен => онлайн, деградировал или неизвестен => неактивен, исчерпан или недоступен => dnd. Необязательные переопределения текста:
autoPresence.healthyTextautoPresence.degradedTextautoPresence.exhaustedText(поддерживает placeholder{reason})
Подтверждения в Discord
Discord поддерживает обработку подтверждений на основе кнопок в личных сообщениях и может дополнительно публиковать запросы подтверждения в исходном канале.
Путь конфигурации:
channels.discord.execApprovals.enabledchannels.discord.execApprovals.approvers(необязательно; по возможности использует fallback наcommands.ownerAllowFrom)channels.discord.execApprovals.target(dm|channel|both, по умолчанию:dm)agentFilter,sessionFilter,cleanupAfterResolve
Discord автоматически включает нативные подтверждения exec, когда enabled не задано или равно "auto" и можно разрешить хотя бы одного подтверждающего — из execApprovals.approvers или из commands.ownerAllowFrom. Discord не выводит подтверждающих exec из allowFrom канала, legacy dm.allowFrom или defaultTo для личных сообщений. Задайте enabled: false, чтобы явно отключить Discord как нативный клиент подтверждений.
Для чувствительных групповых команд только для владельца, таких как /diagnostics и /export-trajectory, OpenClaw отправляет запросы подтверждения и итоговые результаты приватно. Сначала он пробует Discord DM, когда у вызывающего владельца есть маршрут владельца Discord; если он недоступен, он использует fallback на первый доступный маршрут владельца из commands.ownerAllowFrom, например Telegram.
Когда target равен channel или both, запрос подтверждения виден в канале. Кнопки могут использовать только разрешенные подтверждающие; другие пользователи получают эфемерный отказ. Запросы подтверждения включают текст команды, поэтому включайте доставку в канал только в доверенных каналах. Если ID канала нельзя получить из ключа сессии, OpenClaw использует fallback на доставку в DM.
Discord также отображает общие кнопки подтверждения, используемые другими чат-каналами. Нативный адаптер Discord в основном добавляет маршрутизацию DM для подтверждающих и веерную рассылку в каналы.
Когда эти кнопки присутствуют, они являются основным UX подтверждения; OpenClaw
должен включать ручную команду /approve только когда результат инструмента сообщает,
что чат-подтверждения недоступны или ручное подтверждение — единственный путь.
Если нативный runtime подтверждений Discord не активен, OpenClaw сохраняет
видимый локальный детерминированный prompt /approve <id> <decision>. Если
runtime активен, но нативную карточку нельзя доставить ни одной цели,
OpenClaw отправляет уведомление fallback в тот же чат с точной командой /approve
из ожидающего подтверждения.
Аутентификация Gateway и разрешение подтверждений следуют общему контракту клиента Gateway (plugin: IDs разрешаются через plugin.approval.resolve; другие IDs — через exec.approval.resolve). По умолчанию срок действия подтверждений истекает через 30 минут.
См. Подтверждения exec.
Инструменты и action gates
Действия сообщений Discord включают отправку сообщений, администрирование каналов, модерацию, присутствие и действия с метаданными.
Основные примеры:
- сообщения:
sendMessage,readMessages,editMessage,deleteMessage,threadReply - реакции:
react,reactions,emojiList - модерация:
timeout,kick,ban - присутствие:
setPresence
Действие event-create принимает необязательный параметр image (URL или путь к локальному файлу), чтобы задать изображение обложки запланированного события.
Action gates находятся в channels.discord.actions.*.
Поведение gate по умолчанию:
| Группа действий | По умолчанию |
|---|---|
| reactions, messages, threads, pins, polls, search, memberInfo, roleInfo, channelInfo, channels, voiceStatus, events, stickers, emojiUploads, stickerUploads, permissions | включено |
| roles | отключено |
| moderation | отключено |
| presence | отключено |
UI Components v2
OpenClaw использует Discord components v2 для подтверждений exec и маркеров cross-context. Действия сообщений Discord также могут принимать components для пользовательского UI (расширенный сценарий; требует создания payload компонента через инструмент discord), при этом legacy embeds остаются доступными, но не рекомендуются.
channels.discord.ui.components.accentColorзадает цвет акцента, используемый контейнерами компонентов Discord (hex).- Задайте для отдельной учетной записи через
channels.discord.accounts.<id>.ui.components.accentColor. channels.discord.agentComponents.ttlMsуправляет тем, как долго callbacks отправленных компонентов Discord остаются зарегистрированными (по умолчанию1800000, максимум86400000). Задайте для отдельной учетной записи черезchannels.discord.accounts.<id>.agentComponents.ttlMs.embedsигнорируются, когда присутствуют components v2.- Простые предпросмотры URL по умолчанию подавляются. Задайте
suppressEmbeds: falseв действии сообщения, когда одна исходящая ссылка должна разворачиваться.
Пример:
{ channels: { discord: { ui: { components: { accentColor: "#5865F2", }, }, }, },}Голос
У Discord есть две разные голосовые поверхности: realtime голосовые каналы (непрерывные разговоры) и вложения голосовых сообщений (формат предпросмотра с waveform). Gateway поддерживает оба варианта.
Голосовые каналы
Контрольный список настройки:
- Включите Message Content Intent в Discord Developer Portal.
- Включите Server Members Intent, когда используются списки разрешенных ролей/пользователей.
- Пригласите бота со scopes
botиapplications.commands. - Предоставьте Connect, Speak, Send Messages и Read Message History в целевом голосовом канале.
- Включите нативные команды (
commands.nativeилиchannels.discord.commands.native). - Настройте
channels.discord.voice.
Используйте /vc join|leave|status для управления сессиями. Команда использует агента учетной записи по умолчанию и следует тем же правилам списков разрешенных и групповой политики, что и другие команды Discord.
/vc join channel:<voice-channel-id>/vc status/vc leaveЧтобы проверить эффективные разрешения бота перед подключением, выполните:
openclaw channels capabilities --channel discord --target channel:<voice-channel-id>Пример автоматического подключения:
{ channels: { discord: { voice: { enabled: true, model: "openai/gpt-5.5", autoJoin: [ { guildId: "123456789012345678", channelId: "234567890123456789", }, ], allowedChannels: [ { guildId: "123456789012345678", channelId: "234567890123456789", }, ], daveEncryption: true, decryptionFailureTolerance: 24, connectTimeoutMs: 30000, reconnectGraceMs: 15000, realtime: { provider: "openai", model: "gpt-realtime-2", speakerVoice: "cedar", }, }, }, },}Примечания:
voice.ttsпереопределяетmessages.ttsтолько для голосового воспроизведенияstt-tts. Режимы реального времени используютvoice.realtime.speakerVoice.voice.modeуправляет путем разговора. По умолчанию используетсяagent-proxy: голосовой фронтенд реального времени обрабатывает тайминг реплик, прерывание и воспроизведение, делегирует содержательную работу маршрутизированному агенту OpenClaw черезopenclaw_agent_consultи обрабатывает результат как текстовый запрос Discord от этого говорящего.stt-ttsсохраняет прежний пакетный поток STT плюс TTS.bidiпозволяет модели реального времени вести разговор напрямую, предоставляяopenclaw_agent_consultдля мозга OpenClaw.voice.agentSessionуправляет тем, какой разговор OpenClaw получает голосовые реплики. Не задавайте его, чтобы использовать собственную сессию голосового канала, или задайте{ mode: "target", target: "channel:<text-channel-id>" }, чтобы голосовой канал работал как расширение микрофона/динамика существующей сессии текстового канала Discord, например#maintainers.voice.modelпереопределяет мозг агента OpenClaw для голосовых ответов Discord и консультаций реального времени. Не задавайте его, чтобы наследовать модель маршрутизированного агента. Он отделен отvoice.realtime.model.voice.followUsersпозволяет боту подключаться, перемещаться и выходить из голосовых каналов Discord вместе с выбранными пользователями. См. Следование за пользователями в голосе для правил поведения и примеров.agent-proxyмаршрутизирует речь черезdiscord-voice, что сохраняет обычную авторизацию владельца/инструментов для говорящего и целевой сессии, но скрывает инструмент агентаtts, потому что голос Discord сам отвечает за воспроизведение. По умолчаниюagent-proxyпредоставляет консультации полный доступ к инструментам, эквивалентный владельцу, для говорящих владельцев (voice.realtime.toolPolicy: "owner") и настоятельно предпочитает консультироваться с агентом OpenClaw перед содержательными ответами (voice.realtime.consultPolicy: "always"). В этом режимеalwaysпо умолчанию слой реального времени не произносит автоматически заполняющие фразы до ответа консультации; он захватывает и транскрибирует речь, затем произносит маршрутизированный ответ OpenClaw. Если несколько принудительных ответов консультации завершаются, пока Discord еще воспроизводит первый ответ, последующие ответы с точной речью ставятся в очередь до простоя воспроизведения вместо замены речи в середине предложения.- В режиме
stt-ttsSTT используетtools.media.audio;voice.modelне влияет на транскрипцию. - В режимах реального времени
voice.realtime.provider,voice.realtime.modelиvoice.realtime.speakerVoiceнастраивают аудиосессию реального времени. Для OpenAI Realtime 2 плюс мозг Codex используйтеvoice.realtime.model: "gpt-realtime-2"иvoice.model: "openai/gpt-5.5". - Голосовые режимы реального времени по умолчанию включают небольшие файлы профиля
IDENTITY.md,USER.mdиSOUL.mdв инструкции провайдера реального времени, чтобы быстрые прямые реплики сохраняли ту же идентичность, привязку к пользователю и персону, что и маршрутизированный агент OpenClaw. Задайтеvoice.realtime.bootstrapContextFilesкак подмножество, чтобы настроить это, или[], чтобы отключить. Поддерживаемые файлы начальной загрузки реального времени ограничены этими файлами профиля;AGENTS.mdостается в обычном контексте агента. Внедренный контекст профиля не заменяетopenclaw_agent_consultдля работы с рабочей областью, текущих фактов, поиска в памяти или действий на основе инструментов. - В режиме реального времени OpenAI
agent-proxyзадайтеvoice.realtime.requireWakeName: true, чтобы голос Discord в реальном времени молчал, пока транскрипт не начнется или не закончится словом пробуждения. Настроенные имена пробуждения должны состоять из одного или двух слов. Еслиvoice.realtime.wakeNamesне задан, OpenClaw используетnameмаршрутизированного агента плюсOpenClaw, с откатом к идентификатору агента плюсOpenClaw. Фильтрация по имени пробуждения отключает автоответ провайдера реального времени, маршрутизирует принятые реплики через путь консультации агента OpenClaw и дает короткое устное подтверждение, когда начальное имя пробуждения распознано из частичной транскрипции до получения финального транскрипта. - Провайдер реального времени OpenAI принимает текущие имена событий Realtime 2 и устаревшие совместимые с Codex псевдонимы для событий выходного аудио и транскрипта, поэтому совместимые снимки провайдера могут расходиться без потери аудио ассистента.
voice.realtime.bargeInуправляет тем, прерывают ли события начала речи в Discord активное воспроизведение реального времени. Если не задано, следует настройке прерывания входного аудио провайдера реального времени.voice.realtime.minBargeInAudioEndMsуправляет минимальной длительностью воспроизведения ассистента перед тем, как перебивание OpenAI в реальном времени обрежет аудио. По умолчанию:250. Задайте0для немедленного прерывания в комнатах с низким эхом или увеличьте значение для настроек с динамиками и сильным эхом.- Для голоса OpenAI при воспроизведении в Discord задайте
voice.tts.provider: "openai"и выберите голос Text-to-speech вvoice.tts.providers.openai.speakerVoice.cedar— хороший вариант с мужским звучанием на текущей модели TTS OpenAI. - Переопределения
systemPromptDiscord для отдельных каналов применяются к голосовым транскрибированным репликам этого голосового канала. - Голосовые транскрибированные реплики выводят статус владельца из Discord
allowFrom(илиdm.allowFrom) для команд с доступом только владельцу и действий канала. Видимость инструментов агента следует настроенной политике инструментов для маршрутизированной сессии. - Голос Discord включается явно для конфигураций только с текстом; задайте
channels.discord.voice.enabled=true(или сохраните существующий блокchannels.discord.voice), чтобы включить команды/vc, голосовую среду выполнения и намерение GatewayGuildVoiceStates. channels.discord.intents.voiceStatesможет явно переопределить подписку на намерение голосового состояния. Не задавайте его, чтобы намерение следовало эффективному включению голоса.- Если
voice.autoJoinсодержит несколько записей для одной гильдии, OpenClaw подключается к последнему настроенному каналу для этой гильдии. voice.allowedChannels— необязательный список разрешенных мест пребывания. Не задавайте его, чтобы разрешить/vc joinв любой авторизованный голосовой канал Discord. Если задан,/vc join, автоподключение при запуске и перемещения голосового состояния бота ограничены перечисленными записями{ guildId, channelId }. Задайте пустой массив, чтобы запретить все голосовые подключения Discord. Если Discord перемещает бота за пределы списка разрешений, OpenClaw выходит из этого канала и повторно подключается к настроенной цели автоподключения, когда она доступна.voice.daveEncryptionиvoice.decryptionFailureToleranceпередаются в параметры подключения@discordjs/voice.- Значения по умолчанию
@discordjs/voice:daveEncryption=trueиdecryptionFailureTolerance=24, если они не заданы. - OpenClaw использует встроенный кодек
libopus-wasmдля приема голоса Discord и воспроизведения необработанного PCM в реальном времени. Он поставляется с закрепленной сборкой libopus WebAssembly и не требует нативных дополнений opus. voice.connectTimeoutMsуправляет начальным ожиданием Ready@discordjs/voiceдля/vc joinи попыток автоподключения. По умолчанию:30000.voice.reconnectGraceMsуправляет тем, как долго OpenClaw ждет, пока отключенная голосовая сессия начнет переподключаться, прежде чем уничтожить ее. По умолчанию:15000.- В режиме
stt-ttsголосовое воспроизведение не останавливается только потому, что другой пользователь начинает говорить. Чтобы избежать петель обратной связи, OpenClaw игнорирует новый голосовой захват, пока воспроизводится TTS; говорите после завершения воспроизведения для следующей реплики. Режимы реального времени передают начало речи как сигналы перебивания провайдеру реального времени. - В режимах реального времени эхо из динамиков в открытый микрофон может выглядеть как перебивание и прерывать воспроизведение. Для комнат Discord с сильным эхом задайте
voice.realtime.providers.openai.interruptResponseOnInputAudio: false, чтобы OpenAI не прерывал ответ автоматически при входном аудио. Добавьтеvoice.realtime.bargeIn: true, если все еще хотите, чтобы события начала речи Discord прерывали активное воспроизведение. Мост реального времени OpenAI игнорирует усечения воспроизведения корочеvoice.realtime.minBargeInAudioEndMsкак вероятное эхо/шум и логирует их как пропущенные вместо очистки воспроизведения Discord. voice.captureSilenceGraceMsуправляет тем, как долго OpenClaw ждет после сообщения Discord об остановке говорящего, прежде чем завершить этот аудиосегмент для STT. По умолчанию:2000; увеличьте это значение, если Discord разбивает обычные паузы на рваные частичные транскрипты.- Когда выбранным провайдером TTS является ElevenLabs, голосовое воспроизведение Discord использует потоковый TTS и начинается из потока ответа провайдера. Провайдеры без поддержки потоковой передачи откатываются к пути с синтезированным временным файлом.
- OpenClaw также отслеживает сбои расшифровки приема и автоматически восстанавливается, выходя из голосового канала и повторно подключаясь к нему после повторяющихся сбоев за короткое окно.
- Если после обновления в журналах приема повторно появляется
DecryptionFailed(UnencryptedWhenPassthroughDisabled), соберите отчет о зависимостях и журналы. Встроенная линия@discordjs/voiceвключает исправление заполнения из вышестоящего PR discord.js #11449, который закрыл issue discord.js #11419. - События приема
The operation was abortedожидаемы, когда OpenClaw завершает захваченный сегмент говорящего; это подробная диагностика, а не предупреждения. - Подробные журналы голоса Discord включают ограниченный однострочный предпросмотр STT-транскрипта для каждого принятого сегмента говорящего, поэтому отладка показывает и сторону пользователя, и сторону ответа агента без вывода неограниченного текста транскрипта.
- В режиме
agent-proxyпринудительный откат консультации пропускает вероятно неполные фрагменты транскрипта, например текст, заканчивающийся на...или завершающий соединитель вродеand, а также очевидные не требующие действия завершения вроде “be right back” или “bye”. Журналы показываютforced agent consult skipped reason=..., когда это предотвращает устаревший ответ из очереди.
Следование за пользователями в голосе
Используйте voice.followUsers, когда хотите, чтобы голосовой бот Discord оставался с одним или несколькими известными пользователями Discord вместо подключения к фиксированному каналу при запуске или ожидания /vc join.
{ channels: { discord: { voice: { enabled: true, followUsersEnabled: true, followUsers: ["discord:123456789012345678"], allowedChannels: [ { guildId: "123456789012345678", channelId: "234567890123456789", }, ], }, }, },}Поведение:
followUsersпринимает необработанные идентификаторы пользователей Discord и значенияdiscord:<id>. OpenClaw нормализует обе формы перед сопоставлением событий голосового состояния.followUsersEnabledпо умолчанию равноtrue, когда настроенfollowUsers. Задайтеfalse, чтобы сохранить список, но остановить автоматическое следование в голосе.- Когда отслеживаемый пользователь подключается к разрешенному голосовому каналу, OpenClaw подключается к этому каналу. Когда пользователь перемещается, OpenClaw перемещается вместе с ним. Когда активный отслеживаемый пользователь отключается, OpenClaw выходит.
- Если несколько отслеживаемых пользователей находятся в одной гильдии и активный отслеживаемый пользователь выходит, OpenClaw перемещается в канал другого отслеживаемого пользователя перед выходом из гильдии. Если несколько отслеживаемых пользователей перемещаются одновременно, побеждает последнее наблюдаемое событие голосового состояния.
allowedChannelsпо-прежнему применяется. Отслеживаемый пользователь в запрещенном канале игнорируется, а сессия, принадлежащая следованию, перемещается к другому отслеживаемому пользователю или выходит.- OpenClaw сверяет пропущенные события голосового состояния при запуске и с ограниченным интервалом. Сверка выборочно проверяет настроенные гильдии и ограничивает REST-запросы за один запуск, поэтому очень большие списки
followUsersмогут сходиться дольше одного интервала. - Если Discord или администратор перемещает бота, пока он следует за пользователем, OpenClaw перестраивает голосовую сессию и сохраняет владение следованием, когда место назначения разрешено. Если бот перемещен за пределы
allowedChannels, OpenClaw выходит и повторно подключается к настроенной цели, когда она существует. - Восстановление приема DAVE может выйти из того же канала и повторно подключиться к нему после повторяющихся сбоев расшифровки. Сессии, принадлежащие следованию, сохраняют владение следованием на этом пути восстановления, поэтому последующее отключение отслеживаемого пользователя все равно приводит к выходу из канала.
Выберите между режимами подключения:
- Используйте
followUsersдля персональных или операторских настроек, где бот должен автоматически быть в голосе, когда там находитесь вы. - Используйте
autoJoinдля ботов фиксированных комнат, которые должны присутствовать, даже когда в голосе нет отслеживаемого пользователя. - Используйте
/vc joinдля разовых подключений или комнат, где автоматическое голосовое присутствие было бы неожиданным.
Кодек голоса Discord:
- Логи приема голоса показывают
discord voice: opus decoder: libopus-wasm. - Воспроизведение в реальном времени кодирует необработанный стерео PCM 48 кГц в Opus тем же встроенным пакетом
libopus-wasm, прежде чем передать пакеты в@discordjs/voice. - Воспроизведение файлов и потоков провайдера перекодирует аудио в необработанный стерео PCM 48 кГц с помощью ffmpeg, а затем использует
libopus-wasmдля потока пакетов Opus, отправляемого в Discord.
Конвейер STT плюс TTS:
- Захват Discord PCM преобразуется во временный WAV-файл.
tools.media.audioобрабатывает STT, напримерopenai/gpt-4o-mini-transcribe.- Транскрипт отправляется через входящий поток Discord и маршрутизацию, пока ответная LLM запускается с политикой голосового вывода, которая скрывает инструмент агента
ttsи запрашивает возвращаемый текст, потому что финальным воспроизведением TTS для голоса владеет Discord. voice.model, если задан, переопределяет только ответную LLM для этого обращения в голосовом канале.voice.ttsобъединяется поверхmessages.tts; провайдеры с поддержкой потоковой передачи подают данные напрямую в плеер, иначе полученный аудиофайл воспроизводится в присоединенном канале.
Пример сеанса голосового канала agent-proxy по умолчанию:
{ channels: { discord: { voice: { enabled: true, model: "openai/gpt-5.5", followUsersEnabled: true, followUsers: ["123456789012345678"], realtime: { provider: "openai", model: "gpt-realtime-2", speakerVoice: "cedar", }, }, }, },}Без блока voice.agentSession каждый голосовой канал получает собственный маршрутизируемый сеанс OpenClaw. Например, /vc join channel:234567890123456789 обращается к сеансу для этого голосового канала Discord. Модель реального времени является только голосовым фронтендом; содержательные запросы передаются настроенному агенту OpenClaw. Если модель реального времени создает финальный транскрипт без вызова инструмента consult, OpenClaw принудительно выполняет consult как резервный вариант, чтобы поведение по умолчанию по-прежнему было похоже на разговор с агентом.
Устаревший пример STT плюс TTS:
{ channels: { discord: { voice: { enabled: true, mode: "stt-tts", model: "openai/gpt-5.4-mini", tts: { provider: "openai", providers: { openai: { model: "gpt-4o-mini-tts", speakerVoice: "cedar", }, }, }, }, }, },}Пример двунаправленного режима реального времени:
{ channels: { discord: { voice: { enabled: true, mode: "bidi", model: "openai/gpt-5.5", realtime: { provider: "openai", model: "gpt-realtime-2", speakerVoice: "cedar", toolPolicy: "safe-read-only", consultPolicy: "always", }, }, }, },}Голос как расширение существующего сеанса канала Discord:
{ channels: { discord: { voice: { enabled: true, mode: "agent-proxy", model: "openai/gpt-5.5", agentSession: { mode: "target", target: "channel:123456789012345678", }, realtime: { provider: "openai", model: "gpt-realtime-2", speakerVoice: "cedar", }, }, }, },}В режиме agent-proxy бот присоединяется к настроенному голосовому каналу, но обращения к агенту OpenClaw используют обычный маршрутизируемый сеанс и агента целевого канала. Голосовой сеанс реального времени произносит возвращенный результат обратно в голосовой канал. Агент-супервизор по-прежнему может использовать обычные инструменты сообщений согласно своей политике инструментов, включая отправку отдельного сообщения Discord, если это правильное действие.
Пока делегированный запуск OpenClaw активен, новые голосовые транскрипты Discord обрабатываются как оперативное управление запуском перед началом нового обращения к агенту. Фразы вроде "status", "cancel that", "use the smaller fix" или "when you're done also check tests" классифицируются как запрос статуса, отмена, корректировка или последующий ввод для активного сеанса. Статус, отмена, принятая корректировка и результаты последующих вводов проговариваются обратно в голосовой канал, чтобы вызывающий знал, обработал ли OpenClaw запрос.
Полезные формы цели:
target: "channel:123456789012345678"маршрутизирует через сеанс текстового канала Discord.target: "123456789012345678"обрабатывается как цель канала.target: "dm:123456789012345678"илиtarget: "user:123456789012345678"маршрутизирует через этот сеанс личных сообщений.
Пример OpenAI Realtime с сильным эхом:
{ channels: { discord: { voice: { enabled: true, mode: "bidi", model: "openai/gpt-5.5", realtime: { provider: "openai", model: "gpt-realtime-2", speakerVoice: "cedar", bargeIn: true, minBargeInAudioEndMs: 500, consultPolicy: "always", providers: { openai: { interruptResponseOnInputAudio: false, }, }, }, }, }, },}Используйте это, когда модель слышит собственное воспроизведение Discord через открытый микрофон, но вы все равно хотите прерывать ее речью. OpenClaw не дает OpenAI автоматически прерываться на необработанном входном аудио, а bargeIn: true позволяет событиям начала речи в Discord и уже активному аудио говорящего отменять активные ответы реального времени до того, как следующий захваченный фрагмент достигнет OpenAI. Очень ранние сигналы вмешательства с audioEndMs ниже minBargeInAudioEndMs считаются вероятным эхом или шумом и игнорируются, чтобы модель не обрывалась на первом кадре воспроизведения.
Ожидаемые голосовые логи:
- При присоединении:
discord voice: joining ... voiceSession=... supervisorSession=... agentSessionMode=... voiceModel=... realtimeModel=... - При запуске реального времени:
discord voice: realtime bridge starting ... autoRespond=false interruptResponse=false bargeIn=false minBargeInAudioEndMs=... - При аудио говорящего:
discord voice: realtime speaker turn opened ...,discord voice: realtime input audio started ... outputAudioMs=... outputActive=...иdiscord voice: realtime speaker turn closed ... chunks=... discordBytes=... realtimeBytes=... interruptedPlayback=... - При пропущенной устаревшей речи:
discord voice: realtime forced agent consult skipped reason=incomplete-transcript ...илиreason=non-actionable-closing ... - При завершении ответа реального времени:
discord voice: realtime audio playback finishing reason=response.done ... audioMs=... chunks=... - При остановке/сбросе воспроизведения:
discord voice: realtime audio playback stopped reason=... audioMs=... elapsedMs=... chunks=... - При consult в реальном времени:
discord voice: realtime consult requested ... voiceSession=... supervisorSession=... question=... - При ответе агента:
discord voice: agent turn answer ... - При постановке точной речи в очередь:
discord voice: realtime exact speech queued ... queued=... outputAudioMs=... outputActive=..., затемdiscord voice: realtime exact speech dequeued reason=player-idle ... - При обнаружении вмешательства:
discord voice: realtime barge-in detected source=speaker-start ...илиdiscord voice: realtime barge-in detected source=active-speaker-audio ..., затемdiscord voice: realtime barge-in requested reason=... outputAudioMs=... outputActive=... - При прерывании реального времени:
discord voice: realtime model interrupt requested client:response.cancel reason=barge-in, затем либоdiscord voice: realtime model audio truncated client:conversation.item.truncate reason=barge-in audioEndMs=..., либоdiscord voice: realtime model interrupt confirmed server:response.done status=cancelled ... - При проигнорированном эхе/шуме:
discord voice: realtime model interrupt ignored client:conversation.item.truncate.skipped reason=barge-in audioEndMs=0 minAudioEndMs=250 - При отключенном вмешательстве:
discord voice: realtime capture ignored during playback (barge-in disabled) ... - При простое воспроизведения:
discord voice: realtime barge-in ignored reason=... outputActive=false ... playbackChunks=0
Чтобы отладить обрывающееся аудио, читайте голосовые логи реального времени как временную шкалу:
realtime audio playback startedозначает, что Discord начал воспроизводить аудио ассистента. С этого момента мост начинает считать чанки вывода ассистента, байты Discord PCM, байты провайдера реального времени и длительность синтезированного аудио.realtime speaker turn openedотмечает, что говорящий в Discord стал активен. Если воспроизведение уже активно иbargeInвключен, за этим может последоватьbarge-in detected source=speaker-start.realtime input audio startedотмечает первый фактический аудиокадр, полученный для этого фрагмента речи.outputActive=trueили ненулевое значениеoutputAudioMsздесь означает, что микрофон отправляет ввод, пока воспроизведение ассистента все еще активно.barge-in detected source=active-speaker-audioозначает, что OpenClaw увидел живое аудио говорящего, пока воспроизведение ассистента было активно. Это полезно для отличения реального прерывания от события начала речи в Discord без полезного аудио.barge-in requested reason=...означает, что OpenClaw попросил провайдера реального времени отменить или обрезать активный ответ. Он включаетoutputAudioMs,outputActiveиplaybackChunks, чтобы можно было увидеть, сколько аудио ассистента фактически воспроизвелось до прерывания.realtime audio playback stopped reason=...является локальной точкой сброса воспроизведения Discord. Причина показывает, кто остановил воспроизведение:barge-in,player-idle,provider-clear-audio,forced-agent-consult,stream-closeилиsession-close.realtime speaker turn closedсуммирует захваченный входной фрагмент.chunks=0илиhasAudio=falseозначает, что фрагмент речи открылся, но пригодное аудио не дошло до моста реального времени.interruptedPlayback=trueозначает, что этот входной фрагмент пересекся с выводом ассистента и запустил логику вмешательства.
Полезные поля:
outputAudioMs: длительность аудио ассистента, сгенерированного провайдером реального времени до этой строки лога.audioMs: длительность аудио ассистента, которую OpenClaw посчитал до остановки воспроизведения.elapsedMs: время по настенным часам между открытием и закрытием потока воспроизведения или фрагмента речи.discordBytes: байты стерео PCM 48 кГц, отправленные в Discord voice или полученные из него.realtimeBytes: байты PCM в формате провайдера, отправленные провайдеру реального времени или полученные от него.playbackChunks: чанки аудио ассистента, пересланные в Discord для активного ответа.sinceLastAudioMs: промежуток между последним захваченным аудиокадром говорящего и закрытием фрагмента речи.
Распространенные шаблоны:
- Немедленное обрывание с
source=active-speaker-audio, малымoutputAudioMsи тем же пользователем рядом обычно указывает на попадание эха динамика в микрофон. Увеличьтеvoice.realtime.minBargeInAudioEndMs, снизьте громкость динамиков, используйте наушники или задайтеvoice.realtime.providers.openai.interruptResponseOnInputAudio: false. source=speaker-start, за которым следуетspeaker turn closed ... hasAudio=false, означает, что Discord сообщил о начале речи, но аудио не дошло до OpenClaw. Это может быть временное событие Discord voice, поведение шумоподавления или кратковременное включение микрофона клиентом.audio playback stopped reason=stream-closeбез близкого вмешательства илиprovider-clear-audioозначает, что локальный поток воспроизведения Discord неожиданно завершился. Проверьте предшествующие логи провайдера и плеера Discord.capture ignored during playback (barge-in disabled)означает, что OpenClaw намеренно отбросил ввод, пока аудио ассистента было активно. Включитеvoice.realtime.bargeIn, если хотите, чтобы речь прерывала воспроизведение.barge-in ignored ... outputActive=falseозначает, что Discord или VAD провайдера сообщил о речи, но у OpenClaw не было активного воспроизведения для прерывания. Это не должно обрывать аудио.
Учетные данные разрешаются отдельно для каждого компонента: авторизация маршрута LLM для voice.model, авторизация STT для tools.media.audio, авторизация TTS для messages.tts/voice.tts и авторизация провайдера реального времени для voice.realtime.providers или обычной конфигурации авторизации провайдера.
Голосовые сообщения
Голосовые сообщения Discord показывают предварительный просмотр волны и требуют аудио OGG/Opus. OpenClaw генерирует волну автоматически, но для проверки и преобразования на хосте Gateway нужны ffmpeg и ffprobe.
- Укажите локальный путь к файлу (URL отклоняются).
- Не добавляйте текстовое содержимое (Discord отклоняет текст + голосовое сообщение в одной полезной нагрузке).
- Принимается любой аудиоформат; OpenClaw при необходимости преобразует его в OGG/Opus.
message(action="send", channel="discord", target="channel:123", path="/path/to/audio.mp3", asVoice=true)Устранение неполадок
Использованы запрещенные intents или бот не видит сообщения гильдии
- включите Message Content Intent
- включите Server Members Intent, если вы зависите от разрешения пользователей/участников
- перезапустите gateway после изменения intents
Сообщения гильдии неожиданно заблокированы
- проверьте
groupPolicy - проверьте allowlist гильдий в
channels.discord.guilds - если существует карта
channelsдля гильдии, разрешены только перечисленные каналы - проверьте поведение
requireMentionи шаблоны упоминаний
Полезные проверки:
openclaw doctoropenclaw channels status --probeopenclaw logs --followRequire mention false, но все равно заблокировано
Частые причины:
groupPolicy="allowlist"без соответствующей allowlist гильдии/каналаrequireMentionнастроен не в том месте (должен быть вchannels.discord.guildsили записи канала)- отправитель заблокирован allowlist
usersгильдии/канала
Долгие ходы Discord или дублирующиеся ответы
Типичные журналы:
Slow listener detected ...stuck session: sessionKey=agent:...:discord:... state=processing ...
Параметры очереди Discord gateway:
- одна учетная запись:
channels.discord.eventQueue.listenerTimeout - несколько учетных записей:
channels.discord.accounts.<accountId>.eventQueue.listenerTimeout - это управляет только работой слушателя Discord gateway, а не временем жизни хода агента
Discord не применяет тайм-аут, принадлежащий каналу, к поставленным в очередь ходам агента. Слушатели сообщений сразу передают работу дальше, а поставленные в очередь запуски Discord сохраняют порядок в рамках каждой сессии, пока жизненный цикл сессии/инструмента/среды выполнения не завершит или не прервет работу.
{channels: {discord: { accounts: { default: { eventQueue: { listenerTimeout: 120000, }, }, },},},}Предупреждения о тайм-ауте поиска метаданных Gateway
OpenClaw получает метаданные Discord /gateway/bot перед подключением. При временных сбоях используется резервный стандартный URL Gateway Discord, а записи в журналах ограничиваются по частоте.
Параметры тайм-аута метаданных:
- одна учетная запись:
channels.discord.gatewayInfoTimeoutMs - несколько учетных записей:
channels.discord.accounts.<accountId>.gatewayInfoTimeoutMs - резервное значение env, если конфигурация не задана:
OPENCLAW_DISCORD_GATEWAY_INFO_TIMEOUT_MS - значение по умолчанию:
30000(30 секунд), максимум:120000
Перезапуски из-за тайм-аута Gateway READY
OpenClaw ожидает событие READY Gateway Discord во время запуска и после повторных подключений среды выполнения. Настройкам с несколькими учетными записями и разнесенным запуском может потребоваться более длинное окно READY при запуске, чем значение по умолчанию.
Параметры тайм-аута READY:
- запуск, одна учетная запись:
channels.discord.gatewayReadyTimeoutMs - запуск, несколько учетных записей:
channels.discord.accounts.<accountId>.gatewayReadyTimeoutMs - резервное значение env при запуске, если конфигурация не задана:
OPENCLAW_DISCORD_READY_TIMEOUT_MS - значение по умолчанию при запуске:
15000(15 секунд), максимум:120000 - среда выполнения, одна учетная запись:
channels.discord.gatewayRuntimeReadyTimeoutMs - среда выполнения, несколько учетных записей:
channels.discord.accounts.<accountId>.gatewayRuntimeReadyTimeoutMs - резервное значение env среды выполнения, если конфигурация не задана:
OPENCLAW_DISCORD_RUNTIME_READY_TIMEOUT_MS - значение по умолчанию для среды выполнения:
30000(30 секунд), максимум:120000
Несовпадения аудита разрешений
Проверки разрешений channels status --probe работают только для числовых идентификаторов каналов.
Если вы используете ключи-slug, сопоставление во время выполнения всё равно может работать, но probe не сможет полностью проверить разрешения.
Проблемы с личными сообщениями и привязкой
- Личные сообщения отключены:
channels.discord.dm.enabled=false - Политика личных сообщений отключена:
channels.discord.dmPolicy="disabled"(устаревшее:channels.discord.dm.policy) - ожидание подтверждения привязки в режиме
pairing
Циклы bot-to-bot
По умолчанию сообщения, созданные ботами, игнорируются.
Если вы задаёте channels.discord.allowBots=true, используйте строгие правила упоминаний и allowlist, чтобы избежать циклического поведения.
Предпочитайте channels.discord.allowBots="mentions", чтобы принимать только сообщения ботов, которые упоминают бота.
OpenClaw также поставляется с общей защитой от циклов ботов. Каждый раз, когда allowBots пропускает сообщения, созданные ботами, к диспетчеризации, Discord сопоставляет входящее событие с фактами (account, channel, bot pair), а общий pair guard подавляет пару после превышения настроенного бюджета событий. Guard предотвращает неконтролируемые циклы между двумя ботами, которые раньше приходилось останавливать ограничениями скорости Discord; он не влияет на развёртывания с одним ботом или однократные ответы бота, которые остаются в пределах бюджета.
Настройки по умолчанию (активны, когда задан allowBots):
maxEventsPerWindow: 20-- пара ботов может обменяться 20 сообщениями в пределах скользящего окнаwindowSeconds: 60-- длина скользящего окнаcooldownSeconds: 60-- после срабатывания бюджета каждое дополнительное сообщение между ботами в любом направлении отбрасывается в течение одной минуты
Настройте общий default один раз в channels.defaults.botLoopProtection, затем переопределите Discord, когда легитимному workflow нужен больший запас. Приоритет:
channels.discord.accounts.<account>.botLoopProtectionchannels.discord.botLoopProtectionchannels.defaults.botLoopProtection- встроенные значения по умолчанию
Discord использует общие ключи maxEventsPerWindow, windowSeconds и cooldownSeconds.
{channels: {defaults: { botLoopProtection: { maxEventsPerWindow: 20, windowSeconds: 60, cooldownSeconds: 60, },},discord: { // Optional Discord-wide override. Account blocks override individual // fields and inherit omitted fields from here. botLoopProtection: { maxEventsPerWindow: 4, }, accounts: { mantis: { // Mantis listens to other bots only when they mention her. allowBots: "mentions", }, molty: { // Molty listens to all bot-authored Discord messages. allowBots: true, mentionAliases: { // Lets Molty write a Mantis Discord mention with the configured user id. Mantis: "MANTIS_DISCORD_USER_ID", }, botLoopProtection: { // Allow up to five messages per minute before suppressing the pair. maxEventsPerWindow: 5, windowSeconds: 60, cooldownSeconds: 90, }, }, },},},}Voice STT сбрасывается с DecryptionFailed(...)
- поддерживайте OpenClaw в актуальном состоянии (
openclaw update), чтобы присутствовала логика восстановления приёма голоса Discord - подтвердите
channels.discord.voice.daveEncryption=true(по умолчанию) - начните с
channels.discord.voice.decryptionFailureTolerance=24(upstream default) и настраивайте только при необходимости - следите в логах за:
discord voice: DAVE decrypt failures detecteddiscord voice: repeated decrypt failures; attempting rejoin
- если сбои продолжаются после автоматического повторного входа, соберите логи и сравните с историей upstream-приёма DAVE в discord.js #11419 и discord.js #11449
Справочник конфигурации
Основной справочник: Справочник конфигурации - Discord.
Значимые поля Discord
- запуск/auth:
enabled,token,accounts.*,allowBots - политика:
groupPolicy,dm.*,guilds.*,guilds.*.channels.* - команда:
commands.native,commands.useAccessGroups,configWrites,slashCommand.* - очередь событий:
eventQueue.listenerTimeout(бюджет listener),eventQueue.maxQueueSize,eventQueue.maxConcurrency - gateway:
gatewayInfoTimeoutMs,gatewayReadyTimeoutMs,gatewayRuntimeReadyTimeoutMs - ответ/история:
replyToMode,historyLimit,dmHistoryLimit,dms.*.historyLimit - доставка:
textChunkLimit,chunkMode,maxLinesPerMessage - streaming:
streaming(устаревший alias:streamMode),streaming.preview.toolProgress,draftChunk,blockStreaming,blockStreamingCoalesce - медиа/retry:
mediaMaxMb(ограничивает исходящие загрузки в Discord, по умолчанию100MB),retry - действия:
actions.* - presence:
activity,status,activityType,activityUrl - UI:
ui.components.accentColor - функции:
threadBindings, верхнеуровневыйbindings[](type: "acp"),pluralkit,execApprovals,intents,agentComponents.enabled,agentComponents.ttlMs,heartbeat,responsePrefix
Безопасность и эксплуатация
- Рассматривайте токены ботов как секреты (в управляемых средах предпочтителен
DISCORD_BOT_TOKEN). - Предоставляйте Discord разрешения по принципу наименьших привилегий.
- Если deploy/state команд устарел, перезапустите gateway и повторно проверьте с помощью
openclaw channels status --probe.
Связанные материалы
Привяжите пользователя Discord к gateway.
Поведение группового чата и allowlist.
Направляйте входящие сообщения агентам.
Модель угроз и усиление защиты.
Сопоставляйте серверы и каналы с агентами.
Поведение нативных команд.