Discord Voice Transcripts and Automatic Meeting Notes

Learn how to capture speech from a Discord voice channel and generate transcripts and meeting notes. This guide is for operators and developers configuring the transcripts agent tool and autoStart sources.

Read this when

  • Capturing transcripts from a Discord voice channel
  • Configuring a listen-only bot that writes meeting notes

Capture speech from a Discord voice channel and produce transcripts and meeting notes from it.

Capture voice transcripts

voice.autoJoin governs presence and conversation only. It does not begin persistent recording. To capture audio, start it explicitly through the transcripts agent tool, or set up an existing transcripts.autoStart source. Configuration and inspection commands are covered in Transcripts CLI.

An agent with the right authorization can begin capture like this:

{
  "action": "start",
  "providerId": "discord-voice",
  "accountId": "work",
  "guildId": "123456789012345678",
  "channelId": "234567890123456789"
}

Once started, capture stays subscribed to that specific account, guild, and channel until it is stopped. It binds to a matching voice connection that already exists, without taking over conversation or occupancy ownership. Normal voice conversation stays available whenever the capture matches the account's configured voice.autoJoin target, no matter which one started first. If voice.autoJoin[].whenOccupied: true is set, continuous capture keeps waiting through empty rooms and picks up again on the next normal join. It also survives same-channel connection recovery and replacement of the voice manager for that same account. An existing connection is never moved to a different channel by capture.

An authorized capture logs the participants in the chosen room regardless of command access. Conversation, agent tools, and active-run controls remain governed by guild/channel users and roles, commands.ownerAllowFrom, and wake-name gates. Recording grants none of those permissions. When protected playback is running, speech is still recorded, and playback is neither interrupted nor answered. If OpenClaw subscribes while someone is already talking, the speech that is available gets recorded, but no conversational input or commands are produced. For normal conversation, a fresh receive stream is needed after the current one ends. Short pauses within voice.captureSilenceGraceMs preserve the current stream and its record-only behavior.

Complete recording coverage depends on batch audio understanding. Each speaker gets one audio stream, transcribed in batch along with the receiver's user ID, a display label resolved independently, and the audio-ingress time. The same decoded audio can also drive realtime conversation for authorized speakers. Recording keeps going even when every realtime speaker connection is busy. Realtime speech then costs one extra batch transcription, which keeps durable recording decoupled from realtime provider delivery and conversation authorization. Continuous speech is divided into contiguous, bounded audio uploads. Those are segments of one capture session, not separate meetings. Under stt-tts, authorized conversation reuses that batch transcription and responds only after the normal end of speech.

Where batch transcription is turned off or no batch backend exists, realtime-only deployments can still record final text from their active per-speaker connections. This restricted path demands that each submitted audio packet belong to the same active capture. It waits for all batch work to settle and never duplicates a batch result that succeeded or was silent. Fallback recording text cannot be produced from mixed capture input, failed or oversized audio, or provider continuity resets. Only speakers admitted to realtime conversation are covered, so this is not independent room recording. /vc status displays a coverage warning and points operators to audio transcription configuration. If capture is started with tools.media.audio.enabled set to false, an active realtime conversation must already exist, or an enablement error is returned. Per speaker connection, pending realtime finals are capped at 1 MiB and 1,000 entries.

Recording is separate from conversation authorization and replies. A voice connection allows eight unfinished voice requests, and each request may hold at most 1 MiB of decoded audio awaiting admission. Batch requests keep no more than 1 MiB of transcript text and 1,000 segments. Hitting a limit throws away that whole voice request while recording carries on. Speak again once pending requests have finished, or keep the utterance shorter. Across the Gateway process, pending Discord recording work is limited to 128 chunks and 64 MiB of WAV data. When transcription or note saving falls behind, the affected receive stream halts but the capture stays registered. This budget persists across voice reconnections. Let pending audio processing complete, then speak again. Suppose transcription fails or drops input (an oversized upload, for example), a chunk loses command access, or starting or stopping capture discards an uncaptured fragment under the minimum duration. In those cases notes already saved stay saved, but no agent reply or active-run control is triggered by the incomplete utterance. Restored access covers later utterances only, not the missing chunks. A finished transcription that yields no text is valid and does not invalidate the utterance.

If no auto-join target is configured and no conversation is active in that guild, a manual capture joins quietly in transcript-only mode. A later /vc join turns on normal conversation for that connection. A capture aimed at a different channel stays registered without seizing the configured or active conversation, even when a recorder reconnect is queued behind a newer conversation join.

To stop, use the transcripts tool's stop action together with the returned sessionId. Stopping works even while disconnected, and it will not disconnect a connection that conversation owns. Audio already received can finish recording through a connection transition as long as the same capture is still active. A stop or replacement cancels pending publication, so old audio cannot flow into a new capture. When a new capture starts for the same registered source, the subscription transfers without reconnecting or redoing target validation, even while it is dormant. Until explicitly stopped, continuous capture may span several room occupations. For automatic meeting boundaries, use transcripts.autoStart[].whenOccupied as described below. Summaries are never posted to Discord automatically.

Meeting notes

The discord-voice transcripts provider keeps a note-taking bot in a voice channel only while humans are there. With no conversational auto-join target and no active conversation, capture is listen-only and no realtime provider is started. If capture attaches to an existing conversation, that conversation keeps its ownership. Turn on Discord voice, set up an authenticated speech-to-text provider, and add a transcript source driven by occupancy:

{
  channels: {
    discord: {
      voice: { enabled: true },
    },
  },
  tools: {
    media: {
      models: [{ provider: "openai", model: "gpt-4o-transcribe", capabilities: ["audio"] }],
      audio: { enabled: true },
    },
  },
  transcripts: {
    autoStart: [
      {
        providerId: "discord-voice",
        guildId: "123456789012345678",
        channelId: "234567890123456789",
        whenOccupied: true,
      },
    ],
  },
}

In the target channel the bot requires Connect permission, plus the GuildVoiceStates intent, which voice.enabled: true turns on by default. Never disable channels.discord.intents.voiceStates explicitly. The channel must fall within any configured voice.allowedChannels allowlist. For this note-taking recipe, use transcripts.autoStart rather than conversational voice.autoJoin. Before enabling it, inform participants that the bot records and stores transcripts.

When several Discord accounts exist, add accountId to pick the voice-enabled bot, unless the configured default account resolves it without ambiguity. Each account and guild may have at most one occupancy-driven discord-voice entry, since the bot cannot capture more than one voice channel per guild. Conflicting entries added later are skipped with a warning.

The bot joins when a human arrives, including when the channel is already occupied at startup. Once the last human leaves, it waits 30 seconds before departing and generating notes. If someone returns during that grace period, capture continues. Episodes get generated session IDs, and any configured sessionId is ignored. A session stopped under 10 minutes ago can reopen for the same source after a Gateway restart or a short gap, provided its stored origin confirms a generated ID. Its ID, start time, and accumulated utterances are kept. Supplied IDs and legacy records with an unknown origin remain archived, and capture begins fresh without altering those notes.

Notes cover participants, an overview, decisions, action items, and risks. While capture runs, notes refresh roughly every five minutes when new speech has been saved. A silent room does not cause repeated summaries. Stopping capture drains received speech and saves the final notes. They rely on the agent's utility model, falling back to its primary model, and then to rule-based notes if model generation fails. Retrieve stored notes through the transcripts tool, the CLI, or the Control UI Meetings page. The tool's summarize action rebuilds notes from the stored transcript.

1,330 words · updated Oct 26, 2026