Voice Mode in Hermes Agent: CLI, Telegram, Discord Voice Channels

Connects microphone input and TTS output to Hermes Agent for voice interaction across CLI, Telegram, and Discord.

Devices & Environmentsintermediate16 min readVerified Jul 27, 2026
Voice Mode in Hermes Agent: CLI, Telegram, Discord Voice Channels

This page covers the voice mode integration in Hermes Agent, which connects microphone input and audio output to the Hermes Agent runtime. With voice mode enabled, an agent can listen to spoken commands, transcribe them via Whisper, process them through the LLM pipeline, and speak replies back using text-to-speech (TTS), all within the CLI, Telegram, Discord text channels, or Discord voice channels.

What It Does

Voice mode in Hermes Agent provides the following concrete capabilities, as documented in the official guide:

  • Interactive Voice (CLI): Press Ctrl+B to start recording, the agent auto-detects silence and responds with a spoken reply when TTS is enabled.
  • Auto Voice Reply (Telegram and Discord): The agent sends spoken audio alongside text responses in messaging platforms.
  • Voice Channel (Discord): The bot joins a Discord voice channel, listens to users speaking, transcribes their speech, processes it through the agent, and speaks the reply back in the voice channel.
  • Streaming TTS: The agent speaks its reply sentence-by-sentence as it generates text, so you do not wait for the full response.
  • Barge-in: You can interrupt the agent mid-speech by talking over it, typing, or pressing the record key. The agent knows it was interrupted and can react naturally.
  • Hallucination Filter: Whisper-generated phantom text from silence or background noise is filtered out using a set of 26 known hallucination phrases and a regex pattern.
  • Silence Detection: A two-stage algorithm detects when you have finished speaking, with configurable thresholds and duration.
  • Multiple TTS Providers: Edge TTS (free, no key), ElevenLabs (premium), OpenAI TTS, NeuTTS (local), and others.
  • Multiple STT Providers: Local (faster-whisper, no key), Groq, OpenAI, Mistral, xAI.
  • Persistent Voice Mode Settings: Voice mode state (off, voice_only, all) is persisted across gateway restarts.

These capabilities are available across three platforms: CLI, Telegram, and Discord. The CLI and TUI share identical behavior for voice commands, VAD silence detection, streaming TTS, and the hallucination filter. The TUI additionally forwards crash-forensic logs to ~/.hermes/logs/ so push-to-talk failures on exotic audio backends can be reported with a full stack trace.

Setup

Prerequisites

Before using voice features, ensure you have:

  1. Hermes Agent installed via the install script (see Installation).
  2. An LLM provider configured. Run hermes model or set your preferred provider credentials in ~/.hermes/.env.
  3. A working base setup. Run hermes to verify the agent responds to text before enabling voice.

The ~/.hermes/ directory and default config.yaml are created automatically the first time you run hermes. You only need to create ~/.hermes/.env manually for API keys.

A paid Nous Portal subscription supplies the LLM and OpenAI TTS via the Tool Gateway, meaning no separate OpenAI key is needed. On a fresh install, hermes setup --portal wires both up at once.

Python Packages

Install the required Python packages using uv inside the Hermes Agent directory:

# CLI voice mode (microphone + audio playback)
cd ~/.hermes/hermes-agent && uv pip install -e ".[voice]"

# Discord + Telegram messaging (includes discord.py[voice] for VC support)
cd ~/.hermes/hermes-agent && uv pip install -e ".[messaging]"

# Premium TTS (ElevenLabs)
cd ~/.hermes/hermes-agent && uv pip install -e ".[tts-premium]"

# Local TTS (NeuTTS, optional)
python -m pip install -U neutts[all]

# Everything at once
cd ~/.hermes/hermes-agent && uv pip install -e ".[all]"

The extra packages required for each feature are:

  • voice: sounddevice, numpy for CLI voice mode.
  • messaging: discord.py[voice], python-telegram-bot, aiohttp for Discord and Telegram bots.
  • tts-premium: elevenlabs for ElevenLabs TTS provider.

Optional local TTS provider: install neutts separately with python -m pip install -U neutts[all]. On first use it downloads the model automatically.

Note that discord.py[voice] installs PyNaCl (for voice encryption) and opus bindings automatically. This is required for Discord voice channel support.

System Dependencies

Install system-level dependencies:

# macOS
brew install portaudio ffmpeg opus
brew install espeak-ng # for NeuTTS

# Ubuntu/Debian
sudo apt install portaudio19-dev ffmpeg libopus0
sudo apt install espeak-ng # for NeuTTS

The dependencies and their purposes are:

  • PortAudio: Microphone input and audio playback. Required for CLI voice mode.
  • ffmpeg: Audio format conversion (MP3 to Opus, PCM to WAV). Required for all platforms.
  • Opus: Discord voice codec. Required for Discord voice channels.
  • espeak-ng: Phonemizer backend. Required for the local NeuTTS provider.

API Keys

Add the following to ~/.hermes/.env:

# Speech-to-Text, local provider needs NO key at all
# pip install faster-whisper # Free, runs locally, recommended
GROQ_API_KEY = your-key # Groq Whisper, fast, free tier (cloud)
VOICE_TOOLS_OPENAI_KEY = your-key # OpenAI Whisper, paid (cloud)

# Text-to-Speech (optional, Edge TTS and NeuTTS work without any key)
ELEVENLABS_API_KEY = *** # ElevenLabs, premium quality
# VOICE_TOOLS_OPENAI_KEY above also enables OpenAI TTS

If faster-whisper is installed, voice mode works with zero API keys for STT. The model (~150 MB for base) downloads automatically on first use.

Discord Voice Channel Setup

1. Discord Bot Permissions

If you already have a Discord bot set up for text, you need to add voice permissions. Go to the Discord Developer Portal, select your application, then navigate to Installation > Default Install Settings > Guild Install. Add these permissions to the existing text permissions:

  • Connect: Join voice channels.
  • Speak: Play TTS audio in voice channels.
  • Use Voice Activity: Detect when users are speaking (recommended).

The updated permissions integer for text + voice is 309240908864 (all text permissions plus Connect and Speak). The text-only integer is 309237763136.

Re-invite the bot with the updated permissions URL:

https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot+applications.commands&permissions=309240908864

Replace YOUR_APP_ID with your Application ID from the Developer Portal. Re-inviting the bot to a server it is already in will update its permissions without removing it. You will not lose any data or configuration.

2. Privileged Gateway Intents

In the Developer Portal, go to your application > Bot > Privileged Gateway Intents and enable all three:

  • Presence Intent: Detect user online/offline status.
  • Server Members Intent: Resolve usernames in DISCORD_ALLOWED_USERS to numeric IDs (conditional).
  • Message Content Intent: Read text message content in channels.

Message Content Intent is required. Server Members Intent is only needed if your DISCORD_ALLOWED_USERS list uses usernames. If you use numeric user IDs, you can leave it off. Voice-channel SSRC to user_id mapping comes from Discord's SPEAKING opcode on the voice websocket and does not require the Server Members Intent.

3. Opus Codec

The Opus codec library must be installed on the machine running the gateway:

# macOS (Homebrew)
brew install opus

# Ubuntu/Debian
sudo apt install libopus0

The bot auto-loads the codec from:

  • macOS: /opt/homebrew/lib/libopus.dylib
  • Linux: libopus.so.0

4. Environment Variables for Discord

Add to ~/.hermes/.env:

# Discord bot (already configured for text)
DISCORD_BOT_TOKEN = your-bot-token
DISCORD_ALLOWED_USERS = your-user-id

# STT, local provider needs no key (pip install faster-whisper)
# GROQ_API_KEY=your-key # Alternative: cloud-based, fast, free tier

# TTS, optional. Edge TTS and NeuTTS need no key.
# ELEVENLABS_API_KEY=*** # Premium quality
# VOICE_TOOLS_OPENAI_KEY=*** # OpenAI TTS / Whisper

Start the Gateway

Start the gateway to connect to your messaging platforms:

hermes gateway # Start the gateway (connects to configured platforms)
hermes gateway setup # Interactive setup wizard for first-time configuration

The bot should come online in Discord within a few seconds.

Configuration Reference

config.yaml

The following configuration options are available in ~/.hermes/config.yaml:

# Voice recording (CLI)
voice:
  record_key: "ctrl+b" # Key to start/stop recording
  max_recording_seconds: 120 # Maximum recording length
  auto_tts: false # Auto-enable TTS when voice mode starts
  beep_enabled: true # Play record start/stop beeps
  silence_threshold: 200 # RMS level (0-32767) below which counts as silence
  silence_duration: 3.0 # Seconds of silence before auto-stop

# Speech-to-Text
stt:
  enabled: true # set to false to skip auto-transcription, # the gateway still caches the audio file and
                 # passes its path to the agent as part of the
                 # inbound message, useful for custom pipelines
                 # (diarization, alignment, archival, etc.)
  provider: "local" # "local" (free) | "groq" | "openai" | "mistral" | "xai"
  local:
    model: "base" # tiny, base, small, medium, large-v3
    # model: "whisper-1" # Legacy: used when provider is not set

# Text-to-Speech
tts:
  provider: "edge" # "edge" (free) | "elevenlabs" | "openai" | "neutts" | "minimax" | "mistral" | "gemini" | "xai" | "kittentts" | "piper"
  edge:
    voice: "en-US-AriaNeural" # 322 voices, 74 languages
  elevenlabs:
    voice_id: "pNInz6obpgDQGcFmaJgB" # Adam
    model_id: "eleven_multilingual_v2"
  openai:
    model: "gpt-4o-mini-tts"
    voice: "alloy" # alloy, echo, fable, onyx, nova, shimmer
    base_url: "https://api.openai.com/v1" # optional: override for self-hosted or OpenAI-compatible endpoints
  neutts:
    ref_audio: ''
    ref_text: ''
    model: neuphonic/neutts-air-q4-gguf
    device: cpu

Environment Variables

VariablePurposeRequired
GROQ_API_KEYGroq Whisper STT (fast, free tier)No (if using local STT)
VOICE_TOOLS_OPENAI_KEYOpenAI Whisper STT and OpenAI TTSNo (if using local STT/TTS)
STT_GROQ_MODELOverride default Groq STT model (e.g., whisper-large-v3-turbo)No
STT_OPENAI_MODELOverride default OpenAI STT model (e.g., whisper-1)No
GROQ_BASE_URLCustom Groq endpointNo
STT_OPENAI_BASE_URLCustom OpenAI STT endpointNo
ELEVENLABS_API_KEYElevenLabs TTS (premium quality)No (if using Edge TTS or NeuTTS)
DISCORD_BOT_TOKENDiscord bot tokenYes (for Discord)
DISCORD_ALLOWED_USERSComma-separated user IDs or usernames allowed to interact via voiceYes (for Discord voice channels)
DISCORD_REQUIRE_MENTIONSet to false to disable @mention requirement in server channelsNo
DISCORD_FREE_RESPONSE_CHANNELSComma-separated channel IDs where no @mention is neededNo

STT Provider Comparison

ProviderModelSpeedQualityCostAPI Key Required
LocalbaseFast (depends on CPU/GPU)GoodFreeNo
LocalsmallMediumBetterFreeNo
Locallarge-v3SlowBestFreeNo
Groqwhisper-large-v3-turboVery fast (~0.5s)GoodFree tierYes
Groqwhisper-large-v3Fast (~1s)BetterFree tierYes
OpenAIwhisper-1Fast (~1s)GoodPaidYes
OpenAIgpt-4o-transcribeMedium (~2s)BestPaidYes
Mistralvoxtral-mini-latestFastGoodPaidYes
xAIgrok-sttFastGoodPaidYes

Provider priority (automatic fallback): local > groq > openai.

TTS Provider Comparison

ProviderQualityCostLatencyKey Required
Edge TTSGoodFree~1sNo
ElevenLabsExcellentPaid~2sYes
OpenAI TTSGoodPaid~1.5sYes
NeuTTSGoodFreeDepends on CPU/GPUNo

NeuTTS uses the tts.neutts config block in config.yaml.

How It Works

Diagram: How It Works

CLI Voice Mode

Start the CLI with hermes and enable voice mode with /voice on. Press Ctrl+B (configurable via voice.record_key in config.yaml, default ctrl+b). A beep plays (880Hz) and recording starts. A live audio level bar shows your input: ● [▁▂▃▅▇▇▅▂] ❯. After 3 seconds of silence (configurable via voice.silence_duration), recording auto-stops. Two beeps play (660Hz) confirming the recording ended. The audio is transcribed via Whisper and sent to the agent. If TTS is enabled, the agent's reply is spoken aloud. Recording automatically restarts, allowing you to speak again without pressing any key. This loop continues until you press Ctrl+B during recording (exits continuous mode) or 3 consecutive recordings detect no speech.

Silence Detection

The two-stage algorithm works as follows:

  • Speech confirmation: Waits for audio above the RMS threshold (200, configurable via voice.silence_threshold) for at least 0.3 seconds, tolerating brief dips between syllables.
  • End detection: Once speech is confirmed, triggers after 3.0 seconds of continuous silence (configurable via voice.silence_duration).

If no speech is detected at all for 15 seconds, recording stops automatically. Both silence_threshold and silence_duration are configurable in config.yaml. You can also disable the record start/stop beeps with voice.beep_enabled: false.

Streaming TTS

When TTS is enabled, the agent speaks its reply sentence-by-sentence as it generates text. This works with every TTS provider. The pipeline buffers text deltas into complete sentences (minimum 20 characters), strips markdown formatting, emoji, and code blocks, then plays audio per sentence in real-time. Providers with a chunked PCM API (ElevenLabs, OpenAI) stream raw audio for the lowest time-to-first-word. Every other provider (including the default Edge) synthesizes and plays each sentence as it completes. The same pipeline runs in the classic CLI, the TUI, and the desktop app. In a desktop voice conversation, the reply text is fed live into a per-reply speech WebSocket as the model generates it, so speech overlaps generation with one socket and one audio clock per reply, no per-sentence connection gaps.

Barge-in

You can interrupt the agent mid-speech in two ways:

  • Talk over it: In continuous voice mode, a voice-activity monitor listens while the agent speaks and cuts playback the moment you start talking, then goes straight back to recording. The detector calibrates its noise floor against the playback itself, so speaker bleed does not self-trigger. Disable with voice.barge_in: false in config.yaml.
  • Type or press the record key: Sending a new message or hitting the push-to-talk key stops playback instantly on every surface.

The agent knows it was interrupted: the next message carries a short note telling the model its spoken reply was cut off, so it can react naturally (e.g., "rude!") or pick up where it left off instead of being oblivious.

Hallucination Filter

Whisper sometimes generates phantom text from silence or background noise (e.g., "Thank you for watching", "Subscribe"). The agent filters these out using a set of 26 known hallucination phrases across multiple languages, plus a regex pattern that catches repetitive variations.

Discord Voice Channels

When the bot joins a voice channel, it listens to each user's audio stream independently. It detects silence: 1.5 seconds of silence after at least 0.5 seconds of speech triggers processing. The audio is transcribed via Whisper STT (local, Groq, or OpenAI), then processed through the full agent pipeline (session, tools, memory). The reply is spoken back in the voice channel via TTS.

Transcripts appear in the text channel where /voice join was issued, formatted as [Voice] @user: what you said. Agent responses are sent as text in the channel AND spoken in the VC. The bot automatically pauses its audio listener while playing TTS replies, preventing it from hearing and re-processing its own output (echo prevention).

Discord: Channels vs DMs

The bot supports two interaction modes on Discord:

  • Direct Message (DM): Open the bot's profile and click "Message". No @mention needed. Voice replies and all commands work the same as in channels. Recommended for personal use.
  • Server Channel: Type in a text channel where the bot is present. You must @mention the bot (e.g., @hermesbyt4 hello). Make sure you select the bot user from the mention popup, not the role with the same name.

To disable the mention requirement in server channels, add to ~/.hermes/.env:

DISCORD_REQUIRE_MENTION = false

Or set specific channels as free-response (no mention needed):

DISCORD_FREE_RESPONSE_CHANNELS = 123456789,987654321

Gateway Voice Reply (Telegram and Discord)

The following commands work in both Telegram and Discord (DMs and text channels):

  • /voice: Toggle voice mode on/off.
  • /voice on: Voice replies only when you send a voice message.
  • /voice tts: Voice replies for ALL messages.
  • /voice off: Disable voice replies.
  • /voice status: Show current setting.

The voice mode setting is persisted across gateway restarts.

Modes

ModeCommandBehavior
off/voice offText only (default)
voice_only/voice onSpeaks reply only when you send a voice message
all/voice ttsSpeaks reply to every message

Platform Delivery

  • Telegram: Voice bubble (Opus/OGG). Plays inline in chat. ffmpeg converts MP3 to Opus if needed.
  • Discord: Native voice bubble (Opus/OGG). Plays inline like a user voice message. Falls back to file attachment if voice bubble API fails.

Discord Voice Channel Commands

Use these in the Discord text channel where the bot is present:

  • /voice join: Bot joins your current voice channel.
  • /voice channel: Alias for /voice join.
  • /voice leave: Bot disconnects from voice channel.
  • /voice status: Show voice mode and connected channel.

You must be in a voice channel before running /voice join. The bot joins the same VC you are in.

Access Control

Only users listed in DISCORD_ALLOWED_USERS can interact via voice. Other users' audio is silently ignored.

# ~/.hermes/.env
DISCORD_ALLOWED_USERS = 284102345871466496

Requirements and Limitations

Prerequisites

  • Hermes Agent installed via the install script.
  • An LLM provider configured (via hermes model or ~/.hermes/.env).
  • A working base setup (agent responds to text).

Supported Platforms

  • CLI: Classic CLI (hermes chat) and TUI (hermes --tui).
  • Telegram: Via the gateway.
  • Discord: Text channels, DMs, and voice channels.

Python Version

Hermes Agent uses uv for package management. The specific Python version is not stated in the sources, but the installation commands assume a working Python environment with uv.

Known Limitations

  • Discord voice channels: Only users listed in DISCORD_ALLOWED_USERS can interact via voice. Other users' audio is silently ignored.
  • Server Members Intent: Only needed if DISCORD_ALLOWED_USERS uses usernames. If numeric user IDs are used, it can be left off.
  • Opus codec: Must be installed on the machine running the gateway. Auto-loads from specific paths on macOS and Linux.
  • Docker: If running Hermes inside Docker on a Linux desktop, the container needs access to the host audio socket. See the Docker audio bridge notes for a PulseAudio/PipeWire-compatible setup.
  • Hallucination Filter: Catches most cases automatically, but if phantom transcripts persist, a quieter environment, adjusting silence_threshold, or using a different STT model may help.
  • Barge-in: Can be disabled with voice.barge_in: false in config.yaml.
  • Recording: Maximum recording length is configurable via voice.max_recording_seconds (default 120).
  • STT Provider Priority: Automatic fallback order is local > groq > openai.
  • TTS: Edge TTS is the default fallback if no API key is configured.

Troubleshooting

"No audio device found" (CLI)

PortAudio is not installed. Install it:

brew install portaudio # macOS
sudo apt install portaudio19-dev # Ubuntu

If running Hermes inside Docker on a Linux desktop, the container also needs access to your host audio socket. See the Docker audio bridge notes for a PulseAudio/PipeWire-compatible setup.

Bot doesn't respond in Discord server channels

The bot requires an @mention by default in server channels. Make sure you:

  • Type @ and select the bot user (with the discriminator), not the role with the same name.
  • Or use DMs instead (no mention needed).
  • Or set DISCORD_REQUIRE_MENTION=false in ~/.hermes/.env.

Bot joins VC but doesn't hear me

  • Check your Discord user ID is in DISCORD_ALLOWED_USERS.
  • Make sure you are not muted in Discord.
  • The bot needs a SPEAKING event from Discord before it can map your audio. Start speaking within a few seconds of joining.

Bot hears me but doesn't respond

  • Verify STT is available: install faster-whisper (no key needed) or set GROQ_API_KEY / VOICE_TOOLS_OPENAI_KEY.
  • Check the LLM model is configured and accessible.
  • Review gateway logs: tail -f ~/.hermes/logs/gateway.log.

Bot responds in text but not in voice channel

  • TTS provider may be failing. Check API key and quota.
  • Edge TTS (free, no key) is the default fallback.
  • Check logs for TTS errors.

Whisper returns garbage text

The hallucination filter catches most cases automatically. If you are still getting phantom transcripts:

  • Use a quieter environment.
  • Adjust silence_threshold in config (higher = less sensitive).
  • Try a different STT model.

Sources & References

This page was researched from 1 independent source, combined and verified for completeness.

  • 1.
    Voice ModeOfficial documentation · primary source
Newsletter

The #1 AI Newsletter

The most important ai updates, guides, and fixes — one weekly email.

No spam, unsubscribe anytime. Privacy policy

Other Hermes Agent integrations