ペアリング
スラッシュコマンド
チャンネルのトラブルシューティング
クイックセットアップ
ボットを含む Discord アプリケーションを作成し、ボットをサーバーに追加して、OpenClaw とペアリングします。可能であればプライベートサーバーを使用してください。必要に応じて、先にサーバーを作成します(Create My Own > For me and my friends)。Discord アプリケーションとボットを作成する
特権インテントを有効にする
- Message Content Intent(必須)
- Server Members Intent(推奨。ロール許可リスト、名前から ID への照合、チャンネルオーディエンスアクセスグループには必須)
- Presence Intent(任意。プレゼンス更新のみに使用)
ボットトークンをコピーする
招待 URL を生成してボットをサーバーに追加する
botapplications.commands
- View Channels
- Send Messages
- Read Message History
- Embed Links
- Attach Files
- Add Reactions(任意)
Developer Mode を有効にして ID を収集する
- User Settings(歯車アイコン)→ Developer → Developer Mode をオン (モバイルの場合: App Settings → Advanced)
- サーバーアイコンを右クリック → Copy Server ID
- 自分のアバターを右クリック → Copy User ID
サーバーメンバーからの DM を許可する
ボットトークンを安全に設定する(チャットには送信しない)
openclaw gateway run プロセスを停止して再起動してください。
マネージドサービスとしてインストールしている場合は、DISCORD_BOT_TOKEN が設定されているシェルから openclaw gateway install を実行するか、再起動後にサービスが環境変数の SecretRef を解決できるよう、変数を ~/.openclaw/.env に保存します。
ホストが Discord の起動時アプリケーション検索によってブロックまたはレート制限される場合は、起動時にその REST 呼び出しを省略できるよう、Developer Portal のアプリケーション/クライアント ID を設定します。デフォルトアカウントには channels.discord.applicationId、ボットごとには channels.discord.accounts.<accountId>.applicationId を使用します。OpenClaw を設定してペアリングする
- エージェントに依頼
- CLI/設定
「Discord ボットトークンは設定済みです。User ID<user_id>と Server ID<server_id>を使用して Discord のセットアップを完了してください。」
最初の DM ペアリングを承認する
- エージェントに依頼
- CLI
「この Discord ペアリングコードを承認してください: <CODE>」
DISCORD_BOT_TOKEN はデフォルトアカウントにのみ使用されます。
有効な 2 つの Discord アカウントが同じボットトークンに解決される場合、OpenClaw はそのトークンに対して 1 つの Gateway モニターのみを起動します。設定由来のトークンは環境変数フォールバックより優先されます。それ以外の場合は、最初に有効化されたアカウントが優先され、重複するアカウントは理由 duplicate bot token とともに無効として報告されます。
高度な送信呼び出し(メッセージツール/チャンネルアクション)では、呼び出しごとに明示的な token が使用されます。これは送信および読み取り/プローブ形式のアクション(read/search/fetch/thread/pins/permissions)に適用されます。アカウントポリシー/再試行設定は、引き続きアクティブなランタイムスナップショットで選択されたアカウントから取得されます。推奨: ギルドワークスペースをセットアップする
DM が機能するようになったら、サーバーを、各チャンネルが独自のコンテキストを持つ個別のエージェントセッションとして動作する完全なワークスペースにできます。自分とボットだけがいるプライベートサーバーに推奨します。サーバーをギルド許可リストに追加する
- エージェントに依頼
- 設定
「Discord Server ID <server_id> をギルド許可リストに追加してください」
@メンションなしの応答を許可する
messages.groupChat.visibleReplies: "message_tool" を有効にすると、エージェントは待機し、チャンネルへの返信が有用だと判断した場合にのみ投稿できます。これは GPT-5.6 Sol のような、最新世代でツールの信頼性が高いモデルで最も効果的に動作します。ツールが送信しない限り、アンビエントルームイベントは投稿されません。待機モードの完全な設定については、アンビエントルームイベントを参照してください。Discord に入力中と表示され、ログにもトークン使用量が記録されているのにメッセージが投稿されない場合は、そのターンがアンビエントルームイベントとして設定されているか、メッセージツールによる可視返信が有効になっているかを確認してください。- エージェントに依頼
- 設定
「このサーバーで @メンションなしでもエージェントが応答できるようにしてください」
ギルドチャンネルでのメモリ利用を計画する
- エージェントに依頼
- 手動
「Discord チャンネルで質問した際に MEMORY.md の長期コンテキストが必要な場合は、memory_search または memory_get を使用してください。」
#coding、#home、#research などをセットアップしてください。
ランタイムモデル
- Gateway が Discord 接続を管理します。
- 返信ルーティングは決定論的です。Discord から受信したメッセージへの返信は Discord に返されます。
- Discord のギルド/チャンネルメタデータは、ユーザーに表示される返信の接頭辞ではなく、信頼されていないコンテキストとしてモデルプロンプトに追加されます。モデルがそのエンベロープを返信にコピーした場合、OpenClaw は送信返信と今後の再生コンテキストからコピーされたメタデータを削除します。
- デフォルト(
session.dmScope=main)では、ダイレクトチャットはエージェントのメインセッション(agent:main:main)を共有します。 - ギルドチャンネルには分離されたセッションキー(
agent:<agentId>:discord:channel:<channelId>)が割り当てられます。 - グループ DM はデフォルトで無視されます(
channels.discord.dm.groupEnabled=false)。 - ネイティブスラッシュコマンドは分離されたコマンドセッション(
agent:<agentId>:discord:slash:<userId>)で実行されますが、ルーティング先の会話セッションへのCommandTargetSessionKeyは引き続き保持されます。 - Discord へのテキストのみの Cron/Heartbeat アナウンス配信は、アシスタントに表示される最終回答に集約され、1 回だけ送信されます。エージェントが配信可能なペイロードを複数出力した場合、メディアと構造化コンポーネントのペイロードは引き続き複数メッセージとして送信されます。
フォーラムチャンネル
Discord のフォーラムチャンネルとメディアチャンネルでは、スレッドへの投稿のみ受け付けます。OpenClaw では、次の 2 つの方法で作成できます。- フォーラムの親 (
channel:<forumId>) にメッセージを送信すると、スレッドが自動作成されます。スレッドタイトルには、メッセージの最初の空でない行が使用されます(Discord のスレッド名の上限である 100 文字に切り詰められます)。 openclaw message thread createを使用してスレッドを直接作成します。フォーラムチャンネルには--message-idを渡さないでください。
channel:<threadId>) に送信してください。
インタラクティブコンポーネント
OpenClaw は、エージェントメッセージで Discord components v2 コンテナをサポートしています。components ペイロードを指定してメッセージツールを使用します。インタラクションの結果は通常の受信メッセージとしてエージェントに返され、既存の Discord replyToMode 設定に従います。
サポートされているブロック:
text、section、separator、actions、media-gallery、file- アクション行には、最大 5 個のボタンまたは 1 個の選択メニューを配置できます
- 選択タイプ:
string、user、role、mentionable、channel
components.reusable=true を設定します。
ボタンをクリックできるユーザーを制限するには、そのボタンに allowedUsers を設定します(Discord ユーザー ID、タグ、または *)。一致しないユーザーには、一時的な拒否メッセージが表示されます。
コンポーネントのコールバックは、デフォルトでは 30 分後に期限切れになります。デフォルトアカウントのコールバックレジストリの有効期間を変更するには channels.discord.agentComponents.ttlMs を、アカウントごとに変更するには channels.discord.accounts.<accountId>.agentComponents.ttlMs を設定します。値の単位はミリ秒で、正の整数である必要があり、上限は 86400000(24 時間)です。長い TTL は、ボタンを使用可能な状態に保つ必要があるレビューや承認のワークフローに適していますが、古い Discord メッセージから引き続きアクションを実行できる期間も長くなります。要件を満たす最短の TTL を使用し、古いコールバックが予期しない動作を招く場合はデフォルトを維持してください。
/model および /models スラッシュコマンドは、プロバイダー、モデル、互換性のあるランタイムのドロップダウンと Submit ステップを備えたインタラクティブなモデル選択画面を開きます。/models add は非推奨であり、チャットからモデルを登録する代わりに非推奨メッセージを返します。選択画面の応答は一時的で、呼び出したユーザーだけが使用できます。Discord の選択メニューは 25 個のオプションに制限されているため、openai や vllm など、選択したプロバイダーについてのみ動的に検出されたモデルを選択画面に表示する場合は、agents.defaults.modelPolicy.allow に provider/* エントリを追加してください。
ファイル添付:
fileブロックは添付ファイル参照 (attachment://<filename>) を指す必要があります- 添付ファイルは
media/path/filePath(単一ファイル)で指定します。複数のファイルにはmedia-galleryを使用します - アップロード名を添付ファイル参照と一致させる必要がある場合は、
filenameを使用して上書きします
- 最大 5 個のフィールドを含む
components.modalを追加します - フィールドタイプ:
text、checkbox、radio、select、role-select、user-select - OpenClaw がトリガーボタンを自動的に追加します
アクセス制御とルーティング
- DM ポリシー
- アクセスグループ
- ギルドポリシー
- メンションとグループ DM
channels.discord.dmPolicy は DM アクセスを制御します。channels.discord.allowFrom は正規の DM 許可リストです。pairing(デフォルト)allowlist(少なくとも 1 人のallowFrom送信者が必要)open(channels.discord.allowFromに"*"を含める必要があります)disabled
pairing モードではペアリングを求められます)。複数アカウントでの優先順位:channels.discord.accounts.default.allowFromはdefaultアカウントにのみ適用されます。- 単一アカウントでは、
allowFromが従来のdm.allowFromより優先されます。 - 名前付きアカウントでは、独自の
allowFromと従来のdm.allowFromが設定されていない場合、channels.discord.allowFromを継承します。 - 名前付きアカウントは
channels.discord.accounts.default.allowFromを継承しません。
channels.discord.dm.policy と channels.discord.dm.allowFrom は、互換性のために引き続き読み込まれます。アクセスを変更せずに実行できる場合、openclaw doctor --fix はこれらを dmPolicy と allowFrom に移行します。配信用の DM ターゲット形式:user:<id><@id>メンション
allowFrom に記載されている ID は、互換性のためにユーザー DM ターゲットとして扱われます。ロールベースのエージェントルーティング
Discord ギルドのメンバーをロール ID に基づいて異なるエージェントへルーティングするには、bindings[].match.roles を使用します。ロールベースのバインディングではロール ID のみを使用でき、ピアまたは親ピアのバインディングの後、ギルドのみのバインディングの前に評価されます。バインディングにほかの照合フィールド(たとえば peer + guildId + roles)も設定されている場合、設定されたすべてのフィールドが一致する必要があります。
ネイティブコマンドとコマンド認証
commands.nativeのデフォルトは"auto"で、Discord では有効です。- チャンネルごとのオーバーライド:
channels.discord.commands.native。 commands.native=falseは、起動時の Discord スラッシュコマンドの登録とクリーンアップをスキップします。以前に登録されたコマンドは、Discord アプリから削除するまで Discord に表示され続ける場合があります。- ネイティブコマンド認証では、通常のメッセージ処理と同じ Discord の許可リスト/ポリシーが使用されます。
- 権限のないユーザーにも Discord UI でコマンドが表示される場合がありますが、実行時には OpenClaw の認証が適用され、「not authorized」と応答します。
- デフォルトのスラッシュコマンド設定:
ephemeral: true(channels.discord.slashCommand.ephemeral)。
機能の詳細
返信タグとネイティブ返信
返信タグとネイティブ返信
[[reply_to_current]][[reply_to:<id>]]
channels.discord.replyToMode で制御します。off(デフォルト): 暗黙的な返信スレッド化は行いません。明示的な[[reply_to_*]]タグは引き続き適用されますfirst: ターンの最初の送信 Discord メッセージに、暗黙的なネイティブ返信参照を付加しますall: すべての送信メッセージに付加しますbatched: 受信イベントが複数メッセージをデバウンスしたバッチである場合にのみ付加します。すべての単一メッセージのターンではなく、主に曖昧なバースト状のチャットでネイティブ返信を使用したい場合に便利です
リンクプレビュー
リンクプレビュー
channels.discord.accounts.<id>.suppressEmbeds を設定します。エージェントのメッセージツールによる送信では、単一メッセージに suppressEmbeds: false を渡すこともできます。明示的な Discord embeds ペイロードは、デフォルトのリンクプレビュー設定では抑制されません。ライブストリームプレビュー
ライブストリームプレビュー
channels.discord.streaming.mode は off | partial | block | progress を取ります(streaming/従来の streamMode キーが設定されていない場合のデフォルト)。streamMode は従来のエイリアスです。openclaw doctor --fix を実行すると、永続化された設定が正規のネストされた streaming 形式に書き換えられます。offは Discord のプレビュー編集を無効にします。partialは、トークンの到着に合わせて 1 つのプレビューメッセージを編集します。blockは、下書きサイズのチャンクを生成します。サイズと区切り位置はstreaming.preview.chunk(minChars、maxChars、breakPreference)で調整でき、textChunkLimitに制限されます。ブロックストリーミングが明示的に有効な場合、OpenClaw は二重ストリーミングを避けるため、プレビューストリームをスキップします。progressは、最終配信まで編集可能なステータス下書きを 1 つ維持します。デフォルトでは、エージェントの最新の前置きまたはナレーションを 1 行表示し、生成されたラベル、スペーサー、ツール行は表示しません。- メディア、エラー、明示的な返信の最終出力は、保留中のプレビュー編集をキャンセルします。
streaming.preview.toolProgressのデフォルトは、partial/blockモードではtrueです。Discord の進行状況モードでは、デフォルトでツール行は表示されません。オプトインするには、streaming.progress.toolProgress: trueを設定します。🛠️ Bash: run testsや🔎 Web Search: for "query"などのコンパクトなツール/進行状況行を追加するには、streaming.progress.toolProgress: trueを設定します。互換性のため、既存のprogress.labelまたはprogress.labels設定では、以前のツール行のデフォルトが維持されます。行を表示せずにカスタムラベルを使用するには、toolProgress: falseを設定します。streaming.progress.commentary(デフォルトfalse)は、一時的な進行状況の下書きで生のアシスタント解説を表示するようオプトインします。デフォルトの前置き/ナレーションのステータス行は、このオプションとは独立しています。解説は表示前にクリーンアップされ、一時的なままで、最終回答の配信には影響しません。streaming.progress.maxLineCharsは、行ごとの進行状況プレビューの上限を制御します。文章は単語の境界で短縮され、コマンドとパスの詳細では有用な末尾が維持されます。streaming.preview.commandText/streaming.progress.commandTextは、コンパクトな進行状況行のコマンド/実行詳細を制御します。raw(デフォルト)またはstatus(ツールラベルのみ)です。
履歴、コンテキスト、スレッドの動作
履歴、コンテキスト、スレッドの動作
channels.discord.historyLimitのデフォルトは20- フォールバック:
messages.groupChat.historyLimit 0で無効化
channels.discord.dmHistoryLimitchannels.discord.dms["<user_id>"].historyLimit
- Discord スレッドはチャンネルセッションとしてルーティングされ、オーバーライドされない限り親チャンネルの設定を継承します。
- スレッドセッションは、モデル専用のフォールバックとして親チャンネルのセッションレベルの
/model選択を継承します。スレッドローカルの/model選択が優先され、トランスクリプトの継承が有効でない限り、親のトランスクリプト履歴はコピーされません。 channels.discord.thread.inheritParent(デフォルトfalse)は、新しい自動スレッドで親のトランスクリプトを初期データとして使用するようオプトインします。アカウントごとのオーバーライド:channels.discord.accounts.<id>.thread.inheritParent。- メッセージツールのリアクションは、
user:<id>の DM ターゲットを解決できます。 guilds.<guild>.channels.<channel>.requireMention: falseは、返信ステージのアクティベーションのフォールバック中も維持されます。
サブエージェントのスレッド連携セッション
サブエージェントのスレッド連携セッション
/focus <target>現在または新しいスレッドをサブエージェント/セッションターゲットに関連付けます/unfocus現在のスレッドの関連付けを解除します/agentsアクティブな実行と関連付けの状態を表示します/session idle <duration|off>フォーカスされた関連付けの非アクティブ時の自動フォーカス解除を確認/更新します/session max-age <duration|off>フォーカスされた関連付けの最大存続時間を確認/更新します
session.threadBindings.*は、Discord と Telegram の正規ポリシーです。spawnSessionsは、sessions_spawn({ thread: true })および ACP スレッド生成時のスレッドの自動作成/関連付けを制御します。デフォルト:true。defaultSpawnContextは、スレッド連携による生成のネイティブサブエージェントコンテキストを制御します。デフォルト:"fork"。- 非推奨の
spawnSubagentSessions/spawnAcpSessionsキーは、openclaw doctor --fixによって移行されます。 - スレッドの関連付けが無効な場合、
/focusおよび関連操作は使用できません。
送信元メッセージ上のサブエージェント進行状況
送信元メッセージ上のサブエージェント進行状況
channels.discord.subagentProgress: true を設定します。1️⃣ から 🔟)を置き換えます。🔟 は 10 以上も表します。最後の子が終了すると、カウントリアクションは削除されます。失敗、タイムアウト、または強制終了した子は、🔴 リアクションを残します。これはオプトイン機能で、固定された内部タイミングと絵文字のデフォルトを使用します。リアクションによるフィードバックには、ボットに Add Reactions 権限が必要です。アカウントレベルの channels.discord.accounts.<id>.subagentProgress は、トップレベルの値をオーバーライドします。永続的な ACP チャンネル関連付け
永続的な ACP チャンネル関連付け
bindings[]、type: "acp"、および match.channel: "discord"。/acp spawn codex --bind hereは現在のチャンネルまたはスレッドをその場で関連付け、以後のメッセージを同じ ACP セッションに維持します。スレッドメッセージは親チャンネルの関連付けを継承します。- 関連付けられたチャンネルまたはスレッドでは、
/newと/resetが同じ ACP セッションをその場でリセットします。一時的なスレッドの関連付けがアクティブな間は、ターゲット解決をオーバーライドできます。 spawnSessionsは、--thread auto|hereを介した子スレッドの作成/関連付けを制限します。
リアクション通知
リアクション通知
guilds.<id>.reactionNotifications):offown(デフォルト)allallowlist(guilds.<id>.usersを使用)
オンライン状態イベント
オンライン状態イベント
presenceEvents には、ルーティング先エージェントで Heartbeat が有効になっていることと、Discord Developer Portal にあるアプリケーションの Bot ページで特権 Presence Intent が有効になっていることが必要です。OpenClaw は、完全な各 GUILD_CREATE スナップショットから現在オンラインのメンバーを初期登録し、観測されたオフラインからオンラインへの遷移をルーティングします。また、それまで観測されていなかったメンバーから後で初めてオンライン信号を受信した場合も、新たに利用可能になったものとして扱います。そのメンバーはスナップショット後にオンラインになったか参加した可能性があるため、このイベントは正確な直前のステータスを断定しません。対象となるのは、channelId を表示できる人間のみです。チャンネルと公開スレッドでは、そのチャンネルまたは親に対する View Channel が必要で、非公開スレッドではさらにメンバーであるか Manage Threads が必要です。users で対象者をさらに絞り込めます。OpenClaw はボットと変化のないオンライン状態を無視し、ユーザーごとの 8 時間のクールダウンを Gateway の再起動後も保持します。Discord が新しい Gateway セッションを確立して READY を送信すると、OpenClaw はギルドのプレゼンス状態が再構築される間、reconnectSuppressSeconds(デフォルトは 300、0 で無効化)にわたってプレゼンス由来のイベントを抑制し、再観測されたメンバーが 1 人ずつエージェントを起動しないようにします。さらに、正常にキューへ追加されたイベントをギルドごとに、burstWindowSeconds のスライドウィンドウ(デフォルトは 60)あたり burstLimit 件(デフォルトは 8)にレート制限し、各ギルドの抑制期間につき一度だけログを記録します。再開されたセッションは新しいセッションとして扱われません。Discord はメンバー数が 75,000 を超えるギルドのスナップショットを制限します。その場合、OpenClaw が挨拶するには明示的なオフライン更新が事前に必要です。システムイベントは、変更可能な表示名を埋め込まず、不変のユーザー ID、ギルド ID、チャンネル ID を保持します。挨拶するかどうか、およびその方法はエージェントが決定します。確認リアクション
確認リアクション
ackReaction は、OpenClaw が受信メッセージを処理している間、確認用の絵文字を送信します。解決順序:channels.discord.accounts.<accountId>.ackReactionchannels.discord.ackReactionmessages.ackReaction- エージェントのアイデンティティ絵文字へのフォールバック(
agents.entries.*.identity.emoji、なければ「👀」)
- Discord は Unicode 絵文字またはカスタム絵文字名を受け付けます。
- チャンネルまたはアカウントでリアクションを無効にするには、
""を使用します。
messages.ackReactionScope):値:"all"(DM とグループ。アンビエントルームイベントを含む)、"direct"(DM のみ)、"group-all"(アンビエントルームイベントを除くすべてのグループメッセージ。DM は除く)、"group-mentions"(ボットがメンションされたグループ。DM は除く、デフォルト)、"off" / "none"(無効)。"group-mentions")では、ダイレクトメッセージやアンビエントルームイベントに対して確認リアクションは実行されません。受信した Discord の DM と静かなルームイベントに確認リアクションを付けるには、messages.ackReactionScope を "all" に設定します。設定の書き込み
設定の書き込み
/config set|unset のフローに影響します(コマンド機能が有効な場合)。無効化:Gateway プロキシ
Gateway プロキシ
channels.discord.proxy を使用して、Discord Gateway の WebSocket トラフィックと起動時の REST 参照(アプリケーション ID と許可リストの解決)を HTTP(S) プロキシ経由でルーティングします。
Discord Gateway の WebSocket プロキシは明示的に設定する必要があります。WebSocket 接続は Gateway プロセスの環境にあるプロキシ環境変数を継承しません。channels.discord.proxy が設定されている場合、起動時の REST 参照はこのプロキシを使用します。PluralKit のサポート
PluralKit のサポート
- 許可リストでは
pk:<memberId>を使用できます - メンバーの表示名は、
channels.discord.dangerouslyAllowNameMatching: trueの場合にのみ名前またはスラッグで照合されます - 参照では、元のメッセージ ID を使用して PluralKit API に問い合わせます
- 参照に失敗した場合、プロキシされたメッセージはボットメッセージとして扱われ、
allowBotsで通過が許可されていない限り破棄されます
送信メンションのエイリアス
送信メンションのエイリアス
mentionAliases を使用します。キーは先頭の @ を除いたハンドルで、値は Discord ユーザー ID です。不明なハンドル、@everyone、@here、および Markdown のコードスパン内にあるメンションは変更されません。プレゼンスの設定
プレゼンスの設定
activity が設定されている場合、カスタムステータスがデフォルトのアクティビティ種別です):- 0:プレイ中
- 1:配信中(
activityUrlが必要。さらにactivityUrlにはactivityType: 1が必要) - 2:再生中
- 3:視聴中
- 4:カスタム(アクティビティのテキストをステータス状態として使用。絵文字は任意)
- 5:対戦中
intervalMs は 30000、minUpdateIntervalMs は 15000(intervalMs 以下である必要があります)。任意のテキスト上書き:autoPresence.healthyTextautoPresence.degradedTextautoPresence.exhaustedText({reason}プレースホルダーをサポート)
Discord での承認
Discord での承認
channels.discord.execApprovals.enabledchannels.discord.execApprovals.approvers(任意。可能な場合はcommands.ownerAllowFromにフォールバック)channels.discord.execApprovals.target(dm|channel|both、デフォルト:dm)agentFilter、sessionFilter、cleanupAfterResolve
enabled が未設定または "auto" で、execApprovals.approvers または commands.ownerAllowFrom から少なくとも 1 人の承認者を解決できる場合、Discord はネイティブの実行承認を自動的に有効にします。Discord は、チャンネルの allowFrom、従来の dm.allowFrom、またはダイレクトメッセージの defaultTo から実行承認者を推測しません。Discord をネイティブ承認クライアントとして明示的に無効にするには、enabled: false を設定します。/diagnostics や /export-trajectory のような機密性の高い所有者専用グループコマンドでは、OpenClaw は承認プロンプトと最終結果を非公開で送信します。呼び出した所有者に Discord の所有者ルートがある場合は、まず Discord の DM を試します。それ以外の場合は、Telegram など、commands.ownerAllowFrom で利用可能な最初の所有者ルートにフォールバックします。target が channel または both の場合、承認プロンプトはチャンネルに表示されます。ボタンを使用できるのは解決済みの承認者のみです。それ以外のユーザーには一時的な拒否メッセージが表示されます。承認プロンプトにはコマンドテキストが含まれるため、チャンネルへの配信は信頼できるチャンネルでのみ有効にしてください。セッションキーからチャンネル ID を取得できない場合、OpenClaw は DM 配信にフォールバックします。Discord は、他のチャットチャンネルでも使用される共通の承認ボタンをレンダリングします。Discord のネイティブアダプターが主に追加するのは、承認者への DM ルーティングとチャンネルへのファンアウトです。これらのボタンがある場合、それが主要な承認 UX となります。OpenClaw が手動の /approve コマンドを含めるのは、ツールの結果がチャット承認を利用できないと示す場合、または手動承認が唯一の経路である場合に限ります。Discord のネイティブ承認ランタイムが有効でない場合、OpenClaw はローカルで決定的な /approve <id> <decision> プロンプトを表示し続けます。ランタイムが有効でもネイティブカードをどの宛先にも配信できない場合、OpenClaw は保留中の承認に含まれる正確な /approve コマンドとともに、同じチャットへフォールバック通知を送信します。Gateway の認証と承認の解決は、共通の Gateway クライアント契約に従います(plugin: ID は plugin.approval.resolve を通じて解決し、それ以外の ID は exec.approval.resolve を通じて解決します)。承認はデフォルトで 30 分後に期限切れになります。実行承認を参照してください。ツールとアクションゲート
Discord のメッセージアクションは、メッセージング、チャンネル管理、モデレーション、プレゼンス、メタデータを対象とします。 主な例:- メッセージング:
sendMessage、readMessages、editMessage、deleteMessage、threadReply - リアクション:
react、reactions、emojiList - モデレーション:
timeout、kick、ban - プレゼンス:
setPresence
event-create アクションは、スケジュール済みイベントのカバー画像を設定するために、任意の image パラメーター(URL またはローカルファイルパス)を受け付けます。
アクションゲートは channels.discord.actions.* の配下にあります。
デフォルトのゲート動作:
Components v2 UI
OpenClaw は、実行承認とコンテキスト間マーカーに Discord components v2 を使用します。Discord のメッセージアクションでは、カスタム UI 用にcomponents も指定できます(高度な使用方法です。discord ツールを介してコンポーネントペイロードを構築する必要があります)。従来の embeds も引き続き使用できますが、推奨されません。
channels.discord.ui.components.accentColorは、Discord コンポーネントコンテナで使用するアクセントカラー(16 進数)を設定します。アカウントごと:channels.discord.accounts.<id>.ui.components.accentColor。channels.discord.agentComponents.ttlMsは、送信された Discord コンポーネントのコールバックを登録したままにする期間を制御します(デフォルト1800000、最大86400000)。アカウントごと:channels.discord.accounts.<id>.agentComponents.ttlMs。embedsは、components v2 が存在する場合は無視されます。- プレーン URL のプレビューはデフォルトで抑制されます。単一の外部リンクを展開する必要がある場合は、メッセージアクションに
suppressEmbeds: falseを設定します。
音声
Discord には、リアルタイムの ボイスチャンネル(継続的な会話)と ボイスメッセージの添付ファイル(波形プレビュー形式)という 2 つの異なる音声サーフェスがあります。Gateway は両方をサポートしています。ボイスチャンネル
セットアップチェックリスト:- Discord Developer Portal で Message Content Intent を有効にします。
- ロールまたはユーザーの許可リストを使用する場合は、Server Members Intent を有効にします。
botおよびapplications.commandsスコープを指定してボットを招待します。- 対象のボイスチャンネルで Connect、Speak、Send Messages、Read Message History を付与します。
- ネイティブコマンド(
commands.nativeまたはchannels.discord.commands.native)を有効にします。 channels.discord.voiceを設定します。
/vc join|leave|status を使用します。このコマンドはアカウントのデフォルトエージェントを使用し、他の Discord コマンドと同じ許可リストおよびグループポリシーのルールに従います。
- Discord 音声は、テキストのみの構成ではオプトインです。
channels.discord.voice.enabled=trueを設定する(または既存のchannels.discord.voiceブロックを維持する)と、/vcコマンド、音声ランタイム、およびGuildVoiceStatesGateway インテントが有効になります。channels.discord.intents.voiceStatesではインテントのサブスクリプションを明示的に上書きできます。実効的な音声の有効化設定に従うには、未設定のままにしてください。 voice.modeは会話パスを制御します。デフォルトはagent-proxyです。リアルタイム音声フロントエンドがターンのタイミング、中断、再生を処理し、実質的な処理をopenclaw_agent_consult経由でルーティング先の OpenClaw エージェントに委任し、その結果をその話者が入力した Discord プロンプトと同様に扱います。stt-ttsは、従来のバッチ STT と TTS のフローを維持します。bidiでは、OpenClaw の頭脳向けにopenclaw_agent_consultを公開しながら、リアルタイムモデルが直接会話できます。voice.agentSessionは、どの OpenClaw 会話が音声ターンを受信するかを制御します。音声チャンネル独自のセッションを使用する場合は未設定のままにします。または、{ mode: "target", target: "channel:<text-channel-id>" }に設定すると、音声チャンネルを#maintainersなどの既存の Discord テキストチャンネルセッションに対するマイク/スピーカー拡張として機能させることができます。voice.modelは、Discord 音声応答およびリアルタイム相談に使用する OpenClaw エージェントの頭脳を上書きします。ルーティング先エージェントのモデルを継承する場合は、未設定のままにしてください。これはvoice.realtime.modelとは別です。voice.followUsersを使用すると、ボットは選択されたユーザーとともに Discord 音声へ参加、移動、退出できます。音声でユーザーを追跡するを参照してください。agent-proxyは、音声をdiscord-voice経由でルーティングします。これにより、話者と対象セッションに対する通常の所有者/ツール認可は維持されますが、再生は Discord 音声が担当するため、エージェントのttsツールは非表示になります。デフォルトでは、agent-proxyにより、所有者である話者(voice.realtime.toolPolicy: "owner")の相談には所有者と同等の完全なツールアクセスが付与され、実質的な回答を行う前に OpenClaw エージェントへ相談することが強く優先されます(voice.realtime.consultPolicy: "always")。このデフォルトのalwaysモードでは、リアルタイムレイヤーは相談の回答前に間をつなぐ発話を自動再生しません。音声を取得して文字起こしした後、ルーティング先の OpenClaw の回答を読み上げます。Discord が最初の回答を再生している間に複数の強制相談回答が完了した場合、後続の完全一致発話回答は文の途中で音声を置き換えず、再生がアイドル状態になるまでキューに入れられます。stt-ttsモードでは、STT はtools.media.audioを使用します。voice.modelは文字起こしに影響しません。- リアルタイムモードでは、
voice.realtime.provider、voice.realtime.model、およびvoice.realtime.speakerVoiceがリアルタイム音声セッションを構成します。OpenAI Realtime 2.1 と Codex の頭脳を組み合わせる場合は、voice.realtime.model: "gpt-realtime-2.1"とvoice.model: "openai/gpt-5.6-sol"を使用します。 - リアルタイム音声モードでは、デフォルトで小規模な
IDENTITY.md、USER.md、およびSOUL.mdプロファイルファイルがリアルタイムプロバイダーの指示に含まれるため、高速な直接ターンでも、ルーティング先の OpenClaw エージェントと同じアイデンティティ、ユーザーに関する基盤情報、ペルソナが維持されます。これをカスタマイズするにはvoice.realtime.bootstrapContextFilesをサブセットに設定し、無効にするには[]を設定します。サポートされるのはこれらのプロファイルファイルのみです。AGENTS.mdは通常のエージェントコンテキストに残ります。挿入されたプロファイルコンテキストは、ワークスペースでの作業、現在の事実、メモリ検索、またはツールを使用する操作におけるopenclaw_agent_consultの代わりにはなりません。 - OpenAI の
agent-proxyリアルタイムモードでは、ウェイクネームのゲートがデフォルトでルームの状況に適応します。人間が 1 人の場合はウェイクネームなしで自然に話せますが、2 人以上の場合は、ターンの先頭または末尾にウェイクネームを付ける必要があります。他のボットは人数に含まれません。ウェイクネームを常に必須にするにはvoice.realtime.requireWakeName: true、一切必須にしない場合はfalseを設定します。構成するウェイクネームは 1 語または 2 語でなければなりません。voice.realtime.wakeNamesが未設定の場合、OpenClaw はルーティング先エージェントのnameとOpenClawを使用し、それらがない場合はエージェント ID とOpenClawを使用します。ウェイクネームゲートが有効な場合、リアルタイムプロバイダーの自動応答が無効になり、受け付けたターンは OpenClaw エージェントへの相談パスを経由します。また、最終的な文字起こしが到着する前に、部分的な文字起こしから先頭のウェイクネームが認識されると、短い音声確認が返されます。このポリシーは、音声へ再接続することなく、リアルタイムの参加と退出に追随します。 - OpenAI リアルタイムプロバイダーは、出力音声イベントと文字起こしイベントについて、現在の Realtime 2 イベント名と従来の Codex 互換エイリアスを受け付けます。そのため、互換性のあるプロバイダースナップショットに差異が生じても、アシスタントの音声が欠落することはありません。
voice.realtime.bargeInは、Discord の話者開始イベントによって進行中のリアルタイム再生を中断するかどうかを制御します。未設定の場合は、リアルタイムプロバイダーの入力音声中断設定に従います。voice.realtime.minBargeInAudioEndMsは、OpenAI リアルタイムの割り込みによって音声が切り詰められるまでの、アシスタントの最小再生時間を制御します。デフォルト:250。エコーが少ないルームですぐに中断するには0を設定し、エコーが多いスピーカー環境では値を大きくします。voice.ttsは、stt-tts音声再生に限りttsを上書きします。リアルタイムモードでは代わりにvoice.realtime.speakerVoiceを使用します。Discord 再生で OpenAI の音声を使用するには、voice.tts.provider: "openai"を設定し、voice.tts.providers.openai.speakerVoiceでテキスト読み上げ音声を選択します。cedarは、現在の OpenAI TTS モデルで男性的に聞こえる適切な選択肢です。- チャンネル単位の Discord
systemPromptの上書きは、その音声チャンネルの音声文字起こしターンに適用されます。 - OpenClaw が音声チャンネルに参加すると、ルーティング先のエージェントセッションは、現在の参加者一覧を含む無音のシステムイベントを受信します。その後の参加者の参加と退出によってそのセッションは更新されますが、要求されていない音声応答は発生しません。Discord の表示名は信頼されていないラベルとして扱われます。認可された音声ターンも最新の参加者一覧のスナップショットを受信します。
- 音声文字起こしターンと
/vcコマンドは、所有者ステータスの判定にcommands.ownerAllowFrom内の Discord エントリを使用します。Discord コマンドの所有者が構成されていない場合でも、選択された Discord アカウントのallowFrom(または従来のdm.allowFrom)によって、所有者ステータスを付与せずに音声アクセスを認可できます。エージェントのツール表示可否は、ルーティング先セッションに構成されたツールポリシーに従います。 voice.autoJoinに同じギルドのエントリが複数ある場合、OpenClaw はそのギルドで最後に構成されたチャンネルに参加します。voice.allowedChannelsは、任意の滞在許可リストです。/vc joinが認可済みの任意の Discord 音声チャンネルに参加できるようにするには、未設定のままにします。設定すると、/vc join、起動時の自動参加、およびボットの音声状態による移動が、一覧に含まれる{ guildId, channelId }エントリに制限されます。Discord 音声へのすべての参加を拒否するには、空の配列に設定します。Discord がボットを許可リスト外へ移動した場合、OpenClaw はそのチャンネルから退出し、構成済みの自動参加先が利用可能であれば、そこへ再参加します。voice.daveEncryptionとvoice.decryptionFailureToleranceは、@discordjs/voiceの参加オプションへそのまま渡されます。アップストリームのデフォルトはdaveEncryption=trueとdecryptionFailureTolerance=24です。- OpenClaw は、Discord 音声の受信とリアルタイムの raw PCM 再生に、同梱の
libopus-wasmコーデックを使用します。固定バージョンの libopus WebAssembly ビルドが同梱されており、ネイティブの opus アドオンは必要ありません。 voice.connectTimeoutMsは、/vc joinおよび自動参加の試行における、初回の@discordjs/voiceReady 待機時間を制御します。デフォルト:30000。voice.reconnectGraceMsは、切断された音声セッションが再接続を開始するまで、OpenClaw がそのセッションを破棄せずに待機する時間を制御します。デフォルト:15000。stt-ttsモードでは、別のユーザーが話し始めただけでは音声再生は停止しません。フィードバックループを避けるため、OpenClaw は TTS の再生中に新しい音声取得を無視します。次のターンは、再生の終了後に話してください。リアルタイムモードでは、話者の発話開始が割り込み信号としてリアルタイムプロバイダーへ転送されます。- リアルタイムモードでは、スピーカーから開放状態のマイクに入るエコーが割り込みとして認識され、再生を中断することがあります。エコーが多い Discord ルームでは、入力音声による OpenAI の自動中断を防ぐために
voice.realtime.providers.openai.interruptResponseOnInputAudio: falseを設定します。それでも Discord の話者開始イベントで進行中の再生を中断する場合は、voice.realtime.bargeIn: trueを追加します。OpenAI リアルタイムブリッジは、voice.realtime.minBargeInAudioEndMs未満の再生切り詰めをエコー/ノイズの可能性が高いものとして無視し、Discord の再生をクリアせず、スキップとしてログに記録します。 voice.captureSilenceGraceMsは、Discord が話者の発話終了を報告してから、OpenClaw がその音声セグメントを STT 用に確定するまでの待機時間を制御します。デフォルト:2000。Discord が通常の間を細切れの部分文字起こしに分割する場合は、値を大きくしてください。- ElevenLabs が選択された TTS プロバイダーの場合、Discord の音声再生ではストリーミング TTS が使用され、プロバイダーの応答ストリームから再生が開始されます。ストリーミングをサポートしないプロバイダーは、合成された一時ファイルを使用するパスにフォールバックします。
- OpenClaw は受信時の復号失敗を監視し、短時間に失敗が繰り返された場合は、音声チャンネルから退出して再参加することで自動復旧します。
- 更新後に受信ログで
DecryptionFailed(UnencryptedWhenPassthroughDisabled)が繰り返し表示される場合は、依存関係レポートとログを収集してください。同梱の@discordjs/voice系列には、discord.js issue #11419 を解決した discord.js PR #11449 のアップストリームのパディング修正が含まれています。 The operation was aborted受信イベントは、OpenClaw が取得した話者セグメントを確定するときに想定されるものです。これは詳細診断であり、警告ではありません。- Discord の詳細音声ログには、受け付けた各話者セグメントについて、長さが制限された 1 行の STT 文字起こしプレビューが含まれます。そのため、無制限の文字起こしテキストを出力することなく、デバッグ時にユーザー側とエージェントの応答側の両方を確認できます。
agent-proxyモードでは、強制相談のフォールバックは、...で終わるテキストや、末尾の「and」のような接続語など、未完了である可能性が高い文字起こし断片、および「be right back」や「bye」のような明らかに操作を必要としない締めくくりをスキップします。これにより古いキュー内の回答が防止された場合、ログにはforced agent consult skipped reason=...が表示されます。
音声でユーザーを追跡する
起動時に固定チャンネルへ参加したり、/vc join を待機したりする代わりに、Discord 音声ボットを既知の 1 人以上の Discord ユーザーと常に同じ場所にいさせる場合は、voice.followUsers を使用します。
followUsersは、生の Discord ユーザー ID とdiscord:<id>値を受け付けます。OpenClaw は、音声状態イベントと照合する前に両方の形式を正規化します。followUsersが設定されている場合、followUsersEnabledのデフォルトはtrueです。保存済みのリストを維持しつつ、音声の自動追従を停止するには、falseに設定します。followUsersは、音声への在室のみを制御します。発言者アクセス権や所有者権限は付与しません。commands.ownerAllowFromと、ギルドまたはチャンネルのユーザーおよびロールは個別に設定してください。- 追従対象ユーザーが許可された音声チャンネルに参加すると、OpenClaw はそのチャンネルに参加します。ユーザーが移動すると、OpenClaw も一緒に移動します。アクティブな追従対象ユーザーが切断すると、OpenClaw は退出します。
- 複数の追従対象ユーザーが同じギルドにいて、アクティブな追従対象ユーザーが退出した場合、OpenClaw はギルドから退出する前に、追跡中の別の追従対象ユーザーのチャンネルへ移動します。複数の追従対象ユーザーが同時に移動した場合は、最後に観測された音声状態イベントが優先されます。
allowedChannelsは引き続き適用されます。許可されていないチャンネルにいる追従対象ユーザーは無視され、追従所有のセッションは別の追従対象ユーザーへ移動するか退出します。- OpenClaw は、起動時および上限付きの間隔で、取りこぼした音声状態イベントを照合します。照合では設定済みのギルドを抽出し、1 回の実行あたりの REST ルックアップ数に上限を設けるため、非常に大きな
followUsersリストは収束までに複数回の間隔を要する場合があります。 - ユーザーの追従中に Discord または管理者がボットを移動した場合、OpenClaw は音声セッションを再構築し、移動先が許可されていれば追従所有を維持します。ボットが
allowedChannelsの外へ移動された場合、OpenClaw は退出し、設定済みの対象が存在すればそこへ再参加します。 - DAVE の受信復旧では、復号に繰り返し失敗した後、同じチャンネルから退出して再参加する場合があります。追従所有のセッションは、その復旧経路でも追従所有を維持するため、その後に追従対象ユーザーが切断した場合もチャンネルから退出します。
- 自分が音声に参加しているときにボットも自動的に参加する必要がある、個人用またはオペレーター用のセットアップでは、
followUsersを使用します。 - 追跡対象ユーザーが音声に参加していないときでも常駐する必要がある、固定ルーム用ボットでは、
autoJoinを使用します。 - 単発の参加や、音声への自動参加が予想外となるルームでは、
/vc joinを使用します。
- 音声受信ログには
discord voice: opus decoder: libopus-wasmが表示されます。 - リアルタイム再生では、生の 48 kHz ステレオ PCM を、同梱されている同じ
libopus-wasmパッケージで Opus にエンコードしてから、パケットを@discordjs/voiceに渡します。 - ファイルおよびプロバイダーストリームの再生では、ffmpeg を使用して生の 48 kHz ステレオ PCM にトランスコードしてから、Discord に送信する Opus パケットストリームに
libopus-wasmを使用します。
- Discord の PCM キャプチャは、一時 WAV ファイルに変換されます。
tools.media.audioが STT を処理します。たとえばopenai/gpt-4o-mini-transcribeです。- 文字起こしは Discord の受信処理とルーティングを通じて送信されます。その間、応答 LLM は、エージェントの
ttsツールを非表示にし、テキストを返すよう求める音声出力ポリシーで実行されます。これは、最終的な TTS 再生を Discord 音声が所有するためです。 voice.modelが設定されている場合、この音声チャンネルのターンについてのみ応答 LLM を上書きします。voice.ttsはttsにマージされます。ストリーミング対応のプロバイダーはプレーヤーへ直接データを送り、それ以外の場合は生成された音声ファイルが参加中のチャンネルで再生されます。
voice.agentSession ブロックがない場合、音声チャンネルごとに独自のルーティング済み OpenClaw セッションが割り当てられます。たとえば、/vc join channel:234567890123456789 はその Discord 音声チャンネルのセッションと対話します。リアルタイムモデルは音声フロントエンドにすぎず、実質的なリクエストは設定済みの OpenClaw エージェントへ渡されます。リアルタイムモデルが相談ツールを呼び出さずに最終的な文字起こしを生成した場合、OpenClaw はフォールバックとして相談を強制し、デフォルトでもエージェントと会話しているように動作させます。
従来の STT と TTS の例:
agent-proxy モードでは、ボットは設定済みの音声チャンネルに参加しますが、OpenClaw エージェントのターンでは、対象チャンネルの通常のルーティング済みセッションとエージェントが使用されます。リアルタイム音声セッションは、返された結果を音声チャンネルで読み上げます。スーパーバイザーエージェントは、ツールポリシーに従って通常のメッセージツールを引き続き使用できます。適切なアクションであれば、別の Discord メッセージを送信することもできます。
委任された OpenClaw の実行がアクティブな間、新しい Discord 音声の文字起こしは、別のエージェントターンを開始する前に、進行中の実行を制御する入力として扱われます。「ステータス」、「それをキャンセル」、「より小規模な修正を使用」、「完了したらテストも確認」などのフレーズは、アクティブなセッションに対するステータス、キャンセル、方向修正、またはフォローアップ入力として分類されます。ステータス、キャンセル、受理された方向修正、およびフォローアップの結果は音声チャンネルで読み上げられるため、呼び出し元は OpenClaw がリクエストを処理したかどうかを把握できます。
有用な対象形式:
target: "channel:123456789012345678"は、Discord テキストチャンネルセッションを通じてルーティングされます。target: "123456789012345678"は、チャンネル対象として扱われます。target: "dm:123456789012345678"またはtarget: "user:123456789012345678"は、そのダイレクトメッセージセッションを通じてルーティングされます。
bargeIn: true により、次にキャプチャされたターンが OpenAI に到達する前に、Discord の発言者開始イベントと、すでにアクティブな発言者の音声が、進行中のリアルタイム応答をキャンセルできます。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=... - リアルタイム相談時:
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:Discord 音声へ送信、または Discord 音声から受信した 48 kHz ステレオ PCM バイト数。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 音声イベント、ノイズゲートの動作、またはクライアントが一時的にマイクをオンにしたことが原因の場合があります。- 近くでの割り込みまたは
provider-clear-audioがないaudio playback stopped reason=stream-closeは、ローカルの Discord 再生ストリームが予期せず終了したことを意味します。直前のプロバイダーおよび Discord プレーヤーのログを確認してください。 capture ignored during playback (barge-in disabled)は、アシスタント音声がアクティブな間、OpenClaw が意図的に入力を破棄したことを意味します。発話によって再生を中断する場合は、voice.realtime.bargeInを有効にしてください。barge-in ignored ... outputActive=falseは、Discord またはプロバイダーの VAD が発話を報告したものの、OpenClaw に中断対象のアクティブな再生がなかったことを意味します。これによって音声が打ち切られることはありません。
voice.model の LLM ルート認証、tools.media.audio の STT 認証、tts/voice.tts の TTS 認証、および voice.realtime.providers またはプロバイダーの通常の認証設定によるリアルタイムプロバイダー認証です。
ボイスメッセージ
Discord のボイスメッセージには波形プレビューが表示され、OGG/Opus 音声が必要です。OpenClaw は波形を自動生成しますが、検査と変換のために Gateway ホスト上のffmpeg と ffprobe が必要です。
- ローカルファイルパスを指定してください(URL は拒否されます)。
- テキストコンテンツは省略してください(Discord は同じペイロード内のテキストとボイスメッセージを拒否します)。
- 任意の音声形式を使用できます。OpenClaw は必要に応じて OGG/Opus に変換します。
トラブルシューティング
許可されていないインテントが使用された、またはボットにギルドメッセージが表示されない
許可されていないインテントが使用された、またはボットにギルドメッセージが表示されない
- Message Content Intent を有効にする
- ユーザーまたはメンバーの解決に依存する場合は Server Members Intent を有効にする
- インテントを変更した後に Gateway を再起動する
ギルドメッセージが予期せずブロックされる
ギルドメッセージが予期せずブロックされる
groupPolicyを確認するchannels.discord.guilds配下のギルド許可リストを確認する- ギルドの
channelsマップが存在する場合、一覧にあるチャンネルのみが許可される requireMentionの動作とメンションパターンを確認する
メンション必須を false にしてもブロックされる
メンション必須を false にしてもブロックされる
- 一致するギルドまたはチャンネルの許可リストがない
groupPolicy="allowlist" requireMentionが誤った場所に設定されている(channels.discord.guildsまたはチャンネルエントリ配下に配置する必要があります)- 送信者がギルドまたはチャンネルの
users許可リストによってブロックされている
長時間実行される Discord ターンまたは重複した返信
長時間実行される Discord ターンまたは重複した返信
Slow listener detected ...stuck session: sessionKey=agent:...:discord:... state=processing ...
Gateway メタデータ検索のタイムアウト警告
Gateway メタデータ検索のタイムアウト警告
/gateway/bot メタデータを取得します。一時的な失敗時には Discord のデフォルト Gateway URL にフォールバックし、ログ出力はレート制限されます。メタデータのタイムアウトはデフォルトで 30 秒です。通常とは異なるホスト環境では、OPENCLAW_DISCORD_GATEWAY_INFO_TIMEOUT_MS で上書きできます。Gateway READY タイムアウトによる再起動
Gateway READY タイムアウトによる再起動
READY イベントを待機します。起動を時間差で行う複数アカウント構成では、デフォルトより長い起動時 READY 待機時間が必要になる場合があります。起動時は 15 秒、ランタイム再接続時は 30 秒待機します。通常とは異なるホスト環境向けに、OPENCLAW_DISCORD_READY_TIMEOUT_MS と OPENCLAW_DISCORD_RUNTIME_READY_TIMEOUT_MS も引き続き使用できます。権限監査の不一致
権限監査の不一致
channels status --probe の権限チェックは、数値のチャンネル ID でのみ機能します。スラッグキーを使用している場合でもランタイムの照合は機能しますが、プローブでは権限を完全に検証できません。DM とペアリングの問題
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" を推奨します。OpenClaw には共有のボットループ保護も同梱されています。allowBots によってボットが作成したメッセージがディスパッチに到達できる場合、Discord は受信イベントを (account, channel, bot pair) のファクトにマッピングし、汎用のペアガードは設定されたイベント予算を超えたペアを抑制します。このガードは、以前は Discord のレート制限によって停止する必要があった、制御不能な 2 ボット間ループを防ぎます。単一ボットのデプロイや、予算内に収まる単発のボット返信には影響しません。デフォルト設定(allowBots が設定されている場合に有効):maxEventsPerWindow: 20— ボットペアはスライディングウィンドウ内で 20 件のメッセージを交換可能windowSeconds: 60— スライディングウィンドウの長さcooldownSeconds: 60— 予算を超えると、どちらの方向でも以降のボット間メッセージはすべて 1 分間破棄される
channels.defaults.botLoopProtection 配下で一度設定し、正当なワークフローでより大きな余裕が必要な場合に Discord 側で上書きします。優先順位は次のとおりです:channels.discord.accounts.<account>.botLoopProtectionchannels.discord.botLoopProtectionchannels.defaults.botLoopProtection- 組み込みのデフォルト
maxEventsPerWindow、windowSeconds、cooldownSeconds キーを使用します。DecryptionFailed(...) による音声 STT の欠落
DecryptionFailed(...) による音声 STT の欠落
- Discord 音声受信の復旧ロジックが含まれるよう、OpenClaw を最新の状態(
openclaw update)に保つ channels.discord.voice.daveEncryption=true(デフォルト)を確認するchannels.discord.voice.decryptionFailureTolerance=24(アップストリームのデフォルト)から開始し、必要な場合にのみ調整する- ログで以下を確認する:
discord voice: DAVE decrypt failures detecteddiscord voice: repeated decrypt failures; attempting rejoin
- 自動再参加後も失敗が続く場合は、ログを収集し、discord.js #11419 および discord.js #11449 にあるアップストリームの DAVE 受信履歴と比較する
設定リファレンス
主要リファレンス:設定リファレンス - Discord。重要度の高い Discord フィールド
重要度の高い Discord フィールド
- 起動/認証:
enabled、token、applicationId、accounts.*、allowBots - ポリシー:
groupPolicy、dmPolicy、allowFrom、dm.*、guilds.*、guilds.*.channels.* - コマンド:
commands.native、commands.useAccessGroups(グローバル)、configWrites、slashCommand.ephemeral - Gateway:
proxy - 返信/履歴:
replyToMode、historyLimit、dmHistoryLimit、dms.*.historyLimit - 配信:
textChunkLimit(デフォルト2000)、maxLinesPerMessage(デフォルト17) - ストリーミング:
streaming.mode、streaming.chunkMode、streaming.preview.*、streaming.progress.*、streaming.block.*(レガシーのフラットなstreamMode、draftChunk、blockStreaming、blockStreamingCoalesce、chunkModeキーは、openclaw doctor --fixによってstreaming.*に移行されます) - メディア:
mediaMaxMb(Discord への送信アップロードを制限、デフォルト100) - アクション:
actions.* - プレゼンス:
activity、status、activityType、activityUrl、autoPresence.* - UI:
ui.components.accentColor - 機能:
threadBindings、トップレベルのbindings[](type: "acp")、pluralkit、execApprovals、intents、agentComponents.enabled、agentComponents.ttlMs、activities、heartbeat、responsePrefix
Discord Activities
channels.discord.activities を設定すると、エージェントが Discord 内で開く自己完結型 HTML ウィジェットを投稿できるようになります。このブロックはオプトインです。存在しない場合、OpenClaw は Activity のルート、ツール、インタラクションハンドラーを登録しません。Developer Portal、トンネル、セキュリティ、トラブルシューティングの設定については、Discord Activities を参照してください。
activities.clientSecret:Discord アプリケーションの OAuth2 クライアントシークレット。DISCORD_CLIENT_SECRETにフォールバックしますactivities.applicationId:任意の Activity アプリケーション ID。デフォルトでは Gateway 起動時に取得したボットアプリケーション ID を使用します
安全性と運用
- ボットトークンはシークレットとして扱ってください(監視環境では
DISCORD_BOT_TOKENを推奨)。 - Discord の権限は最小権限で付与してください。
- コマンドのデプロイまたは状態が古い場合は、Gateway を再起動し、
openclaw channels status --probeでもう一度確認してください。