> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/moeru-ai/airi/llms.txt
> Use this file to discover all available pages before exploring further.

# Discord Integration

> Add AIRI to your Discord server with voice and text support

## Overview

The Discord integration allows AIRI to join voice channels, listen to users, transcribe speech, and respond with both text and voice. It supports slash commands, mentions, and direct messages.

## Features

* **Voice Channel Support**: Join voice channels and participate in conversations
* **Speech-to-Text**: Automatically transcribe user voice input
* **Text-to-Speech**: Respond with natural-sounding voice
* **Slash Commands**: Interactive commands like `/summon` and `/ping`
* **Text Chat**: Respond to mentions and DMs
* **Multi-Guild Support**: Work across multiple Discord servers simultaneously

## Prerequisites

* Node.js 18 or higher
* A Discord bot token
* OpenAI API key (for LLM and transcription)
* ElevenLabs API key (for TTS)
* AIRI server runtime running

## Setup

### 1. Create Discord Bot

1. Go to [Discord Developer Portal](https://discord.com/developers/applications)
2. Click **New Application**
3. Go to **Bot** section and click **Add Bot**
4. Enable these **Privileged Gateway Intents**:
   * Server Members Intent
   * Message Content Intent
5. Copy your **Bot Token**
6. Copy your **Application ID** (from General Information)

### 2. Invite Bot to Server

Use this URL, replacing `YOUR_CLIENT_ID` with your Application ID:

```
https://discord.com/api/oauth2/authorize?client_id=YOUR_CLIENT_ID&permissions=36703296&scope=bot%20applications.commands
```

**Required Permissions:**

* Read Messages/View Channels
* Send Messages
* Connect to Voice
* Speak in Voice
* Use Voice Activity

### 3. Configure Environment

Navigate to the Discord bot service:

```bash theme={null}
cd services/discord-bot
cp .env .env.local
```

Edit `.env.local`:

```bash theme={null}
# Discord Configuration
DISCORD_TOKEN='your-bot-token-here'
DISCORD_BOT_CLIENT_ID='your-application-id-here'

# AIRI Server Connection
AIRI_URL='ws://localhost:6121/ws'
AIRI_TOKEN='abcd'

# OpenAI Configuration
OPENAI_API_KEY='sk-...'
OPENAI_MODEL='gpt-4o'
OPENAI_API_BASE_URL='https://api.openai.com/v1'

# ElevenLabs Configuration (for TTS)
ELEVENLABS_API_KEY='your-elevenlabs-key'
ELEVENLABS_API_BASE_URL='https://api.elevenlabs.io/v1'
```

### 4. Install Dependencies

From the project root:

```bash theme={null}
pnpm install
```

### 5. Start the Bot

```bash theme={null}
pnpm run -F @proj-airi/discord-bot start
```

You should see:

```
Discord bot ready! User: YourBotName#1234
```

## Usage

### Voice Commands

1. Join a voice channel
2. Use the `/summon` command in any text channel
3. AIRI will join your voice channel
4. Start speaking - AIRI will transcribe and respond

<Note>
  AIRI uses Voice Activity Detection (VAD) to automatically detect when users are speaking.
</Note>

### Text Commands

**Slash Commands:**

* `/ping` - Check if the bot is responsive
* `/summon` - Invite AIRI to your current voice channel

**Mentions:**

Mention the bot in any channel:

```
@AIRI what's the weather like today?
```

**Direct Messages:**

Send a DM to the bot - no mention required.

## Code Examples

### Basic Adapter Setup

From `services/discord-bot/src/adapters/airi-adapter.ts:55`:

```typescript theme={null}
import { Client as AiriClient } from '@proj-airi/server-sdk'
import { Client, GatewayIntentBits } from 'discord.js'

export class DiscordAdapter {
  private airiClient: AiriClient
  private discordClient: Client

  constructor(config: DiscordAdapterConfig) {
    // Initialize Discord client
    this.discordClient = new Client({
      intents: [
        GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildVoiceStates,
        GatewayIntentBits.GuildMessages,
        GatewayIntentBits.MessageContent,
        GatewayIntentBits.DirectMessages,
      ],
    })

    // Initialize AIRI client
    this.airiClient = new AiriClient({
      name: 'discord',
      possibleEvents: [
        'input:text',
        'input:text:voice',
        'input:voice',
        'module:configure',
        'output:gen-ai:chat:message',
      ],
      token: config.airiToken,
      url: config.airiUrl,
    })
  }
}
```

### Sending User Input to AIRI

From `services/discord-bot/src/adapters/airi-adapter.ts:261`:

```typescript theme={null}
// Handle text messages
this.discordClient.on(Events.MessageCreate, async (message) => {
  if (message.author.bot) return
  
  const isMentioned = message.mentions.has(this.discordClient.user)
  const isDM = !message.guild
  
  if (isMentioned || isDM) {
    const content = message.content
      .replace(/<@!?\d+>/g, '')
      .trim()
    
    // Send to AIRI
    this.airiClient.send({
      type: 'input:text',
      data: {
        text: content,
        discord: {
          channelId: message.channelId,
          guildId: message.guildId,
          guildMember: {
            id: message.author.id,
            displayName: message.member?.displayName,
          },
        },
      },
    })
  }
})
```

### Receiving Responses from AIRI

From `services/discord-bot/src/adapters/airi-adapter.ts:159`:

```typescript theme={null}
// Handle output from AIRI system
this.airiClient.onEvent('output:gen-ai:chat:message', async (event) => {
  const message = event.data.message
  const discordContext = event.data['gen-ai:chat'].input.data.discord
  
  if (message?.content && discordContext?.channelId) {
    const channel = await this.discordClient.channels.fetch(
      discordContext.channelId
    )
    
    if (channel?.isTextBased()) {
      // Split long messages if needed
      if (message.content.length <= 2000) {
        await channel.send(message.content)
      } else {
        // Handle chunking for messages over 2000 chars
        // ...
      }
    }
  }
})
```

### Voice Channel Integration

From `services/discord-bot/src/bots/discord/commands/summon.ts:157`:

```typescript theme={null}
import { joinVoiceChannel, createAudioPlayer } from '@discordjs/voice'

async joinChannel(interaction, channel) {
  const connection = joinVoiceChannel({
    channelId: channel.id,
    guildId: channel.guild.id,
    adapterCreator: channel.guild.voiceAdapterCreator,
    selfDeaf: false,
    selfMute: false,
  })

  // Wait for connection to be ready
  await Promise.race([
    entersState(connection, VoiceConnectionStatus.Ready, 20_000),
    entersState(connection, VoiceConnectionStatus.Signalling, 20_000),
  ])

  // Listen to voice data
  connection.receiver.speaking.on('start', (userId) => {
    this.monitorMember(userId, channel.id)
  })
}
```

## Configuration

### Dynamic Reconfiguration

The Discord bot supports runtime configuration updates via the `module:configure` event:

```typescript theme={null}
this.airiClient.onEvent('module:configure', async (event) => {
  const { token, enabled } = event.data.config
  
  if (enabled === false) {
    await this.discordClient.destroy()
    return
  }
  
  if (token && this.discordToken !== token) {
    this.discordToken = token
    await this.discordClient.login(this.discordToken)
  }
})
```

### Voice Settings

* **Sample Rate**: 48000 Hz (Opus)
* **Channels**: Stereo
* **Transcription**: OpenAI Whisper
* **TTS**: ElevenLabs

## Troubleshooting

### Bot is not responding

1. Check the bot is online in Discord
2. Verify the bot has permissions in the channel
3. Check logs for connection errors

### Voice not working

1. Ensure you have `ELEVENLABS_API_KEY` configured
2. Verify the bot has "Connect" and "Speak" permissions
3. Check that voice gateway is connected in logs

### Commands not showing

1. Commands are registered when the bot starts
2. Wait a few minutes for Discord to sync
3. Try reinviting the bot with the correct scope

## Next Steps

<CardGroup cols={2}>
  <Card title="Configure Voice Settings" href="/essentials/configuration">
    Customize voice and transcription settings
  </Card>

  <Card title="Telegram Integration" href="/integrations/telegram">
    Add AIRI to Telegram
  </Card>
</CardGroup>
